User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
blast_corps:eeprom_map [2016/10/14 16:35]
queueram created Blast Corps EEPROM Memory Map
blast_corps:eeprom_map [2017/06/23 10:49] (current)
shygoo ↷ Links adapted because of a move operation
Line 27: Line 27:
 | 0x100 | 0xF0 | [[#​level_times|Level Times]] | | 0x100 | 0xF0 | [[#​level_times|Level Times]] |
 | 0x1F0 | 0x8 | Language \\ 0x1982198219821982 = English \\ 0x1945194519451945 = German | | 0x1F0 | 0x8 | Language \\ 0x1982198219821982 = English \\ 0x1945194519451945 = German |
-| 0x1F8 | 0x8 | Footer |+| 0x1F8 | 0x8 | Footer ​\\ 0x2704197125121981 = Before saving rest of EEPROM data \\ 0x87569AB6CD076AEC = After saving rest of EEPROM data |
  
 ===== Level Times ===== ===== Level Times =====
-There is a time recorded ​for each level as an 4-byte unsigned ​integer in big endian in units of 1/​655360 ​of a second. To convert these values to seconds, divide the value by 655360. e.g., if the value is 0x00E4554E = 14964046, ​then 14964046/​655360 ​= 22.8 seconds. +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 checksumThe checksum is computed as follows (where ^ is XOR): 
 +<code c>​record[2] = 0x55 ^ record[0];​ 
 +record[3] = 0xFF ^ record[0] ^ record[1] ^ record[2];</​code>​ 
 +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 ===== ===== 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. 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.
  
-<code c>u8 ComputeChecksumByte(u8 *data) // 80205760+<code c> 
 +// helper function for checksum update routine below 
 +static ​u8 ComputeChecksumByte(u8 *data) // 80205760
 { {
    u8 cksum = 0;    u8 cksum = 0;
    u8 key;    u8 key;
-   for (int i = 0; i < 33; i++) { // 80205760 +   for (int i = 0; i < 33; i++) { 
-      for (int j = 7; j >= 0; j--) { // 80205760+      for (int j = 7; j >= 0; j--) {
          if (cksum & 0x80) {          if (cksum & 0x80) {
             key = 0x85;             key = 0x85;
Line 49: Line 53:
          if (i == 0x20) {          if (i == 0x20) {
             cksum = cksum & 0xFF;             cksum = cksum & 0xFF;
-         } else { // 80205760+         } else {
             u8 mask = data[i] & (1 << j);             u8 mask = data[i] & (1 << j);
             u8 bit = mask ? 1 : 0;             u8 bit = mask ? 1 : 0;
Line 60: Line 64:
 } }
  
 +// 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 UpdateChecksum(u8 *eeprom, int length) // 801F2C84
 { {
-   ​u8 ​buf[4]; // sp28-sp2B+   ​u8 ​cksum[4];
    int blocks = (length + 0x7F) >> 7;    int blocks = (length + 0x7F) >> 7;
    // zero out existing EEPROM checksum and local buffer    // zero out existing EEPROM checksum and local buffer
-   for (int i = 0; i < 4; i++) { // .Lproc_801F2C84_28:​ 801F2CAC +   for (int i = 0; i < 4; i++) { 
-      ​buf[i] = 0; +      ​cksum[i] = 0; 
-      eeprom[length + i - 4] = buf[i]+      eeprom[length + i - 4] = 0
-   ​} ​// 801F2CE8+   }
    if (blocks > 0) {    if (blocks > 0) {
-      for (int i = 0; i < blocks; i++) { //​.Lproc_801F2C84_78:​ +      for (int i = 0; i < blocks; i++) { 
-         for (int j = 0; j < 4; j++) { //​.Lproc_801F2C84_7C:​+         for (int j = 0; j < 4; j++) {
             int offset = (i << 7) + (j << 5);             int offset = (i << 7) + (j << 5);
             if (offset < length) {             if (offset < length) {
-               ​u8 ​cksum = ComputeChecksumByte(eeprom + offset); +               ​u8 ​ckbyte ​= ComputeChecksumByte(eeprom + offset); 
-               buf[j] += (cksum & 0xFF);+               cksum[j] += (ckbyte ​& 0xFF);
             }             }
          }          }
Line 81: Line 87:
    }    }
    // copy the checksum into the EEPROM data    // copy the checksum into the EEPROM data
-   for (int i = 0; i < 4; i++) { // .Lproc_801F2C84_F8:​ +   for (int i = 0; i < 4; i++) { // 801F2C84 
-      eeprom[length + i - 4] = buf[i];+      eeprom[length + i - 4] = cksum[i];
    }    }
    ​return 0;    ​return 0;
Line 102: Line 108:
 ===== Erasing EEPROM ===== ===== 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" 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"
-{{:bc:​erase_saved_game.png?​direct&​200 |}}+{{blast_corps:​erase_saved_game.png?​direct&​200 |}}