Metroid: Zero Mission
Nintendo R&D1's 2004 Game Boy Advance remake of Metroid, read through metroidret's decompilation of the US release.
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
| Mechanic | Kind | How |
|---|---|---|
| Health upgrade | Whole containers | energy tanks of 100, or 50 on Hard, from 99 at the start, each refilling her energy |
| Ammunition | Several pools | missiles, super missiles, and power bombs, 5, 2, and 2 per tank, or 2, 1, and 1 on Hard |
| Jump | Speed by state | 6 px/frame up, 7.25 with the High Jump, 6.625 without the suit |
| Gravity | One gravity | 0.3125 px/frame² in air, held or not, halved in liquid without the Gravity Suit |
| Variable jump height | Release cap | letting go during the rise sets the vertical speed to 0 at any height |
| Wall jump | Push off from a spin | from a spin jump, facing away within 8 frames of touching a wall |
Every claim about this game, by concept (9)
References
- ^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/mzmHow 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.gbaREADME.md line 21 at 2aae289 · upstream ↗ 15de8536afe1f0078ee6fe1089f890e8c7aa0a6e8 mzm_us.gbamzm_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.
- ^ abWhen a game starts rather than loads a file (
gIsLoadingFileclear),SamusInitfillsgEquipmentwith 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-disassemblyHow 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.
- ^ 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.
- ^ 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.
- ^ abA jump sets Samus's upward
yVelocityto 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-disassemblyrevisedHow 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 192include/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.
- ^ abOut of liquid (or in it with the Gravity Suit) and not held by a Metroid,
SamusUpdatePhysicssets the vertical acceleration to 10 each frame, andSamusUpdateVelocityPositiontakes it fromyVelocityon 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-disassemblyHow 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.
- ^ 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
yVelocitycapped at 192 and shifted right 3, then takes 10 from it).Codemetroidret/mzmHow 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.
- ^On any frame Samus rises (
yVelocityabove 0) without A held, the mid-air handlers setyVelocityto 0, at any height:SamusMidAir,SamusTurningAroundMidAir, andSamusSpinning, 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-disassemblyHow 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.
- ^When a spin jump or Screw Attack touches a wall,
SamusCheckCollisionssetswalljumpTimerto 8 and stores the direction away from the wall. Each timeSamusSpinningruns, 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/mzmrevisedHow 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.
- ^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:
VertAcceleratesets the falling gravity on the first frame with nothing below her.Codenmikstas/metroid-disassemblyHow 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.
Sources
Code
- metroidret contributors. 2026. “mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm).” Commit 2aae289. metroidret/mzm @ 2aae289 · licence, all uses
- nmikstas and Kent Hansen. 2025. “metroid-disassembly: Metroid software disassembly.” Commit 4270d57. nmikstas/metroid-disassembly @ 4270d57 · licence, all uses