The current URL is datacrystal.tcrf.net.
EarthBound/SRAM map: Difference between revisions
m (Add anchor) |
m (Byte count for user data sections was incorrect by 1. Was 0x04df when it should have been 0x04e0. Actual offsets appear to be correct.) |
||
Line 5: | Line 5: | ||
* <tt>001c-001d (0002)</tt>: Save 1A Checksum 1 | * <tt>001c-001d (0002)</tt>: Save 1A Checksum 1 | ||
* <tt>001e-001f (0002)</tt>: Save 1A Checksum 2 | * <tt>001e-001f (0002)</tt>: Save 1A Checksum 2 | ||
* <tt>0020-04ff ( | * <tt>0020-04ff (04e0)</tt>: Save 1A Data | ||
* <tt>0500-0513 (0014)</tt>: Save 1B Signature | * <tt>0500-0513 (0014)</tt>: Save 1B Signature | ||
* <tt>0514-051b (0008)</tt>: '''Unused''' | * <tt>0514-051b (0008)</tt>: '''Unused''' | ||
* <tt>051c-051d (0002)</tt>: Save 1B Checksum 1 | * <tt>051c-051d (0002)</tt>: Save 1B Checksum 1 | ||
* <tt>051e-051f (0002)</tt>: Save 1B Checksum 2 | * <tt>051e-051f (0002)</tt>: Save 1B Checksum 2 | ||
* <tt>0520-09ff ( | * <tt>0520-09ff (04e0)</tt>: Save 1B Data | ||
* <tt>0a00-0a13 (0014)</tt>: Save 2A Signature | * <tt>0a00-0a13 (0014)</tt>: Save 2A Signature | ||
* <tt>0a14-0a1b (0008)</tt>: '''Unused''' | * <tt>0a14-0a1b (0008)</tt>: '''Unused''' | ||
* <tt>0a1c-0a1d (0002)</tt>: Save 2A Checksum 1 | * <tt>0a1c-0a1d (0002)</tt>: Save 2A Checksum 1 | ||
* <tt>0a1e-0a1f (0002)</tt>: Save 2A Checksum 2 | * <tt>0a1e-0a1f (0002)</tt>: Save 2A Checksum 2 | ||
* <tt>0a20-0eff ( | * <tt>0a20-0eff (04e0)</tt>: Save 2A Data | ||
* <tt>0f00-0f13 (0014)</tt>: Save 2B Signature | * <tt>0f00-0f13 (0014)</tt>: Save 2B Signature | ||
* <tt>0f14-0f1b (0008)</tt>: '''Unused''' | * <tt>0f14-0f1b (0008)</tt>: '''Unused''' | ||
* <tt>0f1c-0f1d (0002)</tt>: Save 2B Checksum 1 | * <tt>0f1c-0f1d (0002)</tt>: Save 2B Checksum 1 | ||
* <tt>0f1e-0f1f (0002)</tt>: Save 2B Checksum 2 | * <tt>0f1e-0f1f (0002)</tt>: Save 2B Checksum 2 | ||
* <tt>0f20-12ff ( | * <tt>0f20-12ff (04e0)</tt>: Save 2B Data | ||
* <tt>1300-1313 (0014)</tt>: Save 3A Signature | * <tt>1300-1313 (0014)</tt>: Save 3A Signature | ||
* <tt>1314-131b (0008)</tt>: '''Unused''' | * <tt>1314-131b (0008)</tt>: '''Unused''' | ||
* <tt>131c-131d (0002)</tt>: Save 3A Checksum 1 | * <tt>131c-131d (0002)</tt>: Save 3A Checksum 1 | ||
* <tt>131e-131f (0002)</tt>: Save 3A Checksum 2 | * <tt>131e-131f (0002)</tt>: Save 3A Checksum 2 | ||
* <tt>1320-17ff ( | * <tt>1320-17ff (04e0)</tt>: Save 3A Data | ||
* <tt>1800-1813 (0014)</tt>: Save 3B Signature | * <tt>1800-1813 (0014)</tt>: Save 3B Signature | ||
* <tt>1814-181b (0008)</tt>: '''Unused''' | * <tt>1814-181b (0008)</tt>: '''Unused''' | ||
* <tt>181c-181d (0002)</tt>: Save 3B Checksum 1 | * <tt>181c-181d (0002)</tt>: Save 3B Checksum 1 | ||
* <tt>181e-181f (0002)</tt>: Save 3B Checksum 2 | * <tt>181e-181f (0002)</tt>: Save 3B Checksum 2 | ||
* <tt>1820-1cff ( | * <tt>1820-1cff (04e0)</tt>: Save 3B Data | ||
* <tt>1d00-1fef (02f0)</tt>: '''Unused''' | * <tt>1d00-1fef (02f0)</tt>: '''Unused''' | ||
* <tt>1ff0-1ff0 (0001)</tt>: [[#AntiPiracyCheckByte|Anti-Piracy Check Byte]] | * <tt>1ff0-1ff0 (0001)</tt>: [[#AntiPiracyCheckByte|Anti-Piracy Check Byte]] |
Latest revision as of 19:41, 15 December 2024
The following article is an SRAM map for EarthBound.
- 0000-0013 (0014): Save 1A Signature
- 0014-001b (0008): Unused
- 001c-001d (0002): Save 1A Checksum 1
- 001e-001f (0002): Save 1A Checksum 2
- 0020-04ff (04e0): Save 1A Data
- 0500-0513 (0014): Save 1B Signature
- 0514-051b (0008): Unused
- 051c-051d (0002): Save 1B Checksum 1
- 051e-051f (0002): Save 1B Checksum 2
- 0520-09ff (04e0): Save 1B Data
- 0a00-0a13 (0014): Save 2A Signature
- 0a14-0a1b (0008): Unused
- 0a1c-0a1d (0002): Save 2A Checksum 1
- 0a1e-0a1f (0002): Save 2A Checksum 2
- 0a20-0eff (04e0): Save 2A Data
- 0f00-0f13 (0014): Save 2B Signature
- 0f14-0f1b (0008): Unused
- 0f1c-0f1d (0002): Save 2B Checksum 1
- 0f1e-0f1f (0002): Save 2B Checksum 2
- 0f20-12ff (04e0): Save 2B Data
- 1300-1313 (0014): Save 3A Signature
- 1314-131b (0008): Unused
- 131c-131d (0002): Save 3A Checksum 1
- 131e-131f (0002): Save 3A Checksum 2
- 1320-17ff (04e0): Save 3A Data
- 1800-1813 (0014): Save 3B Signature
- 1814-181b (0008): Unused
- 181c-181d (0002): Save 3B Checksum 1
- 181e-181f (0002): Save 3B Checksum 2
- 1820-1cff (04e0): Save 3B Data
- 1d00-1fef (02f0): Unused
- 1ff0-1ff0 (0001): Anti-Piracy Check Byte
- 1ff1-1ffd (000d): Unused
- 1ffe-1fff (0002): Version
Save Format
EarthBound SRAM contains 3 save files or slots, corresponding with the 3 save games from the main menu. The data of a save file is a copy of the WRAM Persistent Data in the same order and format. For redundancy, each save file is repeated in two separate exact-mirror copies.
Data Integrity
EarthBound employs multiple mechanisms to validate and fix save files against data corruption:
- A version number (
0x0493
for US-release ROMs) is stored at 1ffe-1fff, and on game startup, all 8KB of SRAM is erased/reset if the version number does not match the expectation hard coded in the ROM. This is assumed to primarily be a development compatibility mechanism to ensure incompatible saves with different formats from earlier builds of the game cannot be accidentally loaded, but the mechanism has a secondary role in detecting corruption if the version number somehow changes in SRAM. - The first 20 bytes of each 0x500 block of SRAM is set to a known signature ("HAL Laboratory, inc." in ascii). On game startup, all 6 signatures are validated against the expectation hard coded in the ROM. If any signature does not match the expectation, the respective 0x500 block of SRAM is erased and the signature is rewritten.
- Each 0x500 block of SRAM contains 2 checksum values of the block's respective data section, one derived from adding together all data bytes, and the other from XORing all the data.
On game startup, checksums are recalculated for all 6 SRAM blocks, and if the newly calculated checksums do not match the saved checksums for any SRAM block, the respective 0x500 block of SRAM is erased and the signature is rewritten. For every 2 blocks redundantly storing the same save file, if only 1 block is reset, the entire 0x500 good block (including signature and checksums) is copied over the bad block. If both blocks are invalid and reset, an error message is displayed to the user in the main save-selection menu.
On game save, when data is saved to a 0x500 block of SRAM, checksums for the block are calculated and written to that block. Then the checksums are calculated again, and if either checksum does not match the value saved in the block, the entire save block process starts over.
Anti Piracy Check Byte
Byte 1ff0 is used to implement the infamous EarthBound copy protection. EarthBound first writes 30
to this byte via CPU address $307ff0, then writes 31
to this byte via CPU address $317ff0, and then checks that the first CPU address ($307ff0) matches the expected 31
. In a normal EarthBound cartridge with 8KB of SRAM, the SNES is expected to map both addresses to the same SRAM byte 1ff0. If the game is being run with 16KB or more of SRAM (as would often be the case with pirated games of the era), the SNES would map the two addresses to separate bytes in SRAM (1ff0 and 3ff0), and the second write would not overwrite the first.