From a298ec5b5f4b186d669233cd75206a18b0f89cb9 Mon Sep 17 00:00:00 2001 From: Ryan Myers Date: Wed, 16 Apr 2025 15:27:28 -0400 Subject: [PATCH] Match func_80026430 and fix UB in func_80026070 (#516) * Score and formatting * Fix UB for func_80026070, and get func_80026430 to NON_EQ * func_80026430 near match * documenting * Single diff for func_80026430 * Match func_80026430 * Update score and merge master * Rework func_80026430 to have an AVOID_UB. --- README.md | 20 +++--- include/structs.h | 9 ++- src/menu.c | 6 +- src/tracks.c | 158 ++++++++++++++++++++++++++++++++++++++++------ src/waves.c | 13 ++-- 5 files changed, 165 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index f8bb540b..fbe9c435 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 April 14, 2025, this is our current score: +As of April 16, 2025, this is our current score: -    Decomp progress: 78.93% +    Decomp progress: 79.16%     Documentation progress: 50.05% @@ -117,25 +117,25 @@ s32 is_drumstick_unlocked(void) { ``` -As of April 14, 2025, this is our current score: +As of April 16, 2025, this is our current score: ``` =================================================================== ADVENTURE ONE (ASM -> C Decompilation) - -------------- 78.93% Complete (81.50% NON_MATCHING) -------------- - # Decompiled functions: 1851 - # GLOBAL_ASM remaining: 100 - # NON_MATCHING functions: 12 - # NON_EQUIVALENT WIP functions: 29 + -------------- 79.16% Complete (81.99% NON_MATCHING) -------------- + # Decompiled functions: 1852 + # GLOBAL_ASM remaining: 98 + # NON_MATCHING functions: 13 + # NON_EQUIVALENT WIP functions: 28 --------------------------- Game Status --------------------------- Balloons: 38/47, Keys: 4/4, Trophies: 3/5 T.T. Amulets: 4/4, Wizpig Amulets: 3/4 ------------------------------------------------------------------- - We are collecting silver coins in Haunted Woods. (0/8 silver coins) + We are collecting silver coins in Haunted Woods. (2/8 silver coins) =================================================================== ADVENTURE TWO (Cleanup & Documentation) ------------------------- 50.05% Complete ------------------------- # Documented functions: 1090 - # Undocumented remaining: 564 + # Undocumented remaining: 563 --------------------------- Game Status --------------------------- Balloons: 25/47, Keys: 3/4, Trophies: 2/5 T.T. Amulets: 2/4, Wizpig Amulets: 2/4 diff --git a/include/structs.h b/include/structs.h index c7110a91..93c3928c 100644 --- a/include/structs.h +++ b/include/structs.h @@ -666,6 +666,13 @@ typedef struct ObjectModel { /* 0x54 */ u8 pad[0x2C]; } ObjectModel; +typedef struct CollisionNode { + u16 triangleIndex; // This triangle index + u16 closestTri01; // The closest triangle index to the line made from indices 0 & 1. + u16 closestTri12; // The closest triangle index to the line made from indices 1 & 2. + u16 closestTri20; // The closest triangle index to the line made from indices 2 & 0. +} CollisionNode; + /* Size: 0x44 bytes */ typedef struct LevelModelSegment { /* 0x00 */ Vertex *vertices; @@ -673,7 +680,7 @@ typedef struct LevelModelSegment { /* 0x08 */ s32 unk8; /* 0x0C */ TriangleBatchInfo *batches; /* 0x10 */ s16 *unk10; -/* 0x14 */ u16 *unk14; +/* 0x14 */ CollisionNode *unk14; /* 0x18 */ f32 *unk18; /* 0x1C */ s16 numberOfVertices; /* 0x1E */ s16 numberOfTriangles; diff --git a/src/menu.c b/src/menu.c index 7e33a5fd..b27db463 100644 --- a/src/menu.c +++ b/src/menu.c @@ -5611,11 +5611,9 @@ void pakmenu_render(UNUSED s32 updateRate) { set_current_text_colour(6, 255, 255, 255, 0, 255); set_current_text_background_colour(6, 0, 0, 0, 0); render_dialogue_text(6, POS_CENTRED, 2 - PAKMENU_JP_OFFSET, gMenuText[ASSET_MENU_TEXT_CONTPAK1 + gMenuOption], - 1, - HORZ_ALIGN_CENTER); // CONTROLLER PAK 1 / 2 / 3 / 4 + 1, HORZ_ALIGN_CENTER); // CONTROLLER PAK 1 / 2 / 3 / 4 render_dialogue_text(6, POS_CENTRED, 16 - PAKMENU_JP_OFFSET, gMenuText[ASSET_MENU_TEXT_FREEPAGESX], - sCurrentControllerPakFreePages, - HORZ_ALIGN_CENTER); // FREE PAGES: ~ + sCurrentControllerPakFreePages, HORZ_ALIGN_CENTER); // FREE PAGES: ~ render_dialogue_box(&sMenuCurrDisplayList, NULL, NULL, 6); yPos += 34; // To 82 diff --git a/src/tracks.c b/src/tracks.c index 8792558a..660fb81c 100644 --- a/src/tracks.c +++ b/src/tracks.c @@ -643,16 +643,15 @@ void func_8002581C(u8 *segmentIds, s32 numberOfSegments, s32 viewportIndex) { void func_80026070(LevelModelSegmentBoundingBox *arg0, f32 arg1, f32 arg2, f32 arg3) { f32 sp80[4]; f32 sp70[4]; - s16 temp2; - s32 pad; - f32 sp60[2]; - s16 index; - s16 nextIndex; + f32 sp60[4]; + f32 temp; f32 sp54[2]; f32 sp4C[2]; - f32 temp; + s16 index; + s16 nextIndex; s16 sp40[4]; s16 var_t0; + s16 temp2; sp80[0] = arg0->x1; sp70[0] = arg0->z1; @@ -701,10 +700,8 @@ void func_80026070(LevelModelSegmentBoundingBox *arg0, f32 arg1, f32 arg2, f32 a // Returns must be on the same line. // clang-format off - if (-300.0 > sp60[1]) { return; -} - if (sp60[0] > 300.0) { return; -} + if (-300.0 > sp60[1]) { return; } + if (sp60[0] > 300.0) { return; } // clang-format on if (sp60[0] < -300.0) { @@ -718,7 +715,132 @@ void func_80026070(LevelModelSegmentBoundingBox *arg0, f32 arg1, f32 arg2, f32 a } } -#pragma GLOBAL_ASM("asm/nonmatchings/tracks/func_80026430.s") +void func_80026430(LevelModelSegment *segment, f32 arg1, f32 arg2, f32 arg3) { + s16 i; + s16 index; + s16 verticesOffset; + s16 nextFaceOffset; + s16 nextIndex; + s16 currFaceOffset; + s16 j; + Vertex *vert; + s8 spF8[3]; + f32 temp; + s16 var_s0; + s16 var_t0; +#ifdef AVOID_UB + f32 spE8[3]; // This really should be size of 3, but something is keeping it from matching that way. +#else + f32 spE8[2]; +#endif + f32 spDC[3]; + f32 spD0[3]; + f32 spC4[3]; + f32 spB8[3]; + f32 spB0[2]; + f32 spA8[2]; + f32 spA0[2]; + + if (D_8011D49E >= D_8011D4BA) { + return; + } + + for (i = 0; i < segment->numberOfBatches; i++) { + currFaceOffset = segment->batches[i].facesOffset; + verticesOffset = segment->batches[i].verticesOffset; + nextFaceOffset = segment->batches[i + 1].facesOffset; + if (segment->batches[i].flags & (BATCH_FLAGS_HIDDEN | BATCH_FLAGS_UNK00000200)) { + currFaceOffset = nextFaceOffset; + } + for (j = currFaceOffset; j < nextFaceOffset; j++) { + if ((segment->triangles[j].flags & BACKFACE_DRAW)) { + continue; + } + var_t0 = 0; + for (index = 0; index < 3; index++) { + vert = &(segment->triangles[j].verticesArray[index + 1] + verticesOffset)[segment->vertices]; + spE8[index] = vert->x; + spDC[index] = vert->y; + spD0[index] = vert->z; + spC4[index] = (arg1 * spE8[index]) + (arg2 * spD0[index]) + arg3; + + spF8[index] = (spC4[index] <= 0.0); + var_t0 += (spF8[index] <= 0.0); + } + if ((var_t0 == 1) || (var_t0 == 2)) { + for (var_s0 = 0, index = 0; index < 3; index++) { + nextIndex = index + 1; + if (nextIndex >= 3) { + nextIndex = 0; + } + if ((spF8[nextIndex] != spF8[index]) != 0) { + temp = spC4[index] / (spC4[index] - spC4[nextIndex]); + spB0[var_s0] = spE8[index] + ((spE8[nextIndex] - spE8[index]) * temp); + spB8[var_s0] = spDC[index] + ((spDC[nextIndex] - spDC[index]) * temp); + spA0[var_s0] = spB8[var_s0]; + spA8[var_s0] = spD0[index] + ((spD0[nextIndex] - spD0[index]) * temp); + var_s0++; + } + } + + var_s0 = 0; + spF8[0] = 0; + spF8[1] = 0; + spC4[0] = (D_8011D4A0 * spB0[0]) + (D_8011D4A4 * spA8[0]) + D_8011D4A8; + spC4[1] = (D_8011D4A0 * spB0[1]) + (D_8011D4A4 * spA8[1]) + D_8011D4A8; + if (spC4[0] < -300.0) { + spF8[0] = 1; + } + if (spC4[0] > 300.0) { + spF8[0] |= 2; + } + if (spC4[1] < -300.0) { + spF8[1] = 1; + } + if (spC4[1] > 300.0) { + spF8[1] |= 2; + } + // clang-format off + if ((spF8[0] | spF8[1]) == 0) { var_s0 = 1; } + // clang-format on + else if ((spF8[1] != spF8[0]) != 0) { + index = 0; + if (spC4[1] < spC4[0]) { + index = 1; + } + nextIndex = 1 - index; + if (spF8[index] == 1) { + temp = ((-spC4[index] - 300.0) / (spC4[nextIndex] - spC4[index])); + spB8[index] = spB8[index] + ((spB8[nextIndex] - spB8[index]) * temp); + spC4[index] = -300.0f; + } + if (spF8[nextIndex] == 2) { + temp = ((spC4[nextIndex] - 300.0) / (spC4[nextIndex] - spC4[index])); + spB8[nextIndex] = spB8[nextIndex] + ((spB8[index] - spB8[nextIndex]) * temp); + spC4[nextIndex] = 300.0f; + } + var_s0 = 1; + } + if (var_s0 != 0) { + var_t0 = (segment->unk14[j].triangleIndex << 2); + temp = (spB0[0] + D_8011D4A0) * segment->unk18[var_t0]; + temp += spB8[0] * segment->unk18[var_t0 + 1]; + temp += (spA8[0] + D_8011D4A4) * segment->unk18[var_t0 + 2]; + temp += segment->unk18[var_t0 + 3]; + var_s0 = (temp > 0.0) << 2; + if (segment->unk18[var_t0 + 1] < 0.0f) { + var_s0 |= 1; + } + if (spC4[0] == spC4[1]) { + var_s0 |= 8; + } + func_80026C14(spC4[0], spB8[0], var_s0); + func_80026C14(spC4[1], spB8[1], var_s0); + } + } + } + } +} void func_80026C14(s16 arg0, s16 arg1, s32 arg2) { s16 i; @@ -754,7 +876,7 @@ void func_80026C14(s16 arg0, s16 arg1, s32 arg2) { } void func_80026E54(s16 arg0, s8 *arg1, f32 arg2, f32 arg3) { - s32 pad[7]; + UNUSED s32 pad[7]; unk8011D478 *next; unk8011D478 *curr; s16 temp3; @@ -770,7 +892,7 @@ void func_80026E54(s16 arg0, s8 *arg1, f32 arg2, f32 arg3) { s8 temp; s8 temp0; s8 temp1; - f32 temp2; + UNUSED f32 temp2; f32 sp94[10]; f32 sp6C[10]; s8 sp60[10]; @@ -831,7 +953,7 @@ s32 func_80027184(f32 *arg0, f32 *arg1, f32 arg2, f32 arg3) { Vertex *verts; Triangle *tris; s32 two; - s32 test; + UNUSED s32 test; s32 vertZ1; s32 vertX2; s32 vertZ2; @@ -2209,7 +2331,6 @@ s32 func_8002BAB0(s32 levelSegmentIndex, f32 xIn, f32 zIn, f32 *yOut) { TriangleBatchInfo *currentBatch; f32 *temp_v1_4; Vec4f tempVec4f; - u16 *new_var; u16 temp; if (levelSegmentIndex < 0 || levelSegmentIndex >= gCurrentLevelModel->numberOfSegments) { @@ -2274,8 +2395,7 @@ s32 func_8002BAB0(s32 levelSegmentIndex, f32 xIn, f32 zIn, f32 *yOut) { temp_ra_3 = ((((XInInt - vert1X) * (vert3Z - vert1Z)) - ((vert3X - vert1X) * (ZInInt - vert1Z))) >= 0); var_v0 = faceNum; // fake? if (temp_ra_1 == temp_ra_2 && temp_ra_2 != temp_ra_3) { - new_var = currentSegment->unk14; - temp = new_var[faceNum * 4]; + temp = currentSegment->unk14[faceNum].triangleIndex; temp_v1_4 = (f32 *) ¤tSegment->unk18[temp * 4]; tempVec4f.x = temp_v1_4[0]; tempVec4f.y = temp_v1_4[1]; @@ -2364,7 +2484,7 @@ void func_8002C0C4(s32 modelId) { LOCAL_OFFSET_TO_RAM_ADDRESS(Vertex *, gCurrentLevelModel->segments[k].vertices); LOCAL_OFFSET_TO_RAM_ADDRESS(Triangle *, gCurrentLevelModel->segments[k].triangles); LOCAL_OFFSET_TO_RAM_ADDRESS(TriangleBatchInfo *, gCurrentLevelModel->segments[k].batches); - LOCAL_OFFSET_TO_RAM_ADDRESS(u16 *, gCurrentLevelModel->segments[k].unk14); + LOCAL_OFFSET_TO_RAM_ADDRESS(CollisionNode *, gCurrentLevelModel->segments[k].unk14); } for (k = 0; k < gCurrentLevelModel->numberOfTextures; k++) { gCurrentLevelModel->textures[k].texture = @@ -2873,7 +2993,7 @@ void shadow_generate(Object *obj, s32 isWater) { s32 yPos; f32 xPos; f32 zPos; - s32 *new_var; + UNUSED s32 *pad; s32 cheats; s32 inSegs[28]; s32 i; diff --git a/src/waves.c b/src/waves.c index 36f0b20c..bccfa96f 100644 --- a/src/waves.c +++ b/src/waves.c @@ -284,7 +284,7 @@ void func_800B82B4(LevelModel *arg0, LevelHeader *arg1, s32 arg2) { D_8012A01C = 10000.0f; D_8012A020 = -10000.0f; for (var_s7 = 0; var_s7 < D_80129FC8.unk20; var_s7++) { - D_800E3040[var_s7] = (sins_f(var_s6) * D_80129FC8.unkC) + (sins_f(var_fp) * D_80129FC8.unk18); + D_800E3040[var_s7] = (sins_f(var_s6) * D_80129FC8.unkC) + (sins_f(var_fp) * D_80129FC8.unk18); if (D_80129FC8.unk28 != 0) { D_800E3040[var_s7] *= 2.0f; } @@ -297,7 +297,6 @@ void func_800B82B4(LevelModel *arg0, LevelHeader *arg1, s32 arg2) { var_s6 += sp54; var_fp += sp4C; } - ; save_rng_seed(); set_rng_seed(0x57415646); @@ -352,7 +351,7 @@ void func_800B82B4(LevelModel *arg0, LevelHeader *arg1, s32 arg2) { D_800E3080[var_a0][var_s5].unk2 = (var_s0 + D_80129FC8.unk0) + 1; D_800E3080[var_a0][var_s5].unk3 = var_s0 + 1; var_s5++; - D_800E3080[var_a0][var_s5].unk0 = 0x40; + D_800E3080[var_a0][var_s5].unk0 = 0x40; D_800E3080[var_a0][var_s5].unk1 = var_s0 + 1; D_800E3080[var_a0][var_s5].unk2 = (var_s0 + D_80129FC8.unk0) + 1; D_800E3080[var_a0][var_s5].unk3 = (var_s0 + D_80129FC8.unk0) + 2; @@ -371,7 +370,7 @@ void func_800B82B4(LevelModel *arg0, LevelHeader *arg1, s32 arg2) { for (i = 0; i < ARRAY_COUNT(D_800E3070); i++) { // @note this should probably be the following for loop (or something like it, anyway) // but the change of var_s3 does not work - + // for (j = 0; j < 4; j++) { // if (j == 0) { // var_s3 = 0; @@ -402,7 +401,7 @@ void func_800B82B4(LevelModel *arg0, LevelHeader *arg1, s32 arg2) { temp_vtx->g = temp_vtx_2->g; temp_vtx->b = temp_vtx_2->b; temp_vtx->a = temp_vtx_2->a; - + temp_vtx_3 = &D_800E3070[i][var_t0]; temp_vtx = &D_8012A028[i][1]; temp_vtx->x = temp_vtx_3->x; @@ -414,7 +413,7 @@ void func_800B82B4(LevelModel *arg0, LevelHeader *arg1, s32 arg2) { temp_vtx->a = temp_vtx_3->a; var_t2 = var_t0 + 1; - var_v1 = (var_t0 + 1) * var_t0 ; + var_v1 = (var_t0 + 1) * var_t0; temp_vtx_4 = &D_800E3070[i][var_v1]; temp_vtx = &D_8012A028[i][2]; temp_vtx->x = temp_vtx_4->x; @@ -425,7 +424,7 @@ void func_800B82B4(LevelModel *arg0, LevelHeader *arg1, s32 arg2) { temp_vtx->b = temp_vtx_4->b; temp_vtx->a = temp_vtx_4->a; - var_v1 = (var_t0 + 1) * var_t0 ; + var_v1 = (var_t0 + 1) * var_t0; temp_vtx_5 = &(&D_800E3070[i][var_v1])[var_t0]; temp_vtx = &D_8012A028[i][3]; temp_vtx->x = temp_vtx_5->x;