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

The atlas reads Excitebike 64 through chasmlol’s decompilation, C that builds the hotel, US, and European ROMs byte for byte. Its functions and fields carry names and comments from the decompilation; the claims quote them as theirs and read the US Rev 1 cartridge. Nothing has been measured in the game yet.

The turbo is paid for in engine heat. Below 7000 the throttle and the turbo both heat the engine, and above it only the turbo does, divided by the rider’s turbo stat; at 12000 the engine overheats and cools at a fixed rate until it’s back to 7000, about 4.2 seconds1. Overheated, the engine gives 0.32 of its torque whichever button is held, against 0.75 on the throttle and 1.225 on the turbo2. A turbo pressed in the last 10 updates before a jump adds up to 53 to the bike’s speed at takeoff, less above a speed of 10 and none at 20 or overheated3.

The landing is graded by the difference between the two wheels’ distances to the ground when the first touches down. Within ±0.34 the landing is clean, further out it’s rough, and further still the rider crashes, unless the impact is soft4. A rough landing raises the drag to at least 7.05 for about a second5. In the last quarter second of a long jump the game turns the bike’s pitch toward the ground’s slope, at up to 26 radians a second; a rider stat gates this for human riders, but every profile the atlas has decoded passes the test6.

The CPU riders are rubber-banded through time itself: each one’s physics step is scaled, slower as their pack pulls more than 30 ahead of the humans and faster as it falls behind, by up to ±0.157. In a multiplayer race, trailing humans get the same treatment, up to 5% faster7. Mario Kart 64 adds a force term to its CPU karts instead7.

Mechanics

MechanicKindHow
OverheatPower cutthe turbo heats the engine to an overheat at 12000, after which the engine gives 0.3 of its torque whichever button is held, and no takeoff boost, until the heat falls to 7000
Landing angleGradedthe gap between the wheels' distances to the ground at touchdown sorts a landing into clean, rough (more drag for about a second), or a crash
Rubber-band AITime scaleevery CPU rider's physics run up to 15% faster or slower by how far the CPU pack leads the humans, around a lead of 30
Every claim about this game, by concept (7)
Landing angleIn 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.Code
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).Code
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.Code
OverheatIn 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.Code
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).Code
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.Code
Rubber-band AIIn 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).Code

References

  1. ^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.Codechasmlol/excitebike64revised
    How we know
    56/* The rider's drive: 2 turbo (Z), 1 throttle (A), 0 neither. */
    ⋮
    61    if (rider->input & INPUT_Z) {
    62        return 2;
    ⋮
    64    throttle = rider->input & INPUT_A;
    65    return throttle != 0;
    ⋮
    78    drive = drive_input(rider);
    79    hot = 0;
    80    if (rider->engine.heat > 7000.0f) {
    81        hot = 1;
    ⋮
    83    if (rider->engine.overheated) {
    84        hot = drive = 0;
    ⋮
    86    rate = sEngineHeatRates[hot][drive];
    ⋮
    
    src/game/unnamed/s0_800358C0.c lines 56–106 at 9cdb194 · upstream ↗
    3999f32 sEngineHeatRates[0x6] = {
    4000    /* 0x000 */ -20.0f, 20.0f, 40.0f, -12.0f,
    4001    /* 0x010 */ -8.0f, 20.0f,
    
    src/data/game_800C2280.c lines 3999–4002 at 9cdb194 · upstream ↗
    115    rider = &gRiders[riderIdx];
    116    engine_update_heat(rider);
    
    src/game/unnamed/s0_800358C0.c lines 114–116 at 9cdb194 · upstream ↗
    125    if (rider->rearWheel.airTicks < 1 && (gEvent.flags & EVENT_STOPPED) == 0) {
    
    src/game/unnamed/s0_800358C0.c line 125 at 9cdb194 · upstream ↗
    163        if (rider->rearWheel.surface->flags & SURFACE_COOLS_ENGINE) {
    164            rider->engine.heat = 0.0f;
    
    src/game/unnamed/s0_800358C0.c lines 163–165 at 9cdb194 · upstream ↗
    16#define SURFACE_COOLS_ENGINE        0x0200 /* resets the engine heat */
    
    include/structs/surface.h line 16 at 9cdb194 · upstream ↗
    349    rider->bike.mass = 250.0f;
    350    rider->wallFriction = 0.3f;
    351    rider->landing = 1.0f;
    352    rider->turbo = 1.0f;
    
    src/game/bikenew.c lines 349–352 at 9cdb194 · 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. ^ abIn 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).Codechasmlol/excitebike64revised
    How we know
    190    if ((rider->input & (INPUT_Z | INPUT_A)) != 0 && (gEvent.flags & EVENT_STOPPED) == 0) {
    191        if (rider->rearWheel.airTicks < 1) {
    192            if (rider->engine.overheated != 0) {
    193                tmp = sOverheatPowerScale;
    194            } else if (rider->input & INPUT_Z) {
    195                tmp = sTurboPowerScale;
    196            } else {
    197                tmp = sThrottlePowerScale;
    ⋮
    199            torque = torque * tmp;
    200            rider->engine.torque = torque;
    ⋮
    202    } else if (1.0f < rider->speed) {
    203        rider->engine.torque = -3728.4995f; /* engine braking */
    ⋮
    
    src/game/unnamed/s0_800358C0.c lines 190–206 at 9cdb194 · upstream ↗
    4003f32 sTurboPowerScale = 1.225f;
    4004f32 sThrottlePowerScale = 0.75f;
    4005f32 sOverheatPowerScale = 0.3f;
    
    src/data/game_800C2280.c lines 4003–4005 at 9cdb194 · 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. ^ abIn 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.Codechasmlol/excitebike64
    How we know
    2235    if (rider->rearWheel.airTicks > 0 && rider->frontWheel.airTicks > 0) {
    2236        if (rider->airFrames <= 0) {
    ⋮
    2240            rider->landingTime = (rider->bike.vel.y + rider->bike.vel.y) / GRAVITY;
    ⋮
    2242            takeoffSpeed = rider->speed;
    2243            minAirTime = 0.5f;
    2244            if (!(takeoffSpeed > 20.0f)) {
    2245                minAirTime = 0.25f;
    2246                if (takeoffSpeed > 10.0f) {
    2247                    minAirTime = (takeoffSpeed - 10.0f) / 40.0f + 0.25f;
    ⋮
    2250            if (minAirTime < rider->landingTime) {
    
    src/game/bikenew.c lines 2235–2250 at 9cdb194 · upstream ↗
    2258                if (rider->isCpu == 0 && rider->crashState == CRASH_STATE_RIDING && gRaceFrame - rider->turboPressFrame < 10 && (rider->input & INPUT_Z)) {
    2259                    /* turbo at takeoff: a boost (none when overheated) */
    2260                    speed = rider->speed;
    2261                    if (speed < 20.0f && rider->engine.overheated == 0) {
    2262                        boost = 5.0f;
    2263                        if (speed > 10.0f) {
    2264                            boost = 5.0f - (speed - 10.0f) * 0.5f;
    ⋮
    2266                        if (speed != 0.0f) {
    2267                            speed = boost / speed + 1.0f;
    2268                        } else {
    2269                            speed = 0.0f;
    ⋮
    2271                        rider->bike.vel.x *= speed;
    ⋮
    
    src/game/bikenew.c lines 2258–2285 at 9cdb194 · 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. ^ abIn 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.Codechasmlol/excitebike64
    How we know
    1968/* Lands the bike: cleanly, roughly or in a crash, from the wheels' heights and the impact. */
    1969void bike_handle_landing(Rider *arg)
    ⋮
    1976    impactVel = vec3_dot(vel, &rider->rearWheel.normal.x) + vec3_dot(vel, &rider->frontWheel.normal.x);
    1977    if ((u8)rider->anim < ANIM_TRICK_COUNT && rider->airFrames >= 0xB)
    1978        bike_crash_begin(rider, ANIM_CRASH_FRONT);
    ⋮
    1986    if (rider->airFrames < 0x29)
    1987        goto record_impact;
    1988    wheelDiff = rider->frontWheel.groundDist - rider->rearWheel.groundDist;
    ⋮
    1990    if (wheelDiff < -2.0f) {
    1991        bike_crash_begin(rider, ANIM_CRASH_BACK);
    1992        goto soften;
    ⋮
    1994    if (wheelDiff < -0.8f) {
    ⋮
    
    src/game/bikenew.c lines 1968–2017 at 9cdb194 · upstream ↗
    2018    if (rider->landingAssist != 0) {
    2019        f32 zf = 0.0f;
    2020        rider->bike.angVel.z = zf;
    2021        rider->bike.angVel.y = zf;
    2022        rider->bike.angVel.x = zf;
    
    src/game/bikenew.c lines 2018–2024 at 9cdb194 · upstream ↗
    2462        if (rider->airFrames > 0) {
    2463            bike_handle_landing(rider);
    
    src/game/bikenew.c lines 2462–2463 at 9cdb194 · upstream ↗
    471    axisPos[1] = rider->bike.pos.y + rider->bike.fwd.y * fwdOffset;
    ⋮
    476    pointY = axisPos[1] + dist * rider->bike.up.y;
    ⋮
    481    diff = groundY - pointY;
    482    tolerance = 0.002f;
    483    slope = -1.0f;
    ⋮
    489        dist -= slope * diff;
    ⋮
    495        pointY = axisPos[1] + dist * rider->bike.up.y;
    ⋮
    498        diff = groundY - pointY;
    ⋮
    508                slope = -1.0f;
    ⋮
    514    dist += 0.5f;
    ⋮
    533    wheel->groundDist = dist;
    
    src/game/bikenew.c lines 470–533 at 9cdb194 · upstream ↗
    252    /* 0x28 */ f32 groundDist;      /* along the bike's up axis */
    
    include/structs/rider.h line 252 at 9cdb194 · upstream ↗
    47#define ANIM_NONE                   (-1)
    
    include/structs/rider.h line 47 at 9cdb194 · 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

  5. ^ abIn 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).Codechasmlol/excitebike64revised
    How we know
    1546    if (rider->speed != 0.0f) {
    ⋮
    1551        minDrag = 0.0f;
    1552        if (rider->roughLanding != 0) {
    1553            minDrag = 7.0f;
    ⋮
    1555        drag = 0.21000001f;
    1556        if (rider->airFrames <= 0) {
    1557            drag = (rider->wheelieTimer != 0 ? (rider->rearWheel.surface->drag - 1.0f) * 0.25f + 1.0f : rider->rearWheel.surface->drag) * 0.21000001f;
    ⋮
    1559        if (drag < minDrag) {
    1560            drag = minDrag;
    ⋮
    1562        drag = drag * rider->speed * rider->speed;
    
    src/game/bikenew.c lines 1546–1562 at 9cdb194 · upstream ↗
    1581        rate = drag / rider->speed;
    1582        force.x -= rider->bike.vel.x * rate;
    1583        force.y -= rider->bike.vel.y * rate;
    1584        force.z -= rider->bike.vel.z * rate;
    
    src/game/bikenew.c lines 1581–1584 at 9cdb194 · upstream ↗
    2226    if (rider->roughLanding != 0) {
    2227        rider->roughLanding += ((u8 *)&gPhysTicks)[3]; /* its low byte */
    2228        if (rider->roughLanding >= 60) {
    2229            rider->roughLanding = 0;
    
    src/game/bikenew.c lines 2226–2231 at 9cdb194 · upstream ↗
    401    /* 0x5CD */ u8 roughLanding;    /* frames since a rough landing (more drag), 0 none */
    
    include/structs/rider.h line 401 at 9cdb194 · 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. ^ abIn 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.Codechasmlol/excitebike64revised
    How we know
    2429        if (rider->landingAssist != 0) {
    2430            bike_align_to_ground(rider);
    2431        } else if (rider->landingTime < 0.25f && rider->bike.vel.y < 0.0f && rider->airFrames > FRAMES(30) && rider->wheelieTimer == 0) {
    2432            if (rider->isCpu == 0) {
    ⋮
    2442                height_get_ground_normal(&vec.x);
    2443                axis.x = rider->bike.up.y * vec.z - vec.y * rider->bike.up.z;
    2444                axis.y = rider->bike.up.z * vec.x - vec.z * rider->bike.up.x;
    2445                axis.z = rider->bike.up.x * vec.y - vec.x * rider->bike.up.y;
    2446                tilt = vec3_dot(&axis.x, &rider->bike.right.x);
    2447                limit = rider->landing * 10.0f;
    2448                if (tilt > 0.0f ? tilt < limit : -tilt < limit) {
    2449                    rider->landingAssist = 1;
    ⋮
    
    src/game/bikenew.c lines 2429–2453 at 9cdb194 · upstream ↗
    2088/* In the air: pitches the bike towards the slope of the ground where it will land. */
    ⋮
    2110    if (normal.y < 0.5f) {
    2111        return;
    ⋮
    2116    sinAngle = vec3_dot(&axis.x, &rider->bike.right.x);
    ⋮
    2120    if (sinAngle == 0.0f) {
    2121        return;
    ⋮
    2123    angleWord = math_asini((s32)(sinAngle * 16384.0f));
    2124    angle = (f32)(s16)angleWord * 3.1415927f * 3.0517578e-05f;
    2125    time = rider->landingTime;
    2126    time += 0.1f;
    2127    rate = (angle + angle) / time;
    2128    if (rate > 2.0f) {
    ⋮
    
    src/game/bikenew.c lines 2088–2136 at 9cdb194 · upstream ↗
    1641        if (rider->landingAssist == 0) {
    ⋮
    1647                pitchError = rider->airPitchInput;
    ⋮
    1653            localTorque.x += ((f32)(pitchError / 4) * 3.1415927f * 3.0517578e-05f - rider->localAngVel.x * 0.0625f) * (250.0f * FRAME_RATE);
    
    src/game/bikenew.c lines 1641–1653 at 9cdb194 · upstream ↗
    585/* The unit normal of the ground triangle found last. */
    586void height_get_ground_normal(f32 *out)
    
    src/game/height.c lines 585–586 at 9cdb194 · upstream ↗
    400    /* 0x5CC */ u8 landingAssist;   /* the bike will land straight: pitched to the ground (bike_align_to_ground) */
    
    include/structs/rider.h line 400 at 9cdb194 · upstream ↗
    333void bike_apply_rider_stats(Rider *rider, s32 profile)
    ⋮
    335    if (rider->isCpu == 0) {
    336        rider->bike.mass = 250.0f;
    337        rider->landing = sRiderStatsTable[profile].landing;
    
    src/game/bikenew.c lines 333–337 at 9cdb194 · upstream ↗
    3725u32 sRiderStatsTable[0x50] = {
    
    src/data/game_800C2280.c lines 3725–3740 at 9cdb194 · 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

  7. ^ abcIn 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).Codechasmlol/excitebike64 · n64decomp/mk64revised
    How we know
    2529    gPhysTicks = ticks;
    2530    gPhysDeltaTime = (f32)gPhysTicks * rider->timeScale / (f32)FRAME_RATE;
    
    src/game/bikenew.c lines 2529–2530 at 9cdb194 · upstream ↗
    541    } else if (gGame.mode != GAME_MODE_TIME_TRIAL && gEvent.state >= 5) {
    542        /* after the countdown: CPU riders slow down as their pack leads the humans by more than 30 m and speed up as
    543           it falls behind, around the track's speed for the difficulty and their own skill; humans close up */
    544        cpuLead = ((cpuAvg - humanAvg) - 30.0f) * 0.00390625f;
    545        if (cpuLead > 0.15f) {
    546            cpuLead = 0.15f;
    547        } else if (cpuLead < -0.15f) {
    548            cpuLead = -0.15f;
    ⋮
    552            if (rider->isCpu != 0) {
    553                scale = 0.0f;
    554                if (numCpu >= 2) {
    555                    scale = rider->aiSkill;
    ⋮
    
    src/game/unnamed/s0_80062F50.c lines 541–601 at 9cdb194 · upstream ↗
    790/* Spreads the CPU riders' skills evenly from -0.1 to 0.1 in sAiRiderOrder (then +0.01 for exactly 0.1, -0.01 for
    791   the others) and sets their time scale to 1.03 - skill. */
    ⋮
    800            gRiders[sAiRiderOrder[i]].aiSkill = (i - (count - 1) * 0.5f) / ((count - 1) * 5.0f);
    
    src/game/unnamed/s0_80062F50.c lines 788–807 at 9cdb194 · upstream ↗
    479#define CPU_FAST_EFFECT             0x200000 // CPU Rubberbanding flag
    
    include/defines.h line 479 at 58cfcb0 · upstream ↗
    3086    if ((player->type & PLAYER_HUMAN) != PLAYER_HUMAN) {
    3087        if ((player->effects & CPU_FAST_EFFECT) == CPU_FAST_EFFECT) {
    3088            move_f32_towards(&player->unk_0E8, 380.0f, 0.5f);
    3089        } else {
    3090            move_f32_towards(&player->unk_0E8, 0.0f, 0.1f);
    
    src/player_controller.c lines 3086–3092 at 58cfcb0 · 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