Skip to main content

All Your Radio Are Belong To Us

Grand Theft Auto III is the first game in the 3D universe1 of the series. It lets you cruise around Liberty City in various vehicles. Most of them are equipped with regular radios. However, there are two sets of vehicles that either don’t have radios or override the radio station with some random police chatter.

To complete the game in 100% one has to finish the following side missions2: Paramedic (reach level 12 in one go), Vigilante (kill 20 criminals on each island), Firefighter (extinguish 20 fires on each island). They have one thing in common – all require player to spend a substantial amount of time in a vehicle without normal radio stations.

This summer my friends from the Polish speedrunning community are going to play the entire GTA 3D trilogy 100% in a relay for a third time. Previous attempts were completed in 55h in 2020 and 49h in 2021. One of them found this plugin by ThirteenAG that enables radio stations in all vehicles but unfortunately it doesn’t work with the Steam version of the game. It also has a (later discovered to be deliberate) side effect of allowing all vehicles to use the Pay ’n’ Spray service (it fixes the car and cancels police wanted level) which changes the core gameplay. That last thing motivated me to figure out how the plugin worked in order to create a version that: 1. will work with Steam version; 2. will not make the game easier.

For some reason, the original plugin is no longer available on the GTAGarage page. Luckily, it has been indexed and archived in 2015 by the Wayback Machine so I was able to retrieve it for analysis. It turned out to be a regular DLL file with extension changed to .asi. GTA III loads .asi files placed inside mss directory in the installation directory on startup – that’s great beacause no extra injectors are needed to make mods work.

After a quick analysis it appeared that all the plugin did was:

  • create a thread with delayed execution (never figured out why)
  • detect the version of the game by checking some magic values in memory
  • set other magic values in memory depending on the detected verison. Cool, now I could figure out which offsets in memory did what.
Cheat Engine values table when running a Steam version of the game.
Cheat Engine values table when running a Steam version of the game.

Once I realized which branch should I take for each version of the game I started to play with the values in Cheat Engine debugger. That’s when it turned out that the aforementioned Pay ’n’ Spray “issue” was an intended feature! At this point I could just recreate the mod (or patch the current one) without this “feature” but I wanted to fully understand why it worked. Remember the magic values the mod was setting? I’m not proficient at reverse engineering nor x86 assembly but thanks to pitpo I managed to figure out that the 0xEB in place of 0x77 was in fact turning a conditional jump into an unconditional jump.

I was sceptical about loading the game binary into Ghidra but I eventually did it only to learn that I could easily map the related code to re3. Couple years ago a group of fans made an effort to rewrite the original game in order to fix bugs and port the game to new platforms. It was called re3. I wrote “was” because the project has received a takedown from the publisher of GTA, which was later countered, and then Take-Two took it to court… Thanks to re3 I could confirm that the change I’m making won’t affect any other aspect of the game.

Spot 10 differences.
re3 on the left, ghidra output on the right. Spot 10 differences. Whole car list that includes IDs is available here.

Now the only thing left was to somehow make it work with a binary shipped by Steam. That version is supposedly corresponding to the retail version 1.1 however there’s also a layer of DRM sprinkled on top. Once again pitpo’s help was invaluable as he pointed me in directrion of Steamless. That tool can take out some variants of the SteamStub DRM. To my surprise, it just worked. With the unpacked binary, I was able to trace the required code which turned out to be only slightly offsetted from the 1.1 version.

The final outcome of this journey is available on my GitHub. The pun from the post’s title is now apparent ;)

  1. First there was the 2D universe which included first two games alongside their addons. In 2001 GTA III was released which gave a start for the 3D universe. It not only includes Vice City and San Andreas but also handheld games: Advance, Liberty City Stories, Vice City Stories. The latest universe in the franchise is called HD and it spans across IV (and its two expansions), Chinatown Wars and widely acclaimed V. GTA worlds blend together when it comes to timelines and appearances of some characters and things like brands. ↩︎

  2. Alongside many other tedious tasks. The whole list is available here↩︎