The Output Protocol “USB Multi Interface HID” is a bit special.
It allows the Output to be send as keyboard, mouse and gamepad controls. The connect console/PC on the T2 Output Port will see the T2 as a keyboard/mouse.
This requires different scripting approaches than the usual console controller output protocols. Instead of “set_val” you have to use mouse_set (for mouse output) or key_set (for keyboard output).
Utilizing this “USB Multi Interface HID” Output Protocol you can do scripting with the T2 for the PC. Pablosscripts created a forum post with some information about it: Pablo's Beginners Guide to Scripting for PC
You can find a few scripts for this protocol in the Online Resource within GTuner IV: Search for “usb-hid”.
Some USB HID Script specific links:
Universal HID Gamepack (USB Multi Interface HID)
USB-HID Anti Recoil (USB Multi Interface HID)
USB-HID Gamepad 2 Keyboard+Mouse (USB Multi Interface HID)
Important GPC functions for USB HID protocol usage:
Keyboard: keymapping key_passthru key_check key_status key_get key_set
Mouse: mousemapping mouse_passthru mouse_status mouse_get mouse_set
When you want to forward mouse input or keyboard input use the corresponding _passthru function.
As soon as you want to alter the input before outputting it you need to be careful:
The last value set for a mouse filed is kept between main() iterations. Unless mouse_passthru() is called, which will overwrite the value set by the script. |
Meaning:
If you use mouse_set() function to alter the mouse status (moving mouse/ pressing buttons) you need to always set all inputs each time (x,y,button,wheels) for the mouse to get no unwanted mouse movements/states. |
More information:
mouse_passthru and mouse_set
mouse_set: always set all mouse ouputs -> X/Y/Wheel/Buttons
A very basic example to forward all mouse and keyboard input to the output port will look like this:
init{ mousemapping(); // clears defaultt T2 mouse mappings keymapping(); // clears default T2 keyboard mappings } main{ mouse_passthru(); // forward mouse input to output key_passthru(); // forward keyboard input to output }
When mouse button 1 is pressed the anti recoil will be applied.
#include <mouse.gph> // configuration // note: when a value of 1 is still to strong anti recoil try a higher value for mouse_speed const int mouse_speed = 10; // <- should be around 10 or higher, a value too low can stop the mouse from working int AntiRecoil_X = 0; // anti recoil horizontal int AntiRecoil_Y = 1; // anti recoil vertical // internal int32 X, Y, WHEEL; int32 RX, RY; init { keymapping(); mousemapping(); } main { key_passthru(); RX = 0; RY = 0; X = 0; Y = 0; WHEEL = 0; if(mouse_status(MREPORT_UPDATED)) { mouse_passthru(); // only passthru when there is data to send X = mouse_status(MOUSE_X); Y = mouse_status(MOUSE_Y); WHEEL = mouse_status(MOUSE_WHEEL); } if(mouse_status(MBUTTON_1)) { if(!(system_time()%mouse_speed)) { RX = AntiRecoil_X; RY = AntiRecoil_Y; mouse_set(MOUSE_X, X+RX); mouse_set(MOUSE_Y, Y+RY); mouse_set(MOUSE_WHEEL,WHEEL); } } }
When mouse button 1 is pressed the anti recoil will be applied, supporting decimal/fix32 values.
#include <mouse.gph> // configuration fix32 antirecoil_X = 0.0; // anti recoil horizontal fix32 antirecoil_Y = 0.5; // anti recoil vertical // advanced configuration const int MOUSE_SPEED = 10; // <- should be around 10 or higher, a value too low can stop the mouse from working // internal uint32 ARTIMER; int32 X, Y, WHEEL; int32 RX, RY; fix32 ARX, ARY; init { keymapping(); mousemapping(); } main { key_passthru(); X = 0; Y = 0; WHEEL = 0; RX = 0; RY = 0; if(mouse_status(MREPORT_UPDATED)) { mouse_passthru(); // only passthru when there is data to send X = mouse_status(MOUSE_X); Y = mouse_status(MOUSE_Y); WHEEL = mouse_status(MOUSE_WHEEL); } if(mouse_status(MBUTTON_1)) { ARTIMER += elapsed_time(); if(!(ARTIMER%MOUSE_SPEED)) { ARX += (fix32)(antirecoil_X); ARY += (fix32)(antirecoil_Y); if (antirecoil_X < 0.0) RX += (int)ceil((ARX)); else if (antirecoil_X > 0.0) RX += (int)floor((ARX)); if (antirecoil_Y < 0.0) RY += (int)ceil((ARY)); else if (antirecoil_Y > 0.0) RY += (int)floor((ARY)); mouse_set(MOUSE_X, X+RX); mouse_set(MOUSE_Y, Y+RY); mouse_set(MOUSE_WHEEL,WHEEL); ARX = mod(ARX,1.0); ARY = mod(ARY,1.0); } } else { ARTIMER = MOUSE_SPEED; ARX = 0.0; ARY = 0.0; } }
Mapping controller input to keyboard HID output.
#include <keyboard.gph> #include <mouse.gph> init { keymapping(); mousemapping(); } main { key_passthru(); if(mouse_status(MREPORT_UPDATED)) { mouse_passthru(); } // dpad up mapping to key E if(is_active(BUTTON_10)) key_set(KEY_E, TRUE); }
To make sure the key is released on release of the button as using KMG capture the key may not be reported as released automatically.
#include <keyboard.gph> #include <mouse.gph> init { keymapping(); mousemapping(); } main { key_passthru(); if(mouse_status(MREPORT_UPDATED)) { mouse_passthru(); } // dpad up mapping to key E if(is_active(BUTTON_10)) { keySet(KEY_E, TRUE); // press } if (event_release(BUTTON_10)) { keySet(KEY_E, FALSE); // release } } void keySet(uint8 key, bool flag) { if (key_get(key) != flag) { key_set(key, flag); } }
Mapping keyboard input to keyboard HID output. Useful for some games where you can't change the key assigned to actions.
#include <keyboard.gph> #include <mouse.gph> init { port_connect(PORT_USB_C, PROTOCOL_HID); keymapping(); mousemapping(); } main { key_passthru(); if(mouse_status(MREPORT_UPDATED)) { mouse_passthru(); } // shift <-> ctrl keyMap(KEY_LEFTSHIFT, KEY_LEFTCONTROL); keyMap(KEY_LEFTCONTROL, KEY_LEFTSHIFT, FALSE, KEY_LEFTSHIFT); // <-- for circular mapping // additional shift mapping : alt -> shift keyMap(KEY_LEFTALT, KEY_LEFTSHIFT, TRUE); // <-- for additional key to same destination // caps -> alt keyMap(KEY_CAPSLOCK, KEY_LEFTALT); // left-> page down keyMap(KEY_LEFTARROW, KEY_PAGEDOWN); // right-> page up keyMap(KEY_RIGHTARROW, KEY_PAGEUP); } void keyMap(uint8 keySrc, uint8 keyDst, bool noset, uint8 keyCheck) { if (key_status(keySrc)) { if (!keyCheck) key_set(keySrc, FALSE); else if (!key_status(keyCheck)) key_set(keySrc, FALSE); keySet(keyDst, TRUE); } else if (!noset) key_set(keyDst, FALSE); } void keySet(uint8 key, bool flag) { if (key_get(key) != flag) { key_set(key, flag); } }