Table of Contents

EEPROM Memory Map

Mario Kart 64 uses a 512 byte EEPROM unit to save time trial records and the selected sound mode. A mirror of EEPROM data is kept at 8018EB90 in RAM.

Top level structure

Offset Length Description
0x000 24 Luigi raceway record set
0x018 24 Moo Moo Farm record set
0x030 24 Koopa Troopa Beach record set
0x048 24 Kalimari Desert record set
0x060 24 Toad's Turnpike record set
0x078 24 Frappe Snowland record set
0x090 24 Choco Mountain record set
0x0A8 24 Mario Raceway record set
0x0C0 24 Wario Stadium record set
0x0D8 24 Sherbet Land record set
0x0F0 24 Royal Raceway record set
0x108 24 Bowser's Castle record set
0x120 24 D.K's Jungle Parkway record set
0x138 24 Yoshi Valley record set
0x150 24 Banshee Boardwalk record set
0x168 24 Rainbow Road record set
0x180 4 50cc trophy information
0x181 4 100cc trophy information
0x182 4 150cc trophy information
0x183 4 Extra trophy information
0x184 1 Audio setting
0x185 1 Unused, padding
0x186 2 Checksum of 0x180-0x184
0x188 12 Copies of Mushroom Cup 1st Record Times
0x194 12 Copies of Flower Cup 1st Record Times
0x1A0 12 Copies of Mushroom Cup Lap Record Times
0x1AC 12 Copies of Flower Cup Lap Record Times
0x1B8 6 Unknown (Padding?)
0x1BE 2 Checksum of 0x188-0x1BD
0x1C0 12 Copies of Star Cup 1st Record Times
0x1CC 12 Copies of Special Cup 1st Record Times
0x1D8 12 Copies of Star Cup Lap Record Times
0x1E4 12 Copies of Special Cup Lap Record Times
0x1F0 6 Unknown (Padding?)
0x1F6 2 Checksum of 0x1C0-0x1F5
0x1FC 1 Copy of audio setting (0x184)
0x1FD 1 Copy of Unused, padding? (0x185)
0x1FE 2 Copy of Checksum of 0x180-0x184

Course record set

For each course, there is a 24 byte structure that contains the five best completion records and the best lap record. There is an additional byte which indicates whether or not any records have been saved for the set, and another byte which could be a checksum.

Offset Length Description
0x000 3 1st record
0x003 3 2nd record
0x006 3 3rd record
0x009 3 4th record
0x00C 3 5th record
0x00F 3 Best lap record
0x012 1 Records exist (00 or 01)
0x013 4 Unknown (Unused?)
0x017 1 Record Checksum

Record Format

Record entries are 24 bits each and are stored with little endian byte ordering:

tttttttt tttttttt cccctttt

Where t is a 20 bit value for the completion time in centiseconds and c is a 4 bit ID of the character used in the trial. If a record has a time greater than or equal to 100 minutes, it is not displayed.

Valid character IDs for c are as follows:

ID Character
0 MARIO
1 LUIGI
2 YOSHI
3 TOAD
4 D.K.
5 WARIO
6 PEACH
7 BOWSER

The default value applied to record entries is 0xC02709, which is 100 minutes and Mario as the character selection.

Checksums

Record Checksum

Each record contains a 1-byte checksum at offset 0x17 and is computed as follows:

unsigned char RecordChecksum(unsigned char data[], int offset)
{
   int checksum = 0;
   for (int rec = 0; rec < 7; rec++) {
      for (int i = 0; i < 3; i++) {
         unsigned char val = data[offset + rec * 3 + i];
         checksum += (val * (i + 1)) + rec;
      }
   }
   return (unsigned char)(checksum & 0xFF);
}

0x186

0x186 is a checksum of offsets 0x180-0x184 and is computed by procedure at 800B492C and 0x187 is computed by procedure at 800B49E4

eeprom[0x186] = (eeprom[0x180] + 1 + ((eeprom[0x181] + 1) * 2) + 1 + ((eeprom[0x182] + 1) * 3) + 2 + ((eeprom[0x183] + 1) * 4) + 3 + ((eeprom[0x184] + 1) * 5) + 4) & 0xFF
eeprom[0x187] = (eeprom[0x186] + 0x5A) & 0xFF

0x1BE and 0x1F6

// eeprom: base of EEPROM data
// offset: offset in eeprom to checksum (either 0x188 or 0x1C0)
void Checksum1BEand1F6(unsigned char eeprom[], int offset)
{
   int checksum = 0;
   int blockOffset = offset;
   for (int block = 0; block < 3; block++) {
      int loopOffset = blockOffset + 1;
      checksum += (eeprom[blockOffset] + 1) * (block + 1);
      for (int byteOff = 1; byteOff < 0x11; byteOff += 0x4) {
         int mult2 = (eeprom[loopOffset] + 1) * (block + 1);
         checksum += mult2 + byteOff;
         int mult3 = (eeprom[loopOffset + 1] + 1) * (block + 1);
         checksum += mult3 + byteOff + 1;
         int mult4 = (eeprom[loopOffset + 2] + 1) * (block + 1);
         checksum += mult4 + byteOff + 2;
         int mult5 = (eeprom[loopOffset + 3] + 1) * (block + 1);
         checksum += mult5 + byteOff + 3;
         loopOffset += 4;
      }
      blockOffset += 0x11;
   }
   eeprom[offset + 0x36] = (unsigned char)(checksum & 0xFF);
   eeprom[offset + 0x37] = (unsigned char)((data[offset + 0x36] + 0x5A) & 0xFF);
}

References