Banjo-Kazooie
Rare's 1998 3D platformer for the Nintendo 64, read through the banjo.decomp decompilation.
On this page
The atlas reads Banjo-Kazooie through the banjo.decomp team’s decompilation, C that builds every release. Names and comments quoted here are theirs, and the claims cite the code the US 1.0 build compiles. Many of the helpers Banjo’s movement calls are still unnamed, and the claims say so where they lean on one. Nothing has been measured in the game yet.
Unlike Super Mario 64, which moves Mario a fixed amount each frame, Banjo-Kazooie keeps speeds in units per second and scales each step by the frame’s time1. A jump takes off at 710 units/s2 under half the usual gravity, and letting go of A on the rise brings the full gravity back for the rest of the jump2. Mario’s take-off grows with his speed instead, and with A up his upward speed is divided by 4 on each frame it stays above 20 units/frame3,4.
A second press of A in the air is the Feathery Flap: a small lift, then a fall capped at −399.9 units/s, against the usual −4000, while A stays down5. Super Mario 64 gives A no move in a jump; its double jump comes from a press on landing6. Z in the air is the Beak Buster, Banjo’s ground pound: he hangs, pops up, and drops under a gravity 7.4 times the usual7, where Mario rises up to 110 units and drops from a set speed8.
On the ground the stick’s tilt picks a target speed in five bands, up to 500 units/s9,9; Mario’s target grows with the square of the tilt10.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Jump | One speed | 710 units/s up whatever the run, and the horizontal speed set at once to the stick's target |
| Gravity | Switch on release | −1350 units/s² through a held jump, −2700 once A is up on the rise, and past the peak only if A stays held |
| Variable jump height | Gravity switch | A up while rising doubles the gravity for the rest of the jump, once Banjo has learned the move |
| Flight | Slowed fall | the Feathery Flap: one A press per time in the air, a 280 units/s lift and a fall capped at −399.9, for up to 2.5 s |
| Ground pound | Hover then drop | the Beak Buster: a hang, a pop up at 2300 units/s, then a drop under −20000 to a cap of −5000 |
| Running | Analog | five bands of stick tilt map linearly to a target of up to 500 units/s, closed by a fraction of the gap each frame |
Every claim about this game, by concept (5)
References
- ^Banjo-Kazooie keeps Banjo's speeds in world units per second and his gravity in units per second squared, scaled by each frame's time:
__baphysics_update_normaladds the gravity timestime_getDelta()to his vertical speed, then moves him by his velocity times that same time. The frame's time is a count from the video manager over 60 (50 on a PAL build):viMgr_entryadds 1 toD_802808D8for each message on its queue, and each buffer swap copies the count toD_80280724and zeroes it; the atlas reads the messages as vertical blanks, so the count as the blanks the frame took.func_8033DC20turns the count into seconds and the caller back into a whole count, clamped to 1 to 15, then capped at 0.05 s in US 1.0 (0.06 s on PAL), so at most three sixtieths (computed); that is multiplied by a multiplier thattime_resetsets to 1.Codebanjo.decomp/banjo-kazooierevisedHow we know
97 //update velocity for gravity 98 s_player_velocity[1] = s_player_velocity[1] + time_getDelta()*s_gravity ; 99 if(s_player_velocity[1] < s_terminal_velocity) 100 s_player_velocity[1] = s_terminal_velocity; ⋮ 103 s_delta_position[1] = s_delta_position[1] + s_player_velocity[1]; 104 ml_vec3f_scale(s_delta_position, time_getDelta());
src/core2/ba/physics.c lines 97–107 at e8d31fa · upstream ↗ 14void time_reset(void){ 15 s_dTimeReal_sec = 0.01f; 16 s_timeMultiplier = 1.0f; ⋮ 22 s_dTimeReal_sec = MIN(d_seconds, VER_SELECT(0.05, 0.06, 0.05, 0.05)); ⋮ 25 s_dTimeReal_sec = 0.01f; ⋮ 29void time_setDeltaReal_frames(s32 d_frames){ 30 s_dTimeReal_frames = MAX(MIN(0xf, d_frames) , 1); 31 time_setDeltaReal_sec(s_dTimeReal_frames*(1.0/FRAMERATE)); ⋮ 38f32 time_getDelta(void){ 39 return s_dTimeReal_sec*s_timeMultiplier;
src/core2/time.c lines 14–40 at e8d31fa · upstream ↗ 426 time_setDeltaReal_frames((s32)(func_8033DC20()*(float)FRAMERATE + 0.5));src/core2/code_5C870.c line 426 at e8d31fa · upstream ↗ 22f32 func_8033DC20(void){ 23 f32 out; 24 D_80384470 = viMgr_func_8024BD94(); 25 out = (1.0 / FRAMERATE)*D_80384470; 26 return out;
src/core2/code_B6C60.c lines 22–26 at e8d31fa · upstream ↗ 92s32 viMgr_func_8024BD94(void){ 93 return D_80280724;
src/core1/vimgr.c lines 92–93 at e8d31fa · upstream ↗ 181 osViSwapBuffer(gFramebuffers[sActiveFramebuffer = getOtherFramebuffer()]); ⋮ 187 D_80280724 = D_802808D8; 188 D_802808D8 = 0;
src/core1/vimgr.c lines 180–188 at e8d31fa · upstream ↗ 219void viMgr_entry(void *arg){ ⋮ 223 osRecvMesg(&sMesgQueue1, &sp48, OS_MESG_BLOCK); 224 thread5_checkAndExecutePreNMI(); 225 D_802808D8++;
src/core1/vimgr.c lines 219–225 at e8d31fa · upstream ↗ 80 ml_vec3f_scale_copy(sp84, sp60, func_8029CED0()); 81 ml_vec3f_scale_copy(sp78, sp6C, func_8029CED0()); 82 ml_vec3f_diff(sp84, sp78); 83 ml_vec3f_scale(sp84, time_getDelta()/0.0333333);
src/core2/ba/physics.c lines 80–83 at e8d31fa · upstream ↗ 34#if VERSION == VERSION_USA_1_0 35#define VER_SELECT(usa0, pal, usa1, jp) usa0 ⋮ 44#if VERSION == VERSION_PAL 45#define FRAMERATE 50 46#else 47#define FRAMERATE 60
include/version.h lines 34–48 at e8d31fa · 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.
- ^ abA jump sets Banjo's vertical speed to 710 units/s (610 from water) and his gravity to −1350 units/s², half the usual −2700, and sets his horizontal speed at once to the target speed the stick gives on the ground (banjo-kazooie/walking-speed). On a frame of the jump with A up while he still rises,
bsjump_updateresets the gravity to −2700 for the rest of the jump; nothing sets −1350 again, and with A held the lighter gravity lasts past the peak. Until Banjo has learned the ability the code namesABILITY_A_HOLD_A_JUMP_HIGHER, it resets the gravity every frame. A jump entered from a peck sets neither the speed nor the gravity. A take-off from a spring pad sets a flag that skips the reset; the first frame with A up clears it after the check, so the reset starts the frame after. While that flag is set, the jump's second phase turns into the Shock Spring Jump's charge (BS_21_BSHOCK_CHARGE). Leaving the jump state for anything but a peck restores −2700. Computed without the frame steps, a held jump rises about 187 units in 0.53 s, and one released at once about 93. Super Mario 64 instead adds a quarter of the forward speed to its take-off (sm64/jump-speed) and divides the rise by 4 on each frame A is up while Mario rises faster than 20 units/frame (sm64/jump-release).Codebanjo.decomp/banjo-kazooie · n64decomp/sm64revisedHow we know
20f32 D_80364CD0 = 710.0f; 21f32 D_80364CD4 = -1350.0f;
src/core2/bs/jump.c lines 20–21 at e8d31fa · upstream ↗ 25f32 D_80364CE4 = 610.0f;src/core2/bs/jump.c line 25 at e8d31fa · upstream ↗ 41 D_8037D4C2 = baflag_isTrue(BA_FLAG_2_ON_SPRING_PAD);src/core2/bs/jump.c line 41 at e8d31fa · upstream ↗ 47 if(sp30 == BS_11_BPECK){ ⋮ 52 D_8037D4C0 = 1; ⋮ 54 else {
src/core2/bs/jump.c lines 47–54 at e8d31fa · upstream ↗ 55 D_8037D4C1 = (sp30 == BS_2D_SWIM_IDLE) || (sp30 == BS_2E_SWIM);src/core2/bs/jump.c line 55 at e8d31fa · upstream ↗ 69 func_802B6FA8(); 70 baphysics_set_horizontal_velocity(yaw_getIdeal(), baphysics_get_target_horizontal_velocity()); 71 if(D_8037D4C1){ 72 baphysics_set_vertical_velocity(D_80364CE4); 73 } else { 74 baphysics_set_vertical_velocity(D_80364CD0); ⋮ 76 baphysics_set_gravity(D_80364CD4);
src/core2/bs/jump.c lines 69–76 at e8d31fa · upstream ↗ 101 baphysics_get_velocity(velocity); 102 if((bakey_released(BUTTON_A) && 0.0f < velocity[1] && !D_8037D4C2) || !can_control_jump_height()){ 103 baphysics_reset_gravity();
src/core2/bs/jump.c lines 101–104 at e8d31fa · upstream ↗ 121 case 1://L802B14B4 122 if( 500.0f < (playerPosition_getY() - func_80294438())){ 123 sp34 = BS_2F_FALL; ⋮ 125 if(D_8037D4C2){ 126 D_8037D4C2 = 0; 127 sp34 = BS_21_BSHOCK_CHARGE;
src/core2/bs/jump.c lines 121–128 at e8d31fa · upstream ↗ 143 if(bakey_released(BUTTON_A)) 144 D_8037D4C2 = 0;
src/core2/bs/jump.c lines 143–144 at e8d31fa · upstream ↗ 171 if (bs_getNextState() != BS_11_BPECK) { 172 baphysics_reset_gravity();
src/core2/bs/jump.c lines 171–173 at e8d31fa · upstream ↗ 50 bakey.released_count[i] = bakey.pressed_count[i] 51 ? 0 52 : bakey.released_count[i] + 1;
src/core2/bakey.c lines 50–52 at e8d31fa · upstream ↗ 79int bakey_released(s32 button_indx){ 80 return bakey.released_count[button_indx];
src/core2/bakey.c lines 79–81 at e8d31fa · upstream ↗ 10f32 baphysics_default_gravity = -2700.0f; //defaultGravity 11f32 baphysics_default_terminal_velocity = -4000.0f;
src/core2/ba/physics.c lines 10–11 at e8d31fa · upstream ↗ 397void baphysics_reset_gravity(void){ 398 baphysics_set_gravity(baphysics_default_gravity);
src/core2/ba/physics.c lines 397–399 at e8d31fa · upstream ↗ 67s32 can_control_jump_height(void){ 68 return ability_hasLearned(ABILITY_A_HOLD_A_JUMP_HIGHER);
src/core2/playerutils.c lines 67–68 at e8d31fa · 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 ↗ 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 ↗ 528 if (!(m->input & INPUT_A_DOWN) && m->vel[1] > 20.0f) { 529 return (m->action & ACT_FLAG_CONTROL_JUMP_HEIGHT) != 0;
src/game/mario_step.c lines 528–529 at 9921382 · 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.
- ^A 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.
- ^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.
- ^With the Feathery Flap learned, A pressed during a jump or a fall starts it, once per time in the air: the flag it sets clears only on stable ground, while climbing, or in water, and a peck in the air blocks it. It stops Banjo's rise (vertical speed 0, gravity −1100 units/s²); when the opening animation reaches 0.9 of its length, it sets him rising at 280 units/s with his fall capped at −399.9, against the usual cap of −4000. A let go in the first 0.67 s of the flap, counted from its start through the opening animation by
D_8037D308(the atlas's reading of that unnamed variable as elapsed time), does nothing; after that, A up restores the usual gravity and cap. A 2.5-second timer ends the flap in any case. OnceD_8037D301, which counts the frames the flap animation passes 0.9 of its length from the lift on (the atlas reads it as a loop count), reaches 4, holding A scales the target horizontal speed to 0.35 of what the stick gives. Super Mario 64'sact_jumpchecks B and Z but not A; its second jump comes from a press during a landing (sm64/double-jump).Codebanjo.decomp/banjo-kazooie · n64decomp/sm64revisedHow we know
40int bainput_should_feathery_flap(void){ 41 return bakey_pressed(BUTTON_A) && can_feathery_flap();
src/core2/bainput.c lines 40–42 at e8d31fa · upstream ↗ 53bool can_feathery_flap(void){ 54 return baflag_isFalse(BA_FLAG_12_HAS_FLAPPED) 55 && baflag_isFalse(BA_FLAG_5_HAS_PECKED) 56 && ability_hasLearned(ABILITY_7_FEATHERY_FLAP);
src/core2/playerutils.c lines 53–56 at e8d31fa · upstream ↗ 187 if(player_isStable() || bsclimb_inSet(bs_getState())){ 188 baflag_clear(BA_FLAG_5_HAS_PECKED); 189 baflag_clear(BA_FLAG_12_HAS_FLAPPED); ⋮ 192 if(player_inWater()){ 193 baflag_clear(BA_FLAG_5_HAS_PECKED); 194 baflag_clear(BA_FLAG_12_HAS_FLAPPED);
src/core2/code_D9B0.c lines 187–195 at e8d31fa · upstream ↗ 146 if(bainput_should_feathery_flap()) 147 sp34 = BS_10_BFLAP;
src/core2/bs/jump.c lines 146–147 at e8d31fa · upstream ↗ 225 if(bainput_should_feathery_flap() && baflag_isFalse(BA_FLAG_5_HAS_PECKED)) 226 sp2C = BS_10_BFLAP;
src/core2/bs/jump.c lines 225–226 at e8d31fa · upstream ↗ 13const f32 D_80364A10 = 280.0f; 14const f32 D_80364A14 = -1100.0f; 15const f32 D_80364A18 = -399.9f;
src/core2/bs/bFlap.c lines 13–15 at e8d31fa · upstream ↗ 33 baphysics_set_vertical_velocity(0.0f); 34 baphysics_set_gravity(D_80364A14); 35 modelAppendages_setKazooiesUpperHalfVisibility(TRUE); 36 baflag_set(BA_FLAG_12_HAS_FLAPPED); 37 batimer_set(0, 2.5f);
src/core2/bs/bFlap.c lines 33–37 at e8d31fa · upstream ↗ 55void func_802A2810(void) { ⋮ 58 if (anctrl_isAt(plyrMvPtr, 0.9f)) { 59 D_8037D301++;
src/core2/bs/bFlap.c lines 55–60 at e8d31fa · upstream ↗ 86void func_802A2900(void){ 87 D_8037D304 = D_8037D308; 88 D_8037D308 += time_getDelta();
src/core2/bs/bFlap.c lines 86–89 at e8d31fa · upstream ↗ 113 func_802B6FA8(); 114 switch(D_8037D300){ 115 case 0: ⋮ 119 if(anctrl_isAt(sp18, 0.9f)){ ⋮ 126 baphysics_set_vertical_velocity(D_80364A10); 127 baphysics_set_gravity(D_80364A14); 128 baphysics_set_terminal_velocity(D_80364A18); 129 D_8037D300 = 1; ⋮ 138 if(0.67 <= D_8037D308){ 139 D_8037D300 = 2; ⋮ 148 if(D_8037D301 == 4) { 149 D_8037D300 = 3; ⋮
src/core2/bs/bFlap.c lines 113–182 at e8d31fa · upstream ↗ 10f32 baphysics_default_gravity = -2700.0f; //defaultGravity 11f32 baphysics_default_terminal_velocity = -4000.0f;
src/core2/ba/physics.c lines 10–11 at e8d31fa · upstream ↗ 446s32 act_jump(struct MarioState *m) { 447 if (check_kick_or_dive_in_air(m)) { ⋮ 451 if (m->input & INPUT_Z_PRESSED) { 452 return set_mario_action(m, ACT_GROUND_POUND, 0);
src/game/mario_actions_airborne.c lines 446–453 at 9921382 · upstream ↗ 108s32 check_kick_or_dive_in_air(struct MarioState *m) { 109 if (m->input & INPUT_B_PRESSED) { 110 return set_mario_action(m, m->forwardVel > 28.0f ? ACT_DIVE : ACT_JUMP_KICK, 0);
src/game/mario_actions_airborne.c lines 108–110 at 9921382 · 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.
- ^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.
- ^With the Beak Buster learned, Z pressed during a jump (or in the air in another state) starts it. Banjo stops dead: his velocity, his target horizontal speed, and his gravity all go to 0, and he hangs until the opening stretch of his animation stops and then one more frame. Then he pops up at 2300 units/s under a gravity of −20000 units/s², 7.4 times the usual −2700 (computed), with his fall capped at −5000 instead of −4000. Water ends the move at any phase. When he lands (stable ground, an unnamed flag
BA_FLAG_8, or four frames in a row with under 1 unit of an unnamed vertical measure fromfunc_8029445C), a landing with fall damage goes to a splat (BS_72_SPLAT); otherwise his speed and gravity go to 0 for 0.09 s; then he bounces up at 730 units/s under −2110, or at 400 under −800 if the Beak Buster hit an object whose marker id is 0x9E or 0xA1, which the hit kills. Super Mario 64's ground pound has no upward pop: Mario rises at most 110 units over 10 frames while he holds, then falls from −50 units/frame (sm64/ground-pound).Codebanjo.decomp/banjo-kazooie · n64decomp/sm64revisedHow we know
12int bainput_should_beak_bust(void){ 13 return bakey_pressed(BUTTON_Z) && can_beak_bust();
src/core2/bainput.c lines 12–14 at e8d31fa · upstream ↗ 27s32 can_beak_bust(void){ 28 return ability_hasLearned(ABILITY_2_BEAK_BUSTER);
src/core2/playerutils.c lines 27–28 at e8d31fa · upstream ↗ 152 if(bainput_should_beak_bust()) 153 sp34 = BS_F_BBUSTER;
src/core2/bs/jump.c lines 152–153 at e8d31fa · upstream ↗ 9const f32 D_80364990 = 400.0f; 10const f32 D_80364994 = -800.0f; ⋮ 12const f32 D_80364998 = 730.0f; 13const f32 D_8036499C = -2110.0f; ⋮ 15const f32 D_803649A0 = 2300.0f; 16const f32 D_803649A4 = -20000.0f; 17const f32 D_803649A8 = -5000.0f;
src/core2/bs/bbuster.c lines 9–17 at e8d31fa · upstream ↗ 64 anctrl_setDuration(aCtrl, 1.02f); 65 anctrl_setSubRange(aCtrl, 0.0f, 0.35f); ⋮ 69 baphysics_set_gravity(0.0f); 70 baphysics_set_target_horizontal_velocity(0.0f); 71 ml_vec3f_clear(sp20); 72 baphysics_set_velocity(sp20); ⋮ 78 D_8037D2B0 = 0.0001f;
src/core2/bs/bbuster.c lines 64–78 at e8d31fa · upstream ↗ 98 case 0://8029FDF0 99 if(anctrl_isStopped(baanim_getAnimCtrlPtr())){ ⋮ 101 D_8037D2BA = 1; ⋮ 104 case 1://8029FE24 105 D_8037D2B0 -= time_getDelta(); 106 if(D_8037D2B0 <= 0.0f){ 107 baphysics_reset_gravity(); 108 baphysics_set_terminal_velocity(D_803649A8); 109 baphysics_set_gravity(D_803649A4); 110 baphysics_set_vertical_velocity(D_803649A0);
src/core2/bs/bbuster.c lines 98–113 at e8d31fa · upstream ↗ 128 D_8037D2B9 = baflag_isTrue(BA_FLAG_8); 129 func_8029445C(sp30); 130 //L8029FF78 131 if(((0.0f <= sp30[1])? sp30[1] : -sp30[1]) < 1.0){ 132 D_8037D2BC++; 133 }else{ 134 D_8037D2BC = 0; ⋮ 139 if(player_isStable() || D_8037D2B9 || !(D_8037D2BC < 4)){ ⋮ 143 baphysics_set_velocity(0); 144 baphysics_set_gravity(0.0f); 145 baphysics_set_target_horizontal_velocity(0.0f); ⋮ 148 D_8037D2B0 = 0.09f;
src/core2/bs/bbuster.c lines 128–148 at e8d31fa · upstream ↗ 152 if(bafalldamage_get_damage(&sp3C)){ 153 sp44 = BS_72_SPLAT;
src/core2/bs/bbuster.c lines 152–154 at e8d31fa · upstream ↗ 195 if(player_inWater()) 196 sp44 = BS_4C_LANDING_IN_WATER;
src/core2/bs/bbuster.c lines 195–196 at e8d31fa · upstream ↗ 163 D_8037D2B0 -= time_getDelta(); 164 if(D_8037D2B0 <= 0.0f){ 165 if(D_8037D2BB){ 166 baphysics_set_vertical_velocity(D_80364990); 167 baphysics_set_gravity(D_80364994); 168 }else{ 169 baphysics_set_vertical_velocity(D_80364998); 170 baphysics_set_gravity(D_8036499C);
src/core2/bs/bbuster.c lines 163–171 at e8d31fa · upstream ↗ 209void func_802A02B4(s32 arg0){ 210 D_8037D2BB = arg0;
src/core2/bs/bbuster.c lines 209–210 at e8d31fa · upstream ↗ 273 switch(marker->id){src/core2/ba/marker.c line 273 at e8d31fa · upstream ↗ 313 case 0x9E: //L8028BF54 314 case 0xA1: //L8028BF54 315 if(plyr_hitbox_type == HITBOX_1_BEAK_BUSTER){ 316 func_802A02B4(1); 317 obj_collision_type = MARKER_COLLISION_FUNC_2_DIE;
src/core2/ba/marker.c lines 313–317 at e8d31fa · 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);
src/game/mario_actions_airborne.c lines 924–935 at 9921382 · 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.
- ^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.
- ^ abOn the ground the stick's tilt sets Banjo's target speed in five bands of the stick's distance from center, each axis clamped to a raw 7 to 59 (x) or 7 to 61 (y) and scaled to 0 to 1, and the distance capped at 1. Up to 0.12 the target is 0; above it the target rises linearly within each band: 30 to 80 units/s up to 0.2, 80 to 150 up to 0.5, 150 to 225 up to 0.75, and 225 to 500 at full tilt. The decompilers name the bands creep, slow walk, walk, and fast walk. On ground flagged
BA_FLAG_13_TOUCHING_DANGEROUS_GROUND, the target is instead 30 to 150 by the distance itself, and 0 inside the 0.12 dead zone. Each frame the horizontal velocity closes the gap to the target by a fraction from a five-entry table (0, 0.07, 0.29, 0.15, 0.05) indexed by the unnamedD_8037C284(the atlas reads the index as a movement state), unlessfunc_8029CF48has set an override for that index, whichfunc_8029CED0then returns instead, times the frame's time over 1/30 s; when an unnamed floor check (func_80294548) passes, the target is first scaled by the slope. Super Mario 64's target is 32 times the square of the tilt, and Mario gains a fixed 1.1 − speed/43 units/frame below it (sm64/walking-speed).Codebanjo.decomp/banjo-kazooie · n64decomp/sm64revisedHow we know
18f32 bsWalkMinCreepVelocity = 30.0f;//creep_min 19f32 bsWalkCreepSlowWalkVelocityThreshold = 80.0f;//creep_max/slow_walk_min 20f32 bsWalkSlowWalkWalkVelocityThreshold = 150.0f;//slow_walk_max/walk_min 21f32 bsWalkWalkFastWalkVelocityThreshold = 225.0f;//walk_max/walk_fast_min 22f32 bsWalkMaxFastWalkVelocity = 500.0f;//walk_fast_max 23f32 bsWalkMinMudVelocity = 30.0f; //mud_min 24f32 bsWalkMaxMudVelocity = 150.0f; //mud_max
src/core2/bs/walk.c lines 18–24 at e8d31fa · upstream ↗ 41void func_802B6D00(void){ ⋮ 45 sp1C = bastick_getZonePosition(); 46 sp18 = bastick_getZone(); 47 if(player_isOnDangerousGround()){ 48 if(sp18 == 0){ 49 baphysics_set_target_horizontal_velocity(0.0f); 50 }else{//L802B6D48 51 baphysics_set_target_horizontal_velocity(ml_interpolate_f(bastick_distance(), bsWalkMinMudVelocity, bsWalkMaxMudVelocity)); ⋮ 55 switch(sp18){ 56 case 0://802B6D98 57 baphysics_set_target_horizontal_velocity(0.0f); ⋮ 60 baphysics_set_target_horizontal_velocity(ml_interpolate_f(sp1C, bsWalkMinCreepVelocity, bsWalkCreepSlowWalkVelocityThreshold)); ⋮
src/core2/bs/walk.c lines 41–72 at e8d31fa · upstream ↗ 28f32 bastick_calculateZonePosition(f32 arg0, f32 arg1, f32 arg2){ 29 return (arg0 - arg1)/(arg2 - arg1); ⋮ 35 if (bastick.distance <= bastick.zone_markers[0]) { 36 bastick.zone = 0; 37 bastick.zone_position = 0.0f; ⋮ 63void bastick_resetZones(void) { 64 bastick_setZoneMax(0, 0.12f); 65 bastick_setZoneMax(1, 0.2f); 66 bastick_setZoneMax(2, 0.5f); 67 bastick_setZoneMax(3, 0.75f); 68 bastick_setZoneMax(4, 1.0f);
src/core2/bastick.c lines 28–69 at e8d31fa · upstream ↗ 85 bastick.distance = sqrtf(bastick.value[0]*bastick.value[0] + bastick.value[1]*bastick.value[1]); ⋮ 100 if (bastick.distance > 1.0) { 101 bastick.distance = 1.0f;
src/core2/bastick.c lines 85–102 at e8d31fa · upstream ↗ 51f32 controller_clampAndNormaliseJoyAxis(s32 input, s32 min, s32 max) ⋮ 53 f32 unit = 1 / 80.f; ⋮ 61 if (input > 0) ⋮ 63 input = input > max ? max : input < min ? min : input; 64 input = ((input - min) * 80) / (max - min); ⋮ 72 return unit *= input;
src/core1/joy.c lines 51–72 at e8d31fa · upstream ↗ 155 dst[0] = controller_clampAndNormaliseJoyAxis(sInputs[controllerIdx].stick_x, 7, 59); 156 dst[1] = controller_clampAndNormaliseJoyAxis(sInputs[controllerIdx].stick_y, 7, 61);
src/core1/joy.c lines 155–156 at e8d31fa · upstream ↗ 705f32 ml_interpolate_f(f32 arg0, f32 arg1, f32 arg2) ⋮ 707 return arg0 * (arg2 - arg1) + arg1;
src/core1/ml.c lines 705–707 at e8d31fa · upstream ↗ 188bool player_isOnDangerousGround(void){ 189 return baflag_isTrue(BA_FLAG_13_TOUCHING_DANGEROUS_GROUND);
src/core2/playerutils.c lines 188–189 at e8d31fa · upstream ↗ 49 func_80256D0C(0.0f, baphysics_target_yaw, 0.0f, 0.0f, baphysics_target_horizontal_velocity, &baphysics_target_velocity[0], &baphysics_target_velocity[1], &baphysics_target_velocity[2]); ⋮ 57 if(func_80294548()){ ⋮ 71 ml_vec3f_scale(sp60, 1.0 + sp40); ⋮ 75 ml_vec3f_scale(sp60, sp40 + 1.0); ⋮ 80 ml_vec3f_scale_copy(sp84, sp60, func_8029CED0()); 81 ml_vec3f_scale_copy(sp78, sp6C, func_8029CED0()); 82 ml_vec3f_diff(sp84, sp78); 83 ml_vec3f_scale(sp84, time_getDelta()/0.0333333); 84 s_player_velocity[0] += sp84[0];\
src/core2/ba/physics.c lines 49–86 at e8d31fa · upstream ↗ 16f32 func_8029CED0(void) { ⋮ 19 temp_v0 = func_8029CEB0(); 20 if (D_8037D1F0[temp_v0] != 0) { 21 return D_8037D1F8[temp_v0]; ⋮ 23 return func_8033DE30(temp_v0);
src/core2/code_15F20.c lines 16–23 at e8d31fa · upstream ↗ 30void func_8029CF48(s32 arg0, s32 arg1, f32 arg2) { 31 D_8037D1F0[arg0] = arg1; 32 D_8037D1F8[arg0] = arg2;
src/core2/code_15F20.c lines 30–33 at e8d31fa · upstream ↗ 440s32 func_802944F4(void){ 441 return D_8037C284;
src/core2/code_C4B0.c lines 440–441 at e8d31fa · upstream ↗ 77Struct_Core2_B6CE0_1 D_80371E30[] ={ 78 { 0, 0, 0.0f }, 79 { 1, 0, 0.07f }, 80 { 2, 1, 0.29f }, 81 { 3, 2, 0.15f }, 82 { 4, 1, 0.05f }
src/core2/commonParticle.c lines 77–83 at e8d31fa · upstream ↗ 97f32 func_8033DE30(s32 arg0){ 98 return D_80371E30[arg0].unk4;
src/core2/commonParticle.c lines 97–98 at e8d31fa · upstream ↗ 1295 f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f; ⋮ 1298 m->intendedMag = mag / 2.0f;
src/game/mario.c lines 1295–1298 at 9921382 · upstream ↗ 450 if (m->forwardVel <= 0.0f) { 451 m->forwardVel += 1.1f; 452 } else if (m->forwardVel <= targetSpeed) { 453 m->forwardVel += 1.1f - m->forwardVel / 43.0f;
src/game/mario_actions_moving.c lines 450–453 at 9921382 · 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.
- ^On the ground the stick's tilt sets a target speed:
intendedMagis 32 times the square of the tilt's fraction of full. Below the target Mario gains 1.1 − speed/43 units/frame each frame (1.1 from a standstill); above it, on level ground, he loses 1. The target is at most 32, or 24 on slow floors, and the speed is capped at 48.Coden64decomp/sm64How we know
1295 f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f; ⋮ 1298 m->intendedMag = mag / 2.0f;
src/game/mario.c lines 1295–1298 at 9921382 · upstream ↗ 455 if (controller->stickMag > 64) { ⋮ 458 controller->stickMag = 64;
src/game/game_init.c lines 455–458 at 9921382 · upstream ↗ 438 if (m->floor != NULL && m->floor->type == SURFACE_SLOW) { 439 maxTargetSpeed = 24.0f; 440 } else { 441 maxTargetSpeed = 32.0f; ⋮ 444 targetSpeed = m->intendedMag < maxTargetSpeed ? m->intendedMag : maxTargetSpeed; ⋮ 450 if (m->forwardVel <= 0.0f) { 451 m->forwardVel += 1.1f; 452 } else if (m->forwardVel <= targetSpeed) { 453 m->forwardVel += 1.1f - m->forwardVel / 43.0f; 454 } else if (m->floor->normal.y >= 0.95f) { 455 m->forwardVel -= 1.0f; ⋮ 458 if (m->forwardVel > 48.0f) { ⋮
src/game/mario_actions_moving.c lines 438–460 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.
Sources
Code
- banjo.decomp. 2026. “banjo-kazooie: a decompilation of Banjo-Kazooie (banjo.decomp/banjo-kazooie).” Commit e8d31fa. banjo.decomp/banjo-kazooie @ e8d31fa · licence, all uses
- n64decomp. 2023. “sm64: a decompilation of Super Mario 64 (n64decomp/sm64).” Commit 9921382. n64decomp/sm64 @ 9921382 · licence, all uses