Can we please have documentation of what do hex files contain? Or at least an official statement from the staff on why that is not doable/desirable. Context: I have never modded any sim, I entered the simracing world 3 years ago and I haven't had the time. I dedicated some time to learn how it works in AMS2 in the past days and while I have many things to learn, I get what must be done. (btw I am a computer scientist working in compilers, so it is not the first time I run emacs in hexl-mode to understand what is going on). Given my background it is very tempting to make my own compiler to generate the hex files from plain text. This would be doable after some hours of development but there is a catch: There are some chunks of the hex files that apparently anybody knows what they do. So my question in the first paragraph. I could understand if Reiza does not want us to interpret the binaries, but since they are not encrypted, and Reiza endorse modding, apparently they are ok with that. The reason could be they don't have the time to document things, it is ok. In that case we should do it as a community. Perhaps a thread here could be a start. Edit: I start. Here AMS2 modding docs is the best resource I know. Any other documentation is welcomed.
Any addition of modding info to the wiki is appreciated. I personally don’t know how to mod, but those who can could maybe post some things to the wiki
That is definitely a good place to collect the information, I thought about it already . But we need to gather the information first. Any insights are welcome.
You could make a proof of concept compiler based on the small gearbox file. I think its translation is compete as it hasn't changed since S2U. As far as I know Reiza work with XML files which are then binarized in their tool pipeline. Access to these xmls would be highly appreciated. If you could then make a compiler, it would make modders' life so much easier.
Hi Guys, I am very interested in this matter. I don't know anything about hex editing but I would like to be able to edit the physics. I am attaching a file that I found as samples in case this works for you. If so, I can provide you with more or tell you where there is more documentation about it. I am not sure if it is allowed to put links to other websites here.
Tomorrow is Independence day in Uruguay. I guess now I have a project to nerd about in the long weekend...
Well, basically I got it. I have a CLI utility that can compile a gearbox from plain text, and decompile an existing gearbox hex file to plain text. I must do some further testing. I'll publish the code later. This should scale to the other hex files. My next step will be actually refactor what I have a little bit to save time later. However, more than ever it should be handy to have a better specification of hex files. For now I think what I will do is having the possibility to insert hex chunks in the plain text with a special field. For instance something like the following: <field1> = 0.0 blob = 0xca 0xfe 0xca 0xfe <field 2> = 14 could compile into <field 1 compiled> CAFECAFE <field2 compiled>. This implies my text files are sensible to the ordering in their fields. I wanted a more declarative approach but it is not easy to combine with those bin chunks (also, I have not studied all the hex formats yet, perhaps even there is a fundamental quirk that makes the declarative approach non-doable anyways..) EDIT: For instance if I decompile the hex file for the Clio Cup adaptation from PC2 of Thunderflash, I get: ratio = (15,34) ratio = (18,31) ratio = (16,22) ratio = (14,16) ratio = (50,48) ratio = (18,15) bevel = (1,1) finalDrive = (10,38) If I compile this again (or anything similar modulo whitespaces/comments) I get the original hex file bit by bit.
Update: It worked well in most tests I've done. vrc_chevrette.gdfbin does not decompile, though. the hex file format is not exaclty as documented in AMS2 modding docs...
It's because I used Code: 24 9D 58 F9 64 A2 , which is followed by float, float. It's then much easier to define ratios. My docs guide lists examples of hex code endings here: chassis - AMS2 modding docs but there may be more which are unaccounted for. Anyways, good progress so far, and thanks a lot for working on this! Maybe we should tag @CrimsonEminence to bring this to devs' attention, and perhaps get some feedback on the possibility of getting access to sample xmls with physics files. Hope I'm not being too forward.
Oh I realize you are behind many things Thank you! What I've done is small and would be imposible without the documentation. I'll keep working on this. So, A2 is float,float. Is 02 (without the documented prefixes) byte,byte?
Can you give me the specific key and the file in which I can find it? Then I should be able to figure it out.
Hi! Sorry for the delay in answering. During the week I have been busy with work. To find gear ratios I parsed: 24 9D 58 F9 64 02 X Y with X and Y as bytes. In the chevrette we have instead 24 9D 58 F9 64 A2 X Y where X and Y are floats (If I remember correctly) (of course note that X, Y are no longer bytes so this chunk is longer). A2 means the following values must be interpreted as floats, my question is if the 02 in 24 9D 58 F9 64 02 means that the two values following are just bytes. I see in your documentation that 03 02, 23 02, 83 02 and A3 02 mean things, but not 02. Is it safe to state that 24 9D 58 F9 64 means there is a gear ratio value where the next byte indicates the format it is stored? (02 means two bytes (int8s), A2 means two floats).
Yes, I guess it's safe to assume that. Unless there are two bytes, which indicates a different format, as in the examples you have given. You also need to look at the start of the keys. The most obvious example is `28`, which means the key is empty. The chassis translation should give you a better idea.
Given the lack of engagement by Reiza in this thread, I'm not sure why I bother, but here it is... Thanks to some great reverse engineering job by the modding community, the structure of *fbin files is pretty easy to understand. I am having troubles with mrdf and vdfm files. Except for the different sections, both have the same structure. What puzzles me are the red sections below, and I hope someone can tell me what they are: The second 8 bytes (0x08-0x0F) seem to change for every car and I wasn't able to find a pattern. The last 16 bytes (or really 12 plus 4 trailing zeros) that make up the last section are almost always "01 00 00 00 49 89 07 FB 0E 00 00 00" for mrdf files and "01 00 00 00 5F B5 28 EF 0F 00 00 00" for vdfm (and exception that I found was Mcl650sGT3.mrdf, but that might be incorrect as the last 4 bytes are not zero either). *.mrdf *.vdfm
I am slowly doing things in the time I find, I have basically rewritten the project to make it scalable now that I understand better the format of binaries. The idea is to parse unknown records with the proper hex code as its name, I show an example in the attachment. That way I can de-compile any physics file to text, sometimes with some awkward named key-value pairs, and recompiling it getting the very same original file (eventually doing changes, that is of course the point). I hope I can release it soon (Reiza time ), hopefully by putting some de-compiled examples someone else can figure out some more fields to make it more complete... There is a question I have and I think you could have the answer since you wrote that auriel file. There is a sort of table at the end of the engine file (entries start with 24 51 5F 5E 83 86 AA). What does it mean? I scrapped some AMS2 cars and I also find some tables, for instance starting with "24 04 45 49 29". There is no documentation of those from PC2 afaik Edit: Play the game: the screenshot shows a bug...
Code: 24 51 5F 5E 83 86 AA that the start of turbo. It's followed by Code: 24 51 5F 5E 83 96 AA where the integer is RPM and the floats are boost at throttle positions. The other table you mention has been added by Reiza, and it would be great to get some feedback from the devs on what it does and how to use it. Either way, it's not required for mod cars to work.
Hey there. I'm new to AMS2 modding (And other Madness engine games like PCars), but I noticed that the gearbox files have a different set of hex code values for the final drive to PCars2... the 02 in [24 9D 58 F9 64 02] is replaced by a 42 instead, and after that section, the two values for what I think are the gear cogs (the [64 18]? Or maybe it's the values after the last 64, [18 01]) don't really match what I have for the main gears
Hi All, I've written some editors for the various files used in modding that may be useful to some. Feedback welcomed. https://github.com/RangeyRover/AMS2-VDFM-Editor https://github.com/RangeyRover/AMS2-MRDF-Editor https://github.com/RangeyRover/AMS2-EDF-File-Editor https://github.com/RangeyRover/AMS2-CDF-File-Editor https://github.com/RangeyRover/AMS2-GDF-Editor https://github.com/RangeyRover/AMS2-SDF-File-Editor
VDFM Hex Translation https://github.com/RangeyRover/AMS2-VDFM-Editor/blob/main/Translation_for_VDFM1.1.txt Project CARS / Automobilista 2 Translation for porsche_991_gt3rs.vdfm By JDougNY & RangeyRover Version 1.0 - October 8, 2018 - Initial release Version 1.1 - December 2025 - Modified for AMS2 by RangeyRover, references from GvSE and vehicles vdfm - AMS2 modding docs NOTE: Address locations are typical for all VDFM files up to the beginning of the string data. Use this translation as a guide to editing any VDFM file. ADDRESS Little End. Value Description ------------|-----------|------|---------------- [HEADER - 0x000-0x02F (48 bytes)] 0x010-0x013 = 98010000 = 408 // (Integer) Byte Length of DATA section. Count from 0x030 to end of DATA section (before DATA PAD) 0x015 = 08 // (Byte) number of empty bytes after DATA section (DATA PAD) 0x018-0x01B = 12000000 = 18 // (Integer) Byte length of STRING DATA section If additional bytes are inserted into the string data section, this register is incremented accordingly. 0x01D = 0E = 14 // (Byte) number of empty bytes after STRING DATA section (STRING PAD) Any changes to STRING DATA section requires a check of remaining empty bytes. There is always one "zero" byte after last entry. Empty byte count does not include that last "zero" byte. 0x020-0x023 = 30000000 = 48 // (Integer) Byte length of DATA MAP section (8-byte records) 0x025 = 00 // (Byte) number of empty bytes after the DATA MAP section (MAP PAD) 0x028-0x02B = 0C000000 = 12 // (Integer) Byte length of END section 0x02D = 04 // (Byte) number of empty bytes after the END section (END PAD) (ADDED 1.1 RULE) Section layout from 0x030 onward is fully defined by header lengths/pads: DATA + DATA PAD + STRING DATA + STRING PAD + DATA MAP + MAP PAD + END + END PAD. (ADDED 1.1 RULE) DATA MAP length (0x020-0x023) should be a multiple of 8 (records are 8 bytes). --- [DATA SECTION - starts at 0x030] NOTE: These pointer fields are only meaningful if the corresponding code exists in the DATA MAP. All pointer values below are u32 (little-endian) and are offsets into STRING DATA (relative to STRING DATA start). [Offset 08 of Data Map] 0x038-0x03B = XX000000 = 0 // (Integer) Location in STRING DATA for Chassis filename (*.CDFBIN) [Offset 18 of Data Map] 0x048-0x04B = XX000000 = 0 // (Integer) Location in STRING DATA for Engine filename (*.EDFBIN) [Offset 20 of Data Map] 0x050-0x053 = XX000000 = 0 // (Integer) Location in STRING DATA for Clutches filename (*.CBFBIN) (ALT/LEGACY NOTE) In some older translations this code is described as Turbo at 0x050. [Offset 28 of Data Map] 0x058-0x05B = XX000000 = 0 // (Integer) Location in STRING DATA for Turbo filename (*.TBFBIN) If DATA MAP does not call for Offset 28, then no turbo/supercharger is utilized. [Offset 30 of Data Map] 0x060-0x063 = XX000000 = 0 // (Integer) Location in STRING DATA for Gearbox filename (*.GDFBIN) [Offset 38 of Data Map] 0x068-0x06B = XX000000 = 0 // (Integer) Location in STRING DATA for Suspension filename (*.SDFBIN) (ALT NOTE) Some titles/variants use this pointer as Failure Model filename (*.GDFBIN). [Offset 40 of Data Map] 0x070-0x073 = XX000000 = 0 // (Integer) Location in STRING DATA for Gearbox filename (*.GDFBIN) (ALT NOTE) Some translations call this Collision; see Offset 50 for an additional collision pointer used in some variants. [Offset 48 of Data Map] 0x078-0x07B = XX000000 = 0 // (Integer) Location in STRING DATA for Suspension filename (*.SDFBIN) (ALT NOTE) Some translations call this Tyre; see Offset 58 below for Tyre in some variants. [Offset 50 of Data Map] 0x080-0x083 = XX000000 = 0 // (Integer) Location in STRING DATA for Collision filename(s) (*.XML) [Offset 58 of Data Map] 0x088-0x08B = XX000000 = 0 // (Integer) Location in STRING DATA for Tyre filename (*.HDTBIN) [Offset B8 of Data Map] 0x0E8-0x0EB = XX000000 = 0 // (Integer) Location in STRING DATA for KERS/DRS/Hybrid filename (*.BBFBIN) If DATA MAP does not call for Offset B8, then no *.BBFBIN is utilized. [Offset C0 of Data Map] 0x0F0-0x0F3 = XX000000 = 0 // (Integer) Location in STRING DATA for Push-to-pass filename (string) (ADDED 1.1 RULE) Pointer value rules: * Pointer is relative to STRING DATA start (not an absolute file offset). * Pointer should reference the first byte of a NUL-terminated string inside STRING DATA. * Typical “not present / not used” value is 0, but rely on DATA MAP presence to determine whether the field is valid. 0x088-0x08B = B072483F = 0.783 // (Float) FL Wheel/Tyre lateral offset in Meters 0x08C-0x08F = 3333B33E = 0.350 // (Float) FL Wheel/Tyre vertical offset in Meters 0x090-0x093 = 1B2F9DBF = -1.228 // (Float) FL Wheel/Tyre fore/aft offset in Meters 0x094-0x097 = B07248BF = -0.783 // (Float) FR Wheel/Tyre lateral offset in Meters 0x098-0x09B = 3333B33E = 0.350 // (Float) FR Wheel/Tyre vertical offset in Meters 0x09C-0x09F = 1B2F9DBF = -1.228 // (Float) FR Wheel/Tyre fore/aft offset in Meters 0x0A0-0x0A3 = 4260453F = 0.771 // (Float) RL Wheel/Tyre lateral offset in Meters 0x0A4-0x0A7 = 6DE7BB3E = 0.367 // (Float) RL Wheel/Tyre vertical offset in Meters 0x0A8-0x0AB = 1B2F9D3F = 1.228 // (Float) RL Wheel/Tyre fore/aft offset in Meters 0x0AC-0x0AF = 426045BF = -0.771 // (Float) RR Wheel/Tyre lateral offset in Meters 0x0B0-0x0B3 = 6DE7BB3E = 0.367 // (Float) RR Wheel/Tyre vertical offset in Meters 0x0B4-0x0B7 = 1B2F9D3F = 1.228 // (Float) RR Wheel/Tyre fore/aft offset in Meters 0x0B8-0x0BB = 14AE873E = 0.265 // (Float) FL Tyre width in Meters 0x0BC-0x0BF = 0E2D323F = 0.696 // (Float) FL Tyre height in Meters 0x0C0-0x0C3 = 14AE873E = 0.265 // (Float) FR Tyre width in Meters 0x0C4-0x0C7 = 0E2D323F = 0.696 // (Float) FR Tyre height in Meters 0x0C8-0x0CB = 6666A63E = 0.325 // (Float) RL Tyre width in Meters 0x0CC-0x0CF = 48E13A3F = 0.730 // (Float) RL Tyre height in Meters 0x0D0-0x0D3 = 6666A63E = 0.325 // (Float) RR Tyre width in Meters 0x0D4-0x0D7 = 48E13A3F = 0.730 // (Float) RR Tyre height in Meters 0x130-0x0133 = 00400344 = 525.0 // (Float) Brake Disc Glow Min (Start to glow slightly) 0x134-0x0137 = 00007A44 = 1000.0 // (Float) Brake Disc Glow Max (Full glow effect) 0x138-0x013B = 0000803F = 1.0 // (Float) ?? 0x13C-0x013F = 0000803F = 1.0 // (Float) ?? Unknown 0x140-0x0144 = 0000803F = 1.0 // (Float) ?? 0x13C-0x013F = 0000803F = 1.0 // (Float) ?? 0x140-0x143 = 0000803F = 1.0 // (Float) ?? 0x144-0x147 = FFFFFFFF // Beginning of Container...appears to be 0x148-0x14B = 01000000 = 1 // (Integer) ?? 0x14C-0x14F = 01000000 = 1 // (Integer) ?? 0x150-0x153 = 01000000 = 1 // (Integer) ?? 0x154-0x157 = 01000000 = 1 // (Integer) ?? 0x158-0x15B = 01000000 = 1 // (Integer) ?? 0x15C-0x15F = 01000000 = 1 // (Integer) ?? 0x160-0x163 = 01000000 = 1 // (Integer) ?? 0x164-0x167 = 01000000 = 1 // (Integer) ?? 0x168-0x16B = 01000000 = 1 // (Integer) ?? 0x16C-0x16F = 01000000 = 1 // (Integer) ?? 0x170-0x173 = 01000000 = 1 // (Integer) ?? 0x174-0x177 = 01000000 = 1 // (Integer) ?? 0x178-0x17B = 01000000 = 1 // (Integer) ?? 0x17C-0x17F = 0000B841 = 23.0 // (Float) ?? 0x180-0x183 = 00000000 = 0 0x184-0x187 = 0000803F = 1.0 // (Float) ?? 0x188-0x18B = 0000803F = 1.0 // (Float) ?? 0x18C-0x18F = 0000803F = 1.0 // (Float) ?? 0x190-0x193 = 0000803F = 1.0 // (Float) ?? 0x194-0x197 = 8FC2753E = 0.24 // (Float) ?? 0x198-0x19B = 8FC2753D = 0.06 // (Float) ?? 0x19C-0x19F = CDCC8C40 = 4.4 // (Float) ?? 0x1A0-0x1A3 = 00008040 = 4.0 // (Float) ?? 0x1A4-0x1A7 = C3F5A83E = 0.33 // (Float) ?? 0x1A8-0x1AB = 6666E63E = 0.45 // (Float) ?? 0x1AC-0x1AF = 6666863F = 1.05 // (Float) ?? 0x1B0-0x1B3 = CDCC4C3F = 0.8 // (Float) ?? 0x1B4-0x1B7 = 00000000 = 0 0x1B8-0x1BB = 3333333F = 0.7 // (Float) ?? 0x1BC-0x1BF = 00000000 = 0 0x1C0-0x1C3 = 0AD7233C = 0.01 // (Float) ?? 0x1C4-0x1C7 = 00000000 = 0 0x1C8-0x1CB = 00000000 = 0 Backfire Frequency 0x1CC-0x1CF = 00 00 00 3F = 0.5 = backfire: left exhaust backfire frequency 0x1D0-0x1D4 = CD CC 4C 3D =0.5 = backfire: right exhaust backfire frequency NOTE: From this point onward the addresses can change, due to both the byte length of the STRING DATA section and the size of the DATA MAP section. No matter the addresses the code will flow the same as follows... STRING DATA empty bytes for STRING DATA DATA MAP empty bytes for DATA MAP (if any) END SECTION Empty bytes for END SECTION [STRING DATA SECTION] NUL-terminated strings. There is always one "zero" byte after each entry in this section. (ADDED 1.1 RULE) Offsets stored in pointer fields (DATA) are relative to the start of STRING DATA. If you change STRING DATA length, you must ensure pointers remain valid and header string length (0x018-0x01B) is updated accordingly. [DATA MAP SECTION] This section performs parsing of the STRING DATA section, per the codes defined within this section. (ADDED 1.1 RULE) Each DATA MAP record is 8 bytes: * u32 code (little-endian) * 4 bytes padding (typically 00 00 00 00) The Offset Values are as follows (expanded known set)... 08 = 0x038 = Chassis file lookup (*.CDFBIN) 18 = 0x048 = Engine file lookup (*.EDFBIN) 20 = 0x050 = Clutches file lookup (*.CBFBIN) (legacy docs may call turbo here) 28 = 0x058 = Turbo file lookup (*.TBFBIN) 30 = 0x060 = Gearbox file lookup (*.GDFBIN) 38 = 0x068 = Suspension file lookup (*.SDFBIN) (variant: Failure model *.GDFBIN) 40 = 0x070 = Gearbox file lookup (*.GDFBIN) (variant mappings exist) 48 = 0x078 = Suspension file lookup (*.SDFBIN) (variant mappings exist) 50 = 0x080 = Collision file lookup (*.XML) 58 = 0x088 = Tyre file lookup (*.HDTBIN) B8 = 0x0E8 = KERS/DRS/Hybrid file lookup (*.BBFBIN) C0 = 0x0F0 = Push-to-pass string lookup Actual Data Map for this VDFM (example from porsche_991_gt3rs.vdfm) 0x1F0 = 08 = 0x038 = Chassis file lookup 0x1F8 = 18 = 0x048 = Engine file lookup 0x200 = 30 = 0x060 = Gearbox file lookup 0x208 = 38 = 0x068 = Suspension file lookup 0x210 = 40 = 0x070 = Collision file lookup 0x218 = 48 = 0x078 = Tyre file lookup [END SECTION] End section and empty bytes for end section (length/pad defined in header).