data/claims/mzm.yamlMetroid - Zero Mission (metroidret's decompilation of the US release)
Game: Metroid: Zero Mission.
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. mzm/build
README.md#L9-L12This repository can be used to build multiple ROMs. The ROMs are named like this: `mzm_{region}.gba` (or `mzm_{region}_debug.gba`)
…
- us: USA, North America `sha1: 5de8536afe1f0078ee6fe1089f890e8c7aa0a6e8`mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · README.md#L21The default built ROM is mzm_us.gbamzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · mzm_us.sha1#L15de8536afe1f0078ee6fe1089f890e8c7aa0a6e8 mzm_us.gbaChecked by claude-agent, 2026-10-22 — read the README and mzm_us.sha1, and ran sha1sum on /data/roms/gba/Metroid - Zero Mission (USA).gba, which gives the same hashCited by: Metroid: Zero Mission
When 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. mzm/start-energy
About: Metroid: Zero Mission Health upgrade
Value: 99 energy
Codemzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) ·src/samus.c#L8071-L8088if (!gIsLoadingFile)
{
// Zero out most of samus's data
DMA3_FILL_32(0, &gSamusData, sizeof(gSamusData));
DMA3_FILL_32(0, &gEquipment, sizeof(gEquipment));
…
// Set starting info
gSamusData.pose = SPOSE_FACING_THE_FOREGROUND;
gSamusData.direction = KEY_LEFT;
…
gEquipment.maxEnergy = 99;
gEquipment.currentEnergy = 99;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · include/structs/samus.h#L16-L24struct Equipment {
u16 maxEnergy;
u16 maxMissiles;
u8 maxSuperMissiles;
u8 maxPowerBombs;
u16 currentEnergy;
u16 currentMissiles;
u8 currentSuperMissiles;
u8 currentPowerBombs;metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L1580-L1583LDA #$00 ;
STA HealthLo ;Starting health is
LDA #$03 ;set to 30 units.
STA HealthHi ;Checked by claude-agent, 2026-10-22 — read SamusInit to its end (the zeroing and the 99 sit under gSubGameMode3 == 0 and !gIsLoadingFile; a loaded file takes gEquipment from the save, save_file.c's `gEquipment = pFile->equipment`), the Equipment struct, and Metroid's SamusInit lines already cited by metroid/start-healthsStartingHealthAmmo in src/data/block_data.c holds the same starting values (99 energy, 0 of each ammunition) for the tank caps and the pause screen's debug menu. The game counts energy in whole units, where Metroid's health is binary-coded decimal in tenths (metroid/health-format).
Cited by: Health upgrade, Metroid: Zero Mission
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. mzm/energy-tank
About: Metroid: Zero Mission Health upgrade
Value
{
"easy": 100,
"normal": 100,
"hard": 50
}src/bg_clip.c#L531-L537else if (i == ITEM_TYPE_ENERGY)
{
if (sNumberOfTanksPerArea[MAX_AMOUNT_OF_AREAS - 1].energy * sTankIncreaseAmount[gDifficulty].energy + sStartingHealthAmmo.energy >= gEquipment.maxEnergy + sTankIncreaseAmount[gDifficulty].energy)
{
gEquipment.maxEnergy += sTankIncreaseAmount[gDifficulty].energy;
gEquipment.currentEnergy = gEquipment.maxEnergy;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/data/block_data.c#L52-L53[MAX_AMOUNT_OF_AREAS - 1] = {
.energy = 12,mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/data/block_data.c#L60-L81const struct TankList sStartingHealthAmmo = {
.energy = 99,
…
const struct TankList sTankIncreaseAmount[DIFF_COUNT] = {
[DIFF_EASY] = {
.energy = 100,
…
[DIFF_NORMAL] = {
.energy = 100,
…
[DIFF_HARD] = {
.energy = 50,metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L4354-L4363LDC00:* LDA TankCount ;
LDC03: CMP #$06 ;Has Samus got 6 energy tanks?
LDC05: BEQ + ;If so, she can't have any more.
LDC07: INC TankCount ;Otherwise give her a new tank.
LDC0A:* LDA TankCount ;
LDC0D: JSR Amul16 ;Get tank count and shift into upper nibble.
LDC10: ORA #$09 ;
LDC12: STA HealthHi ;Set new tank count. Upper health digit set to 9.
LDC15: LDA #$99 ;Max out low health digit.
LDC17: STA HealthLo ;Health is now FULL!Checked by claude-agent, 2026-10-22 — read the tank branch of the block-touch code in bg_clip.c and the three tables in block_data.c. Row MAX_AMOUNT_OF_AREAS - 1 is index 7 (MAX_AMOUNT_OF_AREAS is 8, Chozodia is 6), and its 12 equals the sum of the seven area rows (3, 2, 1, 3, 0, 0, 3). With maxEnergy starting at 99 and rising by whole tanks, the test fails first for a 13th tank: 12 x 100 + 99 = 1299, 12 x 50 + 99 = 699. Metroid's side is metroid/energy-tank and metroid/max-healthThe atlas reads row 7 of sNumberOfTanksPerArea as the game's totals, since the code uses it only as a cap and it sums the area rows. The pause screen's debug menu writes the maximum directly and skips this test.
Cited by: Health upgrade, Metroid: Zero Mission
Missiles, 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. mzm/ammo-tanks
About: Metroid: Zero Mission Ammunition
Value
{
"missile": [
5,
2
],
"superMissile": [
2,
1
],
"powerBomb": [
2,
1
]
}src/bg_clip.c#L520-L528if (i == ITEM_TYPE_MISSILE)
{
if (sNumberOfTanksPerArea[MAX_AMOUNT_OF_AREAS - 1].missile * sTankIncreaseAmount[gDifficulty].missile + sStartingHealthAmmo.missile >= gEquipment.maxMissiles + sTankIncreaseAmount[gDifficulty].missile)
{
if (gEquipment.maxMissiles == 0)
isFirstTank = TRUE;
…
gEquipment.maxMissiles += sTankIncreaseAmount[gDifficulty].missile;
gEquipment.currentMissiles += sTankIncreaseAmount[gDifficulty].missile;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/bg_clip.c#L539-L558else if (i == ITEM_TYPE_SUPER_MISSILE)
…
gEquipment.maxSuperMissiles += sTankIncreaseAmount[gDifficulty].superMissile;
gEquipment.currentSuperMissiles += sTankIncreaseAmount[gDifficulty].superMissile;
…
else if (i == ITEM_TYPE_POWER_BOMB)
…
gEquipment.maxPowerBombs += sTankIncreaseAmount[gDifficulty].powerBomb;
gEquipment.currentPowerBombs += sTankIncreaseAmount[gDifficulty].powerBomb;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/data/block_data.c#L52-L54[MAX_AMOUNT_OF_AREAS - 1] = {
.energy = 12,
.missile = 50,mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/data/block_data.c#L67-L84const struct TankList sTankIncreaseAmount[DIFF_COUNT] = {
[DIFF_EASY] = {
.energy = 100,
.missile = 5,
.superMissile = 2,
.powerBomb = 2
},
[DIFF_NORMAL] = {
.energy = 100,
.missile = 5,
.superMissile = 2,
.powerBomb = 2
…metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L4349-L4351LDBF7:* BEQ + ;Branch if item is an energy tank.
LDBF9: LDA #$05 ;
LDBFB: JSR AddToMaxMissiles ;($DD97)Increase missile capacity by 5.metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L4635-L4650; Adds A to both MissileCount & MaxMissiles, storing the new count
…
ADC MissileCount
…
* STA MissileCount
…
ADC MaxMissiles
…
* STA MaxMissilesChecked by claude-agent, 2026-10-22 — read the four tank branches in bg_clip.c and sTankIncreaseAmount; the missile cap is 50 x 5 + 0 = 250 and 50 x 2 + 0 = 100. Row 7's 50 equals the sum of the area rows (10, 9, 13, 13, 1, 3, 1). Metroid's side is metroid/missile-tank, plus AddToMaxMissiles, which adds the same 5 to MissileCount and MaxMissiles (each capped at 255)The first tank of each ammunition (a maximum of 0 before it) sets isFirstTank, which adds 1 to the banner's message id, from MESSAGE_MISSILE_TANK_ACQUIRED to MESSAGE_FIRST_MISSILE_TANK and likewise for the other two (bg_clip.c line 563; the names are the decompilers').
Cited by: Ammunition, Metroid: Zero Mission
A 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. mzm/jump-speed
About: Metroid: Zero Mission Jump
Value
[ 6, 7.25 ]
src/samus.c#L1863-L1877if (pCopy->forcedMovement == FORCED_MOVEMENT_MID_AIR_JUMP)
{
// Set mid air pose, spinning if holding a sideways direction
if (gButtonInput & (KEY_RIGHT | KEY_LEFT))
pData->pose = SPOSE_STARTING_SPIN_JUMP;
else
pData->pose = SPOSE_MIDAIR;
…
// Set Y velocity
if (pEquipment->suitType == SUIT_SUITLESS)
pData->yVelocity = SAMUS_SUITLESS_JUMP_VELOCITY;
else if (pEquipment->suitMiscActivation & SMF_HIGH_JUMP)
…mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L1700-L1709// Starting a jump, always a spin jump because running implies a direction was held
pData->pose = SPOSE_STARTING_SPIN_JUMP;
…
// Set jump velocity
if (pEquipment->suitType == SUIT_SUITLESS)
pData->yVelocity = SAMUS_SUITLESS_JUMP_VELOCITY;
else if (pEquipment->suitMiscActivation & SMF_HIGH_JUMP)
pData->yVelocity = SAMUS_HIGH_JUMP_VELOCITY;
else
pData->yVelocity = SAMUS_LOW_JUMP_VELOCITY;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · include/constants/samus.h#L336-L338#define SAMUS_HIGH_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + PIXEL_SIZE * 3 + ONE_SUB_PIXEL))
#define SAMUS_LOW_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + EIGHTH_BLOCK_SIZE))
#define SAMUS_SUITLESS_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + EIGHTH_BLOCK_SIZE + PIXEL_SIZE / 2 + ONE_SUB_PIXEL / 2.f))mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · include/constants/samus.h#L314-L315#define VELOCITY_TO_SUB_PIXEL(velocity) (DIV_SHIFT((velocity), 8))
#define SUB_PIXEL_TO_VELOCITY(velocity) ((s16)((velocity) * 8))mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · include/types.h#L47-L65// The amount of sub pixels a single visible pixel contains
#define SUB_PIXEL_RATIO 4
// The amount of visible pixels a block contains
#define PIXEL_PER_BLOCK 16
…
#define BLOCK_SIZE (PIXEL_PER_BLOCK * SUB_PIXEL_RATIO)
…
#define QUARTER_BLOCK_SIZE (BLOCK_SIZE / 4)
…
#define EIGHTH_BLOCK_SIZE (BLOCK_SIZE / 8)
…
#define PIXEL_SIZE (BLOCK_SIZE / PIXEL_PER_BLOCK)
…mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L6758-L6776if (pData->yVelocity > gSamusPhysics.positiveYVelocityCap)
{
velocity = DIV_SHIFT(gSamusPhysics.positiveYVelocityCap, 8);
}
…
else
{
velocity = DIV_SHIFT(pData->yVelocity, 8);
}
…
pData->yPosition -= velocity;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · include/constants/samus.h#L325#define SAMUS_Y_POSITIVE_VELOCITY_CAP 192metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L2672-L2698SetSamusJump:
…
LDA #$FC
STA ObjVertSpeed
…
LCFF3: LDY #$18 ; gravity (high value -> low jump)
LDA SamusGear
AND #gr_HIGHJUMP
BEQ + ; branch if Samus doesn't have High Jump
LDY #$12 ; lower gravity value -> high jump!
* STY SamusGravityChecked by claude-agent, 2026-10-22 — read SamusSetMidAir's running-jump and default (standing) cases and the constants. BLOCK_SIZE is 64 subpixels, so the low jump is (16 + 8) x 8 = 192, the High Jump (16 + 12 + 1) x 8 = 232, and the suitless jump (16 + 8 + 2 + 0.5) x 8 = 212; dividing by 8 x 4 = 32 gives px/frame. SamusUpdateVelocityPosition moves Samus by the capped value shifted right 3 (in subpixels) and only then lowers yVelocity by 10, so 232, 222, 212, 202, and 192 each move 24 subpixels. positiveYVelocityCap is 192 out of liquid (SamusUpdatePhysics; mzm/gravity). Metroid's side is metroid-samus/jump-speedThe wall jump also takes the low or High Jump speed (src/samus.c lines 1742-1747, with no suitless case). Samus in the Morph Ball jumps at SAMUS_MORPH_BALL_JUMP_VELOCITY, the same 212. SamusUpdate runs once per frame of play, unless an item pickup's gPreventMovementTimer is running (src/in_game.c).
Cited by: Jump, Metroid: Zero Mission
Out 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. mzm/gravity
About: Metroid: Zero Mission Gravity
Value: 0.3125 px/frame²
Codemzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) ·include/constants/samus.h#L324-L327#define SAMUS_Y_ACCELERATION 10
#define SAMUS_Y_POSITIVE_VELOCITY_CAP 192
#define SAMUS_Y_NEGATIVE_VELOCITY_CAP 128
#define SAMUS_Y_SLOWED_VELOCITY_CAP 40mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L2649-L2697case HAZARD_TYPE_WATER:
case HAZARD_TYPE_LAVA:
case HAZARD_TYPE_WEAK_ACID:
case HAZARD_TYPE_STRONG_ACID:
// In liquid, check has gravity to see if slowed
if (!(pEquipment->suitMiscActivation & SMF_GRAVITY_SUIT))
slowed++;
#ifndef BUGFIX
break;
#endif
…
default:
…mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L6762-L6776else if (pData->yVelocity < -gSamusPhysics.negativeYVelocityCap)
{
velocity = DIV_SHIFT(-gSamusPhysics.negativeYVelocityCap, 8);
}
…
if (pData->yVelocity >= -231)
{
pData->yVelocity -= gSamusPhysics.yAcceleration;
}
…
pData->yPosition -= velocity;metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L2693-L2698LCFF3: LDY #$18 ; gravity (high value -> low jump)
LDA SamusGear
AND #gr_HIGHJUMP
BEQ + ; branch if Samus doesn't have High Jump
LDY #$12 ; lower gravity value -> high jump!
* STY SamusGravitymetroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L5582-L5587;gravity used in the acceleration calculation. The higher the number, the more intense the gravity.
;The possible values for gravity are as follows:
;#$38-When Samus has been hit by an enemy.
;#$1A-When Samus is falling.
;#$18-Jump without high jump boots.
;#$12-Jump with high jump boots.metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L5628-L5629LE3C9:* cmp #$05 ;Has maximum downward speed been reached?
LE3CB:* bcc + ;If not, branch.Checked by claude, 2026-10-25 — read SamusUpdatePhysics, which SamusUpdate calls first every frame, and the airborne poses' branch of SamusUpdateVelocityPosition; 10 / 32 = 0.3125, 128 / 32 = 4, and 40 / 32 = 1.25. Nothing in SamusMidAir or SamusSpinning changes yAcceleration. Metroid's side is metroid-samus/gravity: the jump stores $18, or $12 with the High Jump Boots, at LCFF3, and VertAccelerate caps a fall at 5The liquid cases end in a break that only a BUGFIX build drops, so in the US build a Metroid's grip slows Samus only out of liquid, where the default case checks grabbedByMetroid. A shinespark or ballspark moves her by its own yVelocity with no gravity, and SamusGettingHurt can set the acceleration to 0.
Cited by: Gravity, Metroid: Zero Mission
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). mzm/jump-height
About: Metroid: Zero Mission Jump
Value
[ 58.75, 82.75 ]
include/constants/samus.h#L324-L337#define SAMUS_Y_ACCELERATION 10
#define SAMUS_Y_POSITIVE_VELOCITY_CAP 192
…
#define SAMUS_HIGH_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + PIXEL_SIZE * 3 + ONE_SUB_PIXEL))
#define SAMUS_LOW_JUMP_VELOCITY (SUB_PIXEL_TO_VELOCITY(QUARTER_BLOCK_SIZE + EIGHTH_BLOCK_SIZE))mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L6758-L6776if (pData->yVelocity > gSamusPhysics.positiveYVelocityCap)
{
velocity = DIV_SHIFT(gSamusPhysics.positiveYVelocityCap, 8);
}
…
else
{
velocity = DIV_SHIFT(pData->yVelocity, 8);
}
…
if (pData->yVelocity >= -231)
{
…Checked by claude-agent, 2026-10-22 — a Python loop over the frames from take-off, velocity v from 192 (or 232): move by min(v, 192) >> 3 subpixels, then v -= 10, until the move is 0 or less; the rise sums to 235 and 331 subpixels, divided by 4 for pixels. It assumes nothing else touches yVelocity on the way up (no release, ceiling, or liquid)Not yet measured in the ROM. The shift drops the fraction each frame, so the rise is a little less than v²/2g.
Cited by: Metroid: Zero Mission
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. mzm/release-cap
About: Metroid: Zero Mission Variable jump height
Value: 0 velocity after release
Codemzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) ·src/samus.c#L4572-L4578// Check turning
if (turning)
return SPOSE_TURNING_AROUND_MIDAIR;
…
// Check terminate Y velocity if not pressing A and going up
if (!(gButtonInput & KEY_A) && pData->yVelocity > 0)
pData->yVelocity = 0;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L4645-L4647// Check terminate Y velocity if not pressing A and going up
if (!(gButtonInput & KEY_A) && pData->yVelocity > 0)
pData->yVelocity = 0;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L4774-L4776// Check terminate Y velocity if not pressing A and going up
if (!(gButtonInput & KEY_A) && pData->yVelocity > 0)
pData->yVelocity = 0;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L36-L43[SPOSE_MIDAIR] = SamusMidAir,
[SPOSE_TURNING_AROUND_MIDAIR] = SamusTurningAroundMidAir,
…
[SPOSE_STARTING_SPIN_JUMP] = SamusSpinning,
[SPOSE_SPINNING] = SamusSpinning,
…
[SPOSE_SPACE_JUMPING] = SamusSpinning,
[SPOSE_SCREW_ATTACKING] = SamusSpinning,mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L4716-L4726if (gEquipment.suitMiscActivation & SMF_SPACE_JUMP && !gSamusPhysics.slowedByLiquid)
{
// Check can space jump
if (gChangedInput & KEY_A && pData->yVelocity <= -SUB_PIXEL_TO_VELOCITY(EIGHTH_BLOCK_SIZE))
{
…
return SPOSE_NONE;metroid-disassembly: Metroid software disassembly · Source_Files/Bank07.asm#L2701-L2709SamusJump:
LDA SamusJmpDsplcmnt
BIT ObjVertSpeed
BPL + ; branch if falling down
CMP #$20
BCC + ; branch if jumped less than 32 pixels upwards
BIT Joy1Status
BMI + ; branch if JUMP button still pressed
JSR StopVertMovement ;($D147)Stop jump (start falling).Checked by claude-agent, 2026-10-22 — read the three handlers' ends and the pose-handler table; the handler runs before SamusUpdateVelocityPosition in SamusUpdate, so a zeroed velocity moves Samus 0 that frame. The button is KEY_A in the code, not a reassignable one. Metroid's side is metroid-samus/release-capThe Morph Ball's mid-air handler, SamusMorphballMidAir, has the same test inside one of its branches (src/samus.c line 5231), not read here in full.
Cited by: Metroid: Zero Mission, Variable jump height
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. mzm/wall-jump
About: Metroid: Zero Mission Wall jump
Value: 8 frames of the spin handler after the last wall touch
Codemzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) ·src/samus.c#L1109-L1112case SPOSE_SPINNING:
case SPOSE_SCREW_ATTACKING:
pData->walljumpTimer = 8;
pData->lastWallTouchedMidAir = pData->direction ^ (KEY_RIGHT | KEY_LEFT);mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L4716-L4751if (gEquipment.suitMiscActivation & SMF_SPACE_JUMP && !gSamusPhysics.slowedByLiquid)
…
else
{
// Check can wall jump
if (pData->walljumpTimer != 0)
{
pData->walljumpTimer--;
…
// Holding correct direction and pressed A
if (pData->direction & pData->lastWallTouchedMidAir)
{
…mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L4760-L4763// Check turn
if (gButtonInput & (OPPOSITE_DIRECTION(pData->direction)))
{
pData->direction ^= KEY_RIGHT | KEY_LEFT;mzm: a decompilation of Metroid: Zero Mission (metroidret/mzm) · src/samus.c#L1739-L1747// Perform wall jump, set spinning
pData->pose = SPOSE_SPINNING;
…
if (pCopy->forcedMovement == FORCED_MOVEMENT_MID_AIR_JUMP)
{
if (pEquipment->suitMiscActivation & SMF_HIGH_JUMP)
pData->yVelocity = SAMUS_HIGH_JUMP_VELOCITY;
else
pData->yVelocity = SAMUS_LOW_JUMP_VELOCITY;Checked by claude-agent, 2026-10-22 — read the touchingSideBlock switch in SamusCheckCollisions, SamusSpinning from its Space Jump test to the turn, and SamusSetMidAir's SPOSE_STARTING_WALL_JUMP case. Facing is pData->direction, which the turn at the end of SamusSpinning flips when the opposite direction is held, so in play the player holds away from the wall. HALF_BLOCK_SIZE + EIGHTH_BLOCK_SIZE is 32 + 8 = 40 subpixels. slowedByLiquid is set in liquid without the Gravity Suit or in a Metroid's grip (mzm/gravity); the half-speed liquid jump is lines 1750-1753. The no-wall-jump side is metroid-samus/no-air-jumpSamusStartingWallJump drops Samus instead if she fires or holds up or down without a side direction; in liquid the wall jump takes off at half the High Jump speed. While the timer runs and she faces away, SamusSpinning cuts her mid-air acceleration to 1.
Cited by: Metroid: Zero Mission, Wall jump