data/claims/metroid-ii.yamlMetroid II - Return of Samus (alex-west's M2RoS disassembly)
Game: Metroid II: Return of Samus.
alex-west's M2RoS disassembly of Metroid II, assembled with rgbds, equals Metroid II - Return of Samus (World) byte for byte. metroid-ii/build
0x184A-0x1898 — bank 0 $184A, jumpArcTable, the bytes the jump claims below readM2RoS: Return of Samus Disassembly · readme.md#L13The resultant file should have this hash: `md5: 9639948ad274fa15281f549e5f9c4d87`Checked by claude, 2026-10-21 — ran extract.py on the ROM and built with rgbds v1.0.1 (make all); out/M2RoS.gb has MD5 9639948ad274fa15281f549e5f9c4d87, and the ROM file has the same MD5 (SHA-1 74a2fad86b9a4c013149b1e214bc4600efb1066d)Cited by: Metroid II: Return of Samus
A jump sets samus_jumpArcCounter to $31, or $21 with the Hi-Jump Boots. While A is held and the counter is below $40, poseFunc_jump lifts Samus 2 px each frame, 3 with the boots, and adds 1 to the counter: up to 15 frames, or 31. Letting go sets the counter to $56, which the comment calls the start of the arc's falling portion. Before this, poseFunc_jumpStart lifts her 2 to 3 px a frame for up to 6 frames while A is held. metroid-ii/jump-ascent
About: Metroid II: Return of Samus Variable jump height
Value
[ 15, 31 ]
SRC/bank_000.asm#L3328-L3339; High jump parameters
ld a, samus_jumpArrayBaseOffset - $1F ;$21
…
; Normal jump parameters
ld a, samus_jumpArrayBaseOffset - $0F ;$31
ld [samus_jumpArcCounter], aM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L3884-L3903; Check if in linear portion of ascent
ld a, [samus_jumpArcCounter]
cp samus_jumpArrayBaseOffset
…
; Set speed, subtracting an extra 1 from it if we have high jump
…
; If A is not pressed, start falling portion of arc
ld a, samus_jumpArrayBaseOffset + $16 ;56
ld [samus_jumpArcCounter], aM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L3937-L3940; Increment jump counter
ld a, [samus_jumpArcCounter]
inc a
ld [samus_jumpArcCounter], aM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L4206-L4229poseFunc_jumpStart: ;{ 00:19E2 - $09 and $0A - Starting to jump
; Check if A is pressed
…
; Move up 2 pixel/frame, with an extra pixel 2 out of 4 frames
…
; Increment jump-start counter
…
; Branch ahead if counter has expired
cp $06M2RoS: Return of Samus Disassembly · SRC/constants.asm#L26def samus_jumpArrayBaseOffset = $40Checked by claude, 2026-10-21 — read the ground jump in poseFunc_standing, poseFunc_jumpStart (its counter stops the start pose at 6), and poseFunc_jump, which increments the counter after each move; $40 - $31 = 15 and $40 - $21 = 31In water the jump adds $10 to the starting counter, so the held ascent is 16 frames shorter.
Cited by: Metroid II: Return of Samus
Past the held ascent, a jump follows a table: each frame poseFunc_jump moves Samus by the next entry of jumpArcTable, a signed whole number of pixels from 2 up to 3 down, and the $80 that ends the table starts a fall. metroid-ii/jump-arc
About: Metroid II: Return of Samus Jump
Value
[ -2, 3 ]
SRC/bank_000.asm#L3906-L3915; Get vertical speed from jumpArcTable
sub samus_jumpArrayBaseOffset
ld hl, jumpArcTable
…
; Start falling pose if at the end of the table
cp samus_jumpArrayBaseOffset + $40 ;$80
jr z, .startFallingM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L3927-L3928.moveVertical:
call samus_moveVerticalM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L4857-L4860samus_moveVertical: ;{ 00:1D4E - move down
; Move up if negative
bit 7, a
jr nz, .moveUpM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L3991-L3999; Jump arc table
; - This starts being referenced when the jump counter is $40
…
jumpArcTable: ;{ 00:184A - Jump arc table
db $fe, $fe, $fe, $fe, $ff, $fe, $ff, $fe, $ff, $ff, $ff, $ff, $ff, $ff, $00, $ff
…
db $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $80Checked by claude, 2026-10-21 — read poseFunc_jump to samus_moveVertical, which moves by the signed value in A, and the 79-byte tableCited by: Metroid II: Return of Samus
Walking has no speed variable to build up: samus_walkRight adds 1 or 2 px to Samus's X position on alternate frames (1.5 px/frame), 2 px/frame with the Varia Suit, and 1 px/frame in water. metroid-ii/walk
About: Metroid II: Return of Samus Running
Value: 1.5 px/frame
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L4596-L4618ld b, $01
; Check if touching water
…
; Varia walking speed
ld b, $02
…
; Normal walking speed (1.5 px/f)
ldh a, [frameCounter]
and $01
add $01
ld b, a
…
…Checked by claude, 2026-10-21 — read samus_walkRight and samus_walkLeft, which add B to the X position directlyCited by: Metroid II: Return of Samus
In a plain jump, poseFunc_jump moves Samus 1 px each frame toward a held direction, and not at all when neither is held. metroid-ii/air-control
About: Metroid II: Return of Samus Air control
Value: 1 px/frame
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L3953-L3967;moveHorizontal
; Move right if right is pressed
ldh a, [hInputPressed]
bit PADB_RIGHT, a
jr z, .endIf_F
call samus_moveRightInAir.turn
.endIf_F:
…
; Move left if left is pressed
ldh a, [hInputPressed]
bit PADB_LEFT, a
jr z, .endIf_G
…M2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L4780-L4788samus_moveRightInAir: ;{ 00:1CF5
…
; Set speed
ld a, $01
ld b, aChecked by claude, 2026-10-21 — read the end of poseFunc_jump and both air moversRunning off a ledge puts Samus straight into the falling pose, and in that pose a jump press starts a jump only while samus_unmorphJumpTimer runs, the 16-frame window after she unmorphs in the air. metroid-ii/no-coyote-time
About: Metroid II: Return of Samus Coyote time
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L3362-L3367poseFunc_running: ;{ 00:14D6 - $03: Running
; Fall if ground is missing
call collision_samusBottom
jr c, .endIf_A
ld a, pose_fallM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L3048-L3066poseFunc_fall: ;{ 00:12F5 - $07 - Falling
; Check if A was just pressed
…
; Check if unmorph jump timer is non-zero
ld a, [samus_unmorphJumpTimer]
and a
jr z, .endIf_AM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L3946-L3950call samus_unmorphInAir
ld a, $10
ld [samus_unmorphJumpTimer], aM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L744-L749; Decrement unmorph jump timer
ld a, [samus_unmorphJumpTimer]
and a
jr z, .endIf_B
dec a
ld [samus_unmorphJumpTimer], aChecked by claude, 2026-10-21 — read poseFunc_running's ground check and poseFunc_fall; the acid branch before the timer check is never taken, as the disassembly notes; the timer counts down once per main-loop frameCited by: Coyote time
Against the background, Samus is tested at points, one x for the side she moves toward and a list of up to five y offsets for her pose. Against enemies, collision_samusEnemies runs first and compares each enemy's hitbox with Samus's, whose top is set per pose. metroid-ii/hitbox
About: Metroid II: Return of Samus Hitbox
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L4981-L4996; Get offset for right side
ldh a, [hSamusXPixel]
add OAM_X_OFS + samusOriginX_toRight
…
; Do sprite collision
call collision_samusEnemies.horizontal
…
; Get base address to the first entry for the pose's y offset listM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L5543-L5545collision_samusHorizontalYOffsetLists: ;{ 00:20FF - Y-Offset collision lists per pose ($80 terminated)
; Note: Due to limitations of the function that read this
; despite each row being 8 bytes long, only 5 offsets are supportedM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L9481collision_samusSpriteHitboxTopTable: ;{ 00:369B - Offset for the top of Samus's hitbox per pose (for sprite collisions)M2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L8708-L8714; Get hitbox pointer of enemy
…
ld hl, enemyHitboxPointersChecked by claude, 2026-10-21 — read collision_samusHorizontal and collision_samusOneEnemy, which loads each enemy's top, bottom, left, and right from its hitboxCited by: Hitbox
An enemy hit sets samusInvulnerableTimer to $33 (51), and while it is above 0 the hit code returns before any damage. drawSamus takes 1 from it each time it draws her, once per frame of play, and blinks her 4 frames on, 4 off. metroid-ii/i-frames
About: Metroid II: Return of Samus Invincibility frames
Value: 51 frames
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L7802-L7812; Exit if i-frames are active
ld a, [samusInvulnerableTimer]
and a
ret nz
…
; Give Samus i-frames
ld a, $33
ld [samusInvulnerableTimer], aM2RoS: Return of Samus Disassembly · SRC/bank_001.asm#L560-L568drawSamus: ;{ 01:4BD9 Draw Samus
…
; Check if damage frames are active
ld a, [samusInvulnerableTimer]
and a
jr z, .endIf_A
dec a
ld [samusInvulnerableTimer], a
; 4 frames on, 4 frames offM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L740call drawSamus_longJump ; Draw SamusChecked by claude, 2026-10-21 — read the enemy-hit routine, drawSamus, and the main game loop, which calls drawSamus_longJump once per frameCited by: Metroid II: Return of Samus
A hit sends Samus away from the side of the enemy she touched along a fixed arc from .bombArcTable, 3 px a frame up at first, and 1 px a frame sideways. She can't change direction until the arc's counter reaches $56, which the comment calls the end of the rising portion. metroid-ii/knockback
About: Metroid II: Return of Samus Knockback
Value: -3 px/frame (first rise)
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L7824-L7836; Set travel direction to damage boost direction
ld a, [samus_damageBoostDirection]
ld [samusAirDirection], a
…
; Set jump arc counter to base
ld a, samus_jumpArrayBaseOffsetM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L8840-L8847; If Samus was on the left side of the enemy
…
; If so, change the damage boost value to the left
ld a, $ff
ld [samus_damageBoostDirection], aM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L2439-L2442poseFunc_bombed: ;{ 00:0F6C - $11: Bombed (standing)
; Load y speed from bombArcTableM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L2469-L2470; Don't let Samus change aerial direction during the rising portion of the knockback
cp samus_jumpArrayBaseOffset + $16 ; $56M2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L2525-L2529.bombArcTable: ; 00:0FF6
db $fd, $fd, $fd, $fd, $fe, $fd, $fe, $fd, $fe, $fe, $fe, $fe, $fe, $fe, $ff, $feM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L2491-L2495; Move right if applicable
ld a, [samusAirDirection]
cp $01
jr nz, .endIf_F
call samus_moveRightInAir.noTurnM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L4785-L4788.noTurn: ; 00:1CFA Alternate entry
; Set speed
ld a, $01
ld b, aChecked by claude, 2026-10-21 — read the hit routine, poseFunc_hurt (which falls through to poseFunc_bombed without a jump press), and poseFunc_bombed, which calls the no-turn air movers for 1 px/frameCited by: Metroid II: Return of Samus
During knockback a jump press clears samusInvulnerableTimer and starts a jump in the air with a ground jump's counter, $31 or $21. metroid-ii/knockback-jump
About: Metroid II: Return of Samus Knockback
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L2350-L2376poseFunc_hurt: ;{ 00:0EF7 - $0F - Knockback
; Go to "bombed" pose handler if jump is not pressed
…
; Do a mid-air jump
…
; Clear i-frames
xor a
ld [samusInvulnerableTimer], a
…
ld a, samus_jumpArrayBaseOffset - $1F ;$21
…
ld a, samus_jumpArrayBaseOffset - $0F ;$31Checked by claude, 2026-10-21 — read poseFunc_hurt to its end, which then sets the jump-start pose (L2391)Cited by: Metroid II: Return of Samus
A new game starts with 99 units of energy, no energy tanks, and 30 of 30 missiles. metroid-ii/start-health
About: Metroid II: Return of Samus Health upgrade
Value: 99 units
CodeM2RoS: Return of Samus Disassembly ·SRC/data/initialSave.asm#L20-L25db $00 ; Samus' equipment
…
dw $0099 ; Samus' health
dw $0030 ; Samus' max missiles
dw $0030 ; Samus' missilesM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L9942-L9946pickup_missileTank: ;{
; Add 10 to max missiles
ld a, [samusMaxMissilesLow]
add $10
daaChecked by claude, 2026-10-21 — read initialSave; health and missiles are binary-coded decimal, as the decimal adjust after adding $10 for 10 missiles showsCited by: Ammunition, Health upgrade
An energy tank adds a tank, up to 5, and fills Samus's energy, setting its high byte to the tank count and its low byte to 99. metroid-ii/energy-tank
About: Metroid II: Return of Samus Health upgrade
Value: 5 tanks at most
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L9895-L9907pickup_energyTank: ;{
; Check if energy tanks are at max
ld a, [samusEnergyTanks]
cp $05 ; Max Energy tanks
…
; Set current health to max
ld [samusCurHealthHigh], a
ld a, $99
ld [samusCurHealthLow], aChecked by claude, 2026-10-21 — read pickup_energyTank and pickup_energyRefillCited by: Health upgrade
A missile tank adds 10 to Samus's missile capacity and 10 to her missiles, each capped at 999. metroid-ii/missile-tank
About: Metroid II: Return of Samus Ammunition
Value: 10 missiles
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L9942-L9976pickup_missileTank: ;{
; Add 10 to max missiles
ld a, [samusMaxMissilesLow]
add $10
daa
…
; Clamp max missiles at 999
…
; Add 10 to current missiles
…
; Clamp current missiles to 999Checked by claude, 2026-10-21 — read pickup_missileTank to its endCited by: Ammunition
The morph ball needs no item: a Down press while crouching calls samus_morphOnGround, and the item bits list bombs, Hi-Jump, Screw Attack, Space Jump, Spring Ball, Spider Ball, and Varia, with no bit for the ball. A new game starts with no item bits set. metroid-ii/morph-ball
About: Metroid II: Return of Samus Morph ball
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L3705-L3710; Handle down input
; Rising edge
ldh a, [hInputRisingEdge]
bit PADB_DOWN, a
jr z, .endIf_L
call samus_morphOnGroundM2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L4524-L4527samus_morphOnGround: ;{ 00:1BA4
; Set pose
ld a, pose_morph
ld [samusPose], aM2RoS: Return of Samus Disassembly · SRC/constants.asm#L49-L56def itemMask_bomb = %00000001 ; 01: Bombs
…
def itemMask_spring = %00010000 ; 10: Spring ball
def itemMask_spider = %00100000 ; 20: Spider ball
def itemMask_varia = %01000000 ; 40: Varia suit
def itemMask_UNUSED = %10000000 ; 80: UnusedM2RoS: Return of Samus Disassembly · SRC/data/initialSave.asm#L20db $00 ; Samus' equipmentChecked by claude, 2026-10-21 — read poseFunc_crouch's down handling and samus_morphOnGround, which sets the pose with no item testCited by: Metroid II: Return of Samus, Morph ball
In the morph ball, A starts a jump only with the Spring Ball, from a counter of $2E. metroid-ii/spring-ball
About: Metroid II: Return of Samus Morph ball
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L3780-L3793; Handle spring ball
; Check if A is pressed
ldh a, [hInputPressed]
bit PADB_A, a
jr z, .endIf_C
; Check if we have spring ball
ld a, [samusItems]
bit itemBit_spring, a
jr z, .endIf_C
; Set jump parameter
ld a, samus_jumpArrayBaseOffset - $12 ;$2eChecked by claude, 2026-10-21 — read poseFunc_morphBall; without the item, the ball only bounces after a fast landingCited by: Metroid II: Return of Samus, Morph ball
In a spin jump with the Space Jump, a new A press restarts the jump only on frames whose spaceJumpTable entry is nonzero: entries 44 to 63, where jumpArcTable falls 1 to 3 px a frame. The restart sets the counter to $28, or $18 with the Hi-Jump Boots, below $40, so a held A gives a new linear ascent. metroid-ii/space-jump
About: Metroid II: Return of Samus Space Jump
Value
[ 44, 63 ]
SRC/bank_000.asm#L4002-L4011; Space Jump Table
; - $00 means no space jumping on that frame
; - Non-zero values mean that you can space jump on that frame
…
spaceJumpTable: ;{ 00:1899
…
db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $02, $01, $02, $02
db $02, $02, $03, $02, $02, $03, $02, $02, $03, $02, $03, $02, $03, $02, $03, $02
db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $80M2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L3997-L3998db $00, $01, $01, $00, $01, $01, $01, $01, $01, $01, $02, $01, $02, $01, $02, $02
db $02, $02, $03, $02, $02, $03, $02, $02, $03, $02, $03, $02, $03, $02, $03, $02M2RoS: Return of Samus Disassembly · SRC/bank_000.asm#L4014-L4078poseFunc_spinJump: ;{ 00:18E8 - $02: Spin jumping
…
; If jump timer is > $40, then jump ahead
ld a, [samus_jumpArcCounter]
cp samus_jumpArrayBaseOffset
jr nc, .endIf_B
; Handle linear ascent of the jump
…
; Skip ahead if not holding jump
ldh a, [hInputRisingEdge]
bit PADB_A, a
…
…The atlas reads this differently: hInputRisingEdge holds only the buttons pressed this frame, so the code skips unless A was just pressed; holding A never restarts the jump.Checked by claude, 2026-10-21 — read poseFunc_spinJump; the comment says "if holding jump" but the code reads hInputRisingEdge, a new press. Entries 44-63 of jumpArcTable are steps of 1 to 3 px downOnly poseFunc_spinJump reads the table; a plain jump can't space jump.
Cited by: Metroid II: Return of Samus, Space Jump
With the Screw Attack, an enemy Samus touches in a spin jump or its start pose takes a Screw Attack weapon hit, and the contact doesn't hurt her. Solid enemies, whose damage entry is $FF, are exempt. metroid-ii/screw-attack
About: Metroid II: Return of Samus Screw Attack
CodeM2RoS: Return of Samus Disassembly ·SRC/bank_000.asm#L8850-L8892; Check if screw attack is active
ld a, [samusItems]
bit itemBit_screw, a
jr z, .iceCase
ld a, [samusPose]
cp pose_spinJump
jr z, .screwCase
ld a, [samusPose]
cp pose_spinStart
…
; Don't screw if damage is $FF (enemy is solid)
…
…Checked by claude, 2026-10-21 — read collision_samusOneEnemy from the hit test through .screwCase; a frozen enemy with an even ice counter is also skippedCited by: Screw Attack