USB: Further troubleshooting of FFB "loss of detail" issues
Due to changing life circumstances I won't be able to continue work on FFB for a while, so I'm putting this draft PR up to help other maintainers that might want to pick this up.
Description of Changes
SDL adds some unnecessary flags to DirectInput SetParameters calls, which causes unnecessary HID reports to be sent over the wire to the FFB device. This may be the cause of complaints about a loss of definition/detail compared to the old WXWidgets USB plugin. This draft PR offers a hack that should make it easier for affected users to test whether this is the cause.
Rationale behind Changes
- Prevents unnecessary HID reports from being sent over the wire. These unnecessary reports could be causing wheels to repeatedly re-initialize the force ID that they're using as a constant force, which could be what's causing the loss of definition.
- This is the only other thing that current PCSX2 does differently than the old WXWidgets USB plugin, which directly used DirectInput.
- I tested the WX build alongside USBPcap in order to confirm that this hack makes the behavior of the two identical over the wire
Suggested Testing Steps
- Windows is required
- Any FFB game that predominantly relies on constant forces (GT4 is the only game I have to test with)
- Toggle it on and off and see if you can feel a difference (the setting will update immediately after checking/unchecking)
- Use wireshark with usbpcap to confirm that redundant HID reports are no longer being sent
Take a look at this screenshot, and I'll give some context:
- The USB PID ("physical interface device" or something) spec is really similar to the semantics of DirectInput in a lot of ways. Forces are created as individual objects with a type (constant, spring, etc), then following commands need to reference the ID of that force in order to update/set its data.
- Report ID 0x01 updates a force's generic data (anything that is common among all force types)
- Report ID 0x05 updates a constant force's magnitude (there is a different report id for each force type's type-specific data)
- See more of the spec here: https://www.usb.org/sites/default/files/documents/pid1_01.pdf
- The redundant sending of 0x01 with each force update might be causing some wheels to lose "detail" in the force. Possibly some reinitialization? Either way, commercial PC titles don't redundantly send report ID 0x01 the way that PCSX2 is (I'm not aware of any commercial titles that use SDL for force feedback wheels, they either use DirectInput or they send the raw HID reports directly via their own implementation)
This is a screenshot from quickly toggling this hack off and on in Gran Turismo 4, a game which primarily relies on constant forces for its FFB effects.
IMPORTANT: The hack is off by default. You'll need to toggle it on when testing:
BTW: it's a known issue that the cmake builds fail. i probably would've had to adjust a cmake file to include the directinput headers, but this is an experimental build for testing so it didn't make sense to bother given the time I had
I don't understand how I actually download this
I don't understand how I actually download this
Checks tab at the top, then Windows Builds on the left, then scroll down to the artifacts section and pick the top item from the list. Should say avx2-clang, and not end with symbols.
Oops, sorry for the lack of instructions @JZStudiosGit . Previous commenter was correct, you'd normally nab them by going to the Actions tab, filtering by windows builds, and finding the action associated with this pull request. Then, on that page you'll grab the clang-avx2 version from the top of the "Artifacts" list (scroll down if you don't see it). Ignore the "symbols" files, you don't need them. The download will be a zip file, which you can extract and run like any other version of PCSX2.
Right now, the up to date build is right here: https://github.com/PCSX2/pcsx2/actions/runs/11705900986
If I make any changes, there'll be a new build in the actions tab. I'll try to link to them in the future for the sake of convenience.
Okay, so preliminary testing. It doesn't seem to do anything. With the hack enabled but not the previous fix, I still had a FFB dropout. Enthusia is still broken and GT4 doesn't seem to be any different. Actually thinking about it now, if SDL is an issue with constant forces, wouldn't the problem also be apparent on the dualshocks, or anything else with vibration?
sorry if there was any misunderstanding; this hack is only intended to address loss of detail when the FFB dropout workaround is disabled. (I can work on alternate approaches for FFB workarounds after knowing whether this hack helps with the loss of detail)
if SDL is an issue with constant forces, wouldn't the problem also be apparent on the dualshocks, or anything else with vibration?
Controller vibration is a much simpler, separate interface which won't be affected by FFB changes. I think sometimes people call controller vibration FFB, and that's unfortunately created a bit of a blurred line when really the two are very different.
sorry if there was any misunderstanding; this hack is only intended to address loss of detail when the FFB dropout workaround is disabled. (I can work on alternate approaches for FFB workarounds after knowing whether this hack helps with the loss of detail)
Yeah, with only the hack enabled there doesn't seem to be any changes and the FFB still drops out. It's still not the same as 1.6
Ah, well, that sucks. Unfortunately that means I'd need to grab a wheel and re-record a ton of USB messages to try and identify what else could be different, and I won't have access to a wheel for a while.
Thanks for testing anyway, though. As for the dropouts, I do know why 1.6 didn't have them, but fixing that would require a hack similar to this right now (SDL doesn't make it possible to pass in those flags without hacking around it).
To be honest, this makes me wonder if we'd be better off replacing the current usage of SDL with something else.
Well, maybe in a few weeks I'll have time to pick around with a raw-output implementation. I think a lot of modern games do this too, bypassing DirectInput entirely. It might be easier in the long run, but I'd have to learn a lot of low-level stuff, so it wouldn't happen for a bit.
Yeah. At least in the meantime GT4 is now playable, if not 100%.
Note for posterity:
A few people reached out via Discord to let me know that this hack improved quality for them, so I've gone ahead and filed an issue with SDL to see if they're able to address this on their end.
That said, this PR has fulfilled its purpose, so it's now going to be closed.