On this page
  1. Related
  2. Mechanics
  3. References
  4. Sources

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

MechanicKindHow
JumpOne speed710 units/s up whatever the run, and the horizontal speed set at once to the stick's target
GravitySwitch 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 heightGravity switchA up while rising doubles the gravity for the rest of the jump, once Banjo has learned the move
FlightSlowed fallthe 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 poundHover then dropthe Beak Buster: a hang, a pop up at 2300 units/s, then a drop under −20000 to a cap of −5000
RunningAnalogfive 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)
FlightWith 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. Once D_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's act_jump checks B and Z but not A; its second jump comes from a press during a landing (sm64/double-jump).Code
GravityBanjo-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_normal adds the gravity times time_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_entry adds 1 to D_802808D8 for each message on its queue, and each buffer swap copies the count to D_80280724 and zeroes it; the atlas reads the messages as vertical blanks, so the count as the blanks the frame took. func_8033DC20 turns 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 that time_reset sets to 1.Code
Ground poundWith 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 from func_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).Code
JumpA 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_update resets 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 names ABILITY_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).Code
RunningOn 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 unnamed D_8037C284 (the atlas reads the index as a movement state), unless func_8029CF48 has set an override for that index, which func_8029CED0 then 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).Code

References

  1. ^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_normal adds the gravity times time_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_entry adds 1 to D_802808D8 for each message on its queue, and each buffer swap copies the count to D_80280724 and zeroes it; the atlas reads the messages as vertical blanks, so the count as the blanks the frame took. func_8033DC20 turns 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 that time_reset sets to 1.Codebanjo.decomp/banjo-kazooierevised
    How 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.

    In the claim ledger

  2. ^ 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_update resets 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 names ABILITY_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/sm64revised
    How 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.

    In the claim ledger

  3. ^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.

    In the claim ledger

  4. ^Releasing A cuts a jump short: on a frame with A up and the rise above 20 units/frame, apply_gravity divides the vertical speed by 4 instead of subtracting gravity. Only actions flagged ACT_FLAG_CONTROL_JUMP_HEIGHT do 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/sm64revised
    How 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.

    In the claim ledger

  5. ^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. Once D_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's act_jump checks B and Z but not A; its second jump comes from a press during a landing (sm64/double-jump).Codebanjo.decomp/banjo-kazooie · n64decomp/sm64revised
    How 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.

    In the claim ledger

  6. ^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 doubleJumpTimer to 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, because set_jump_from_landing checks 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/sm64revised
    How 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.

    In the claim ledger

  7. ^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 from func_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/sm64revised
    How 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.

    In the claim ledger

  8. ^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.

    In the claim ledger

  9. ^ 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 unnamed D_8037C284 (the atlas reads the index as a movement state), unless func_8029CF48 has set an override for that index, which func_8029CED0 then 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/sm64revised
    How 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.

    In the claim ledger

  10. ^On the ground the stick's tilt sets a target speed: intendedMag is 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/sm64
    How 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.

    In the claim ledger

Sources

Code