Skip to content

Conversation

@dwillbarron
Copy link
Contributor

@dwillbarron dwillbarron commented Dec 3, 2025

Hi there. Same guy, different account--It's been a while, but I finally got the time to write the PR for this.

Context

Anecodtally, some force-feedback wheels have been reported to experience a reduced "definition", "texture", "precision", or "je ne sais quoi", which appears to be caused by sending more update flags than necessary to DirectInput.

This may be related to the fact that there are two USB PID packets that are sent when updating a device: One contains the "general" force data, and the other contains the "type-specific" data. My speculation is that many wheels expect to only receive the latter, and misbehave when receiving both.

This has been tested and validated anecdotally by others who have received a hacked-together version of PCSX2 that corrects the flags sent to DirectInput, who noted a significant improvement in the "feeling" of the FFB effects.

The only way to validate this at a technical level is to grab a wheel that uses the "generic" DirectInput FFB drivers (which map nearly 1:1 with the USB PID specification), and inspect the USB packets (e.g. with USBPcap) to check whether redundant data is being sent.

Description

This PR adjusts the DirectInput Haptic implementation to compare the requested haptic update to the previous state of the haptic effect. Using this, it calculates which update flags to pass on to DirectInput, which prevents redundant flags from being sent. This appears to fix subjective FFB quality problems on certain specific FFB wheels.

Existing Issue(s)

Issue #12511: SDL_DINPUT_HapticUpdateEffect sends unnecessary flags to IDirectInputEffect_SetParameters, which harms FFB quality in certain devices/usecases

Anecodtally, some force-feedback wheels have been reported to experience a
reduced "definition", "texture", "precision", or "je ne sais quoi", which
appears to be caused by sending more update flags than necessary to
DirectInput.

This may be related to the fact that there are two USB PID packets that are
sent when updating a device: One contains the "general" force data, and the
other contains the "type-specific" data. My speculation is that many wheels
expect to only receive the latter, and misbehave when receiving both.

This has been tested and validated anecdotally by others who have received
a hacked-together version of PCSX2 that corrects the flags sent to DirectInput,
who noted a significant improvement in the "feeling" of the FFB effects.

The only way to validate this at a technical level is to grab a wheel that uses
the "generic" DirectInput FFB drivers (which map nearly 1:1 with the USB PID
specification), and inspect the USB packets (e.g. with USBPcap) to check whether
redundant data is being sent.
@slouken
Copy link
Collaborator

slouken commented Dec 3, 2025

Welcome back! Offhand the code looks good.

@dwillbarron
Copy link
Contributor Author

Update on this: Unfortunately I'm having trouble recruiting as many active testers as I would've liked. That said, I've tested the changes on my own two wheels and confirmed in Wireshark that the USB packets look good.

My only reservation was whether some obscure wheel would misbehave in a new way due to some incorrect driver/firmware, but after digging into the internals of some common sims, it looks like my concerns are likely overblown. After looking at BeamNG's usage of DInput, it similarly avoids passing unnecessary flags when updating forces. If this were going to cause a compatibility issue, it probably would've already been noticed and blamed on the wheel, rather than the software.

I'm unmarking this as a draft for that reason, but ultimately it's your call as to whether you feel the need to solicit more testers. Worst-case scenario, I'll keep my eyes peeled for any complaints of regressions.

@dwillbarron dwillbarron marked this pull request as ready for review December 30, 2025 21:21
return SDL_memcmp(before->rglDirection, after->rglDirection, sizeof(LONG) * before->cAxes) != 0;
}

BOOL DIGetEnvelopeUpdateFlag(DIEFFECT* before, DIEFFECT* after) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
BOOL DIGetEnvelopeUpdateFlag(DIEFFECT* before, DIEFFECT* after) {
BOOL DIGetEnvelopeUpdateFlag(DIEFFECT *before, DIEFFECT *after) {

@slouken
Copy link
Collaborator

slouken commented Dec 30, 2025

I did a more thorough review and committed some style suggestions, and I'm going to call it good.

@dwillbarron
Copy link
Contributor Author

Thanks! Should've thought to check which side the codebase puts the pointer asterisk on, but that's what happens when you get rusty at C. Old, stubborn habit of mine.

@slouken slouken merged commit 618eb57 into libsdl-org:main Dec 30, 2025
43 checks passed
@slouken
Copy link
Collaborator

slouken commented Dec 30, 2025

Merged, thanks!

@dwillbarron
Copy link
Contributor Author

Awesome! I've went ahead and let the maintainers of PCSX2 know so that they can grab me if anyone finds a regression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants