What is ‘gible’?
‘gible’ is actually the name of a Pokemon in Sinnoh.
It’s also the name of the open-source binary patcher I wrote focusing on mainly patching GBA ROMs. It’s written in GNU99 C and has a Makefile build system.
You can find the entire source of gible here.
If you’re already familiar with C, you should be able to go through its code in an hour or two without any issues.
Why?
Retro games have always been a fascination to me. Working their way through the limits imposed on them, be it hardware specs or software limitations, to produce something magical and memorable throughout the decades is awe-inspiring.
My favorite piece of hardware is the GBA, and my favorite games for it were the ones from the Pokemon series.
A lot of years have passed since it first hit the shelves, and in that span of time, both consoles and games in general have vastly improved.
But there are still people who play these games and reminisce the g-olden days, and there are others who set upon to improve and bring these games to the modern standard by making modifications to the game directly.
Now, how did these “modifications” work exactly?
For most retro consoles, the games were stored in a ROM cartridge. These cartridges could be dumped to get the contents of the ROM itself as a single file. This file is known as the game ROM. The game ROM could be modified/hacked to bring the changes you wanted.
Now, you couldn’t just give out the modified file out directly. That would be in violation of a few IP laws.
But, what if we just compared both the original ROM file and the modified file, took note of wherever the data had changed and packaged these changes into a single file. It would have no direct relation to the original ROM file and was only useful if a person actually had the original copy on hand, all with the added benefit of being light in size.
Well, that’s essentially what a binary patch is.
gible aids in the application and creation of a few commonly used binary patches in the GBA rom hacking scene.
Different Patch Types
gible supports applying IPS, IPS32, UPS and BPS patches to files. It can also create IPS, IPS32 and UPS patches too, although I really wouldn’t recommend it.
Here’s a simple overview of all the patches mentioned above.
IPS
Easiest patch type to apply and create.
Uses 3-byte unsigned integers for storing offsets, so the patches cannot affect data beyond the offset of 16842750, effectively limiting them to a range of 16MB.
It also handles multiple repeated bytes separately (RLE).
IPS32
Improved version of IPS.
Uses 4-byte unsigned integers instead of 3-byte ones for storing offsets, resulting in greater patch range (4.2GB).
UPS
Uses VLE encoding for storing offsets, which eliminates the range limitation.
Offsets are encoded relatively.
It also stores the input and output file sizes with the same encoding.
The patch is stored as a series of bytes which are to be XOR’ed with the input.
At the end, there are 3 CRC32 checksums for the source, output and the patch (everything up until the final checksum).
You can retrieve the original file from a patched file by reapplying the same patch over it.
BPS
Similar to the UPS patch in most aspects, but instead of having series of data to be inserted, BPS stores the steps to create the output file from the input file.
This means you can’t retrieve the original file from the patched one.
It can also store metadata information.
File I/O
For handling I/O with files, a simple filemap system was implemented.
A file can be either memory mapped (using mmap in Unix and MapViewOfFile in Windows) or just simply loaded into heap memory (read into a malloc-ed array).
Either way, having a filemap makes the patching functions much less complex and more faster as you have direct access to the data as an array of bytes.
A simple byte vector has been implemented for creating patches.
Interface
gible is a CLI application. There is no GUI, and there aren’t any plans to make one for it either. You just use it directly from the terminal by passing in arguments.
For parsing CLI arguments, there’s a tiny, yet scalable argument parser shipped with gible. This makes the process of adding new arguments to the program much more easier than hard-coding argument cases in a huge switch statement.
gible has two subcommands for its two major functionalities - ‘patch’ and ‘create’.
Patch mode is used to apply a existing patch onto a file. You can specify arguments to either ignore the checksums or make checksum checking more strict for formats which support them (UPS and BPS).
Create mode is used to create a patch from a source file and modified file. The type of patch created is decided through the extension used for the resulting file.
Build System
gible uses a simple Makefile script as its build system. Building it on Unix is as easy as typing in “make”.
For Windows, it’s the same script, but instead of a bare “make”, use “make windows”. This runs the same script, but invokes the MinGW toolchain’s compiler, resulting in a Windows executable build.
Closing
gible had its first commit on 31st May 2022. It was started as an attempt to learn the inner workings of these binary patches and how to apply and create the file myself.
It’s been more than an year since its inception, and I wasn’t exactly be consistent with its development. I’d fix some bugs one day, then leave it for months on end, before continuing on with this wretched cycle.
At the early stages, it only supported Unix systems and did not support patch creation. Now, both of those features have been added, lots of bugs have been fixed along the way and a lot of code has been rewritten.
Ergo, gible is nearing completion, at least, in terms of the vision for this project. BPS creation will be implemented in the near future, but it’s nowhere done in terms of optimization and the loads of bugfixes to come.
It might not be the best or the most feature-rich binary patcher out there, but it served its purpose, for me at least.