This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
mario_kart_64:eeprom_map [2016/04/10 16:16] shygoo created |
mario_kart_64:eeprom_map [2017/06/23 10:49] (current) shygoo ↷ Links adapted because of a move operation |
||
---|---|---|---|
Line 5: | Line 5: | ||
===== Top level structure ===== | ===== Top level structure ===== | ||
^ Offset ^ Length ^ Description ^ | ^ Offset ^ Length ^ Description ^ | ||
- | | 0x000 | 24 | Luigi raceway record set | | + | | 0x000 | 24 | Luigi raceway [[#record_format|record set]] | |
| 0x018 | 24 | Moo Moo Farm record set | | | 0x018 | 24 | Moo Moo Farm record set | | ||
| 0x030 | 24 | Koopa Troopa Beach record set | | | 0x030 | 24 | Koopa Troopa Beach record set | | ||
Line 21: | Line 21: | ||
| 0x150 | 24 | Banshee Boardwalk record set | | | 0x150 | 24 | Banshee Boardwalk record set | | ||
| 0x168 | 24 | Rainbow Road record set | | | 0x168 | 24 | Rainbow Road record set | | ||
- | | 0x180 | 4 | Unknown (Unused padding?) | | + | | 0x180 | 4 | 50cc trophy information | |
+ | | 0x181 | 4 | 100cc trophy information | | ||
+ | | 0x182 | 4 | 150cc trophy information | | ||
+ | | 0x183 | 4 | Extra trophy information | | ||
| 0x184 | 1 | Audio setting | | | 0x184 | 1 | Audio setting | | ||
- | | 0x185 | 1 | Unknown (Unused padding?) | | + | | 0x185 | 1 | Unused, padding | |
- | | 0x186 | 2 | Unknown (Checksum?) | | + | | 0x186 | 2 | [[#x186|Checksum of 0x180-0x184]] | |
- | | 0x188 | 48 | Copies of all 1st records | | + | | 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?) | | | 0x1B8 | 6 | Unknown (Padding?) | | ||
- | | 0x1BE | 2 | Unknown (Checksum?) | | + | | 0x1BE | 2 | [[[#x1BE_and_0x1F6|Checksum of 0x188-0x1BD]] | |
- | | 0x1C0 | 48 | Another 16 records (What for?) | | + | | 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?) | | | 0x1F0 | 6 | Unknown (Padding?) | | ||
- | | 0x1F6 | 2 | Unknown (Checksum?) | | + | | 0x1F6 | 2 | [[#x1BE_and_0x1F6|Checksum of 0x1C0-0x1F5]] | |
| 0x1FC | 1 | Copy of audio setting (0x184) | | | 0x1FC | 1 | Copy of audio setting (0x184) | | ||
- | | 0x1FD | 1 | Copy of Unknown (Unused padding?) (0x185) | | + | | 0x1FD | 1 | Copy of Unused, padding? (0x185) | |
- | | 0x1FE | 2 | Copy of Unknown (Checksum?) (0x186) | | + | | 0x1FE | 2 | Copy of [[#x186|Checksum of 0x180-0x184]] | |
===== Course record set ===== | ===== Course record set ===== | ||
Line 45: | Line 54: | ||
| 0x00C | 3 | 5th record | | | 0x00C | 3 | 5th record | | ||
| 0x00F | 3 | Best lap record | | | 0x00F | 3 | Best lap record | | ||
- | | 0x012 | 3 | Records exist (00 or 01) | | + | | 0x012 | 1 | Records exist (00 or 01) | |
| 0x013 | 4 | Unknown (Unused?) | | | 0x013 | 4 | Unknown (Unused?) | | ||
- | | 0x017 | 1 | Unknown (Checksum?) | | + | | 0x017 | 1 | [[#record_checksum|Record Checksum]] | |
- | {{:mk64:yjuty.png?200}} | + | {{mario_kart_64:yjuty.png?200}} |
===== Record Format ===== | ===== Record Format ===== | ||
- | Record entries are 24 bits each and are formatted in the following manner: | + | Record entries are 24 bits each and are stored with little endian byte ordering: |
- | ''<color red>tttttttt tttttttt</color> <color green>cccc</color> <color red>tttt</color>'' | + | ''<color red>tttttttt tttttttt</color> <color green>cccc</color><color red>tttt</color>'' |
- | Where ''<color red>t</color>'' is a 20 bit little endian value for the completion time and ''<color green>c</color>'' is a 4 bit ID of the character used in the trial. The game seems to display the time as ''((<color red>t</color> / 6000) * 10000) + (<color red>t</color> % 6000)'' in decimal notation, with the literal digits split into minutes, seconds, and centiseconds (e.g. a <color red>t</color> value of 1234 will simply display 00'12"34 and a value of 65536 will display 10'55"36). If a record has a time greater than or equal to 100 minutes, it is not displayed. | + | Where ''<color red>t</color>'' is a 20 bit value for the completion time in centiseconds and ''<color green>c</color>'' 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 ''<color green>c</color>'' are as follows: | Valid character IDs for ''<color green>c</color>'' are as follows: | ||
- | ^ ID ^ Name ^ | + | ^ ID ^ Character ^ |
| 0 | MARIO | | | 0 | MARIO | | ||
| 1 | LUIGI | | | 1 | LUIGI | | ||
Line 69: | Line 78: | ||
| 6 | PEACH | | | 6 | PEACH | | ||
| 7 | BOWSER | | | 7 | BOWSER | | ||
- | | 8 | (none, unused) | | ||
- | | 9 | (none, default) | | ||
- | The default value applied to record entries is ''0xC02709'', which is 100 minutes and no character. | + | 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: | ||
+ | <code c> | ||
+ | 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); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== 0x186 ==== | ||
+ | 0x186 is a checksum of offsets 0x180-0x184 and is computed by procedure at 800B492C and 0x187 is computed by procedure at 800B49E4 | ||
+ | |||
+ | <code c>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</code> | ||
+ | |||
+ | ==== 0x1BE and 0x1F6 ==== | ||
+ | |||
+ | <code c> | ||
+ | // 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); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ===== References ===== | ||
+ | * http://origami64.net/showthread.php?tid=47&pid=2936#pid2936 |