Post by Nuppiz on Apr 17, 2020 11:06:11 GMT 2
Editor's note: Salvaged from an SQL backup of GPRaceGames.com, kindly shared by hmw2.
So here it is, the (hopefully) ultimate guide to GPM2 hex editing. With this guide you can edit (almost) everything you possibly can in a GPM2 executable. Please be aware that the hex addresses included in this guide are for the 1.02B version, as the possibility to edit everything and way more than what the Starfire Editor is capable of exe-wise renders hex editing the old exes obsolete. However, the Starfire Editor itself still remains very relevant due to its other features, some of which are also helpful during hex editing.
Before starting anything, make a backup of your EXE. Nothing should go wrong if everything is done according to the guide, but just in case you accidentally make a wrong edit the EXE may become permanently corrupt and you lose all of your edits.
First some basics of hex editing. When you open any file in a hex editor, you'll see all those weird values like 3A, 05, FF etc. These are hexadecimal representations of the file's data. Hexadecimal is a numbering system different to our normal decimal system, which ranges from 0-9 (10 distinct values); the hexadecimal system ranges from 0-F (16 distinct values, 0-15 in decimal values). This hexadecimal data is always stored in bytes, pairs of two hexadecimal values. So for example a value representing 1 is written as 01 in hexadecimal, and a value representing 15 in the decimal system is written as 0F. Therefore, a single byte can hold 16 x 16 = 256 different values ranging from 0 (written as 00) to 255 (written as FF). This is an 8-bit integer.
Logically, any data that never has more than 256 alternatives uses a single 8-bit byte. In a GPM2 exe this means all nationality settings (drivers, engines, tracks), supplier ratings, ideal track setups (each setting has its own value separate from others), track lap counts, minutes and seconds in lap records and driver skills and certain statistics (for those drivers that have their skills also stored in the exe). Most hex editors have a "data inspector" enabled either by default or through a menu which shows the hex value's equivalent in a decimal value, so you can instantly see how your edits have affected the numerical parameters.
So what happens when the value has more than 256 alternatives? Then we move on to a 16-bit integer, also known as a shortint (short integer) which combines the values of two bytes. A shortint can therefore hold 256 x 256 = 65 536 different values (FF FF in hexadecimal). For example, if we want to use the value of 500 (which cannot be reached on a single byte) we have to write F4 01; the latter byte represents a value of 256 on which the value of the former byte (F4, or 244 in decimal) is added. Likewise, a value of 800 would be represented as 20 03 - three full 256s amount to 768, on top of which we need to add 32 (20 in hexadecimal) to reach the desired amount.
Luckily, most hex editors come with a base converter so you don't have to manually calculate decimal values into hexadecimal, but the above helps you understand how the longer hex values work. In a GPM2 exe, shortints are used to save all values that can be higher than 255 (the maximum value a single byte can hold, remember?). These are pretty much just engine power and weight, milliseconds in lap records and certain statistics of the drivers who are saved in the exe.
Finally, if we need even bigger values we need to use 32-bit integers, or longints. These babies can store no less than 256 x 256 x 256 x 256 = 4 294 967 296 different values, or well over four billion in simpler terms. These behave in such a manner that using a base converter is pretty much required (not that you would try calculating these manually anyway, right?), which is also why I'm not going into any further detail regarding them. In a GPM2 exe longints are used exclusively for price and salary data. Customer engines usually cost between a few hundred thousand and a couple of million dollars, so using longints to determine their price makes sense. Similarly, driver wages (again, for those drivers that have their data stored) can be in the millions. But oddly enough all external supplier and car part prices are determined in longints as well, so it's theoretically possible to have a fuel contract or a nose cone that costs $4 billion!
Aside from numerical data, a lot of plain text can be found in the exe as well. The names of all parts, sponsors, nationalities, external suppliers and track record holders are easily editable if your hex editor supports text editing (most of them do). But always keep one rule in mind: there must always be at least one 00 byte between each text string, otherwise the game refuses to work completely. You can't add bytes to make the available space longer - what you see is what you have to work with. An example: one of the track records you want to edit is held by Damon Hill but you want to change that to Nigel Mansell. Since the name you want to insert is longer than the space reserved for it, you have to shorten it - "N Mansell" should suffice. Now the name is actually one character shorter than what it was originally, so without edits you'd end up with N Manselll in-game. To eliminate this problem, move back to the hexadecimal side of things and enter 00 bytes until all of the "extra" text is cleared.
Fig. 1: Click at the start of the name you want to edit on the text side of the editor
Fig. 2: Write over the name
Fig. 3: Remove the leftovers of the previous name by inserting 00 bytes on the hexadecimal side
In the above example you only needed to remove one letter, but if for example you replaced Michael Schumacher with Ayrton Senna, you'd need to remove six (the "macher" part). For this, you can use two methods: either replace all six letters with 00 bytes, or if you don't mind a bit messy-looking exe just replace the first "extra" letter with a 00 byte and leave the rest ("acher") alone. GPM2 understands 00 as the end of that string and moves to the start of the next string, ignoring the leftover bit you just left there. This same rule applies to any text strings you may edit in the exe.
And that's it, there's all of the basics of GPM2 hex editing covered! The next post contains the most important bits: all known editable addresses in a GPM2 exe.
So here it is, the (hopefully) ultimate guide to GPM2 hex editing. With this guide you can edit (almost) everything you possibly can in a GPM2 executable. Please be aware that the hex addresses included in this guide are for the 1.02B version, as the possibility to edit everything and way more than what the Starfire Editor is capable of exe-wise renders hex editing the old exes obsolete. However, the Starfire Editor itself still remains very relevant due to its other features, some of which are also helpful during hex editing.
Before starting anything, make a backup of your EXE. Nothing should go wrong if everything is done according to the guide, but just in case you accidentally make a wrong edit the EXE may become permanently corrupt and you lose all of your edits.
First some basics of hex editing. When you open any file in a hex editor, you'll see all those weird values like 3A, 05, FF etc. These are hexadecimal representations of the file's data. Hexadecimal is a numbering system different to our normal decimal system, which ranges from 0-9 (10 distinct values); the hexadecimal system ranges from 0-F (16 distinct values, 0-15 in decimal values). This hexadecimal data is always stored in bytes, pairs of two hexadecimal values. So for example a value representing 1 is written as 01 in hexadecimal, and a value representing 15 in the decimal system is written as 0F. Therefore, a single byte can hold 16 x 16 = 256 different values ranging from 0 (written as 00) to 255 (written as FF). This is an 8-bit integer.
Logically, any data that never has more than 256 alternatives uses a single 8-bit byte. In a GPM2 exe this means all nationality settings (drivers, engines, tracks), supplier ratings, ideal track setups (each setting has its own value separate from others), track lap counts, minutes and seconds in lap records and driver skills and certain statistics (for those drivers that have their skills also stored in the exe). Most hex editors have a "data inspector" enabled either by default or through a menu which shows the hex value's equivalent in a decimal value, so you can instantly see how your edits have affected the numerical parameters.
So what happens when the value has more than 256 alternatives? Then we move on to a 16-bit integer, also known as a shortint (short integer) which combines the values of two bytes. A shortint can therefore hold 256 x 256 = 65 536 different values (FF FF in hexadecimal). For example, if we want to use the value of 500 (which cannot be reached on a single byte) we have to write F4 01; the latter byte represents a value of 256 on which the value of the former byte (F4, or 244 in decimal) is added. Likewise, a value of 800 would be represented as 20 03 - three full 256s amount to 768, on top of which we need to add 32 (20 in hexadecimal) to reach the desired amount.
Luckily, most hex editors come with a base converter so you don't have to manually calculate decimal values into hexadecimal, but the above helps you understand how the longer hex values work. In a GPM2 exe, shortints are used to save all values that can be higher than 255 (the maximum value a single byte can hold, remember?). These are pretty much just engine power and weight, milliseconds in lap records and certain statistics of the drivers who are saved in the exe.
Finally, if we need even bigger values we need to use 32-bit integers, or longints. These babies can store no less than 256 x 256 x 256 x 256 = 4 294 967 296 different values, or well over four billion in simpler terms. These behave in such a manner that using a base converter is pretty much required (not that you would try calculating these manually anyway, right?), which is also why I'm not going into any further detail regarding them. In a GPM2 exe longints are used exclusively for price and salary data. Customer engines usually cost between a few hundred thousand and a couple of million dollars, so using longints to determine their price makes sense. Similarly, driver wages (again, for those drivers that have their data stored) can be in the millions. But oddly enough all external supplier and car part prices are determined in longints as well, so it's theoretically possible to have a fuel contract or a nose cone that costs $4 billion!
Aside from numerical data, a lot of plain text can be found in the exe as well. The names of all parts, sponsors, nationalities, external suppliers and track record holders are easily editable if your hex editor supports text editing (most of them do). But always keep one rule in mind: there must always be at least one 00 byte between each text string, otherwise the game refuses to work completely. You can't add bytes to make the available space longer - what you see is what you have to work with. An example: one of the track records you want to edit is held by Damon Hill but you want to change that to Nigel Mansell. Since the name you want to insert is longer than the space reserved for it, you have to shorten it - "N Mansell" should suffice. Now the name is actually one character shorter than what it was originally, so without edits you'd end up with N Manselll in-game. To eliminate this problem, move back to the hexadecimal side of things and enter 00 bytes until all of the "extra" text is cleared.
Fig. 1: Click at the start of the name you want to edit on the text side of the editor
Fig. 2: Write over the name
Fig. 3: Remove the leftovers of the previous name by inserting 00 bytes on the hexadecimal side
In the above example you only needed to remove one letter, but if for example you replaced Michael Schumacher with Ayrton Senna, you'd need to remove six (the "macher" part). For this, you can use two methods: either replace all six letters with 00 bytes, or if you don't mind a bit messy-looking exe just replace the first "extra" letter with a 00 byte and leave the rest ("acher") alone. GPM2 understands 00 as the end of that string and moves to the start of the next string, ignoring the leftover bit you just left there. This same rule applies to any text strings you may edit in the exe.
And that's it, there's all of the basics of GPM2 hex editing covered! The next post contains the most important bits: all known editable addresses in a GPM2 exe.