-
Notifications
You must be signed in to change notification settings - Fork 13
5.d Controller | Adding new devices
Notes:
- First line of the config, need the be the information about the vid/pid
- Each controller needs a seperate config file
- The config files are case-insensitive.
- Comments can be added after a "//"
To get the data you can you HID-TEST. Simply start it from the homebrew launcher and you see your vid,pid and input data.
You'll need the vid and pid for your controller. Each HID device has his unique vid/pid combination, that can be used to identify them. Provide them in the first line of your config file.
When create a config file for a controller with the following data:
- vid: 0x0D41
- pid: 0xE124
The config line would look like this:
[vid=0x0D41,pid=0xE124]
To set the buttons, you need the the following information:
- the position of the byte holding the information in the inputdata (counting starts a 0x00)
- the value when the button is pressed (More precisely: the value that BIT OR'd)
Here a list of the buttons that can be mapped. On the right side you see the name you need for the config file.
Buttons:
A = VPAD_BUTTON_A
B = VPAD_BUTTON_B
X = VPAD_BUTTON_X
Y = VPAD_BUTTON_Y
Plus = VPAD_BUTTON_PLUS
Minus = VPAD_BUTTON_MINUS
Home = VPAD_BUTTON_HOME (Won't trigger the home menu)
Sync = VPAD_BUTTON_SYNC
TV = VPAD_BUTTON_TV
DPAD:
DPAD left = VPAD_BUTTON_LEFT
DPAD left = VPAD_BUTTON_RIGHT
DPAD left = VPAD_BUTTON_UP
DPAD left = VPAD_BUTTON_DOWN
Trigger:
ZR = VPAD_BUTTON_ZR
ZL = VPAD_BUTTON_ZL
L = VPAD_BUTTON_L
R = VPAD_BUTTON_R
Sticks:
Stick press left = VPAD_BUTTON_STICK_L
Stick press right = VPAD_BUTTON_STICK_R
To set a button, you'll need to set the byte postion and value
VPAD_BUTTON_A = [position],[value]
The connected USB controller set the 3 byte (0x02) to 0x08 when a button is pressed.
Using the following line in the config file, the button will be mapped to the X button.
VPAD_BUTTON_X = 0x02,0x08
Do this for every button you want to map
Different devices have different method to provivde the DPAD data. The controller patcher engine currently supports 3 of them. If you found an other method, that's currently not supported, please open an issue with further information.
In order to use the DPAD, you'll need to set right DPAD mode. To set the DPAD mode, use the following config line:
DPAD_MODE = [DPAD_NORMAL/DPAD_HAT/DPAD_ABSOLUTE_2VALUES]
Example for setting it to the "hat" mode.
DPAD_MODE = DPAD_HAT
Note: When no mode is set, the normal mode will be used.
The value depends on the data the device is sending. Detailed information on how to identify and set up the invidual mode can be found in the following sections.
In the "normal"-mode, the DPAD data is stored in one byte.
The directions north, south, west and east get their own values. To represent the direction, the pressed directions will be bitwise OR'd.
Example:
NOTE: Example values.
Values that will be OR'd when one the direction is pressed.
(UP) North = 0x01 (bitwise: 0b0000 0001)
(RIGHT) East = 0x02 (bitwise: 0b0000 0010)
(DOWN) South = 0x04 (bitwise: 0b0000 0100)
(LEFT) West = 0x08 (bitwise: 0b0000 1000)
The combined directions can result in other directions:
(UP+RIGHT) North-East = 0x03 (bitwise: 0b0000 0011. Result of 0x01|0x02)
(DOWN+LEFT) South-West = 0x0C (bitwise: 0b0000 1100. Result of 0x04|0x08)
When the device uses this method for the DPAD data, you'll need to set the following data:
VPAD_BUTTON_LEFT = [position],[value]
VPAD_BUTTON_RIGHT = [position],[value]
VPAD_BUTTON_UP = [position],[value]
VPAD_BUTTON_DOWN = [position],[value]
Example:
DPAD data is provided in "normal" mode, the values are stored in the 3rd byte (aka 0x02, we're counting from 0) of the incoming data.
Values:
- N = 0x01, E = 0x02, S = 0x04, W = 0x08.
DPAD_MODE = DPAD_NORMAL
VPAD_BUTTON_LEFT = 0x02,0x08 //W
VPAD_BUTTON_RIGHT = 0x02,0x02 //E
VPAD_BUTTON_UP = 0x02,0x01 //N
VPAD_BUTTON_DOWN = 0x02,0x04 //S
In the "normal"-mode, the DPAD data is stored in one byte.
The directions north, north-east, east, south-east, south, south-west, west, north-west and the neutral position get their own values.
Example:
NOTE: Example values.
Each direction has his own, unique value.
(UP) North = 0x01
(UP+RIGHT) North-East = 0x02
(RIGHT) East = 0x03
(DOWN + RIGHT) South-East = 0x04
(DOWN) South = 0x05
(DOWN + LEFT) South-West = 0x06
(LEFT) West = 0x07
(UP + LEFT) North-West = 0x08
(NOTHING) Neutral = 0x0F
In addition to the values, you need a bit-mask for the values. Sometimes buttons and the dpad are stored in the same byte. The first 8 bit are used for the buttons, the last 8 bits for the DPAD (the other way round). The work with the data, we need to isolate the DPAD data from it.
- When to data is in the last part of the byte (e.g. 0x05, 0x07), we need a 0x0F mask.
- When to data is in the first part of the byte (e.g. 0x50, 0x70), we need a 0xF0 mask.
Example:
DPAD data is provided in "Hat" mode, the values are stored in the 6th byte (aka 0x05, we're counting from 0) of the incoming data.
Values:
- N = 0x01, NE = 0x02, E = 0x03, SE = 0x04, S = 0x05, SW = 0x06, W = 0x07, NW = 0x08
- neutral = 0x0F
- bit-mask = 0x0F
DPAD_MODE = DPAD_HAT // normal mode
DPad_MASK = 0x0F // mask: 0x0F
VPAD_BUTTON_DPAD_N = 0x05,0x00 // postion: 0x05, value: 0x00
VPAD_BUTTON_DPAD_NE = 0x05,0x01 // postion: 0x05, value: 0x01
VPAD_BUTTON_DPAD_E = 0x05,0x02 // postion: 0x05, value: 0x02
VPAD_BUTTON_DPAD_SE = 0x05,0x03 // postion: 0x05, value: 0x03
VPAD_BUTTON_DPAD_S = 0x05,0x04 // postion: 0x05, value: 0x04
VPAD_BUTTON_DPAD_SW = 0x05,0x05 // postion: 0x05, value: 0x05
VPAD_BUTTON_DPAD_W = 0x05,0x06 // postion: 0x05, value: 0x06
VPAD_BUTTON_DPAD_NW = 0x05,0x07 // postion: 0x05, value: 0x07
VPAD_BUTTON_DPAD_Neutral = 0x05,0x0F // postion: 0x05, value: 0x0F
Sometimes the DPAD info is stored like a stick: two bytes, one byte for each axis. When its a digital DPAD, the bytes will mostly have three states: the direction of the axis (up/down or left/right) and a value for the neutral position. Currently its not possible to map a "real" stick with analog values to the DPAD.
(NEUTRAL) = X: 0x80 Y: 0x80
(UP) North = X: 0x00 Y: 0x80
(RIGHT) East = X: 0x80 Y: 0xFF
(DOWN) South = X: 0xFF Y: 0x80
(LEFT) West = X: 0x80 Y: 0x00
Example 1:
Here is a sample configuration.
- The data is coming from a digital DPAD, each byte only has three possible value (neutral and the 2 directions)
- The X Axis (left/right) is on the first byte (0x00). Left = 0x00, Right = 0xFF
- The Y Axis (up/down) is on the second byte (0x01). Up = 0x00, Down = 0xFF
DPAD_MODE = DPAD_Absolute_2Values
VPAD_BUTTON_DPAD_ABS_UP = 0x01, 0x00 // byte at postion 0x01 needs to be 0x00
VPAD_BUTTON_DPAD_ABS_DOWN = 0x01, 0xFF // byte at postion 0x01 needs to be 0xFF
VPAD_BUTTON_DPAD_ABS_LEFT = 0x00, 0x00 // byte at postion 0x00 needs to be 0x00
VPAD_BUTTON_DPAD_ABS_RIGHT = 0x00, 0xFF // byte at postion 0x00 needs to be 0xFF
The WiiU Gamepad has 2 sticks with 2 axis. To map the stick from a hid device to them, you need the following information for each axis of each stick:
- the position of the byte (counting from 0)
- the byte value when its in neutral position.
- the minimum and maxmimum value of the byte
- (optional) the size of the deadzone. (Whats the minimum the values has to change to be recognized as an actual input)
- (optional) is the axis inverted.
When you have these values, you can fill the config file. You need to set the values for each axis seperatly.
Left Stick X-Axis = VPad_L_Stick_X
Left Stick Y-Axis = VPad_L_Stick_Y
Right Stick X-Axis = VPad_R_Stick_X
Right Stick Y-Axis = VPad_R_Stick_Y
The lines for setting the byte postion + neutral value is this:
VPad_L_Stick_X = [position],[neutral value] //left stick x Axis
VPad_L_Stick_Y = [position],[neutral value] //left stick y Axis
VPad_R_Stick_X = [position],[neutral value] //right stick x Axis
VPad_R_Stick_Y = [position],[neutral value] //right stick y Axis
Example:
VPad_L_Stick_X = 0x03,0x80 //leftstick x Axis
The lines for setting the min/max value is this:
VPad_L_Stick_X_MinMax = [min value],[max value] //left stick X Axis
VPad_L_Stick_Y_MinMax = [min value],[max value] //left stick Y Axis
VPad_R_Stick_X_MinMax = [min value],[max value] //right stick x Axis
VPad_R_Stick_Y_MinMax = [min value],[max value] //right stick x Axis
Example:
VPad_R_Stick_Y_MinMax = 0x00,0xFF //right stick x Axis
The lines for setting the deadzone is this:
VPad_L_Stick_X_Deadzone = [deazone size] //left stick X Axis
VPad_L_Stick_Y_Deadzone = [deazone size] //left stick Y Axis
VPad_R_Stick_X_Deadzone = [deazone size] //right stick X Axis
VPad_R_Stick_Y_Deadzone = [deazone size] //right stick Y Axis
Example:
VPad_L_Stick_Y_Deadzone = 0x09 //left stick Y Axis
When you need to know what value you should use: Thats depends on your actual gamepad. The deadzone is the value how much the stick can move before its getting recognized as a real movement.
Example: you have a stick that has this values:
Value in neutral position: 0x80, Min: 0x00, Max 0xFF
By the time the stick gets older and the stick produces other values than 0x80 in neutral position (probably 0x82, 0x89 or 0x74).
This leads to "random" movements even when the stick is not touched.
To ignore this, you can set the deadzone. When the deadzone is set to 0x0F and the neutral postion is 0x80, everything between 0x70 and 0x90 will be handled as no movement (ignored).
You can use HID-TEST to see the values of you gamepad. Move the sticks arround and try to get different values for the neutral position in both directions. Then calculate the deadzone.
The lines for inverting a Axis is this:
VPad_L_Stick_X_Invert = [true/false] //left stick X Axis
VPad_L_Stick_Y_Invert = [true/false] //left stick Y Axis
VPad_R_Stick_X_Invert = [true/false] //right stick X Axis
VPad_R_Stick_Y_Invert = [true/false] //right stick Y Axis
Example:
VPad_R_Stick_Y_Invert = true //invert right stick Y Axis
VPad_R_Stick_X_Invert = false //don't invert right stick Y Axis
//Thumbsticks
VPad_L_Stick_X = 0x03,0x80 // postion: 0x03, neutral value: 0x80
VPad_L_Stick_X_MinMax = 0x00,0xFF // min value: 0x00, max value: 0xFF
VPad_L_Stick_X_Deadzone = 0x0A // deadzone: 0x0A
VPad_L_Stick_Y = 0x04,0x80 // postion: 0x04, neutral value: 0x80
VPad_L_Stick_Y_MinMax = 0x00,0xFF // min value: 0x00, max value: 0xFF
VPad_L_Stick_Y_Deadzone = 0x0A // deadzone: 0x0A
VPad_L_Stick_Y_Invert = True //invert Y-Axis
VPad_R_Stick_X = 0x02,0x80 // postion: 0x02, neutral value: 0x80
VPad_R_Stick_X_MinMax = 0x00,0xFF // min value: 0x00, max value: 0xFF
VPad_R_Stick_X_Deadzone = 0x0A // deadzone: 0x0A
VPad_R_Stick_Y = 0x01,0x80 // postion: 0x01, neutral value: 0x80
VPad_R_Stick_Y_MinMax = 0x00,0xFF // min value: 0x00, max value: 0xFF
VPad_R_Stick_Y_Deadzone = 0x0A // deadzone: 0x0A
VPad_R_Stick_Y_Invert = True //invert Y-Axis
It's also possible to map buttons (for example the DPAD) to a stick
VPAD_L_STICK_UP = 0x01, 0x01
VPAD_L_STICK_DOWN = 0x01, 0x02
VPAD_L_STICK_LEFT = 0x01, 0x04
VPAD_L_STICK_RIGHT = 0x01, 0x08
VPAD_R_STICK_UP = 0x02, 0x01
VPAD_R_STICK_DOWN = 0x02, 0x02
VPAD_R_STICK_LEFT = 0x02, 0x04
VPAD_R_STICK_RIGHT = 0x02, 0x08
Some adapters has 2 ports and support mutiple controllers at the same time (the DualShock 1&2 Adapter, official GC-Adpater and maybe more). The dualshock 1/2 adapter is sending the information for each port alternating, with information about the port in the first byte.
HID 01 80 80 64 80 0F 00 00 // inputdata from port 1
HID 02 7F 7F 7F 7F 0F 00 00 // inputdata from port 2
HID 01 80 80 64 80 0F 00 00 // inputdata from port 1
HID 02 7F 7F 7F 7F 0F 00 00 // inputdata from port 2
Now we have two options:
- Using only the information from one slot (old method)
- Use each slot as a new controller
At first, we need to tell the system, that this device could have (for example) two controllers.
PAD_COUNT=2 //This device has the information for 2 controllers.
Of course also other values are possible, if the device has slot for 3 or more controllers. Currently the maximum is 5.
For each controller we want to use, we need to write one rule, which acts like a filter.
PAD1_FILTER=0x00,0x01
PAD2_FILTER=0x00,0x02
The first value is the postion of the byte we're looking at, the second value is value we want.
After applying the filter, we get this input data for pad 1
HID 01 80 80 64 80 0F 00 00 // input data from port 1
HID 01 80 80 64 80 0F 00 00 // input data from port 1
And get this input data for pad 2
HID 02 7F 7F 7F 7F 0F 00 00 // inputdata from port 2
HID 02 7F 7F 7F 7F 0F 00 00 // inputdata from port 2
In this case we only want the data from one of the ports. To do this, a filter can be applied.
We only want to look at the inputdata, when the first byte is "0x01". This way to only read the data from one port.
This can be accomplished through the "INPUT_FILTER=x,x" line. In this example the following line would do the job.
INPUT_FILTER=0x00,0x01
The first value is the postion of the byte we're looking at, the second value is value we want.
After applying the filter, we only get this inputdata
HID 01 80 80 64 80 0F 00 00 // inputdata from port 1
HID 01 80 80 64 80 0F 00 00 // inputdata from port 1
You can find examples in the controller_patcher_configs repository. Most of the files should have helpful comments