The Legend of Zelda
Nintendo's 1986 action-adventure, read through Aldo Núñez's disassembly and measured in the US Rev 1 ROM.
On this page
The Legend of Zelda is Nintendo’s 1986 action-adventure; its NES release reached North America in August 19871. Aldo Núñez’s disassembly labels and comments the whole US release. He built it from the first revision, PRG0. The ROM measured here is Rev 1, and its combat and drop code is byte-identical to his source2.
#Hearts and damage
Link’s health is a count of full hearts plus a partial heart, a byte from $00 to $FF; a new file starts with 3 hearts3,3. A monster’s contact damage comes from a table with one byte per object type. Half a heart is the most common entry, and Ganon’s four hearts tie for the largest4,5. Each level of ring halves the damage before it is subtracted6.
When the partial heart can’t cover a hit, the game takes a full heart and refills the partial heart to $FF rather than $100. Each such borrow costs an extra 1/256 of a heart7. In the probe, five half-heart hits from three hearts leave a partial heart of $7D, not $808.
#Invincibility after a hit
A hit sets Link’s invincibility timer to 24 and his shove distance to 32 px, and no monster can touch him while the timer is above 09. The timer drops by 1 only on even frames, so 24 lasts 48 frames10. The comment beside it reads “Mark Link invincible $18 frames”, counting timer steps as frames9.
The probe holds a Tektite against Link from power-on. It hurts him every 47 or 48 frames8, depending on whether the hit falls on an odd or even frame8. The timer reaches 0 before the monsters’ contact checks run, so a monster still touching Link hurts him on that same frame8.
While Link holds the clock, the game adds 16 to the timer every frame, and monsters’ contact checks return no collision11.
#The shove
A shove moves Link 4 px/frame12, one pixel of shove distance at a time12. It points away from the monster13. It stops early at the room’s edge, or at an unwalkable tile when Link is aligned to the grid12. While it lasts, it replaces his walking, so the player can’t steer14. The monster then turns around, unless it is a Vire or carries the attribute bit that the disassembly’s comments call “reverse after hit Link”13.
In the probe, three hits shove Link 32 px in 8 frames15 each. The fourth hit lands 8 px from the room’s edge, and the shove covers only those 8 px15.
#Hitting monsters
The wooden, white, and magical swords take $10, $20, and $40 from a monster’s hit points. Fire takes $10 and a bomb $40; the boomerang only stuns16. A monster that a weapon hurts gets the same treatment as Link with different numbers. Its timer is set to 16, which lasts 32 frames, and it is shoved 64 px in the weapon’s direction17. A monster immune to the weapon’s damage type is neither hurt nor shoved17.
#Item drops
When a monster dies, SetUpDroppedItem chooses its drop by a table, a counter, and a chance18,19,20. The monster’s type puts it in one of four groups; seven types, among them the Gels, the Keese, and the Like Like, never drop anything18. Every kill advances a kill cycle from 0 to 9 and back, before the drop is chosen21. Three types don’t advance it, among them the ones the comments call Child Gel and Red Keese21.
The group picks a row of the table and the kill cycle its column19. The drop then happens only when the monster’s slot’s byte of Random is below the group’s rate20:
| Group | Types | Rate | Row, columns 0–9 |
|---|---|---|---|
| A | $07 $08 Octoroks, $0E Tektite, $04 Moblin, $0F Leever, $23 Wizzrobe18,5 | 80 in 25620 | heart, rupee, heart, rupee, fairy, rupee, heart, heart, rupee, rupee19 |
| B | $21 $22 Ghinis, $0D Tektite, $10 Leever, $13 Zol, $28 Rope, $2A Stalfos, $27 Wallmaster, $16 Pols Voice18,5 | 152 in 25620 | 5 rupees, rupee, heart, rupee, 5 rupees, heart, clock, rupee, rupee, rupee19 |
| C | $09 $0A Octoroks, $03 Moblin, $01 Lynel, $12 Vire, $06 Goriya, $0B Darknut, $24 Wizzrobe, $30 Gibdo18,5 | 104 in 25620 | heart, bombs, rupee, clock, rupee, heart, bombs, rupee, bombs, heart19 |
| D | every other type that drops, such as $05 Goriya and $0C Darknut18,5 | 104 in 25620 | heart, heart, fairy, rupee, heart, fairy, heart, heart, heart, rupee19 |
Two counters override the table. Both count kills since Link was last hurt, and a hit zeroes them22. The 16th such kill drops a fairy, if the monster can drop at all23. The 10th drops 5 rupees, or bombs when the 10th kill was by bomb, and its count starts again24. A fairy restores 3 hearts and a heart 125. A dropped item lasts about 510 frames, and Link can’t take it for the first 30 or so26.
The probe calls the game’s own routine for every group, kill-cycle column, and random byte. It drops in 800, 1,520, 1,040, and 1,040 of 2,56027 cases for groups A to D, each time the item in its column27. The Speed Demos Archive Knowledge Base gives the same 10th-kill and 16th-kill rules28.
on a kill (the death sparkle has ended):
kill_cycle = (kill_cycle + 1) mod 10 # not for split Gels and Keese
if type never drops: done
item = TABLE[group][kill_cycle]
if kills_since_hurt == 16: item = fairy; help_count = 0
elif help_count >= 10: item = bombs if the 10th was by bomb else 5 rupees; help_count = 0
elif Random[slot] >= RATE[group]: no drop
#Health growth
A heart container adds a container and a full heart, up to 16 containers29. A new file has three3.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Status bar split | Sprite 0 hit | waits for sprite 0 under the map and item bar; scrolls vertically between rooms by rewriting PPUADDR mid-frame |
| Raster effects | Two bands | a PPUADDR rewrite at the split gives the room below its own vertical position |
| Music driver | Length table | Super Mario Bros.' layout: per-song length rows, big-endian periods |
| DPCM samples | Sound effects | 7 samples for boss roars, a boss hit, and a hurt sound |
| Invincibility frames | Slow timer | 24 on a timer that counts down every other frame |
| Knockback | Fixed shove | a fixed 32 px shove at 4 px per frame |
| Item drop table | Kill cycle | four groups, a 10-step kill cycle, and streak bonuses |
| Damage formula | Fixed table | a damage byte per monster type, halved per ring |
| Health upgrade | Whole containers | heart containers only, three to sixteen |
| Sword beam | Near full | any sword, with up to half a heart missing |
| Keys and locked doors | One count | one key per locked door, or none with the magic key |
| Password and battery save | Battery save with copies | three files with a 16-bit sum and marker bytes; each save goes to a scratch copy first |
Every claim about this game, by concept (39)
References
- ^Wikidata lists Nintendo and Nintendo Entertainment Analysis & Development as the developers of The Legend of Zelda and Nintendo as its publisher; it dates the game 21 February 1986, with no place or platform, and its NES release in North America 22 August 1987.WikidataWikidata
How we know
+1986-02-21T00:00:00Z … +1987-11-15T00:00:00Z … +1987-08-22T00:00:00Z
Q12395, P178 developer, P123 publisher, and P577 publication date qualified by P291 place and P400 platform · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-21.
- ^The PRG0 source of aldonunez's disassembly differs from Rev 1 in the music engine, in bank 5's continue screen and room code, which Rev 1 moves, in bank 7's calls into that code, and in the header checksum; the combat code in banks 1 and 7 and the drop code in bank 4 are byte-identical.Code“Legend of Zelda, The (USA) (Rev 1)” · aldonunez/zelda1-disassembly
How we know
In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1 BeginShove, run from RAM at $7E26, one of the routines identical in both. We don't reproduce the bytes.
6016; Unknown block 6017 .BYTE $5A, $45, $4C, $44, $41, $D7, $C8, $00 6018 .BYTE $00, $38, $04, $01, $04, $01, $BE
src/Z_07.asm lines 6016–6018 at 50a1c86 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abcLink's health is
HeartValues, whose high nibble is the heart containers less one and whose low nibble is the full hearts, plus a partial heart inHeartPartialfrom$00to$FF; a new file starts at$22and$FF, three containers and three hearts.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
1667 ; Initialize file B hearts value to 3 heart containers and 2 hearts. 1668 LDY #$18 1669 LDA #$22 1670 STA ($C0), Y 1671 INY ; Initialize file B heart partial to full. 1672 LDA #$FF
src/Z_02.asm lines 1667–1672 at 50a1c86 · upstream ↗ 4681CompareHeartsToContainers: 4682 LDA HeartValues ⋮ 4684 AND #$0F ⋮ 4687 LSR 4688 LSR 4689 LSR 4690 LSR 4691 CMP $00
src/Z_01.asm lines 4681–4691 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 2 $9EF0, UpdateModeERegister, which writes the new file. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^A monster's contact damage comes from
ObjTypeToDamagePoints, one byte per object type, whose low nibble is whole hearts and whose high nibble is sixteenths of a heart; of its 93 entries, 30 are half a heart, 24 one heart, 18 two hearts, and 3 four hearts.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
5574ObjTypeToDamagePoints: 5575 .BYTE $60, $02, $01, $80, $80, $01, $80, $80 5576 .BYTE $80, $80, $80, $01, $02, $80, $80, $01
src/Z_01.asm lines 5574–5586 at 50a1c86 · upstream ↗ 5725 ; Unpack the damage points for the monster's type. 5726 ; The low nibble is the high byte. 5727 ; (Damage points byte AND $F0) is the low byte. 5728 LDY ObjType, X 5729 LDA ObjTypeToDamagePoints, Y 5730 PHA 5731 AND #$0F 5732 STA $0D 5733 PLA 5734 AND #$F0 5735 STA $0E
src/Z_01.asm lines 5725–5735 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1, the table, run from RAM at $7A4A. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Checked by a second AI model, 2026-10-25.
- ^ abcdeAn object's type indexes
UpdateObject_JumpTable, whose routines name the monsters: Lynel$01, Moblin$03–$04, Goriya$05–$06, Octorok$07–$0A, Darknut$0B–$0C, Tektite$0D–$0E, Leever$0F–$10, Vire$12, Zol$13, Gel$14–$15, Pols Voice$16, Like Like$17, Keese$1B–$1D, Ghini$21–$22, Wizzrobe$23–$24, Wallmaster$27, Rope$28, Stalfos$2A, Gibdo$30, and Ganon$3E.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
5322 .ADDR DoNothing 5323 .ADDR UpdateLynel 5324 .ADDR UpdateLynel 5325 .ADDR UpdateMoblin 5326 .ADDR UpdateMoblin ⋮ 5329 .ADDR UpdateOctorock 5330 .ADDR UpdateOctorock 5331 .ADDR UpdateOctorock 5332 .ADDR UpdateOctorock ⋮ 5342 .ADDR UpdateGel 5343 .ADDR UpdateGel ⋮ 5347 .ADDR DoNothing ⋮
src/Z_07.asm lines 5321–5384 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 7 $FBB4, the jump table. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^Each level of ring halves the damage before it is subtracted, so the first ring takes half and the second a quarter.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”
How we know
5750 ; For every level of ring (1 or 2), divide the 16-bit damage amount in [0E:0D] by 2. 5751 LDY InvRing 5752 BEQ @ResetHelp ⋮ 5754 LSR $0D 5755 ROR $0E 5756 DEY 5757 BNE :-
src/Z_01.asm lines 5750–5757 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1 CheckLinkCollision through Link_BeHarmed, run from RAM at $7AA7. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^When the partial heart can't cover the damage, the game takes a full heart and refills the partial heart to
$FFrather than$100, so each such borrow costs Link an extra 1/256 of a heart.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
5789@BorrowHeart: 5790 ; This isn't a simple case of borrowing. For example, supposing: 5791 ; full heart=4 partial heart=$70 5792 ; The straightforward way to subtract $80 would yield $3F0. 5793 ; But the method here yields $3EF, because partial heart is 5794 ; considered full when = $FF instead of $100. ⋮ 5802 DEC HeartValues 5803 LDA #$FF 5804 STA HeartPartial
src/Z_01.asm lines 5789–5805 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1, as in ring. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abcdMeasured in Rev 1, a Tektite held against Link hurts him every 47 or 48 frames, taking half a heart each time; from three hearts, five hits leave
$20and$7D, 3/256 of a heart under a half heart.Verified“Legend of Zelda, The (USA) (Rev 1)” · aldonunez/zelda1-disassemblyHow we know
In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1, the contact check and damage the probe exercises. We don't reproduce the bytes.
5769 LDA HeartPartial 5770 CMP $0E 5771 BCC @BorrowHeart 5772 SEC 5773 SBC $0E 5774 STA HeartPartial ⋮ 5784 SEC ⋮ 5796 SEC ⋮ 5802 DEC HeartValues 5803 LDA #$FF 5804 STA HeartPartial ⋮ 5817 STA HeartPartial
src/Z_01.asm lines 5600–5822 at 50a1c86 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on Legend of Zelda, The (USA) (Rev 1) (SHA-1
4671517d72d0…). It fails if the result disagrees with the claim.The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Checked by a second AI model, 2026-10-25.
- ^ abA monster that touches Link while his invincibility timer is above 0 does nothing; a hit sets the timer to 24 and his shove distance to 32 px.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”
How we know
5610 ; If Link is invincible, or we have the magic clock, 5611 ; or Link is stunned, or the monster is stunned; 5612 ; then return no collision. 5613 LDA ObjInvincibilityTimer 5614 ORA InvClock 5615 ORA ObjStunTimer 5616 ORA ObjStunTimer, X 5617 BNE L73A9_Exit
src/Z_01.asm lines 5610–5617 at 50a1c86 · upstream ↗ 6589 ; If Link is invincible, return without shoving. 6590 LDA ObjInvincibilityTimer 6591 BNE @Exit ⋮ 6601 ; Mark Link invincible $18 frames, and should move $20 pixels. 6602 LDA #$18 6603 STA ObjInvincibilityTimer 6604 LDA #$20 6605 STA ObjShoveDistance
src/Z_01.asm lines 6589–6605 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1 BeginShove, run from RAM at $7E26. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^
DecrementInvincibilityTimerlowers an object's invincibility timer by 1 only on frames whenFrameCounteris even, so a timer of lasts frames.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
5782DecrementInvincibilityTimer: 5783 LDA ObjInvincibilityTimer, X 5784 BEQ @Exit ; If the timer is already zero, then return. 5785 LDA FrameCounter ; Every two frames, decrease the timer. 5786 LSR 5787 BCS @Exit 5788 DEC ObjInvincibilityTimer, X
src/Z_07.asm lines 5782–5788 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 7 $FE98. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^While Link holds the clock,
BeginUpdateWorldadds 16 to his invincibility timer every frame, and monsters' contact checks return no collision.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
1876BeginUpdateWorld: 1877 ; If we have the clock, then 1878 ; force the player's invincibility. 1879 LDA InvClock 1880 BEQ @NotInvincible 1881 LDA ObjInvincibilityTimer 1882 CLC 1883 ADC #$10 1884 STA ObjInvincibilityTimer
src/Z_07.asm lines 1876–1884 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 7 $EC7A, these lines only; BeginUpdateWorld differs in Rev 1 further on. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abcA shoved object moves 4 px a frame, 1 px of shove distance at a time, and the shove ends early when the object reaches the room's edge or, aligned to the grid, an unwalkable tile.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”
How we know
2397ShoveMoveMin: 2398 ; Try to move 4 pixels. [03] is the counter. 2399 LDA #$04 2400 STA $03 ⋮ 2411 JSR GetCollidingTileMoving 2412 CMP ObjectFirstUnwalkableTile 2413 BCS ResetShoveInfo ⋮ 2416 ; Regardless of the grid offset, if the object runs into the 2417 ; bounds of the room, then stop shoving.
src/Z_07.asm lines 2397–2420 at 50a1c86 · upstream ↗ 2450 ; We're OK to change the position. So, decrease the distance 2451 ; that's left to move. 2452 DEC ObjShoveDistance, X
src/Z_07.asm lines 2450–2452 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 7 Obj_Shove and ShoveMoveMin, $EEB8. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abWhen a monster hits Link, the shove points away from the monster along one axis: the horizontal one when Link is between grid squares and faces left or right, the vertical one when he is between squares facing up or down. The monster then turns around, unless bit 7 of its object attributes is set (a flag the disassembly's comments name "reverse after hit Link") or it is a Vire (object type
$12).Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
6528 LDA #$08 6529 STA $08 6530 LDA ObjY, X 6531 STA $04 6532 LDA a:ObjY, Y 6533 STA $05 ⋮ 6538 CPY #$00 6539 BNE :+ 6540 LDA ObjGridOffset 6541 BEQ :+ 6542 LDA ObjDir 6543 AND #$03 ⋮
src/Z_01.asm lines 6528–6581 at 50a1c86 · upstream ↗ 6597 LDA $08 6598 ORA #$80 6599 STA ObjShoveDir
src/Z_01.asm lines 6597–6599 at 50a1c86 · upstream ↗ 6614 ; If the monster's object attribute "reverse after hit Link" is set, 6615 ; then return. 6616 LDA ObjAttr, X 6617 AND #$80 6618 BNE @Exit ⋮ 6621 LDA ObjType, X 6622 CMP #$12 6623 BEQ @Exit ⋮ 6626 LDA ObjDir, X 6627 JSR GetOppositeDir 6628 STA ObjDir, X
src/Z_01.asm lines 6612–6628 at 50a1c86 · upstream ↗ 5321UpdateObject_JumpTable: 5322 .ADDR DoNothing ⋮ 5340 .ADDR UpdateVire
src/Z_07.asm lines 5321–5340 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1 BeginShove. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Checked by a second AI model, 2026-10-25.
- ^
Walker_Movemoves a walking object by its shove whenever one is set, in place of its walking, so Link can't steer during a shove.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
2600Walker_Move: 2601 ; If the object is being shoved, then go shove it. 2602 LDA ObjShoveDir, X 2603 BEQ @ChooseObjDirOrInputDir 2604 JMP Obj_Shove
src/Z_07.asm lines 2600–2604 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 7 $EFD0. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abMeasured in Rev 1, each of the Tektite's first three hits shoves Link 32 px to the right in 8 frames.Verified“Legend of Zelda, The (USA) (Rev 1)” · aldonunez/zelda1-disassemblyrevised
How we know
In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 7 Obj_Shove and ShoveMoveMin, which move Link in the probe. We don't reproduce the bytes.
2348 LDA ObjGridOffset, X ⋮ 2397ShoveMoveMin: ⋮ 2399 LDA #$04 2400 STA $03 ⋮ 2405 LDA ObjGridOffset, X ⋮ 2452 DEC ObjShoveDistance, X ⋮ 2455 LDA ObjGridOffset, X 2456 CLC 2457 ADC $02 2458 STA ObjGridOffset, X ⋮ 2470 STA ObjGridOffset, X
src/Z_07.asm lines 2323–2470 at 50a1c86 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on Legend of Zelda, The (USA) (Rev 1) (SHA-1
4671517d72d0…). It fails if the result disagrees with the claim.The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-25.
- ^The wooden, white, and magical swords take
$10,$20, and$40from a monster's hit points; fire takes$10, a bomb$40, and the boomerang none, only stunning.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
6162SwordDamagePoints: 6163 .BYTE $10, $20, $40
src/Z_01.asm lines 6162–6163 at 50a1c86 · upstream ↗ 6111 ; Set up parameters for a fire. ⋮ 6114 LDA #$10 6115 STA $07 ; [07] holds $10 damage points ⋮ 6127 ; Else set up parameters for a bomb. ⋮ 6130 LDA #$40 6131 STA $07 ; [07] holds $40 damage points
src/Z_01.asm lines 6111–6131 at 50a1c86 · upstream ↗ 5914 ; Still the boomerang. 5915 ; Reset [07] damage points, and set the monster's stun timer to $10 ($A0 frames). 5916 LDA #$00 5917 STA $07 5918 LDA #$10 5919 STA ObjStunTimer, X
src/Z_01.asm lines 5914–5919 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1 CheckMonsterBombOrFireCollision through CheckMonsterSwordCollision. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Checked by a second AI model, 2026-10-25.
- ^ abA weapon that hurts a monster sets the monster's invincibility timer to 16, which lasts 32 frames, and shoves it 64 px in the weapon's direction, unless the monster is already invincible or immune to the weapon's damage type.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”
How we know
6503BeginShove: 6504 ; If a weapon attacks a monster, and the weapon's damage 6505 ; type matches the monster's invincibility mask; 6506 ; then return without shoving.
src/Z_01.asm lines 6503–6514 at 50a1c86 · upstream ↗ 6636 ; Set the shove direction to the weapon's direction, ⋮ 6653 ; If the monster is invincible, then return without shoving. 6654 LDA ObjInvincibilityTimer, X 6655 BNE @Exit2 ⋮ 6671 BNE @Exit2 ⋮ 6676 BNE @Exit2 ⋮ 6687 ; Mark the monster invincible $10 frames, and should move $40 pixels. 6688 LDA #$40 6689 STA ObjShoveDistance, X 6690 LDA #$10 6691 STA ObjInvincibilityTimer, X
src/Z_01.asm lines 6636–6691 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1 BeginShove. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abcdef
SetUpDroppedItemsorts a dead monster's type into one of four drop groups by three type lists, with every unlisted type in the fourth; seven types, among them the Gels, the Keese, and the Like Like, drop nothing.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
11030; Types of objects that do not drop items. ⋮ 11032NoDropMonsterTypes: 11033 .BYTE $5D, $14, $15, $1B, $1C, $1D, $17 ⋮ 11035DropItemMonsterTypes0: 11036 .BYTE $07, $08, $0E, $04, $0F, $23 ⋮ 11038DropItemMonsterTypes1: 11039 .BYTE $21, $22, $0D, $10, $13, $28, $2A, $27 11040 .BYTE $16 ⋮ 11042DropItemMonsterTypes2: 11043 .BYTE $09, $0A, $03, $01, $12, $06, $0B, $24 11044 .BYTE $30
src/Z_04.asm lines 11030–11044 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 4 $B01B, the lists, tables, and SetUpDroppedItem. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abcdef
DropItemTableholds ten items for each group, and the kill cycle picks the column; group A's row is heart, rupee, heart, rupee, fairy, rupee, heart, heart, rupee, rupee.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
11057; ID's for items dropped by monsters. 11058; WorldKillCycle addresses the column. ⋮ 11060; Monsters are arranged in groups that determine the row. 11061; There are four rows. ⋮ 11063DropItemTable: 11064 .BYTE $22, $18, $22, $18, $23, $18, $22, $22 11065 .BYTE $18, $18, $0F, $18, $22, $18, $0F, $22 11066 .BYTE $21, $18, $18, $18, $22, $00, $18, $21 11067 .BYTE $18, $22, $00, $18, $00, $22, $22, $22 11068 .BYTE $23, $18, $22, $23, $22, $22, $22, $18
src/Z_04.asm lines 11057–11068 at 50a1c86 · upstream ↗ 11137 LDY $01 11138 LDA DropItemSetBaseOffsets, Y 11139 CLC 11140 ADC WorldKillCycle 11141 TAY 11142 LDA DropItemTable, Y 11143 STA $00 ; [00] Dropped item ID
src/Z_04.asm lines 11137–11143 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 4, as in drop-groups. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abcdefOutside the special cases, a drop happens only when the dead monster's slot's byte of
Randomis below its group's rate:$50,$98,$68, and$68, or 80, 152, 104, and 104 in 256.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
11051; Top drop an item, a random value must be less than the 11052; element for the monster group. ⋮ 11054DropItemRates: 11055 .BYTE $50, $98, $68, $68
src/Z_04.asm lines 11051–11055 at 50a1c86 · upstream ↗ 11176@RandomlyCancel: 11177 ; If the random value >= drop item rate for the monster's group, 11178 ; then go destroy the monster. 11179 LDY $01 11180 LDA Random, X 11181 CMP DropItemRates, Y 11182 BCS @DestroyMonster
src/Z_04.asm lines 11176–11182 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 4, as in drop-groups. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abEach kill advances
WorldKillCyclefrom 0 to 9 and back to 0 before the drop is chosen, except kills of types$5D,$14, and$1C, which the comments call a Child Gel and a Red Keese.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
5457 ; Certain objects don't advance the world kill cycle. 5458 CMP #$5D 5459 BEQ @DropItem 5460 CMP #$14 ; Child Gel 5461 BEQ @DropItem 5462 CMP #$1C ; Red Keese 5463 BEQ @DropItem ⋮ 5465 ; Advance the world kill cycle (0 to 9). 5466 LDA WorldKillCycle 5467 CLC 5468 ADC #$01 5469 CMP #$0A ⋮
src/Z_07.asm lines 5457–5488 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 7 UpdateMetaObjectEnd, $FC95. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^Whenever Link is hurt, the game zeroes
WorldKillCount,HelpDropCount, andHelpDropValue, the counters behind the fairy and the 10th-kill drops.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
5759@ResetHelp: 5760 ; Reset values used in special item drops. 5761 LDA #$00 5762 STA WorldKillCount 5763 STA HelpDropCount 5764 STA HelpDropValue
src/Z_01.asm lines 5759–5764 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1, as in ring. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^When
WorldKillCount, the kills since Link was last hurt, equals 16 and the monster can drop items, the drop is a fairy, whatever its random byte.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
11145 ; If the global kill count = $10, set the dropped item to a fairy. 11146 LDA #$23 11147 LDY WorldKillCount 11148 CPY #$10 11149 BEQ @SetHelpItem
src/Z_04.asm lines 11145–11149 at 50a1c86 · upstream ↗ 5996HandleMonsterDied: 5997 ; Handle the monster dying. 5998 INC WorldKillCount
src/Z_01.asm lines 5996–5998 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 4, as in drop-groups. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^The 10th kill since Link was last hurt brings a guaranteed drop of 5 rupees, or of bombs when that 10th kill was by bomb, and the count starts again from 0.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”
How we know
6000 ; Increase the help drop counter, if not at max ($A). 6001 LDA HelpDropCount 6002 CMP #$0A 6003 BCS @SetDyingMetastate 6004 INC HelpDropCount ⋮ 6006 ; If the help drop counter has reached the max, and damage type = bomb (8); 6007 ; then set [51] HelpDropValue in order to drop a bomb next time.
src/Z_01.asm lines 6000–6007 at 50a1c86 · upstream ↗ 11151 ; If help drop counter < $A, then use the dropped item ID as is. 11152 ; But there is a random chance that the item drop will be canceled. ⋮ 11157 ; Otherwise, the item will be guaranteed to be made. 11158 ; [51] HelpDropValue determines which kind: 11159 ; - 0: 5 rupees 11160 ; - other: bomb ⋮ 11172 STA HelpDropCount 11173 STA HelpDropValue
src/Z_04.asm lines 11151–11173 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 4, as in drop-groups. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^In
TakeItem, item$18is a rupee,$0Ffive rupees,$22a heart,$23a fairy,$21the clock, and$00four bombs; a heart restores 1 heart and a fairy 3.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”How we know
4318ItemIdToSlot: 4319 .BYTE $01, $00, $00, $00, $06, $05, $04, $04 4320 .BYTE $02, $02, $03, $0D, $09, $0C, $1B, $1C 4321 .BYTE $08, $0A, $0B, $0B, $0E, $0F, $10, $11 4322 .BYTE $16, $17, $18, $1A, $1F, $1D, $1E, $07 4323 .BYTE $07, $15, $19, $14 ⋮ 4341ItemIdToDescriptor: 4342 .BYTE $14, $21, $22, $23, $01, $01, $21, $22 4343 .BYTE $21, $22, $01, $01, $01, $01, $01, $15 4344 .BYTE $01, $01, $21, $22, $01, $01, $01, $01 4345 .BYTE $11, $11, $10, $01, $01, $01, $01, $11 4346 .BYTE $22, $01, $10, $12
src/Z_01.asm lines 4318–4346 at 50a1c86 · upstream ↗ 4540 CPY #$18 ; Heart container item slot 4541 BEQ @TakeHeartContainer 4542 CPY #$1C ; 5 Rupees item slot 4543 BEQ Take5Rupees 4544 CPY #$16 ; Rupee item slot 4545 BEQ @TakeRupee
src/Z_01.asm lines 4540–4545 at 50a1c86 · upstream ↗ 4651TakeHeartsNoSound: 4652 LDA $0A ; Move item value in [0A] to [01]. 4653 STA $01 ; [01] holds the number of hearts to add minus 1.
src/Z_01.asm lines 4651–4653 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1 TakeItem through the heart routines, run from RAM at $7370. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^A dropped item lasts 255 decrements of its lifetime, one every other frame, about 510 frames, and Link can't take it until the 16th decrement, about 32 frames.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”revised
How we know
11206UpdateItem: 11207 ; Every other frame, decrement the item lifetime. 11208 LDA FrameCounter 11209 LSR 11210 BCC :+ 11211 DEC Item_ObjItemLifetime, X ⋮ 11213 ; If lifetime reached 0, go destroy the object. 11214 LDA Item_ObjItemLifetime, X 11215 BEQ DestroyMonster_Bank4
src/Z_04.asm lines 11206–11215 at 50a1c86 · upstream ↗ 4417 ; [03A8][X] is used to count down the life of the item. 4418 LDA Item_ObjItemLifetime, X 4419 CMP #$F0 4420 BCS L6C28_Exit
src/Z_01.asm lines 4416–4420 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 4 UpdateItem, $B0FC. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Revised after a check by a second AI model, 2026-10-21: Pickup is blocked for 16 lifetime decrements, not 15.
- ^ abCalled in Rev 1 for every group, kill-cycle column, and value of the random byte,
SetUpDroppedItemdrops in 800, 1,520, 1,040, and 1,040 of 2,560 cases for groups A to D, each the item its column names; it gives a fairy at a kill count of 16, and 5 rupees or bombs at a help count of 10.Verified“Legend of Zelda, The (USA) (Rev 1)” · aldonunez/zelda1-disassemblyHow we know
In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 4, the routine and tables the probe calls. We don't reproduce the bytes.
11138 LDA DropItemSetBaseOffsets, Y ⋮ 11140 ADC WorldKillCycle ⋮ 11142 LDA DropItemTable, Y ⋮ 11147 LDY WorldKillCount 11148 CPY #$10 ⋮ 11153 LDA HelpDropCount 11154 CMP #$0A ⋮ 11180 LDA Random, X 11181 CMP DropItemRates, Y 11182 BCS @DestroyMonster
src/Z_04.asm lines 11070–11201 at 50a1c86 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on Legend of Zelda, The (USA) (Rev 1) (SHA-1
4671517d72d0…). It fails if the result disagrees with the claim.The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Checked by a second AI model, 2026-10-25.
- ^The Speed Demos Archive Knowledge Base states that 10 kills without being hit force a 5-rupee drop, or a bomb when the 10th is killed by bomb, and that 16 kills in a row force a fairy, only when the 16th enemy can drop items.WikiSpeed Demos Archive, “The Legend of Zelda”revised
How we know
Kill 10 enemies without getting hit and you’ll get a forced, guaranteed 5 rupee drop … Kill the 10th enemy with a bomb instead, and instead of a 5 rupee you’ll get a forced, guaranteed bomb drop! Kill 16 enemies in a row and you get a fairy drop forced, but only if the 16th enemy is capable of dropping an item
Enemy drops · archived copy ↗ The quote matches our archived copy.
Revised after a check by a second AI model, 2026-10-21.
- ^A heart container adds one container and one full heart, up to 16 containers; a new file starts with three.Codealdonunez/zelda1-disassembly · “Legend of Zelda, The (USA) (Rev 1)”
How we know
4585@TakeHeartContainer: 4586 ; For heart containers, cap at $10. 4587 ; Add a heart container and a heart. 4588 LDA Items, Y 4589 CMP #$F0 4590 BCS L6C28_Exit ; If we already have max hearts, return. 4591 ADC #$11 4592 JMP SetItemValue ; Go set the item value and return.
src/Z_01.asm lines 4585–4592 at 50a1c86 · upstream ↗ In the cartridge (“Legend of Zelda, The (USA) (Rev 1)”): bank 1, as in item-ids. We don't reproduce the bytes.
Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
Sources
Code
- n.d. “Legend of Zelda, The (USA) (Rev 1).” · licence, all uses
- Núñez, Aldo. 2021. “zelda1-disassembly: A complete disassembly of The Legend of Zelda.” Commit 50a1c86. aldonunez/zelda1-disassembly @ 50a1c86 · licence, all uses
Secondary
- Wikidata contributors. 2026. “Wikidata.” Wikimedia Foundation. original · licence, all uses
- Speed Demos Archive Knowledge Base contributors. 2013. “The Legend of Zelda.” Speed Demos Archive. original · archived · licence, all uses