The saveram .srm file is 2,048 (0x800) bytes long. It seems only 512 (0x200) bytes are used. A simple sum-of-bytes checksum is used on each of the 3 sections of best record time data.
|Knight League + checksum||0xA7 bytes|
|Queen League + checksum||0xA7 bytes|
|King League + checksum||0xA7 bytes|
|Master Class enable||0x01 byte|
|unused (0xFF filled)||0x600 bytes|
FZERO string bytes
The sram data begins and ends with 5 bytes FZERO (
0x4F). These 5 bytes are compared to the ROM location $00:8869 (PC file location 0x0869) and must match.
Each League section contains 55 best records, followed by a 2 byte checksum. There are 10 best records plus 1 best lap record per track (in that order). There are 5 tracks per League.
Best Record format
Each best record uses 3 bytes. The upper 4 bits of the first byte defines which car set the record, and whether or not it was in practice mode. If the upper 4 bits are 0, then the record is ignored. The lower 4 bits of the first byte are the minutes. The second byte is the seconds. The third byte is the milliseconds. The game initializes all records to
Above: the upper 4 bits of the first byte is B, which represents the Fire Stingray set the time in Grand Prix mode.
|8||Blue Falcon||Grand Prix|
|9||Wild Goose||Grand Prix|
|A||Golden Fox||Grand Prix|
|B||Fire Stingray||Grand Prix|
Each League section contains 0xA5 bytes of best records followed by 2 bytes of checksum (stored little endian). To calculate the checksum, simply add each of the bytes together, and take the lower 16 bits of the total. Then you byte-swap the value and write that to the .srm. So if you add all of the 0xA5 bytes together and get
0x1234, then it will be stored as
0x12. There are 3 separate checksums for the 3 Leagues.
Master Class unlock
This is a single byte that unlocks Master Class for each League. It is not covered by a checksum and can be freely edited, but the upper 4 bits must equal the lower 4 bits. It is a bitwise value, so
0x33 would unlock for Knight and Queen but not King. Setting the upper most bit
0x88 results in an invalid value and gets reset to
||max value: all|