Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USB: Use infinite duration for FFB forces, make the recently added FFB workaround optional #11915

Merged
merged 1 commit into from
Oct 23, 2024

Conversation

badfontkeming
Copy link
Contributor

@badfontkeming badfontkeming commented Oct 14, 2024

Note

This PR changed a lot over the course of its development as a lot of research was done to ensure this was the correct approach; I ultimately pivoted back to this after digging through everything I could find. As a result, the comment history may be confusing/misleading if read out of context.

Description of Changes

  • By default, remove the workaround that bypassed the "effect already running" check for constant forces
  • Change the length of all FFB effects to SDL_HAPTIC_INFINITY.
  • Add a config option to restore the old workaround for wheels that still need it

Rationale behind Changes

Getting here has been a bit of a journey, and I'm not sure whether this counts as a victory or a surrender. Some wheels are just... outright bugged. Issues we've been seeing with the Simagic wheel appear to be encountered by some other games such as BeamNG, which have some workarounds in their config options that specifically specify that "buggy wheels" might need them.

For the wheels that are bugged-but-less-bugged, adding an infinite duration to the constant force will prevent FFB dropouts. The majority of wheels that don't respect the iteration count still respect infinite durations... except Simagic (at least the Alpha Mini).

The old workaround's approach of restarting the force constantly results in a loss of subjective quality/definition in the wheel, as independently noticed by several testers. As a result, we want that behavior configurable and off-by-default, since most wheels will no longer need it.

This leaves room for followup PRs that improve the workaround by restarting the force every 10-ish seconds, rather than every time the force is updated.

Suggested Testing Steps

  • The workaround toggle can be validated via Wireshark with USBPcap. Try this filter: usb.src=="host" && usb.data_len!=0 && usbhid.data[0]==0x0a

Known problem wheels:

  • Moza series: Does not honor DI effect iteration counts, DOES honor infinite durations, experiences detail loss with old workaround.
  • Simagic Alpha Mini: Does not honor DI effect iteration counts, does NOT honor infinite durations. Experiences detail loss with old workaround, but still needs it to avoid dropouts (A followup PR can mitigate this)
  • Accuforce V2: Does not honor DI effect iteration counts, DOES (appear to) honor infinite durations, and experiences notable micro-drops with the old workaround due to the wheel temporarily pausing when a force is restarted.

Known good wheels for regression testing:

  • Thrustmaster T150: Implements DI effect iteration count, implements infinite force durations, gummy gear drive so you'll never notice a loss of detail if one manifests 😅. Ironically, despite being a low-end wheel, it's by far the most compliant with the HID force-feedback standard.

@limeaway510
Copy link

Wheelbase: Simagic Alpha Mini
Car used: Toyota Castrol Tom's Supra '00
Tracks driven/lap count/FFB drop occured:
- Laguna Seca, 7 laps, no FFB drops
- Fuji Speedway '80s, 10 laps, one FFB drop
- Test Course, 4 laps, forgot to count but definitely got drops at the end of the banked turns

So starting with the good news. FFB worked just as well as it did with the changes made in #11906 . No drops (mostly) and no cobblestone effect (btw this is not the same as oscillation!). The drops I experienced were very fringe cases that we expected, but maybe these weren't expected with #11915 ? Not sure. In the previous PR, badfont stated that "long-living constant forces will still eventually timeout" and that's consistent with the drops that occured in my testing tonight.

FYI, for the rest of this comment I'm going abbreviate long-living constant forces as LLCF.

On Fuji Speedway '80s, the one and only drop happened somewhere in the middle of the last corner leading to the main straight. I don't remember which lap it occured, but I wasn't able to reproduce it. I guess depending on the line you take you could end up with a LLCF since the last section of this track is essentially an extremely long right turn. FFB quickly recovered as soon as I exited the turn onto the main straight, which again is consistent with what badfont described in the previous PR.

I wish I had thought to do this over the weekend, but Test Course is probably the best... test course lol... for this issue. The long banked turns are prime candidates for LLCFs. I stayed towards the upper section of the banking, driving centered on the outer most yellow line or outside of it. My experience was that staying on the outside created enough FFB "events" to prevent the timeout. The top of the banking is quite bumpy. Whereas staying on the outer yellow line led to timeouts towards the end of the banked turns. And just like with Fuji Speedway '80s, FFB recovered after recentering the wheel on the long straights.

Hearing that the FFB drops are happening again I'm sure isn't what we want to hear, but these were such specific cases that most are likely never to encounter them. With Fuji 80s you have to take a very specific line to recreate the drop. With Test Course, you can easily recreate the drop but I would argue that 99% of GT4 players are not spending their time racing on an oval anyway. The rest of the tracks are "technical" enough that you should basically never encounter an LLCF timeout with this workaround. In my opinion, this is an acceptable flaw until more time and effort can be spent on a more "robust" solution. For what it's worth, I spent about three hours last night playing Nightly Release v2.1.202 and had zero drops in that session.

It'll be later in the week, but I definitely want to do these same tests using Nightly Release v2.1.202. Particularly interested in trying to recreate the LLCF timeout on Test Course with the previous changes.

Also, going forward I think it would be good to have a standardized test that people can follow if they desire. Any car works really, but a higher powered one would get you through the tests laps faster. Fuji '80s and Test Course should definitely be on the track list because of the potential for LLCF timeout. Laguna is one of my favorite tracks, so I'm biased, but in PCSX2 stable you can get a FFB timeout like clockwork going into the Andretti Hairpin. Makes sense because the main straight is more of a long left hander (LLCF!!!).

Sorry for the essay of a response. Hope this feedback is useful!

@badfontkeming
Copy link
Contributor Author

That's very useful feedback, thank you for the thorough response! This leaves me with a lot of lingering questions, but the first thing I'd want to do is eliminate the most possible confounding factor, which is whether this could possibly happen on the old set of changes too.

At least on paper, dropouts should be able to happen on the old changes too based on how you described, but with the caveat that a single FFB update would've been enough to restore the feedback in that scenario.

There's actually a really good standard place ingame to test some of my assumptions, which would help me know what I'm looking at on your end. If you're able, I'd appreciate if you could do this on the "old" and "new" fix:

  • Go into GT4's menu
  • In PCSX2's controller settings, "reconnect" the wheel by changing "Wheel Device" to "Not Connected", then back to "Wheel Device"
  • You should notice the wheel has some gentle auto-centering provided by the game. Start a stopwatch, hold the wheel at about 90 degrees, and time exactly how long it takes before this auto-centering effect drops out.

Some other thoughts:

You noted that the force didn't return until the effect was stopped by centering the wheel and car, but you also noted that keeping the car in a "bumpier" part prevented the dropout. This is surprising to me, and leads to a few possibilities:

  • The Alpha Mini might actually have a "safety timeout" when a force isn't regularly updated, and the force may need to be completely restarted if it times out.
  • The Alpha Mini might have a hardcoded cap on constant force lengths, and the bumpy surface may have incidentally issued "stop" commands which naturally required restarting the force.

I wonder if I can get a hold of the wheel's developers via email. Sim racing equipment is a small world, they might actually be able to get my question to an engineer over there.

@badfontkeming
Copy link
Contributor Author

I think the next step here is probably for me to scrap together a temporary version with some improved FFB logging included. There's already some FFB logs included in PCSX2's debug builds, but if I can get something more human-readable into your hands that'd significantly improve the information I have to work with.

@badfontkeming
Copy link
Contributor Author

badfontkeming commented Oct 15, 2024

On stream, Jimmy Broadbent was reporting a feeling of heaviness and loss of definition on his Moza R21 with the previously merged workaround, implying the work in this PR may have a positive effect on the FFB feel on Moza wheels.

I'm not an experienced sim racer so it's harder for me to intuitively spot this, but I'm going to see if I can find any places ingame where the difference is sufficiently "obvious" between this approach and the previously merged one, just for the sake of reference.

The approach in this PR should result in more faithful FFB output for devices that suffered quality loss in the previous update. Some testing todos:

  • Find out more about the Simagic Alpha Mini's dropouts. Are they caused by a timeout from not receiving updates, or does it sincerely need the effect to be regularly re-run?
  • Right now, SetConstantForce has a check that skips calling SDL_HapticUpdateEffect if the force is unchanged. Could this inadvertently result in timeouts if it suppresses duplicate updates? This also depends on how often the game sends updates. (Update: Nah, the game rarely ever sends duplicate requests; it appears to filter them out on its end.)
  • Improved logging will help with this, and I'm going to add some when I'm home from work.

@SOVL22
Copy link

SOVL22 commented Oct 15, 2024

After testing the latest pr i can confirm coblestoning is completely fixed on the acuforce v2 but after spending some time last night it seems the ffb is inverted. The steering axis is correct but the ffb seems to be completely opposite what it should be. As I turn In you normally see counter force due to the resistance of understeer but the ffb actually force the steering in towards the corner. Normally if a curb is hit the ffb forces the wheel away from the impact but it's currently turning it inward toward to curb. Would it be possible to add a invert ffb option as a toggle perhaps? If not I may manage a work around by creating a vjoy device and inverting the steering axis and then mapping it correctly in pcsx2. An inverted steering axis toggle could also fix it i think but would require you to initially map the axis inverted and then enable the toggle of that makes sense?

I would also like to confirm the menu spring works correctly and does keep the wheel centered and no longer cuts ffb.

@limeaway510
Copy link

@SOVL22 shouldn't you be able to invert FFB within the driver software? I've never seen the Accuforce software but I'd imagine it has a feature like that. I know Simagic does. Odd issue if this is actually happening though.

@badfontkeming I'll report back some time this week. Fortunately, I have all three versions of PCSX2 installed (stable, previous merge, and this PR) so it'll be easy for me to test all three. I didn't notice the loss in detail that Jimmy is reporting, but I also didn't think too much of it because I was so focused on checking for the drops.

I guess it's also worth noting that Jimmy has a way more powerful wheelbase compared to mine (21Nm vs 10Nm), so the level of detail he can feel will likely be different than what I do. Also, he's an actual race car driver where I'm just playing pretend in my bedroom, lol. Regardless, I'm sure I'll be able to feel the difference once I'm actually looking for it. Anyway, feel free to ping me here or on discord if there's anything you need to chat about. I'm fully on-board with helping you test out future changes.

@SOVL22
Copy link

SOVL22 commented Oct 15, 2024 via email

@limeaway510
Copy link

That's very odd. Anyway, I just remembered you can manually edit the .ini files for your input profiles. It's a common issue for pedals to be inverted. I experienced this with my VNM pedals.

If you go to your PCSX2 root directory, go to the inputprofiles folder and open up which ever input profile you're using for GT4. You can open the .ini files using notepad. Once it's open, scroll down until you find the [USB1] or [USB2] header and underneath that you'll find all of your peripheral bindings. Somewhere in that list will be your steering axis and FFB device.

At the end of these three lines of code, add a ~ to the end if it doesn't already exist. If it does, then delete. Save the file. Relaunch PCSX2 and reassign your input profile to GT4. This worked for my pedals so I'd imagine it will be the same for any of the other inputs. Let me know if it works or if you need further instructions.

@badfontkeming badfontkeming marked this pull request as draft October 15, 2024 22:54
@badfontkeming
Copy link
Contributor Author

Converting the PR to a draft in preparation for some temporary logging additions to trace down any remaining dropout causes.

@badfontkeming
Copy link
Contributor Author

Some very basic logs have been added that simply print whenever the force has been started, stopped, or updated.

Next time you test dropouts, pull the log up alongside the game and watch it update as you play, so you can see whether the wheel is being updated, as well as whether it's stopped/started, when it drops out on you.

@badfontkeming
Copy link
Contributor Author

After cranking my wheel to its maximum and testing it out, I think I'm able to reproduce the "feel" issues caused by the last PR. It seems like re-running the effect with each update somehow overrepresents weaker opposing forces caused by things like simulated bumps in the road. I can confirm that this PR doesn't have that issue.

@badfontkeming
Copy link
Contributor Author

badfontkeming commented Oct 16, 2024

Other research notes:

After digging through the code of the scarce few open source FFB implementations I could find including some other emulators (Model 3's Supermodel, as well as Dolphin), the only things I noted were:

  • Both emus seem to use DirectInput directly, rather than going through SDL. After reading SDL's source, however, I don't see any obvious deficiencies or differences in behavior that would explain these issues. Notably, SDL's API closely matches some of DirectInput's semantics.
  • Supermodel sets DirectInput's "play immediately" flag when updating the FFB effect, but Dolphin doesn't, so this might be a red herring.
  • Both emus send an iteration count of 1 instead of infinite, it's not clear whether this could do anything, but given that many of these problematic wheels don't respect any iteration count, it's possible that non-one iteration counts evoke weird behavior in some wheels?
  • Some notes online, someone mentioned that a Fanatec developer suggested that they send constant forces with an infinite duration (which is what this PR does)
  • Most modern software is going to very frequently send FFB updates, potentially hundreds of times a second, where GT4 sends them far less frequently than that, sometimes waiting upwards of 150-300ms between updates. Some wheels may misbehave when updated this infrequently, but that feels like a stretch to assume.
  • It seems like, for the Driving Force Pro, GT4 uses a spring force or something of the like to center the wheel in menus, not constant forces. I might've gotten it confused with how it handles the non-pro wheel, or I might've just been 110% wrong.

I'm almost tempted to either reverse engineer the game or acquire hardware to sniff the USB line to confirm that the updates are this infrequent, since I know a few PCSX2 developers have shaky faith in the USB subsystems. The latter would be a huge commitment (especially in terms of having even more crap lying around my apartment lmao), so if I do anything it'll probably be reverse engineering.

@mirh
Copy link

mirh commented Oct 17, 2024

I mean, supposedly you could even just check out the old wx builds that worked.
But stupid question: if those wheels aren't respecting SDL's expectations, why isn't this getting fixed there?

@badfontkeming
Copy link
Contributor Author

badfontkeming commented Oct 17, 2024

You could just check out the old wx builds that worked.

Yeah should've done that lmao; I just kinda assumed they had similar faults. If I have time after work this is a logical next step. Thanks for suggesting it, I get tunnelvision when working on stuff like this.

But stupid question: if those wheels aren't respecting SDL's expectations, why isn't this getting fixed there?

Not a stupid question at all! Thing is, the iteration count that isn't being respected has a 1:1 correspondence with the semantics of DirectInput, which is what SDL ultimately uses under the hood on Windows.

As a result, using DirectInput directly won't solve this problem, and there's nothing to fix on SDL's end. This is an issue of device drivers not respecting the standard because of how rare it is for FFB effects to be looped given that most modern sims send up to hundreds of constant force updates a second.

Egg on my face, there is actually something we can accomplish by using DirectInput directly, as SDL isn't passing along the DIEP_START flag into DirectInput's SetParameter function. See below comments for more details

@Ziemas
Copy link
Contributor

Ziemas commented Oct 17, 2024

Would it help to periodically update the effect? We could just update it with the same value if the game doesn't send them frequently enough.

@badfontkeming
Copy link
Contributor Author

badfontkeming commented Oct 17, 2024

That's one of the things I'm looking to determine with those temp logging statements I added, as it should help testers spot whether dropouts are happening in the middle of a "drought" of updates. I'd rather have that info first, just to be confident that it achieved something if I added it.

Beyond that, FFB as a whole is so nonstandard that I don't know whether sending redundant updates will affect the feeling of the FFB, similar to how re-running the effect does.

@badfontkeming
Copy link
Contributor Author

I looked at the old dinput implementation, and it seems like it sets two flags: DIEP_TYPESPECIFICPARAMS | DIEP_START

Meanwhile, SDL sets several more flags that communicate to DInput that various parts of the effect data are present and valid, such as direction, duration, envelope, etc. It also does not include the DIEP_START flag. This makes me wonder two things:

  • Could excess flags for infrequently used features (envelopes, trigger buttons) be evoking driver/firmware bugs? Does including the duration flag inadvertently cut the duration short somehow, etc?
  • Could DIEP_START be the secret here? Does it "magically" reset the FFB timeout? If so, it might be technically possible to scoop out SDL's DInput handle for the effect and meddle with it for testing.

@limeaway510
Copy link

limeaway510 commented Oct 17, 2024

Did a few laps on Test Course during my lunch break.

On the banked turns, I'm pretty much able to keep the wheel at a steady angle. While doing so, the log prints out "FFB Constant Force: Updated: some value". Similar to my previous tests, FFB drops right around the the end of the banked turns which interestingly doesn't change anything in the logs. It keeps printing the "Updated: some value" line.

Once the wheel was centered, sometimes FFB recovered immediately and sometimes it took a few seconds. When it did recover, log printed the following:

FFB Constant Force: STOPPED
FFB Constant Force: Updated: "some value"
FFB Constant Force STARTED

I noticed on the long straights I'll see the same sequence printed pretty frequently. I'm assuming that happens because of the oscillations that occur with wheel on center at higher speeds. There were a few instances where a small steering input on the banked turns would lead to a STOPPED-VALUE-STARTED sequence. If this happened late enough in the sector then I wouldn't get a FFB drop.

I also tried the hold at 90 deg test in the menus. Did it three times while holding for 1 minutes, but no change in the wheelbase or logs.

Attached file contains some snippets of the log.

pcsx2-log-ffb-drop-101724.txt

@badfontkeming
Copy link
Contributor Author

I just pushed a super-ugly test commit that digs into the guts of SDL in order to send the DIEP_START flag with each constant force update. Ignore the failing builds, this is a bit more quick-and-dirty for the sake of gathering information so I made no attempt to "correctly" integrate DirectInput into the project.

On my Moza R9, setting the flag when updating a constant force refreshes the duration. Additionally, if the duration elapses, this flag appears to re-start the effect on its own. My gut instinct from rifling through various samples and tutorials is that setting this flag is common practice; I guess this is why. As mentioned before, PCSX2's old DirectInput implementation sends this flag (along with an infinite duration), so I wouldn't be surprised if it's de-facto necessary.

As for whether or not this flag causes a similar feel issue to the previous approach of re-running the effect: I doubt it. From my reading this flag seems like the "normal" way to rapidly update an ongoing constant force for racing sims/etc, so devices are probably equipped to deal with this. I'll still test on my own wheel later to confirm that I can't tell a difference.

If this hack works to resolve dropouts for affected users, we probably want to weigh our options, including potentially modifying SDL (if practical) to add the ability to set this flag when calling SDL_HapticUpdateEffect. I doubt any maintainers would want this hack in the codebase as-is.

@Ziemas
Copy link
Contributor

Ziemas commented Oct 17, 2024

It might be worth asking the SDL maintainers about this. If they have a reason to not use that flag it would be good to now it.

@badfontkeming
Copy link
Contributor Author

Turns out there's a long-closed issue in SDL's tracker that mentions these issues specifically with PCSX2. I'm going to wait to gather a few reports about whether DIEP_START fixes their dropouts, and if it does, I'll approach the SDL maintainers and try to reopen that issue with the new information.

@mirh
Copy link

mirh commented Oct 18, 2024

As a result, using DirectInput directly won't solve this problem, and there's nothing to fix on SDL's end.

Be it as it may, you know SDL has a device quirks database right?

This is an issue of device drivers not respecting the standard

At this point I could probably just tell you to try to see if you can find anything meaningful with ghidra... but I think you'll have such a better time asking to @JacKeTUs which has been banging their head on this for months.

@badfontkeming
Copy link
Contributor Author

As a result, using DirectInput directly won't solve this problem, and there's nothing to fix on SDL's end.

Be it as it may, you know SDL has a device quirks database right?

I should probably go back and edit some previous comments, as I've had to correct myself on exactly that--my most recent build does in fact go directly to DirectInput specifically because SDL isn't passing a flag to DirectInput that we need. Sorry for the confusion, many of my older comments aren't up-to-date with my current knowledge.

@TheLastRar
Copy link
Contributor

TheLastRar commented Oct 18, 2024

If this hack works to resolve dropouts for affected users, we probably want to weigh our options, including potentially modifying SDL (if practical) to add the ability to set this flag when calling SDL_HapticUpdateEffect.

We build SDL with a batch file, and adding a step to apply a patch would be possible (like we do with shaderc, or used to with qt).

Ideally getting it fixed upstream would be best, but it's still an option

@badfontkeming
Copy link
Contributor Author

badfontkeming commented Oct 18, 2024

We build SDL with a batch file, and adding a step to apply a patch would be possible (like we do with shaderc, or used to with qt).

Ideally getting it fixed upstream would be best, but it's still an option

Good to know, thanks. In the short term, I'm thinking it makes sense to patch it on our end and confirm the results before sending it upstream; the SDL team has a lot more variables to account for than we do when it comes to using this flag, since they have to account for all software consuming SDL. For a purpose-built PCSX2-specific patch, we should only need a single line to add the flag--due to the simplicity of PCSX2's usage of SDL haptics, I don't even think we need any conditional logic.

@badfontkeming
Copy link
Contributor Author

BTW, I went ahead and updated the OP since the information has changed significantly since the original writeup. Should be good to catch anyone up if they're not sure where things are.

@limeaway510
Copy link

I tested the "hack", nightly 2.1.202, and stable.

For the hack version, the logs didn't show anything interesting and I didn't get any drops during my usual test on the oval. However, something about this version just feels very off but it's hard to describe other than saying that it feels very vague. There's definitely resistance when I make a steering input, but a lot of the road imperfections that would normally jolt your wheel were very weak. The on-center oscillations that normally occur were also very weak unless I took my hands completely off the wheel. This is not the case with all the other versions.

I think I feel the difference that Jimmy Broadbent was describing between 2.1.202 and stable, but it's hard for me to say for sure because the drops are just so frequent with stable.

@badfontkeming
Copy link
Contributor Author

I tested the "hack", nightly 2.1.202, and stable.

For the hack version, the logs didn't show anything interesting and I didn't get any drops during my usual test on the oval. However, something about this version just feels very off but it's hard to describe other than saying that it feels very vague. There's definitely resistance when I make a steering input, but a lot of the road imperfections that would normally jolt your wheel were very weak. The on-center oscillations that normally occur were also very weak unless I took my hands completely off the wheel. This is not the case with all the other versions.

I think I feel the difference that Jimmy Broadbent was describing between 2.1.202 and stable, but it's hard for me to say for sure because the drops are just so frequent with stable.

Hmm. That confused me a bit, so I disassembled BeamNG in order to peek at what it does here, since I figured their developers would mind the least out of any. It appears to pass the DIEP_START and DIEP_TYPESPECIFICPARAMS flags with a very similar convention to this test build. I say "appears" because there's a chance I'm wrong, as Ghidra struggled a bit due to how the engine swaps between native and Lua code.

That said, it sets DIEP_START conditionally, and I'm not sure under which conditions. Might be based on a quirks list, might be based on the state of the wheel. Not sure yet.

@badfontkeming
Copy link
Contributor Author

badfontkeming commented Oct 18, 2024

The digging will continue until morale improves. I need to do some live debugging later when I have the time to confirm that I'm not missing something, but it seems like some other titles are actually just using the HID API to send HID commands straight to the wheel, bypassing DirectInput entirely.

If DirectInput turns out to be uncommon amongst contemporary sims, it'd make sense why their DirectInput drivers would be lackluster.

I'm treating this like a red herring for now, this may have actually been a manufacturer-specific SDK. Either way, I finally found a "canon" interaction between a modern PC game and the problem Simagic wheel (see below), which gives me a clearer path forward.

@badfontkeming badfontkeming changed the title USB: Infinite length for FFB effects for wheel compatibility USB: Investigate the Wild Mystery of Modern Force Feedback Wheels™ Oct 18, 2024
@badfontkeming
Copy link
Contributor Author

I had the idea to look up any relationship between Simagic wheels and BeamNG, and discovered that Beam's condition for setting the DIEP_START flag is a dropdown in the settings, which they recommend leaving off for performance and ffb quality reasons.

The setting specifically advertises itself as a workaround for "buggy wheels". It's a relief to see other devs acknowledging that this is a bug. Some guides for setting up Simagic wheels specifically instruct the user to enable this flag, so I at least have some closure now. I checked in Wireshark+USBPcap to confirm that it does exactly this.

Following that, I think it probably makes sense to follow their footsteps and just submit to the reality of needing a config setting for this. The wheel's probably just bugged.

@badfontkeming
Copy link
Contributor Author

Chopping this PR up as I've had some ideas on how to keep the scope down.

@badfontkeming badfontkeming changed the title USB: Investigate the Wild Mystery of Modern Force Feedback Wheels™ USB: Use infinite duration for FFB forces, make the recently added FFB workaround optional Oct 19, 2024
@badfontkeming badfontkeming marked this pull request as ready for review October 19, 2024 08:50
@JacKeTUs
Copy link

In out research we found out that "infinite" effect length value is not consistent between different OS. So in our patched pidff driver for Linux we use 0 from software as infinite value. (https://github.com/JacKeTUs/universal-pidff/blob/330e7db32f7b09c2929799d2001779f85c25dd1c/hid-pidff.c#L373)

Patch to the kernel with an explanation still not merged
https://lkml.org/lkml/2022/10/2/99

@badfontkeming
Copy link
Contributor Author

We're going through SDL for all FFB output and are using their constant, SDL_HAPTIC_INFINITY, for our effect durations. SDL is responsible for transforming that into any platform-specific values.

Interesting thought, though—I wonder if some noncompliant wheels are expecting 0 for duration? May experiment with that in followup work.

@badfontkeming
Copy link
Contributor Author

@JacKeTUs From a quick skim, it looks like SDL uses 0 for infinity when working with Linux, so your drivers should work fine.

Take a look at https://github.com/libsdl-org/SDL/blob/SDL2/src/haptic/linux/SDL_syshaptic.c if you want to double check.

pcsx2/USB/usb-pad/usb-pad.cpp Outdated Show resolved Hide resolved
pcsx2/USB/usb-pad/usb-pad.cpp Outdated Show resolved Hide resolved
…tional

The original workaround for FFB issues simply restarted the constant force
each time it was updated. Turns out that a lot of wheels don't behave
perfectly during this. A better fix was found, which is to set the effect
duration to infinite. However, some wheels are so bugged that they don't even
respect THAT, so the workaround needs to stick around in some capacity.
@F0bes F0bes merged commit f46f788 into PCSX2:master Oct 23, 2024
11 of 12 checks passed
@mirh
Copy link

mirh commented Oct 24, 2024

Following that, I think it probably makes sense to follow their footsteps and just submit to the reality of needing a config setting for this.

Certainly SDL can be even smarter than that, and whether it is a matter of specific wheels models or specific system conditions handle the setting automagically?

Patch to the kernel with an explanation still not merged

https://bugs.winehq.org/show_bug.cgi?id=51922

From a quick skim, it looks like SDL uses 0 for infinity when working with Linux, so your drivers should work fine.

Meaning that SDL is doing something different between windows and linux?

@badfontkeming
Copy link
Contributor Author

Certainly SDL can be even smarter than that, and whether it is a matter of specific wheels models or specific system conditions handle the setting automagically?

Unfortunately no, for a few reasons.

  • Even the wheels that are still misbehaving without the workaround experience fewer dropouts with this change.
  • Some wheels that need the workaround still experience reduced FFB quality when using it, so users should be allowed to choose between rare FFB dropouts versus consistent, but muddled FFB.
  • At a technical architecture level, it wouldn't be practical for SDL implement a workaround any better than our current one, but we have room to improve the workaround on our end if necessary. This is not a deficiency in SDL.
  • Automatic settings aren't super practical due to the maintenance burden it adds, as well as the fact that many of these wheels still receive regular driver and firmware updates that may change the compatibility status.
  • The existence of the checkbox informs users that their wheel's firmware is incorrect, and gives them a chance to check for an update or contact their manufacturer to request a fix. It also helps explain why they may feel worsened FFB with their wheel relative to others.
  • FFB is a relatively tiny feature for PCSX2 in a messy region of the codebase, keeping it dead-simple is crucial.
  • I've about exhausted my initial energy (and available time) towards this after several nights of disassembling games, learning the PID spec, and reading raw USB communications over Wireshark to make sure I was making the right conclusions. Code-wise we're already at the point of diminishing returns, I can't justify the work given how few people would benefit.
  • This really should be getting fixed at the firmware level. The wheels in question have issues with other commercial titles, and in the case of BeamNG, it even has a menu option just like this with the same effect.

Meaning that SDL is doing something different between windows and linux?

SDL interfaces with platform APIs and does not send raw HID/PID data to the device. So, technically, yes, but practically, no. It just uses the values that API expects to see. All APIs map fairly cleanly onto the PID standard minus some fluff like what intermediate value they use to describe infinity.

If all drivers are behaving correctly, this should result in the same bytes going down the wire regardless of OS.

@JZStudiosGit
Copy link

  • This really should be getting fixed at the firmware level. The wheels in question have issues with other commercial titles, and in the case of BeamNG, it even has a menu option just like this with the same effect.

I just want to chime in and say I have a Fanatec CSL DD and I've been avoiding PCSX2 because of the dropout issues, but it otherwise works pretty much flawlessly in everything else I've tried, even Need For Speed 3 from '98. I'm only checking this because of the just released stable. I'll have to do some testing and comparison between 1.6 where it works and 2.2.

On immediate testing, GT4 does seem to no longer cut out, but Enthusia is still completely wrong when it works on 1.6. Really weird oscillations and FFB spikes.

@badfontkeming
Copy link
Contributor Author

@jshfdoiquergh I'll have to see if I can find a copy of Enthusia used. It might be mixing different force types, or something along those lines. The existing patches only focused on constant forces since that's all I could test with GT4.

@JZStudiosGit
Copy link

JZStudiosGit commented Oct 31, 2024

Another quick preliminary test, GT4, feels immediately different and less small detail forces on current build than 1.6, workaround or not. The workaround toggle doesn't seem to change anything. Something about how it's generating or delivering the FFB is very different in GT4 and Enthusia. The smattering of other games I tried had fairly poor wheel support to begin with, so it's hard to tell. I'm not sure which games actually support the driving force pro to test. I only know of GT4 and Enthusia.

Obviously it's hard to say which is objectively "correct" to PS2 hardware, but the old plugin was far more objectively useful. I'd suggest trying to play with 1.6 and the plugin on your wheel and see if it still has the same issues, because somehow something about it is different.

@badfontkeming
Copy link
Contributor Author

@jshfdoiquergh Would you mind if I pinged you if I have the time to open up a draft PR with some experimental builds? I'd like to explore a theory on why this could be happening and I'd love some help testing.

@JZStudiosGit
Copy link

Sure, but I'm not that techy so I don't know what I have to do to set up test builds.

@badfontkeming
Copy link
Contributor Author

Not too much. Once I put the draft in place, Github will automatically compile it after a few minutes, and then you'll be able to download and run it like any other—the file just comes from a different place.

@JZStudiosGit
Copy link

Yeah, that's do-able. This an annoying issue since FFB and wheel support was pretty good prior, and now there's a bunch of fixes to GT4 specifically. Though I did notice the sky is blown out in 2.2...

@badfontkeming
Copy link
Contributor Author

Yeah, I apologize for not being able to test more games. For legal reasons I'm not able to write code for PCSX2 unless everything I'm developing and testing against is 100% above-board and legal, and the PS2 wasn't my primary console in my youth so I don't have a lot of games to work with. Not sure what might be around me locally, but it looks like the game is cheap on eBay. May be a while before I can get a copy.

@JZStudiosGit
Copy link

No worries. I know Enthusia makes use of spring force, which GT4 doesn't really, but it's possible if GT4 gets fixed so will other things.

@badfontkeming
Copy link
Contributor Author

@JZStudiosGit Please check out the draft PR here: #11985

Please leave any future comments in that PR. I'm going to have to step away from FFB work for a bit due to life circumstances, but if ya'll are able to test and see whether it fixes the issue for you, that will give future devs enough information to know how to make the proper fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants