User Tools


EEPROM Memory Map

Blast Corps uses a 512 byte EEPROM in the cartridge to save game state of levels unlocked, record times, and tutorials given. A copy of the EEPROM data is stored at 80364A40 in RAM.

Top level structure

Offset Length Description
0x000 0x8 Name (ASCII name entered during game start)
0x008 0x1 Selected Level
0x009 0x1 Unknown?
0x00A 0x2 Points
0x00C 0x1 Rank
0x00D 0x3 Unknown?
0x010 0x4 Vehicles
0x014 0x4 Total Accumulated Money
0x018 0x3C Level Medals
0x054 0x3C Level Paths
0x090 0x1 Scientists
0x091 0x1 Event
0x092 0x3C Level Vehicles
0x0CE 0x12 Tutorials
0x0E0 0xE Unknown?
0x0EE 0x1 Cut Scenes
0x0EF 0x4 Unknown?
0x0F3 0x1 Control Mode
0x0F4 0x8 Unknown?
0x0FC 0x4 Checksum
0x100 0xF0 Level Times
0x1F0 0x8 Language
0x1982198219821982 = English
0x1945194519451945 = German
0x1F8 0x8 Footer
0x2704197125121981 = Before saving rest of EEPROM data
0x87569AB6CD076AEC = After saving rest of EEPROM data

Level Times

The record time is stored for each level as a 2-byte integer in big endian in units of hundredths of a second followed by two bytes of checksum. The checksum is computed as follows (where ^ is XOR):

record[2] = 0x55 ^ record[0];
record[3] = 0xFF ^ record[0] ^ record[1] ^ record[2];

For example, if the record value is 0x00E4554E, the time is 0x00E4 = 228 = 22.8 seconds.
Checksum verifies because 0x00 ^ 0x55 = 0x55, and 0xFF ^ 0x00 ^ 0xE4 ^ 0x55 = 0x4E

Checksum

The 4-byte checksum at 0xFC is computed using functions that are stored in the hd_front_end_text.raw gzip file. The UpdateChecksum/801F2C84 function takes a pointer to the start of the EEPROM data in A0 and an offset to compute the checksum over and store result in A1. It uses helper function ComputeChecksumByte/80205760 to compute each round.

// helper function for checksum update routine below
static u8 ComputeChecksumByte(u8 *data) // 80205760
{
   u8 cksum = 0;
   u8 key;
   for (int i = 0; i < 33; i++) {
      for (int j = 7; j >= 0; j--) {
         if (cksum & 0x80) {
            key = 0x85;
         } else {
            key = 0x00;
         }
         cksum = cksum << 1;
         if (i == 0x20) {
            cksum = cksum & 0xFF;
         } else {
            u8 mask = data[i] & (1 << j);
            u8 bit = mask ? 1 : 0;
            cksum |= bit;
         }
         cksum = cksum ^ key;
      }
   }
   return cksum;
}
 
// usually called with base address of EEPROM data and length = 0x100
// this will update checksum at eeprom[0x100 - 4]
u8 UpdateChecksum(u8 *eeprom, int length) // 801F2C84
{
   u8 cksum[4];
   int blocks = (length + 0x7F) >> 7;
   // zero out existing EEPROM checksum and local buffer
   for (int i = 0; i < 4; i++) {
      cksum[i] = 0;
      eeprom[length + i - 4] = 0;
   }
   if (blocks > 0) {
      for (int i = 0; i < blocks; i++) {
         for (int j = 0; j < 4; j++) {
            int offset = (i << 7) + (j << 5);
            if (offset < length) {
               u8 ckbyte = ComputeChecksumByte(eeprom + offset);
               cksum[j] += (ckbyte & 0xFF);
            }
         }
      }
   }
   // copy the checksum into the EEPROM data
   for (int i = 0; i < 4; i++) { // 801F2C84
      eeprom[length + i - 4] = cksum[i];
   }
   return 0;
}

The EEPROM functions are all stored in the hd_front_end_text.raw gzip file. In the (U) (1.0) ROM, these are inflated to 0x801E7000.

RAM/offset Function
801F1944/00A944 int ManageEeprom(u8 block, u8 mode)
801F2C84/00BC84 u8 UpdateChecksum(u8 *eeprom, int length)
80205760/01E760 u8 ComputeChecksumByte(u8 *data)
80202850/01B850 s32 osEepromProbe(OSMesgQueue *mq)
802042A0/01D2A0 s32 osEepromLongWrite(OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes)
802043E0/01D3E0 s32 osEepromLongRead(OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes)
80204BE0/01DBE0 s32 osEepromWrite(OSMesgQueue *mq, u8 address, u8 *buffer)
802050C0/01E0C0 s32 osEepromRead(OSMesgQueue *mq, u8 address, u8 *buffer)

Erasing EEPROM

The EEPROM can be cleared by holding the 'Start' button while the during reset and startup of the game. You will then be prompted to “Erase Saved Game”