From 3346ac1d5999850caf46814fd459e048f4a9bc4d Mon Sep 17 00:00:00 2001 From: Ryan Myers Date: Fri, 23 May 2025 14:51:48 -0400 Subject: [PATCH] Match func_80017E98 (#586) * Match func_80017E98 * Document some math functions using Wikipedia for my knowledge base. --- README.md | 12 +- include/level_object_entries.h | 4 +- src/objects.c | 226 +++++++++++++++++++++++---- src/objects.h | 4 +- src/racer.c | 6 +- ver/symbols/symbol_addrs.jpn.v79.txt | 4 +- ver/symbols/symbol_addrs.pal.v77.txt | 4 +- ver/symbols/symbol_addrs.pal.v80.txt | 4 +- ver/symbols/symbol_addrs.us.v77.txt | 4 +- ver/symbols/symbol_addrs.us.v80.txt | 4 +- 10 files changed, 216 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index b71b9e76..bead4926 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ This repo contains a work-in-progress decompilation of Diddy Kong Racing for the All versions are supported, and the US 1.0 version (SHA1 = 0cb115d8716dbbc2922fda38e533b9fe63bb9670) of the game is the default if not specified. -As of May 21, 2025, this is our current score: +As of May 23, 2025, this is our current score: -    Decomp progress: 88.16% +    Decomp progress: 88.37%     Documentation progress: 56.99% @@ -117,13 +117,13 @@ s32 is_drumstick_unlocked(void) { ``` -As of May 21, 2025, this is our current score: +As of May 23, 2025, this is our current score: ``` ===================================================================== ADVENTURE ONE (ASM -> C Decompilation) - --------------- 88.16% Complete (89.12% NON_MATCHING) --------------- - # Decompiled functions: 1899 - # GLOBAL_ASM remaining: 52 + --------------- 88.37% Complete (89.33% NON_MATCHING) --------------- + # Decompiled functions: 1900 + # GLOBAL_ASM remaining: 51 # NON_MATCHING functions: 5 # NON_EQUIVALENT WIP functions: 15 ---------------------------- Game Status ---------------------------- diff --git a/include/level_object_entries.h b/include/level_object_entries.h index 844e9692..8faa7211 100644 --- a/include/level_object_entries.h +++ b/include/level_object_entries.h @@ -145,10 +145,10 @@ typedef struct LevelObjectEntry_Checkpoint { /* 0x14 */ s8 unk14; /* 0x15 */ s8 unk15; /* 0x16 */ s8 unk16; - /* 0x17 */ s8 unk17; + /* 0x17 */ u8 unk17; /* 0x18 */ s8 unk18; /* 0x19 */ u8 unk19; - /* 0x1A */ u8 unk1A; + /* 0x1A */ s8 unk1A; /* 0x1B */ u8 unk1B; } LevelObjectEntry_Checkpoint; diff --git a/src/objects.c b/src/objects.c index 0e5b6385..ccc00ef2 100644 --- a/src/objects.c +++ b/src/objects.c @@ -28,6 +28,7 @@ #include "audio_vehicle.h" #include "vehicle_misc.h" #include "PRinternal/viint.h" +#include "printf.h" #define MAX_CHECKPOINTS 60 #define OBJECT_POOL_SIZE 0x15800 @@ -443,9 +444,8 @@ void racerfx_free(void) { gParticlePtrList_flush(); } -#pragma GLOBAL_ASM("asm/nonmatchings/objects/func_8000B38C.s") - void func_8000B38C(Vertex *, Triangle *, ObjectTransform *, f32, f32, s16, TextureHeader *arg6); +#pragma GLOBAL_ASM("asm/nonmatchings/objects/func_8000B38C.s") void func_8000B750(Object *racerObj, s32 racerIndex, s32 vehicleIDPrev, s32 boostType, s32 arg4) { f32 sp74[3]; @@ -4493,7 +4493,165 @@ UNUSED s16 get_taj_challenge_type(void) { return gTajChallengeType; } -#pragma GLOBAL_ASM("asm/nonmatchings/objects/func_80017E98.s") +void func_80017E98(void) { + f32 xDiff; + f32 zDiff; + f32 yDiff; + s32 temp_v1; + s32 checkpointNum; + s32 duplicateCheckpoint; + s32 breakOut; + s32 altRouteId; + s32 i; + s32 altId; + s32 var_a0; + f32 ox; + f32 oy; + f32 oz; + Object *obj; + CheckpointNode *checkpoint; + LevelObjectEntry_Checkpoint *checkpointEntry; + f32 mtx[4][4]; + ObjectTransform transform; + s32 var_t2; + + var_t2 = 0; + gNumberOfCheckpoints = 0; + for (i = 0; i < gObjectCount; i++) { + obj = gObjPtrList[i]; + if (!(obj->segment.trans.flags & OBJ_FLAGS_PARTICLE) && obj->behaviorId == BHV_CHECKPOINT && + gNumberOfCheckpoints < MAX_CHECKPOINTS) { + checkpointEntry = &obj->segment.level_entry->checkpoint; + if (checkpointEntry->unk1A == gTajChallengeType) { + gTrackCheckpoints[gNumberOfCheckpoints].obj = obj; + var_a0 = checkpointEntry->unk9; + if (checkpointEntry->unk17) { + var_a0 += 255; + var_t2++; + } + gTrackCheckpoints[gNumberOfCheckpoints].unk2C = var_a0; + gTrackCheckpoints[gNumberOfCheckpoints].altRouteID = -1; + gNumberOfCheckpoints++; + } + } + } + + duplicateCheckpoint = FALSE; + do { + altId = TRUE; + + for (i = 0; i < gNumberOfCheckpoints - 1; i++) { + if (gTrackCheckpoints[i].unk2C == gTrackCheckpoints[i + 1].unk2C) { + duplicateCheckpoint = TRUE; + checkpointNum = gTrackCheckpoints[i].unk2C; + } + + if (gTrackCheckpoints[i + 1].unk2C < gTrackCheckpoints[i].unk2C) { + temp_v1 = gTrackCheckpoints[i].unk2C; + obj = gTrackCheckpoints[i].obj; + gTrackCheckpoints[i].unk2C = gTrackCheckpoints[i + 1].unk2C; + gTrackCheckpoints[i].obj = gTrackCheckpoints[i + 1].obj; + gTrackCheckpoints[i + 1].unk2C = temp_v1; + gTrackCheckpoints[i + 1].obj = obj; + altId = FALSE; + } + } + } while (!altId); + D_8011AED4 = gNumberOfCheckpoints; + gNumberOfCheckpoints -= var_t2; + if (duplicateCheckpoint) { + set_render_printf_position(20, 220); + render_printf(sDuplicateCheckpointString /* "Error: Multiple checkpoint no: %d !!\n"; */, checkpointNum); + } + for (i = gNumberOfCheckpoints; i < D_8011AED4; i++) { + temp_v1 = gTrackCheckpoints[i].unk2C - 255; + for (var_a0 = 0, breakOut = FALSE; var_a0 < gNumberOfCheckpoints && !breakOut; var_a0++) { + if (temp_v1 == gTrackCheckpoints[var_a0].unk2C) { + gTrackCheckpoints[var_a0].altRouteID = i; + gTrackCheckpoints[i].altRouteID = var_a0; + breakOut = TRUE; + } + } + } + + for (i = 0; i < D_8011AED4; i++) { + checkpoint = &gTrackCheckpoints[i]; + obj = checkpoint->obj; + checkpointEntry = &obj->segment.level_entry->checkpoint; + transform.rotation.y_rotation = obj->segment.trans.rotation.y_rotation; + transform.rotation.x_rotation = obj->segment.trans.rotation.x_rotation; + transform.rotation.z_rotation = obj->segment.trans.rotation.z_rotation; + transform.scale = 1.0f; + transform.x_position = 0.0f; + transform.y_position = 0.0f; + transform.z_position = 0.0f; + object_transform_to_matrix(&mtx[0], &transform); + guMtxXFMF(&mtx[0], 0.0f, 0.0f, 1.0f, &ox, &oy, &oz); + checkpoint->rotationXFrac = ox; + checkpoint->rotationYFrac = oy; + checkpoint->rotationZFrac = oz; + checkpoint->unkC = -(((obj->segment.trans.x_position * ox) + (obj->segment.trans.y_position * oy)) + + (obj->segment.trans.z_position * oz)); + checkpoint->x = obj->segment.trans.x_position; + checkpoint->y = obj->segment.trans.y_position; + checkpoint->z = obj->segment.trans.z_position; + checkpoint->scale = obj->segment.trans.scale * 2; + checkpoint->unk2C = obj->segment.trans.scale * 128.0f; + checkpoint->unk24 = 0.0f; + checkpoint->distance = 0.0f; + if (i < gNumberOfCheckpoints) { + temp_v1 = i + 1; + if (temp_v1 == gNumberOfCheckpoints) { + temp_v1 = 0; + } + xDiff = obj->segment.trans.x_position - gTrackCheckpoints[temp_v1].obj->segment.trans.x_position; + yDiff = obj->segment.trans.y_position - gTrackCheckpoints[temp_v1].obj->segment.trans.y_position; + zDiff = obj->segment.trans.z_position - gTrackCheckpoints[temp_v1].obj->segment.trans.z_position; + checkpoint->distance = sqrtf(((xDiff * xDiff) + (yDiff * yDiff)) + (zDiff * zDiff)); + altRouteId = gTrackCheckpoints[temp_v1].altRouteID; + if (altRouteId != -1) { + xDiff = obj->segment.trans.x_position - gTrackCheckpoints[altRouteId].obj->segment.trans.x_position; + yDiff = obj->segment.trans.y_position - gTrackCheckpoints[altRouteId].obj->segment.trans.y_position; + zDiff = obj->segment.trans.z_position - gTrackCheckpoints[altRouteId].obj->segment.trans.z_position; + checkpoint->unk24 = sqrtf(((xDiff * xDiff) + (yDiff * yDiff)) + (zDiff * zDiff)); + } else { + checkpoint->unk24 = checkpoint->distance; + } + } else { + temp_v1 = gTrackCheckpoints[i].altRouteID + 1; + if (temp_v1 == gNumberOfCheckpoints) { + temp_v1 = 0; + } + xDiff = obj->segment.trans.x_position - gTrackCheckpoints[temp_v1].obj->segment.trans.x_position; + yDiff = obj->segment.trans.y_position - gTrackCheckpoints[temp_v1].obj->segment.trans.y_position; + zDiff = obj->segment.trans.z_position - gTrackCheckpoints[temp_v1].obj->segment.trans.z_position; + checkpoint->distance = sqrtf(((xDiff * xDiff) + (yDiff * yDiff)) + (zDiff * zDiff)); + altRouteId = gTrackCheckpoints[temp_v1].altRouteID; + if (altRouteId != -1) { + xDiff = obj->segment.trans.x_position - gTrackCheckpoints[altRouteId].obj->segment.trans.x_position; + yDiff = obj->segment.trans.y_position - gTrackCheckpoints[altRouteId].obj->segment.trans.y_position; + zDiff = obj->segment.trans.z_position - gTrackCheckpoints[altRouteId].obj->segment.trans.z_position; + checkpoint->unk24 = sqrtf(((xDiff * xDiff) + (yDiff * yDiff)) + (zDiff * zDiff)); + } else { + checkpoint->unk24 = checkpoint->distance; + } + } + checkpoint->unk2E[0] = checkpointEntry->unkB; + checkpoint->unk32[0] = checkpointEntry->unkF; + checkpoint->unk36[0] = checkpointEntry->unk13; + checkpoint->unk2E[1] = checkpointEntry->unkC; + checkpoint->unk32[1] = checkpointEntry->unk10; + checkpoint->unk36[1] = checkpointEntry->unk14; + checkpoint->unk2E[2] = checkpointEntry->unkD; + checkpoint->unk32[2] = checkpointEntry->unk11; + checkpoint->unk36[2] = checkpointEntry->unk15; + checkpoint->unk2E[3] = checkpointEntry->unkE; + checkpoint->unk32[3] = checkpointEntry->unk12; + checkpoint->unk36[3] = checkpointEntry->unk16; + checkpoint->unk3B = checkpointEntry->unk19; + } +} + #pragma GLOBAL_ASM("asm/nonmatchings/objects/func_800185E4.s") /** @@ -6379,14 +6537,14 @@ s8 func_800214E4(Object *obj, s32 updateRate) { f32 catmull_rom_interpolation(f32 *data, s32 index, f32 x) { f32 ret; - f32 temp3, temp2, temp; + f32 c, b, a; - temp = (-0.5 * data[index]) + (1.5 * data[index + 1]) + (-1.5 * data[index + 2]) + (0.5 * data[index + 3]); - temp2 = (1.0 * data[index]) + (-2.5 * data[index + 1]) + (2.0 * data[index + 2]) + (-0.5 * data[index + 3]); - temp3 = (data[index + 2] * 0.5) + (0.0 * data[index + 1]) + (-0.5 * data[index]) + (0.0 * data[index + 3]); + a = (-0.5 * data[index]) + (1.5 * data[index + 1]) + (-1.5 * data[index + 2]) + (0.5 * data[index + 3]); + b = (1.0 * data[index]) + (-2.5 * data[index + 1]) + (2.0 * data[index + 2]) + (-0.5 * data[index + 3]); + c = (data[index + 2] * 0.5) + (0.0 * data[index + 1]) + (-0.5 * data[index]) + (0.0 * data[index + 3]); ret = (1.0 * data[index + 1]); - ret = (((((temp * x) + temp2) * x) + temp3) * x) + ret; + ret = (((((a * x) + b) * x) + c) * x) + ret; return ret; } @@ -6396,48 +6554,50 @@ f32 catmull_rom_interpolation(f32 *data, s32 index, f32 x) { */ f32 cubic_spline_interpolation(f32 *data, s32 index, f32 x, f32 *derivative) { f32 ret; - f32 temp3, temp2, temp; + f32 c, b, a; - temp = (-0.5 * data[index]) + (1.5 * data[index + 1]) + (-1.5 * data[index + 2]) + (0.5 * data[index + 3]); - temp2 = (1.0 * data[index]) + (-2.5 * data[index + 1]) + (2.0 * data[index + 2]) + (-0.5 * data[index + 3]); - temp3 = (data[index + 2] * 0.5) + (0.0 * data[index + 1]) + (-0.5 * data[index]) + (0.0 * data[index + 3]); + a = (-0.5 * data[index]) + (1.5 * data[index + 1]) + (-1.5 * data[index + 2]) + (0.5 * data[index + 3]); + b = (1.0 * data[index]) + (-2.5 * data[index + 1]) + (2.0 * data[index + 2]) + (-0.5 * data[index + 3]); + c = (data[index + 2] * 0.5) + (0.0 * data[index + 1]) + (-0.5 * data[index]) + (0.0 * data[index + 3]); ret = (1.0 * data[index + 1]); - *derivative = (((temp * 3 * x) + (2 * temp2)) * x) + temp3; - ret = (((((temp * x) + temp2) * x) + temp3) * x) + ret; + *derivative = (((a * 3 * x) + (2 * b)) * x) + c; + ret = (((((a * x) + b) * x) + c) * x) + ret; return ret; } -f32 func_8002277C(f32 *data, s32 index, f32 x) { +f32 catmull_rom_derivative(f32 *data, s32 index, f32 x) { f32 derivative; - f32 temp3, temp2, temp; + f32 c, b, a; - temp = (-0.5 * data[index]) + (1.5 * data[index + 1]) + (-1.5 * data[index + 2]) + (0.5 * data[index + 3]); - temp2 = (1.0 * data[index]) + (-2.5 * data[index + 1]) + (2.0 * data[index + 2]) + (-0.5 * data[index + 3]); - temp3 = (data[index + 2] * 0.5) + (0.0 * data[index + 1]) + (-0.5 * data[index]) + (0.0 * data[index + 3]); + a = (-0.5 * data[index]) + (1.5 * data[index + 1]) + (-1.5 * data[index + 2]) + (0.5 * data[index + 3]); + b = (1.0 * data[index]) + (-2.5 * data[index + 1]) + (2.0 * data[index + 2]) + (-0.5 * data[index + 3]); + c = (data[index + 2] * 0.5) + (0.0 * data[index + 1]) + (-0.5 * data[index]) + (0.0 * data[index + 3]); - derivative = (((temp * 3 * x) + (2 * temp2)) * x) + temp3; + derivative = (((a * 3 * x) + (2 * b)) * x) + c; return derivative; } -UNUSED f32 lerp(f32 *arg0, u32 arg1, f32 arg2) { - f32 result = arg0[arg1 + 1] + ((arg0[arg1 + 2] - arg0[arg1 + 1]) * arg2); +/** + * Imprecise method, which does not guarantee v = v1 when t = 1. (From Wikipedia) + */ +f32 lerp(f32 *data, u32 index, f32 t) { + f32 result = data[index + 1] + t * ((data[index + 2] - data[index + 1])); return result; } -UNUSED f32 func_800228B0(f32 *arg0, u32 arg1, f32 arg2, f32 *arg3) { - f32 new_var2; - f32 temp_f12; - f32 new_var; - f32 temp_f2; - new_var = arg0[arg1 + 2] - arg0[arg1 + 1]; - temp_f2 = new_var * arg2; - temp_f12 = arg0[arg1 + 1]; - new_var2 = temp_f12 + temp_f2; - *arg3 = arg0[arg1 + 2] - arg0[arg1 + 1]; - return new_var2; +/** + * Peforms the lerp, and also returns the distance between the two points. + */ +f32 lerp_and_get_derivative(f32 *data, u32 index, f32 t, f32 *derivative) { + f32 lerp; + f32 vector; + vector = data[index + 2] - data[index + 1]; + lerp = data[index + 1] + (vector * t); + *derivative = vector; + return lerp; } UNUSED void func_800228DC(UNUSED s32 arg0, UNUSED s32 arg1, UNUSED s32 arg2) { diff --git a/src/objects.h b/src/objects.h index 51aff5f5..2b4f2124 100644 --- a/src/objects.h +++ b/src/objects.h @@ -422,7 +422,7 @@ void func_8001F3C8(s32 arg0); void func_8001F450(void); s32 func_800210CC(s8 arg0); s8 func_800214C4(void); -f32 lerp(f32 *arg0, u32 arg1, f32 arg2); +f32 lerp(f32 *data, u32 index, f32 t); void func_800228DC(s32 arg0, s32 arg1, s32 arg2); void init_racer_for_challenge(s32 vehicleID); s8 is_taj_challenge(void); @@ -496,7 +496,7 @@ void race_finish_time_trial(void); s32 obj_dist_racer(f32 x, f32 y, f32 z, f32 radius, s32 is2dCheck, Object **sortObj); void mode_init_taj_race(void); void racerfx_update(s32 updateRate); -f32 func_8002277C(f32 *data, s32 index, f32 x); +f32 catmull_rom_derivative(f32 *data, s32 index, f32 x); void race_transition_adventure(s32 updateRate); void func_8001E4C4(void); void racerfx_alloc(s32 numberOfVertices, s32 numberOfTriangles); diff --git a/src/racer.c b/src/racer.c index c825dceb..a3bd3df9 100644 --- a/src/racer.c +++ b/src/racer.c @@ -757,9 +757,9 @@ void func_80045C48(Object *obj, Object_Racer *racer, s32 updateRate) { racer->unk1BA = magnitude; //(s16) (s32) (((sp7C - sp78) * var_f20) + sp78); racer->unk1BC = magnitude; //(s16) (s32) (((sp6C - sp68) * var_f20) + sp68); } - xDerivative = func_8002277C(splineX, 0, magnitude); - yDerivative = func_8002277C(splineY, 0, magnitude); - zDerivative = func_8002277C(splineZ, 0, magnitude); + xDerivative = catmull_rom_derivative(splineX, 0, magnitude); + yDerivative = catmull_rom_derivative(splineY, 0, magnitude); + zDerivative = catmull_rom_derivative(splineZ, 0, magnitude); temp_f0 = sqrtf((xDerivative * xDerivative) + (yDerivative * yDerivative) + (zDerivative * zDerivative)); if (temp_f0 != 0.0f) { temp_f0 = 100.0f / temp_f0; diff --git a/ver/symbols/symbol_addrs.jpn.v79.txt b/ver/symbols/symbol_addrs.jpn.v79.txt index 12fd0060..176960e1 100644 --- a/ver/symbols/symbol_addrs.jpn.v79.txt +++ b/ver/symbols/symbol_addrs.jpn.v79.txt @@ -374,9 +374,9 @@ func_800214E4 = 0x800214E4; func_80021600 = 0x80021600; catmull_rom_interpolation = 0x80022540; cubic_spline_interpolation = 0x8002263C; -func_8002277C = 0x8002277C; +catmull_rom_derivative = 0x8002277C; lerp = 0x80022888; -func_800228B0 = 0x800228B0; +lerp_and_get_derivative = 0x800228B0; func_800228DC = 0x800228DC; init_racer_for_challenge = 0x800228EC; mode_init_taj_race = 0x80022948; diff --git a/ver/symbols/symbol_addrs.pal.v77.txt b/ver/symbols/symbol_addrs.pal.v77.txt index d7837efd..1c349c74 100644 --- a/ver/symbols/symbol_addrs.pal.v77.txt +++ b/ver/symbols/symbol_addrs.pal.v77.txt @@ -374,9 +374,9 @@ func_800214E4 = 0x800214E4; func_80021600 = 0x80021600; catmull_rom_interpolation = 0x80022540; cubic_spline_interpolation = 0x8002263C; -func_8002277C = 0x8002277C; +catmull_rom_derivative = 0x8002277C; lerp = 0x80022888; -func_800228B0 = 0x800228B0; +lerp_and_get_derivative = 0x800228B0; func_800228DC = 0x800228DC; init_racer_for_challenge = 0x800228EC; mode_init_taj_race = 0x80022948; diff --git a/ver/symbols/symbol_addrs.pal.v80.txt b/ver/symbols/symbol_addrs.pal.v80.txt index a5fdafcc..bcdf426a 100644 --- a/ver/symbols/symbol_addrs.pal.v80.txt +++ b/ver/symbols/symbol_addrs.pal.v80.txt @@ -374,9 +374,9 @@ func_800214E4 = 0x80021518; func_80021600 = 0x80021634; catmull_rom_interpolation = 0x80022574; cubic_spline_interpolation = 0x80022670; -func_8002277C = 0x800227B0; +catmull_rom_derivative = 0x800227B0; lerp = 0x800228BC; -func_800228B0 = 0x800228E4; +lerp_and_get_derivative = 0x800228E4; func_800228DC = 0x80022910; init_racer_for_challenge = 0x80022920; mode_init_taj_race = 0x8002297C; diff --git a/ver/symbols/symbol_addrs.us.v77.txt b/ver/symbols/symbol_addrs.us.v77.txt index 9c8131a3..fde577cb 100644 --- a/ver/symbols/symbol_addrs.us.v77.txt +++ b/ver/symbols/symbol_addrs.us.v77.txt @@ -374,9 +374,9 @@ func_800214E4 = 0x800214E4; func_80021600 = 0x80021600; catmull_rom_interpolation = 0x80022540; cubic_spline_interpolation = 0x8002263C; -func_8002277C = 0x8002277C; +catmull_rom_derivative = 0x8002277C; lerp = 0x80022888; -func_800228B0 = 0x800228B0; +lerp_and_get_derivative = 0x800228B0; func_800228DC = 0x800228DC; init_racer_for_challenge = 0x800228EC; mode_init_taj_race = 0x80022948; diff --git a/ver/symbols/symbol_addrs.us.v80.txt b/ver/symbols/symbol_addrs.us.v80.txt index 3c522de7..98e1eb15 100644 --- a/ver/symbols/symbol_addrs.us.v80.txt +++ b/ver/symbols/symbol_addrs.us.v80.txt @@ -374,9 +374,9 @@ func_800214E4 = 0x80021518; func_80021600 = 0x80021634; catmull_rom_interpolation = 0x80022574; cubic_spline_interpolation = 0x80022670; -func_8002277C = 0x800227B0; +catmull_rom_derivative = 0x800227B0; lerp = 0x800228BC; -func_800228B0 = 0x800228E4; +lerp_and_get_derivative = 0x800228E4; func_800228DC = 0x80022910; init_racer_for_challenge = 0x80022920; mode_init_taj_race = 0x8002297C;