Claim set · data/claims/excitebike64.yaml

Excitebike 64 (the chasmlol/excitebike64 decompilation)

Game: Excitebike 64.

In Excitebike 64's US Rev 1 build, engine_update_heat moves a rider's engine heat each bike update by a rate from sEngineHeatRates, picked by whether the heat is above 7000 and by the drive: Z (the turbo), else A (the throttle), else neither. At 7000 or below the rates are −20 with neither, +20 on the throttle, and +40 on the turbo; above 7000 they're −12, −8, and +20. A positive rate while Z is held is divided by the rider's turbo stat, which is 1.0 for CPU riders. The heat is held between 0 and 12000. Reaching 12000 sets overheated, and while it's set the rate is −20 whatever is held, until the heat is back to 7000 or below. At 60 updates a second, a turbo stat of 1.0 takes a cold engine to 12000 in 425 updates, about 7.1 seconds, and an overheat lasts 250 updates, about 4.2 seconds; the throttle alone holds the heat around 7000 (computed). While the rear wheel is on the ground and the event isn't stopped (EVENT_STOPPED), a surface flagged SURFACE_COOLS_ENGINE (commented "resets the engine heat") sets the heat to 0. excitebike64/turbo-heat

About: Excitebike 64 Overheat

Value: 12000 engine heat (overheat threshold)

CodeExcitebike 64 decompilation (chasmlol/excitebike64) · src/game/unnamed/s0_800358C0.c#L56-L106/* The rider's drive: 2 turbo (Z), 1 throttle (A), 0 neither. */ … if (rider->input & INPUT_Z) { return 2; } throttle = rider->input & INPUT_A; return throttle != 0; … drive = drive_input(rider); hot = 0; if (rider->engine.heat > 7000.0f) { hot = 1; …Excitebike 64 decompilation (chasmlol/excitebike64) · src/data/game_800C2280.c#L3999-L4002f32 sEngineHeatRates[0x6] = { /* 0x000 */ -20.0f, 20.0f, 40.0f, -12.0f, /* 0x010 */ -8.0f, 20.0f, };Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/unnamed/s0_800358C0.c#L114-L116rider = &gRiders[riderIdx]; engine_update_heat(rider);Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/unnamed/s0_800358C0.c#L125-L125if (rider->rearWheel.airTicks < 1 && (gEvent.flags & EVENT_STOPPED) == 0) {Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/unnamed/s0_800358C0.c#L163-L165if (rider->rearWheel.surface->flags & SURFACE_COOLS_ENGINE) { rider->engine.heat = 0.0f; }Excitebike 64 decompilation (chasmlol/excitebike64) · include/structs/surface.h#L16#define SURFACE_COOLS_ENGINE 0x0200 /* resets the engine heat */Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L349-L352rider->bike.mass = 250.0f; rider->wallFriction = 0.3f; rider->landing = 1.0f; rider->turbo = 1.0f;Checked by claude, 2026-10-22 — read engine_update_heat and drive_input, the heat-rate table and the power scales in game_800C2280.c (no VERSION branch until L4006), engine_update's call and its cooling-surface test, and the CPU branch of bike_apply_rider_stats; engine_update runs once per bike_update (bikenew.c L2578, L2634), and FRAME_RATE is 60 outside the European build. Worked the times from the rates: 7000/40 + 5000/20 = 425, 5000/20 = 250.

Human riders take the turbo stat of their profile in sRiderStatsTable (bikenew.c L343), a table the repo holds as raw words; decoded, the six profiles of floats at its head have turbo stats from 1.0 to 1.55, which would stretch the time to overheat by the same factor. The statement leaves them out because the table isn't quotable as text. engine_update_heat runs once per call even when a far CPU rider takes a double step (ticks = 2).

Cited by: Excitebike 64, Overheat

In Excitebike 64's US Rev 1 build, engine_update scales the engine's torque by sTurboPowerScale (1.225) while Z, the turbo, is held, by sThrottlePowerScale (0.75) on A, the throttle, alone, and by sOverheatPowerScale (0.3) while the engine is overheated, whichever of the two is held. The scale applies only while the rear wheel is on the ground and the event isn't stopped (EVENT_STOPPED). With neither button held, or with either held while the event is stopped, the torque is −3728.4995 (commented "engine braking") above a speed of 1 and 0 below it. The turbo gives about 1.63 times the throttle's torque, and an overheated engine 0.4 times the throttle's and about 0.24 times the turbo's (computed). excitebike64/turbo-power

About: Excitebike 64 Overheat

Value: 0.3 × engine torque (overheated)

CodeExcitebike 64 decompilation (chasmlol/excitebike64) · src/game/unnamed/s0_800358C0.c#L190-L206if ((rider->input & (INPUT_Z | INPUT_A)) != 0 && (gEvent.flags & EVENT_STOPPED) == 0) { if (rider->rearWheel.airTicks < 1) { if (rider->engine.overheated != 0) { tmp = sOverheatPowerScale; } else if (rider->input & INPUT_Z) { tmp = sTurboPowerScale; } else { tmp = sThrottlePowerScale; } torque = torque * tmp; rider->engine.torque = torque; } …Excitebike 64 decompilation (chasmlol/excitebike64) · src/data/game_800C2280.c#L4003-L4005f32 sTurboPowerScale = 1.225f; f32 sThrottlePowerScale = 0.75f; f32 sOverheatPowerScale = 0.3f;Checked by claude, 2026-10-22 — read engine_update's torque scaling at L190-L206 (after the LodgeNet branch, which ends at L184) and the three scales in game_800C2280.c, outside any VERSION branch. Ratios: 1.225/0.75, 0.3/0.75, 0.3/1.225.

The scaled value is the engine torque from engine_torque_at_rpm; the drive force also passes through the gear ratio, the rider's power stat, and the tire's grip (sTurboTraction with the turbo, bikenew.c L711), not traced here.

Cited by: Excitebike 64, Overheat

In Excitebike 64's US Rev 1 build, bike_update_jump boosts a human rider who leaves the ground while riding and holding Z, the turbo, first pressed fewer than 10 updates earlier (turboPressFrame), on a jump whose predicted time in the air (landingTime, twice the vertical speed over gravity) is longer than a minimum: 0.25 seconds up to a takeoff speed of 10, 0.5 above 20, and linear between. Below a speed of 20 and while the engine isn't overheated, the bike's velocity is scaled so its speed gains 5, less half the speed above 10: 5 at 10 or less, 2.5 at 15, and nothing at 20. If the bike's pitch (rot[0]) is −0x17FF or more, its angular velocity also loses 2 times its right axis; the LodgeNet build subtracts 3, and the decompilers comment that "retail pitches the bike less". CPU riders get no takeoff boost. excitebike64/takeoff-turbo

About: Excitebike 64 Overheat

Value: 5 speed gained at takeoff (at a speed of 10 or less)

CodeExcitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2235-L2250if (rider->rearWheel.airTicks > 0 && rider->frontWheel.airTicks > 0) { if (rider->airFrames <= 0) { … rider->landingTime = (rider->bike.vel.y + rider->bike.vel.y) / GRAVITY; … takeoffSpeed = rider->speed; minAirTime = 0.5f; if (!(takeoffSpeed > 20.0f)) { minAirTime = 0.25f; if (takeoffSpeed > 10.0f) { minAirTime = (takeoffSpeed - 10.0f) / 40.0f + 0.25f; } …Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2258-L2285if (rider->isCpu == 0 && rider->crashState == CRASH_STATE_RIDING && gRaceFrame - rider->turboPressFrame < 10 && (rider->input & INPUT_Z)) { /* turbo at takeoff: a boost (none when overheated) */ speed = rider->speed; if (speed < 20.0f && rider->engine.overheated == 0) { boost = 5.0f; if (speed > 10.0f) { boost = 5.0f - (speed - 10.0f) * 0.5f; } if (speed != 0.0f) { speed = boost / speed + 1.0f; } else { speed = 0.0f; …Checked by claude, 2026-10-22 — read bike_update_jump's takeoff branch from L2235 to the boost's end at L2285, the US Rev 1 side of its VERSION branch; gRaceFrame counts updates (bikes_update adds its ticks, L2708). Scaling the velocity by boost/speed + 1 adds boost to the speed.

The statement doesn't say which way the angular velocity change turns the bike; the comment calls it pitch. A speed of 0 zeroes the velocity, a branch a rider leaving the ground can't reach.

Cited by: Excitebike 64

In Excitebike 64's US Rev 1 build, bike_handle_landing runs when a wheel touches down. After 41 or more updates in the air (airFrames), it takes the front wheel's groundDist, the signed offset along the bike's up axis from the wheel's point on the bike to the ground plus 0.5, which grows as the ground comes nearer, less the rear wheel's, so the difference is negative when the rear wheel is nearer the ground. Below −2.0 the rider crashes at once (ANIM_CRASH_BACK); from −2.0 to under −0.8 that crash is queued (pendingCrash); from −0.8 to under −0.3 the landing is rough (roughLanding); from −0.3 to under 0.3 it's clean, and the bike's turning is stopped; from 0.3 to under 0.6 it's rough; from 0.6 up a crash is queued (ANIM_CRASH_FRONT). A queued crash becomes a rough landing when the impact, the bike's velocity along the two wheels' ground normals added together, is above −10. Whatever the wheels, a rider still in a trick animation after 11 or more updates in the air crashes. By the atlas's reading the wheel difference measures the bike's pitch against the ground it lands on. excitebike64/landing-grade

About: Excitebike 64 Landing angle

Value: 0.3 wheel difference, clean landing band (±)

CodeExcitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L1968-L2017/* Lands the bike: cleanly, roughly or in a crash, from the wheels' heights and the impact. */ void bike_handle_landing(Rider *arg) … impactVel = vec3_dot(vel, &rider->rearWheel.normal.x) + vec3_dot(vel, &rider->frontWheel.normal.x); if ((u8)rider->anim < ANIM_TRICK_COUNT && rider->airFrames >= 0xB) bike_crash_begin(rider, ANIM_CRASH_FRONT); … if (rider->airFrames < 0x29) goto record_impact; wheelDiff = rider->frontWheel.groundDist - rider->rearWheel.groundDist; … if (wheelDiff < -2.0f) { …Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2018-L2024if (rider->landingAssist != 0) { f32 zf = 0.0f; rider->bike.angVel.z = zf; rider->bike.angVel.y = zf; rider->bike.angVel.x = zf; }Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2462-L2463if (rider->airFrames > 0) { bike_handle_landing(rider);Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L470-L533axisPos[1] = rider->bike.pos.y + rider->bike.fwd.y * fwdOffset; … pointY = axisPos[1] + dist * rider->bike.up.y; … diff = groundY - pointY; tolerance = 0.002f; slope = -1.0f; … dist -= slope * diff; … dist += 0.5f; … …Excitebike 64 decompilation (chasmlol/excitebike64) · include/structs/rider.h#L252/* 0x28 */ f32 groundDist; /* along the bike's up axis */Excitebike 64 decompilation (chasmlol/excitebike64) · include/structs/rider.h#L47#define ANIM_NONE (-1)Checked by claude, 2026-10-25 — read bike_wheel_find_ground (L459-L540), which sets groundDist, and bike_handle_landing whole (L1968-L2037) and its call in bike_update_jump's else branch, which runs once either wheel is down (the in-air branch needs both wheels' airTicks above 0, L2235); ANIM_NONE is −1, so the trick test's u8 cast leaves it out. No VERSION branch in the function.

Which way each crash animation throws the rider isn't stated; the names are the decompilers'. A queued crash (pendingCrash > 0) is carried out by bike_update once both wheels' airTicks are under 10 (L2537-L2541). The landing assist also zeroes the bike's angular velocity in the clean band, which is what "the bike's turning is stopped" means. Until 2026-10-25 the statement read the difference as negative when the front wheel is nearer, taking groundDist for a plain distance; bike_wheel_find_ground solves for the offset d at which the axis point plus d times the up axis reaches the ground's height, so with the ground below d is negative and rises as the ground comes nearer. The crash names fit that sign: a large negative difference (rear wheel down first) queues ANIM_CRASH_BACK, a large positive one ANIM_CRASH_FRONT.

Cited by: Excitebike 64, Landing angle

In Excitebike 64's US Rev 1 build, a rough landing (roughLanding, commented "frames since a rough landing (more drag)") raises the bike's drag coefficient, the one multiplied by the square of its speed and applied against its velocity, to at least 7.0; otherwise it's 0.21 in the air and, on the ground, 0.21 times the rear wheel's surface drag, softened during a wheelie (wheelieTimer not 0) to (drag − 1) × 0.25 + 1. bike_update_jump adds each update's ticks to the counter, which starts at 1, and clears it at 60, so the extra drag lasts 59 updates, about a second (computed). On a surface whose drag is 1, that's about 33 times the usual coefficient (computed). excitebike64/rough-landing

About: Excitebike 64 Landing angle

Value: 7 drag coefficient floor (rough landing)

CodeExcitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L1546-L1562if (rider->speed != 0.0f) { … minDrag = 0.0f; if (rider->roughLanding != 0) { minDrag = 7.0f; } drag = 0.21000001f; if (rider->airFrames <= 0) { drag = (rider->wheelieTimer != 0 ? (rider->rearWheel.surface->drag - 1.0f) * 0.25f + 1.0f : rider->rearWheel.surface->drag) * 0.21000001f; } if (drag < minDrag) { drag = minDrag; …Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L1581-L1584rate = drag / rider->speed; force.x -= rider->bike.vel.x * rate; force.y -= rider->bike.vel.y * rate; force.z -= rider->bike.vel.z * rate;Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2226-L2231if (rider->roughLanding != 0) { rider->roughLanding += ((u8 *)&gPhysTicks)[3]; /* its low byte */ if (rider->roughLanding >= 60) { rider->roughLanding = 0; } }Excitebike 64 decompilation (chasmlol/excitebike64) · include/structs/rider.h#L401/* 0x5CD */ u8 roughLanding; /* frames since a rough landing (more drag), 0 none */Checked by claude, 2026-10-22 — read the drag term of the force sum (L1546-L1584) and the counter at the head of bike_update_jump; bikes_update(1) runs each update (min.c L1301), so gPhysTicks is 1 for riders on a single step. With a wheelie the surface drag is softened (the L1557 ternary), which the statement leaves to the quote.

Surface drag values are in the surface table, ROM data the atlas doesn't hold as text, so the 33 times is for a drag of 1 only (7.0 / 0.21).

Cited by: Excitebike 64, Landing angle

In Excitebike 64's US Rev 1 build, bike_update_jump sets landingAssist (commented "the bike will land straight: pitched to the ground") on a falling bike more than 30 updates into a jump and not in a wheelie, once its predicted landing (landingTime) is under 0.25 seconds away: always for a CPU rider, and for a human when the pitch part of the misalignment between the bike's up axis and the landing point's ground normal, the dot product of their cross product with the bike's right axis, is smaller in size than 10 times the rider's landing stat. While it's set, bike_align_to_ground sets the bike's turning to a pitch toward the ground's slope at twice the angle over the time left plus 0.1 seconds, at most 2 radians a second; it returns without setting anything when the landing point's ground normal has a y below 0.5 or the angle's sine is 0. Either way, while the flag is set the player's air pitch input isn't read. For unit axes that dot product is at most 1, and the six profiles of floats at the head of sRiderStatsTable set landing from 0.25 to 5, so the human test passes for every one (computed); the code reads the stat nowhere else. excitebike64/landing-assist

About: Excitebike 64 Landing angle

Value: 2 radians a second (largest assisted pitch rate)

CodeExcitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2429-L2453if (rider->landingAssist != 0) { bike_align_to_ground(rider); } else if (rider->landingTime < 0.25f && rider->bike.vel.y < 0.0f && rider->airFrames > FRAMES(30) && rider->wheelieTimer == 0) { if (rider->isCpu == 0) { … height_get_ground_normal(&vec.x); axis.x = rider->bike.up.y * vec.z - vec.y * rider->bike.up.z; axis.y = rider->bike.up.z * vec.x - vec.z * rider->bike.up.x; axis.z = rider->bike.up.x * vec.y - vec.x * rider->bike.up.y; tilt = vec3_dot(&axis.x, &rider->bike.right.x); limit = rider->landing * 10.0f; if (tilt > 0.0f ? tilt < limit : -tilt < limit) { …Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2088-L2136/* In the air: pitches the bike towards the slope of the ground where it will land. */ … if (normal.y < 0.5f) { return; } … sinAngle = vec3_dot(&axis.x, &rider->bike.right.x); … if (sinAngle == 0.0f) { return; } angleWord = math_asini((s32)(sinAngle * 16384.0f)); …Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L1641-L1653if (rider->landingAssist == 0) { … pitchError = rider->airPitchInput; … localTorque.x += ((f32)(pitchError / 4) * 3.1415927f * 3.0517578e-05f - rider->localAngVel.x * 0.0625f) * (250.0f * FRAME_RATE);Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/height.c#L585-L586/* The unit normal of the ground triangle found last. */ void height_get_ground_normal(f32 *out)Excitebike 64 decompilation (chasmlol/excitebike64) · include/structs/rider.h#L400/* 0x5CC */ u8 landingAssist; /* the bike will land straight: pitched to the ground (bike_align_to_ground) */Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L333-L337void bike_apply_rider_stats(Rider *rider, s32 profile) { if (rider->isCpu == 0) { rider->bike.mass = 250.0f; rider->landing = sRiderStatsTable[profile].landing;Excitebike 64 decompilation (chasmlol/excitebike64) · src/data/game_800C2280.c#L3725-L3740u32 sRiderStatsTable[0x50] = {Checked by claude, 2026-10-22 — read the assist test in bike_update_jump, bike_align_to_ground (L2088-L2136), the air branch of the force sum that reads airPitchInput only when landingAssist is 0 (L1641-L1650), and height_get_ground_normal, which divides by the length; up and right are rows of the bike's rotation matrix from its quaternion. Decoded sRiderStatsTable's words as big-endian floats by the RiderStats layout (bikenew.c L316-L328): the first 0xF0 bytes are six profiles with landing 4, 0.5, 0.25, 0.7, 3, and 5; from 0xF0 on the table holds pointers. rider->landing is read only at L2447 (set at L337, L351, and in tuning mode 15 at L1983).

The six landing stats are decoded from the table's raw words, which the claim doesn't quote. The assist pitches the bike only about its right axis, so a sideways lean isn't corrected. Whether some landings still go wrong depends on how much pitch the capped rate can take out in the last quarter second; a probe could measure it.

Cited by: Excitebike 64

In Excitebike 64's US Rev 1 build, riders are rubber-banded through timeScale, which multiplies the length of each of a rider's physics steps (gPhysDeltaTime). After the countdown, outside time trial and with a human racing, race_update_riders steps each CPU rider's scale by 0.0002 per update toward a target: 1 plus its skill (spread evenly over about ±0.1 by race_init_ai_skills, and used when there are two or more CPU riders), less 0.1 when it's more than 64 ahead of the CPU riders' average raceDist, less the CPU pack's lead over the humans' average beyond 30, divided by 256 and held to ±0.15, all times the track's cpuSpeed for the difficulty (a finished rider targets 1, the Beat This cheat uses the hardest difficulty's cpuSpeed plus 0.05, and a duel 1.15 times the track's). The code's comment says "CPU riders slow down as their pack leads the humans by more than 30 m and speed up as it falls behind". A human's scale steps by 0.001 toward 1 plus their distance behind the humans' average (plus 16 when it's over 2) over 1024, held between 0.95 and 1.05. With one human the target is 1, and since the step has no dead zone the scale alternates between 1 and 1.001. Mario Kart 64 instead adds a force term toward 380 while a pacing flag is set (mk64/rubber-band). excitebike64/cpu-time-scale

About: Excitebike 64 Rubber-band AI

Value: 0.15 largest pack-lead change to a CPU rider's time scale (±)

CodeExcitebike 64 decompilation (chasmlol/excitebike64) · src/game/bikenew.c#L2529-L2530gPhysTicks = ticks; gPhysDeltaTime = (f32)gPhysTicks * rider->timeScale / (f32)FRAME_RATE;Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/unnamed/s0_80062F50.c#L541-L601} else if (gGame.mode != GAME_MODE_TIME_TRIAL && gEvent.state >= 5) { /* after the countdown: CPU riders slow down as their pack leads the humans by more than 30 m and speed up as it falls behind, around the track's speed for the difficulty and their own skill; humans close up */ cpuLead = ((cpuAvg - humanAvg) - 30.0f) * 0.00390625f; if (cpuLead > 0.15f) { cpuLead = 0.15f; } else if (cpuLead < -0.15f) { cpuLead = -0.15f; } … if (rider->isCpu != 0) { scale = 0.0f; …Excitebike 64 decompilation (chasmlol/excitebike64) · src/game/unnamed/s0_80062F50.c#L788-L807/* Spreads the CPU riders' skills evenly from -0.1 to 0.1 in sAiRiderOrder (then +0.01 for exactly 0.1, -0.01 for the others) and sets their time scale to 1.03 - skill. */ … gRiders[sAiRiderOrder[i]].aiSkill = (i - (count - 1) * 0.5f) / ((count - 1) * 5.0f);mk64: a decompilation of Mario Kart 64 (n64decomp/mk64) · include/defines.h#L479#define CPU_FAST_EFFECT 0x200000 // CPU Rubberbanding flagmk64: a decompilation of Mario Kart 64 (n64decomp/mk64) · src/player_controller.c#L3086-L3092if ((player->type & PLAYER_HUMAN) != PLAYER_HUMAN) { if ((player->effects & CPU_FAST_EFFECT) == CPU_FAST_EFFECT) { move_f32_towards(&player->unk_0E8, 380.0f, 0.5f); } else { move_f32_towards(&player->unk_0E8, 0.0f, 0.1f);Checked by claude, 2026-10-22 — read race_update_riders from its averages (cpuAvg over isCpu 1 riders, humanAvg over humans) through the time-scale branch, race_init_ai_skills, and bike_update's step length; race_update_riders runs from bikes_update each update outside time trial and the hill climb, tutorial, and stunt modes (bikenew.c L2755-L2771). The MK64 lines are those mk64/rubber-band reads.

Units of raceDist are metres by the code's comment. With one human the human average is that rider's own distance, so the human branch targets exactly 1. A time scale moves every physics step, so it speeds or slows the whole bike (acceleration, top speed, and air time alike), not one force; heat (excitebike64/turbo-heat) isn't scaled. The two extra riders that appear in a single-player race (isCpu 2) take the CPU branch but aren't in the CPU average. Skill spread: race_init_ai_skills gives (i − (n − 1)/2) / (5(n − 1)), then subtracts 0.01 from every value except exactly 0.1.

Cited by: Excitebike 64