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

A drift boost rewards a drift with speed. Mario Kart 64 charges stages while the stick counter-steers during a drift, and two stages give a mini-turbo when the drift ends1. Holding R through a power slide in Diddy Kong Racing instead gives a car 1.1 × top speed while held2, and the slide ends with no boost. Ridge Racer’s slide gives no boost: ending it only costs speed, by the angle between the car’s heading and its travel3.

  • NoneRidge Racer (1993). The slide gives no boost: its end only takes speed off, more the wider the angle between heading and travel.3,4
  • Held speedDiddy Kong Racing (1997). Holding R through a car's power slide raises its top speed by a tenth, and the slide ends with no boost.2
  • Stick stagesMario Kart 64 (1996). Counter-steering during a drift charges a stage after 18 counts and 8 more for each after; two stages give a 31-update mini-turbo.1

Games

GameYearHowNote
Diddy Kong Racing1997Held speedholding R through a car's power slide raises its top speed by a tenth, and the slide ends with no boost
Mario Kart 641996Stick stagescounter-steering during a drift charges a stage after 18 counts and 8 more for each after; two stages give a 31-update mini-turbo
Every claim about this mechanic, by game (7)
Ridge Racer 1993In Ridge Racer's Japanese release (SLPS-00001), car_simulate (func_80019CF4) runs one of four handlers each update by the car's state at offset 0xB4: 0 func_80026E7C, 1 func_80027734, 2 func_80027F60, 3 func_80028294, which the atlas reads as grip, slide, slide recovery, and the start. In state 0 the heading turns a fifth of the way to the steering's target each update, and the car moves only along its heading: the code keeps the forward part of its velocity and drops the sideways part.Code
In Ridge Racer's Japanese release (SLPS-00001), a car in grip (state 0, func_80026E7C) enters a slide (state 1) in two ways. Pressing the accelerator again after lifting off: the code counts the updates the accelerator stays below half (0x80) without a fresh brake press, and on the update the accelerator is pressed again it multiplies the count by the car's speed; a speed above 960 and a product above the car's threshold start the slide. Or a fresh brake press with the accelerator off: the car's sideways velocity times its speed over 64, above the threshold at a speed above 320. The threshold is 14 times a value from the car model's spec table. The product that started the slide becomes the slide's budget (D_801732F0), and the car's yaw rate (D_8012CFE0) is set against its sideways velocity: at least twice it on the accelerator, once on the brake.Code
In Ridge Racer's Japanese release (SLPS-00001), a car in a slide (state 1, func_80027734) turns its heading by its yaw rate over 256 each update, with the yaw rate held within ±0x3600, so at most 54 of the 4,096 units of a full turn (computed: about 4.7°). While the slide's budget is above 0, a term from Phys 0x54 (w54), which the atlas reads as the steering target, adds to the yaw rate and the budget drains each update by 0x40, by the square of the slip angle (heading against direction of travel) over 65,536, by (0x3600 − |yaw rate|)/64, and by 4 times the brake value, with more drained below a speed of 400, below half the car's spec speed, or at a slip under 0x80 with a slow yaw. Once the budget is spent, the yaw rate falls to 15/16 each update, and the slide ends on the first update it starts below 0x1000.Code
In Ridge Racer's Japanese release (SLPS-00001), when a slide ends (func_80027734) the car's direction of travel snaps to its heading and its speed is multiplied by 1 − w²/2²⁰, where w is the slip angle between them folded to at most a quarter turn: a slide that ends at 45° keeps 75% of its speed and one at 90° keeps none (computed). The part taken off keeps moving the car along its old direction in state 2 (func_80027F60), shrinking to 31/32 each update with the leftover angle, and the car returns to grip (state 0) when both reach 0.Code
In Ridge Racer's Japanese release (SLPS-00001), car_simulate gives a car in a slide (state 1) an eighth of the engine drive it gets in the other states, and lets its speed fall by 0.4% an update instead of 6%. The slide handler (func_80027734) then scales that drive by (0x200 − w)/0x200 for a slip angle w up to a quarter turn: full drive with no slip, none at 45°, and a pull against the motion beyond (computed). func_80026CA8 adds the drive along the heading, but the slide handler saves the direction of travel before the call and restores it after, so in a slide the drive changes only the speed.Code
Mario Kart 64 1996In the US version of Mario Kart 64, while a kart drifts on the ground, holding the stick at least 10 of its 53 steps toward the outside of the turn counts up driftStateCounter. Letting the stick back after 18 to 99 counts raises driftState by one, up to 3, and sets the count to 10, so each later step takes 8 more counts (computed); letting it back before 10 counts, or at 100 or more, resets both to 0. When a human player's drift ends with driftState at 2 or more, the kart gets MINI_TURBO_EFFECT for 31 player updates (computed), during which a term in its forward force moves toward 580 by a fifth of the gap each update.Code
Diddy Kong Racing 1997In the US 1.0 version of Diddy Kong Racing, a car's power slide starts in its ground routine when R is held, the stick is past 15 either way, and the car is going forward faster than 3 (the code's velocity below -3). While R stays held the routine multiplies the top-speed value by 1.1. Letting go of R, or slowing to a velocity above -2, ends the slide and sets nothing else. During a slide the car update clamps the stick to 50 either way, quarters steering into the slide, and adds 60 toward it; holding the stick 26 or more against the slide adds the update rate to a count, and past 80 the car spins out and the slide ends. In an atlas search of src/, every write to the boost timer belongs to a zip pad, zipper, the start, a Nitro, a magnet, a plane trick, the loop-the-loop vehicle, or a boss, so a slide ends without a boost. Mario Kart 64 instead charges stages toward a mini-turbo while the stick counter-steers a drift.Code

References

  1. ^ abIn the US version of Mario Kart 64, while a kart drifts on the ground, holding the stick at least 10 of its 53 steps toward the outside of the turn counts up driftStateCounter. Letting the stick back after 18 to 99 counts raises driftState by one, up to 3, and sets the count to 10, so each later step takes 8 more counts (computed); letting it back before 10 counts, or at 100 or more, resets both to 0. When a human player's drift ends with driftState at 2 or more, the kart gets MINI_TURBO_EFFECT for 31 player updates (computed), during which a term in its forward force moves toward 580 by a fifth of the gap each update.Coden64decomp/mk64
    How we know
    1148void update_drift_state_counter(Player* player, s8 playerIndex) {
    1149    if (((s16) player->unk_0C0 / DEGREES(1)) > 0) {
    1150        if (((s32) player->steerPosition >> 16) <= -10) {
    1151            if (player->driftStateCounter <= 100) {
    1152                player->driftStateCounter++;
    ⋮
    1157        } else {
    1158            if ((player->driftStateCounter >= 18) && (player->driftStateCounter < 100)) {
    1159                if (player->driftState < 3) {
    1160                    player->driftState++;
    ⋮
    1163            if ((player->driftStateCounter >= 10) && (player->driftStateCounter < 100)) {
    1164                player->driftStateCounter = 10;
    1165            } else {
    ⋮
    
    src/player_controller.c lines 1148–1170 at 58cfcb0 · upstream ↗
    4166    if (((player->effects & HOP_EFFECT) != HOP_EFFECT) && ((player->effects & DRIFTING_EFFECT) != DRIFTING_EFFECT)) {
    
    src/player_controller.c line 4166 at 58cfcb0 · upstream ↗
    4194    } else if (((player->effects & MIDAIR_EFFECT) != MIDAIR_EFFECT) && ((player->effects & HOP_EFFECT) != HOP_EFFECT)) {
    4195        if ((((s16) player->unk_0C0) / DEGREES(1)) > 0) {
    ⋮
    4198            if ((player->steerPosition >> 16) <= -40) {
    4199                player->effects |= DRIFT_OUTSIDE_EFFECT;
    ⋮
    4201                    player->effects |= DRIFT_OUTSIDE_EFFECT;
    ⋮
    4204            update_drift_state_counter(player, playerIndex);
    ⋮
    4208            if ((player->steerPosition >> 16) >= 40) {
    4209                player->effects |= DRIFT_OUTSIDE_EFFECT;
    ⋮
    4211                    player->effects |= DRIFT_OUTSIDE_EFFECT;
    ⋮
    4214            update_drift_state_counter(player, playerIndex);
    
    src/player_controller.c lines 4194–4214 at 58cfcb0 · upstream ↗
    487#define DRIFT_OUTSIDE_EFFECT      0x20000000 // drifting toward the outside of your turn
    
    include/defines.h line 487 at 58cfcb0 · upstream ↗
    278    /* 0x007C */ s32 steerPosition; // Where the kart is steering, related to joystick position. Basically, in [-53 to 53], but shifted 16 bits left
    
    include/common_structs.h line 278 at 58cfcb0 · upstream ↗
    3956    clamped_x = get_clamped_stickX_with_deadzone(controller);
    ⋮
    3960    player->steerPosition = (clamped_x << 16) & 0xFFFF0000;
    
    src/player_controller.c lines 3956–3960 at 58cfcb0 · upstream ↗
    4862    if (temp_stickX > 0x35) {
    4863        temp_stickY = (temp_stickY * 0x0035) / temp_stickX;
    4864        temp_stickX = 0x0035;
    ⋮
    4866    if (temp_stickX < -0x35) {
    4867        temp_stickY = (temp_stickY * 0x0035) / -temp_stickX;
    4868        temp_stickX = -0x0035;
    
    src/player_controller.c lines 4862–4869 at 58cfcb0 · upstream ↗
    1123void func_8002A79C(Player* player, s8 playerIndex) {
    1124    if (((player->effects & MINI_TURBO_EFFECT) != MINI_TURBO_EFFECT) &&
    1125        ((player->effects & DRIFTING_EFFECT) != DRIFTING_EFFECT) && (player->driftState >= 2)) {
    1126        player->effects |= MINI_TURBO_EFFECT;
    1127        player->unk_23A = 0;
    ⋮
    1137    } else if ((player->effects & MINI_TURBO_EFFECT) == MINI_TURBO_EFFECT) {
    1138        player->unk_23A += 1;
    1139        if (player->unk_23A >= 0x1F) {
    1140            player->unk_23A = 0;
    1141            player->effects &= ~MINI_TURBO_EFFECT;
    
    src/player_controller.c lines 1123–1143 at 58cfcb0 · upstream ↗
    2139    if ((player->type & PLAYER_HUMAN) == PLAYER_HUMAN) {
    2140        func_8002A79C(player, playerId);
    
    src/player_controller.c lines 2139–2140 at 58cfcb0 · upstream ↗
    3093    if ((player->type & PLAYER_HUMAN) == PLAYER_HUMAN) {
    3094        if (((player->effects & MINI_TURBO_EFFECT) == MINI_TURBO_EFFECT) &&
    3095            ((player->effects & DRIFTING_EFFECT) != DRIFTING_EFFECT)) {
    3096            move_f32_towards(&player->unk_0E8, 580.0f, 0.2f);
    3097        } else {
    3098            move_f32_towards(&player->unk_0E8, 0.0f, 0.01f);
    ⋮
    3102        } else {
    ⋮
    3107    var_f2 = (player->unk_08C + player->unk_0E8 + player->boostPower + player->unk_0E4) - player->unk_0A0;
    
    src/player_controller.c lines 3093–3107 at 58cfcb0 · upstream ↗
    863void move_f32_towards(f32* startingValue, f32 targetValue, f32 somePercent) {
    864    *startingValue -= ((*startingValue - targetValue) * somePercent);
    
    src/render_player.c lines 863–864 at 58cfcb0 · upstream ↗
    2742    spF4[2] = func_80030150(player, playerId);
    2743    mtxf_transform_vec3f_mat3(spF4, player->orientationMatrix);
    ⋮
    2748    newVelocity[2] += (((spF4[2] + sp7C) + spD0[2]) - (newVelocity[2] * (0.12 * player->kartFriction))) / 6000.0;
    
    src/player_controller.c lines 2742–2748 at 58cfcb0 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-25.

    Checked by a second AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-25.

    In the claim ledger

  2. ^ abIn the US 1.0 version of Diddy Kong Racing, a car's power slide starts in its ground routine when R is held, the stick is past 15 either way, and the car is going forward faster than 3 (the code's velocity below -3). While R stays held the routine multiplies the top-speed value by 1.1. Letting go of R, or slowing to a velocity above -2, ends the slide and sets nothing else. During a slide the car update clamps the stick to 50 either way, quarters steering into the slide, and adds 60 toward it; holding the stick 26 or more against the slide adds the update rate to a count, and past 80 the car spins out and the slide ends. In an atlas search of src/, every write to the boost timer belongs to a zip pad, zipper, the start, a Nitro, a magnet, a plane trick, the loop-the-loop vehicle, or a boss, so a slide ends without a boost. Mario Kart 64 instead charges stages toward a mini-turbo while the stick counter-steers a drift.CodeDavidSM64/Diddy-Kong-Racing · n64decomp/mk64
    How we know
    5224    // Decide which way to drift when the R button is held
    5225    if (racer->drift_direction == 0 && gCurrentRacerInput & R_TRIG && racer->velocity < -3.0 &&
    5226        (gCurrentStickX > 15 || gCurrentStickX < -15)) {
    ⋮
    5234    // Disable drifting if going too slow
    5235    if (racer->velocity > -2.0) {
    5236        racer->drift_direction = 0;
    ⋮
    5238    // Get top speed value
    5239    topSpeed = handle_racer_top_speed(obj, racer);
    5240    // If currently drifting, apply a minor speed multiplier and tilt the natural steering towards the drift direction
    5241    if (gCurrentRacerInput & R_TRIG && racer->drift_direction != 0) {
    5242        topSpeed *= 1.1;
    ⋮
    5249    } else {
    ⋮
    
    src/racer.c lines 5224–5251 at a5eb080 · upstream ↗
    5519    racer->velocity -= traction * racer->throttle;
    
    src/racer.c line 5519 at a5eb080 · upstream ↗
    4751        if (racer->drift_direction != 0) {
    4752            if (racer->drift_direction < 0 && gCurrentStickX >= 26) {
    4753                racer->unk16E += updateRate;
    ⋮
    4755                    racer->unk16E = 0;
    ⋮
    4757            } else if (racer->drift_direction > 0 && gCurrentStickX <= -26) {
    4758                racer->unk16E -= updateRate;
    ⋮
    4760                    racer->unk16E = 0;
    ⋮
    4762            } else {
    4763                racer->unk16E = 0;
    ⋮
    4769            if (spB8 > 80.0f) {
    4770                racer_play_sound(racerObj, SOUND_CAR_BRAKE);
    4771                racer->spinout_timer = -racer->drift_direction;
    ⋮
    
    src/racer.c lines 4751–4785 at a5eb080 · upstream ↗
    4794        if (racer->spinout_timer != 0) {
    4795            racer_spinout_car(racerObj, racer, updateRate, updateRateF);
    4796        } else if (racer->groundedWheels > 0) {
    4797            update_player_car_velocity_ground(racerObj, racer, updateRate, updateRateF);
    
    src/racer.c lines 4794–4797 at a5eb080 · upstream ↗
    1148void update_drift_state_counter(Player* player, s8 playerIndex) {
    1149    if (((s16) player->unk_0C0 / DEGREES(1)) > 0) {
    1150        if (((s32) player->steerPosition >> 16) <= -10) {
    1151            if (player->driftStateCounter <= 100) {
    1152                player->driftStateCounter++;
    ⋮
    1158            if ((player->driftStateCounter >= 18) && (player->driftStateCounter < 100)) {
    1159                if (player->driftState < 3) {
    1160                    player->driftState++;
    
    src/player_controller.c lines 1148–1160 at 58cfcb0 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  3. ^ abIn Ridge Racer's Japanese release (SLPS-00001), when a slide ends (func_80027734) the car's direction of travel snaps to its heading and its speed is multiplied by 1 − w²/2²⁰, where w is the slip angle between them folded to at most a quarter turn: a slide that ends at 45° keeps 75% of its speed and one at 90° keeps none (computed). The part taken off keeps moving the car along its old direction in state 2 (func_80027F60), shrinking to 31/32 each update with the leftover angle, and the car returns to grip (state 0) when both reach 0.Codekazuyette/rr-decomp
    How we know
    71            D_801D7E30 = t = func_80019CA8(q->dir, car->ang);
    72            D_80173438 = q->dir;
    73            q->dir = car->ang;
    74            w = t < 0 ? -t : t;
    75            if (w > 0x400)
    76                w = 0x800 - w;
    77            w = w * w;
    78            D_8007C4E8 = w * q->spd / 0x100000;
    79            q->spd = (0x100000 - w) * q->spd / 0x100000;
    80            q->w5C = 2;
    
    src/fn/func_80027734.c lines 71–80 at 3b42b36 · upstream ↗
    26    car->u.c.vx = func_80044D0C(car->u.c.dir + D_801D7E30) * car->u.c.spd / 256;
    ⋮
    30    car->u.c.vx = func_80044D0C(D_80173438) * D_8007C4E8 / 256 + s * v.vz / 4096;
    ⋮
    38    D_8007C4E8 = D_8007C4E8 * 31 / 32;
    39    D_801D7E30 = D_801D7E30 * 31 / 32;
    40    if (D_8007C4E8 == 0 && D_801D7E30 == 0)
    41        q->slide = 0;
    
    src/fn/func_80027F60.c lines 26–41 at 3b42b36 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  4. ^In Ridge Racer's Japanese release (SLPS-00001), car_simulate gives a car in a slide (state 1) an eighth of the engine drive it gets in the other states, and lets its speed fall by 0.4% an update instead of 6%. The slide handler (func_80027734) then scales that drive by (0x200 − w)/0x200 for a slip angle w up to a quarter turn: full drive with no slip, none at 45°, and a pull against the motion beyond (computed). func_80026CA8 adds the drive along the heading, but the slide handler saves the direction of travel before the call and restores it after, so in a slide the drive changes only the speed.Codekazuyette/rr-decomprevised
    How we know
    191    q->w58 = q->rpm * e->a;
    192    if (q->type == 1) {
    193        q->w4C = q->w58 / 256 / 32 / 128;
    194        q->spd = q->spd * 996 / 1000;
    195    } else {
    196        q->w4C = q->w58 / 256 / 32 / 16;
    197        q->spd = q->spd * 94 / 100;
    
    src/fn/func_80019CF4.c lines 191–198 at 3b42b36 · upstream ↗
    85    d = func_80019C6C(car->ang, q->dir);
    86    if (d > 0x400)
    87        q->w4C = q->w4C / 2 + (u = (0x3600 - a) * 4) * q->w4C * (d - 0x400) / 1024 / 0x3600;
    88    else
    89        q->w4C = (0x200 - d) * q->w4C / 512;
    90    d = q->dir;
    91    func_80026CA8(car);
    
    src/fn/func_80027734.c lines 85–91 at 3b42b36 · upstream ↗
    12    v.vx = (func_80044D0C(p->b) * p->r) / 4 + func_80044D0C(p->a) * p->d;
    ⋮
    15    p->r = func_80040B54(p->r * p->r + p->d * p->d + (p->r * 2 * p->d * (t / 4096)) / 4096) >> 6;
    16    p->b = 0x400 - func_800187A0(v.vx, v.vz);
    
    src/fn/func_80026CA8.c lines 12–16 at 3b42b36 · 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

Sources

Code