-
Notifications
You must be signed in to change notification settings - Fork 3
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
Ghost Control Entry Parser for analog steering #15
Comments
I'm not sure what version of the game you're talking about. I'm assuming TM2/TMUF. You're almost correct, but there's some errors:
|
Indeed, TM2 & TMUF. Having a special rule "0x1 represents full left steer" makes a lot less sense than simply interpreting the 3 first bytes as an Int24. Also, nearly full left steer is, in your structure, steer = 0xFFFF, direction = 0x00 with FFFF being 65535. Interpreting it as an Int explains why direction = 0x2 doubles the steering. |
|
We both get the same results... BTW I just noticed it's thanks to your trackmania TAS video (What now?) I started looking into this. |
@TMDarky Thank you for that info and opening the issue! I was actually just thinking about that a few days ago and was about to think about good ways of implementing it. |
Okay, I looked into the disassembly of the game executable and it seems like the data is indeed encoded as 24-bit segments as you said @TMDarky. I think I actually found the method that interprets those values too, but it'll take me some time to fully understand how it works. |
For reference, here's a demonstration of what value pairs lead to what steering in-game: https://streamable.com/pghixl. I hope this clears things a little bit and helps with the development. |
@donadigo could you check at what exact value gas gets turned on ? (both forwards and backwards) It should be at around 0x004E00 (your structure : 20000 0) for acceleration and 0xFFB200 (~40000 255 ?) for brakes |
@TMDarky Looking into the disassembly, some values seem to be interpreted as floats. So those approximate values you mention might actually make more sense when interpreted as such. Regarding precise interpretation of all the values: I'd love to implement that, especially if it's useful for someone. If you're interested in looking into how it functions internally, I can also give you access to some code I decompiled from the game executable which I'll look at more thoroughly in the coming days. One other thing to note: It seems that while TMNF/TMUF and TM2 encode those values in the same way, there has apparently been a change in TM2020, where those values are now encoded slightly differently. I'll try and look into how we can parse both of the formats, too. |
@TMDarky the exact value (or offset) at which acceleration triggers is |
I revised my previous assumptions and code as well and of course, I was wrong. I also have some new insights that should help reversing the code further. I wrongly assumed that I wrote some Python code to convert between those single values and the 24bit pair, and also incorporated it into my tools: def analog_value_to_state(value):
axis = 0
flags = 0
if value < 0:
mul = int(value / 65536)
flags = -mul
axis = -value + (mul * 65536)
elif value > 0:
value -= 1
mul = int(value / 65536)
flags = 255 - mul
value -= (mul * 65536)
axis = 65535 - value
return axis, flags
def state_to_analog_value(axis, flags):
if flags < 128:
return -axis - (flags * 65536)
else:
mul = 255 - flags
return (mul * 65536) + (65536 - axis) And verifying that the algorithm covers the full 24bit range: for val in range(-8388607, 8388608 + 1):
axis, flags = analog_value_to_state(val)
assert(state_to_analog_value(axis, flags) == val) Regarding TM2020, I've got some info that, because the game engine is now entirely based on Shootmania, the inputs saved in the file could be more "generalized" inputs, rather than values strictly related to car control. This needs further investigation. |
Interesting stuff, thanks for the info @donadigo ! @stefan-baumann I'm not sure I'll be able to read decompiled code, but I'd like to take a look, sure ! |
The code assumes any non-zero value means the button is "On".
This is mostly correct, but is incomplete.
result.OnOffU = reader.ReadUInt32();
public bool OnOff => this.OnOffU > 0;
For normal buttons, the value is 0 (Off) or 0x80 (On).
For analog controls, the value is between -65536 and +65536 (0xFF0000 , 0x010000).
This is an Int24 followed by 8 unused bits as far as I can tell (always 0x00).
The control "Steer" is often used and the extracted data isn't easy to parse as the values are encoded as an Int24 inside 32 bits (OnOffU).
Extra analog details
Steer (if button _FakeDontInverseAxis is On) : negative values turn left, positive values turn right. 0 indicates no steering.
Steer (if button _FakeDontInverseAxis is not On (i.e. not present at all) : negative values turn right, positive values turn left. 0 indicates no steering.
Gas : negative values brake (reverse), positive values accelerate. 0 indicates no brakes/gas.
AccelerateReal : analog acceleration.
BrakeReal : analog braking.
For AccelerateReal and BrakeReal, the game seems to treat all values between 0xFF0000 and ~0x004E00 as Off, and everything else (until 0x010000) as On. They are set as 0xFF0000 at the beginning of the race.
For Gas, the same is true: [~0xFFB200, ~0x004E00] is no brake/acceleration. < ~0xFFB200 is full braking, > ~0x004E00 is full acceleration.
I'm adding tildes everywhere because I couldn't pinpoint the exact value, but it's somewhere around there.
As a result, the analog acceleration and brakes are not really analog as they map only to On and Off.
The text was updated successfully, but these errors were encountered: