On this page
  1. Energy and ammunition
  2. The jump
  3. Related
  4. Mechanics
  5. References
  6. Sources

Metroid: Zero Mission retells Metroid on the Game Boy Advance. The atlas reads it through metroidret’s C decompilation, whose default build is the North American ROM1. Names and comments cited here are the decompilers’. Nothing here has been measured in the ROM yet.

#Energy and ammunition

Samus starts with 99 energy2 and nothing else; Metroid started her at 30 units2. An energy tank adds 100 per tank (50 on Hard)3 and refills her, up to 12 tanks3. Missiles, super missiles, and power bombs are separate pools, where Metroid had missiles only. A missile tank adds 5 missiles per tank (2 on Hard)4, the same 5 as Metroid’s on Easy and Normal4.

#The jump

A jump takes off at 6 px/frame (7.25 with the High Jump)5. Metroid’s took off at 4 px/frame for every jump, and its boots lowered the gravity instead5. Gravity is 0.3125 px/frame²6, about 3.3 times Metroid’s (computed)6. Held to the top, a jump rises about 59 px (83 with the High Jump)7 (computed)7.

Letting go of A while Samus rises stops the rise at once, at any height. Metroid counted a release only after 32 px8.

A spin jump that touches a wall can push off it. For 8 frames after the touch, a jump press with Samus facing away and the wall within 10 px starts a wall jump. With the Space Jump active out of liquid, the game skips this check9. Metroid takes a jump press in the air only in lava, so it has no wall jump10.

Mechanics

MechanicKindHow
Health upgradeWhole containersenergy tanks of 100, or 50 on Hard, from 99 at the start, each refilling her energy
AmmunitionSeveral poolsmissiles, super missiles, and power bombs, 5, 2, and 2 per tank, or 2, 1, and 1 on Hard
JumpSpeed by state6 px/frame up, 7.25 with the High Jump, 6.625 without the suit
GravityOne gravity0.3125 px/frame² in air, held or not, halved in liquid without the Gravity Suit
Variable jump heightRelease capletting go during the rise sets the vertical speed to 0 at any height
Wall jumpPush off from a spinfrom a spin jump, facing away within 8 frames of touching a wall
Every claim about this game, by concept (9)
generalThe mzm decompilation's README names mzm_us.gba, the North American release, as its default build and gives its SHA-1 as 5de8536afe1f0078ee6fe1089f890e8c7aa0a6e8, which is the SHA-1 of the No-Intro file Metroid - Zero Mission (USA).gba. The atlas hasn't built it.Code
AmmunitionMissiles, super missiles, and power bombs each have their own maximum and count, and each tank adds to both: 5 missiles, 2 super missiles, or 2 power bombs on Easy and Normal, and 2, 1, or 1 on Hard, from a start of 0 (mzm/start-energy). Missile tanks stop adding past 50 tanks' worth, 250 missiles, or 100 on Hard (computed). Metroid has missiles only, and its tank adds 5 to both the count and the capacity.Code
GravityOut of liquid (or in it with the Gravity Suit) and not held by a Metroid, SamusUpdatePhysics sets the vertical acceleration to 10 each frame, and SamusUpdateVelocityPosition takes it from yVelocity on every frame of the airborne poses while the velocity is at least -231, whether A is held or not: 0.3125 px/frame² (computed). A fall moves at most 128, 4 px/frame. In water, lava, or acid without the Gravity Suit, or out of liquid in a Metroid's grip, the acceleration halves to 5 and both caps drop to 40, 1.25 px/frame. Metroid's jump gravity is 0.09375 px/frame² (0.0703 with the High Jump Boots), and its falls reach 5 px/frame.Code
Health upgradeWhen a game starts rather than loads a file (gIsLoadingFile clear), SamusInit fills gEquipment with zeros and then sets Samus's maximum and current energy to 99, so she starts with 99 energy, no tanks, and no missiles, super missiles, or power bombs. Metroid starts her with 30 units.Code
On Easy and Normal an energy tank adds 100 to Samus's maximum energy, and on Hard 50, and sets her energy to the new maximum. A tank adds nothing if the maximum plus one more tank would pass 12 tanks plus the starting 99, so the maximum is 1299, or 699 on Hard (computed). In Metroid each tank holds 100 units, up to 6 tanks and 699.9 units, with the same refill.Code
JumpA jump sets Samus's upward yVelocity to 192 (SAMUS_LOW_JUMP_VELOCITY), 232 with the High Jump active, or 212 without the suit, which is checked first. The velocity counts eighths of a subpixel and a pixel is 4 subpixels, so these are 6, 7.25, and 6.625 px/frame (computed). Movement caps the velocity at 192 (24 subpixels, 6 px), so the High Jump's first five frames each rise 6 px (computed). Metroid's jump always takes off at 4 px/frame, and its High Jump Boots lower the gravity instead of raising the speed.Code
Stepping the code's arithmetic with A held, out of liquid, a jump from the ground peaks about 59 px up (235 subpixels) on its 19th frame, and a High Jump about 83 px (331 subpixels) on its 23rd (computed: each frame moves yVelocity capped at 192 and shifted right 3, then takes 10 from it).Code
Variable jump heightOn any frame Samus rises (yVelocity above 0) without A held, the mid-air handlers set yVelocity to 0, at any height: SamusMidAir, SamusTurningAroundMidAir, and SamusSpinning, which runs the spin jump, the Space Jump, and the Screw Attack. The check is each handler's last step, so a frame whose earlier branch returns, such as a Space Jump or wall jump press, skips it. Metroid lets a release stop the rise only after 32 px.Code
Wall jumpWhen a spin jump or Screw Attack touches a wall, SamusCheckCollisions sets walljumpTimer to 8 and stores the direction away from the wall. Each time SamusSpinning runs, unless the Space Jump is active and Samus isn't slowed (slowedByLiquid), it takes 1 from a nonzero timer, and if Samus faces away from the wall, a new A press, with a solid block 10 px (40 subpixels) to the wall's side, starts a wall jump. The jump takes off at the normal or High Jump speed (mzm/jump-speed). Metroid takes a jump press in the air only in lava (metroid-samus/no-air-jump), so it has no wall jump.Code

References

  1. ^The mzm decompilation's README names mzm_us.gba, the North American release, as its default build and gives its SHA-1 as 5de8536afe1f0078ee6fe1089f890e8c7aa0a6e8, which is the SHA-1 of the No-Intro file Metroid - Zero Mission (USA).gba. The atlas hasn't built it.Codemetroidret/mzm
    How we know
    9This repository can be used to build multiple ROMs. The ROMs are named like this: `mzm_{region}.gba` (or `mzm_{region}_debug.gba`)
    ⋮
    12- us: USA, North America `sha1: 5de8536afe1f0078ee6fe1089f890e8c7aa0a6e8`
    
    README.md lines 9–12 at 2aae289 · upstream ↗
    21The default built ROM is mzm_us.gba
    
    README.md line 21 at 2aae289 · upstream ↗
    15de8536afe1f0078ee6fe1089f890e8c7aa0a6e8  mzm_us.gba
    
    mzm_us.sha1 line 1 at 2aae289 · upstream ↗

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

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

    In the claim ledger

  2. ^ abWhen a game starts rather than loads a file (gIsLoadingFile clear), SamusInit fills gEquipment with zeros and then sets Samus's maximum and current energy to 99, so she starts with 99 energy, no tanks, and no missiles, super missiles, or power bombs. Metroid starts her with 30 units.Codemetroidret/mzm · nmikstas/metroid-disassembly
    How we know
    8071        if (!gIsLoadingFile)
    ⋮
    8073            // Zero out most of samus's data
    8074            DMA3_FILL_32(0, &gSamusData, sizeof(gSamusData));
    8075            DMA3_FILL_32(0, &gEquipment, sizeof(gEquipment));
    ⋮
    8083            // Set starting info
    8084            gSamusData.pose = SPOSE_FACING_THE_FOREGROUND;
    8085            gSamusData.direction = KEY_LEFT;
    ⋮
    8087            gEquipment.maxEnergy = 99;
    8088            gEquipment.currentEnergy = 99;
    
    src/samus.c lines 8071–8088 at 2aae289 · upstream ↗
    16struct Equipment {
    17    u16 maxEnergy;
    18    u16 maxMissiles;
    19    u8 maxSuperMissiles;
    20    u8 maxPowerBombs;
    21    u16 currentEnergy;
    22    u16 currentMissiles;
    23    u8 currentSuperMissiles;
    24    u8 currentPowerBombs;
    
    include/structs/samus.h lines 16–24 at 2aae289 · upstream ↗
    1580        LDA #$00                ;
    1581        STA HealthLo            ;Starting health is
    1582        LDA #$03                ;set to 30 units.
    1583        STA HealthHi            ;
    
    Source_Files/Bank07.asm lines 1580–1583 at 4270d57 · upstream ↗

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

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

    In the claim ledger

  3. ^ abOn Easy and Normal an energy tank adds 100 to Samus's maximum energy, and on Hard 50, and sets her energy to the new maximum. A tank adds nothing if the maximum plus one more tank would pass 12 tanks plus the starting 99, so the maximum is 1299, or 699 on Hard (computed). In Metroid each tank holds 100 units, up to 6 tanks and 699.9 units, with the same refill.Codemetroidret/mzm · nmikstas/metroid-disassembly
    How we know
    531                else if (i == ITEM_TYPE_ENERGY)
    ⋮
    533                    if (sNumberOfTanksPerArea[MAX_AMOUNT_OF_AREAS - 1].energy * sTankIncreaseAmount[gDifficulty].energy + sStartingHealthAmmo.energy >= gEquipment.maxEnergy + sTankIncreaseAmount[gDifficulty].energy)
    ⋮
    535                        gEquipment.maxEnergy += sTankIncreaseAmount[gDifficulty].energy;
    536                        gEquipment.currentEnergy = gEquipment.maxEnergy;
    
    src/bg_clip.c lines 531–537 at 2aae289 · upstream ↗
    52    [MAX_AMOUNT_OF_AREAS - 1] = {
    53        .energy = 12,
    
    src/data/block_data.c lines 52–53 at 2aae289 · upstream ↗
    60const struct TankList sStartingHealthAmmo = {
    61    .energy = 99,
    ⋮
    67const struct TankList sTankIncreaseAmount[DIFF_COUNT] = {
    68    [DIFF_EASY] = {
    69        .energy = 100,
    ⋮
    74    [DIFF_NORMAL] = {
    75        .energy = 100,
    ⋮
    80    [DIFF_HARD] = {
    81        .energy = 50,
    
    src/data/block_data.c lines 60–81 at 2aae289 · upstream ↗
    4354LDC00:* LDA TankCount           ;
    4355LDC03:  CMP #$06            ;Has Samus got 6 energy tanks?
    4356LDC05:  BEQ +               ;If so, she can't have any more.
    4357LDC07:  INC TankCount           ;Otherwise give her a new tank.
    4358LDC0A:* LDA TankCount           ;
    4359LDC0D:  JSR Amul16          ;Get tank count and shift into upper nibble.
    4360LDC10:  ORA #$09            ;
    4361LDC12:  STA HealthHi            ;Set new tank count. Upper health digit set to 9.
    4362LDC15:  LDA #$99            ;Max out low health digit.
    4363LDC17:  STA HealthLo            ;Health is now FULL!
    
    Source_Files/Bank07.asm lines 4354–4363 at 4270d57 · upstream ↗

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

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

    In the claim ledger

  4. ^ abMissiles, super missiles, and power bombs each have their own maximum and count, and each tank adds to both: 5 missiles, 2 super missiles, or 2 power bombs on Easy and Normal, and 2, 1, or 1 on Hard, from a start of 0 (mzm/start-energy). Missile tanks stop adding past 50 tanks' worth, 250 missiles, or 100 on Hard (computed). Metroid has missiles only, and its tank adds 5 to both the count and the capacity.Codemetroidret/mzm · nmikstas/metroid-disassembly
    How we know
    520                if (i == ITEM_TYPE_MISSILE)
    ⋮
    522                    if (sNumberOfTanksPerArea[MAX_AMOUNT_OF_AREAS - 1].missile * sTankIncreaseAmount[gDifficulty].missile + sStartingHealthAmmo.missile >= gEquipment.maxMissiles + sTankIncreaseAmount[gDifficulty].missile)
    ⋮
    524                        if (gEquipment.maxMissiles == 0)
    525                            isFirstTank = TRUE;
    ⋮
    527                        gEquipment.maxMissiles += sTankIncreaseAmount[gDifficulty].missile;
    528                        gEquipment.currentMissiles += sTankIncreaseAmount[gDifficulty].missile;
    
    src/bg_clip.c lines 520–528 at 2aae289 · upstream ↗
    539                else if (i == ITEM_TYPE_SUPER_MISSILE)
    ⋮
    546                        gEquipment.maxSuperMissiles += sTankIncreaseAmount[gDifficulty].superMissile;
    547                        gEquipment.currentSuperMissiles += sTankIncreaseAmount[gDifficulty].superMissile;
    ⋮
    550                else if (i == ITEM_TYPE_POWER_BOMB)
    ⋮
    557                        gEquipment.maxPowerBombs += sTankIncreaseAmount[gDifficulty].powerBomb;
    558                        gEquipment.currentPowerBombs += sTankIncreaseAmount[gDifficulty].powerBomb;
    
    src/bg_clip.c lines 539–558 at 2aae289 · upstream ↗
    52    [MAX_AMOUNT_OF_AREAS - 1] = {
    53        .energy = 12,
    54        .missile = 50,
    
    src/data/block_data.c lines 52–54 at 2aae289 · upstream ↗
    67const struct TankList sTankIncreaseAmount[DIFF_COUNT] = {
    68    [DIFF_EASY] = {
    69        .energy = 100,
    70        .missile = 5,
    71        .superMissile = 2,
    72        .powerBomb = 2
    ⋮
    74    [DIFF_NORMAL] = {
    75        .energy = 100,
    76        .missile = 5,
    77        .superMissile = 2,
    78        .powerBomb = 2
    ⋮
    80    [DIFF_HARD] = {
    ⋮
    
    src/data/block_data.c lines 67–84 at 2aae289 · upstream ↗
    4349LDBF7:* BEQ +               ;Branch if item is an energy tank.
    4350LDBF9:  LDA #$05            ;
    4351LDBFB:  JSR AddToMaxMissiles        ;($DD97)Increase missile capacity by 5.
    
    Source_Files/Bank07.asm lines 4349–4351 at 4270d57 · upstream ↗
    4635; Adds A to both MissileCount & MaxMissiles, storing the new count
    ⋮
    4641    ADC MissileCount
    ⋮
    4644*   STA MissileCount
    ⋮
    4647    ADC MaxMissiles
    ⋮
    4650*   STA MaxMissiles
    
    Source_Files/Bank07.asm lines 4635–4650 at 4270d57 · upstream ↗

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

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

    In the claim ledger

  5. ^ abA jump sets Samus's upward yVelocity to 192 (SAMUS_LOW_JUMP_VELOCITY), 232 with the High Jump active, or 212 without the suit, which is checked first. The velocity counts eighths of a subpixel and a pixel is 4 subpixels, so these are 6, 7.25, and 6.625 px/frame (computed). Movement caps the velocity at 192 (24 subpixels, 6 px), so the High Jump's first five frames each rise 6 px (computed). Metroid's jump always takes off at 4 px/frame, and its High Jump Boots lower the gravity instead of raising the speed.Codemetroidret/mzm · nmikstas/metroid-disassemblyrevised
    How we know
    1863            if (pCopy->forcedMovement == FORCED_MOVEMENT_MID_AIR_JUMP)
    ⋮
    1865                // Set mid air pose, spinning if holding a sideways direction
    1866                if (gButtonInput & (KEY_RIGHT | KEY_LEFT))
    1867                    pData->pose = SPOSE_STARTING_SPIN_JUMP;
    1868                else
    1869                    pData->pose = SPOSE_MIDAIR;
    ⋮
    1871                // Set Y velocity
    1872                if (pEquipment->suitType == SUIT_SUITLESS)
    1873                    pData->yVelocity = SAMUS_SUITLESS_JUMP_VELOCITY;
    1874                else if (pEquipment->suitMiscActivation & SMF_HIGH_JUMP)
    1875                    pData->yVelocity = SAMUS_HIGH_JUMP_VELOCITY;
    1876                else
    ⋮
    
    src/samus.c lines 1863–1877 at 2aae289 · upstream ↗
    1700            // Starting a jump, always a spin jump because running implies a direction was held
    1701            pData->pose = SPOSE_STARTING_SPIN_JUMP;
    ⋮
    1703            // Set jump velocity
    1704            if (pEquipment->suitType == SUIT_SUITLESS)
    1705                pData->yVelocity = SAMUS_SUITLESS_JUMP_VELOCITY;
    1706            else if (pEquipment->suitMiscActivation & SMF_HIGH_JUMP)
    1707                pData->yVelocity = SAMUS_HIGH_JUMP_VELOCITY;
    1708            else
    1709                pData->yVelocity = SAMUS_LOW_JUMP_VELOCITY;
    
    src/samus.c lines 1700–1709 at 2aae289 · upstream ↗
    336#define SAMUS_HIGH_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + PIXEL_SIZE * 3 + ONE_SUB_PIXEL))
    337#define SAMUS_LOW_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + EIGHTH_BLOCK_SIZE))
    338#define SAMUS_SUITLESS_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + EIGHTH_BLOCK_SIZE + PIXEL_SIZE / 2 + ONE_SUB_PIXEL / 2.f))
    
    include/constants/samus.h lines 336–338 at 2aae289 · upstream ↗
    314#define VELOCITY_TO_SUB_PIXEL(velocity) (DIV_SHIFT((velocity), 8))
    315#define SUB_PIXEL_TO_VELOCITY(velocity) ((s16)((velocity) * 8))
    
    include/constants/samus.h lines 314–315 at 2aae289 · upstream ↗
    47// The amount of sub pixels a single visible pixel contains
    48#define SUB_PIXEL_RATIO 4
    49// The amount of visible pixels a block contains
    50#define PIXEL_PER_BLOCK 16
    ⋮
    53#define BLOCK_SIZE (PIXEL_PER_BLOCK * SUB_PIXEL_RATIO)
    ⋮
    57#define QUARTER_BLOCK_SIZE (BLOCK_SIZE / 4)
    ⋮
    61#define EIGHTH_BLOCK_SIZE (BLOCK_SIZE / 8)
    ⋮
    63#define PIXEL_SIZE (BLOCK_SIZE / PIXEL_PER_BLOCK)
    ⋮
    65#define ONE_SUB_PIXEL (PIXEL_SIZE / PIXEL_SIZE)
    
    include/types.h lines 47–65 at 2aae289 · upstream ↗
    6758            if (pData->yVelocity > gSamusPhysics.positiveYVelocityCap)
    ⋮
    6760                velocity = DIV_SHIFT(gSamusPhysics.positiveYVelocityCap, 8);
    ⋮
    6766            else
    ⋮
    6768                velocity = DIV_SHIFT(pData->yVelocity, 8);
    ⋮
    6776            pData->yPosition -= velocity;
    
    src/samus.c lines 6758–6776 at 2aae289 · upstream ↗
    325#define SAMUS_Y_POSITIVE_VELOCITY_CAP 192
    
    include/constants/samus.h line 325 at 2aae289 · upstream ↗
    2672SetSamusJump:
    ⋮
    2681        LDA #$FC
    2682        STA ObjVertSpeed
    ⋮
    2686        LDA SamusGear
    ⋮
    2693LCFF3:  LDY #$18                ; gravity (high value -> low jump)
    2694        LDA SamusGear
    2695        AND #gr_HIGHJUMP
    2696        BEQ +                   ; branch if Samus doesn't have High Jump
    2697        LDY #$12                ; lower gravity value -> high jump!
    2698*       STY SamusGravity
    
    Source_Files/Bank07.asm lines 2672–2698 at 4270d57 · upstream ↗

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

    Revised after a check by a second AI model, 2026-10-22.

    In the claim ledger

  6. ^ abOut of liquid (or in it with the Gravity Suit) and not held by a Metroid, SamusUpdatePhysics sets the vertical acceleration to 10 each frame, and SamusUpdateVelocityPosition takes it from yVelocity on every frame of the airborne poses while the velocity is at least -231, whether A is held or not: 0.3125 px/frame² (computed). A fall moves at most 128, 4 px/frame. In water, lava, or acid without the Gravity Suit, or out of liquid in a Metroid's grip, the acceleration halves to 5 and both caps drop to 40, 1.25 px/frame. Metroid's jump gravity is 0.09375 px/frame² (0.0703 with the High Jump Boots), and its falls reach 5 px/frame.Codemetroidret/mzm · nmikstas/metroid-disassembly
    How we know
    324#define SAMUS_Y_ACCELERATION 10
    325#define SAMUS_Y_POSITIVE_VELOCITY_CAP 192
    326#define SAMUS_Y_NEGATIVE_VELOCITY_CAP 128
    327#define SAMUS_Y_SLOWED_VELOCITY_CAP 40
    
    include/constants/samus.h lines 324–327 at 2aae289 · upstream ↗
    2649        case HAZARD_TYPE_WATER:
    2650        case HAZARD_TYPE_LAVA:
    2651        case HAZARD_TYPE_WEAK_ACID:
    2652        case HAZARD_TYPE_STRONG_ACID:
    2653            // In liquid, check has gravity to see if slowed
    2654            if (!(pEquipment->suitMiscActivation & SMF_GRAVITY_SUIT))
    2655                slowed++;
    2656#ifndef BUGFIX
    2657            break;
    2658#endif
    ⋮
    2660        default:
    2661            // Check grabbed by metroid
    ⋮
    
    src/samus.c lines 2649–2697 at 2aae289 · upstream ↗
    6762            else if (pData->yVelocity < -gSamusPhysics.negativeYVelocityCap)
    ⋮
    6764                velocity = DIV_SHIFT(-gSamusPhysics.negativeYVelocityCap, 8);
    ⋮
    6766            else
    ⋮
    6771            if (pData->yVelocity >= -231)
    ⋮
    6773                pData->yVelocity -= gSamusPhysics.yAcceleration;
    ⋮
    6776            pData->yPosition -= velocity;
    
    src/samus.c lines 6762–6776 at 2aae289 · upstream ↗
    2693LCFF3:  LDY #$18                ; gravity (high value -> low jump)
    2694        LDA SamusGear
    2695        AND #gr_HIGHJUMP
    2696        BEQ +                   ; branch if Samus doesn't have High Jump
    2697        LDY #$12                ; lower gravity value -> high jump!
    2698*       STY SamusGravity
    
    Source_Files/Bank07.asm lines 2693–2698 at 4270d57 · upstream ↗
    5582;gravity used in the acceleration calculation. The higher the number, the more intense the gravity.
    5583;The possible values for gravity are as follows:
    5584;#$38-When Samus has been hit by an enemy.
    5585;#$1A-When Samus is falling.
    5586;#$18-Jump without high jump boots.
    5587;#$12-Jump with high jump boots.
    
    Source_Files/Bank07.asm lines 5582–5587 at 4270d57 · upstream ↗
    5628LE3C9:* cmp #$05            ;Has maximum downward speed been reached?
    5629LE3CB:* bcc +               ;If not, branch.
    
    Source_Files/Bank07.asm lines 5628–5629 at 4270d57 · upstream ↗

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

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

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

    In the claim ledger

  7. ^ abStepping the code's arithmetic with A held, out of liquid, a jump from the ground peaks about 59 px up (235 subpixels) on its 19th frame, and a High Jump about 83 px (331 subpixels) on its 23rd (computed: each frame moves yVelocity capped at 192 and shifted right 3, then takes 10 from it).Codemetroidret/mzm
    How we know
    324#define SAMUS_Y_ACCELERATION 10
    325#define SAMUS_Y_POSITIVE_VELOCITY_CAP 192
    ⋮
    336#define SAMUS_HIGH_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + PIXEL_SIZE * 3 + ONE_SUB_PIXEL))
    337#define SAMUS_LOW_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + EIGHTH_BLOCK_SIZE))
    
    include/constants/samus.h lines 324–337 at 2aae289 · upstream ↗
    6758            if (pData->yVelocity > gSamusPhysics.positiveYVelocityCap)
    ⋮
    6760                velocity = DIV_SHIFT(gSamusPhysics.positiveYVelocityCap, 8);
    ⋮
    6766            else
    ⋮
    6768                velocity = DIV_SHIFT(pData->yVelocity, 8);
    ⋮
    6771            if (pData->yVelocity >= -231)
    ⋮
    6773                pData->yVelocity -= gSamusPhysics.yAcceleration;
    ⋮
    6776            pData->yPosition -= velocity;
    
    src/samus.c lines 6758–6776 at 2aae289 · upstream ↗

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

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

    In the claim ledger

  8. ^On any frame Samus rises (yVelocity above 0) without A held, the mid-air handlers set yVelocity to 0, at any height: SamusMidAir, SamusTurningAroundMidAir, and SamusSpinning, which runs the spin jump, the Space Jump, and the Screw Attack. The check is each handler's last step, so a frame whose earlier branch returns, such as a Space Jump or wall jump press, skips it. Metroid lets a release stop the rise only after 32 px.Codemetroidret/mzm · nmikstas/metroid-disassembly
    How we know
    4572    // Check turning
    4573    if (turning)
    4574        return SPOSE_TURNING_AROUND_MIDAIR;
    ⋮
    4576    // Check terminate Y velocity if not pressing A and going up
    4577    if (!(gButtonInput & KEY_A) && pData->yVelocity > 0)
    4578        pData->yVelocity = 0;
    
    src/samus.c lines 4572–4578 at 2aae289 · upstream ↗
    4645    // Check terminate Y velocity if not pressing A and going up
    4646    if (!(gButtonInput & KEY_A) && pData->yVelocity > 0)
    4647        pData->yVelocity = 0;
    
    src/samus.c lines 4645–4647 at 2aae289 · upstream ↗
    4774    // Check terminate Y velocity if not pressing A and going up
    4775    if (!(gButtonInput & KEY_A) && pData->yVelocity > 0)
    4776        pData->yVelocity = 0;
    
    src/samus.c lines 4774–4776 at 2aae289 · upstream ↗
    36    [SPOSE_MIDAIR] = SamusMidAir,
    37    [SPOSE_TURNING_AROUND_MIDAIR] = SamusTurningAroundMidAir,
    ⋮
    39    [SPOSE_STARTING_SPIN_JUMP] = SamusSpinning,
    40    [SPOSE_SPINNING] = SamusSpinning,
    ⋮
    42    [SPOSE_SPACE_JUMPING] = SamusSpinning,
    43    [SPOSE_SCREW_ATTACKING] = SamusSpinning,
    
    src/samus.c lines 36–43 at 2aae289 · upstream ↗
    4716    if (gEquipment.suitMiscActivation & SMF_SPACE_JUMP && !gSamusPhysics.slowedByLiquid)
    ⋮
    4718        // Check can space jump
    4719        if (gChangedInput & KEY_A && pData->yVelocity <= -SUB_PIXEL_TO_VELOCITY(EIGHTH_BLOCK_SIZE))
    ⋮
    4726            return SPOSE_NONE;
    
    src/samus.c lines 4716–4726 at 2aae289 · upstream ↗
    2701SamusJump:
    2702        LDA SamusJmpDsplcmnt
    2703        BIT ObjVertSpeed
    2704        BPL +      ; branch if falling down
    2705        CMP #$20
    2706        BCC +      ; branch if jumped less than 32 pixels upwards
    2707        BIT Joy1Status
    2708        BMI +      ; branch if JUMP button still pressed
    2709        JSR StopVertMovement        ;($D147)Stop jump (start falling).
    
    Source_Files/Bank07.asm lines 2701–2709 at 4270d57 · upstream ↗

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

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

    In the claim ledger

  9. ^When a spin jump or Screw Attack touches a wall, SamusCheckCollisions sets walljumpTimer to 8 and stores the direction away from the wall. Each time SamusSpinning runs, unless the Space Jump is active and Samus isn't slowed (slowedByLiquid), it takes 1 from a nonzero timer, and if Samus faces away from the wall, a new A press, with a solid block 10 px (40 subpixels) to the wall's side, starts a wall jump. The jump takes off at the normal or High Jump speed (mzm/jump-speed). Metroid takes a jump press in the air only in lava (metroid-samus/no-air-jump), so it has no wall jump.Codemetroidret/mzmrevised
    How we know
    1109            case SPOSE_SPINNING:
    1110            case SPOSE_SCREW_ATTACKING:
    1111                pData->walljumpTimer = 8;
    1112                pData->lastWallTouchedMidAir = pData->direction ^ (KEY_RIGHT | KEY_LEFT);
    
    src/samus.c lines 1109–1112 at 2aae289 · upstream ↗
    4716    if (gEquipment.suitMiscActivation & SMF_SPACE_JUMP && !gSamusPhysics.slowedByLiquid)
    ⋮
    4723            else
    ⋮
    4729    else
    ⋮
    4731        // Check can wall jump
    4732        if (pData->walljumpTimer != 0)
    ⋮
    4734            pData->walljumpTimer--;
    ⋮
    4736            // Holding correct direction and pressed A
    4737            if (pData->direction & pData->lastWallTouchedMidAir)
    ⋮
    4739                if (gChangedInput & KEY_A)
    ⋮
    4741                    // Get check offset
    4742                    if (pData->lastWallTouchedMidAir & KEY_RIGHT)
    4743                        xOffset = -(HALF_BLOCK_SIZE + EIGHTH_BLOCK_SIZE);
    ⋮
    
    src/samus.c lines 4716–4751 at 2aae289 · upstream ↗
    4760    // Check turn
    4761    if (gButtonInput & (OPPOSITE_DIRECTION(pData->direction)))
    ⋮
    4763        pData->direction ^= KEY_RIGHT | KEY_LEFT;
    
    src/samus.c lines 4760–4763 at 2aae289 · upstream ↗
    1739            // Perform wall jump, set spinning
    1740            pData->pose = SPOSE_SPINNING;
    ⋮
    1742            if (pCopy->forcedMovement == FORCED_MOVEMENT_MID_AIR_JUMP)
    ⋮
    1744                if (pEquipment->suitMiscActivation & SMF_HIGH_JUMP)
    1745                    pData->yVelocity = SAMUS_HIGH_JUMP_VELOCITY;
    1746                else
    1747                    pData->yVelocity = SAMUS_LOW_JUMP_VELOCITY;
    
    src/samus.c lines 1739–1747 at 2aae289 · upstream ↗

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

    Revised after a check by a second AI model, 2026-10-22.

    In the claim ledger

  10. ^Once Samus is airborne, the run and jump handlers start a jump only while she is in lava. Walking off a ledge makes her airborne at once: VertAccelerate sets the falling gravity on the first frame with nothing below her.Codenmikstas/metroid-disassembly
    How we know
    2252SamusRun:
    2253LCCC2:  ldx SamusDir
    2254    lda SamusGravity
    2255    beq +++++++
    
    Source_Files/Bank07.asm lines 2252–2255 at 4270d57 · upstream ↗
    2286*   lda SamusInLava
    2287    beq +
    2288    lda Joy1Change
    2289    bmi LCD40       ; branch if JUMP pressed
    
    Source_Files/Bank07.asm lines 2286–2289 at 4270d57 · upstream ↗
    2720        LDA SamusInLava
    2721        BEQ +
    2722        LDA Joy1Change
    2723        BPL +      ; branch if JUMP not pressed
    2724        JSR LCFC3
    
    Source_Files/Bank07.asm lines 2719–2724 at 4270d57 · upstream ↗
    5590LE37A:  lda SamusGravity        ;Is Samus rising or falling?
    ⋮
    5599LE38F:  jsr CheckMoveDown       ;($E7AD)Is Samus obstructed downwards?
    ⋮
    5606LE3A0:  lda #$1A            ;Samus is falling. Store falling gravity value.
    5607LE3A2:  sta SamusGravity        ;
    
    Source_Files/Bank07.asm lines 5590–5607 at 4270d57 · 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