-
Notifications
You must be signed in to change notification settings - Fork 20
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
Force effect corrections part1 #105
Conversation
That's really cool, nice work. I suppose since most games are run under Wine, it might make sense to try and match the Wine behaviour to Windows as closely as possible. I would be really interested in seeing how other effects square up, particularly the periodic effect as they seems to be the most popular ones behind the constant force. Sine wave probably the foremost among them. Unless I'm mistaken, you wrote one program that directly calls DirectInput on Windows/Wine, but did you write the Linux program with direct ioctl calls or did you use a library like SDL? The approach to handling FFB differs between Windows and Linux and I'm not entirely sure how directly comparable they are, using SDL or something along those lines should (at least in theory) produce the same graphs for the same program regardless of operating system. I wrote a program that does something along those lines, see https://github.com/Kimplul/ffbsdl, but I didn't do anywhere near as neat a job collecting data as you have. Did you notice any significant difference in games with this fix? I believe at least DiRT Rally only uses the constant effect, and I could image that if the wheel starts clipping forces it could make for a pretty jarring experience. |
The good thing (at least in case of the constant effect) is matching the Linux driver corrects the behavior inside Wine too, so both native and Wine games should behave correctly.
The Windows program calls DirectInput the Linux one calls ioctl and write. I attached them as txt to the first post because cpp files cannot be attached for some reason.
Yeah, using some library that abstracts away the differences between Linux and Windows would make the graphs match visually, but then I have to deal with whatever the library may modify inside the effects. I tried to be close as possible to the hardware/OS and that was the native API. If I send some effect that way, I can tell what may the driver/OS modified inside them before sent to the wheel. If I have a library between me and the wheel, then I have to deal with that too. The way I compared them is if something correspond to the maximum force in the native API (
I haven't played any games with the wheel recently, so I don't have that "yeah, it feels better" comparison, but numerically it should be correct. |
Good point.
Oh, completely glossed over those, sorry. Thought
Might make them match, or at least that would be the intended behaviour. If there are any differences, we know we're breaking some internal assumption about the Linux FFB subsystem that SDL has, thought that would be a reasonably quick check.
Granted, that's also a good point.
Makes sense, just wanted to check there weren't any surprises in actual usage. I should probably try out some games I know to work and compare anyway. Do you want to do more effects in this pull request or do like one effect per PR? I don't think there's any hurry in getting patches out to people but this also seems like something that could be 'rolled out' in steps. |
If we split it up too much, then there will be a force scaling difference between the effects, so some forces maybe stronger than others. This probably worse than having equally strong forces. |
Purely anecdotally, the constant effect is the most common one, with the periodic sine a fairly distant second. Autocentering and gain are both common, but in a slightly different way since they generally act as a global setting. I've seen some games use friction and spring effects, but can't remember ever seeing ramps or other periodic effects than the sinusoidal one. Periodic effects are treated pretty much the same by the wheel so correcting one would likely apply to the others, though. EDIT: Nor can I remember seeing any effects use envelopes. |
Part1
Part2 (maybe can be 1 too)
Part3
Part4
Just an idea, feel free to change anything you see fit. |
Sounds perfectly reasonable either way. |
I'm checking the periodic effects now, may take a day or two to complete it. The constant force is done, the only unknown is the envelopes that the Windows driver places in them if no envelope is added to the effect. Probably irrelevant because they all have 0 length. I have marked this PR as ready for review if you want to send this out into the wild before I finish the periodic ones. |
Pushed the first part of the periodic effect fixes, the remaining part is the offset. |
Amazing work |
} | ||
|
||
/* the interval [0; 32677[ is used by the wheel for the [0; 360[ degree phase shift */ | ||
periodic->phase = periodic->phase * 32677 / 0x10000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
32677 is a bit surprising, I would've expected it to be 32768. I guess it could be that the driver is trying to avoid some unwanted behaviour with values at the extreme ranges?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it maps to some lookup table inside the wheel, although the value choice still odd, but it works out perfectly.
Wine has some issues using the correct values through the whole range, especially from 390 to 399 deg. I don't know why it happens, but it had it before too (see spreadsheet).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
32677 + 91 = 32768, I guess the Windows driver just doesn't use the last interval or something.
but it works out perfectly.
Does 32768 still work, or did you mean that the 32677 maximum is the highest working value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we assume the Windows driver is working correctly, then [0; 32677[ -> [0; 360[
and [0; 65354[ -> [0; 720[
.
The wheel responds to the whole [0, 65535]
interval.
@@ -948,6 +980,8 @@ static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, | |||
int ret; | |||
|
|||
level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; | |||
/* the Windows driver uses the range [-16385;16381] */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous comment also applies to this, even more weird is the range being asymmetric.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an about -2
offset on the whole range in the constant force magnitude and in the periodic effect offset.
The Windows driver using -2
instead of 0
force/offset in these cases and never uses 0
(see spreadsheet).
I have not replicated this because I think it's a rounding error and saw no difference in behavior.
Would you mind also writing up a small analysis of your findings and methodology? Doesn't have to be as detailed as the one for the constant force, but at a minimum I'd like to see the test programs you used. |
The method was the same: try everything and see what it does. A comparison of what Windows and what this PR uses:
Notable things
Updated spreadsheet: ffb.ods |
Played some games (DiRT Rally 1 & 2, ETS2, RRRE) with the corrections, didn't feel any significant difference from before but the data is pretty convincing. I suppose the differences primarily become more noticeable with stronger effects like crashes, which are pretty chaotic by default. Thanks a lot, really interested in seeing what's wrong with the other effects! |
I read #46 and wondered why they can feel it different with the driver installed inside the prefix, I thought maybe the driver applies some modification to the values that got sent out.
To test the things out I installed a Win10 in VirtualBox, installed the TM drivers, and wrote a POC program to send constant force effect with a range of force levels. I have done the same on Linux and Wine and compared the force levels that got sent out using Wireshark.
Some notable differences between the two:
-10000
to10000
(DI_FFNOMINALMAX
)-0x8000
to0x7FFF
Things I did:
lMagnitude
(level) setlevel
setThings I found:
[-10000;10000]
range to[-16385;16381]
<-10000
and>10000
values, and the sent force is-16385
and16381
respectively<-10000
and>10000
values, so I left them out[-0x8000;0x7FFF]
range to[-0x8000;0x7FFF]
, so essentially from 50% in either direction the force is unchanged (I don't feel any difference in the force above16381
)tm_api_lib_*.dll
) is involved when a difference is made.Based on these observations I gathered the requested and sent out values under Windows, Wine, and Linux and made a nice plot out of it. I also modified the driver to roughly match the force levels of the Windows driver by dividing the force level by 2.
Plot of the original and the modified force levels:
All the things I said are relevant only to the T300RS, I have no other wheels available.
Checklist:
If you think it's not a complete nonsense, and it's wroth to go through the checklist, let me know.
POCs
ffbtest_win.cpp.txt
ffbtest_linux.cpp.txt
Wireshark captures
const_-8000-7fff_win.pcapng.gz
const_-8000-7fff_linux_wheel.pcapng.gz
const_-10000-10000_wine_wheel.pcapng.gz
const_-8000-7fff_linux_corr2_wheel.pcapng.gz
const_-10000-10000_wine_corr2_wheel.pcapng.gz
Gathered data
ffb.ods