Drift boost
A burst of speed earned by drifting through a turn and charging the drift before letting it go.
On this page
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
| Game | Year | How | Note |
|---|---|---|---|
| Diddy Kong Racing | 1997 | Held speed | holding R through a car's power slide raises its top speed by a tenth, and the slide ends with no boost |
| Mario Kart 64 | 1996 | Stick stages | 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 |
Every claim about this mechanic, by game (7)
References
- ^ 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 raisesdriftStateby 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 withdriftStateat 2 or more, the kart getsMINI_TURBO_EFFECTfor 31 player updates (computed), during which a term in its forward force moves toward 580 by a fifth of the gap each update.Coden64decomp/mk64How 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 turninclude/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 leftinclude/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.
- ^ 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.
- ^ 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 Ridge Racer's Japanese release (SLPS-00001),
car_simulategives 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-decomprevisedHow 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.
Sources
Code
- n64decomp. 2026. “mk64: a decompilation of Mario Kart 64 (n64decomp/mk64).” Commit 58cfcb0. n64decomp/mk64 @ 58cfcb0 · licence, all uses
- DavidSM64 and Diddy-Kong-Racing contributors. 2026. “Diddy-Kong-Racing: a decompilation of Diddy Kong Racing (DavidSM64/Diddy-Kong-Racing).” Commit a5eb080. DavidSM64/Diddy-Kong-Racing @ a5eb080 · licence, all uses
- kazuyette. 2026. “Ridge Racer decompilation (kazuyette/rr-decomp).” Commit 3b42b36. kazuyette/rr-decomp @ 3b42b36 · licence, all uses