Support for up to 16bit stick axis values, and signed values
Purpose
I set out to add support for the Adaptoid N64-controller-to-USB-HID adapter made by Wish Technologies in around 1999, which was popular during the heyday of the UltraHLE N64 emulator on PC.
Changes
In order to do this I needed to extend controller_patcher to support the following:
- Stick axis values up to 16bit (Adaptoid uses 12bit, controller_patcher had used 8bits only)
- Signed axis values (Adaptoid uses -1200 to 1200 range)
- Non-byte-aligned HID axis reports (Adaptoid packs two 12bit reports into 3 bytes, so the second one starts one nibble into a byte).
Rationale
My aim was to introduce this support without making breaking changes to the schema for existing INI files, and with minimal impact to the existing code. I initially tried changing all the config value types from u8 to u16 but this seemed too disruptive.
Instead, where I needed additional bytes of precision for existing variables, I added new parameters to capture their most significant bytes (MSB). I wrote additional logic to read in this additional data and to properly sign-extend and cast signed values. I then extended the inputs of the convertAnalogValue function from u8 to s32 type so that they could accommodate the full range of both signed and unsigned 16bit values. I also amended the deadzone and scaling logic to cope with negative values.
Status
- Working Adaptoid device support when mapped to a Gamepad using HidtoVpad.
- When Adaptoid is mapped to a Pro Controller input buffering isn't correct however. If I hold a stick direction it resets to zero input. Inputs are only registered while HID stick data is changing, e.g. running Mario in S-like patterns rather than directly forward. I've spent a long time debugging but I cannot figure this out. There must be some edge case in function
setProControllerDataFromHIDthat doesn't apply insetControllerDataFromHID. This behaviour only occurs after I exit HidtoVpad and apply patches. While I remain in HidtoVpad the debug logging confirms that all stick movement is polled correctly. I spent a long time reading the Gbatemp forum thread for HidtoVpad and I did see some other mention of a device not working properly with one type of binding being ok using the other type, so I am inclined to think this is more of a long standing issue which I am unlikely to be able to solve.
Download
- Download the compiled HidtoVpad binary and device profile here at Gbatemp.
Testing
- I have used UDP debug logging to confirm the deadzone logic and sanity of the config and HID data values.
- These changes work perfectly using an Adaptoid with N64 controller playing the Wii U port of Super Mario 64.
- Ship of Harkinian also works fine, but you will need a forwarder since it's not possible to relaunch the Homebrew channel when using HidtoVpad (same applies for Super Mario 64).
- I can also confirm that I did not break the existing processing logic for the official Nintendo GameCube controller adapter (unsigned 8 bit axis data).
- Unfortunately the Adaptoid stick input exhibits issues in the Virtual Console version of Super Mario 64. It seems that if I push fully in a direction on the stick Mario will turn back in the opposite direction. This never happens on the Wii U port so I can't really understand it. If tilt the stick to say 90% range then it's fine - I don't see this behaviour. I do see that this exact issue was already reported long before I made these changes. There was a recommendation to use the N64 emulator INI to limit the stick values to 90 and use a newer emulator binary, which had also been an issue with gc_to_vpad. GameCube controllers are unaffected.
- Strangely, when considering the above point, the Adaptoid behaves fine in the Virtual Console versions of Mario Kart 64 and F-Zero X. Upon further reading, it seems these use a later version of Nintendo's Virtual Console N64 emulator.
- For native Wii U software, the Adaptoid works perfectly for Breath of The Wild and for Mario Kart 8.
Misc
I have included my controller INI definition for the Adaptoid in the root folder, demonstrating the new configuration parameters. I realise it should go in the controller_patcher_configs repo but I figured that can wait while this PR is pending.