Energy meter
One meter that is a vehicle's health and, in some games, the fuel its boosts burn.
On this page
An energy meter makes one number the vehicle’s health and, where boosts draw on it, the price of speed. In F-Zero X a boost costs 0.15 of the meter, a wall takes 0.7 times the speed into it, a landmine 12.5, and the pits fill it back1,2,3.
Games
| Game | Year | How | Note |
|---|---|---|---|
| F-Zero X | 1998 | Pays for boost | one meter of 142 to 190 by body grade takes the damage, pays 0.15 of itself for each boost from the second lap, and refills on the pits |
Every claim about this mechanic, by game (7)
References
- ^ abIn F-Zero X's US build, pressing B starts a boost only when no boost is running (
boostTimeris 0),energyisn't exactly 0, and the machine hasRACER_STATE_CAN_BOOST. The boost setsboostTimerto 100 (sInitialBoostTimer), and on each update while it runs, the machine paysboostEnergyUsage, 0.0015 of itsmaxEnergy, fromenergy; if that takes the energy below 0, it's set to 0 and the boost ends on that update. A whole boost costs 0.15 of the meter and lasts 100 updates, about 1.7 seconds at 60 updates a second, the rate the race clock counts (computed). In a multiplayer race with the VS handicap on, the cost falls with distance behind the leader, linearly to 0.1 of it at 2000 or more behind.Codeinspectredc/fzeroxHow we know
3598 if ((buttonPressed & BTN_B) && (racer->boostTimer == 0) && (racer->energy != 0.0) && 3599 (racer->stateFlags & RACER_STATE_CAN_BOOST)) { ⋮ 3603 racer->boostTimer = sInitialBoostTimer;
src/game/racer.c lines 3598–3603 at 4b00f36 · upstream ↗ 386s32 sInitialBoostTimer = 100;src/game/racer.c line 386 at 4b00f36 · upstream ↗ 1661 racer->boostEnergyUsage = racer->maxEnergy * 0.0015f;src/game/racer.c line 1661 at 4b00f36 · upstream ↗ 4035 if (racer->boostTimer != 0) { 4036 if (racer->stateFlags & RACER_STATE_DASH_PAD_BOOST) { ⋮ 4040 } else { ⋮ 4047 if ((gNumPlayers == 1) || (gSettingVsHandicap == 0)) { 4048 sp128 = racer->boostEnergyUsage; 4049 } else { 4050 sp128 = (gRacersByPosition[0]->raceDistance - racer->raceDistance); 4051 sp128 /= D_800CE4D8; 4052 if (sp128 >= 1.0f) { 4053 sp128 = racer->boostEnergyUsage * 0.1f; 4054 } else { 4055 sp128 = (((1.0f - sp128) * 0.9f) + 0.1f) * racer->boostEnergyUsage; ⋮
src/game/racer.c lines 4035–4071 at 4b00f36 · upstream ↗ 343f32 D_800CE4D8 = 2000.0f;src/game/racer.c line 343 at 4b00f36 · upstream ↗ 4303 racer->unk_2A4++; 4304#if OS_TV_TYPE == OS_TV_TYPE_NTSC 4305 racer->raceTime = (s32) (racer->unk_2A4 * 50) / 3;
src/game/racer.c lines 4303–4305 at 4b00f36 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abIn F-Zero X's US build,
Racer_ReceiveDamagesubtracts the damage it's given fromenergy, unless the machine is crashed or has finished (RACER_STATE_CRASHED,RACER_STATE_FINISHED). If that takes the energy below 0, a machine whosemachineLodis 0 is set to 0.1 instead, and nothing else happens;Racer_Drawsets that field to 0 for a machine outside the camera's view (behind it, more than 2500 ahead, or off the screen's edges), andRacer_Updatesets every machine's to 1 when more than one player is racing. Any other machine is set to 0 and, unless already crashed or spinning out, put into the state the decompilers nameRACER_STATE_SPINNING_OUT.Racer_HitWalldeals 0.7 times the machine's speed into the wall, when that speed is above 0.01, and a landmine (within 30 units of the machine) deals 12.5.Codeinspectredc/fzeroxHow we know
2240 if (racer->stateFlags & (RACER_STATE_CRASHED | RACER_STATE_FINISHED)) {src/game/racer.c line 2240 at 4b00f36 · upstream ↗ 2292 } else { 2293#if BUILD_REVISION >= REVISION_C ⋮ 2296 racer->energy -= damageStrength; 2297#if BUILD_REVISION >= REVISION_C ⋮ 2301 if (racer->energy < 0.0f) { 2302 if (racer->machineLod == 0) { 2303 racer->energy = 0.1f; 2304 return; ⋮ 2306 racer->energy = 0.0f; ⋮ 2315 if (!(racer->stateFlags & (RACER_STATE_CRASHED | RACER_STATE_SPINNING_OUT))) { 2316 racer->stateFlags |= RACER_STATE_SPINNING_OUT;
src/game/racer.c lines 2292–2316 at 4b00f36 · upstream ↗ 5609 for (racer = sLastRacer; racer >= gRacers; racer--) { 5610 racer->machineLod = racer->unk_2B2 = racer->unk_2B3 = 0; 5611 if (racer->stateFlags & RACER_STATE_ACTIVE) { ⋮ 5616 if ((temp_fa0 < 0.0f) || (temp_fa0 > 2500.0f)) { 5617 continue;
src/game/racer.c lines 5609–5618 at 4b00f36 · upstream ↗ 5094 if (gNumPlayers != 1) { 5095 for (racer = sLastRacer; racer >= gRacers; racer--) { 5096 racer->machineLod = racer->unk_2B2 = racer->unk_2B3 = 1;
src/game/racer.c lines 5094–5097 at 4b00f36 · upstream ↗ 2353 if (lateralVelocity * wallDirection > 0.01f) { ⋮ 2365 Racer_ReceiveDamage(racer, lateralVelocity * wallDirection * 0.7f);
src/game/racer.c lines 2353–2366 at 4b00f36 · upstream ↗ 3641 if ((SQ(var_fs1) + SQ(var_fs0) + SQ(var_ft4)) < 900.0f) { ⋮ 3645 racer->stateFlags |= RACER_STATE_TOUCHING_LANDMINE; 3646 Racer_ReceiveDamage(racer, 12.5f);
src/game/racer.c lines 3641–3646 at 4b00f36 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abIn F-Zero X's US build, on each update that a machine is on a pit surface (
COURSE_EFFECT_PIT) and isn't crashed, airborne, or spinning out, it gainsenergyIncrease, 0.008 of itsmaxEnergy(sEnergyRefillScale), up to the maximum. An empty meter refills in 125 updates, about 2.1 seconds at 60 updates a second (computed).Codeinspectredc/fzeroxHow we know
387f32 sEnergyRefillScale = 0.008f;src/game/racer.c line 387 at 4b00f36 · upstream ↗ 1666 racer->energyIncrease = racer->maxEnergy * sEnergyRefillScale;src/game/racer.c line 1666 at 4b00f36 · upstream ↗ 4482 if ((racer->stateFlags & (RACER_STATE_CRASHED | RACER_STATE_AIRBORNE | RACER_STATE_SPINNING_OUT | 4483 COURSE_EFFECT_MASK)) == COURSE_EFFECT_PIT) { 4484 racer->energy += racer->energyIncrease; 4485 if (racer->maxEnergy < racer->energy) { 4486 racer->energy = racer->maxEnergy;
src/game/racer.c lines 4482–4487 at 4b00f36 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^In F-Zero X's US build,
Racer_InitRacersets a machine'senergyandmaxEnergyfromgBodyHealthValuesby its body grade (BODY_STAT): 190 for grade A, 178 for B, 166 for C, 154 for D, and 142 for E, so a racer starts each race with a full meter. In Death Race (GAMEMODE_DEATH_RACE),Racer_Initthen halves both values for every racer aftergRacers[0], which holds player 1's machine, so the other machines run on half a meter (71 to 95).Codeinspectredc/fzeroxHow we know
440f32 gBodyHealthValues[] = { 441 190.0f, 178.0f, 166.0f, 154.0f, 142.0f,
src/game/racer.c lines 440–442 at 4b00f36 · upstream ↗ 58typedef enum BodyStat { 59 /* 0 */ BODY_A, ⋮ 63 /* 4 */ BODY_E, 64} BodyStat;
include/fzx_racer.h lines 58–64 at 4b00f36 · upstream ↗ 1660 racer->energy = racer->maxEnergy = gBodyHealthValues[machine->machineStats[BODY_STAT]];src/game/racer.c line 1660 at 4b00f36 · upstream ↗ 1823 if (gGameMode == GAMEMODE_DEATH_RACE) { 1824 for (racer = sLastRacer; racer > gRacers; racer--) { 1825 racer->energy *= 0.5f; 1826 racer->maxEnergy *= 0.5f;
src/game/racer.c lines 1823–1828 at 4b00f36 · upstream ↗ 862 for (i = gNumPlayers - 1; i >= 0; i--) { 863 gPlayerCharacters[i] = gRacers[i].character;
src/game/racer.c lines 862–866 at 4b00f36 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^In F-Zero X's US build, a machine starts the race without
RACER_STATE_CAN_BOOSTunless the race is the title demo, Practice, or Death Race, which set it from the start. A machine starts atlap0 withlapsCompleted1, andlapcounts up at each crossing of the line; when it reaches one more thanlapsCompleted(and no more than one past the last lap), the code records the lap and sets the flag. The first crossing, at the start, bringslapto 1 and doesn't set it; completing the first lap does, so in the Grand Prix and VS races boosting opens from the second lap (computed from the counters).Codeinspectredc/fzeroxHow we know
1580 if ((gTitleDemoState != TITLE_DEMO_INACTIVE) || (gGameMode == GAMEMODE_PRACTICE) || 1581 (gGameMode == GAMEMODE_DEATH_RACE)) { ⋮ 1583 if ((gTitleDemoState != TITLE_DEMO_INACTIVE) || (gGameMode == GAMEMODE_PRACTICE) || ⋮ 1586 racer->stateFlags = 1587 RACER_STATE_ACTIVE | RACER_STATE_FLAGS_20000000 | RACER_STATE_CAN_BOOST | RACER_STATE_FLAGS_8000; 1588 } else { 1589 racer->stateFlags = RACER_STATE_ACTIVE | RACER_STATE_FLAGS_20000000 | RACER_STATE_FLAGS_8000;
src/game/racer.c lines 1580–1590 at 4b00f36 · upstream ↗ 1614 racer->lapsCompletedDistance = -gCurrentCourseInfo->length; ⋮ 1619 racer->lapsCompleted = 1; ⋮ 1623 racer->bodyWhiteTimer = racer->spinOutTimer = racer->completedLapsTime = racer->raceTime = racer->lap = ⋮ 1625 racer->vibrationStrength = 0;
src/game/racer.c lines 1614–1625 at 4b00f36 · upstream ↗ 4309 if (sCourseHalfLength < sp128) { 4310 racer->lapsCompletedDistance += gCurrentCourseInfo->length; 4311 racer->lap++; 4312 if ((racer->lap == racer->lapsCompleted + 1) && (racer->lap <= (gTotalLapCount + 1))) { 4313 racer->lapsCompleted = racer->lap; 4314 racer->stateFlags |= RACER_STATE_CAN_BOOST;
src/game/racer.c lines 4309–4314 at 4b00f36 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^In F-Zero X's US build, when two machines first touch and one belongs to a human player, the other records that player as its last contact (
unk_28C) and resets a counter (unk_288) that counts up on each update while the machine isn't crashed, finished, or falling off the track, the race intro timer (gRaceIntroTimer) is under 40, and the mode isn'tGAMEMODE_RECORDS. When damage puts a machine into its spin-out,func_8008DBB8credits that player if the contact was no more than 60 updates before and the player isn't finished, retired, or spinning out: it adds togRacersKOd(by the atlas's reading of the name, a count of knock-outs), and in the Grand Prix the fifth (gRacersKOd== 5) gives player 1 a life. The player gains an eighth of theirmaxEnergy(energyRegain), added on the next update they aren't crashed or spinning out, up to the maximum.Codeinspectredc/fzeroxrevisedHow we know
5148 if (!racerPair->areColliding) { 5149 if (racer->id < gNumPlayers) { 5150 racer2->unk_288 = 0; 5151 racer2->unk_28C = racer; ⋮ 5153 if (racer2->id < gNumPlayers) { 5154 racer->unk_288 = 0; 5155 racer->unk_28C = racer2;
src/game/racer.c lines 5148–5156 at 4b00f36 · upstream ↗ 4298 if (!(racer->stateFlags & (RACER_STATE_CRASHED | RACER_STATE_FINISHED | RACER_STATE_FALLING_OFF_TRACK)) && 4299 (gRaceIntroTimer < 40) && (gGameMode != GAMEMODE_RECORDS)) { ⋮ 4302 racer->unk_288++;
src/game/racer.c lines 4298–4302 at 4b00f36 · upstream ↗ 2315 if (!(racer->stateFlags & (RACER_STATE_CRASHED | RACER_STATE_SPINNING_OUT))) { 2316 racer->stateFlags |= RACER_STATE_SPINNING_OUT; ⋮ 2320 func_8008DBB8(racer, 60);
src/game/racer.c lines 2315–2320 at 4b00f36 · upstream ↗ 2196void func_8008DBB8(Racer* arg0, s32 arg1) { ⋮ 2199 if (arg1 < arg0->unk_288) { 2200 return; ⋮ 2203 temp_v0 = arg0->unk_28C; 2204 if (temp_v0 == NULL) { 2205 return; ⋮ 2207 if (temp_v0->stateFlags & (RACER_STATE_FINISHED | RACER_STATE_RETIRED | RACER_STATE_SPINNING_OUT)) { 2208 return; ⋮ 2212 gRacersKOd++; 2213 if ((gGameMode == GAMEMODE_GP_RACE) && (gRacersKOd == 5)) { 2214 gPlayerLives[0]++; ⋮ 2221 temp_v0->energyRegain += temp_v0->maxEnergy * 0.125f;
src/game/racer.c lines 2196–2221 at 4b00f36 · upstream ↗ 5085 if ((racer->energyRegain != 0.0f) && !(racer->stateFlags & (RACER_STATE_CRASHED | RACER_STATE_SPINNING_OUT))) { 5086 racer->energy += racer->energyRegain; 5087 if (racer->energy > racer->maxEnergy) { 5088 racer->energy = racer->maxEnergy; ⋮ 5090 racer->energyRegain = 0.0f;
src/game/racer.c lines 5085–5091 at 4b00f36 · 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 F-Zero X's US build,
Machine_DrawBlueFalconLod1, by its name a draw routine for the Blue Falcon, reads the word at offset 0x510 of the cartridge ROM until it has read the same value three times in a row (the first read is compared with 0). If its lowest bit is set, it counts the call (D_800CE784), and from the 13th such call it sets all fivegBodyHealthValuesto 1.0, the maximum energy machines are given when a race is set up, and callsfunc_i2_801039BC. The atlas hasn't read what the word holds on a retail cartridge.Codeinspectredc/fzeroxrevisedHow we know
4942Gfx* Machine_DrawBlueFalconLod1(Gfx* gfx) { ⋮ 4950 var_a0 = 0; ⋮ 4952 while (var_a0 < 2) { 4953 while (IO_READ(PI_STATUS_REG) & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) {} ⋮ 4955 temp_v1 = ROM_READ(0x510); 4956 if (temp_v1 == var_a1) { 4957 var_a0++; 4958 } else { 4959 var_a0 = 0; ⋮ 4961 var_a1 = temp_v1; ⋮ 4964 if (temp_v1 & 1) { 4965 D_800CE784++; ⋮
src/overlays/ovl_i9/machine_draw.c lines 4941–4969 at 4b00f36 · upstream ↗ 1660 racer->energy = racer->maxEnergy = gBodyHealthValues[machine->machineStats[BODY_STAT]];src/game/racer.c line 1660 at 4b00f36 · 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
- inspectredc and fzerox contributors. 2026. “F-Zero X decompilation (inspectredc/fzerox).” Commit 4b00f36. inspectredc/fzerox @ 4b00f36 · licence, all uses