Pokémon GBA Save Format
The Pokemon GBA games save their data to 128 KB of flash memory on the cartridge. This is larger than the GBA can address as a whole, so it is handling by a banking system that splits this into 2 64 KB banks.
Each bank is further split into 16 4KB blocks. These blocks contain data, as well as validation and identification values which aid in preventing modification and allowing detection of corruption.
The game uses these 32 blocks to save 2 save slots which take up 14 blocks each, so the second crosses the bank boundary. It alternates between each slot when you save the game so there is always a copy of your current game and your previous game should corruption occur. It also rotates the starting block number, so you may find that the first block is number 5, and blocks 0-4 come after block 13.
Note: emulators do not often recognise this banking method and will not save the second page to the .sav file. This results in the message "The save file is corrupt, the previous file will be used." This can usually be avoided by ensuring that 128KB save support is enabled.
Unpacking the Save File
So I mentioned that each block contained validation and identification values. This is in the form of a 12 Byte block footer that contains the following information:
- Block Number as an 8-bit integer (within the current save)
- A byte of padding
- A 16-bit CheckSum of the data portion of the block
- A 32-bit validation code that is always 0x08012025
- And the Save Number as a 32-bit integer.
The first 3,968 Bytes of the block contain the actual save data.
First you would need to identify the most recent save based on the Save Number. The higher number indicates the more recent save.
Because the game calculates the checksum before it loads the file, you cannot just modify the save file as it is, you'd need to update the CheckSum after editing. Editing in this format is somewhat impractical though as a number of data structures cross the block boundaries.
Building the full save file requires you to sort the blocks into the correct order and append the data from each block together. The resulting data should be 55,552 Bytes in total.
Calculating the Checksum
The checksum is generated by first adding up the data section cast as 32-bit integers (little-endian byte order). Then add the upper and lower 16-bit values together. So (sum & 0xFFFF) + (sum >> 16), and truncate to 16-bits.
I previously believed this to be a simple 16-bit checksum but I've recently tested it myself, found it to be wrong and part-remembered, part-looked up the correct method. Apologies to anyone I have advised otherwise.
Repacking the Save File
To repack the file to save it to a slot, first split it into 14 blocks of 3,968 Bytes. Add 116 Bytes of padding to each block, then add the 12 Byte footer structure as above, incrimenting the Save Number appropriately.
Join the blocks together, starting with the first block that was previously saved + 1. This will produce the 14 block save file which you can just write into the slot with the oldest file.
Note: If you're writing to a 64 KB .save file then just overwrite the first slot as the second one will be missing all but 2 blocks. The game will see that the second save is incomplete and pick up the first one.