data/claims/zelda-save.yamlThe Legend of Zelda's battery save (Aldo Núñez's disassembly and the US ROM)
Game: The Legend of Zelda.
The Legend of Zelda keeps three save files in battery-backed cartridge RAM; each holds an 8-byte name, a 40-byte item block, 384 bytes of world flags, and four single bytes (whether the slot is in use, one unlabeled byte, the death count, and the quest), with a 16-bit checksum that is the plain sum of those 436 bytes, and, kept apart and outside the sum, two marker bytes, $5A and $A5. zelda-save/file
About: The Legend of Zelda Password and battery save
Value
{
"files": 3,
"fields": [
{
"what": "name",
"bytes": 8
},
{
"what": "items",
"bytes": 40
},
{
"what": "world flags",
"bytes": 384
},
{
"what": "slot in use",
"bytes": 1
},
{
"what": "unlabeled",
"bytes": 1
},
{
"what": "death count",
"bytes": 1
},
{
"what": "quest number",
"bytes": 1
}
],
"check": "16-bit sum of the 436 bytes",
"markers": [
90,
165
]
}0x6-0x6 — header flags 6, $12: bit 1 set, battery-backed PRG RAM at $6000-$7FFFzelda1-disassembly: A complete disassembly of The Legend of Zelda · src/Variables.inc#L301-L323SaveRamBegin := $6001
SaveFileAName0 := $6002
…
SaveFileAItems0 := $601A
…
SaveFileAWorldFlags0 := $6092
…
SaveFileOpenMarkers := $651E
SaveFileCloseMarkers := $6521
FileAChecksums := $6524
IsSaveFileBCommitted := $652Azelda1-disassembly: A complete disassembly of The Legend of Zelda · src/Z_02.asm#L2319-L2372CalculateFileAChecksum:
…
LDY #$07 ; Sum the name (8 bytes).
…
LDY #$27 ; Add the Items block ($28 bytes) to [$0F:0E].
…
LDY #$00 ; Add World Flags ($180 bytes) to [$0F:0E].
…
LDA ($06), Y ; IsSaveSlotActive
JSR AddATo0F0E
LDA ($08), Y ; TODO: Add byte at [[$08:09]] to [$0F:0E].
JSR AddATo0F0E
…zelda1-disassembly: A complete disassembly of The Legend of Zelda · src/Z_02.asm#L2289-L2295LDA SaveFileOpenMarkers, Y ; Are the static markers intact?
CMP #$5A
BNE @FormatA
LDA SaveFileCloseMarkers, Y
CMP #$A5Checked by claude, 2026-10-22 — read CalculateFileAChecksum and the save RAM definitions at the pinned commit (bank 2 and the definitions match Rev 1, per the source record); read the Rev 1 header byteThe sum adds each byte into a 16-bit total with carry, so it catches a changed byte but not two bytes swapped. Aldo Núñez leaves the fourth single byte unnamed (a TODO). CalculateFileAChecksum reads only the name, items, world flags, and the four single bytes; the markers ($651E, $6521) and the sum itself are checked on their own.
Cited by: Password and battery save
The Legend of Zelda saves in two steps; it first writes the whole file to a second copy, file B, sums it, stores that sum, and marks B uncommitted, and on the next step it sums B again and, if the sums agree, clears file A's markers, copies B over A, writes A's markers and sum, and marks B committed. zelda-save/two-step-save
About: The Legend of Zelda Password and battery save
Codezelda1-disassembly: A complete disassembly of The Legend of Zelda ·src/Z_02.asm#L2944-L3046UpdateModeDSave_Sub0:
; Initialize file B, and copy profile to it.
; Calculate and store file B checksum.
; Mark file B uncommitted.
…
UpdateModeDSave_Sub1:
LDY CurSaveSlot
LDA IsSaveFileBCommitted, Y
BNE @IncSubmode
JSR FetchFileBAddressSet
JSR CalculateFileBChecksum
…
…zelda1-disassembly: A complete disassembly of The Legend of Zelda · src/Z_02.asm#L3048-L3140CopyFileBToFileA:
LDY CurSaveSlot
LDA #$00 ; Reset the save file markers.
STA SaveFileOpenMarkers, Y
STA SaveFileCloseMarkers, Y
…
LDA #$5A ; Write the save file markers.
…
TYA ; Copy the checksum from file B to file A.
…
LDA #$FF ; File B has been committed.
STA IsSaveFileBCommitted, Yzelda1-disassembly: A complete disassembly of The Legend of Zelda · src/Z_02.asm#L1350-L1360SaveFileBAddressSets:
.BYTE $98, $68, $10, $69, $80, $68, $90, $6Dzelda1-disassembly: A complete disassembly of The Legend of Zelda · src/Variables.inc#L325LevelBlockAttrsA := $687EChecked by claude, 2026-10-22 — read UpdateModeDSave's first two submodes and CopyFileBToFileA at the pinned commitFile B's pointers start at $6898 (items), $6910 (world flags), and $6880 (name), in battery RAM from $6880 to $6D9B; the disassembly also labels that range as level data (LevelBlockAttrsA from $687E). The commit flag, IsSaveFileBCommitted, is itself in battery RAM at $652A.
Cited by: Password and battery save
When its title demo or its file select screen starts, The Legend of Zelda checks each of the three slots; a file B still marked uncommitted whose sum matches is copied over file A, finishing a save that was cut off, and a file A whose markers are not $5A and $A5 or whose sum doesn't match is formatted, its name set to spaces and every other byte to 0. zelda-save/file-check
About: The Legend of Zelda Password and battery save
Codezelda1-disassembly: A complete disassembly of The Legend of Zelda ·src/Z_02.asm#L2252-L2316; For each save slot:
; If file B is uncommitted and valid, then
; Copy file B to file A (also marks file B committed)
; If file A's static markers are wrong or file is invalid, then
; Format file A
…
LDA FileAChecksums, Y ; Does the checksum match?
CMP $0E
BNE @FormatA
…
@FormatA:
JSR FetchFileAAddressSet
…zelda1-disassembly: A complete disassembly of The Legend of Zelda · src/Z_02.asm#L2374-L2410FormatFileA:
LDY #$07
LDA #$24 ; Make the name 8 spaces.
…
LDY #$27 ; Reset the file's Items block.
LDA #$00
…
LDY #$00 ; Reset World Flags ($180 bytes) at [$02:03].
…
STA ($06), Y ; Reset the file's IsSaveSlotActive.Checked by claude, 2026-10-22 — read UpdateMode0Demo_Sub1 and FormatFileA at the pinned commitThe routine is submode 1 of mode 0, the demo, and the init of mode 1, the file select screen. FormatFileA then writes a fresh sum and the markers, so an erased slot reads as an empty, valid file.
Cited by: Password and battery save