diff --git a/include/common_structs.h b/include/common_structs.h index 8be8502cf..971f53011 100644 --- a/include/common_structs.h +++ b/include/common_structs.h @@ -297,6 +297,56 @@ typedef struct { /* 0x0DD4 */ s16 unk_DD4; } Player; // size = 0xDD8 +typedef struct { + // 6 little endian 3-byte records. + // When converted to big endian the bottom 5 nibbles can be interpreted as the centisecond count for that record. + // The top nibble is the character ID of the charcter used to set that record + // The first 5 records are the top 5 3-lap records + // The 6th record is the best 1-lap record + u8 records[6][3]; + // It's unknown what these bytes are used for + // Byte 1 might be an indicator that there is a ghost available for that course + u8 unknownBytes[6]; +} CourseTimeTrialRecords; // size = 0x18 + +typedef struct { + // Each cup is made up of 4 courses + CourseTimeTrialRecords courseRecords[4]; +} CupTimeTrialRecords; // size = 0x60 + +typedef struct { + // There are 4 cups total + CupTimeTrialRecords cupRecords[4]; +} AllCourseTimeTrialRecords; // size = 0x180 + +typedef struct { + // Records 0 through 3 are for the first cup's courses + // Records 4 through 7 are for the second cup's courses + u8 bestThreelaps[8][3]; + u8 bestSinglelaps[8][3]; + // It's unknown what these bytes are used for + u8 unknownBytes[8]; +} OnlyBestTimeTrialRecords; // size = 0x38 + +typedef struct { + AllCourseTimeTrialRecords allCourseTimeTrialRecords; + // GP Points scored for each CC mode + // 1st place is 3 points, 2nd is 2, etc. + // Lowest dibit is the Mushroom Cup, 2nd dibit is the Flower Cup, etc + u8 grandPrixPoints[4]; + // Its unknown what these bytes are used for + // They appear related to the Grand Prix points in some capacity but I can't figure out how + u8 unknownBytes1[4]; + // For some reason there's 2 entries covering 4 cups + // Instead of 4 entries, one per cup. Or even just one big entry for all 4 cups + // Its also unknown why these are here when they're identical to the values found + // in allCourseTimeTrialRecords + OnlyBestTimeTrialRecords onlyBestTimeTrialRecords[2]; + // Its unknown what these bytes are used for, they appear to be identical to + // grandPrixPoints and unknownBytes1 + u8 unknownBytes2[8]; +} SaveData; // size = 0x200 + typedef struct { /* 0x00 */ char unk_00[0x1D]; /* 0x1D */ s8 unk_1D; diff --git a/include/defines.h b/include/defines.h index 80e65731c..a54434ea7 100644 --- a/include/defines.h +++ b/include/defines.h @@ -71,6 +71,15 @@ #define BOWSER 7 /** + * Indexes for accessing Time Trial records +**/ +#define TIME_TRIAL_3LAP_RECORD_1 0 +#define TIME_TRIAL_3LAP_RECORD_2 1 +#define TIME_TRIAL_3LAP_RECORD_3 2 +#define TIME_TRIAL_3LAP_RECORD_4 3 +#define TIME_TRIAL_3LAP_RECORD_5 4 +#define TIME_TRIAL_1LAP_RECORD 5 + * Text color options * The 2 cycling options cycle through Blue -> Green -> Red * Cycle 2 appears to be one step ahead of Cycle 1 diff --git a/include/variables.h b/include/variables.h index 8f53d6d01..06723004e 100644 --- a/include/variables.h +++ b/include/variables.h @@ -3,13 +3,17 @@ #include "global.h" +extern s32 gCCSelection; extern s8 gCourseSelection; extern s16 gCurrentCourseId; -extern s32 gModeSelection; -extern s32 gPlayerCountSelection1; +extern s8 gCupSelection; +extern s8 gHumanPlayerCount; extern f32 gKartFrictionTable[]; extern f32 gKartBoundingBoxTable[]; extern f32 gKartGravityTable[]; +extern s8 gGPOverallRanks[8]; +extern s32 gModeSelection; +extern s32 gPlayerCountSelection1; extern struct_D_802874D8 D_802874D8; extern s16 D_801650D0[4][8]; @@ -33,7 +37,6 @@ extern s16 D_80165572; extern s16 D_80165580; extern s16 D_80165582; extern s8 D_800E86A8[4]; -extern s8 gGPOverallRanks[8]; extern s16 D_80165270[8]; extern Player* D_800DC4DC; extern Player* D_800DC4E0; @@ -59,7 +62,6 @@ extern s16* D_80164550; extern f32 D_80165210[]; extern f32 D_80165230[]; extern struct_D_800E261C D_800E261C; -extern s32 gCCSelection; extern f32 D_80164510[]; extern s32 D_80165420[]; extern s32 D_80165440[]; diff --git a/src/code_800AF9B0.c b/src/code_800AF9B0.c index c16c55be0..67fc383a9 100644 --- a/src/code_800AF9B0.c +++ b/src/code_800AF9B0.c @@ -1,10 +1,13 @@ #include #include #include +#include "global.h" +#include "common_structs.h" u32 func_802A7B70(u16 x); extern u32 D_8018EDB8; extern u32 D_8018EDBC; +extern SaveData D_8018EB90; void func_800AF9B0(void) { D_8018EDB8 = func_802A7B70(7680); @@ -3213,64 +3216,69 @@ GLOBAL_ASM("asm/non_matchings/code_800AF9B0/func_800B4DCC.s") #ifdef MIPS_TO_C //generated by mips_to_c commit 3c3b0cede1a99430bfd3edf8d385802b94f91307 -s32 func_800B4DF4(void *arg0) { - return ((arg0->unk1 << 8) + arg0->unk0 + (arg0->unk2 << 0x10)) & 0xFFFFFF; +// Convert time trial record from its little-endian form to big-endian +s32 func_800B4DF4(u8 *arg0) { + return (arg0[0] + (arg0[1] << 8) + (arg0[2] << 0x10)) & 0xFFFFFF; } #else GLOBAL_ASM("asm/non_matchings/code_800AF9B0/func_800B4DF4.s") #endif -#ifdef MIPS_TO_C +#if 1 //generated by mips_to_c commit 3c3b0cede1a99430bfd3edf8d385802b94f91307 -? func_800B4DF4(void *, s32); // extern -extern ? D_8018EB90; -extern s8 gCupSelection; - -void func_800B4E24(s32 arg0) { - s32 temp_v0; - - temp_v0 = (gCupSelection * 4) + gCourseSelection; - func_800B4DF4(((temp_v0 / 4) * 0x60) + ((temp_v0 % 4) * 0x18) + (arg0 * 3) + &D_8018EB90, arg0); +// Get a time trial record, infer course index +s32 func_800B4E24(s32 recordIndex) { + return func_800B4DF4( + D_8018EB90.allCourseTimeTrialRecords \ + .cupRecords[(((gCupSelection * 4) + gCourseSelection) / 4)] \ + .courseRecords[(((gCupSelection * 4) + gCourseSelection) % 4)] \ + .records[recordIndex] + ); } #else GLOBAL_ASM("asm/non_matchings/code_800AF9B0/func_800B4E24.s") #endif -#ifdef MIPS_TO_C +#if 1 //generated by mips_to_c commit 3c3b0cede1a99430bfd3edf8d385802b94f91307 -? func_800B4DF4(void *, s32); // extern -extern ? D_8018EB90; - -void func_800B4EB4(s32 arg0, s32 arg1) { - func_800B4DF4(((arg1 / 4) * 0x60) + ((arg1 % 4) * 0x18) + (arg0 * 3) + &D_8018EB90, arg0); +// Get a time trial record, but take the course index as an argument +s32 func_800B4EB4(s32 recordIndex, s32 courseIndex) { + return func_800B4DF4( + D_8018EB90.allCourseTimeTrialRecords \ + .cupRecords[(courseIndex / 4)] \ + .courseRecords[(courseIndex % 4)] \ + .records[recordIndex] + ); } #else GLOBAL_ASM("asm/non_matchings/code_800AF9B0/func_800B4EB4.s") #endif -#ifdef MIPS_TO_C +#if 1 //generated by mips_to_c commit 3c3b0cede1a99430bfd3edf8d385802b94f91307 -? func_800B4DF4(void *); // extern -extern ? D_8018EB90; -extern s8 gCupSelection; - -void func_800B4F2C(void) { - s32 temp_v0; - - temp_v0 = (gCupSelection * 4) + gCourseSelection; - func_800B4DF4(((temp_v0 / 4) * 0x60) + ((temp_v0 % 4) * 0x18) + 0xF + &D_8018EB90); +// Get Best Lap record of the inferred course index +s32 func_800B4F2C(void) { + return func_800B4DF4( + D_8018EB90.allCourseTimeTrialRecords \ + .cupRecords[(((gCupSelection * 4) + gCourseSelection) / 4)] \ + .courseRecords[(((gCupSelection * 4) + gCourseSelection) % 4)] \ + .records[TIME_TRIAL_1LAP_RECORD] + ); } #else GLOBAL_ASM("asm/non_matchings/code_800AF9B0/func_800B4F2C.s") #endif -#ifdef MIPS_TO_C +#if 1 //generated by mips_to_c commit 3c3b0cede1a99430bfd3edf8d385802b94f91307 -? func_800B4DF4(void *, s32); // extern -extern ? D_8018EB90; - -void func_800B4FB0(s32 arg0) { - func_800B4DF4(((arg0 / 4) * 0x60) + ((arg0 % 4) * 0x18) + 0xF + &D_8018EB90, arg0); +// Get the best single lap time record of the given course index +s32 func_800B4FB0(s32 courseIndex) { + return func_800B4DF4( + D_8018EB90.allCourseTimeTrialRecords \ + .cupRecords[(courseIndex / 4)] \ + .courseRecords[(courseIndex % 4)] \ + .records[TIME_TRIAL_1LAP_RECORD] + ); } #else GLOBAL_ASM("asm/non_matchings/code_800AF9B0/func_800B4FB0.s")