On this page
  1. Related
  2. Mechanics
  3. References
  4. Sources

The atlas reads Metroid II: Return of Samus through alex-west’s M2RoS disassembly, which reassembles the World release byte for byte1. Labels and comments cited here are the disassembly’s. Nothing here has been measured in the ROM yet.

Samus’s jump has no gravity. While A is held, she rises at a fixed 2 px per frame for up to 15 frames, or 3 px for up to 31 with the Hi-Jump Boots2. A table then moves her a whole number of pixels each frame through the top of the arc and the fall3. She walks at a steady 1.5 px per frame, and the Varia Suit raises it to 24.

A hit gives 51 frames5 of invincibility5 and throws Samus along a fixed arc away from the enemy6. A jump press during that arc starts a jump in midair and ends the invincibility7.

Samus can roll into the morph ball from the start8, and the Spring Ball lets the ball jump9. The Space Jump restarts a spin jump at a new press, but only during part of the fall10.

Mechanics

MechanicKindHow
JumpTablea held linear rise, then one pixel step per frame from a 79-entry table
Variable jump heightHold timerA holds a 2 px/frame rise for up to 15 frames, 31 at 3 px/frame with the Hi-Jump Boots
RunningInstant1.5 px/frame from 1- and 2-pixel steps, 2 px/frame with the Varia Suit
Air controlDirect1 px/frame toward a held direction in a plain jump, none without
HitboxPoints and a boxup to five points per side against the background, a box against enemies
Invincibility framesFrame timera 51-frame timer that drops each time Samus is drawn
KnockbackTable arca fixed arc from its own table, 3 px/frame up and 1 sideways, which a jump press cancels
Health upgradeWhole containersup to 5 energy tanks, each one refilling her energy
AmmunitionOne pool30 missiles at the start, 10 more per missile tank, up to 999
Morph ballSpring upgradeavailable from the start; the Spring Ball lets it jump
Space JumpWindow in the arca new press restarts a spin jump during 20 entries of the arc's fall
Screw AttackAny spinany spin jump, from its start pose
Status bar splitWindow layerthe HUD is the window's bottom 8 lines, raised to 16 for save and item messages; the Queen's head takes the window in her room
GravityNoneno gravity in a jump; the arc table sets every frame's step
Coyote timeNonerunning off a ledge starts a fall, and a fall jumps only just after an unmorph
Every claim about this game, by concept (18)
generalalex-west's M2RoS disassembly of Metroid II, assembled with rgbds, equals Metroid II - Return of Samus (World) byte for byte.Code
Air controlIn a plain jump, poseFunc_jump moves Samus 1 px each frame toward a held direction, and not at all when neither is held.Code
AmmunitionA missile tank adds 10 to Samus's missile capacity and 10 to her missiles, each capped at 999.Code
Coyote timeRunning 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.Code
Health upgradeA new game starts with 99 units of energy, no energy tanks, and 30 of 30 missiles.Code
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.Code
HitboxAgainst 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.Code
Invincibility framesAn 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.Code
JumpPast 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.Code
KnockbackA 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.Code
During knockback a jump press clears samusInvulnerableTimer and starts a jump in the air with a ground jump's counter, $31 or $21.Code
Morph ballThe 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.Code
In the morph ball, A starts a jump only with the Spring Ball, from a counter of $2E.Code
RunningWalking 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.Code
Screw AttackWith 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.Code
Space JumpIn 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.Code
Status bar splitThe HUD is the window layer, set to X 7. The main game mode's handler sets window Y to $88 (line 136, the bottom 8 lines), or $80 (16 lines) to show a message while Samus touches a save point or collects a major item. In the Queen's room the HUD moves to the background layer, because her head uses the window.Code
Variable jump heightA 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.Code

References

  1. ^alex-west's M2RoS disassembly of Metroid II, assembled with rgbds, equals Metroid II - Return of Samus (World) byte for byte.Code“Metroid II - Return of Samus (World)” · alex-west/M2RoS
    How we know

    In the cartridge (“Metroid II - Return of Samus (World)”): bank 0 $184A, jumpArcTable, the bytes the jump claims below read. We don't reproduce the bytes.

    13The resultant file should have this hash: `md5: 9639948ad274fa15281f549e5f9c4d87`
    
    readme.md line 13 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  2. ^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.Codealex-west/M2RoS
    How we know
    3328        ; High jump parameters
    3329        ld a, samus_jumpArrayBaseOffset - $1F ;$21
    3330        ld [samus_jumpArcCounter], a
    ⋮
    3337            ; Normal jump parameters
    3338            ld a, samus_jumpArrayBaseOffset - $0F ;$31
    3339            ld [samus_jumpArcCounter], a
    
    SRC/bank_000.asm lines 3328–3339 at 031aea3 · upstream ↗
    3884    ; Check if in linear portion of ascent
    3885    ld a, [samus_jumpArcCounter]
    3886    cp samus_jumpArrayBaseOffset
    ⋮
    3892            ; Set speed, subtracting an extra 1 from it if we have high jump
    ⋮
    3901        ; If A is not pressed, start falling portion of arc
    3902        ld a, samus_jumpArrayBaseOffset + $16 ;56
    3903        ld [samus_jumpArcCounter], a
    
    SRC/bank_000.asm lines 3884–3903 at 031aea3 · upstream ↗
    3937    ; Increment jump counter
    3938    ld a, [samus_jumpArcCounter]
    3939    inc a
    3940    ld [samus_jumpArcCounter], a
    
    SRC/bank_000.asm lines 3937–3940 at 031aea3 · upstream ↗
    4206poseFunc_jumpStart: ;{ 00:19E2 - $09 and $0A - Starting to jump
    4207    ; Check if A is pressed
    ⋮
    4211        ; Move up 2 pixel/frame, with an extra pixel 2 out of 4 frames
    ⋮
    4224        ; Increment jump-start counter
    ⋮
    4228        ; Branch ahead if counter has expired
    4229        cp $06
    
    SRC/bank_000.asm lines 4206–4229 at 031aea3 · upstream ↗
    26def samus_jumpArrayBaseOffset = $40
    
    SRC/constants.asm line 26 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  3. ^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.Codealex-west/M2RoS
    How we know
    3906    ; Get vertical speed from jumpArcTable
    3907    sub samus_jumpArrayBaseOffset
    3908    ld hl, jumpArcTable
    ⋮
    3913    ; Start falling pose if at the end of the table
    3914    cp samus_jumpArrayBaseOffset + $40 ;$80
    3915        jr z, .startFalling
    
    SRC/bank_000.asm lines 3906–3915 at 031aea3 · upstream ↗
    3927.moveVertical:
    3928    call samus_moveVertical
    
    SRC/bank_000.asm lines 3927–3928 at 031aea3 · upstream ↗
    4857samus_moveVertical: ;{ 00:1D4E - move down
    4858    ; Move up if negative
    4859    bit 7, a
    4860        jr nz, .moveUp
    
    SRC/bank_000.asm lines 4857–4860 at 031aea3 · upstream ↗
    3991; Jump arc table
    3992; - This starts being referenced when the jump counter is $40
    ⋮
    3994jumpArcTable: ;{ 00:184A - Jump arc table
    3995    db $fe, $fe, $fe, $fe, $ff, $fe, $ff, $fe, $ff, $ff, $ff, $ff, $ff, $ff, $00, $ff
    ⋮
    3999    db $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $03, $80
    
    SRC/bank_000.asm lines 3991–3999 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  4. ^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.Codealex-west/M2RoS
    How we know
    4596    ld b, $01
    4597    ; Check if touching water
    ⋮
    4605            ; Varia walking speed
    4606            ld b, $02
    ⋮
    4609            ; Normal walking speed (1.5 px/f)
    4610            ldh a, [frameCounter]
    4611            and $01
    4612            add $01
    4613            ld b, a
    ⋮
    4616    ; Move Samus right
    4617    ldh a, [hSamusXPixel]
    4618    add b
    
    SRC/bank_000.asm lines 4596–4618 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  5. ^ abAn 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.Codealex-west/M2RoS
    How we know
    7802    ; Exit if i-frames are active
    7803    ld a, [samusInvulnerableTimer]
    7804    and a
    7805        ret nz
    ⋮
    7810    ; Give Samus i-frames
    7811    ld a, $33
    7812    ld [samusInvulnerableTimer], a
    
    SRC/bank_000.asm lines 7802–7812 at 031aea3 · upstream ↗
    560drawSamus: ;{ 01:4BD9 Draw Samus
    ⋮
    562    ; Check if damage frames are active
    563    ld a, [samusInvulnerableTimer]
    564    and a
    565    jr z, .endIf_A
    566        dec a
    567        ld [samusInvulnerableTimer], a
    568        ; 4 frames on, 4 frames off
    
    SRC/bank_001.asm lines 560–568 at 031aea3 · upstream ↗
    740    call drawSamus_longJump ; Draw Samus
    
    SRC/bank_000.asm line 740 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  6. ^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.Codealex-west/M2RoS
    How we know
    7824    ; Set travel direction to damage boost direction
    7825    ld a, [samus_damageBoostDirection]
    7826    ld [samusAirDirection], a
    ⋮
    7832        ld [samusAirDirection], a
    ⋮
    7835    ; Set jump arc counter to base
    7836    ld a, samus_jumpArrayBaseOffset
    
    SRC/bank_000.asm lines 7824–7836 at 031aea3 · upstream ↗
    8840    ; If Samus was on the left side of the enemy
    ⋮
    8845        ; If so, change the damage boost value to the left
    8846        ld a, $ff
    8847        ld [samus_damageBoostDirection], a
    
    SRC/bank_000.asm lines 8840–8847 at 031aea3 · upstream ↗
    2439poseFunc_bombed: ;{ 00:0F6C - $11: Bombed (standing)
    2440    ; Load y speed from bombArcTable
    
    SRC/bank_000.asm lines 2439–2442 at 031aea3 · upstream ↗
    2469    ; Don't let Samus change aerial direction during the rising portion of the knockback
    2470    cp samus_jumpArrayBaseOffset + $16 ; $56
    
    SRC/bank_000.asm lines 2469–2470 at 031aea3 · upstream ↗
    2525.bombArcTable: ; 00:0FF6
    2526    db $fd, $fd, $fd, $fd, $fe, $fd, $fe, $fd, $fe, $fe, $fe, $fe, $fe, $fe, $ff, $fe
    
    SRC/bank_000.asm lines 2525–2529 at 031aea3 · upstream ↗
    2491    ; Move right if applicable
    2492    ld a, [samusAirDirection]
    2493    cp $01
    2494    jr nz, .endIf_F
    2495        call samus_moveRightInAir.noTurn
    
    SRC/bank_000.asm lines 2491–2495 at 031aea3 · upstream ↗
    4785.noTurn: ; 00:1CFA Alternate entry
    4786    ; Set speed
    4787    ld a, $01
    4788    ld b, a
    
    SRC/bank_000.asm lines 4785–4788 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  7. ^During knockback a jump press clears samusInvulnerableTimer and starts a jump in the air with a ground jump's counter, $31 or $21.Codealex-west/M2RoS
    How we know
    2350poseFunc_hurt: ;{ 00:0EF7 - $0F - Knockback
    2351    ; Go to "bombed" pose handler if jump is not pressed
    ⋮
    2355    ; Do a mid-air jump
    ⋮
    2361    ; Clear i-frames
    2362    xor a
    2363    ld [samusInvulnerableTimer], a
    ⋮
    2366    ld a, samus_jumpArrayBaseOffset - $1F ;$21
    ⋮
    2375        ld a, samus_jumpArrayBaseOffset - $0F ;$31
    
    SRC/bank_000.asm lines 2350–2376 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  8. ^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.Codealex-west/M2RoS
    How we know
    3705; Handle down input
    3706    ; Rising edge
    3707    ldh a, [hInputRisingEdge]
    3708    bit PADB_DOWN, a
    3709    jr z, .endIf_L
    3710        call samus_morphOnGround
    
    SRC/bank_000.asm lines 3705–3710 at 031aea3 · upstream ↗
    4524samus_morphOnGround: ;{ 00:1BA4
    4525    ; Set pose
    4526    ld a, pose_morph
    4527    ld [samusPose], a
    
    SRC/bank_000.asm lines 4524–4527 at 031aea3 · upstream ↗
    49def itemMask_bomb   = %00000001 ; 01: Bombs
    ⋮
    53def itemMask_spring = %00010000 ; 10: Spring ball
    54def itemMask_spider = %00100000 ; 20: Spider ball
    55def itemMask_varia  = %01000000 ; 40: Varia suit
    56def itemMask_UNUSED = %10000000 ; 80: Unused
    
    SRC/constants.asm lines 49–56 at 031aea3 · upstream ↗
    20    db $00       ; Samus' equipment
    
    SRC/data/initialSave.asm line 20 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  9. ^In the morph ball, A starts a jump only with the Spring Ball, from a counter of $2E.Codealex-west/M2RoS
    How we know
    3780    ; Handle spring ball
    3781    ; Check if A is pressed
    3782    ldh a, [hInputPressed]
    3783    bit PADB_A, a
    3784    jr z, .endIf_C
    3785        ; Check if we have spring ball
    3786        ld a, [samusItems]
    3787        bit itemBit_spring, a
    3788        jr z, .endIf_C
    3789            ; Set jump parameter
    3790            ld a, samus_jumpArrayBaseOffset - $12 ;$2e
    
    SRC/bank_000.asm lines 3780–3793 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  10. ^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.Codealex-west/M2RoS
    How we know
    4002; Space Jump Table
    4003; - $00 means no space jumping on that frame
    4004; - Non-zero values mean that you can space jump on that frame
    ⋮
    4006spaceJumpTable: ;{ 00:1899
    ⋮
    4009    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $02, $01, $02, $02
    4010    db $02, $02, $03, $02, $02, $03, $02, $02, $03, $02, $03, $02, $03, $02, $03, $02
    4011    db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $80
    
    SRC/bank_000.asm lines 4002–4011 at 031aea3 · upstream ↗
    3997    db $00, $01, $01, $00, $01, $01, $01, $01, $01, $01, $02, $01, $02, $01, $02, $02
    3998    db $02, $02, $03, $02, $02, $03, $02, $02, $03, $02, $03, $02, $03, $02, $03, $02
    
    SRC/bank_000.asm lines 3997–3998 at 031aea3 · upstream ↗
    4014poseFunc_spinJump: ;{ 00:18E8 - $02: Spin jumping
    ⋮
    4016    ldh a, [hInputRisingEdge]
    ⋮
    4023    ; If jump timer is > $40, then jump ahead
    4024    ld a, [samus_jumpArcCounter]
    4025    cp samus_jumpArrayBaseOffset
    4026    jr nc, .endIf_B
    4027        ; Handle linear ascent of the jump
    ⋮
    4030        bit PADB_A, a
    ⋮
    4034            ld a, [samusItems]
    ⋮
    4053    ; Skip ahead if not holding jump
    4054    ldh a, [hInputRisingEdge]
    4055    bit PADB_A, a
    ⋮
    
    SRC/bank_000.asm lines 4014–4078 at 031aea3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

Sources

Code