Tag Archives: Stunt GP

Stunt GP #2: Timeless issues

When I started playing Stunt GP on Windows 10 I immediately noticed there is an annoying half second freeze every 7 minutes 9.5 seconds, making the game way more annoying than on older PCs, where the problem seemed non-existent. After one and a half years I finally found the reason for that and fixed it 🙂

The problem

The game uses QueryPerformanceFrequency() and QueryPer-
formanceCounter()
functions to measure time. This first function returns frequency with which the counter will update. This frequency is different on each PC, but I’ll talk more about that later. Performance counter itself is 64bit, on even fastest PCs it would take 24 THOUSANDS years for the performance counter to fill up and overflow, resetting to 0 (assuming 24 MHz frequency). The problem is the game uses only 32 bits of this counter, meaning the counter will overflow after just 3 minutes in worst case scenario.

On older PCs the frequency of this timer oscillated (pun intended) around 2-3 MHz, so the counter would overflow after 23 to 36 minutes. In Windows 10 Microsoft decided to set the frequency of this counter to 10MHz, independent of the hardware, so the counter would fill up after exactly 7 minutes and 9.5 seconds. Users may force Windows to use hardware timer, but instead of seeing 2-3MHz clock speeds on newer PCs with High Precision Event Timer (HPET) this timer may as well have speed of 14 or 24MHz, filling the counter in 5 or even 3 minutes!

Now, the game very badly handles this overflow, simply freezing. The only reason the game unfreezes after 0.5s is code that detects if the game freezes for a half second, but the overflow itself isn’t handled when it happens.

The solution

Using StuntKit solution I was able to create a new module that on the game start replaces function that counts the time with one that detects overflow and resets internal game timers, removing 0.5s freezes.

Stunt GP #1: unpacking files

What is inside the game folder?

In the game directory there are .wad, .pc, and .pmd files. .Pmd files are in “meshdata” directory, so they probably are 3D models. .Pc files are located in “graphics24”, so they could be textures. With only .wad files remaining I assumed they might be some kind of archive, perhaps the same as .wad files used by Doom.

Magic and wizardry

Many binary files contains “magic”, first few bytes of a file that helps identifying it, so we’ll start there. .Pmd files magic were “PMD V1.83”, I haven’t found anything about this format anywhere. .Pc files magic was “TM!”, and .wad files was “DIR”.

Left part of the hex editor shows bytes in the file, and the right part shows text representation of each byte (if it exists)

.Wad files

As it turns out, after first 4 bytes there’s file size written as 32bit little-endian integer. Little endian means that the order of bytes is reversed, so in below example “1C 64 02 00” written in hexadecimal should be 0x0002641C, or 156700 in decimal system, exactly the same as the size in bytes of boot.wad. After that there are 4 bytes of unknown purpose. And after these 12 bytes we see “TM!” meaning that .wad file is really some kind of archive and this one contains at least one .pc file inside.

The unknown value from before is smaller than the file size, so it might point at something inside this file. Let’s look what’s under the address 0x000252B4:

“0A” and many 00 bytes, with some occasional random data here and there. About 4096 bytes after this we can see names of the files inside this archive:

As at the beginning of the file here also most of the fields are aligned to 4 bytes, so after the filename there are “00” bytes. After that there are 12 bytes, probably grouped as 3 4-byte numbers, so the first file should also have these 12 bytes before a filename.

For the first file the first number is 0, second one is equal to 0x0C, and third is 0x448A (17 546). Second value is a pointer to where data starts in the archive and third is a size of the data. These informations should suffice for unpacking all files from the archive.

.Wad files: more info

I’ll skip most of the description how I was able to determine what each value should be or do , this post is already quite long, and I’ll jump straight to some conclusions.

After each file data there is “1A” byte and padding “00” bytes, so the next file will always start on a offset aligned to 4 bytes. As it turns out, the .wad files are just renamed .dir files form Worms Armageddon, what I learned after creating unpacking script 🙁 However the information about the hash array with 1024 4-bytes entries allowed me to create my own .wad files and replace existing files.

.Pc files

In this file values are aligned to 2 bytes: at the beginning there is 4-bytes of magic “TM! 0x1A”, 0x0003 value that never changes and seems unused in the game, width and height of the image and compressed image data.

256x256px image (0x100 = 256)

Luckily, .pc to .bmp converter already exists: https://forum.xentax.com/viewtopic.php?f=16&t=16944&p=160362#p146133,

Sadly, it was just a wrapper for a function written in assembly, ripped directly from the game executable, making it hard to read or edit. I was able to understand how decomproession of these files works and rewrite the converter (and packer!) in Python: https://github.com/StuntKit/stunt_gp_formats

Replacing files works. I’ve chosen the worst possible image to replace, because team logo uses three separate files and I have replaced just one of them.