Skip to content

Commit 44c71a7

Browse files
authored
Document versus rankings and finish info (#766)
* Document versus rankings and finish info * Document race states * variable renames
1 parent 44fe054 commit 44c71a7

12 files changed

Lines changed: 213 additions & 185 deletions

include/defines.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,14 @@ player spins. Something with avoding rollover of aniamation frame data? */
529529
#define FACING_Y_AXIS 0x4000
530530
#define FACING_X_AXIS 0x8000
531531
#define FACING_Z_AXIS 0x2000
532+
533+
// race states
534+
535+
#define RACE_NONE 0
536+
#define RACE_PREP 1
537+
#define RACE_STAGING 2
538+
#define RACE_IN_PROGRESS 3
539+
#define RACE_HUMAN_FINISHED 4 // At least 1 human has finished
540+
#define RACE_DONE 5
541+
#define RACE_QUITTING 6
542+
#define RACE_QUADRANT_RESULTS 7 // The results screen in GP and Time trials mode

src/code_800029B0.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ u16 D_8015F894;
130130
// Indexed by Player ID. Track time in seconds since player has last crossed the finish line
131131
f32 gTimePlayerLastTouchedFinishLine[8];
132132

133-
u8* gNmiUnknown1;
134-
u8* gNmiUnknown2;
135-
u8* gNmiUnknown3;
133+
u8* nmi_gVersusResults2P;
134+
u8* nmi_gVersusResults3P;
135+
u8* nmi_gVersusResults4P;
136136
u8* gNmiUnknown4;
137137
u8* gNmiUnknown5;
138138
u8* gNmiUnknown6;
@@ -204,7 +204,7 @@ void setup_race(void) {
204204
func_80005310();
205205
func_8003D080();
206206
init_hud();
207-
D_800DC510 = 0;
207+
gRaceState = RACE_NONE;
208208
gNumSpawnedShells = 0;
209209
D_800DC5B8 = 0;
210210
D_80152308 = 0;

src/code_800029B0.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ extern u16 D_8015F892;
118118
extern u16 D_8015F894;
119119
extern f32 gTimePlayerLastTouchedFinishLine[];
120120

121-
extern u8* gNmiUnknown1;
122-
extern u8* gNmiUnknown2;
123-
extern u8* gNmiUnknown3;
121+
extern u8* nmi_gVersusResults2P;
122+
extern u8* nmi_gVersusResults3P;
123+
extern u8* nmi_gVersusResults4P;
124124
extern u8* gNmiUnknown4;
125125
extern u8* gNmiUnknown5;
126126
extern u8* gNmiUnknown6;

src/cpu_vehicles_camera_path.c

Lines changed: 66 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ u16 D_801631F8[10];
8888
f32 gCurrentCpuTargetSpeed;
8989
f32 gPreviousCpuTargetSpeed[10];
9090
s32 D_80163238;
91-
u16 D_80163240[12];
91+
u16 gCrossedFinishLine[12];
9292
u16 gWrongDirectionCounter[12];
9393
u16 gIsPlayerWrongDirection[12];
9494
s32 gPreviousLapProgressScore[10];
@@ -154,7 +154,7 @@ s16 D_80164358;
154154
s16 D_8016435A;
155155
s16 D_8016435C;
156156
s16 gGPCurrentRacePlayerIdByRank[12]; // D_80164360
157-
s16 D_80164378[12];
157+
s16 gPrevPlayerIdByRank[12];
158158
s32 gLapCountByPlayerId[10]; // D_80164390
159159
s32 gGPCurrentRaceRankByPlayerId[10]; // D_801643B8
160160
s32 gPreviousGPCurrentRaceRankByPlayerId[10];
@@ -707,15 +707,15 @@ void detect_wrong_player_direction(s32 playerId, Player* player) {
707707
}
708708

709709
void set_places(void) {
710-
s32 temp_s2;
711-
f32 temp_f0;
712-
s32 rankPlayer[8];
713-
s32 a_really_cool_variable_name;
710+
s32 playerIdToSwap;
711+
f32 courseCompletionToSwap;
712+
s32 playerIdByRank[8];
713+
s32 prevPlayerId;
714714
UNUSED s32 pad;
715715
s32 numPlayer;
716+
s32 rank;
716717
s32 playerId;
717-
s32 temp_a0;
718-
s32 var_t1_3;
718+
s32 rankHigh;
719719

720720
switch (gModeSelection) {
721721
case BATTLE:
@@ -731,69 +731,70 @@ void set_places(void) {
731731
}
732732

733733
if (D_8016348C == 0) {
734-
for (playerId = 0; playerId < numPlayer; playerId++) {
735-
temp_a0 = gGPCurrentRacePlayerIdByRank[playerId];
736-
rankPlayer[playerId] = temp_a0;
737-
gCourseCompletionPercentByRank[playerId] = gCourseCompletionPercentByPlayerId[temp_a0];
734+
for (rank = 0; rank < numPlayer; rank++) {
735+
playerId = gGPCurrentRacePlayerIdByRank[rank];
736+
playerIdByRank[rank] = playerId;
737+
gCourseCompletionPercentByRank[rank] = gCourseCompletionPercentByPlayerId[playerId];
738738
}
739739
} else {
740-
for (playerId = 0; playerId < numPlayer; playerId++) {
741-
temp_a0 = gGPCurrentRacePlayerIdByRank[playerId];
742-
rankPlayer[playerId] = temp_a0;
743-
gCourseCompletionPercentByRank[playerId] = -gTimePlayerLastTouchedFinishLine[temp_a0];
740+
// used in grand Prix mode once all players cross finish line to determine finish order
741+
for (rank = 0; rank < numPlayer; rank++) {
742+
playerId = gGPCurrentRacePlayerIdByRank[rank];
743+
playerIdByRank[rank] = playerId;
744+
gCourseCompletionPercentByRank[rank] = -gTimePlayerLastTouchedFinishLine[playerId];
744745
}
745746
}
746747

747-
for (playerId = 0; playerId < numPlayer - 1; playerId++) {
748-
if ((gPlayers[gGPCurrentRacePlayerIdByRank[playerId]].type & PLAYER_CINEMATIC_MODE)) {
748+
for (rank = 0; rank < numPlayer - 1; rank++) {
749+
if ((gPlayers[gGPCurrentRacePlayerIdByRank[rank]].type & PLAYER_CINEMATIC_MODE)) {
749750
continue;
750751
}
751752

752-
for (var_t1_3 = playerId + 1; var_t1_3 < numPlayer; var_t1_3++) {
753-
if (gCourseCompletionPercentByRank[playerId] < gCourseCompletionPercentByRank[var_t1_3]) {
754-
if (!(gPlayers[gGPCurrentRacePlayerIdByRank[var_t1_3]].type & 0x800)) {
755-
temp_s2 = rankPlayer[playerId];
756-
rankPlayer[playerId] = rankPlayer[var_t1_3];
757-
rankPlayer[var_t1_3] = temp_s2;
758-
temp_f0 = gCourseCompletionPercentByRank[playerId];
759-
gCourseCompletionPercentByRank[playerId] = gCourseCompletionPercentByRank[var_t1_3];
760-
gCourseCompletionPercentByRank[var_t1_3] = temp_f0;
753+
for (rankHigh = rank + 1; rankHigh < numPlayer; rankHigh++) {
754+
if (gCourseCompletionPercentByRank[rank] < gCourseCompletionPercentByRank[rankHigh]) {
755+
if (!(gPlayers[gGPCurrentRacePlayerIdByRank[rankHigh]].type & PLAYER_CINEMATIC_MODE)) {
756+
playerIdToSwap = playerIdByRank[rank];
757+
playerIdByRank[rank] = playerIdByRank[rankHigh];
758+
playerIdByRank[rankHigh] = playerIdToSwap;
759+
courseCompletionToSwap = gCourseCompletionPercentByRank[rank];
760+
gCourseCompletionPercentByRank[rank] = gCourseCompletionPercentByRank[rankHigh];
761+
gCourseCompletionPercentByRank[rankHigh] = courseCompletionToSwap;
761762
}
762763
}
763764
}
764765
}
765766

766-
for (playerId = 0; playerId < NUM_PLAYERS; playerId++) {
767-
gPreviousGPCurrentRaceRankByPlayerId[playerId] = gGPCurrentRaceRankByPlayerId[playerId];
767+
// actually player_id, not rank
768+
for (rank = 0; rank < NUM_PLAYERS; rank++) {
769+
gPreviousGPCurrentRaceRankByPlayerId[rank] = gGPCurrentRaceRankByPlayerId[rank];
768770
}
769771

770-
for (playerId = 0; playerId < numPlayer; playerId++) {
771-
gGPCurrentRacePlayerIdByRank[playerId] = rankPlayer[playerId];
772-
gGPCurrentRaceRankByPlayerId[rankPlayer[playerId]] = playerId;
772+
for (rank = 0; rank < numPlayer; rank++) {
773+
gGPCurrentRacePlayerIdByRank[rank] = playerIdByRank[rank];
774+
gGPCurrentRaceRankByPlayerId[playerIdByRank[rank]] = rank;
773775
}
774-
775-
for (playerId = 0; playerId < numPlayer; playerId++) {
776-
a_really_cool_variable_name = D_80164378[playerId];
777-
rankPlayer[playerId] = a_really_cool_variable_name;
778-
gCourseCompletionPercentByRank[playerId] = gCourseCompletionPercentByPlayerId[a_really_cool_variable_name];
776+
for (rank = 0; rank < numPlayer; rank++) {
777+
prevPlayerId = gPrevPlayerIdByRank[rank];
778+
playerIdByRank[rank] = prevPlayerId;
779+
gCourseCompletionPercentByRank[rank] = gCourseCompletionPercentByPlayerId[prevPlayerId];
779780
}
780781

781-
for (playerId = 0; playerId < numPlayer - 1; playerId++) {
782-
for (var_t1_3 = playerId + 1; var_t1_3 < numPlayer; var_t1_3++) {
783-
if (gCourseCompletionPercentByRank[playerId] < gCourseCompletionPercentByRank[var_t1_3]) {
784-
temp_s2 = rankPlayer[playerId];
785-
rankPlayer[playerId] = rankPlayer[var_t1_3];
786-
rankPlayer[var_t1_3] = temp_s2;
787-
temp_f0 = gCourseCompletionPercentByRank[playerId];
788-
gCourseCompletionPercentByRank[playerId] = gCourseCompletionPercentByRank[var_t1_3];
789-
gCourseCompletionPercentByRank[var_t1_3] = temp_f0;
782+
for (rank = 0; rank < numPlayer - 1; rank++) {
783+
for (rankHigh = rank + 1; rankHigh < numPlayer; rankHigh++) {
784+
if (gCourseCompletionPercentByRank[rank] < gCourseCompletionPercentByRank[rankHigh]) {
785+
playerIdToSwap = playerIdByRank[rank];
786+
playerIdByRank[rank] = playerIdByRank[rankHigh];
787+
playerIdByRank[rankHigh] = playerIdToSwap;
788+
courseCompletionToSwap = gCourseCompletionPercentByRank[rank];
789+
gCourseCompletionPercentByRank[rank] = gCourseCompletionPercentByRank[rankHigh];
790+
gCourseCompletionPercentByRank[rankHigh] = courseCompletionToSwap;
790791
}
791792
}
792793
}
793794

794-
for (playerId = 0; playerId < numPlayer; playerId++) {
795-
gGPCurrentRaceRankByPlayerIdDup[rankPlayer[playerId]] = playerId;
796-
D_80164378[playerId] = rankPlayer[playerId];
795+
for (rank = 0; rank < numPlayer; rank++) {
796+
gGPCurrentRaceRankByPlayerIdDup[playerIdByRank[rank]] = rank;
797+
gPrevPlayerIdByRank[rank] = playerIdByRank[rank];
797798
}
798799
}
799800

@@ -992,7 +993,7 @@ bool func_800088D8(s32 playerId, s16 arg1, s16 arg2) {
992993
if (arg2 == 0) {
993994
if (gDemoMode == 1) {
994995
STEMP_V0 = gNumPathPointsTraversed[playerId];
995-
STEMP_V1 = gNumPathPointsTraversed[D_80164378[7]];
996+
STEMP_V1 = gNumPathPointsTraversed[gPrevPlayerIdByRank[7]];
996997
progress = STEMP_V0 - STEMP_V1;
997998
if (progress < 0) {
998999
progress = -progress;
@@ -1018,7 +1019,7 @@ bool func_800088D8(s32 playerId, s16 arg1, s16 arg2) {
10181019
rank = gGPCurrentRaceRankByPlayerId[gBestRankedHumanPlayer];
10191020
if (((((gPathCountByPathIndex[0] * 2) / 3)) < progress) && ((rank) >= 6)) {
10201021
STEMP_V0 = gNumPathPointsTraversed[playerId];
1021-
STEMP_V1 = temp = gNumPathPointsTraversed[D_80164378[rank - 1]];
1022+
STEMP_V1 = temp = gNumPathPointsTraversed[gPrevPlayerIdByRank[rank - 1]];
10221023
progress = STEMP_V0 - STEMP_V1;
10231024
}
10241025
if (progress < 0) {
@@ -1200,11 +1201,12 @@ void update_cpu_path_completion(s32 playerId, Player* player) {
12001201

12011202
/**
12021203
* Helps calculate time since player last touched finishline.
1204+
* Assumes constant z-speed and subtracts portion of frame where the finish line was already crossed
12031205
**/
1204-
f32 func_80009258(UNUSED s32 playerId, f32 arg1, f32 arg2) {
1205-
f32 temp_f2 = gPathStartZ - arg2;
1206-
f32 temp_f12 = arg1 - gPathStartZ;
1207-
return gCourseTimer - ((COURSE_TIMER_ITER_f * temp_f2) / (temp_f2 + temp_f12));
1206+
f32 time_crossed_finish_line(UNUSED s32 playerId, f32 previousPlayerZ, f32 playerZ) {
1207+
f32 z_change_after_cross = gPathStartZ - playerZ;
1208+
f32 z_change_before_cross = previousPlayerZ - gPathStartZ;
1209+
return gCourseTimer - ((COURSE_TIMER_ITER_f * z_change_after_cross) / (z_change_after_cross + z_change_before_cross));
12081210
}
12091211

12101212
void update_player_path_completion(s32 playerId, Player* player) {
@@ -1220,7 +1222,7 @@ void update_player_path_completion(s32 playerId, Player* player) {
12201222
playerZ = player->pos[2];
12211223
previousPlayerZ = gPreviousPlayerZ[playerId];
12221224
gIsPlayerNewPathPoint = false;
1223-
D_80163240[playerId] = 0;
1225+
gCrossedFinishLine[playerId] = 0;
12241226
sSomeNearestPathPoint = update_player_path(playerX, playerY, playerZ, gNearestPathPointByPlayerId[playerId], player,
12251227
playerId, gPlayerPathIndex);
12261228
gCurrentNearestPathPoint = sSomeNearestPathPoint;
@@ -1276,12 +1278,12 @@ void update_player_path_completion(s32 playerId, Player* player) {
12761278
// clang-format on
12771279
}
12781280
}
1279-
D_80163240[playerId] = 1;
1281+
gCrossedFinishLine[playerId] = 1;
12801282
update_player_completion(playerId);
12811283
reset_cpu_behaviour(playerId);
12821284
cpu_ItemStrategy[playerId].numItemUse = 0;
12831285
if ((D_8016348C == 0) && !(player->type & PLAYER_CINEMATIC_MODE)) {
1284-
gTimePlayerLastTouchedFinishLine[playerId] = func_80009258(playerId, previousPlayerZ, playerZ);
1286+
gTimePlayerLastTouchedFinishLine[playerId] = time_crossed_finish_line(playerId, previousPlayerZ, playerZ);
12851287
}
12861288
}
12871289
}
@@ -1461,7 +1463,11 @@ void update_player(s32 playerId) {
14611463
player->kartProps &= ~BACK_UP;
14621464
}
14631465
update_player_path_completion(playerId, player);
1464-
if ((gCurrentCourseId != COURSE_AWARD_CEREMONY) && ((D_80163240[playerId] == 1) || (playerId == 0))) {
1466+
1467+
// Because this takes place in a per-player loop and runs primarily when player 1 crosses the finish line,
1468+
// player 1 effectively has a 1 frame advantage when determining places. However, it runs for everyone when
1469+
// they cross the finish line, resulting in lower port numbers always winning ties in versus mode.
1470+
if ((gCurrentCourseId != COURSE_AWARD_CEREMONY) && ((gCrossedFinishLine[playerId] == 1) || (playerId == 0))) {
14651471
set_places();
14661472
}
14671473
if (player->type & PLAYER_CPU) {
@@ -2100,7 +2106,7 @@ void init_players(void) {
21002106
}
21012107
temp_v0_3 = gGPCurrentRaceRankByPlayerId[i];
21022108
gGPCurrentRacePlayerIdByRank[temp_v0_3] = (s16) i;
2103-
D_80164378[temp_v0_3] = (s16) i;
2109+
gPrevPlayerIdByRank[temp_v0_3] = (s16) i;
21042110
gGPCurrentRaceRankByPlayerIdDup[i] = temp_v0_3;
21052111
gWrongDirectionCounter[i] = 0;
21062112
gIsPlayerWrongDirection[i] = 0;

src/cpu_vehicles_camera_path.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void update_player_completion(s32);
115115

116116
void yoshi_valley_cpu_path(s32);
117117
void update_cpu_path_completion(s32, Player*);
118-
f32 func_80009258(s32, f32, f32);
118+
f32 time_crossed_finish_line(s32, f32, f32);
119119
void update_player_path_completion(s32, Player*);
120120
void update_vehicles(void);
121121
void play_cpu_sound_effect(s32, Player*);
@@ -323,7 +323,7 @@ extern u16 D_801631F8[];
323323
extern f32 gCurrentCpuTargetSpeed;
324324
extern f32 gPreviousCpuTargetSpeed[];
325325
extern s32 D_80163238;
326-
extern u16 D_80163240[];
326+
extern u16 gCrossedFinishLine[];
327327
extern u16 gWrongDirectionCounter[];
328328
extern u16 gIsPlayerWrongDirection[];
329329
extern s32 gPreviousLapProgressScore[];
@@ -383,7 +383,7 @@ extern s16 D_80164358;
383383
extern s16 D_8016435A;
384384
extern s16 D_8016435C;
385385
extern s16 gGPCurrentRacePlayerIdByRank[]; // D_80164360
386-
extern s16 D_80164378[];
386+
extern s16 gPrevPlayerIdByRank[]; // D_80164378
387387
extern s32 gLapCountByPlayerId[]; // D_80164390
388388
extern s32 gGPCurrentRaceRankByPlayerId[]; // D_801643B8
389389
extern s32 gPreviousGPCurrentRaceRankByPlayerId[];

src/main.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#ifndef GCC
2-
#define D_800DC510_AS_U16
2+
#define gRaceState_AS_U16
33
#endif
44
#include <ultra64.h>
55
#include <PR/os.h>
@@ -162,8 +162,8 @@ OSMesg gPIMesgBuf[32];
162162
OSMesgQueue gPIMesgQueue;
163163

164164
s32 gGamestate = 0xFFFF;
165-
// D_800DC510 is externed as an s32 in other files. D_800DC514 is only used in main.c, likely a developer mistake.
166-
u16 D_800DC510 = 0;
165+
// gRaceState is externed as an s32 in other files. D_800DC514 is only used in main.c, likely a developer mistake.
166+
u16 gRaceState = RACE_NONE;
167167
u16 D_800DC514 = 0;
168168
u16 creditsRenderMode = 0; // Renders the whole track. Displays red if used in normal race mode.
169169
u16 gDemoMode = DEMO_MODE_INACTIVE;
@@ -1179,10 +1179,10 @@ void thread5_game_loop(UNUSED void* arg) {
11791179
set_vblank_handler(2, &gGameVblankHandler, &gGameVblankQueue, (OSMesg) OS_EVENT_SW2);
11801180
// These variables track stats such as player wins.
11811181
// In the event of a console reset, it remembers them.
1182-
gNmiUnknown1 = &pAppNmiBuffer[0]; // 2 u8's, tracks number of times player 1/2 won a VS race
1183-
gNmiUnknown2 =
1182+
nmi_gVersusResults2P = &pAppNmiBuffer[0]; // 2 u8's, tracks number of times player 1/2 won a VS race
1183+
nmi_gVersusResults3P =
11841184
&pAppNmiBuffer[2]; // 9 u8's, 3x3, tracks number of times player 1/2/3 has placed in 1st/2nd/3rd in a VS race
1185-
gNmiUnknown3 = &pAppNmiBuffer[11]; // 12 u8's, 4x3, tracks number of times player 1/2/3/4 has placed in 1st/2nd/3rd
1185+
nmi_gVersusResults4P = &pAppNmiBuffer[11]; // 12 u8's, 4x3, tracks number of times player 1/2/3/4 has placed in 1st/2nd/3rd
11861186
// in a VS race
11871187
gNmiUnknown4 = &pAppNmiBuffer[23]; // 2 u8's, tracking number of Battle mode wins by player 1/2
11881188
gNmiUnknown5 = &pAppNmiBuffer[25]; // 3 u8's, tracking number of Battle mode wins by player 1/2/3

src/main.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,13 @@ extern OSMesg gPIMesgBuf[];
198198
extern OSMesgQueue gPIMesgQueue;
199199
void race_logic_loop(void);
200200
extern s32 gGamestate;
201-
#ifndef D_800DC510_AS_U16
201+
#ifndef gRaceState_AS_U16
202202
// Prevent overlapping writes in gcc
203-
// Whether D_800DC510 was intended to be a separate variable in main.c from the rest of the game is unknown
203+
// Whether gRaceState was intended to be a separate variable in main.c from the rest of the game is unknown
204204
#ifdef GCC
205-
extern u16 D_800DC510;
205+
extern u16 gRaceState;
206206
#else
207-
extern s32 D_800DC510;
207+
extern s32 gRaceState;
208208
#endif
209209
#endif
210210

0 commit comments

Comments
 (0)