Super Mario 64
Nintendo's 1996 3D platformer for the Nintendo 64, read through the n64decomp decompilation.
On this page
The atlas reads Super Mario 64 through the n64decomp team’s decompilation, C that compiles to the original ROMs byte for byte. Names and comments quoted here are theirs, and the claims cite the code the US build compiles. Nothing has been measured in the game yet.
Speeds are floats in world units per frame, and a frame waits for two vertical blanks, at most 30 a second on an NTSC console1. A jump takes off at 42 + forward speed × 0.252,2, under a gravity of 4 units/frame²3,3. Letting go of A while Mario still rises fast quarters his upward speed4.
A press during a landing chains a higher jump: the double jump5, then the triple jump if Mario runs fast enough6. The long jump trades height for 1.5 times the forward speed7, and its cap misses backward speeds, the cause of the backwards long jump8. A wall kick has a 7-frame window9, and the ground pound stops Mario in the air before dropping him10.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Jump | Speed from the run | 42 units/frame plus a quarter of the forward speed, with a double and a triple jump chained from landings |
| Gravity | One gravity | 4 units/frame² in most jumps and 2 in the long jump, down to −75 |
| Variable jump height | Release cut | letting go above 20 units/frame quarters the rise at once; the triple jump, backflip, and side flip can't be cut |
| Running | Analog | the stick's tilt sets a target speed of up to 32 units/frame, approached by 1.1 − speed/43 a frame |
| Wall jump | Kick | a wall hit at speed holds Mario against it, and A within 7 frames kicks him off at 62 units/frame up |
| Triple jump | Landing chain | a press during a landing chains 42, 52, then 69 units/frame, the third above 20 forward |
| Long jump | From a crouch slide | A from a crouch slide: 30 units/frame up and 1.5 times the forward speed, capped at 48 only going forward |
| Ground pound | Hover then drop | Z in the air: a short rise and hold, then a fall from −50 units/frame |
Every claim about this game, by concept (11)
References
- ^Super Mario 64 keeps Mario's speeds as floats in world units per frame:
perform_air_stepmoves him a quarter of his velocity in each of four quarter steps. A frame waits for two vertical blanks indisplay_and_vsync, so on an NTSC console the game runs at most 30 frames a second.Coden64decomp/sm64revisedHow we know
618 for (i = 0; i < 4; i++) { 619 intendedPos[0] = m->pos[0] + m->vel[0] / 4.0f; 620 intendedPos[1] = m->pos[1] + m->vel[1] / 4.0f; 621 intendedPos[2] = m->pos[2] + m->vel[2] / 4.0f;
src/game/mario_step.c lines 618–621 at 9921382 · upstream ↗ 372 osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK); 373 osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[sRenderedFramebuffer])); ⋮ 375 osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
src/game/game_init.c lines 372–375 at 9921382 · upstream ↗ 428#if defined(VERSION_US) || defined(VERSION_SH) || defined(VERSION_CN) 429 if (sp24 == TV_TYPE_NTSC) { 430 osViSetMode(&osViModeTable[OS_VI_NTSC_LAN1]);
src/game/main.c lines 428–433 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^ abA single jump sets Mario's vertical speed to 42 plus a quarter of his forward speed, in units per frame, and multiplies the forward speed by 0.8.Coden64decomp/sm64
How we know
763static void set_mario_y_vel_based_on_fspeed(struct MarioState *m, f32 initialVelY, f32 multiplier) { ⋮ 766 m->vel[1] = initialVelY + get_additive_y_vel_for_jumps() + m->forwardVel * multiplier;
src/game/mario.c lines 763–766 at 9921382 · upstream ↗ 821 case ACT_JUMP: 822 case ACT_HOLD_JUMP: ⋮ 824 set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.25f); 825 m->forwardVel *= 0.8f;
src/game/mario.c lines 821–826 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abMario's usual gravity subtracts 4 units/frame from his vertical speed each frame, down to a fastest fall of −75. The long jump and the slide kick use 2 instead, with the same cap.Coden64decomp/sm64
How we know
575 } else { 576 m->vel[1] -= 4.0f; 577 if (m->vel[1] < -75.0f) { 578 m->vel[1] = -75.0f;
src/game/mario_step.c lines 575–580 at 9921382 · upstream ↗ 543 } else if (m->action == ACT_LONG_JUMP || m->action == ACT_SLIDE_KICK 544 || m->action == ACT_BBH_ENTER_SPIN) { 545 m->vel[1] -= 2.0f; 546 if (m->vel[1] < -75.0f) {
src/game/mario_step.c lines 543–548 at 9921382 · upstream ↗ 646 if (m->action != ACT_FLYING) { 647 apply_gravity(m);
src/game/mario_step.c lines 646–648 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^Releasing A cuts a jump short: on a frame with A up and the rise above 20 units/frame,
apply_gravitydivides the vertical speed by 4 instead of subtracting gravity. Only actions flaggedACT_FLAG_CONTROL_JUMP_HEIGHTdo this, among them the single and double jumps and the wall kick; the triple jump, backflip, and side flip lack the flag and keep their full height. The check also needs a flag that every airborne action sets and bouncing off an enemy clears.Coden64decomp/sm64revisedHow we know
519u32 should_strengthen_gravity_for_jump_ascent(struct MarioState *m) { 520 if (!(m->flags & MARIO_UNKNOWN_08)) { 521 return FALSE; ⋮ 525 return FALSE; ⋮ 528 if (!(m->input & INPUT_A_DOWN) && m->vel[1] > 20.0f) { 529 return (m->action & ACT_FLAG_CONTROL_JUMP_HEIGHT) != 0; ⋮ 532 return FALSE;
src/game/mario_step.c lines 519–533 at 9921382 · upstream ↗ 559 } else if (should_strengthen_gravity_for_jump_ascent(m)) { 560 m->vel[1] /= 4.0f;
src/game/mario_step.c lines 559–560 at 9921382 · upstream ↗ 256#define ACT_JUMP 0x03000880 // (0x080 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT) 257#define ACT_DOUBLE_JUMP 0x03000881 // (0x081 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT) 258#define ACT_TRIPLE_JUMP 0x01000882 // (0x082 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) 259#define ACT_BACKFLIP 0x01000883 // (0x083 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) ⋮ 261#define ACT_WALL_KICK_AIR 0x03000886 // (0x086 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT) 262#define ACT_SIDE_FLIP 0x01000887 // (0x087 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) 263#define ACT_LONG_JUMP 0x03000888 // (0x088 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
include/sm64.h lines 256–263 at 9921382 · upstream ↗ 887 m->peakHeight = m->pos[1]; 888 m->flags |= MARIO_UNKNOWN_08;
src/game/mario.c lines 887–888 at 9921382 · upstream ↗ 515void bounce_off_object(struct MarioState *m, struct Object *o, f32 velY) { ⋮ 519 m->flags &= ~MARIO_UNKNOWN_08;
src/game/interaction.c lines 515–519 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^A press while Mario lands from a jump or a fall starts a double jump, at 52 units/frame plus a quarter of his forward speed. The landing lasts 4 frames, and each of them sets
doubleJumpTimerto 5; that timer counts down once a frame, and while it runs a press from the stop action that follows the landing still double-jumps, becauseset_jump_from_landingchecks the timer and the previous action. With the stick held, the stop action turns into walking at once, and walking's previous action is the stop, so only a Mario standing still can double-jump after the 4-frame landing.Coden64decomp/sm64revisedHow we know
785 case ACT_DOUBLE_JUMP: 786 set_mario_y_vel_based_on_fspeed(m, 52.0f, 0.25f); 787 m->forwardVel *= 0.8f;
src/game/mario.c lines 785–788 at 9921382 · upstream ↗ 26struct LandingAction sJumpLandAction = { 27 4, 5, ACT_FREEFALL, ACT_JUMP_LAND_STOP, ACT_DOUBLE_JUMP, ACT_FREEFALL, ACT_BEGIN_SLIDING, ⋮ 30struct LandingAction sFreefallLandAction = { 31 4, 5, ACT_FREEFALL, ACT_FREEFALL_LAND_STOP, ACT_DOUBLE_JUMP, ACT_FREEFALL, ACT_BEGIN_SLIDING,
src/game/mario_actions_moving.c lines 26–32 at 9921382 · upstream ↗ 1767 m->doubleJumpTimer = landingAction->unk02; ⋮ 1774 return set_mario_action(m, landingAction->endAction, 0); ⋮ 1777 if (++m->actionTimer >= landingAction->numFrames) { 1778 return set_mario_action(m, landingAction->endAction, 0); ⋮ 1781 if (m->input & INPUT_A_PRESSED) { 1782 return setAPressAction(m, landingAction->aPressedAction, 0);
src/game/mario_actions_moving.c lines 1767–1783 at 9921382 · upstream ↗ 1411 if (m->doubleJumpTimer > 0) { 1412 m->doubleJumpTimer--;
src/game/mario.c lines 1411–1413 at 9921382 · upstream ↗ 848 if (m->input & INPUT_A_PRESSED) { 849 if (!action) { 850 return set_jump_from_landing(m);
src/game/mario_actions_stationary.c lines 848–850 at 9921382 · upstream ↗ 1030 if ((m->doubleJumpTimer == 0) || (m->squishTimer != 0)) { 1031 set_mario_action(m, ACT_JUMP, 0); 1032 } else { 1033 switch (m->prevAction) { 1034 case ACT_JUMP_LAND: 1035 set_mario_action(m, ACT_DOUBLE_JUMP, 0); ⋮ 1039 set_mario_action(m, ACT_DOUBLE_JUMP, 0); ⋮ 1043 set_mario_action(m, ACT_DOUBLE_JUMP, 0);
src/game/mario.c lines 1030–1043 at 9921382 · upstream ↗ 856 if (m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE)) { 857 return check_common_action_exits(m);
src/game/mario_actions_stationary.c lines 856–857 at 9921382 · upstream ↗ 1124 if (m->input & INPUT_NONZERO_ANALOG) { 1125 return set_mario_action(m, ACT_WALKING, 0);
src/game/mario.c lines 1124–1125 at 9921382 · upstream ↗ 1006 m->prevAction = m->action; 1007 m->action = action;
src/game/mario.c lines 1006–1007 at 9921382 · upstream ↗ 791 if (m->input & INPUT_A_PRESSED) { 792 return set_jump_from_landing(m);
src/game/mario_actions_moving.c lines 791–792 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^A press while Mario lands from a double jump starts a triple jump if his forward speed is above 20 units/frame, and a single jump otherwise. With the wing cap, the press always starts a different action, the flying triple jump (
ACT_FLYING_TRIPLE_JUMP, 82 units/frame). The triple jump takes off at 69 units/frame whatever the speed, and releasing A doesn't cut it.Coden64decomp/sm64revisedHow we know
1874s32 act_double_jump_land(struct MarioState *m) { 1875 if (common_landing_cancels(m, &sDoubleJumpLandAction, set_triple_jump_action)) {
src/game/mario_actions_moving.c lines 1874–1876 at 9921382 · upstream ↗ 147s32 set_triple_jump_action(struct MarioState *m, UNUSED u32 action, UNUSED u32 actionArg) { 148 if (m->flags & MARIO_WING_CAP) { 149 return set_mario_action(m, ACT_FLYING_TRIPLE_JUMP, 0); 150 } else if (m->forwardVel > 20.0f) { 151 return set_mario_action(m, ACT_TRIPLE_JUMP, 0); 152 } else { 153 return set_mario_action(m, ACT_JUMP, 0);
src/game/mario_actions_moving.c lines 147–153 at 9921382 · upstream ↗ 796 case ACT_TRIPLE_JUMP: 797 set_mario_y_vel_based_on_fspeed(m, 69.0f, 0.0f); 798 m->forwardVel *= 0.8f; ⋮ 801 case ACT_FLYING_TRIPLE_JUMP: 802 set_mario_y_vel_based_on_fspeed(m, 82.0f, 0.0f);
src/game/mario.c lines 796–802 at 9921382 · upstream ↗ 50struct LandingAction sDoubleJumpLandAction = { 51 4, 5, ACT_FREEFALL, ACT_DOUBLE_JUMP_LAND_STOP, ACT_JUMP, ACT_FREEFALL, ACT_BEGIN_SLIDING,
src/game/mario_actions_moving.c lines 50–52 at 9921382 · upstream ↗ 258#define ACT_TRIPLE_JUMP 0x01000882 // (0x082 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)include/sm64.h line 258 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^Z while running starts a crouch slide, and A in its first 30 frames at a forward speed above 10 units/frame starts a long jump. It takes off at 30 units/frame up and multiplies the forward speed by 1.5, capped at 48; in the air it falls with a gravity of 2 instead of 4.Coden64decomp/sm64revised
How we know
807 if (m->input & INPUT_Z_PRESSED) { 808 return set_mario_action(m, ACT_CROUCH_SLIDE, 0);
src/game/mario_actions_moving.c lines 807–808 at 9921382 · upstream ↗ 1459 if (m->actionTimer < 30) { 1460 m->actionTimer++; 1461 if (m->input & INPUT_A_PRESSED) { 1462 if (m->forwardVel > 10.0f) { 1463 return set_jumping_action(m, ACT_LONG_JUMP, 0);
src/game/mario_actions_moving.c lines 1459–1463 at 9921382 · upstream ↗ 863 case ACT_LONG_JUMP: ⋮ 865 set_mario_y_vel_based_on_fspeed(m, 30.0f, 0.0f); ⋮ 870 if ((m->forwardVel *= 1.5f) > 48.0f) { 871 m->forwardVel = 48.0f;
src/game/mario.c lines 863–873 at 9921382 · upstream ↗ 543 } else if (m->action == ACT_LONG_JUMP || m->action == ACT_SLIDE_KICK 544 || m->action == ACT_BBH_ENTER_SPIN) { 545 m->vel[1] -= 2.0f;
src/game/mario_step.c lines 543–545 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^The long jump's cap clips only a forward speed above 48. A backward (negative) speed is multiplied by 1.5 with no limit, which the decompilers' comment names as the cause of backwards long jumps (BLJs). A long jump's landing chains into another long jump on A with Z held. In the air, each frame moves the speed 0.35 toward 0, adds the stick's push (up to 1.5 along Mario's facing), and adds 2 more while it is below −16. This is the US build; the Shindou and iQue builds set a negative speed to 0 when a long jump lands.Coden64decomp/sm64revised
How we know
868 //! (BLJ's) This properly handles long jumps from getting forward speed with 869 // too much velocity, but misses backwards longs allowing high negative speeds. 870 if ((m->forwardVel *= 1.5f) > 48.0f) { 871 m->forwardVel = 48.0f;
src/game/mario.c lines 868–871 at 9921382 · upstream ↗ 46struct LandingAction sLongJumpLandAction = { 47 6, 5, ACT_FREEFALL, ACT_LONG_JUMP_LAND_STOP, ACT_LONG_JUMP, ACT_FREEFALL, ACT_BEGIN_SLIDING,
src/game/mario_actions_moving.c lines 46–48 at 9921382 · upstream ↗ 1847s32 act_long_jump_land(struct MarioState *m) { 1848#if defined(VERSION_SH) || defined(VERSION_CN) 1849 // BLJ (Backwards Long Jump) speed build up fix, crushing SimpleFlips's dreams since July 1997 1850 if (m->forwardVel < 0.0f) { 1851 m->forwardVel = 0.0f; ⋮ 1853#endif ⋮ 1855 if (!(m->input & INPUT_Z_DOWN)) { 1856 m->input &= ~INPUT_A_PRESSED; ⋮ 1859 if (common_landing_cancels(m, &sLongJumpLandAction, set_jumping_action)) {
src/game/mario_actions_moving.c lines 1847–1859 at 9921382 · upstream ↗ 223 dragThreshold = m->action == ACT_LONG_JUMP ? 48.0f : 32.0f; 224 m->forwardVel = approach_f32(m->forwardVel, 0.0f, 0.35f, 0.35f); ⋮ 226 if (m->input & INPUT_NONZERO_ANALOG) { ⋮ 228 intendedMag = m->intendedMag / 32.0f; ⋮ 230 m->forwardVel += intendedMag * coss(intendedDYaw) * 1.5f; ⋮ 235 if (m->forwardVel > dragThreshold) { 236 m->forwardVel -= 1.0f; ⋮ 238 if (m->forwardVel < -16.0f) { 239 m->forwardVel += 2.0f;
src/game/mario_actions_airborne.c lines 223–240 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^A jump that hits a wall at a forward speed above 16 turns Mario around and holds him in
ACT_AIR_HIT_WALL. A press on its first 2 frames kicks off the wall. On the 3rd he bonks away,wallKickTimeris set to 5 and counts down once a frame, and A still kicks while it is nonzero: 7 frames in all. The kick takes off at 62 units/frame up and at least 24 forward.Coden64decomp/sm64revisedHow we know
388 case AIR_STEP_HIT_WALL: ⋮ 391 if (m->forwardVel > 16.0f) { ⋮ 396 m->faceAngle[1] += 0x8000; ⋮ 399 set_mario_action(m, ACT_AIR_HIT_WALL, 0);
src/game/mario_actions_airborne.c lines 388–399 at 9921382 · upstream ↗ 1314 if (++(m->actionTimer) <= 2) { 1315 if (m->input & INPUT_A_PRESSED) { ⋮ 1318 return set_mario_action(m, ACT_WALL_KICK_AIR, 0); ⋮ 1320 } else if (m->forwardVel >= 38.0f) { 1321 m->wallKickTimer = 5; ⋮ 1327 return set_mario_action(m, ACT_BACKWARD_AIR_KB, 0); 1328 } else { 1329 m->wallKickTimer = 5; ⋮ 1337 return set_mario_action(m, ACT_SOFT_BONK, 0);
src/game/mario_actions_airborne.c lines 1314–1337 at 9921382 · upstream ↗ 1156s32 act_backward_air_kb(struct MarioState *m) { 1157 if (check_wall_kick(m)) { 1158 return TRUE;
src/game/mario_actions_airborne.c lines 1156–1158 at 9921382 · upstream ↗ 1247s32 act_soft_bonk(struct MarioState *m) { 1248 if (check_wall_kick(m)) { 1249 return TRUE;
src/game/mario_actions_airborne.c lines 1247–1249 at 9921382 · upstream ↗ 1147s32 check_wall_kick(struct MarioState *m) { 1148 if ((m->input & INPUT_A_PRESSED) && m->wallKickTimer != 0 && m->prevAction == ACT_AIR_HIT_WALL) { 1149 m->faceAngle[1] += 0x8000; 1150 return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
src/game/mario_actions_airborne.c lines 1147–1151 at 9921382 · upstream ↗ 1407 if (m->wallKickTimer > 0) { 1408 m->wallKickTimer--;
src/game/mario.c lines 1407–1409 at 9921382 · upstream ↗ 1705 update_mario_inputs(gMarioState); ⋮ 1714 // The function can loop through many action shifts in one frame, ⋮ 1717 while (inLoop) {
src/game/mario.c lines 1705–1717 at 9921382 · upstream ↗ 828 case ACT_WALL_KICK_AIR: 829 case ACT_TOP_OF_POLE_JUMP: 830 set_mario_y_vel_based_on_fspeed(m, 62.0f, 0.0f); 831 if (m->forwardVel < 24.0f) { 832 m->forwardVel = 24.0f;
src/game/mario.c lines 828–834 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^Z in the air starts a ground pound. Mario stops dead and, on each of the first 10 frames (t counting from 0), rises 20 − 2t units, 110 in all, each rise skipped unless his new height plus 160 stays below the ceiling. He holds there until his spin animation ends plus 4 frames; then he falls from −50 units/frame under the usual gravity.Coden64decomp/sm64revised
How we know
451 if (m->input & INPUT_Z_PRESSED) { 452 return set_mario_action(m, ACT_GROUND_POUND, 0);
src/game/mario_actions_airborne.c lines 451–453 at 9921382 · upstream ↗ 924 if (m->actionState == 0) { 925 if (m->actionTimer < 10) { 926 yOffset = 20 - 2 * m->actionTimer; 927 if (m->pos[1] + yOffset + 160.0f < m->ceilHeight) { 928 m->pos[1] += yOffset; ⋮ 934 m->vel[1] = -50.0f; 935 mario_set_forward_vel(m, 0.0f); ⋮ 943 m->actionTimer++; 944 if (m->actionTimer >= m->marioObj->header.gfx.animInfo.curAnim->loopEnd + 4) { ⋮ 946 m->actionState = 1;
src/game/mario_actions_airborne.c lines 924–947 at 9921382 · upstream ↗ 948 } else { 949 set_mario_animation(m, MARIO_ANIM_GROUND_POUND); ⋮ 951 stepResult = perform_air_step(m, 0);
src/game/mario_actions_airborne.c lines 948–951 at 9921382 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
Sources
Code
- n64decomp. 2023. “sm64: a decompilation of Super Mario 64 (n64decomp/sm64).” Commit 9921382. n64decomp/sm64 @ 9921382 · licence, all uses