feat: add DInput/WinMM controller support for Windows#71
feat: add DInput/WinMM controller support for Windows#71deadman96385 wants to merge 1 commit intosmartcmd:mainfrom
Conversation
…amepads) Hooks XInputGetState and XInputGetCapabilities via IAT patching so non-XInput controllers (DS4, generic HID gamepads) are visible to 4J_Input.lib and the rest of the game. Uses the WinMM joystick API to read device state and translates it to XINPUT_STATE format, mapping DS4 axes (Z=RSX, Rz=RSY, Ry=R2, Rx=L2) and buttons to their Xbox equivalents. Unoccupied XInput slots are assigned toDInput devices and rescanned every ~3 seconds.
|
WIP? |
|
Works fully on DS4 and my BT Xbox controller but haven't tested on generic ones. |
|
Please do and report back |
|
I do not have any sadly |
|
pls :D great addition |
Legeend28
left a comment
There was a problem hiding this comment.
yea pretty good bro 10/10 legeend28 approved
|
I will not merge until someone with a controller tests this one. We've had too much of untested/hallucinated by LLM PRs on day 1. |
|
I have just finished testing this with seven different controller configurations:
Besides the N64 controller having mapping issues (which is to be expected, it's a controller that wouldn't realistically be usable for Minecraft), I think that a 50% success rate isn't high enough to say that it brings proper compatibility for DInput controllers. Are there any other ways to bridge the API that would offer better compatibility? |
|
How do I download it, what do I need to do it, it seems a bit silly to ask |
Click on the |
I don't know anything about this, I've never done it, can you send it to me so I can just run it? |
Pull Request
Description
Adds support for non-XInput controllers (PS4/DS4, generic HID gamepads) on Windows by bridging the WinMM joystick API into the game's XInput-based input pipeline.
Changes
Previous Behavior
Only XInput-compatible controllers (Xbox controllers and XInput-mode adapters) worked on the Windows build. Connecting a PS4 DualShock 4 or any other DirectInput/HID gamepad produced no input in the game.
Root Cause
The game's input library (4J_Input.lib) is a precompiled static library that exclusively uses the XInput API (XInputGetState, XInputGetCapabilities). XInput is Xbox-specific and is completely blind to non-XInput devices — the DS4 and other
HID gamepads register with Windows as DirectInput/WinMM joysticks and are never enumerated by XInput, so the game had no path to receive their input.
New Behavior
Non-XInput controllers are automatically detected and assigned to empty controller slots. The DS4 and other HID gamepads work with correct button and axis mapping: face buttons, D-pad, shoulder buttons, analog sticks, and analog triggers all
behave as they would on an Xbox controller. The device list is refreshed every ~3 seconds to handle hot-plugging.
Fix Implementation
Since 4J_Input.lib is statically linked, it shares the host executable's Import Address Table (IAT). At startup, DInputManager_Init() walks the PE header of the process (IMAGE_DOS_HEADER → IMAGE_NT_HEADERS → IMAGE_IMPORT_DESCRIPTOR) to find the XInput DLL import entries and overwrites the XInputGetState and XInputGetCapabilities function pointers with hooks using VirtualProtect. The hooked XInputGetState first tries the real XInput call; if a slot reports ERROR_DEVICE_NOT_CONNECTED, it checks whether a WinMM joystick has been assigned to that slot and reads it via joyGetPosEx. The WinMM state is then translated into XINPUT_STATE format — DS4 buttons are mapped via the dwButtons bitmask, the POV hat is converted to XInput DPAD flags, stick axes are scaled from WinMM's 0–65535 range to XInput's −32768–32767 (with Y axes inverted), and trigger axes (DS4 HID axis order: Z=RSX, Rz=RSY, Ry=R2, Rx=L2) are scaled to 0–255. DInputManager_Tick() is called once per frame and periodically re-runs slot assignment to pick up newly connected devices.