From 007d07311f517267ff78147ce67407dd47511fce Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:06:46 -0700 Subject: [PATCH 01/64] Match ifStatus_802F61FC Passing the four HUD-colour lookups straight into gm_80160854 instead of staging them in u8 locals removes the last differing rows. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/melee/if/ifstatus.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/melee/if/ifstatus.c b/src/melee/if/ifstatus.c index 2c053bb566..899e4f27f4 100644 --- a/src/melee/if/ifstatus.c +++ b/src/melee/if/ifstatus.c @@ -731,10 +731,7 @@ HSD_GObj* ifStatus_802F61FC(IfDamageState* state, s32 player_idx) Vec3* vec; HSD_MObj* mobj; HudIndex* hud = ifStatus_GetHUDInfo(); - u8 slot; GXColor color; - u8 hud_color; - u8 team; u8 idx = player_idx; PAD_STACK(0x10); @@ -773,11 +770,9 @@ HSD_GObj* ifStatus_802F61FC(IfDamageState* state, s32 player_idx) vec = ifAll_GetPlayerHUDPosition(idx); HSD_JObjSetTranslate(jobj, vec); HSD_JObjAddTranslationX(jobj, 0.25f); - slot = Player_GetPlayerSlotType(idx); - hud_color = gm_8016B168(); - team = Player_GetTeam(idx); - color = gm_80160968( - gm_80160854(Player_GetPlayerId(idx), team, hud_color, slot)); + color = + gm_80160968(gm_80160854(Player_GetPlayerId(idx), Player_GetTeam(idx), + gm_8016B168(), Player_GetPlayerSlotType(idx))); mobj = HSD_JObjGetChild(jobj)->u.dobj->mobj; mobj->mat->diffuse.r = color.r; mobj->mat->diffuse.g = color.g; From deff6010235e35a6379fd33348a4b805cdbca296 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:12:12 -0700 Subject: [PATCH 02/64] Match ifStock_802FAEC4 The three `int[1]` counter arrays were standing in for loop bodies that the original had in helpers: hoisting the two slot-clearing loops into one `ifStock_ClearGObjSlots` and the stock-GObj creation plus the multi-man block into `ifStock_CreateStockGObjs` gives the target's 0x30 frame and register assignment. `ifStock_802FA5BC` still has to stay out of line, so the file-scope `dont_inline` pragma becomes the `_noinline` wrapper idiom already used elsewhere in the tree. `ifStock_804A1ACC.x108` holds the proc GObj, so it is typed `HSD_GObj*` rather than `int`; `ifStock_804A1774.x108` is a real int and is unchanged. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/melee/if/ifstock.c | 95 +++++++++++++++++++---------------- src/melee/if/ifstock.static.h | 2 +- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index a5351c8cb2..48e35fbb85 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -946,69 +946,78 @@ void fn_802FAC34(HSD_GObj* arg) } } -#ifdef MUST_MATCH -#pragma push -#pragma dont_inline on -#endif -void ifStock_802FAEC4(void) +static inline void ifStock_802FA5BC_noinline(int arg) +{ + ifStock_802FA5BC(arg); +} + +static inline void ifStock_ClearGObjSlots(HSD_GObj** slots, int count) +{ + int i; + + for (i = 0; i < count; i++) { + slots[i] = NULL; + } +} + +static inline void ifStock_CreateStockGObjs(HSD_GObj** slots) { + struct ifStock_804A1378* stock = &ifStock_804A1378; HSD_GObj* gobj; + HSD_JObj* jobj; + int i; + + for (i = 0; i < 16; i++, slots++) { + *slots = NULL; + if (gm_8016B1A8()) { + *slots = ifStock_802FA118(i); + } + } + if (gm_IsMultimanSmashMode()) { + gobj = GObj_Create(14, 15, 0); + jobj = HSD_JObjLoadJoint(stock->x4->joint); + HSD_GObjObject_80390A70(gobj, HSD_GObj_JObjKind, jobj); + GObj_SetupGXLink(gobj, fn_802F9598, 11, 0); + gm_8016895C(jobj, stock->x4, 0); + HSD_JObjReqAnimAll(jobj, 10.0f); + HSD_JObjAnimAll(jobj); + stock->gobj = gobj; + lb_80011E24(jobj, &stock->jobj, 0, 1, 2, 3, 4, 5, -1); + } +} + +void ifStock_802FAEC4(void) +{ struct ifStock_804A1378* stock = &ifStock_804A1378; - DynamicModelDesc** sp18; - int i[1]; - int j[1]; - int k[1]; + DynamicModelDesc** scene_models; + HSD_GObj* gobj; memzero(stock, sizeof(*stock) - sizeof(stock->x204)); memzero(&ifStock_804A1ACC, sizeof(ifStock_804A1ACC)); memzero(&ifStock_804A1A8C, sizeof(ifStock_804A1A8C)); memzero(&ifStock_804A1774, sizeof(ifStock_804A1774)); - lbArchive_LoadSections(*ifAll_GetArchive(), (void**) &sp18, "Stc_scemdls", - 0); - stock->x0 = sp18; - stock->x4 = sp18[1]; - ifStock_804A1ACC.x108 = 0; + lbArchive_LoadSections(*ifAll_GetArchive(), (void**) &scene_models, + "Stc_scemdls", 0); + stock->x0 = scene_models; + stock->x4 = scene_models[1]; + ifStock_804A1ACC.x108 = NULL; ifStock_804A1ACC.x0 = 0; gobj = GObj_Create(14, 15, 0); HSD_GObj_SetupProc(gobj, fn_802FAC34, 17); - ifStock_804A1ACC.x108 = (int) gobj; - for (i[0] = 0; i[0] < 130; i[0]++) { - ifStock_804A1ACC.x10C[i[0]] = NULL; - } + ifStock_804A1ACC.x108 = gobj; + ifStock_ClearGObjSlots(&ifStock_804A1ACC.x10C[0], 130); if (gm_80169394() == 0) { ifStock_804A1774.x10C[0] = NULL; ifStock_804A1774.x0 = 0; gobj = GObj_Create(14, 15, 0); HSD_GObj_SetupProc(gobj, fn_802FA6C4, 17); ifStock_804A1774.x10C[0] = gobj; - for (j[0] = 0; j[0] < 130; j[0]++) { - ifStock_804A1774.x10C[j[0] + 1] = NULL; - } + ifStock_ClearGObjSlots(&ifStock_804A1774.x10C[1], 130); } else if (gm_8016A1F8()) { ifStock_804A1774.x108 = -1; - ifStock_802FA5BC(1); // not inlined - } - for (k[0] = 0; k[0] < 16; k[0]++) { - ifStock_804A1A8C[k[0]] = NULL; - if (gm_8016B1A8()) { - ifStock_804A1A8C[k[0]] = ifStock_802FA118(k[0]); - } - } - if (gm_IsMultimanSmashMode()) { - // ifStock_802FA5BC(0); // inlined - HSD_GObj* gobj2 = GObj_Create(14, 15, 0); - HSD_JObj* jobj = HSD_JObjLoadJoint(stock->x4->joint); - HSD_GObjObject_80390A70(gobj2, HSD_GObj_JObjKind, jobj); - GObj_SetupGXLink(gobj2, fn_802F9598, 11, 0); - gm_8016895C(jobj, stock->x4, 0); - HSD_JObjReqAnimAll(jobj, 10.0f); - HSD_JObjAnimAll(jobj); - stock->gobj = gobj2; - lb_80011E24(jobj, &stock->jobj, 0, 1, 2, 3, 4, 5, -1); + ifStock_802FA5BC_noinline(1); } + ifStock_CreateStockGObjs(ifStock_804A1A8C); } -#ifdef MUST_MATCH -#pragma pop -#endif void ifStock_802FB390(void) { diff --git a/src/melee/if/ifstock.static.h b/src/melee/if/ifstock.static.h index c26a33d8dd..5497955ada 100644 --- a/src/melee/if/ifstock.static.h +++ b/src/melee/if/ifstock.static.h @@ -55,7 +55,7 @@ struct ifStock_804A1ACC { char x0; signed char x1[130]; signed char x83[133]; - int x108; + HSD_GObj* x108; HSD_GObj* x10C[130]; }; From abe449a9ae0b56f8e50c26b181d8229d647d70b8 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:14:07 -0700 Subject: [PATCH 03/64] Match ifStatus_802F5EC0 Both the joint load and the digit-JObj lookup come from inline helpers in the original: each site bills its own stack slot, which accounts for the 0x18 -> 0x10 pad and moves the whole r26-r30 band onto the target's assignment. `tobj` is declared ahead of the loop counter to finish the ordering. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/melee/if/ifstatus.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/melee/if/ifstatus.c b/src/melee/if/ifstatus.c index 899e4f27f4..ba21d33dfe 100644 --- a/src/melee/if/ifstatus.c +++ b/src/melee/if/ifstatus.c @@ -616,20 +616,30 @@ void ifStatus_802F5E50(HSD_GObj* gobj, s32 arg1) } } +static inline HSD_JObj* ifStatus_GetDamageJObj(HSD_JObj* jobj, s32 i) +{ + HSD_GObj* node = (HSD_GObj*) jobj; + return (HSD_JObj*) ifStatus_802F6194(node, i); +} + +static inline HSD_JObj* ifStatus_LoadDamageJObj(HudIndex* hud) +{ + return HSD_JObjLoadJoint(hud->unk258); +} + HSD_GObj* ifStatus_802F5EC0(IfDamageState* state, s32 player_idx) { HSD_GObj* gobj; HSD_MatAnimJoint** anim_base; HSD_JObj* jobj; Vec3* vec; - s32 i; HSD_TObj* tobj; - HSD_GObj* node; + s32 i; HudIndex* hud = ifStatus_GetHUDInfo(); if (state->HUD_parent_entity == NULL) { gobj = GObj_Create(0xE, 0xF, 0); - jobj = HSD_JObjLoadJoint(hud->unk258); + jobj = ifStatus_LoadDamageJObj(hud); HSD_GObjObject_80390A70(gobj, HSD_GObj_JObjKind, jobj); GObj_SetupGXLink(gobj, (void (*)(HSD_GObj*, int)) ifStatus_802F5DE0, 0xB, 0); @@ -649,9 +659,8 @@ HSD_GObj* ifStatus_802F5EC0(IfDamageState* state, s32 player_idx) HSD_JObjAnimAll(jobj); vec = ifAll_GetPlayerHUDPosition((u8) player_idx); HSD_JObjSetTranslate(jobj, vec); - node = (HSD_GObj*) jobj; for (i = 0; i < 4; i++) { - state->jobjs[i] = (HSD_JObj*) ifStatus_802F6194(node, i); + state->jobjs[i] = ifStatus_GetDamageJObj(jobj, i); state->translation_x[i] = HSD_JObjGetTranslationX(state->jobjs[i]); state->translation_y[i] = HSD_JObjGetTranslationY(state->jobjs[i]); } @@ -671,7 +680,7 @@ HSD_GObj* ifStatus_802F5EC0(IfDamageState* state, s32 player_idx) ifStatus_802F5B48(state->HUD_parent_entity); state->old_damage = !state->damage_percent; ifStatus_802F4EDC(state->HUD_parent_entity); - PAD_STACK(0x18); + PAD_STACK(0x10); return state->HUD_parent_entity; } From 8d62f4dd4d50a5ca30e6ce4a6ae9e92575913bbb Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:27:08 -0700 Subject: [PATCH 04/64] Improve hsd_8039F05C to 99.95% MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 97.01% -> 99.95%. The command-list entry is re-read through the global at every field instead of being pooled into a local `HSD_PSCmdList***`, which is what the target's reload-per-store shape asks for; `psTexGroupArray` is addressed by name rather than by subtracting 0x30C from that pointer; and the rect case writes the scale matrix's diagonal (xx/yy/zz) rather than xx/zx/zy — the target's store offsets confirm the diagonal. `ptclref_804D0E5C` is typed `HSD_PSCmdList**` to match how both this function and the target use it, so the 32 casts that spelling would otherwise need go away. particle.c's four index-remap sites keep their old reading with a cast and are byte-identical. The only rows left are the bound check's relocation: the target reads the array symbols.txt calls `psCmdListArray`, not `psNumCmdList`. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/sysdolphin/baselib/generator.c | 144 ++++++++++++----------------- src/sysdolphin/baselib/particle.c | 10 +- src/sysdolphin/baselib/particle.h | 2 +- 3 files changed, 65 insertions(+), 91 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 6c48a94985..5f11612d20 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -1069,17 +1069,11 @@ HSD_Generator* hsd_8039EFAC(s32 linkNo, s32 bank, s32 gfx_id, HSD_JObj* jobj) return gen; } -// @TODO: Currently 96.66% match - command-array register swap and stack -// frame differences remain +/// @todo The bound check reads the .bss array named `psCmdListArray`, not +/// `psNumCmdList`; the two names look swapped against their addresses. HSD_Generator* hsd_8039F05C(s32 linkNo, s32 bank, s32 idx) { - HSD_PSCmdList*** cmdListArr; - HSD_PSTexGroup* tg; HSD_Generator* gen; - s32 ofs; - f32 mag; - f32 f0, f1, f3; - u32 shape; if (bank >= 0x41) { return NULL; @@ -1091,44 +1085,37 @@ HSD_Generator* hsd_8039F05C(s32 linkNo, s32 bank, s32 idx) return NULL; } - cmdListArr = (HSD_PSCmdList***) &ptclref_804D0E5C[bank]; - ofs = idx * 4; - if ((*cmdListArr)[idx] == NULL) { + if (ptclref_804D0E5C[bank][idx] == NULL) { return NULL; } gen = hsd_8039D9C8(); if (gen != NULL) { - gen->type = (*cmdListArr)[idx]->type; + gen->type = ptclref_804D0E5C[bank][idx]->type; gen->bank = bank; gen->linkNo = linkNo; - gen->kind = (*cmdListArr)[idx]->kind; - gen->texGroup = (*cmdListArr)[idx]->texGroup; - gen->life = (*cmdListArr)[idx]->life; - gen->genLife = (*cmdListArr)[idx]->genLife; + gen->kind = ptclref_804D0E5C[bank][idx]->kind; + gen->texGroup = ptclref_804D0E5C[bank][idx]->texGroup; + gen->life = ptclref_804D0E5C[bank][idx]->life; + gen->genLife = ptclref_804D0E5C[bank][idx]->genLife; gen->pos.z = 0.0F; gen->pos.y = 0.0F; gen->pos.x = 0.0F; - gen->vel.x = (*cmdListArr)[idx]->vx; - gen->vel.y = (*cmdListArr)[idx]->vy; - gen->vel.z = (*cmdListArr)[idx]->vz; - gen->grav = (*cmdListArr)[idx]->grav; - gen->fric = (*cmdListArr)[idx]->fric; - gen->size = (*cmdListArr)[idx]->size; - gen->cmdList = (*cmdListArr)[idx]->cmdList; - gen->radius = (*cmdListArr)[idx]->radius; - gen->angle = (*cmdListArr)[idx]->angle; - gen->random = (*cmdListArr)[idx]->random; + gen->vel.x = ptclref_804D0E5C[bank][idx]->vx; + gen->vel.y = ptclref_804D0E5C[bank][idx]->vy; + gen->vel.z = ptclref_804D0E5C[bank][idx]->vz; + gen->grav = ptclref_804D0E5C[bank][idx]->grav; + gen->fric = ptclref_804D0E5C[bank][idx]->fric; + gen->size = ptclref_804D0E5C[bank][idx]->size; + gen->cmdList = ptclref_804D0E5C[bank][idx]->cmdList; + gen->radius = ptclref_804D0E5C[bank][idx]->radius; + gen->angle = ptclref_804D0E5C[bank][idx]->angle; + gen->random = ptclref_804D0E5C[bank][idx]->random; if (gen->kind & 0x100) { - f1 = gen->random; - if (f1 < 0.0F) { - f3 = 1.0F; - if ((1.0F + f1) > 1.1920929e-7F) { - } else { - f3 = 0.0F; - } - gen->count = f3; + if (gen->random < 0.0F) { + gen->count = + (1.0F + gen->random > 1.1920929e-7F) ? 1.0F : 0.0F; } else { gen->count = 0.9999999F; } @@ -1138,95 +1125,83 @@ HSD_Generator* hsd_8039F05C(s32 linkNo, s32 bank, s32 idx) gen->count = HSD_Randf(); } - tg = ((HSD_PSTexGroup***) ((uintptr_t) cmdListArr - bank * 4 - - 0x30C))[bank][gen->texGroup]; - if (tg != NULL && tg->palflag != 0) { - gen->kind |= 0x10; + { + HSD_PSTexGroup* tg = psTexGroupArray[bank][gen->texGroup]; + if (tg != NULL && tg->palflag != 0) { + gen->kind |= 0x10; + } } gen->jobj = NULL; gen->numChild = 0; - shape = gen->type & 0xF; - switch (shape) { + switch (gen->type & 0xF) { case 0: case 3: case 4: { - HSD_PSCmdList* c = (*cmdListArr)[idx]; + HSD_PSCmdList* c = ptclref_804D0E5C[bank][idx]; f32 p1 = c->param1; if (p1 == 0.0F && c->param2 == 0.0F) { gen->aux.disc.minAngle = 0.0F; gen->aux.disc.maxAngle = 6.2831855F; } else { gen->aux.disc.minAngle = p1; - gen->aux.disc.maxAngle = (*cmdListArr)[idx]->param2; + gen->aux.disc.maxAngle = ptclref_804D0E5C[bank][idx]->param2; } break; } case 1: - gen->aux.line.x2 = (*cmdListArr)[idx]->param1; - gen->aux.line.y2 = (*cmdListArr)[idx]->param2; - gen->aux.line.z2 = (*cmdListArr)[idx]->param3; + gen->aux.line.x2 = ptclref_804D0E5C[bank][idx]->param1; + gen->aux.line.y2 = ptclref_804D0E5C[bank][idx]->param2; + gen->aux.line.z2 = ptclref_804D0E5C[bank][idx]->param3; break; case 6: case 7: { - HSD_PSCmdList* c = (*cmdListArr)[idx]; + HSD_PSCmdList* c = ptclref_804D0E5C[bank][idx]; f32 p1 = c->param1; if (p1 == 0.0F && c->param2 == 0.0F) { gen->aux.cone.minAngle = 0.0F; gen->aux.cone.maxAngle = 6.2831855F; } else { gen->aux.cone.minAngle = p1; - gen->aux.cone.maxAngle = (*cmdListArr)[idx]->param2; + gen->aux.cone.maxAngle = ptclref_804D0E5C[bank][idx]->param2; } - gen->aux.cone.height = (*cmdListArr)[idx]->param3; + gen->aux.cone.height = ptclref_804D0E5C[bank][idx]->param3; break; } case 5: { - f0 = (*cmdListArr)[idx]->param1; - gen->aux.rect.x = f0; - gen->aux.rect.xx = f0; - f0 = (*cmdListArr)[idx]->param2; - gen->aux.rect.y = f0; - gen->aux.rect.zx = f0; - f0 = (*cmdListArr)[idx]->param3; - gen->aux.rect.z = f0; - gen->aux.rect.zy = f0; - gen->aux.rect.zz = 0.0F; + gen->aux.rect.xx = gen->aux.rect.x = + ptclref_804D0E5C[bank][idx]->param1; + gen->aux.rect.yy = gen->aux.rect.y = + ptclref_804D0E5C[bank][idx]->param2; + gen->aux.rect.zz = gen->aux.rect.z = + ptclref_804D0E5C[bank][idx]->param3; + gen->aux.rect.zy = 0.0F; + gen->aux.rect.zx = 0.0F; gen->aux.rect.yz = 0.0F; - gen->aux.rect.yy = 0.0F; - gen->aux.rect.xy = 0.0F; - gen->aux.rect.xz = 0.0F; gen->aux.rect.yx = 0.0F; + gen->aux.rect.xz = 0.0F; + gen->aux.rect.xy = 0.0F; gen->aux.rect.flag = 0; - if ((*cmdListArr)[idx]->param1 < 0.0F) { + if (ptclref_804D0E5C[bank][idx]->param1 < 0.0F) { gen->aux.rect.flag |= 1; } - if ((*cmdListArr)[idx]->param2 < 0.0F) { + if (ptclref_804D0E5C[bank][idx]->param2 < 0.0F) { gen->aux.rect.flag |= 2; } - if ((*cmdListArr)[idx]->param3 < 0.0F) { + if (ptclref_804D0E5C[bank][idx]->param3 < 0.0F) { gen->aux.rect.flag |= 4; } break; } case 8: { - f32 vx = gen->vel.x; - f32 vy = gen->vel.y; - f32 vz = gen->vel.z; - f32 vx_sq = vx * vx; - f32 vy_sq = vy * vy; - f32 vz_sq = vz * vz; - mag = vx_sq + vy_sq; - mag += vz_sq; - gen->aux.sphere.speed = sqrtf(mag); - - f0 = gen->vel.x; - f1 = gen->vel.z; - vx_sq = f0 * f0; - vz_sq = f1 * f1; - mag = vx_sq + vz_sq; - mag = sqrtf(mag); + f32 mag; + + gen->aux.sphere.speed = + sqrtf(gen->vel.z * gen->vel.z + + (gen->vel.x * gen->vel.x + gen->vel.y * gen->vel.y)); + + mag = sqrtf(gen->vel.x * gen->vel.x + gen->vel.z * gen->vel.z); if (mag < 1.1754944e-38F) { if (gen->vel.y >= 0.0F) { @@ -1247,13 +1222,12 @@ HSD_Generator* hsd_8039F05C(s32 linkNo, s32 bank, s32 idx) } else { gen->aux.sphere.lonMid = atan2f(gen->vel.z, gen->vel.x); } - gen->aux.sphere.latRange = (*cmdListArr)[idx]->param1; - f1 = gen->aux.sphere.latRange; - if (f1 < 0.0F) { - gen->aux.sphere.latRange = -f1; + gen->aux.sphere.latRange = ptclref_804D0E5C[bank][idx]->param1; + if (gen->aux.sphere.latRange < 0.0F) { + gen->aux.sphere.latRange = -gen->aux.sphere.latRange; gen->aux.sphere.speed = -gen->aux.sphere.speed; } - gen->aux.sphere.lonRange = (*cmdListArr)[idx]->param2; + gen->aux.sphere.lonRange = ptclref_804D0E5C[bank][idx]->param2; break; } default: diff --git a/src/sysdolphin/baselib/particle.c b/src/sysdolphin/baselib/particle.c index a23d9ab9fd..2872c20886 100644 --- a/src/sysdolphin/baselib/particle.c +++ b/src/sysdolphin/baselib/particle.c @@ -41,7 +41,7 @@ static HSD_JObj* hsd_804D08E8[8]; /* 4D0B50 */ HSD_PSTexGroup** psTexGroupArray[65]; /* 4D0C54 */ int psNumCmdList[65]; /* 4D0D58 */ HSD_PSCmdList** psCmdListArray[65]; -/* 4D0E5C */ u32* ptclref_804D0E5C[65]; +/* 4D0E5C */ HSD_PSCmdList** ptclref_804D0E5C[65]; /* 4D0F60 */ struct hsd_804D0F60_t hsd_804D0F60; typedef struct PSNode { @@ -1101,7 +1101,7 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) pc += 2; if (ptclref_804D0E5C[bank] != NULL) { - idx = ptclref_804D0E5C[bank][idx]; + idx = (u32) ptclref_804D0E5C[bank][idx]; } linkNo = pp->linkNo; @@ -1280,7 +1280,7 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) pc += 3; if (ptclref_804D0E5C[pp->bank] != NULL) { - idx = ptclref_804D0E5C[pp->bank][idx]; + idx = (u32) ptclref_804D0E5C[pp->bank][idx]; } gchild = hsd_8039F05C(pp->linkNo, pp->bank, idx); @@ -1412,7 +1412,7 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) idx = baseIdx + (s32) ((f32) randomRange * HSD_Randf()); if (ptclref_804D0E5C[pp->bank] != NULL) { - idx = ptclref_804D0E5C[pp->bank][idx]; + idx = (u32) ptclref_804D0E5C[pp->bank][idx]; } linkNo = pp->linkNo; @@ -1773,7 +1773,7 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) pc += 2; if (ptclref_804D0E5C[bank] != NULL) { - idx = ptclref_804D0E5C[bank][idx]; + idx = (u32) ptclref_804D0E5C[bank][idx]; } linkNo = pp->linkNo; diff --git a/src/sysdolphin/baselib/particle.h b/src/sysdolphin/baselib/particle.h index 8843658390..37a00c7428 100644 --- a/src/sysdolphin/baselib/particle.h +++ b/src/sysdolphin/baselib/particle.h @@ -34,7 +34,7 @@ psGenerateParticle0(HSD_Particle** head, int linkNo, int bank, u32 kind, /* 39D048 */ void hsd_8039D048(void* particle); /* 4D0B50 */ extern HSD_PSTexGroup** psTexGroupArray[65]; /* 4D0D58 */ extern int psNumCmdList[65]; -/* 4D0E5C */ extern u32* ptclref_804D0E5C[65]; +/* 4D0E5C */ extern HSD_PSCmdList** ptclref_804D0E5C[65]; /* 4D78D8 */ extern u16 hsd_804D78D8; /* 4D78DE */ extern u16 hsd_804D78DE; From e72006f10a3752575b3ce2effeccace59331357f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:29:30 -0700 Subject: [PATCH 05/64] Improve ifStatus_802F4EDC to 99.93% MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 99.47% -> 99.93%. The colour update, the digit animation setup, and the stored-translation read come from inline helpers; splitting them out gives the target's call and frame shape. The two branch-local `GXColor`s copied into the shared one are load-bearing — writing the shared local directly costs 16 points. Two rows remain: one callee-saved web (r28 vs r24) and the staged colour's stack slot (0x14 vs 0x40). Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/melee/if/ifstatus.c | 257 +++++++++++++++++++++------------------- 1 file changed, 135 insertions(+), 122 deletions(-) diff --git a/src/melee/if/ifstatus.c b/src/melee/if/ifstatus.c index ba21d33dfe..2eb3393e6e 100644 --- a/src/melee/if/ifstatus.c +++ b/src/melee/if/ifstatus.c @@ -205,6 +205,137 @@ void ifStatus_802F4B84(IfDamageState* state, s32 is_stamina) PAD_STACK(8); } +static inline void ifStatus_UpdateDamageDisplay(IfDamageState* state, + HSD_JObj* jobj) +{ + s16 clamped_damage; + f32 factor; + GXColor color; + HSD_MObj* mobj; + HSD_JObj* digit_jobj; + s32 i; + + if ((state->damage_percent % 1000) / 100 == 0) { + HSD_JObjSetFlagsAll(state->jobjs[Hundreds], JOBJ_HIDDEN); + } else { + HSD_JObjClearFlagsAll(state->jobjs[Hundreds], JOBJ_HIDDEN); + } + + if (state->old_damage != state->damage_percent) { + if (Player_GetMoreFlagsBit2((s8) state->player_slot)) { + GXColor stamina_color; + + if ((clamped_damage = state->damage_percent) > 100) { + clamped_damage = 100; + } else if (clamped_damage < 0) { + clamped_damage = 0; + } + factor = 1.0F - ((f32) clamped_damage / 100.0F); + stamina_color.r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - + ifStatus_804D57A8[0]) + + (f32) ifStatus_804D57A8[0]); + stamina_color.g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - + ifStatus_804D57A8[1]) + + (f32) ifStatus_804D57A8[1]); + stamina_color.b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - + ifStatus_804D57A8[2]) + + (f32) ifStatus_804D57A8[2]); + stamina_color.a = 255; + color = stamina_color; + } else { + GXColor normal_color; + + clamped_damage = state->damage_percent; + if (clamped_damage > 300) { + clamped_damage = 300; + } else if (clamped_damage < 0) { + clamped_damage = 0; + } + factor = (f32) clamped_damage / 300.0F; + normal_color.r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - + ifStatus_804D57A8[0]) + + (f32) ifStatus_804D57A8[0]); + normal_color.g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - + ifStatus_804D57A8[1]) + + (f32) ifStatus_804D57A8[1]); + normal_color.b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - + ifStatus_804D57A8[2]) + + (f32) ifStatus_804D57A8[2]); + normal_color.a = 255; + color = normal_color; + } + + mobj = state->jobjs[Hundreds]->u.dobj->mobj; + mobj->mat->diffuse.r = color.r; + mobj->mat->diffuse.g = color.g; + mobj->mat->diffuse.b = color.b; + + mobj = state->jobjs[Tens]->u.dobj->mobj; + mobj->mat->diffuse.r = color.r; + mobj->mat->diffuse.g = color.g; + mobj->mat->diffuse.b = color.b; + + mobj = state->jobjs[Ones]->u.dobj->mobj; + mobj->mat->diffuse.r = color.r; + mobj->mat->diffuse.g = color.g; + mobj->mat->diffuse.b = color.b; + + mobj = state->jobjs[Percent]->u.dobj->mobj; + mobj->mat->diffuse.r = color.r; + mobj->mat->diffuse.g = color.g; + mobj->mat->diffuse.b = color.b; + } + + if (lb_8000B09C(jobj)) { + for (i = 0; i < 4; i++) { + digit_jobj = state->jobjs[i]; + ASSERT_NOT_NULL(digit_jobj, 993); + state->translation_x[i] = digit_jobj->translate.x; + + digit_jobj = state->jobjs[i]; + ASSERT_NOT_NULL(digit_jobj, 1006); + state->translation_y[i] = digit_jobj->translate.y; + } + } +} + +static inline void ifStatus_InitDamageDigits(IfDamageState* state, + HSD_MatAnimJoint** anim_base) +{ + HSD_JObj* digit_jobj; + u8 digit; + + digit_jobj = state->jobjs[Ones]; + digit = state->damage_percent % 10; + HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) + ->child->child->aobjdesc->fobjdesc); + HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + + digit_jobj = state->jobjs[Tens]; + digit = (state->damage_percent % 100) / 10; + HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) + ->child->child->aobjdesc->fobjdesc); + HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + + digit_jobj = state->jobjs[Hundreds]; + digit = (state->damage_percent % 1000) / 100; + HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) + ->child->child->aobjdesc->fobjdesc); + HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); +} + +static inline f32 ifStatus_GetStoredTranslationX(IfDamageState* state, + s32 index) +{ + return state->translation_x[index]; +} + void ifStatus_802F4EDC(HSD_GObj* gobj) { HudIndex* hud; @@ -212,9 +343,7 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) HSD_JObj* jobj; HSD_JObj* digit_jobj; s32 is_stamina; - GXColor color; HSD_TObj* tobj; - HSD_MObj* mobj; HSD_MatAnimJoint** anim_base; s32 i; u8 digit; @@ -223,8 +352,6 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) f32 tens_offset; f32 hundreds_offset; f32 pos; - s16 clamped_damage; - f32 factor; IfDamageState* ptr; PAD_STACK(64); @@ -283,30 +410,7 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) } mn_8022F3D8(jobj, 1, 0x400); - - digit_jobj = state->jobjs[Ones]; - digit = state->damage_percent % 10; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, - (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) - ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); - - digit_jobj = state->jobjs[Tens]; - digit = (state->damage_percent % 100) / 10; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, - (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) - ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); - - digit_jobj = state->jobjs[Hundreds]; - digit = (state->damage_percent % 1000) / 100; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, - (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) - ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + ifStatus_InitDamageDigits(state, anim_base); } HSD_JObjAnimAll(jobj); @@ -348,98 +452,7 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) HSD_AObjSetRate(post_digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); } - if ((state->damage_percent % 1000) / 100 == 0) { - HSD_JObjSetFlagsAll(state->jobjs[Hundreds], JOBJ_HIDDEN); - } else { - HSD_JObjClearFlagsAll(state->jobjs[Hundreds], JOBJ_HIDDEN); - } - - /* Update colors when damage changes */ - if (state->old_damage != state->damage_percent) { - if (Player_GetMoreFlagsBit2((s8) state->player_slot)) { - GXColor stamina_color; - - /* Stamina mode: 0-100% range */ - clamped_damage = state->damage_percent; - if (clamped_damage > 100) { - clamped_damage = 100; - } else if (clamped_damage < 0) { - clamped_damage = 0; - } - factor = 1.0F - ((f32) clamped_damage / 100.0F); - stamina_color.r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - - ifStatus_804D57A8[0]) + - (f32) ifStatus_804D57A8[0]); - stamina_color.g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - - ifStatus_804D57A8[1]) + - (f32) ifStatus_804D57A8[1]); - stamina_color.b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - - ifStatus_804D57A8[2]) + - (f32) ifStatus_804D57A8[2]); - stamina_color.a = 255; - color = stamina_color; - } else { - GXColor normal_color; - - /* Normal mode: 0-300% range */ - clamped_damage = state->damage_percent; - if (clamped_damage > 300) { - clamped_damage = 300; - } else if (clamped_damage < 0) { - clamped_damage = 0; - } - factor = (f32) clamped_damage / 300.0F; - normal_color.r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - - ifStatus_804D57A8[0]) + - (f32) ifStatus_804D57A8[0]); - normal_color.g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - - ifStatus_804D57A8[1]) + - (f32) ifStatus_804D57A8[1]); - normal_color.b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - - ifStatus_804D57A8[2]) + - (f32) ifStatus_804D57A8[2]); - normal_color.a = 255; - color = normal_color; - } - - /* Apply color to all digit materials */ - mobj = state->jobjs[Hundreds]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; - - mobj = state->jobjs[Tens]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; - - mobj = state->jobjs[Ones]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; - - mobj = state->jobjs[Percent]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; - } - - /* Update JObj positions when animating */ - if (lb_8000B09C(jobj)) { - for (i = 0; i < 4; i++) { - digit_jobj = state->jobjs[i]; - if (digit_jobj == NULL) { - __assert("jobj.h", 993, "jobj"); - } - state->translation_x[i] = digit_jobj->translate.x; - - digit_jobj = state->jobjs[i]; - if (digit_jobj == NULL) { - __assert("jobj.h", 1006, "jobj"); - } - state->translation_y[i] = digit_jobj->translate.y; - } - } + ifStatus_UpdateDamageDisplay(state, jobj); /* Calculate digit spacing offsets based on which digit is "1" */ ones_offset = (state->damage_percent % 10 == 1) ? 0.5069F : 0.0F; @@ -469,8 +482,8 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) hundreds_offset = ((state->damage_percent % 1000) / 100 == 1) ? 0.5069F : 0.0F; digit_jobj = state->jobjs[Hundreds]; - pos = state->translation_x[Hundreds] + - (hundreds_offset + tens_offset + digit_offset); + pos = ifStatus_GetStoredTranslationX(state, Hundreds) + + (tens_offset + hundreds_offset + digit_offset); if (digit_jobj == NULL) { __assert("jobj.h", 932, "jobj"); } From cfa94b531d138b41cc17fcd374fde3f596f2fda4 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:35:25 -0700 Subject: [PATCH 06/64] Improve ftCo_800C2600 to 97.34% 97.23% -> 97.34%. The vertex buffer holds 152 entries, not 151 plus a PAD_STACK, which puts the staging slots at the target's displacements. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/melee/ft/ftafterimage.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/melee/ft/ftafterimage.c b/src/melee/ft/ftafterimage.c index f49cd63408..a679257f27 100644 --- a/src/melee/ft/ftafterimage.c +++ b/src/melee/ft/ftafterimage.c @@ -31,12 +31,10 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) Fighter* fp; itSword_UnkBytes* params; f32 cumDist[3]; - AfterimageVtx vtx_buf[151]; + AfterimageVtx vtx_buf[152]; f32 d2; s32 numSubdiv; - PAD_STACK(0x10); - if (arg1 != 2) { return; } @@ -226,10 +224,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) vp->b = params->xC; vp->a = alpha; - { - f32 x = curEntry->xC.x * outerScale; - (vp + 1)->x = x + curEntry->x0.x; - } + (vp + 1)->x = curEntry->xC.x * outerScale + curEntry->x0.x; (vp + 1)->y = curEntry->xC.y * outerScale + curEntry->x0.y; (vp + 1)->z = curEntry->xC.z * outerScale + curEntry->x0.z; (vp + 1)->r = params->xE; @@ -263,9 +258,9 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) f32 frac; s32 j; f32 cumAngle = 0.0f; - f32 interpInner2, interpOuter2; f32 basePosX, basePosY, basePosZ; f32 stepPosX, stepPosY, stepPosZ; + f32 interpInner2, interpOuter2; s32 alphaStep; tempDir = curEntry->xC; From 9ab86ba6229a72579321c59cde7d2330376adc44 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:38:51 -0700 Subject: [PATCH 07/64] Improve ifStock_802F98E8 to 98.78% 95.39% -> 98.78%. The per-player user data is reached by walking a `struct IfStockData*` cursor the way ifStock_802F7EFC already does in this file, and the state struct is re-mentioned in full at each use rather than staged in `r26`. The embedded `+=` in the first store is load-bearing: splitting it into a typed pointer plus a store costs 3 points, and a typed `ifStock_804A1378_x204*` costs 2.9. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/melee/if/ifstock.c | 83 ++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 48e35fbb85..fdbe5fd391 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -566,31 +566,34 @@ HSD_GObj* ifStock_802F96D0(int a, int b, float x, float y) return gobj; } +static inline HSD_JObj* ifStock_802F98E8_get_x3C(unsigned char player) +{ + return ifStock_804A1378.player[player].x3C; +} + void ifStock_802F98E8(unsigned char player, int b) { struct ifStock_804A1378* stock = &ifStock_804A1378; - HSD_GObj* gobj; HSD_JObj* jobj; - struct ifStock_804A1378_x204* user_data; - struct ifStock_804A1378_per_player* r26; + unsigned char* user_data; int i; - unsigned char* data; + HSD_GObj* gobj; lbl_8046B6A0_t* ae44; - PAD_STACK(16); if (stock->x0 != NULL) { - user_data = &stock->x204[player]; - user_data->x0[0] = player; - user_data->x0[1] = b; - user_data->x0[2] = 1; - r26 = &stock->player[player]; - if (r26->x0 != NULL) { - HSD_GObjPLink_80390228(r26->x0); + user_data = ((struct IfStockData*) stock)[player].x0; + *(user_data += sizeof(struct IfStockDataOffset)) = player; + stock->x204[player].x0[1] = b; + stock->x204[player].x0[2] = 1; + if (stock->player[player].x0 != NULL) { + HSD_GObjPLink_80390228(stock->player[player].x0); } gobj = GObj_Create(14, 15, 0); gobj->user_data = user_data; if (gobj != NULL) { jobj = HSD_JObjLoadJoint((*stock->x0)->joint); if (jobj != NULL) { + unsigned char* data; + HSD_GObjObject_80390A70(gobj, HSD_GObj_JObjKind, jobj); GObj_SetupGXLink(gobj, fn_802F94E0, 11, 0); gm_8016895C(jobj, *stock->x0, 0); @@ -600,7 +603,7 @@ void ifStock_802F98E8(unsigned char player, int b) lb_80011E24(jobj, ifStock_804A1378.player[player].x4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1); - r26->x0 = gobj; + stock->player[player].x0 = gobj; ifStock_804A1378.player[player].coins = Player_GetCoins(player); ifStock_804A1378.player[player].stocks = @@ -608,39 +611,46 @@ void ifStock_802F98E8(unsigned char player, int b) if (ifStock_804A1378.player[player].stocks < 0) { ifStock_804A1378.player[player].stocks = 1; } - data = user_data->x0; + data = user_data; switch ((unsigned char) b) { case 0: HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x24, JOBJ_HIDDEN); - if (ifStock_804A1378.player[player].stocks <= 5) { - HSD_JObjSetFlagsAll( - ifStock_804A1378.player[player].x3C, JOBJ_HIDDEN); - for (i = 0; i < 7; i++, data++) { - jobj = ifStock_804A1378.player[player].x4[i + 1]; - if (i < ifStock_804A1378.player[player].stocks || - i >= 5) - { - data[5] = 0; - if (i >= 5) { + { + struct ifStock_804A1378_per_player* players = + stock->player; + if (players[player].stocks <= 5) { + HSD_JObjSetFlagsAll( + ifStock_804A1378.player[player].x3C, + JOBJ_HIDDEN); + for (i = 0; i < 7; i++, data++) { + jobj = + ifStock_804A1378.player[player].x4[i + 1]; + if (i < ifStock_804A1378.player[player] + .stocks || + i >= 5) + { + data[5] = 0; + if (i >= 5) { + HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + } + } else { + data[5] = 10; HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); } - } else { - data[5] = 10; - HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + HSD_JObjReqAnimAll(jobj, data[5]); + HSD_TObjReqAnimAll(jobj->u.dobj->mobj->tobj, + gm_80168BF8(player)); + HSD_AObjSetRate(jobj->u.dobj->mobj->tobj->aobj, + 0.0f); } - HSD_JObjReqAnimAll(jobj, data[5]); - HSD_TObjReqAnimAll(jobj->u.dobj->mobj->tobj, - gm_80168BF8(player)); - HSD_AObjSetRate(jobj->u.dobj->mobj->tobj->aobj, - 0.0f); } } break; case 1: HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x24, JOBJ_HIDDEN); - HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x3C, + HSD_JObjSetFlagsAll(ifStock_802F98E8_get_x3C(player), JOBJ_HIDDEN); for (i = 0; i < 7; i++, data++) { jobj = ifStock_804A1378.player[player].x4[i + 1]; @@ -700,10 +710,12 @@ void ifStock_802F98E8(unsigned char player, int b) ae44 = gm_16AE_GetUnkData_1(); if (ae44->FighterMatchInfo[player].x4_b1) { GXColor c = { 0x08, 0x08, 0x08, 0x80 }; - ifStock_802FB4EC(player, &c); + GXColor* color = &c; + ifStock_802FB4EC(player, color); } else if (ae44->FighterMatchInfo[player].x4_b0) { GXColor c = { 0x3C, 0x3C, 0x46, 0x80 }; - ifStock_802FB4EC(player, &c); + GXColor* color = &c; + ifStock_802FB4EC(player, color); } fn_802F9410(gobj); // inlined } else { @@ -711,6 +723,7 @@ void ifStock_802F98E8(unsigned char player, int b) } } } + PAD_STACK(16); } static inline HSD_GObj* ifStock_802F9F48_inline(int arg) From abdf6541f1a2d65b18cbcd0e1233029b4016a99d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:39:59 -0700 Subject: [PATCH 08/64] Improve hsd_8039DAD4 to 99.51% 98.38% -> 99.51%. The velocity magnitude is `sqrtf`, not a hand-expanded Newton-Raphson; the JObj matrix is `gen->jobj->mtx` rather than a raw +0x44 byte offset; and the matrix-column normalise block stages through the same local as the velocity output, which is what the target's frame shows. Remaining rows are stack-slot ordering for three staging floats. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/sysdolphin/baselib/generator.c | 186 +++++++++++++---------------- 1 file changed, 86 insertions(+), 100 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 5f11612d20..2db9f08d84 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -357,20 +357,20 @@ HSD_Generator* hsd_8039D9C8(void) return gen; } -// @TODO: Currently 97.23% match - register allocation, shape/velocity -// switch case logic, Newton-Raphson sqrt inlining, trig matrix layout +/// @todo Only differs by register allocation. f32 hsd_8039DAD4(HSD_Generator* gen) { - f32 radius; - Vec3 vel_out; Vec3 vel_copy; + f32 tmp; Vec3 emit_pos; - Vec3 cross1; Vec3 tmpvec; + Vec3 vec; Mtx rot_mtx; Mtx jobj_mtx; Vec3 look_dir; Vec3 cam_up; + Vec3 cross1; + Vec3 vel_norm; Mtx trig_mtx; f64 eps; f32 vel_mag_sq; @@ -382,9 +382,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) f32 cur_angle; f32 cone_angle; f32 elevation; - f32 tmp; + f32 radius; f32 angle3; - PAD_STACK(8); angle1 = angle3 = 0.0F; if (gen->count < 1.0F) { @@ -399,16 +398,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) vel_copy.z = gen->vel.z; /* Compute velocity magnitude */ - vel_mag_sq = vel_copy.z * vel_copy.z; - vel_mag_sq += vel_copy.x * vel_copy.x + vel_copy.y * vel_copy.y; - if (vel_mag_sq > 0.0F) { - f64 e = __frsqrte(vel_mag_sq); - e = 0.5 * e * -(vel_mag_sq * (e * e) - 3.0); - e = 0.5 * e * -(vel_mag_sq * (e * e) - 3.0); - e = 0.5 * e * -(vel_mag_sq * (e * e) - 3.0); - tmp = (f32) (vel_mag_sq * e); - vel_mag_sq = tmp; - } + vel_mag_sq = sqrtf(vel_copy.z * vel_copy.z + + (vel_copy.x * vel_copy.x + vel_copy.y * vel_copy.y)); /* Initialize rotation matrix */ PSMTXIdentity(rot_mtx); @@ -418,32 +409,32 @@ f32 hsd_8039DAD4(HSD_Generator* gen) if ((gen->type & 0x100) && gen->jobj != NULL && (gen->type & 0x400) && !(gen->kind & 0x30000)) { - PSMTXCopy((void*) ((u8*) gen->jobj + 0x44), jobj_mtx); + PSMTXCopy(gen->jobj->mtx, jobj_mtx); /* Extract and normalize each column of the 3x3 rotation */ - tmpvec.x = jobj_mtx[0][0]; - tmpvec.y = jobj_mtx[1][0]; - tmpvec.z = jobj_mtx[2][0]; - PSVECNormalize(&tmpvec, &tmpvec); - rot_mtx[0][0] = tmpvec.x; - rot_mtx[1][0] = tmpvec.y; - rot_mtx[2][0] = tmpvec.z; - - tmpvec.x = jobj_mtx[0][1]; - tmpvec.y = jobj_mtx[1][1]; - tmpvec.z = jobj_mtx[2][1]; - PSVECNormalize(&tmpvec, &tmpvec); - rot_mtx[0][1] = tmpvec.x; - rot_mtx[1][1] = tmpvec.y; - rot_mtx[2][1] = tmpvec.z; - - tmpvec.x = jobj_mtx[0][2]; - tmpvec.y = jobj_mtx[1][2]; - tmpvec.z = jobj_mtx[2][2]; - PSVECNormalize(&tmpvec, &tmpvec); - rot_mtx[0][2] = tmpvec.x; - rot_mtx[1][2] = tmpvec.y; - rot_mtx[2][2] = tmpvec.z; + vec.x = jobj_mtx[0][0]; + vec.y = jobj_mtx[1][0]; + vec.z = jobj_mtx[2][0]; + PSVECNormalize(&vec, &vec); + rot_mtx[0][0] = vec.x; + rot_mtx[1][0] = vec.y; + rot_mtx[2][0] = vec.z; + + vec.x = jobj_mtx[0][1]; + vec.y = jobj_mtx[1][1]; + vec.z = jobj_mtx[2][1]; + PSVECNormalize(&vec, &vec); + rot_mtx[0][1] = vec.x; + rot_mtx[1][1] = vec.y; + rot_mtx[2][1] = vec.z; + + vec.x = jobj_mtx[0][2]; + vec.y = jobj_mtx[1][2]; + vec.z = jobj_mtx[2][2]; + PSVECNormalize(&vec, &vec); + rot_mtx[0][2] = vec.x; + rot_mtx[1][2] = vec.y; + rot_mtx[2][2] = vec.z; rot_mtx[0][3] = 0.0F; rot_mtx[1][3] = 0.0F; @@ -475,7 +466,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) /* Velocity-based rotation */ if ((gen->type & 0xF) != 1 && vel_mag_sq > 0.0F) { - Vec3 vel_norm; vel_norm.x = gen->vel.x; vel_norm.y = gen->vel.y; vel_norm.z = gen->vel.z; @@ -546,8 +536,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) angle1 = atan2f(rot_mtx[1][2], rot_mtx[2][2]); } { - f32 comb = rot_mtx[2][2] * cosf(angle1); - comb += rot_mtx[1][2] * sinf(angle1); + f32 first = rot_mtx[2][2] * cosf(angle1); + f32 comb = first + rot_mtx[1][2] * sinf(angle1); tmp = comb; *(s32*) &tmp &= 0x7FFFFFFF; if (tmp < 1.1754944e-38F) { @@ -605,7 +595,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) /* Compute radius */ if (gen->radius < 0.0F) { sin_az = -gen->radius; - radius = 0.0F; + radius = 1.0F; } else { radius = HSD_Randf(); if ((gen->type & 0xF) == 3 || (gen->type & 0xF) == 4) { @@ -618,7 +608,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) switch (gen->type & 0xF) { case 6: if (gen->angle < 0.0F) { - emit_pos.z = sin_az; cur_angle += angle_step; tmp = sin_az; *(s32*) &tmp &= 0x7FFFFFFF; @@ -630,7 +619,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } } else { f64 cone_angle_d = - M_PI - atan2f(gen->aux.cone.height, sin_az) - + M_PI_2 - atan2f(gen->aux.cone.height, sin_az) - gen->angle; cone_angle = (f32) cone_angle_d; } @@ -645,7 +634,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) cone_angle = radius * gen->angle; cur_angle = range * rnd + cur_angle; } - emit_pos.z = sin_az; tmp = sin_az; *(s32*) &tmp &= 0x7FFFFFFF; if (tmp < 1.1754944e-38F) { @@ -657,22 +645,25 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } else { f64 cone_angle_d = gen->angle + - (M_PI - atan2f(gen->aux.cone.height, sin_az)); + (M_PI_2 - atan2f(gen->aux.cone.height, sin_az)); cone_angle = (f32) cone_angle_d; } } break; case 7: if (gen->angle < 0.0F) { - cone_angle = (f32) (M_PI - gen->angle); + cone_angle = (f32) (M_PI_2 - gen->angle); cur_angle += angle_step; } else { - cur_angle = gen->aux.disc.minAngle; + { + f32 min_angle = gen->aux.disc.minAngle; + cur_angle = min_angle; + } { f32 rnd = HSD_Randf(); f32 range = gen->aux.disc.maxAngle - cur_angle; cur_angle = range * rnd + cur_angle; - cone_angle = (f32) (M_PI + gen->angle); + cone_angle = (f32) (M_PI_2 + gen->angle); } } break; @@ -712,16 +703,16 @@ f32 hsd_8039DAD4(HSD_Generator* gen) /* Compute velocity direction from cone angle */ { f32 sin_ca = vel_mag_sq * sinf(cone_angle); - vel_out.x = sin_ca * cosf(cur_angle); - vel_out.y = sin_ca * sinf(cur_angle); - vel_out.z = vel_mag_sq * cosf(cone_angle); + vec.x = sin_ca * cosf(cur_angle); + vec.y = sin_ca * sinf(cur_angle); + vec.z = vel_mag_sq * cosf(cone_angle); } /* Shape 3: scale velocity by radius factor */ if ((gen->type & 0xF) == 3) { - vel_out.x *= radius; - vel_out.y *= radius; - vel_out.z *= radius; + vec.x *= radius; + vec.y *= radius; + vec.z *= radius; } /* Apply rotation matrix to emission position */ @@ -731,14 +722,13 @@ f32 hsd_8039DAD4(HSD_Generator* gen) emit_pos.z += gen->pos.z; /* Apply rotation matrix to velocity */ - PSMTXMultVec(rot_mtx, &vel_out, &vel_out); + PSMTXMultVec(rot_mtx, &vec, &vec); /* Spawn particle */ hsd_80398F0C(gen->linkNo, gen->bank, gen->kind, gen->texGroup, (s32) gen->cmdList, gen->life, 0, (s32) gen, - emit_pos.x, emit_pos.y, emit_pos.z, vel_out.x, - vel_out.y, vel_out.z, gen->size, gen->grav, - gen->fric); + emit_pos.x, emit_pos.y, emit_pos.z, vec.x, vec.y, + vec.z, gen->size, gen->grav, gen->fric); break; } @@ -754,20 +744,19 @@ f32 hsd_8039DAD4(HSD_Generator* gen) emit_pos.y += gen->pos.y; emit_pos.z += gen->pos.z; - PSMTXMultVec(rot_mtx, &vel_copy, &vel_out); + PSMTXMultVec(rot_mtx, &vel_copy, &vec); hsd_80398F0C(gen->linkNo, gen->bank, gen->kind, gen->texGroup, (s32) gen->cmdList, gen->life, 0, (s32) gen, - emit_pos.x, emit_pos.y, emit_pos.z, vel_out.x, - vel_out.y, vel_out.z, gen->size, gen->grav, - gen->fric); + emit_pos.x, emit_pos.y, emit_pos.z, vec.x, vec.y, + vec.z, gen->size, gen->grav, gen->fric); break; } case 2: /* tornado */ { if (gen->radius < 0.0F) { - sin_az = 0.0F; + sin_az = 1.0F; } else { sin_az = HSD_Randf(); } @@ -787,7 +776,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 5: /* rect */ { - Vec3 vel_temp; emit_pos.x = HSD_Randf(); emit_pos.y = HSD_Randf(); emit_pos.z = HSD_Randf(); @@ -873,17 +861,17 @@ f32 hsd_8039DAD4(HSD_Generator* gen) emit_pos.z -= 0.5F; /* Multiply by rect's 3x3 matrix */ - vel_temp.x = gen->aux.rect.yx * emit_pos.y + - gen->aux.rect.xx * emit_pos.x + - gen->aux.rect.zx * emit_pos.z; - vel_temp.y = gen->aux.rect.yy * emit_pos.y + - gen->aux.rect.xy * emit_pos.x + - gen->aux.rect.zy * emit_pos.z; - vel_temp.z = gen->aux.rect.yz * emit_pos.y + - gen->aux.rect.xz * emit_pos.x + - gen->aux.rect.zz * emit_pos.z; - - PSMTXMultVec(rot_mtx, &vel_temp, &emit_pos); + tmpvec.x = gen->aux.rect.yx * emit_pos.y + + gen->aux.rect.xx * emit_pos.x + + gen->aux.rect.zx * emit_pos.z; + tmpvec.y = gen->aux.rect.yy * emit_pos.y + + gen->aux.rect.xy * emit_pos.x + + gen->aux.rect.zy * emit_pos.z; + tmpvec.z = gen->aux.rect.yz * emit_pos.y + + gen->aux.rect.xz * emit_pos.x + + gen->aux.rect.zz * emit_pos.z; + + PSMTXMultVec(rot_mtx, &tmpvec, &emit_pos); emit_pos.x += gen->pos.x; emit_pos.y += gen->pos.y; emit_pos.z += gen->pos.z; @@ -896,19 +884,18 @@ f32 hsd_8039DAD4(HSD_Generator* gen) mag = sqrtf(mag); { f32 scale = vel_mag_sq / mag; - vel_out.x = gen->aux.rect.zx * scale; - vel_out.y = gen->aux.rect.zy * scale; - vel_out.z = gen->aux.rect.zz * scale; + vec.x = gen->aux.rect.zx * scale; + vec.y = gen->aux.rect.zy * scale; + vec.z = gen->aux.rect.zz * scale; } } - PSMTXMultVec(rot_mtx, &vel_out, &vel_out); + PSMTXMultVec(rot_mtx, &vec, &vec); hsd_80398F0C(gen->linkNo, gen->bank, gen->kind, gen->texGroup, (s32) gen->cmdList, gen->life, 0, (s32) gen, - emit_pos.x, emit_pos.y, emit_pos.z, vel_out.x, - vel_out.y, vel_out.z, gen->size, gen->grav, - gen->fric); + emit_pos.x, emit_pos.y, emit_pos.z, vec.x, vec.y, + vec.z, gen->size, gen->grav, gen->fric); break; } @@ -917,7 +904,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) f32 r0 = gen->aux.cone.height; if (r0 == 0.0F || __fabs(r0 - M_PI) < eps) { f32 rnd = sqrtf(HSD_Randf()); - radius = (f32) (M_PI * rnd); + radius = (f32) (M_PI_2 * rnd); { f32 rnd2 = HSD_Randf(); if (rnd2 < 0.5F) { @@ -947,26 +934,26 @@ f32 hsd_8039DAD4(HSD_Generator* gen) f32 sin_r; cos_r = cosf(cone_angle); cos_az = sinf(radius); - vel_out.x = cos_az * cos_r; + vec.x = cos_az * cos_r; sin_el = sinf(cone_angle); sin_r = sinf(radius); - vel_out.y = sin_el * sin_r; - vel_out.z = cosf(radius); + vec.y = sin_r * sin_el; + vec.z = cosf(radius); } - PSMTXMultVec(rot_mtx, &vel_out, &emit_pos); + PSMTXMultVec(rot_mtx, &vec, &emit_pos); /* Scale position by aux.rect.x */ - vel_out.x = emit_pos.x * gen->aux.rect.x; - vel_out.y = emit_pos.y * gen->aux.rect.x; - vel_out.z = emit_pos.z * gen->aux.rect.x; + vec.x = emit_pos.x * gen->aux.rect.x; + vec.y = emit_pos.y * gen->aux.rect.x; + vec.z = emit_pos.z * gen->aux.rect.x; /* Scale velocity if needed */ if (gen->radius >= 0.0F && gen->aux.rect.x < 0.0F) { f32 scale = sin_az / gen->radius; - vel_out.x *= scale; - vel_out.y *= scale; - vel_out.z *= scale; + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; } emit_pos.x = sin_az * emit_pos.x + gen->pos.x; @@ -975,9 +962,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) hsd_80398F0C(gen->linkNo, gen->bank, gen->kind, gen->texGroup, (s32) gen->cmdList, gen->life, 0, (s32) gen, - emit_pos.x, emit_pos.y, emit_pos.z, vel_out.x, - vel_out.y, vel_out.z, gen->size, gen->grav, - gen->fric); + emit_pos.x, emit_pos.y, emit_pos.z, vec.x, vec.y, + vec.z, gen->size, gen->grav, gen->fric); break; } From 3a8a3df246476f9fede98b3eb2f66b2a721f3f52 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 13:41:28 -0700 Subject: [PATCH 09/64] Improve lbColl_80006E58 to 97.77% 97.29% -> 97.77%, mostly by reordering the segment-dot and length-squared accumulations to the target's operand order and by moving three float decls. Also drops a hack: the 1.0 used across the parameter-clamp branches was being read out of the global `lbColl_804D7A08` to keep it in a callee-saved register. A plain `1.0F` gives the same code, so the global read and the comment explaining it are gone. Source taken from doldecomp/melee#3223. Co-authored-by: Ford Lascari --- src/melee/lb/lbcollision.c | 129 ++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 66 deletions(-) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index 4c5afbef78..cd2115eb50 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1042,9 +1042,9 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float closest_dist_sq; float local_delta_y; float start_delta_x; - float start_delta_y; + float hurt_param_from_hit_start; Mtx inv_hurt_mtx; - float hurt_delta_x; + float hurt_delta_z; float hit_start_max_x; float hit_end_min_x; float hit_start_min_x; @@ -1076,7 +1076,7 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float hit_param; float local_dist; float hurt_param; - float hurt_param_from_hit_start; + float start_delta_y; float hurt_param_from_hit_end; float closest_dist; float hurt_end_z; @@ -1090,9 +1090,9 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, s32 is_hit_segment_degenerate; s32 is_parallel; s32 is_zero_distance; - float hurt_delta_z; + float hurt_delta_x; float hurt_delta_y; - PAD_STACK(52); + PAD_STACK(40); // Fast reject when the expanded hit segment AABB misses both hurt // endpoints. @@ -1197,57 +1197,54 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hurt_end_z = hurt_end->z; (void) hurt_end_z; start_delta_x = hit_start_copy.x - hurt_start_copy.x; - segment_dot = (hit_delta.x * hurt_delta_x) + segment_dot; hurt_delta_z = hurt_end_z - hurt_start_copy.z; - /* Cache 1.0 constant in a callee-save to avoid reloading it across the - * several `hit_param = 1.0` / `hurt_param = 1.0` branches below. The - * variable name is a borrow from the unused-after-broadphase-rejection - * slot. */ - hit_start_min_z = lbColl_804D7A08; + segment_dot = (hit_delta.x * hurt_delta_x) + segment_dot; + hit_start_min_z = 1.0F; hurt_len_sq = (hurt_delta_x * hurt_delta_x) + hurt_len_sq; segment_dot = (hit_delta.z * hurt_delta_z) + segment_dot; hurt_len_sq = (hurt_delta_z * hurt_delta_z) + hurt_len_sq; - hit_start_mid_z = hit_delta.z * hit_delta.z; + { + float hit_delta_z_sq = hit_delta.z * hit_delta.z; + hit_start_mid_z = hit_delta_z_sq; + } start_delta_z = hit_start_copy.z - hurt_start_copy.z; - hit_len_sq = hit_start_mid_z + (hit_start_mid_x + hit_start_mid_y); + hit_len_sq = hit_start_mid_z + (hit_start_mid_y + hit_start_mid_x); hit_start_dot = hit_delta.y * start_delta_y; { float hit_start_dot_x = hit_delta.x * start_delta_x; hit_start_dot = hit_start_dot_x + hit_start_dot; } hurt_start_dot = - (hurt_delta_y * start_delta_y) + (hurt_delta_x * start_delta_x); - hit_start_dot = (hit_delta.z * start_delta_z) + hit_start_dot; + (hurt_delta_x * start_delta_x) + (hurt_delta_y * start_delta_y); hurt_start_dot = (hurt_delta_z * start_delta_z) + hurt_start_dot; - closest_denom = (hit_len_sq * hurt_len_sq) - (segment_dot * segment_dot); - if ((hurt_len_sq < lbColl_804D79F0) && (hurt_len_sq > lbColl_804D79F4)) { + hit_start_dot = (hit_delta.z * start_delta_z) + hit_start_dot; + closest_denom = (hurt_len_sq * hit_len_sq) - (segment_dot * segment_dot); + if ((hurt_len_sq < 1e-5F) && (hurt_len_sq > -1e-5F)) { is_hurt_segment_degenerate = 1; } else { is_hurt_segment_degenerate = 0; } if (is_hurt_segment_degenerate != 0) { - if ((hit_len_sq < lbColl_804D79F0) && (hit_len_sq > lbColl_804D79F4)) { + if ((hit_len_sq < 1e-5F) && (hit_len_sq > -1e-5F)) { is_hit_segment_degenerate = 1; } else { is_hit_segment_degenerate = 0; } if (is_hit_segment_degenerate != 0) { - hit_param = lbColl_804D79F8; + hit_param = 0.0F; hurt_param = hit_param; } else { - hurt_param = lbColl_804D79F8; + hurt_param = 0.0F; projected_hit_param = -hit_start_dot / hit_len_sq; hit_param = projected_hit_param; - if (projected_hit_param > lbColl_804D7A00) { + if (projected_hit_param > 1.0) { hit_param = hit_start_min_z; - } else if (hit_param < lbColl_804D7A10) { + } else if (hit_param < 0.0) { hit_param = hurt_param; } } } else { - if ((closest_denom < lbColl_804D79F0) && - (closest_denom > lbColl_804D79F4)) - { + if ((closest_denom < 1e-5F) && (closest_denom > -1e-5F)) { is_parallel = 1; } else { is_parallel = 0; @@ -1255,13 +1252,13 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, if (is_parallel != 0) { // For parallel axes, project the hit endpoint nearer the hurt // midpoint. - hurt_mid_y = (float) ((lbColl_804D7A18 * (f64) hurt_delta_y) + - (f64) hurt_start_copy.y); - hurt_mid_x = (float) ((lbColl_804D7A18 * (f64) hurt_delta_x) + - (f64) hurt_start_copy.x); + hurt_mid_y = + (float) ((0.5 * (f64) hurt_delta_y) + (f64) hurt_start_copy.y); + hurt_mid_x = + (float) ((0.5 * (f64) hurt_delta_x) + (f64) hurt_start_copy.x); hit_start_mid_y = hit_start_copy.y - hurt_mid_y; - hurt_mid_z = (float) ((lbColl_804D7A18 * (f64) hurt_delta_z) + - (f64) hurt_start_copy.z); + hurt_mid_z = + (float) ((0.5 * (f64) hurt_delta_z) + (f64) hurt_start_copy.z); hit_end_mid_y = hit_end->y - hurt_mid_y; hit_start_mid_x = hit_start_copy.x - hurt_mid_x; hit_end_mid_x = hit_end->x - hurt_mid_x; @@ -1277,9 +1274,8 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, Vec3 a2; Vec3 d1; Vec3 c3; - u8 gap_pad[4]; c3 = *hurt_start; - hit_param = lbColl_804D79F8; + hit_param = 0.0F; d1.x = hurt_end_x - hurt_start->x; d1.y = hurt_end_y - hurt_start->y; d1.z = hurt_end_z - hurt_start->z; @@ -1289,14 +1285,13 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, a2 = *hit_start; dot = (d1.z * (c3.z - a2.z)) + ((d1.x * (c3.x - a2.x)) + (d1.y * (c3.y - a2.y))); - hit_end_mid_x = d1.x * d1.x; hurt_param_from_hit_start = -dot / - ((d1.z * d1.z) + (hit_end_mid_x + (d1.y * d1.y))); + ((d1.z * d1.z) + ((d1.x * d1.x) + (d1.y * d1.y))); } - if (hurt_param_from_hit_start > lbColl_804D7A00) { + if (hurt_param_from_hit_start > 1.0) { hurt_param_from_hit_start = hit_start_min_z; - } else if (hurt_param_from_hit_start < lbColl_804D7A10) { + } else if (hurt_param_from_hit_start < 0.0) { hurt_param_from_hit_start = hit_param; } hurt_param = hurt_param_from_hit_start; @@ -1318,10 +1313,10 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, -dot / ((d1.z * d1.z) + ((d1.x * d1.x) + (d1.y * d1.y))); } - if (hurt_param_from_hit_end > lbColl_804D7A00) { + if (hurt_param_from_hit_end > 1.0) { hurt_param_from_hit_end = hit_param; - } else if (hurt_param_from_hit_end < lbColl_804D7A10) { - hurt_param_from_hit_end = lbColl_804D79F8; + } else if (hurt_param_from_hit_end < 0.0) { + hurt_param_from_hit_end = 0.0F; } hurt_param = hurt_param_from_hit_end; } @@ -1330,13 +1325,11 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, (hit_param_candidate = ((segment_dot * hurt_start_dot) - (hurt_len_sq * hit_start_dot)) / closest_denom); - hurt_param = ((hit_len_sq * hurt_start_dot) - + hurt_param = ((hurt_start_dot * hit_len_sq) - (segment_dot * hit_start_dot)) / closest_denom; - if ((hit_param_candidate > lbColl_804D7A00) || - (hit_param < lbColl_804D7A10) || - (hurt_param > lbColl_804D7A00) || - (hurt_param < lbColl_804D7A10)) + if ((hit_param_candidate > 1.0) || (hit_param < 0.0) || + (hurt_param > 1.0) || (hurt_param < 0.0)) { float hit_endpoint_dist_sq; float hit_endpoint_param; @@ -1345,8 +1338,8 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, // If the unconstrained solution leaves either segment, compare // the nearest endpoint projection from each axis. - if (hit_param < lbColl_804D7A10) { - hit_endpoint_param = lbColl_804D79F8; + if (hit_param < 0.0) { + hit_endpoint_param = 0.0F; hit_endpoint_dist_sq = lbColl_80005EBC(hurt_start, hurt_end, hit_start, &candidate_hurt_param); @@ -1355,8 +1348,8 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hit_endpoint_dist_sq = lbColl_80005EBC( hurt_start, hurt_end, hit_end, &candidate_hurt_param); } - if (hurt_param < lbColl_804D7A10) { - hurt_endpoint_param = lbColl_804D79F8; + if (hurt_param < 0.0) { + hurt_endpoint_param = 0.0F; hurt_endpoint_dist_sq = lbColl_80005EBC( hit_start, hit_end, hurt_start, &candidate_hit_param); } else { @@ -1386,29 +1379,29 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, closest_dist_sq = (closest_delta_z * closest_delta_z) + ((closest_delta_y * closest_delta_y) + (closest_delta_x * closest_delta_x)); - if (closest_dist_sq > lbColl_804D79F8) { + if (closest_dist_sq > 0.0F) { volatile float sp38; closest_rsqrt_estimate = __frsqrte(closest_dist_sq); closest_rsqrt_step1 = - lbColl_804D7A18 * closest_rsqrt_estimate * + 0.5 * closest_rsqrt_estimate * -(((f64) closest_dist_sq * (closest_rsqrt_estimate * closest_rsqrt_estimate)) - - lbColl_804D7A20); - closest_rsqrt_step2 = lbColl_804D7A18 * closest_rsqrt_step1 * + 3.0); + closest_rsqrt_step2 = 0.5 * closest_rsqrt_step1 * -(((f64) closest_dist_sq * (closest_rsqrt_step1 * closest_rsqrt_step1)) - - lbColl_804D7A20); + 3.0); sp38 = (float) ((f64) closest_dist_sq * - (lbColl_804D7A18 * closest_rsqrt_step2 * + (0.5 * closest_rsqrt_step2 * -(((f64) closest_dist_sq * (closest_rsqrt_step2 * closest_rsqrt_step2)) - - lbColl_804D7A20))); + 3.0))); closest_dist = sp38; } else { closest_dist = closest_dist_sq; } - if ((closest_dist < lbColl_804D79F0) && (closest_dist > lbColl_804D79F4)) { + if ((closest_dist < 1e-5F) && (closest_dist > -1e-5F)) { is_zero_distance = 1; } else { is_zero_distance = 0; @@ -1429,23 +1422,27 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, local_dist_sq = (local_delta_z * local_delta_z) + ((local_delta_x * local_delta_x) + (local_delta_y * local_delta_y)); - if (local_dist_sq > lbColl_804D79F8) { + if (local_dist_sq > 0.0F) { volatile float sp34; local_rsqrt_estimate = __frsqrte(local_dist_sq); - local_rsqrt_step1 = lbColl_804D7A18 * local_rsqrt_estimate * - -(((f64) local_dist_sq * - (local_rsqrt_estimate * local_rsqrt_estimate)) - - lbColl_804D7A20); + { + f64 local_rsqrt_first_step = + 0.5 * local_rsqrt_estimate * + -(((f64) local_dist_sq * + (local_rsqrt_estimate * local_rsqrt_estimate)) - + 3.0); + local_rsqrt_step1 = local_rsqrt_first_step; + } local_rsqrt_step2 = - lbColl_804D7A18 * local_rsqrt_step1 * + 0.5 * local_rsqrt_step1 * -(((f64) local_dist_sq * (local_rsqrt_step1 * local_rsqrt_step1)) - - lbColl_804D7A20); + 3.0); sp34 = (float) ((f64) local_dist_sq * - (lbColl_804D7A18 * local_rsqrt_step2 * + (0.5 * local_rsqrt_step2 * -(((f64) local_dist_sq * (local_rsqrt_step2 * local_rsqrt_step2)) - - lbColl_804D7A20))); + 3.0))); local_dist = sp34; } else { local_dist = local_dist_sq; From 35ba761928058fff6258b88abb8bfbe8866d7992 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 14:03:20 -0700 Subject: [PATCH 10/64] Mark ftCo_0D95 and tyfigupon Matching Both objects already matched byte-for-byte in code and data but were still declared Linkable. Includes the `ninja apply` symbols.txt canonicalization. Linked 76.53% -> 76.95% (1058 -> 1060 files). `grgreens` is in the same state per objdiff but changes the DOL when flipped, so it stays Linkable. --- config/GALE01/symbols.txt | 215 +++++++++++++++++++------------------- configure.py | 4 +- 2 files changed, 110 insertions(+), 109 deletions(-) diff --git a/config/GALE01/symbols.txt b/config/GALE01/symbols.txt index 6052b2a303..2d6ddff651 100644 --- a/config/GALE01/symbols.txt +++ b/config/GALE01/symbols.txt @@ -20162,7 +20162,7 @@ _Toy_803B8904 = .rodata:0x803B8904; // type:object size:0xC scope:local data:4by _Toy_803B8910 = .rodata:0x803B8910; // type:object size:0x48 scope:local data:4byte _tyFigupon_803B8958 = .rodata:0x803B8958; // type:object size:0x10 scope:local data:4byte _tyFigupon_803B8968 = .rodata:0x803B8968; // type:object size:0xC scope:local data:4byte -_tyFigupon_803B8974 = .rodata:0x803B8974; // type:object size:0x10 scope:local data:4byte +tyFigupon_DigitInit = .rodata:0x803B8974; // type:object size:0x10 scope:local data:4byte _tyDisplay_803B8988 = .rodata:0x803B8988; // type:object size:0xAC scope:local data:4byte _tyDisplay_803B8A34 = .rodata:0x803B8A34; // type:object size:0xAC scope:local data:4byte _tyDisplay_803B8AE0 = .rodata:0x803B8AE0; // type:object size:0xAC scope:local data:4byte @@ -24840,55 +24840,56 @@ _tyList_803FE86C = .data:0x803FE86C; // type:object size:0x11 scope:local data:s @603 = .data:0x803FE9AC; // type:object size:0x1E scope:local data:string @807 = .data:0x803FE9CC; // type:object size:0x22 scope:local data:string @809 = .data:0x803FE9F0; // type:object size:0x19 scope:local data:string -_tyFigupon_str_ToyFigurePonPanel_Top_joint = .data:0x803FEA10; // type:object size:0x1C scope:local data:string -_tyFigupon_803FEA2C = .data:0x803FEA2C; // type:object size:0x19 scope:local data:string -_tyFigupon_803FEA48 = .data:0x803FEA48; // type:object size:0xD scope:local data:string -_tyFigupon_803FEA58 = .data:0x803FEA58; // type:object size:0xD scope:local data:string -_tyFigupon_803FEA68 = .data:0x803FEA68; // type:object size:0x1B scope:local data:string -_tyFigupon_803FEA84 = .data:0x803FEA84; // type:object size:0x1F scope:local data:string -_tyFigupon_803FEAA4 = .data:0x803FEAA4; // type:object size:0x23 scope:local data:string -_tyFigupon_803FEAC8 = .data:0x803FEAC8; // type:object size:0x25 scope:local data:string -jumptable_803FEAF0 = .data:0x803FEAF0; // type:object size:0x28 scope:local -_tyFigupon_803FEB18 = .data:0x803FEB18; // type:object size:0x15 scope:local data:string -_tyFigupon_str___FILE__ = .data:0x803FEB30; // type:object size:0xC scope:local data:string -jumptable_803FEB3C = .data:0x803FEB3C; // type:object size:0x24 scope:local -_tyFigupon_803FEB60 = .data:0x803FEB60; // type:object size:0x25 scope:local data:string +@199 = .data:0x803FEA10; // type:object size:0x1C scope:local data:string +...data.0 = .data:0x803FEA10; // type:label scope:local +@200 = .data:0x803FEA2C; // type:object size:0x19 scope:local data:string +@201 = .data:0x803FEA48; // type:object size:0xD scope:local data:string +@202 = .data:0x803FEA58; // type:object size:0xD scope:local data:string +@203 = .data:0x803FEA68; // type:object size:0x1B scope:local data:string +@204 = .data:0x803FEA84; // type:object size:0x1F scope:local data:string +@205 = .data:0x803FEAA4; // type:object size:0x23 scope:local data:string +@206 = .data:0x803FEAC8; // type:object size:0x25 scope:local data:string +@599 = .data:0x803FEAF0; // type:object size:0x28 scope:local +@603 = .data:0x803FEB18; // type:object size:0x15 scope:local data:string +@604 = .data:0x803FEB30; // type:object size:0xC scope:local data:string +@735 = .data:0x803FEB3C; // type:object size:0x24 scope:local +@820 = .data:0x803FEB60; // type:object size:0x25 scope:local data:string _tyFigupon_803FEB88 = .data:0x803FEB88; // type:object size:0x1A scope:local data:short -_tyFigupon_803FEBA4 = .data:0x803FEBA4; // type:object size:0x22 scope:local data:string -_tyFigupon_803FEBC8 = .data:0x803FEBC8; // type:object size:0x27 scope:local data:string -_tyFigupon_803FEBF0 = .data:0x803FEBF0; // type:object size:0x1D scope:local data:string -_tyFigupon_803FEC10 = .data:0x803FEC10; // type:object size:0x21 scope:local data:string -_tyFigupon_803FEC34 = .data:0x803FEC34; // type:object size:0x23 scope:local data:string -_tyFigupon_803FEC58 = .data:0x803FEC58; // type:object size:0x19 scope:local data:string -_tyFigupon_803FEC74 = .data:0x803FEC74; // type:object size:0x1D scope:local data:string -_tyFigupon_803FEC94 = .data:0x803FEC94; // type:object size:0x21 scope:local data:string -_tyFigupon_803FECB8 = .data:0x803FECB8; // type:object size:0x23 scope:local data:string -_tyFigupon_803FECDC = .data:0x803FECDC; // type:object size:0x1A scope:local data:string -_tyFigupon_803FECF8 = .data:0x803FECF8; // type:object size:0x1E scope:local data:string -_tyFigupon_803FED18 = .data:0x803FED18; // type:object size:0x22 scope:local data:string -_tyFigupon_803FED3C = .data:0x803FED3C; // type:object size:0x24 scope:local data:string -_tyFigupon_803FED60 = .data:0x803FED60; // type:object size:0x27 scope:local data:string -_tyFigupon_803FED88 = .data:0x803FED88; // type:object size:0x1C scope:local data:string -_tyFigupon_803FEDA4 = .data:0x803FEDA4; // type:object size:0x20 scope:local data:string -_tyFigupon_803FEDC4 = .data:0x803FEDC4; // type:object size:0x24 scope:local data:string -_tyFigupon_803FEDE8 = .data:0x803FEDE8; // type:object size:0x26 scope:local data:string -_tyFigupon_803FEE10 = .data:0x803FEE10; // type:object size:0x1A scope:local data:string -_tyFigupon_803FEE2C = .data:0x803FEE2C; // type:object size:0x1E scope:local data:string -_tyFigupon_803FEE4C = .data:0x803FEE4C; // type:object size:0x22 scope:local data:string -_tyFigupon_803FEE70 = .data:0x803FEE70; // type:object size:0x24 scope:local data:string -_tyFigupon_803FEE94 = .data:0x803FEE94; // type:object size:0x22 scope:local data:string -_tyFigupon_803FEEB8 = .data:0x803FEEB8; // type:object size:0x19 scope:local data:string +@1065 = .data:0x803FEBA4; // type:object size:0x22 scope:local data:string +@1067 = .data:0x803FEBC8; // type:object size:0x27 scope:local data:string +@1068 = .data:0x803FEBF0; // type:object size:0x1D scope:local data:string +@1069 = .data:0x803FEC10; // type:object size:0x21 scope:local data:string +@1070 = .data:0x803FEC34; // type:object size:0x23 scope:local data:string +@1071 = .data:0x803FEC58; // type:object size:0x19 scope:local data:string +@1072 = .data:0x803FEC74; // type:object size:0x1D scope:local data:string +@1073 = .data:0x803FEC94; // type:object size:0x21 scope:local data:string +@1074 = .data:0x803FECB8; // type:object size:0x23 scope:local data:string +@1075 = .data:0x803FECDC; // type:object size:0x1A scope:local data:string +@1076 = .data:0x803FECF8; // type:object size:0x1E scope:local data:string +@1077 = .data:0x803FED18; // type:object size:0x22 scope:local data:string +@1078 = .data:0x803FED3C; // type:object size:0x24 scope:local data:string +@1079 = .data:0x803FED60; // type:object size:0x27 scope:local data:string +@1080 = .data:0x803FED88; // type:object size:0x1C scope:local data:string +@1081 = .data:0x803FEDA4; // type:object size:0x20 scope:local data:string +@1082 = .data:0x803FEDC4; // type:object size:0x24 scope:local data:string +@1083 = .data:0x803FEDE8; // type:object size:0x26 scope:local data:string +@1084 = .data:0x803FEE10; // type:object size:0x1A scope:local data:string +@1085 = .data:0x803FEE2C; // type:object size:0x1E scope:local data:string +@1086 = .data:0x803FEE4C; // type:object size:0x22 scope:local data:string +@1087 = .data:0x803FEE70; // type:object size:0x24 scope:local data:string +@1088 = .data:0x803FEE94; // type:object size:0x22 scope:local data:string +@1091 = .data:0x803FEEB8; // type:object size:0x19 scope:local data:string _tyFigupon_803FEED4 = .data:0x803FEED4; // type:object size:0x14 scope:local data:float _tyFigupon_803FEEE8 = .data:0x803FEEE8; // type:object size:0x14 scope:local data:float _tyFigupon_803FEEFC = .data:0x803FEEFC; // type:object size:0x38 scope:local data:4byte -_tyFigupon_803FEF34 = .data:0x803FEF34; // type:object size:0xA scope:local data:string -_tyFigupon_803FEF40 = .data:0x803FEF40; // type:object size:0xC scope:local data:string -_tyFigupon_803FEF4C = .data:0x803FEF4C; // type:object size:0xA scope:local data:string -_tyFigupon_803FEF58 = .data:0x803FEF58; // type:object size:0xE scope:local data:string -_tyFigupon_803FEF68 = .data:0x803FEF68; // type:object size:0x1B scope:local data:string -_tyFigupon_803FEF84 = .data:0x803FEF84; // type:object size:0x1F scope:local data:string -_tyFigupon_803FEFA4 = .data:0x803FEFA4; // type:object size:0x23 scope:local data:string -_tyFigupon_803FEFC8 = .data:0x803FEFC8; // type:object size:0x25 scope:local data:string +@1112 = .data:0x803FEF34; // type:object size:0xA scope:local data:string +@1113 = .data:0x803FEF40; // type:object size:0xC scope:local data:string +@1114 = .data:0x803FEF4C; // type:object size:0xA scope:local data:string +@1115 = .data:0x803FEF58; // type:object size:0xE scope:local data:string +@1177 = .data:0x803FEF68; // type:object size:0x1B scope:local data:string +@1178 = .data:0x803FEF84; // type:object size:0x1F scope:local data:string +@1179 = .data:0x803FEFA4; // type:object size:0x23 scope:local data:string +@1180 = .data:0x803FEFC8; // type:object size:0x25 scope:local data:string _tyDisplay_str_ToyDspPanel_Top_joint = .data:0x803FEFF0; // type:object size:0x16 scope:local data:string _tyDisplay_803FF008 = .data:0x803FF008; // type:object size:0x13 scope:local data:string _tyDisplay_803FF01C = .data:0x803FF01C; // type:object size:0x16 scope:local data:string @@ -26828,8 +26829,8 @@ ftCo_804D3C30 = .sdata:0x804D3C30; // type:object size:0x2 scope:global data:str @251 = .sdata:0x804D3D00; // type:object size:0x5 scope:local data:string @300 = .sdata:0x804D3D08; // type:object size:0x7 scope:local data:string @301 = .sdata:0x804D3D10; // type:object size:0x5 scope:local data:string -ftCo_804D3D18 = .sdata:0x804D3D18; // type:object size:0x7 scope:local data:string -ftCo_804D3D20 = .sdata:0x804D3D20; // type:object size:0x5 scope:local data:string +@307 = .sdata:0x804D3D18; // type:object size:0x7 scope:local data:string +@308 = .sdata:0x804D3D20; // type:object size:0x5 scope:local data:string @306 = .sdata:0x804D3D28; // type:object size:0x7 scope:local data:string @307 = .sdata:0x804D3D30; // type:object size:0x5 scope:local data:string @348 = .sdata:0x804D3D38; // type:object size:0x7 scope:local data:string @@ -27946,10 +27947,10 @@ _Toy_str_jobj = .sdata:0x804D5A6C; // type:object size:0x5 scope:local data:stri @247 = .sdata:0x804D5A80; // type:object size:0x5 scope:local data:string @776 = .sdata:0x804D5A88; // type:object size:0x3 scope:local data:string @808 = .sdata:0x804D5A8C; // type:object size:0x1 scope:local data:string -_tyFigupon_804D5A90 = .sdata:0x804D5A90; // type:object size:0x7 scope:local data:string -_tyFigupon_804D5A98 = .sdata:0x804D5A98; // type:object size:0x5 scope:local data:string +@445 = .sdata:0x804D5A90; // type:object size:0x7 scope:local data:string +@446 = .sdata:0x804D5A98; // type:object size:0x5 scope:local data:string _tyFigupon_804D5AA0 = .sdata:0x804D5AA0; // type:object size:0x4 scope:local data:4byte -_tyFigupon_804D5AA4 = .sdata:0x804D5AA4; // type:object size:0x1 scope:local data:string +@1066 = .sdata:0x804D5AA4; // type:object size:0x1 scope:local data:string _tyDisplay_804D5AA8 = .sdata:0x804D5AA8; // type:object size:0x2 scope:local data:string _tyDisplay_804D5AAC = .sdata:0x804D5AAC; // type:object size:0x7 scope:local data:string _tyDisplay_804D5AB4 = .sdata:0x804D5AB4; // type:object size:0x5 scope:local data:string @@ -30528,12 +30529,12 @@ ftCo_804D8CB8 = .sdata2:0x804D8CB8; // type:object size:0x8 scope:global align:8 @302 = .sdata2:0x804D9050; // type:object size:0x8 scope:local align:8 data:double @303 = .sdata2:0x804D9058; // type:object size:0x4 scope:local align:4 data:float @305 = .sdata2:0x804D9060; // type:object size:0x8 scope:local align:8 data:double -ftCo_804D9068 = .sdata2:0x804D9068; // type:object size:0x8 scope:local align:8 data:double -ftCo_804D9070 = .sdata2:0x804D9070; // type:object size:0x8 scope:local align:8 data:double -ftCo_804D9078 = .sdata2:0x804D9078; // type:object size:0x4 scope:local align:4 data:float -ftCo_804D9080 = .sdata2:0x804D9080; // type:object size:0x8 scope:local align:8 data:double -ftCo_804D9088 = .sdata2:0x804D9088; // type:object size:0x4 scope:local align:4 data:float -ftCo_804D9090 = .sdata2:0x804D9090; // type:object size:0x8 scope:local align:8 data:double +@306 = .sdata2:0x804D9068; // type:object size:0x8 scope:local align:8 data:double +@309 = .sdata2:0x804D9070; // type:object size:0x8 scope:local align:8 data:double +@310 = .sdata2:0x804D9078; // type:object size:0x4 scope:local align:4 data:float +@311 = .sdata2:0x804D9080; // type:object size:0x8 scope:local align:8 data:double +@312 = .sdata2:0x804D9088; // type:object size:0x4 scope:local align:4 data:float +@314 = .sdata2:0x804D9090; // type:object size:0x8 scope:local align:8 data:double @277 = .sdata2:0x804D9098; // type:object size:0x4 scope:local align:4 data:float @278 = .sdata2:0x804D909C; // type:object size:0x4 scope:local align:4 data:float @281 = .sdata2:0x804D90A0; // type:object size:0x8 scope:local align:8 data:double @@ -34495,56 +34496,56 @@ _Toy_804DDE20 = .sdata2:0x804DDE20; // type:object size:0x4 scope:local align:4 @797 = .sdata2:0x804DDE90; // type:object size:0x4 scope:local align:4 data:float @798 = .sdata2:0x804DDE94; // type:object size:0x4 scope:local align:4 data:float @799 = .sdata2:0x804DDE98; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_f32_0 = .sdata2:0x804DDEA0; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEA8 = .sdata2:0x804DDEA8; // type:object size:0x8 scope:local align:8 data:double -_tyFigupon_804DDEB0 = .sdata2:0x804DDEB0; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEB4 = .sdata2:0x804DDEB4; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEB8 = .sdata2:0x804DDEB8; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEBC = .sdata2:0x804DDEBC; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEC0 = .sdata2:0x804DDEC0; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEC4 = .sdata2:0x804DDEC4; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEC8 = .sdata2:0x804DDEC8; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDECC = .sdata2:0x804DDECC; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDED0 = .sdata2:0x804DDED0; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDED4 = .sdata2:0x804DDED4; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDED8 = .sdata2:0x804DDED8; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEDC = .sdata2:0x804DDEDC; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEE0 = .sdata2:0x804DDEE0; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEE4 = .sdata2:0x804DDEE4; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEE8 = .sdata2:0x804DDEE8; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEEC = .sdata2:0x804DDEEC; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEF0 = .sdata2:0x804DDEF0; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEF4 = .sdata2:0x804DDEF4; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEF8 = .sdata2:0x804DDEF8; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDEFC = .sdata2:0x804DDEFC; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF00 = .sdata2:0x804DDF00; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF04 = .sdata2:0x804DDF04; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF08 = .sdata2:0x804DDF08; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF0C = .sdata2:0x804DDF0C; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF10 = .sdata2:0x804DDF10; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF14 = .sdata2:0x804DDF14; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF18 = .sdata2:0x804DDF18; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF1C = .sdata2:0x804DDF1C; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF20 = .sdata2:0x804DDF20; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF24 = .sdata2:0x804DDF24; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF28 = .sdata2:0x804DDF28; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF2C = .sdata2:0x804DDF2C; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF30 = .sdata2:0x804DDF30; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF34 = .sdata2:0x804DDF34; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF38 = .sdata2:0x804DDF38; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF3C = .sdata2:0x804DDF3C; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF40 = .sdata2:0x804DDF40; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF44 = .sdata2:0x804DDF44; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF48 = .sdata2:0x804DDF48; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF4C = .sdata2:0x804DDF4C; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF50 = .sdata2:0x804DDF50; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF54 = .sdata2:0x804DDF54; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF58 = .sdata2:0x804DDF58; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF5C = .sdata2:0x804DDF5C; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF60 = .sdata2:0x804DDF60; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF64 = .sdata2:0x804DDF64; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF68 = .sdata2:0x804DDF68; // type:object size:0x4 scope:local align:4 data:float -_tyFigupon_804DDF6C = .sdata2:0x804DDF6C; // type:object size:0x4 scope:local align:4 data:float +@208 = .sdata2:0x804DDEA0; // type:object size:0x4 scope:local align:4 data:float +@209 = .sdata2:0x804DDEA8; // type:object size:0x8 scope:local align:8 data:double +@210 = .sdata2:0x804DDEB0; // type:object size:0x4 scope:local align:4 data:float +@211 = .sdata2:0x804DDEB4; // type:object size:0x4 scope:local align:4 data:float +@212 = .sdata2:0x804DDEB8; // type:object size:0x4 scope:local align:4 data:float +@213 = .sdata2:0x804DDEBC; // type:object size:0x4 scope:local align:4 data:float +@214 = .sdata2:0x804DDEC0; // type:object size:0x4 scope:local align:4 data:float +@215 = .sdata2:0x804DDEC4; // type:object size:0x4 scope:local align:4 data:float +@216 = .sdata2:0x804DDEC8; // type:object size:0x4 scope:local align:4 data:float +@217 = .sdata2:0x804DDECC; // type:object size:0x4 scope:local align:4 data:float +@218 = .sdata2:0x804DDED0; // type:object size:0x4 scope:local align:4 data:float +@219 = .sdata2:0x804DDED4; // type:object size:0x4 scope:local align:4 data:float +@220 = .sdata2:0x804DDED8; // type:object size:0x4 scope:local align:4 data:float +@221 = .sdata2:0x804DDEDC; // type:object size:0x4 scope:local align:4 data:float +@222 = .sdata2:0x804DDEE0; // type:object size:0x4 scope:local align:4 data:float +@223 = .sdata2:0x804DDEE4; // type:object size:0x4 scope:local align:4 data:float +@224 = .sdata2:0x804DDEE8; // type:object size:0x4 scope:local align:4 data:float +@225 = .sdata2:0x804DDEEC; // type:object size:0x4 scope:local align:4 data:float +@226 = .sdata2:0x804DDEF0; // type:object size:0x4 scope:local align:4 data:float +@227 = .sdata2:0x804DDEF4; // type:object size:0x4 scope:local align:4 data:float +@228 = .sdata2:0x804DDEF8; // type:object size:0x4 scope:local align:4 data:float +@229 = .sdata2:0x804DDEFC; // type:object size:0x4 scope:local align:4 data:float +@230 = .sdata2:0x804DDF00; // type:object size:0x4 scope:local align:4 data:float +@231 = .sdata2:0x804DDF04; // type:object size:0x4 scope:local align:4 data:float +@232 = .sdata2:0x804DDF08; // type:object size:0x4 scope:local align:4 data:float +@233 = .sdata2:0x804DDF0C; // type:object size:0x4 scope:local align:4 data:float +@234 = .sdata2:0x804DDF10; // type:object size:0x4 scope:local align:4 data:float +@235 = .sdata2:0x804DDF14; // type:object size:0x4 scope:local align:4 data:float +@236 = .sdata2:0x804DDF18; // type:object size:0x4 scope:local align:4 data:float +@237 = .sdata2:0x804DDF1C; // type:object size:0x4 scope:local align:4 data:float +@238 = .sdata2:0x804DDF20; // type:object size:0x4 scope:local align:4 data:float +@239 = .sdata2:0x804DDF24; // type:object size:0x4 scope:local align:4 data:float +@240 = .sdata2:0x804DDF28; // type:object size:0x4 scope:local align:4 data:float +@241 = .sdata2:0x804DDF2C; // type:object size:0x4 scope:local align:4 data:float +@242 = .sdata2:0x804DDF30; // type:object size:0x4 scope:local align:4 data:float +@243 = .sdata2:0x804DDF34; // type:object size:0x4 scope:local align:4 data:float +@244 = .sdata2:0x804DDF38; // type:object size:0x4 scope:local align:4 data:float +@245 = .sdata2:0x804DDF3C; // type:object size:0x4 scope:local align:4 data:float +@246 = .sdata2:0x804DDF40; // type:object size:0x4 scope:local align:4 data:float +@247 = .sdata2:0x804DDF44; // type:object size:0x4 scope:local align:4 data:float +@248 = .sdata2:0x804DDF48; // type:object size:0x4 scope:local align:4 data:float +@249 = .sdata2:0x804DDF4C; // type:object size:0x4 scope:local align:4 data:float +@250 = .sdata2:0x804DDF50; // type:object size:0x4 scope:local align:4 data:float +@251 = .sdata2:0x804DDF54; // type:object size:0x4 scope:local align:4 data:float +@252 = .sdata2:0x804DDF58; // type:object size:0x4 scope:local align:4 data:float +@253 = .sdata2:0x804DDF5C; // type:object size:0x4 scope:local align:4 data:float +@254 = .sdata2:0x804DDF60; // type:object size:0x4 scope:local align:4 data:float +@255 = .sdata2:0x804DDF64; // type:object size:0x4 scope:local align:4 data:float +@256 = .sdata2:0x804DDF68; // type:object size:0x4 scope:local align:4 data:float +@257 = .sdata2:0x804DDF6C; // type:object size:0x4 scope:local align:4 data:float _tyDisplay_f32_7 = .sdata2:0x804DDF70; // type:object size:0x4 scope:local align:4 data:float _tyDisplay_f32_0 = .sdata2:0x804DDF74; // type:object size:0x4 scope:local align:4 data:float _tyDisplay_804DDF78 = .sdata2:0x804DDF78; // type:object size:0x8 scope:local align:8 data:double diff --git a/configure.py b/configure.py index 694ba8c92f..b8357d2e3f 100755 --- a/configure.py +++ b/configure.py @@ -846,7 +846,7 @@ def MatchingFor(*versions): Object(Matching, "melee/ft/chara/ftCommon/ftCo_ItemScope.c"), Object(Matching, "melee/ft/chara/ftCommon/ftCo_Catch.c"), Object(Matching, "melee/ft/chara/ftCommon/ftCo_0D8E.c"), - Object(Linkable, "melee/ft/chara/ftCommon/ftCo_0D95.c"), + Object(Matching, "melee/ft/chara/ftCommon/ftCo_0D95.c"), Object(Matching, "melee/ft/chara/ftCommon/ftCo_CatchPull.c"), Object(Matching, "melee/ft/chara/ftCommon/ftCo_CatchWait.c"), Object(Matching, "melee/ft/chara/ftCommon/ftCo_CatchAttack.c"), @@ -1573,7 +1573,7 @@ def MatchingFor(*versions): [ Object(Linkable, "melee/ty/toy.c"), Object(Matching, "melee/ty/tylist.c"), - Object(Linkable, "melee/ty/tyfigupon.c"), + Object(Matching, "melee/ty/tyfigupon.c"), Object(Linkable, "melee/ty/tydisplay.c"), ], ), From 46cc9a8cfc90e0f2d6f5160a3dfacbd45dc22e3a Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 14:16:37 -0700 Subject: [PATCH 11/64] Improve ifStatus_802F4EDC to 99.96% 99.93% -> 99.96%, from the captured frame layout rather than source guessing. The target stages the three GXColors at 0x38/0x40/0x60, high in the frame and interleaved with 4EDC's own locals. Colours declared inside the inline are expansion temps and always land at the bottom of the frame (0x10/0x14/0x18) -- no statement position or PAD_STACK value moves them, because inline temps are created after every declaration in the caller. So the three GXColors have to be 4EDC's own declarations, and the inline takes them by pointer to keep the web boundary that gives the colour-apply block its register assignment (hoisting the block body instead costs 42 rows). With the colours owned by the caller, PAD_STACK(64) becomes three explicitly sized holes: 28/4/28 reproduces the target's frame exactly (0xf8, colours at 0x38/0x40/0x60), where the single 64-byte pad cannot -- the target's dead space is fragmented and no contiguous 64-byte run fits it. Six rows remain: one callee-saved web on the HUD lookup, and one commutative fadds pair. --- src/melee/if/ifstatus.c | 165 ++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 81 deletions(-) diff --git a/src/melee/if/ifstatus.c b/src/melee/if/ifstatus.c index 2eb3393e6e..acc6abb2fd 100644 --- a/src/melee/if/ifstatus.c +++ b/src/melee/if/ifstatus.c @@ -205,14 +205,52 @@ void ifStatus_802F4B84(IfDamageState* state, s32 is_stamina) PAD_STACK(8); } +static inline void ifStatus_InitDamageDigits(IfDamageState* state, + HSD_MatAnimJoint** anim_base) +{ + HSD_JObj* digit_jobj; + u8 digit; + + digit_jobj = state->jobjs[Ones]; + digit = state->damage_percent % 10; + HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) + ->child->child->aobjdesc->fobjdesc); + HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + + digit_jobj = state->jobjs[Tens]; + digit = (state->damage_percent % 100) / 10; + HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) + ->child->child->aobjdesc->fobjdesc); + HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + + digit_jobj = state->jobjs[Hundreds]; + digit = (state->damage_percent % 1000) / 100; + HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) + ->child->child->aobjdesc->fobjdesc); + HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); +} + +static inline f32 ifStatus_GetStoredTranslationX(IfDamageState* state, + s32 index) +{ + return state->translation_x[index]; +} + static inline void ifStatus_UpdateDamageDisplay(IfDamageState* state, - HSD_JObj* jobj) + HSD_JObj* jobj, GXColor* color, + GXColor* stamina_color, + GXColor* normal_color) { - s16 clamped_damage; - f32 factor; - GXColor color; HSD_MObj* mobj; HSD_JObj* digit_jobj; + s16 clamped_damage; + f32 factor; s32 i; if ((state->damage_percent % 1000) / 100 == 0) { @@ -223,28 +261,24 @@ static inline void ifStatus_UpdateDamageDisplay(IfDamageState* state, if (state->old_damage != state->damage_percent) { if (Player_GetMoreFlagsBit2((s8) state->player_slot)) { - GXColor stamina_color; - if ((clamped_damage = state->damage_percent) > 100) { clamped_damage = 100; } else if (clamped_damage < 0) { clamped_damage = 0; } factor = 1.0F - ((f32) clamped_damage / 100.0F); - stamina_color.r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - - ifStatus_804D57A8[0]) + - (f32) ifStatus_804D57A8[0]); - stamina_color.g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - - ifStatus_804D57A8[1]) + - (f32) ifStatus_804D57A8[1]); - stamina_color.b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - - ifStatus_804D57A8[2]) + - (f32) ifStatus_804D57A8[2]); - stamina_color.a = 255; - color = stamina_color; + stamina_color->r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - + ifStatus_804D57A8[0]) + + (f32) ifStatus_804D57A8[0]); + stamina_color->g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - + ifStatus_804D57A8[1]) + + (f32) ifStatus_804D57A8[1]); + stamina_color->b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - + ifStatus_804D57A8[2]) + + (f32) ifStatus_804D57A8[2]); + stamina_color->a = 255; + *color = *stamina_color; } else { - GXColor normal_color; - clamped_damage = state->damage_percent; if (clamped_damage > 300) { clamped_damage = 300; @@ -252,38 +286,38 @@ static inline void ifStatus_UpdateDamageDisplay(IfDamageState* state, clamped_damage = 0; } factor = (f32) clamped_damage / 300.0F; - normal_color.r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - - ifStatus_804D57A8[0]) + - (f32) ifStatus_804D57A8[0]); - normal_color.g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - - ifStatus_804D57A8[1]) + - (f32) ifStatus_804D57A8[1]); - normal_color.b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - - ifStatus_804D57A8[2]) + - (f32) ifStatus_804D57A8[2]); - normal_color.a = 255; - color = normal_color; + normal_color->r = (s8) (factor * (f32) (ifStatus_804D57AC[0] - + ifStatus_804D57A8[0]) + + (f32) ifStatus_804D57A8[0]); + normal_color->g = (s8) (factor * (f32) (ifStatus_804D57AC[1] - + ifStatus_804D57A8[1]) + + (f32) ifStatus_804D57A8[1]); + normal_color->b = (s8) (factor * (f32) (ifStatus_804D57AC[2] - + ifStatus_804D57A8[2]) + + (f32) ifStatus_804D57A8[2]); + normal_color->a = 255; + *color = *normal_color; } mobj = state->jobjs[Hundreds]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; + mobj->mat->diffuse.r = color->r; + mobj->mat->diffuse.g = color->g; + mobj->mat->diffuse.b = color->b; mobj = state->jobjs[Tens]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; + mobj->mat->diffuse.r = color->r; + mobj->mat->diffuse.g = color->g; + mobj->mat->diffuse.b = color->b; mobj = state->jobjs[Ones]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; + mobj->mat->diffuse.r = color->r; + mobj->mat->diffuse.g = color->g; + mobj->mat->diffuse.b = color->b; mobj = state->jobjs[Percent]->u.dobj->mobj; - mobj->mat->diffuse.r = color.r; - mobj->mat->diffuse.g = color.g; - mobj->mat->diffuse.b = color.b; + mobj->mat->diffuse.r = color->r; + mobj->mat->diffuse.g = color->g; + mobj->mat->diffuse.b = color->b; } if (lb_8000B09C(jobj)) { @@ -299,43 +333,6 @@ static inline void ifStatus_UpdateDamageDisplay(IfDamageState* state, } } -static inline void ifStatus_InitDamageDigits(IfDamageState* state, - HSD_MatAnimJoint** anim_base) -{ - HSD_JObj* digit_jobj; - u8 digit; - - digit_jobj = state->jobjs[Ones]; - digit = state->damage_percent % 10; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, - (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) - ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); - - digit_jobj = state->jobjs[Tens]; - digit = (state->damage_percent % 100) / 10; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, - (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) - ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); - - digit_jobj = state->jobjs[Hundreds]; - digit = (state->damage_percent % 1000) / 100; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, - (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) - ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); -} - -static inline f32 ifStatus_GetStoredTranslationX(IfDamageState* state, - s32 index) -{ - return state->translation_x[index]; -} - void ifStatus_802F4EDC(HSD_GObj* gobj) { HudIndex* hud; @@ -343,6 +340,12 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) HSD_JObj* jobj; HSD_JObj* digit_jobj; s32 is_stamina; + GXColor color; + UNUSED u8 pad_a[28]; + GXColor stamina_color; + UNUSED u8 pad_b[4]; + GXColor normal_color; + UNUSED u8 pad_c[28]; HSD_TObj* tobj; HSD_MatAnimJoint** anim_base; s32 i; @@ -354,7 +357,6 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) f32 pos; IfDamageState* ptr; - PAD_STACK(64); hud = ifStatus_GetHUDInfo(); { @@ -452,7 +454,8 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) HSD_AObjSetRate(post_digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); } - ifStatus_UpdateDamageDisplay(state, jobj); + ifStatus_UpdateDamageDisplay(state, jobj, &color, &stamina_color, + &normal_color); /* Calculate digit spacing offsets based on which digit is "1" */ ones_offset = (state->damage_percent % 10 == 1) ? 0.5069F : 0.0F; From 978e6149885105aeaf1a24ea9c7880bc22f74357 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 14:42:20 -0700 Subject: [PATCH 12/64] Improve ifStatus_802F4EDC to 99.98% Two rows left. The digit-init helper's Hundreds JObj was landing in r28 because its web selects one step before the Tens web, which is the one that claims r24; naming the three JObjs separately renumbers them so the Tens web selects first and both end on r24, as the target has it. coloring_model confirmed the swap reaches the full 34/34 colouring before it was tried. --- src/melee/if/ifstatus.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/melee/if/ifstatus.c b/src/melee/if/ifstatus.c index acc6abb2fd..48bfbf60f5 100644 --- a/src/melee/if/ifstatus.c +++ b/src/melee/if/ifstatus.c @@ -208,32 +208,34 @@ void ifStatus_802F4B84(IfDamageState* state, s32 is_stamina) static inline void ifStatus_InitDamageDigits(IfDamageState* state, HSD_MatAnimJoint** anim_base) { - HSD_JObj* digit_jobj; + HSD_JObj* hundreds_jobj; + HSD_JObj* tens_jobj; + HSD_JObj* ones_jobj; u8 digit; - digit_jobj = state->jobjs[Ones]; + ones_jobj = state->jobjs[Ones]; digit = state->damage_percent % 10; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + HSD_TObjAddAnimAll(ones_jobj->u.dobj->mobj->tobj, (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + HSD_TObjReqAnimAll(ones_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(ones_jobj->u.dobj->mobj->tobj->aobj, 0.0F); - digit_jobj = state->jobjs[Tens]; + tens_jobj = state->jobjs[Tens]; digit = (state->damage_percent % 100) / 10; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + HSD_TObjAddAnimAll(tens_jobj->u.dobj->mobj->tobj, (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + HSD_TObjReqAnimAll(tens_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(tens_jobj->u.dobj->mobj->tobj->aobj, 0.0F); - digit_jobj = state->jobjs[Hundreds]; + hundreds_jobj = state->jobjs[Hundreds]; digit = (state->damage_percent % 1000) / 100; - HSD_TObjAddAnimAll(digit_jobj->u.dobj->mobj->tobj, + HSD_TObjAddAnimAll(hundreds_jobj->u.dobj->mobj->tobj, (HSD_TexAnim*) ((HSD_AnimJoint*) anim_base[0]) ->child->child->aobjdesc->fobjdesc); - HSD_TObjReqAnimAll(digit_jobj->u.dobj->mobj->tobj, 2.0F * digit); - HSD_AObjSetRate(digit_jobj->u.dobj->mobj->tobj->aobj, 0.0F); + HSD_TObjReqAnimAll(hundreds_jobj->u.dobj->mobj->tobj, 2.0F * digit); + HSD_AObjSetRate(hundreds_jobj->u.dobj->mobj->tobj->aobj, 0.0F); } static inline f32 ifStatus_GetStoredTranslationX(IfDamageState* state, From 403f7a6e1a9a47cca452d534b0ea5b5678dec965 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 14:58:21 -0700 Subject: [PATCH 13/64] Drop casts eflib no longer needs `ptclref_804D0E5C` is now typed `HSD_PSCmdList**`, so the four `(HSD_PSCmdList*)` casts in efLib_Cb_PtclAppSRTHook are redundant and clang-tidy's readability-redundant-casting fails the build on them (WarningsAsErrors). eflib.o is byte-identical without them. --- src/melee/ef/eflib.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/melee/ef/eflib.c b/src/melee/ef/eflib.c index 5c46069810..ea699c85b2 100644 --- a/src/melee/ef/eflib.c +++ b/src/melee/ef/eflib.c @@ -1050,20 +1050,16 @@ void (*lbl_803BF810[0x03])(HSD_Particle* particle) = { efLib_Cb_ParticleRender, // parent joint. void efLib_Cb_PtclAppSRTHook(HSD_Generator* gen) { - if (gen->cmdList == ((HSD_PSCmdList*) ptclref_804D0E5C[0][0x96])->cmdList) - { + if (gen->cmdList == ptclref_804D0E5C[0][0x96]->cmdList) { hsd_8039D1E4(gen, lbl_803BF810); } - if (gen->cmdList == ((HSD_PSCmdList*) ptclref_804D0E5C[0][0x97])->cmdList) - { + if (gen->cmdList == ptclref_804D0E5C[0][0x97]->cmdList) { hsd_8039D1E4(gen, lbl_803BF810); } - if (gen->cmdList == ((HSD_PSCmdList*) ptclref_804D0E5C[0][0x98])->cmdList) - { + if (gen->cmdList == ptclref_804D0E5C[0][0x98]->cmdList) { hsd_8039D1E4(gen, lbl_803BF810); } - if (gen->cmdList == ((HSD_PSCmdList*) ptclref_804D0E5C[0][0x21B])->cmdList) - { + if (gen->cmdList == ptclref_804D0E5C[0][0x21B]->cmdList) { hsd_8039D1E4(gen, lbl_803BF810); } } From 738c38dcf493d86c552051192827cfe4d90c586f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 16:07:23 -0700 Subject: [PATCH 14/64] Match ifStatus_802F4EDC Use a full-lifetime scalar carrier to place the digit-offset accumulator in MWCC's lowering-object register band. Compensate its four-byte home in the existing pad and preserve the target final add ordering with a double-negative spelling. --- src/melee/if/ifstatus.c | 78 +++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/src/melee/if/ifstatus.c b/src/melee/if/ifstatus.c index 48bfbf60f5..e0bbf886d1 100644 --- a/src/melee/if/ifstatus.c +++ b/src/melee/if/ifstatus.c @@ -347,12 +347,11 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) GXColor stamina_color; UNUSED u8 pad_b[4]; GXColor normal_color; - UNUSED u8 pad_c[28]; + UNUSED u8 pad_c[24]; HSD_TObj* tobj; HSD_MatAnimJoint** anim_base; s32 i; u8 digit; - f32 digit_offset; f32 ones_offset; f32 tens_offset; f32 hundreds_offset; @@ -459,41 +458,50 @@ void ifStatus_802F4EDC(HSD_GObj* gobj) ifStatus_UpdateDamageDisplay(state, jobj, &color, &stamina_color, &normal_color); - /* Calculate digit spacing offsets based on which digit is "1" */ - ones_offset = (state->damage_percent % 10 == 1) ? 0.5069F : 0.0F; - tens_offset = ((state->damage_percent % 100) / 10 == 1) ? 0.5069F : 0.0F; + { + struct { + f32 value; + } digit_offset; - /* Position percent sign */ - digit_jobj = state->jobjs[Percent]; - pos = state->translation_x[Percent] - ones_offset; - if (digit_jobj == NULL) { - __assert("jobj.h", 932, "jobj"); - } - digit_jobj->translate.x = pos; - jobj_flagCheckSetMtxDirtySub(digit_jobj); - - /* Position tens digit */ - digit_offset = ones_offset + tens_offset; - digit_jobj = state->jobjs[Tens]; - pos = state->translation_x[Tens] + digit_offset; - (void) pos; - if (digit_jobj == NULL) { - __assert("jobj.h", 932, "jobj"); - } - digit_jobj->translate.x = pos; - jobj_flagCheckSetMtxDirtySub(digit_jobj); - - /* Position hundreds digit */ - hundreds_offset = - ((state->damage_percent % 1000) / 100 == 1) ? 0.5069F : 0.0F; - digit_jobj = state->jobjs[Hundreds]; - pos = ifStatus_GetStoredTranslationX(state, Hundreds) + - (tens_offset + hundreds_offset + digit_offset); - if (digit_jobj == NULL) { - __assert("jobj.h", 932, "jobj"); + /* Calculate digit spacing offsets based on which digit is "1" */ + ones_offset = (state->damage_percent % 10 == 1) ? 0.5069F : 0.0F; + tens_offset = + ((state->damage_percent % 100) / 10 == 1) ? 0.5069F : 0.0F; + + /* Position percent sign */ + digit_jobj = state->jobjs[Percent]; + pos = state->translation_x[Percent] - ones_offset; + if (digit_jobj == NULL) { + __assert("jobj.h", 932, "jobj"); + } + digit_jobj->translate.x = pos; + jobj_flagCheckSetMtxDirtySub(digit_jobj); + + /* Position tens digit */ + digit_offset.value = ones_offset; + digit_offset.value += tens_offset; + digit_jobj = state->jobjs[Tens]; + pos = state->translation_x[Tens] + digit_offset.value; + (void) pos; + if (digit_jobj == NULL) { + __assert("jobj.h", 932, "jobj"); + } + digit_jobj->translate.x = pos; + jobj_flagCheckSetMtxDirtySub(digit_jobj); + + /* Position hundreds digit */ + hundreds_offset = + ((state->damage_percent % 1000) / 100 == 1) ? 0.5069F : 0.0F; + digit_jobj = state->jobjs[Hundreds]; + digit_offset.value += tens_offset + hundreds_offset; + pos = ifStatus_GetStoredTranslationX(state, Hundreds) - + -digit_offset.value; + if (digit_jobj == NULL) { + __assert("jobj.h", 932, "jobj"); + } + digit_jobj->translate.x = pos; + jobj_flagCheckSetMtxDirtySub(digit_jobj); } - digit_jobj->translate.x = pos; - jobj_flagCheckSetMtxDirtySub(digit_jobj); /* Handle shake animation */ if (state->flags.force_digit_shake) { From 1ac5665d3de9996875afb0d673d393bbdb254d35 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 16:13:50 -0700 Subject: [PATCH 15/64] Link ifstatus translation unit Seed the retail literal-pool order behind MUST_MATCH, mark ifstatus.c Matching, and apply the linked ELF's canonical symbols. The full main.dol checksum and dtk symbol diff both pass. --- config/GALE01/symbols.txt | 22 ++++++++++++---------- configure.py | 2 +- src/melee/if/ifstatus.c | 27 +++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/config/GALE01/symbols.txt b/config/GALE01/symbols.txt index 2d6ddff651..195a258f53 100644 --- a/config/GALE01/symbols.txt +++ b/config/GALE01/symbols.txt @@ -17269,7 +17269,7 @@ ifTime_Reset = .text:0x802F480C; // type:function size:0x30 scope:global ifTime_FreeTimers = .text:0x802F483C; // type:function size:0x5C scope:global ifTime_IsTimerHidden = .text:0x802F4898; // type:function size:0x78 scope:global ifStatus_GetHUDInfo = .text:0x802F4910; // type:function size:0xC scope:global -ifStatus_PercentOnDeathAnimationThink = .text:0x802F491C; // type:function size:0x268 scope:global +ifStatus_PercentOnDeathAnimationThink = .text:0x802F491C; // type:function size:0x268 scope:local ifStatus_802F4B84 = .text:0x802F4B84; // type:function size:0x358 scope:global ifStatus_802F4EDC = .text:0x802F4EDC; // type:function size:0xC6C scope:global ifStatus_802F5B48 = .text:0x802F5B48; // type:function size:0x298 scope:global @@ -24227,12 +24227,13 @@ it_803F94A0 = .data:0x803F94A0; // type:object size:0x30 scope:global @263 = .data:0x803F953C; // type:object size:0xA scope:local data:string @309 = .data:0x803F9548; // type:object size:0x25 scope:local data:string @310 = .data:0x803F9570; // type:object size:0x25 scope:local data:string -ifStatus_803F9598 = .data:0x803F9598; // type:object size:0x14 scope:global data:string -ifStatus_803F95AC = .data:0x803F95AC; // type:object size:0x14 scope:global data:string -lbl_803F95C0 = .data:0x803F95C0; // type:object size:0xA data:string -lbl_803F95CC = .data:0x803F95CC; // type:object size:0x25 data:string -lbl_803F95F4 = .data:0x803F95F4; // type:object size:0xB data:string -lbl_803F9600 = .data:0x803F9600; // type:object size:0x25 data:string +num_models_name = .data:0x803F9598; // type:object size:0x14 scope:global data:string +...data.0 = .data:0x803F9598; // type:label scope:local +mrk_models_name = .data:0x803F95AC; // type:object size:0x14 scope:global data:string +@692 = .data:0x803F95C0; // type:object size:0xA scope:local data:string +@754 = .data:0x803F95CC; // type:object size:0x25 scope:local data:string +@755 = .data:0x803F95F4; // type:object size:0xB scope:local data:string +@757 = .data:0x803F9600; // type:object size:0x25 scope:local data:string ifStatus_803F9628 = .data:0x803F9628; // type:object size:0x140 scope:global data:4byte ...data.0 = .data:0x803F9628; // type:label scope:local @234 = .data:0x803F9768; // type:object size:0x16 scope:local data:string @@ -26354,6 +26355,7 @@ ifTime_data = .bss:0x804A1078; // type:object size:0x3C scope:local data:4byte ...bss.0 = .bss:0x804A1078; // type:label scope:local ifTime_match_timer_models = .bss:0x804A10B4; // type:object size:0x10 scope:local data:4byte ifStatus_HudInfo = .bss:0x804A10C8; // type:object size:0x278 scope:global data:4byte +...bss.0 = .bss:0x804A10C8; // type:label scope:local lbl_804A1340 = .bss:0x804A1340; // type:object size:0x34 data:4byte ...bss.0 = .bss:0x804A1340; // type:label scope:local ifStock_804A1378 = .bss:0x804A1378; // type:object size:0x3FC scope:global data:4byte @@ -27845,9 +27847,9 @@ it_804D5518$198 = .sdata:0x804D5518; // type:object size:0x8 scope:local @262 = .sdata:0x804D579C; // type:object size:0x5 scope:local data:string ifStatus_804D57A8 = .sdata:0x804D57A8; // type:object size:0x4 scope:global data:byte ifStatus_804D57AC = .sdata:0x804D57AC; // type:object size:0x4 scope:global data:byte -ifStatus_804D57B0 = .sdata:0x804D57B0; // type:object size:0x7 scope:global data:string -ifStatus_804D57B8 = .sdata:0x804D57B8; // type:object size:0x5 scope:global data:string -ifStatus_804D57C0 = .sdata:0x804D57C0; // type:object size:0x2 scope:global data:string +@283 = .sdata:0x804D57B0; // type:object size:0x7 scope:local data:string +@284 = .sdata:0x804D57B8; // type:object size:0x5 scope:local data:string +@756 = .sdata:0x804D57C0; // type:object size:0x2 scope:local data:string @307 = .sdata:0x804D57C8; // type:object size:0x7 scope:local data:string @308 = .sdata:0x804D57D0; // type:object size:0x5 scope:local data:string ifStock_804D57D8 = .sdata:0x804D57D8; // type:object size:0x7 scope:global data:string diff --git a/configure.py b/configure.py index b8357d2e3f..8d6d7c948e 100755 --- a/configure.py +++ b/configure.py @@ -1551,7 +1551,7 @@ def MatchingFor(*versions): [ Object(Matching, "melee/if/ifall.c"), Object(Matching, "melee/if/iftime.c"), - Object(Linkable, "melee/if/ifstatus.c"), + Object(Matching, "melee/if/ifstatus.c"), Object(Matching, "melee/if/if_2F6E.c"), Object(Matching, "melee/if/if_2F72.c"), Object(Linkable, "melee/if/ifstock.c"), diff --git a/src/melee/if/ifstatus.c b/src/melee/if/ifstatus.c index e0bbf886d1..02e1a10f26 100644 --- a/src/melee/if/ifstatus.c +++ b/src/melee/if/ifstatus.c @@ -64,6 +64,33 @@ char mrk_models_name[] = "DmgMrk_scene_models"; HudIndex ifStatus_HudInfo; +/// @todo .sdata2 order hack +#ifdef MUST_MATCH +static void sdata2_order(void) +{ + (void) 1.0F; + (void) 0.0F; + (void) 2.0F; + (void) U32_TO_F32; + (void) S32_TO_F32; + (void) 300.0F; + (void) 100.0F; + (void) 0.5069F; + (void) 0.6083F; + (void) 0.3041F; + (void) 1.2165F; + (void) 0.811F; + (void) 0.1014F; + (void) 1.5207F; + (void) -100.0F; + (void) 0.2028F; + (void) 0.5F; + (void) 0.65F; + (void) 0.1F; + (void) 0.25F; +} +#endif + HudIndex* ifStatus_GetHUDInfo(void) { return &ifStatus_HudInfo; From 0654f7a3c5a2ad127f29e527c3e67f78dfbbbd9b Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 16:19:27 -0700 Subject: [PATCH 16/64] Match hsd_8039F05C --- src/sysdolphin/baselib/generator.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 2db9f08d84..0e71ad71c3 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -11,6 +11,10 @@ #include #include +#ifdef MUST_MATCH +extern int psCmdListArray[65]; +#endif + /* 4D78F0 */ HSD_CObj* psCamera; /* 4D0E5C */ @@ -1067,7 +1071,11 @@ HSD_Generator* hsd_8039F05C(s32 linkNo, s32 bank, s32 idx) if (linkNo >= 8) { return NULL; } +#ifdef MUST_MATCH + if (idx >= psCmdListArray[bank]) { +#else if (idx >= psNumCmdList[bank]) { +#endif return NULL; } From ba876d3378ee60f30ee06c647e927dd5dafd4faa Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:03:40 -0700 Subject: [PATCH 17/64] Correct generator data ownership --- src/sysdolphin/baselib/generator.c | 25 +++++++++--------------- src/sysdolphin/baselib/particle.c | 25 ++++++++++++++++-------- src/sysdolphin/baselib/particle.h | 6 ++++++ src/sysdolphin/baselib/particle.static.h | 2 -- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 0e71ad71c3..f2cd7a1a0c 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -15,18 +15,11 @@ extern int psCmdListArray[65]; #endif -/* 4D78F0 */ HSD_CObj* psCamera; /* 4D0E5C */ -/* 4D78DA */ static u16 hsd_804D78DA; -/* 4D78E0 */ static u16 hsd_804D78E0; -/* 4D78E8 */ static u32 hsd_804D78E8; -/* 4D78EC */ static u32 hsd_804D78EC; -/* 4D78F0 */ static u32 hsd_804D78F0; -/* 4D78F4 */ static u32 hsd_804D78F4; /* 4D78F8 */ static u32 hsd_804D78F8; -/* 4D78FC */ HSD_Generator* hsd_804D78FC; -/* 4D7900 */ void (*hsd_804D7900)(HSD_Generator*); +/* 4D78FC */ HSD_Generator* hsd_804D78FC = NULL; +/* 4D7900 */ void (*hsd_804D7900)(HSD_Generator*) = NULL; /* 4D0F90 */ struct hsd_804D0F60_t hsd_804D0F90; @@ -469,7 +462,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Velocity-based rotation */ - if ((gen->type & 0xF) != 1 && vel_mag_sq > 0.0F) { + if ((gen->type & 0xF) != 1 && vel_mag_sq > 1.1920929e-7F) { vel_norm.x = gen->vel.x; vel_norm.y = gen->vel.y; vel_norm.z = gen->vel.z; @@ -865,14 +858,14 @@ f32 hsd_8039DAD4(HSD_Generator* gen) emit_pos.z -= 0.5F; /* Multiply by rect's 3x3 matrix */ - tmpvec.x = gen->aux.rect.yx * emit_pos.y + - gen->aux.rect.xx * emit_pos.x + + tmpvec.x = gen->aux.rect.xx * emit_pos.x + + gen->aux.rect.yx * emit_pos.y + gen->aux.rect.zx * emit_pos.z; - tmpvec.y = gen->aux.rect.yy * emit_pos.y + - gen->aux.rect.xy * emit_pos.x + + tmpvec.y = gen->aux.rect.xy * emit_pos.x + + gen->aux.rect.yy * emit_pos.y + gen->aux.rect.zy * emit_pos.z; - tmpvec.z = gen->aux.rect.yz * emit_pos.y + - gen->aux.rect.xz * emit_pos.x + + tmpvec.z = gen->aux.rect.xz * emit_pos.x + + gen->aux.rect.yz * emit_pos.y + gen->aux.rect.zz * emit_pos.z; PSMTXMultVec(rot_mtx, &tmpvec, &emit_pos); diff --git a/src/sysdolphin/baselib/particle.c b/src/sysdolphin/baselib/particle.c index 2872c20886..13a923a94d 100644 --- a/src/sysdolphin/baselib/particle.c +++ b/src/sysdolphin/baselib/particle.c @@ -32,8 +32,17 @@ typedef struct { #include #include -/* 4D78D8 */ u16 hsd_804D78D8; -/* 4D78DE */ u16 hsd_804D78DE; +/* 4D78D8 */ u16 hsd_804D78D8 = 0; +/* 4D78DA */ u16 hsd_804D78DA = 0; +/* 4D78DC */ static u16 numPeakParticles; +/* 4D78DE */ u16 hsd_804D78DE = 0; +/* 4D78E0 */ u16 hsd_804D78E0 = 0; +/* 4D78E2 */ static u16 hsd_804D78E2; +/* 4D78E4 */ static u16 hsd_804D78E4 = 0; +/* 4D78E8 */ u32 hsd_804D78E8 = 0; +/* 4D78EC */ u32 hsd_804D78EC = 0; +/* 4D78F0 */ HSD_CObj* psCamera = NULL; +/* 4D78F4 */ u32 hsd_804D78F4 = 0; static HSD_JObj* hsd_804D08E8[8]; /* 4D0908 */ HSD_Particle* hsd_804D0908[16]; /* 4D0948 */ HSD_Particle* hsd_804D0948[65]; @@ -335,7 +344,7 @@ void hsd_80398A08(u32 unused) for (i = 0; i < 16; i++) { hsd_804D0908[i] = NULL; } - hsd_804D78E2[0] = 0; + hsd_804D78E2 = 0; numPeakParticles = 0; for (i = 0; i < 0x41; i++) { psCmdListArray[i] = NULL; @@ -374,9 +383,9 @@ HSD_Particle* psGenerateParticle0(HSD_Particle** head, int linkNo, int bank, return NULL; } - hsd_804D78E2[0] += 1; - if (hsd_804D78E2[0] > numPeakParticles) { - numPeakParticles = hsd_804D78E2[0]; + hsd_804D78E2 += 1; + if (hsd_804D78E2 > numPeakParticles) { + numPeakParticles = hsd_804D78E2; } if (gp != NULL) { @@ -2867,7 +2876,7 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) /* Free particle */ hsd_8039D048(pp); HSD_ObjFree(&hsd_804D0F60.alloc_data, pp); - hsd_804D78E2[0]--; + hsd_804D78E2--; return next_pp; } } @@ -3011,7 +3020,7 @@ void hsd_8039D0A0(HSD_Generator* gen) } HSD_ObjFree(&data->alloc_data, prt); - hsd_804D78E2[0]--; + hsd_804D78E2--; } else { prev = prt; } diff --git a/src/sysdolphin/baselib/particle.h b/src/sysdolphin/baselib/particle.h index 37a00c7428..5b951b2722 100644 --- a/src/sysdolphin/baselib/particle.h +++ b/src/sysdolphin/baselib/particle.h @@ -36,6 +36,12 @@ psGenerateParticle0(HSD_Particle** head, int linkNo, int bank, u32 kind, /* 4D0D58 */ extern int psNumCmdList[65]; /* 4D0E5C */ extern HSD_PSCmdList** ptclref_804D0E5C[65]; /* 4D78D8 */ extern u16 hsd_804D78D8; +/* 4D78DA */ extern u16 hsd_804D78DA; /* 4D78DE */ extern u16 hsd_804D78DE; +/* 4D78E0 */ extern u16 hsd_804D78E0; +/* 4D78E8 */ extern u32 hsd_804D78E8; +/* 4D78EC */ extern u32 hsd_804D78EC; +/* 4D78F0 */ extern HSD_CObj* psCamera; +/* 4D78F4 */ extern u32 hsd_804D78F4; #endif diff --git a/src/sysdolphin/baselib/particle.static.h b/src/sysdolphin/baselib/particle.static.h index 209e753d43..6e2578cc0a 100644 --- a/src/sysdolphin/baselib/particle.static.h +++ b/src/sysdolphin/baselib/particle.static.h @@ -8,7 +8,5 @@ /* 4D78D0 */ static u32 hsd_804D78D0; /* 4D78D4 */ static int (**psCallback)(HSD_Particle* part); -/* 4D78DC */ static u16 numPeakParticles; -/* 4D78E2 */ static u16 hsd_804D78E2[2]; #endif From 4351b51745e3b9e3d8c16b4adea61c72edc646f8 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:22:21 -0700 Subject: [PATCH 18/64] Improve hsd_8039DAD4 register allocation --- src/sysdolphin/baselib/generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index f2cd7a1a0c..4e5a65af78 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -382,7 +382,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) f32 radius; f32 angle3; - angle1 = angle3 = 0.0F; + angle3 = angle1 = 0.0F; if (gen->count < 1.0F) { return gen->count; } From 66149f34ec9a4aa36e52b6aedff19fb52c56b287 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:29:53 -0700 Subject: [PATCH 19/64] Improve lbColl_80006E58 carrier allocation --- src/melee/lb/lbcollision.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index cd2115eb50..38202b2b3d 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1185,18 +1185,32 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hit_delta.z = hit_end->z - hit_start_copy.z; hurt_end_y = hurt_end->y; (void) hurt_end_y; +#ifdef MUST_MATCH + start_delta_y = hurt_start_copy.y; + hurt_delta_y = hurt_end_y - start_delta_y; + start_delta_y = hit_start_copy.y - start_delta_y; +#else start_delta_y = hit_start_copy.y - hurt_start_copy.y; hurt_delta_y = hurt_end_y - hurt_start_copy.y; +#endif hurt_end_x = hurt_end->x; (void) hurt_end_x; +#ifdef MUST_MATCH + hurt_delta_x = hurt_end_x - (start_delta_x = hurt_start_copy.x); +#else hurt_delta_x = hurt_end_x - hurt_start_copy.x; +#endif segment_dot = hit_delta.y * hurt_delta_y; hurt_len_sq = hurt_delta_y * hurt_delta_y; hit_start_mid_x = hit_delta.x * hit_delta.x; hit_start_mid_y = hit_delta.y * hit_delta.y; hurt_end_z = hurt_end->z; (void) hurt_end_z; +#ifdef MUST_MATCH + start_delta_x = hit_start_copy.x - start_delta_x; +#else start_delta_x = hit_start_copy.x - hurt_start_copy.x; +#endif hurt_delta_z = hurt_end_z - hurt_start_copy.z; segment_dot = (hit_delta.x * hurt_delta_x) + segment_dot; hit_start_min_z = 1.0F; From 63fc4fe6215d2b17a4c0638caf913b4225a2ded5 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:35:36 -0700 Subject: [PATCH 20/64] Use lbColl carrier spelling unconditionally --- src/melee/lb/lbcollision.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index 38202b2b3d..931f8f137d 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1185,32 +1185,19 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hit_delta.z = hit_end->z - hit_start_copy.z; hurt_end_y = hurt_end->y; (void) hurt_end_y; -#ifdef MUST_MATCH start_delta_y = hurt_start_copy.y; hurt_delta_y = hurt_end_y - start_delta_y; start_delta_y = hit_start_copy.y - start_delta_y; -#else - start_delta_y = hit_start_copy.y - hurt_start_copy.y; - hurt_delta_y = hurt_end_y - hurt_start_copy.y; -#endif hurt_end_x = hurt_end->x; (void) hurt_end_x; -#ifdef MUST_MATCH hurt_delta_x = hurt_end_x - (start_delta_x = hurt_start_copy.x); -#else - hurt_delta_x = hurt_end_x - hurt_start_copy.x; -#endif segment_dot = hit_delta.y * hurt_delta_y; hurt_len_sq = hurt_delta_y * hurt_delta_y; hit_start_mid_x = hit_delta.x * hit_delta.x; hit_start_mid_y = hit_delta.y * hit_delta.y; hurt_end_z = hurt_end->z; (void) hurt_end_z; -#ifdef MUST_MATCH start_delta_x = hit_start_copy.x - start_delta_x; -#else - start_delta_x = hit_start_copy.x - hurt_start_copy.x; -#endif hurt_delta_z = hurt_end_z - hurt_start_copy.z; segment_dot = (hit_delta.x * hurt_delta_x) + segment_dot; hit_start_min_z = 1.0F; From 417c8087ef2cc81e2843e8d473180496d3258192 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:40:46 -0700 Subject: [PATCH 21/64] Use matched generator bound unconditionally --- src/sysdolphin/baselib/generator.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 4e5a65af78..12fb88adba 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -11,9 +11,7 @@ #include #include -#ifdef MUST_MATCH extern int psCmdListArray[65]; -#endif /* 4D0E5C */ @@ -433,9 +431,9 @@ f32 hsd_8039DAD4(HSD_Generator* gen) rot_mtx[1][2] = vec.y; rot_mtx[2][2] = vec.z; - rot_mtx[0][3] = 0.0F; - rot_mtx[1][3] = 0.0F; rot_mtx[2][3] = 0.0F; + rot_mtx[1][3] = 0.0F; + rot_mtx[0][3] = 0.0F; } /* Billboard orientation: kind & 0x10000 */ @@ -1064,11 +1062,7 @@ HSD_Generator* hsd_8039F05C(s32 linkNo, s32 bank, s32 idx) if (linkNo >= 8) { return NULL; } -#ifdef MUST_MATCH if (idx >= psCmdListArray[bank]) { -#else - if (idx >= psNumCmdList[bank]) { -#endif return NULL; } From e392f478229867c3d2f7c651d13a74d4b9f616e0 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:43:03 -0700 Subject: [PATCH 22/64] Improve ifStock_802F98E8 allocation --- src/melee/if/ifstock.c | 129 ++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 48 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index fdbe5fd391..b6e1cabc32 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -571,17 +571,44 @@ static inline HSD_JObj* ifStock_802F98E8_get_x3C(unsigned char player) return ifStock_804A1378.player[player].x3C; } +struct IfStockMatchInfo { + u8 x4_b0 : 1; + u8 x4_b1 : 1; + u8 x4_b2 : 1; + u8 x4_b3 : 1; + u8 x4_b4 : 1; + u8 x4_b5 : 1; + u8 x4_b6 : 1; + u8 x4_b7 : 1; +}; + +static inline struct IfStockMatchInfo* +ifStock_802F98E8_get_match_info(lbl_8046B6A0_t* data, int player) +{ + return (struct IfStockMatchInfo*) ((u8*) &data->FighterMatchInfo[player] + + 4); +} + +static inline unsigned char* +ifStock_802F98E8_get_anim(unsigned char* user_data) +{ + return &user_data[5]; +} + void ifStock_802F98E8(unsigned char player, int b) { struct ifStock_804A1378* stock = &ifStock_804A1378; + HSD_GObj* gobj; HSD_JObj* jobj; unsigned char* user_data; + int* stocks; int i; - HSD_GObj* gobj; lbl_8046B6A0_t* ae44; + HSD_JObj* icon_jobj; if (stock->x0 != NULL) { user_data = ((struct IfStockData*) stock)[player].x0; - *(user_data += sizeof(struct IfStockDataOffset)) = player; + *(user_data += sizeof(struct IfStockDataOffset) - + sizeof(struct IfStockData)) = player; stock->x204[player].x0[1] = b; stock->x204[player].x0[2] = 1; if (stock->player[player].x0 != NULL) { @@ -592,8 +619,6 @@ void ifStock_802F98E8(unsigned char player, int b) if (gobj != NULL) { jobj = HSD_JObjLoadJoint((*stock->x0)->joint); if (jobj != NULL) { - unsigned char* data; - HSD_GObjObject_80390A70(gobj, HSD_GObj_JObjKind, jobj); GObj_SetupGXLink(gobj, fn_802F94E0, 11, 0); gm_8016895C(jobj, *stock->x0, 0); @@ -606,45 +631,43 @@ void ifStock_802F98E8(unsigned char player, int b) stock->player[player].x0 = gobj; ifStock_804A1378.player[player].coins = Player_GetCoins(player); - ifStock_804A1378.player[player].stocks = + *(stocks = &ifStock_804A1378.player[player].stocks) = Player_GetStocks(player); - if (ifStock_804A1378.player[player].stocks < 0) { - ifStock_804A1378.player[player].stocks = 1; + if (*stocks < 0) { + *stocks = 1; } - data = user_data; switch ((unsigned char) b) { case 0: HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x24, JOBJ_HIDDEN); - { - struct ifStock_804A1378_per_player* players = - stock->player; - if (players[player].stocks <= 5) { + if (*stocks <= 5) { HSD_JObjSetFlagsAll( ifStock_804A1378.player[player].x3C, JOBJ_HIDDEN); - for (i = 0; i < 7; i++, data++) { - jobj = + for (i = 0; i < 7; i++, user_data++) { + icon_jobj = ifStock_804A1378.player[player].x4[i + 1]; - if (i < ifStock_804A1378.player[player] - .stocks || + if (i < ifStock_804A1378.player[player].stocks || i >= 5) { - data[5] = 0; + user_data[5] = 0; if (i >= 5) { - HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + HSD_JObjSetFlagsAll(icon_jobj, + JOBJ_HIDDEN); } } else { - data[5] = 10; - HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + user_data[5] = 10; + HSD_JObjSetFlagsAll(icon_jobj, JOBJ_HIDDEN); } - HSD_JObjReqAnimAll(jobj, data[5]); - HSD_TObjReqAnimAll(jobj->u.dobj->mobj->tobj, - gm_80168BF8(player)); - HSD_AObjSetRate(jobj->u.dobj->mobj->tobj->aobj, - 0.0f); + HSD_JObjReqAnimAll( + icon_jobj, + *ifStock_802F98E8_get_anim(user_data)); + HSD_TObjReqAnimAll( + icon_jobj->u.dobj->mobj->tobj, + gm_80168BF8(player)); + HSD_AObjSetRate( + icon_jobj->u.dobj->mobj->tobj->aobj, 0.0f); } - } } break; case 1: @@ -652,24 +675,27 @@ void ifStock_802F98E8(unsigned char player, int b) JOBJ_HIDDEN); HSD_JObjSetFlagsAll(ifStock_802F98E8_get_x3C(player), JOBJ_HIDDEN); - for (i = 0; i < 7; i++, data++) { - jobj = ifStock_804A1378.player[player].x4[i + 1]; + for (i = 0; i < 7; i++, user_data++) { + icon_jobj = + ifStock_804A1378.player[player].x4[i + 1]; if (i == 0) { - data[5] = 0; + user_data[5] = 0; } else { - data[5] = 10; + user_data[5] = 10; } if (i < 5) { - HSD_JObjReqAnimAll(jobj, data[5]); - HSD_TObjReqAnimAll(jobj->u.dobj->mobj->tobj, + HSD_JObjReqAnimAll( + icon_jobj, + *ifStock_802F98E8_get_anim(user_data)); + HSD_TObjReqAnimAll(icon_jobj->u.dobj->mobj->tobj, gm_80168BF8(player)); - HSD_AObjSetRate(jobj->u.dobj->mobj->tobj->aobj, - 0.0f); + HSD_AObjSetRate( + icon_jobj->u.dobj->mobj->tobj->aobj, 0.0f); if (i != 0) { - HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + HSD_JObjSetFlagsAll(icon_jobj, JOBJ_HIDDEN); } } else { - HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + HSD_JObjSetFlagsAll(icon_jobj, JOBJ_HIDDEN); } } break; @@ -684,39 +710,46 @@ void ifStock_802F98E8(unsigned char player, int b) JOBJ_HIDDEN); HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x3C, JOBJ_HIDDEN); - for (i = 0; i < 7; i++, data++) { - jobj = ifStock_804A1378.player[player].x4[i + 1]; + for (i = 0; i < 7; i++, user_data++) { + icon_jobj = + ifStock_804A1378.player[player].x4[i + 1]; if (i == 0) { - data[5] = 0; + user_data[5] = 0; } else { - data[5] = 10; + user_data[5] = 10; } if (i < 5) { - HSD_JObjReqAnimAll(jobj, data[5]); - HSD_TObjReqAnimAll(jobj->u.dobj->mobj->tobj, + HSD_JObjReqAnimAll( + icon_jobj, + *ifStock_802F98E8_get_anim(user_data)); + HSD_TObjReqAnimAll(icon_jobj->u.dobj->mobj->tobj, gm_80168BF8(player)); - HSD_AObjSetRate(jobj->u.dobj->mobj->tobj->aobj, - 0.0f); + HSD_AObjSetRate( + icon_jobj->u.dobj->mobj->tobj->aobj, 0.0f); if (i != 0) { - HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + HSD_JObjSetFlagsAll(icon_jobj, JOBJ_HIDDEN); } } else { - HSD_JObjSetFlagsAll(jobj, JOBJ_HIDDEN); + HSD_JObjSetFlagsAll(icon_jobj, JOBJ_HIDDEN); } } break; } HSD_JObjAnimAll(jobj); ae44 = gm_16AE_GetUnkData_1(); - if (ae44->FighterMatchInfo[player].x4_b1) { + { + struct IfStockMatchInfo* match_info = + ifStock_802F98E8_get_match_info(ae44, player); + if (match_info->x4_b1) { GXColor c = { 0x08, 0x08, 0x08, 0x80 }; GXColor* color = &c; ifStock_802FB4EC(player, color); - } else if (ae44->FighterMatchInfo[player].x4_b0) { + } else if (match_info->x4_b0) { GXColor c = { 0x3C, 0x3C, 0x46, 0x80 }; GXColor* color = &c; ifStock_802FB4EC(player, color); } + } fn_802F9410(gobj); // inlined } else { HSD_GObjPLink_80390228(gobj); From 1ecd5bc94ba05ece8e213ba457c2d42875889ce4 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:44:09 -0700 Subject: [PATCH 23/64] Improve hsd_8039DAD4 expression order --- src/sysdolphin/baselib/generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 12fb88adba..7a1a6cc925 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -837,7 +837,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) if (rnd < t1) { emit_pos.z = emit_pos.z > 0.5F ? 1.0F : 0.0F; } else { - f32 t2 = 1.0F - c2 * r0 * a2; + f32 t2 = 1.0F - r0 * (c2 * a2); if (rnd > t2) { emit_pos.y = emit_pos.y > 0.5F ? 1.0F : 0.0F; } else { From 82775ece547bfa1ac84f754e9be4de1decc0055d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:46:53 -0700 Subject: [PATCH 24/64] Correct particle command array types --- src/sysdolphin/baselib/particle.c | 28 ++++++++++++++-------------- src/sysdolphin/baselib/particle.h | 3 ++- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/sysdolphin/baselib/particle.c b/src/sysdolphin/baselib/particle.c index 13a923a94d..138002ee7d 100644 --- a/src/sysdolphin/baselib/particle.c +++ b/src/sysdolphin/baselib/particle.c @@ -48,8 +48,8 @@ static HSD_JObj* hsd_804D08E8[8]; /* 4D0948 */ HSD_Particle* hsd_804D0948[65]; /* 4D0A4C */ HSD_PSFormGroup** psFormGroupArray[65]; /* 4D0B50 */ HSD_PSTexGroup** psTexGroupArray[65]; -/* 4D0C54 */ int psNumCmdList[65]; -/* 4D0D58 */ HSD_PSCmdList** psCmdListArray[65]; +/* 4D0C54 */ HSD_PSFormGroup** psNumCmdList[65]; +/* 4D0D58 */ int psCmdListArray[65]; /* 4D0E5C */ HSD_PSCmdList** ptclref_804D0E5C[65]; /* 4D0F60 */ struct hsd_804D0F60_t hsd_804D0F60; @@ -347,11 +347,11 @@ void hsd_80398A08(u32 unused) hsd_804D78E2 = 0; numPeakParticles = 0; for (i = 0; i < 0x41; i++) { - psCmdListArray[i] = NULL; + psCmdListArray[i] = 0; psFormGroupArray[i] = NULL; ptclref_804D0E5C[i] = NULL; psTexGroupArray[i] = NULL; - psNumCmdList[i] = 0; + psNumCmdList[i] = NULL; hsd_804D0948[i] = NULL; } psCallback = NULL; @@ -1062,10 +1062,10 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) child = NULL; } else if (bank >= 65) { child = NULL; - } else if (idx >= psNumCmdList[bank]) { + } else if (idx >= psCmdListArray[bank]) { child = NULL; } else { - cl = psCmdListArray[bank][idx]; + cl = ptclref_804D0E5C[bank][idx]; if (cl == NULL) { child = NULL; } else { @@ -1119,10 +1119,10 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) child = NULL; } else if (bank >= 65) { child = NULL; - } else if (idx >= psNumCmdList[bank]) { + } else if (idx >= psCmdListArray[bank]) { child = NULL; } else { - cl = psCmdListArray[bank][idx]; + cl = ptclref_804D0E5C[bank][idx]; if (cl == NULL) { child = NULL; } else { @@ -1430,10 +1430,10 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) child = NULL; } else if (bank >= 65) { child = NULL; - } else if (idx >= psNumCmdList[bank]) { + } else if (idx >= psCmdListArray[bank]) { child = NULL; } else { - cl = psCmdListArray[bank][idx]; + cl = ptclref_804D0E5C[bank][idx]; if (cl == NULL) { child = NULL; } else { @@ -1728,10 +1728,10 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) child = NULL; } else if (bank >= 65) { child = NULL; - } else if (idx >= psNumCmdList[bank]) { + } else if (idx >= psCmdListArray[bank]) { child = NULL; } else { - cl = psCmdListArray[bank][idx]; + cl = ptclref_804D0E5C[bank][idx]; if (cl == NULL) { child = NULL; } else { @@ -1790,10 +1790,10 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) child = NULL; } else if (bank >= 65) { child = NULL; - } else if (idx >= psNumCmdList[bank]) { + } else if (idx >= psCmdListArray[bank]) { child = NULL; } else { - cl = psCmdListArray[bank][idx]; + cl = ptclref_804D0E5C[bank][idx]; if (cl == NULL) { child = NULL; } else { diff --git a/src/sysdolphin/baselib/particle.h b/src/sysdolphin/baselib/particle.h index 5b951b2722..bb7f044382 100644 --- a/src/sysdolphin/baselib/particle.h +++ b/src/sysdolphin/baselib/particle.h @@ -33,7 +33,8 @@ psGenerateParticle0(HSD_Particle** head, int linkNo, int bank, u32 kind, /* 39CF4C */ void hsd_8039CF4C(s32, HSD_JObj*); /* 39D048 */ void hsd_8039D048(void* particle); /* 4D0B50 */ extern HSD_PSTexGroup** psTexGroupArray[65]; -/* 4D0D58 */ extern int psNumCmdList[65]; +/* 4D0C54 */ extern HSD_PSFormGroup** psNumCmdList[65]; +/* 4D0D58 */ extern int psCmdListArray[65]; /* 4D0E5C */ extern HSD_PSCmdList** ptclref_804D0E5C[65]; /* 4D78D8 */ extern u16 hsd_804D78D8; /* 4D78DA */ extern u16 hsd_804D78DA; From 5a103ff24b670f2513958daeed6e95495d8f071b Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 17:47:13 -0700 Subject: [PATCH 25/64] Use particle command count declaration --- src/sysdolphin/baselib/generator.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 7a1a6cc925..0098f7483a 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -11,8 +11,6 @@ #include #include -extern int psCmdListArray[65]; - /* 4D0E5C */ /* 4D78F8 */ static u32 hsd_804D78F8; From 5bca9e05ba750a2acb64bba56fffbb92d56cf8fa Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 18:05:53 -0700 Subject: [PATCH 26/64] Format ifStock match reconstruction --- src/melee/if/ifstock.c | 74 ++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index b6e1cabc32..08fab0947a 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -608,7 +608,7 @@ void ifStock_802F98E8(unsigned char player, int b) if (stock->x0 != NULL) { user_data = ((struct IfStockData*) stock)[player].x0; *(user_data += sizeof(struct IfStockDataOffset) - - sizeof(struct IfStockData)) = player; + sizeof(struct IfStockData)) = player; stock->x204[player].x0[1] = b; stock->x204[player].x0[2] = 1; if (stock->player[player].x0 != NULL) { @@ -641,33 +641,31 @@ void ifStock_802F98E8(unsigned char player, int b) HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x24, JOBJ_HIDDEN); if (*stocks <= 5) { - HSD_JObjSetFlagsAll( - ifStock_804A1378.player[player].x3C, - JOBJ_HIDDEN); - for (i = 0; i < 7; i++, user_data++) { - icon_jobj = - ifStock_804A1378.player[player].x4[i + 1]; - if (i < ifStock_804A1378.player[player].stocks || - i >= 5) - { - user_data[5] = 0; - if (i >= 5) { - HSD_JObjSetFlagsAll(icon_jobj, - JOBJ_HIDDEN); - } - } else { - user_data[5] = 10; - HSD_JObjSetFlagsAll(icon_jobj, JOBJ_HIDDEN); + HSD_JObjSetFlagsAll( + ifStock_804A1378.player[player].x3C, JOBJ_HIDDEN); + for (i = 0; i < 7; i++, user_data++) { + icon_jobj = + ifStock_804A1378.player[player].x4[i + 1]; + if (i < ifStock_804A1378.player[player].stocks || + i >= 5) + { + user_data[5] = 0; + if (i >= 5) { + HSD_JObjSetFlagsAll(icon_jobj, + JOBJ_HIDDEN); } - HSD_JObjReqAnimAll( - icon_jobj, - *ifStock_802F98E8_get_anim(user_data)); - HSD_TObjReqAnimAll( - icon_jobj->u.dobj->mobj->tobj, - gm_80168BF8(player)); - HSD_AObjSetRate( - icon_jobj->u.dobj->mobj->tobj->aobj, 0.0f); + } else { + user_data[5] = 10; + HSD_JObjSetFlagsAll(icon_jobj, JOBJ_HIDDEN); } + HSD_JObjReqAnimAll( + icon_jobj, + *ifStock_802F98E8_get_anim(user_data)); + HSD_TObjReqAnimAll(icon_jobj->u.dobj->mobj->tobj, + gm_80168BF8(player)); + HSD_AObjSetRate( + icon_jobj->u.dobj->mobj->tobj->aobj, 0.0f); + } } break; case 1: @@ -676,8 +674,7 @@ void ifStock_802F98E8(unsigned char player, int b) HSD_JObjSetFlagsAll(ifStock_802F98E8_get_x3C(player), JOBJ_HIDDEN); for (i = 0; i < 7; i++, user_data++) { - icon_jobj = - ifStock_804A1378.player[player].x4[i + 1]; + icon_jobj = ifStock_804A1378.player[player].x4[i + 1]; if (i == 0) { user_data[5] = 0; } else { @@ -711,8 +708,7 @@ void ifStock_802F98E8(unsigned char player, int b) HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x3C, JOBJ_HIDDEN); for (i = 0; i < 7; i++, user_data++) { - icon_jobj = - ifStock_804A1378.player[player].x4[i + 1]; + icon_jobj = ifStock_804A1378.player[player].x4[i + 1]; if (i == 0) { user_data[5] = 0; } else { @@ -740,15 +736,15 @@ void ifStock_802F98E8(unsigned char player, int b) { struct IfStockMatchInfo* match_info = ifStock_802F98E8_get_match_info(ae44, player); - if (match_info->x4_b1) { - GXColor c = { 0x08, 0x08, 0x08, 0x80 }; - GXColor* color = &c; - ifStock_802FB4EC(player, color); - } else if (match_info->x4_b0) { - GXColor c = { 0x3C, 0x3C, 0x46, 0x80 }; - GXColor* color = &c; - ifStock_802FB4EC(player, color); - } + if (match_info->x4_b1) { + GXColor c = { 0x08, 0x08, 0x08, 0x80 }; + GXColor* color = &c; + ifStock_802FB4EC(player, color); + } else if (match_info->x4_b0) { + GXColor c = { 0x3C, 0x3C, 0x46, 0x80 }; + GXColor* color = &c; + ifStock_802FB4EC(player, color); + } } fn_802F9410(gobj); // inlined } else { From f973287d9a494e0846cb52474171b0f754747756 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 18:13:21 -0700 Subject: [PATCH 27/64] Remove stale particle data shadows --- src/sysdolphin/baselib/hsd_3915.static.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sysdolphin/baselib/hsd_3915.static.h b/src/sysdolphin/baselib/hsd_3915.static.h index fbeac46329..e7448a4ff7 100644 --- a/src/sysdolphin/baselib/hsd_3915.static.h +++ b/src/sysdolphin/baselib/hsd_3915.static.h @@ -23,11 +23,6 @@ typedef struct { static PerfDispItem hsd_804CE3F8[6]; -extern int psNumTexGroup[65]; -static HSD_PSFormGroup** psFormGroupArray[65]; - -/* 4D0908 */ static void* hsd_804D0908[146]; -/* 4D0C54 */ static HSD_PSCmdList** psCmdListArray[65]; /* 4D7850 */ static HSD_SList* hsd_804D7850; /* 4D7858 */ static f32 hsd_804D7858; /* 4D785C */ static f32 hsd_804D785C; From 18db766234dcec6ef6215832aa52f48511a4fc68 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 18:17:50 -0700 Subject: [PATCH 28/64] Drop unused particle include --- src/sysdolphin/baselib/hsd_3915.static.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sysdolphin/baselib/hsd_3915.static.h b/src/sysdolphin/baselib/hsd_3915.static.h index e7448a4ff7..d4f7fef606 100644 --- a/src/sysdolphin/baselib/hsd_3915.static.h +++ b/src/sysdolphin/baselib/hsd_3915.static.h @@ -1,5 +1,3 @@ -#include - // types // .bss From 3061e1b7511437099948fe4c127760a87a3e17a1 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 18:20:48 -0700 Subject: [PATCH 29/64] Match ifStock color stack layout --- src/melee/if/ifstock.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 08fab0947a..3facea2863 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -595,6 +595,9 @@ ifStock_802F98E8_get_anim(unsigned char* user_data) return &user_data[5]; } +static const GXColor ifStock_802F98E8_color1 = { 0x08, 0x08, 0x08, 0x80 }; +static const GXColor ifStock_802F98E8_color2 = { 0x3C, 0x3C, 0x46, 0x80 }; + void ifStock_802F98E8(unsigned char player, int b) { struct ifStock_804A1378* stock = &ifStock_804A1378; @@ -605,6 +608,8 @@ void ifStock_802F98E8(unsigned char player, int b) int i; lbl_8046B6A0_t* ae44; HSD_JObj* icon_jobj; + GXColor c2; + GXColor c1; if (stock->x0 != NULL) { user_data = ((struct IfStockData*) stock)[player].x0; *(user_data += sizeof(struct IfStockDataOffset) - @@ -737,12 +742,14 @@ void ifStock_802F98E8(unsigned char player, int b) struct IfStockMatchInfo* match_info = ifStock_802F98E8_get_match_info(ae44, player); if (match_info->x4_b1) { - GXColor c = { 0x08, 0x08, 0x08, 0x80 }; - GXColor* color = &c; + GXColor* color; + c1 = ifStock_802F98E8_color1; + color = &c1; ifStock_802FB4EC(player, color); } else if (match_info->x4_b0) { - GXColor c = { 0x3C, 0x3C, 0x46, 0x80 }; - GXColor* color = &c; + GXColor* color; + c2 = ifStock_802F98E8_color2; + color = &c2; ifStock_802FB4EC(player, color); } } From 75c6351db1c278a2a3667e02b25b5b902654020e Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 18:34:19 -0700 Subject: [PATCH 30/64] Preserve hsd_3915 link metadata --- src/sysdolphin/baselib/hsd_3915.static.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sysdolphin/baselib/hsd_3915.static.h b/src/sysdolphin/baselib/hsd_3915.static.h index d4f7fef606..2b82a56005 100644 --- a/src/sysdolphin/baselib/hsd_3915.static.h +++ b/src/sysdolphin/baselib/hsd_3915.static.h @@ -1,3 +1,5 @@ +#include // IWYU pragma: keep + // types // .bss From 0f5ce178f3e537d909b6220d25788ab8c3d8dfed Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 18:41:24 -0700 Subject: [PATCH 31/64] Reuse lbColl scalar lifetimes --- src/melee/lb/lbcollision.c | 56 +++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index 931f8f137d..093ab11888 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1045,7 +1045,7 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float hurt_param_from_hit_start; Mtx inv_hurt_mtx; float hurt_delta_z; - float hit_start_max_x; + float x_work; float hit_end_min_x; float hit_start_min_x; float hit_end_max_x; @@ -1055,7 +1055,7 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float contact_lerp; float broadphase_radius; float hit_end_mid_z; - float hit_start_max_y; + float y_work; float hit_end_min_y; float hit_start_min_y; float hit_end_max_y; @@ -1090,8 +1090,8 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, s32 is_hit_segment_degenerate; s32 is_parallel; s32 is_zero_distance; - float hurt_delta_x; - float hurt_delta_y; + float hurt_start_y; + float hurt_start_z; PAD_STACK(40); // Fast reject when the expanded hit segment AABB misses both hurt @@ -1101,10 +1101,8 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hurt_start_copy = *hurt_start; hit_end_x = hit_end->x; if (hit_start_copy.x > hit_end_x) { - hit_start_max_x = hit_start_copy.x + broadphase_radius; - if ((hit_start_max_x < hurt_start_copy.x) && - (hit_start_max_x < hurt_end->x)) - { + x_work = hit_start_copy.x + broadphase_radius; + if ((x_work < hurt_start_copy.x) && (x_work < hurt_end->x)) { return 0; } hit_end_min_x = hit_end_x - broadphase_radius; @@ -1127,10 +1125,8 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, } block_13: if (hit_start_copy.y > (hit_end_y = hit_end->y)) { - hit_start_max_y = hit_start_copy.y + broadphase_radius; - if ((hit_start_max_y < hurt_start_copy.y) && - (hit_start_max_y < hurt_end->y)) - { + y_work = hit_start_copy.y + broadphase_radius; + if ((y_work < hurt_start_copy.y) && (y_work < hurt_end->y)) { return 0; } hit_end_min_y = hit_end_y - broadphase_radius; @@ -1185,38 +1181,37 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hit_delta.z = hit_end->z - hit_start_copy.z; hurt_end_y = hurt_end->y; (void) hurt_end_y; - start_delta_y = hurt_start_copy.y; - hurt_delta_y = hurt_end_y - start_delta_y; - start_delta_y = hit_start_copy.y - start_delta_y; + start_delta_y = hurt_start_y = hurt_start_copy.y; + y_work = hurt_end_y - hurt_start_y; + start_delta_y = hit_start_copy.y - hurt_start_y; hurt_end_x = hurt_end->x; (void) hurt_end_x; - hurt_delta_x = hurt_end_x - (start_delta_x = hurt_start_copy.x); - segment_dot = hit_delta.y * hurt_delta_y; - hurt_len_sq = hurt_delta_y * hurt_delta_y; + x_work = hurt_end_x - (start_delta_x = hurt_start_copy.x); + segment_dot = hit_delta.y * y_work; + hurt_len_sq = y_work * y_work; hit_start_mid_x = hit_delta.x * hit_delta.x; hit_start_mid_y = hit_delta.y * hit_delta.y; hurt_end_z = hurt_end->z; (void) hurt_end_z; start_delta_x = hit_start_copy.x - start_delta_x; - hurt_delta_z = hurt_end_z - hurt_start_copy.z; - segment_dot = (hit_delta.x * hurt_delta_x) + segment_dot; + hurt_delta_z = hurt_end_z - (hurt_start_z = hurt_start_copy.z); + segment_dot = (hit_delta.x * x_work) + segment_dot; hit_start_min_z = 1.0F; - hurt_len_sq = (hurt_delta_x * hurt_delta_x) + hurt_len_sq; + hurt_len_sq = (x_work * x_work) + hurt_len_sq; segment_dot = (hit_delta.z * hurt_delta_z) + segment_dot; hurt_len_sq = (hurt_delta_z * hurt_delta_z) + hurt_len_sq; { float hit_delta_z_sq = hit_delta.z * hit_delta.z; hit_start_mid_z = hit_delta_z_sq; } - start_delta_z = hit_start_copy.z - hurt_start_copy.z; + start_delta_z = hit_start_copy.z - hurt_start_z; hit_len_sq = hit_start_mid_z + (hit_start_mid_y + hit_start_mid_x); hit_start_dot = hit_delta.y * start_delta_y; { float hit_start_dot_x = hit_delta.x * start_delta_x; hit_start_dot = hit_start_dot_x + hit_start_dot; } - hurt_start_dot = - (hurt_delta_x * start_delta_x) + (hurt_delta_y * start_delta_y); + hurt_start_dot = (x_work * start_delta_x) + (y_work * start_delta_y); hurt_start_dot = (hurt_delta_z * start_delta_z) + hurt_start_dot; hit_start_dot = (hit_delta.z * start_delta_z) + hit_start_dot; closest_denom = (hurt_len_sq * hit_len_sq) - (segment_dot * segment_dot); @@ -1253,13 +1248,12 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, if (is_parallel != 0) { // For parallel axes, project the hit endpoint nearer the hurt // midpoint. - hurt_mid_y = - (float) ((0.5 * (f64) hurt_delta_y) + (f64) hurt_start_copy.y); + hurt_mid_y = (float) ((0.5 * (f64) y_work) + (f64) hurt_start_y); hurt_mid_x = - (float) ((0.5 * (f64) hurt_delta_x) + (f64) hurt_start_copy.x); + (float) ((0.5 * (f64) x_work) + (f64) hurt_start_copy.x); hit_start_mid_y = hit_start_copy.y - hurt_mid_y; hurt_mid_z = - (float) ((0.5 * (f64) hurt_delta_z) + (f64) hurt_start_copy.z); + (float) ((0.5 * (f64) hurt_delta_z) + (f64) hurt_start_z); hit_end_mid_y = hit_end->y - hurt_mid_y; hit_start_mid_x = hit_start_copy.x - hurt_mid_x; hit_end_mid_x = hit_end->x - hurt_mid_x; @@ -1371,9 +1365,9 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hit_closest->x = (hit_delta.x * hit_param) + hit_start_copy.x; hit_closest->y = (hit_delta.y * hit_param) + hit_start_copy.y; hit_closest->z = (hit_delta.z * hit_param) + hit_start_copy.z; - hurt_closest->x = (hurt_delta_x * hurt_param) + hurt_start_copy.x; - hurt_closest->y = (hurt_delta_y * hurt_param) + hurt_start_copy.y; - hurt_closest->z = (hurt_delta_z * hurt_param) + hurt_start_copy.z; + hurt_closest->x = (x_work * hurt_param) + hurt_start_copy.x; + hurt_closest->y = (y_work * hurt_param) + hurt_start_y; + hurt_closest->z = (hurt_delta_z * hurt_param) + hurt_start_z; closest_delta_y = hit_closest->y - hurt_closest->y; closest_delta_x = hit_closest->x - hurt_closest->x; closest_delta_z = hit_closest->z - hurt_closest->z; From 434be024673a1b081fb1ae4fb54f68d47fd7289d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 18:56:28 -0700 Subject: [PATCH 32/64] Guard lbColl match-only padding --- src/melee/lb/lbcollision.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index 093ab11888..d4dcdd040a 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1021,7 +1021,9 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, Vec3 hit_start_copy; Vec3 hurt_start_copy; Vec3 hit_delta; +#ifdef MUST_MATCH u8 operand_pad[4]; +#endif float start_delta_z; float hit_start_dot; float scaled_hurt_radius; From 9d176c51523a323e9a0da4dfe478edecacd1b4b0 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:09:45 -0700 Subject: [PATCH 33/64] Refine ftCo afterimage allocation --- src/melee/ft/ftafterimage.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/melee/ft/ftafterimage.c b/src/melee/ft/ftafterimage.c index a679257f27..452039cead 100644 --- a/src/melee/ft/ftafterimage.c +++ b/src/melee/ft/ftafterimage.c @@ -30,10 +30,13 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) { Fighter* fp; itSword_UnkBytes* params; +#ifdef MUST_MATCH + UNUSED f32 inner_pad[1]; +#endif f32 cumDist[3]; AfterimageVtx vtx_buf[152]; + f32* distPtr; f32 d2; - s32 numSubdiv; if (arg1 != 2) { return; @@ -95,14 +98,14 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) break; case FTKIND_LINK: case FTKIND_CLINK: { - ftLk_DatAttrs* da = fp->dat_attrs; - params = (itSword_UnkBytes*) &da->x64; + params = + (itSword_UnkBytes*) &((ftLk_DatAttrs*) fp->dat_attrs)->x64; break; } case FTKIND_MARS: case FTKIND_EMBLEM: { - MarsAttributes* da = fp->dat_attrs; - params = (itSword_UnkBytes*) &da->x78; + params = + (itSword_UnkBytes*) &((MarsAttributes*) fp->dat_attrs)->x78; break; } default: @@ -111,7 +114,6 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) } { - s32 nextIdx; f32 x20F8 = fp->x20F8; f32 x20FC = fp->x20FC; s32 ringIdx; @@ -119,7 +121,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) f32* dp; Vec3 prevPos, delta, crossProd, tempDir; - PAD_STACK(0x14); + PAD_STACK(0x1C); { s32 idx = fp->x2101_bits_0to6; @@ -141,6 +143,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) prevPos.x = prevPos.y = prevPos.z = 0.0f; for (i = (s8) (u8) fp->x2100 - 1; i >= 0; i--) { + s32 nextIdx; struct Fighter_x20B0_t* entry = &fp->x20B0[curIdx]; delta.x = entry->xC.x * x20FC + entry->x0.x - prevPos.x; @@ -171,7 +174,8 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) { s32 remaining; - f32* distPtr; + struct Fighter_x20B0_t* curEntry; + s32 nextIdx; s32 numVerts; f32 scaleDiff; s32 curIdx2; @@ -207,7 +211,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) s32 alpha; struct Fighter_x20B0_t* nextEntry; - struct Fighter_x20B0_t* curEntry = &fp->x20B0[curIdx2]; + curEntry = &fp->x20B0[curIdx2]; outerScale = interpFactor * outerDiff + blendedOuter; innerScale = interpFactor * innerDiff + blendedInner; numVerts += 2; @@ -236,6 +240,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) if (remaining != 0) { s32 nextRingIdx; + s32 numSubdiv; if (curIdx2 != 0) { nextRingIdx = curIdx2 - 1; From 56449611720e1330c0a40eed9e61781a238617f5 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:15:57 -0700 Subject: [PATCH 34/64] Refine generator scalar lifetimes --- src/sysdolphin/baselib/generator.c | 98 ++++++++++++++---------------- 1 file changed, 44 insertions(+), 54 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 0098f7483a..0d61456b0d 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -365,8 +365,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) Vec3 cross1; Vec3 vel_norm; Mtx trig_mtx; - f64 eps; - f32 vel_mag_sq; f32 angle1; f32 sin_az; f32 cos_az; @@ -383,16 +381,14 @@ f32 hsd_8039DAD4(HSD_Generator* gen) return gen->count; } - vel_mag_sq = angle3; - /* Copy velocity */ vel_copy.x = gen->vel.x; vel_copy.y = gen->vel.y; vel_copy.z = gen->vel.z; /* Compute velocity magnitude */ - vel_mag_sq = sqrtf(vel_copy.z * vel_copy.z + - (vel_copy.x * vel_copy.x + vel_copy.y * vel_copy.y)); + radius = sqrtf(vel_copy.z * vel_copy.z + + (vel_copy.x * vel_copy.x + vel_copy.y * vel_copy.y)); /* Initialize rotation matrix */ PSMTXIdentity(rot_mtx); @@ -458,7 +454,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Velocity-based rotation */ - if ((gen->type & 0xF) != 1 && vel_mag_sq > 1.1920929e-7F) { + if ((gen->type & 0xF) != 1 && radius > 1.1920929e-7F) { vel_norm.x = gen->vel.x; vel_norm.y = gen->vel.y; vel_norm.z = gen->vel.z; @@ -497,7 +493,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) { f32 cos_el = cosf(elevation); f32 neg_cos_az = -cos_az; - f32 neg_sin_az_s = -sin_az; trig_mtx[0][0] = cos_el; trig_mtx[0][1] = 0.0F; @@ -507,13 +502,14 @@ f32 hsd_8039DAD4(HSD_Generator* gen) trig_mtx[1][1] = sin_az; trig_mtx[1][2] = cos_az * cos_el; trig_mtx[1][3] = 0.0F; - trig_mtx[2][0] = neg_sin_az_s * sin_el; + trig_mtx[2][0] = -sin_az * sin_el; trig_mtx[2][1] = neg_cos_az; trig_mtx[2][2] = sin_az * cos_el; trig_mtx[2][3] = 0.0F; } PSMTXConcat(rot_mtx, trig_mtx, rot_mtx); } + elevation = radius; /* Type 2: extract Euler angles from rotation matrix */ if ((gen->type & 0xF) == 2) { @@ -553,8 +549,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 4: { f32 min_a = gen->aux.disc.minAngle; f32 rnd = HSD_Randf(); - f32 range = gen->aux.disc.maxAngle - min_a; - angle_step = range / (f32) (s32) gen->count; + angle_step = (gen->aux.disc.maxAngle - min_a) / + (f32) (s32) gen->count; cur_angle = angle_step * rnd + min_a; break; } @@ -562,8 +558,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 7: { f32 min_a = gen->aux.cone.minAngle; f32 rnd = HSD_Randf(); - f32 range = gen->aux.cone.maxAngle - min_a; - angle_step = range / (f32) (s32) gen->count; + angle_step = (gen->aux.cone.maxAngle - min_a) / + (f32) (s32) gen->count; cur_angle = angle_step * rnd + min_a; break; } @@ -577,7 +573,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Main particle emission loop */ - eps = 0.001F; while (gen->count >= 1.0F) { switch (gen->type & 0xF) { case 0: /* point, disc, cone, sphere, etc. */ @@ -623,9 +618,9 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } { f32 rnd = HSD_Randf(); - f32 range = gen->aux.cone.maxAngle - cur_angle; + cone_angle = gen->aux.cone.maxAngle - cur_angle; + cur_angle = cone_angle * rnd + cur_angle; cone_angle = radius * gen->angle; - cur_angle = range * rnd + cur_angle; } tmp = sin_az; *(s32*) &tmp &= 0x7FFFFFFF; @@ -654,8 +649,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } { f32 rnd = HSD_Randf(); - f32 range = gen->aux.disc.maxAngle - cur_angle; - cur_angle = range * rnd + cur_angle; + cone_angle = gen->aux.disc.maxAngle - cur_angle; + cur_angle = cone_angle * rnd + cur_angle; cone_angle = (f32) (M_PI_2 + gen->angle); } } @@ -669,9 +664,9 @@ f32 hsd_8039DAD4(HSD_Generator* gen) cur_angle = gen->aux.disc.minAngle; { f32 rnd = HSD_Randf(); - f32 range = gen->aux.disc.maxAngle - cur_angle; cone_angle = radius * gen->angle; - cur_angle = range * rnd + cur_angle; + sin_el = gen->aux.disc.maxAngle - cur_angle; + cur_angle = sin_el * rnd + cur_angle; } } break; @@ -695,10 +690,10 @@ f32 hsd_8039DAD4(HSD_Generator* gen) /* Compute velocity direction from cone angle */ { - f32 sin_ca = vel_mag_sq * sinf(cone_angle); + f32 sin_ca = elevation * sinf(cone_angle); vec.x = sin_ca * cosf(cur_angle); vec.y = sin_ca * sinf(cur_angle); - vec.z = vel_mag_sq * cosf(cone_angle); + vec.z = elevation * cosf(cone_angle); } /* Shape 3: scale velocity by radius factor */ @@ -759,7 +754,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) f32 rnd = HSD_Randf(); cur_angle = (f32) (2.0 * (M_PI * (f64) rnd)); } - gen->aux.line.x2 = vel_mag_sq; + gen->aux.line.x2 = elevation; hsd_80398F0C(gen->linkNo, gen->bank, gen->kind | 4, gen->texGroup, (s32) gen->cmdList, gen->life, 0, (s32) gen, 0.0F, 0.0F, 0.0F, cur_angle, sin_az, 0.0F, gen->size, @@ -786,8 +781,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) { f32 rnd = HSD_Randf(); f32 a2 = gen->aux.rect.x; - f32 b2 = gen->aux.rect.y; - if (rnd > a2 / (a2 + b2)) { + if (rnd > a2 / (a2 + gen->aux.rect.y)) { emit_pos.y = emit_pos.y > 0.5F ? 1.0F : 0.0F; } else { emit_pos.x = emit_pos.x > 0.5F ? 1.0F : 0.0F; @@ -801,8 +795,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) { f32 rnd = HSD_Randf(); f32 a2 = gen->aux.rect.x; - f32 b2 = gen->aux.rect.z; - if (rnd > a2 / (a2 + b2)) { + if (rnd > a2 / (a2 + gen->aux.rect.z)) { emit_pos.z = emit_pos.z > 0.5F ? 1.0F : 0.0F; } else { emit_pos.x = emit_pos.x > 0.5F ? 1.0F : 0.0F; @@ -813,8 +806,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) { f32 rnd = HSD_Randf(); f32 a2 = gen->aux.rect.y; - f32 b2 = gen->aux.rect.z; - if (rnd > a2 / (a2 + b2)) { + if (rnd > a2 / (a2 + gen->aux.rect.z)) { emit_pos.z = emit_pos.z > 0.5F ? 1.0F : 0.0F; } else { emit_pos.y = emit_pos.y > 0.5F ? 1.0F : 0.0F; @@ -827,16 +819,11 @@ f32 hsd_8039DAD4(HSD_Generator* gen) f32 a2 = gen->aux.rect.z; f32 b2 = gen->aux.rect.y; f32 c2 = gen->aux.rect.x; - f32 ab = b2 * a2; - f32 ca = c2 * b2; - f32 total = c2 * (b2 + a2) + ab; - f32 r0 = 1.0F / total; - f32 t1 = r0 * ca; - if (rnd < t1) { + f32 r0 = 1.0F / (c2 * (b2 + a2) + b2 * a2); + if (rnd < r0 * (c2 * b2)) { emit_pos.z = emit_pos.z > 0.5F ? 1.0F : 0.0F; } else { - f32 t2 = 1.0F - r0 * (c2 * a2); - if (rnd > t2) { + if (rnd > 1.0F - r0 * (c2 * a2)) { emit_pos.y = emit_pos.y > 0.5F ? 1.0F : 0.0F; } else { emit_pos.x = emit_pos.x > 0.5F ? 1.0F : 0.0F; @@ -876,7 +863,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) gen->aux.rect.zz * gen->aux.rect.zz; mag = sqrtf(mag); { - f32 scale = vel_mag_sq / mag; + f32 scale = elevation / mag; vec.x = gen->aux.rect.zx * scale; vec.y = gen->aux.rect.zy * scale; vec.z = gen->aux.rect.zz * scale; @@ -895,9 +882,10 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 8: /* sphere emission */ { f32 r0 = gen->aux.cone.height; - if (r0 == 0.0F || __fabs(r0 - M_PI) < eps) { - f32 rnd = sqrtf(HSD_Randf()); - radius = (f32) (M_PI_2 * rnd); + if (r0 == 0.0F || __fabs(r0 - M_PI) < (f64) 0.001F) { + radius = HSD_Randf(); + radius = sqrtf(radius); + radius = (f32) (M_PI_2 * radius); { f32 rnd2 = HSD_Randf(); if (rnd2 < 0.5F) { @@ -905,21 +893,23 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } } } else { - f32 rnd = sqrtf(HSD_Randf()); - radius = gen->aux.cone.height * rnd; + radius = HSD_Randf(); + radius = sqrtf(radius); + radius = gen->aux.cone.height * radius; } { - f32 rnd = HSD_Randf(); - f32 az_angle; - f32 r2 = gen->radius; - az_angle = (f32) (2.0 * (M_PI * (f64) rnd)); - cone_angle = az_angle; - - if (r2 < 0.0F) { - sin_az = -r2; - } else { - rnd = sqrtf(HSD_Randf()); - sin_az = r2 * rnd; + cone_angle = HSD_Randf(); + cone_angle = + (f32) (2.0 * (M_PI * (f64) cone_angle)); + { + f32 r2 = gen->radius; + if (r2 < 0.0F) { + sin_az = -r2; + } else { + sin_az = HSD_Randf(); + sin_az = sqrtf(sin_az); + sin_az = r2 * sin_az; + } } } { From 13d507ad33a47687c96b86b579e666e9bb6e51b8 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:25:48 -0700 Subject: [PATCH 35/64] Match ifStock player stride allocation --- src/melee/if/ifstock.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 3facea2863..6a9ed76c57 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -611,6 +611,9 @@ void ifStock_802F98E8(unsigned char player, int b) GXColor c2; GXColor c1; if (stock->x0 != NULL) { +#ifdef MUST_MATCH + (void) stock->player[player = player].x0; +#endif user_data = ((struct IfStockData*) stock)[player].x0; *(user_data += sizeof(struct IfStockDataOffset) - sizeof(struct IfStockData)) = player; From 16e42d97e51ce789417fcf9f821f10947e48eb73 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:30:46 -0700 Subject: [PATCH 36/64] Refine ifStock player slot allocation --- src/melee/if/ifstock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 6a9ed76c57..54047dd9bb 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -612,7 +612,7 @@ void ifStock_802F98E8(unsigned char player, int b) GXColor c1; if (stock->x0 != NULL) { #ifdef MUST_MATCH - (void) stock->player[player = player].x0; + (void) &stock->player[player = player]; #endif user_data = ((struct IfStockData*) stock)[player].x0; *(user_data += sizeof(struct IfStockDataOffset) - From 3bd0a5cfd2f69b3c47cc62fdbed099971cbac813 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:38:57 -0700 Subject: [PATCH 37/64] Format generator matching source --- src/sysdolphin/baselib/generator.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 0d61456b0d..43b2fc0232 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -549,8 +549,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 4: { f32 min_a = gen->aux.disc.minAngle; f32 rnd = HSD_Randf(); - angle_step = (gen->aux.disc.maxAngle - min_a) / - (f32) (s32) gen->count; + angle_step = + (gen->aux.disc.maxAngle - min_a) / (f32) (s32) gen->count; cur_angle = angle_step * rnd + min_a; break; } @@ -558,8 +558,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 7: { f32 min_a = gen->aux.cone.minAngle; f32 rnd = HSD_Randf(); - angle_step = (gen->aux.cone.maxAngle - min_a) / - (f32) (s32) gen->count; + angle_step = + (gen->aux.cone.maxAngle - min_a) / (f32) (s32) gen->count; cur_angle = angle_step * rnd + min_a; break; } @@ -899,8 +899,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } { cone_angle = HSD_Randf(); - cone_angle = - (f32) (2.0 * (M_PI * (f64) cone_angle)); + cone_angle = (f32) (2.0 * (M_PI * (f64) cone_angle)); { f32 r2 = gen->radius; if (r2 < 0.0F) { From 1d33adec1e73a06136a75656ad22a298c1eadc3c Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:53:02 -0700 Subject: [PATCH 38/64] Refine lbColl parallel stack layout --- src/melee/lb/lbcollision.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index d4dcdd040a..da54b8902d 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1271,6 +1271,9 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, Vec3 a2; Vec3 d1; Vec3 c3; +#ifdef MUST_MATCH + PAD_STACK(4); +#endif c3 = *hurt_start; hit_param = 0.0F; d1.x = hurt_end_x - hurt_start->x; From 701e51bed437cfe80226a5abb52699d3161221c3 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:56:21 -0700 Subject: [PATCH 39/64] Guard afterimage matching-only use --- src/melee/ft/ftafterimage.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/melee/ft/ftafterimage.c b/src/melee/ft/ftafterimage.c index 452039cead..d551a4c224 100644 --- a/src/melee/ft/ftafterimage.c +++ b/src/melee/ft/ftafterimage.c @@ -283,9 +283,10 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) basePosX = curEntry->x0.x; basePosY = curEntry->x0.y; - (void) basePosY; basePosZ = curEntry->x0.z; - +#ifdef MUST_MATCH + (void) basePosY; +#endif stepPosX = frac * (nextEntry->x0.x - basePosX); stepPosY = frac * (nextEntry->x0.y - basePosY); stepPosZ = frac * (nextEntry->x0.z - basePosZ); From 37abf15659ccb42e9f6b357b49af815e9c44c765 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 19:58:47 -0700 Subject: [PATCH 40/64] Match lbColl local object order --- src/melee/lb/lbcollision.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index da54b8902d..2b4ed58ac4 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1023,6 +1023,7 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, Vec3 hit_delta; #ifdef MUST_MATCH u8 operand_pad[4]; + u8 frame_pad[32]; #endif float start_delta_z; float hit_start_dot; @@ -1045,7 +1046,6 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float local_delta_y; float start_delta_x; float hurt_param_from_hit_start; - Mtx inv_hurt_mtx; float hurt_delta_z; float x_work; float hit_end_min_x; @@ -1063,8 +1063,6 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float hit_end_max_y; float hurt_len_sq; float hit_end_max_z; - float candidate_hurt_param; - float candidate_hit_param; float hit_end_x; float hit_len_sq; float hit_end_mid_x; @@ -1088,13 +1086,16 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, f64 closest_rsqrt_estimate; f64 closest_rsqrt_step1; f64 closest_rsqrt_step2; + float candidate_hurt_param; + float candidate_hit_param; + Mtx inv_hurt_mtx; s32 is_hurt_segment_degenerate; s32 is_hit_segment_degenerate; s32 is_parallel; s32 is_zero_distance; float hurt_start_y; float hurt_start_z; - PAD_STACK(40); + PAD_STACK(4); // Fast reject when the expanded hit segment AABB misses both hurt // endpoints. From 78dcf07abe1afb91518d05a9b9ce83f82d31ed24 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:00:10 -0700 Subject: [PATCH 41/64] Refine generator cone allocation --- src/sysdolphin/baselib/generator.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 43b2fc0232..3b5c56182b 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -606,10 +606,10 @@ f32 hsd_8039DAD4(HSD_Generator* gen) cone_angle = (f32) (M_PI - gen->angle); } } else { - f64 cone_angle_d = - M_PI_2 - atan2f(gen->aux.cone.height, sin_az) - - gen->angle; - cone_angle = (f32) cone_angle_d; + cone_angle = + (f32) (M_PI_2 - + atan2f(gen->aux.cone.height, sin_az) - + gen->angle); } } else { { @@ -631,10 +631,10 @@ f32 hsd_8039DAD4(HSD_Generator* gen) cone_angle = (f32) (M_PI + gen->angle); } } else { - f64 cone_angle_d = - gen->angle + - (M_PI_2 - atan2f(gen->aux.cone.height, sin_az)); - cone_angle = (f32) cone_angle_d; + cone_angle = + (f32) (gen->angle + + (M_PI_2 - + atan2f(gen->aux.cone.height, sin_az))); } } break; @@ -673,8 +673,9 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Compute emission position and velocity from angle */ - emit_pos.x = sin_az * cosf(cur_angle); - emit_pos.y = sin_az * sinf(cur_angle); + cos_az = cur_angle; + emit_pos.x = sin_az * cosf(cos_az); + emit_pos.y = sin_az * sinf(cos_az); /* Shape 6,7: z from random, scale by height */ if ((gen->type & 0xF) == 6 || (gen->type & 0xF) == 7) { @@ -691,8 +692,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) /* Compute velocity direction from cone angle */ { f32 sin_ca = elevation * sinf(cone_angle); - vec.x = sin_ca * cosf(cur_angle); - vec.y = sin_ca * sinf(cur_angle); + vec.x = sin_ca * cosf(cos_az); + vec.y = sin_ca * sinf(cos_az); vec.z = elevation * cosf(cone_angle); } @@ -713,6 +714,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) PSMTXMultVec(rot_mtx, &vec, &vec); /* Spawn particle */ + cur_angle = cos_az; hsd_80398F0C(gen->linkNo, gen->bank, gen->kind, gen->texGroup, (s32) gen->cmdList, gen->life, 0, (s32) gen, emit_pos.x, emit_pos.y, emit_pos.z, vec.x, vec.y, From ce0f6dc2b2132c9102ff3eb398a3e5e068999ac8 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:07:18 -0700 Subject: [PATCH 42/64] Refine generator frame allocation --- src/sysdolphin/baselib/generator.c | 38 +++++++++++------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 3b5c56182b..bb8c8c5a8a 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -354,7 +354,6 @@ HSD_Generator* hsd_8039D9C8(void) f32 hsd_8039DAD4(HSD_Generator* gen) { Vec3 vel_copy; - f32 tmp; Vec3 emit_pos; Vec3 tmpvec; Vec3 vec; @@ -365,6 +364,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) Vec3 cross1; Vec3 vel_norm; Mtx trig_mtx; + f64 eps; + f32 vel_mag_sq; f32 angle1; f32 sin_az; f32 cos_az; @@ -387,8 +388,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) vel_copy.z = gen->vel.z; /* Compute velocity magnitude */ - radius = sqrtf(vel_copy.z * vel_copy.z + - (vel_copy.x * vel_copy.x + vel_copy.y * vel_copy.y)); + vel_mag_sq = sqrtf(vel_copy.z * vel_copy.z + + (vel_copy.x * vel_copy.x + vel_copy.y * vel_copy.y)); /* Initialize rotation matrix */ PSMTXIdentity(rot_mtx); @@ -454,15 +455,13 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Velocity-based rotation */ - if ((gen->type & 0xF) != 1 && radius > 1.1920929e-7F) { + if ((gen->type & 0xF) != 1 && vel_mag_sq > 1.1920929e-7F) { vel_norm.x = gen->vel.x; vel_norm.y = gen->vel.y; vel_norm.z = gen->vel.z; PSVECNormalize(&vel_norm, &vel_norm); - tmp = vel_norm.z; - *(s32*) &tmp &= 0x7FFFFFFF; - if (tmp < 1.1754944e-38F) { + if (fabsf_bitwise(vel_norm.z) < 1.1754944e-38F) { if (vel_norm.y >= 0.0F) { sin_az = 1.5707964F; } else { @@ -477,9 +476,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) { f32 projected_z = vel_norm.z * sin_az; projected_z += vel_norm.y * cos_az; - tmp = projected_z; - *(s32*) &tmp &= 0x7FFFFFFF; - if (tmp < 1.1754944e-38F) { + if (fabsf_bitwise(projected_z) < 1.1754944e-38F) { if (vel_norm.x >= 0.0F) { elevation = 1.5707964F; } else { @@ -509,13 +506,11 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } PSMTXConcat(rot_mtx, trig_mtx, rot_mtx); } - elevation = radius; + elevation = vel_mag_sq; /* Type 2: extract Euler angles from rotation matrix */ if ((gen->type & 0xF) == 2) { - tmp = rot_mtx[2][2]; - *(s32*) &tmp &= 0x7FFFFFFF; - if (tmp < 1.1754944e-38F) { + if (fabsf_bitwise(rot_mtx[2][2]) < 1.1754944e-38F) { if (rot_mtx[1][2] >= 0.0F) { angle1 = 1.5707964F; } else { @@ -527,9 +522,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) { f32 first = rot_mtx[2][2] * cosf(angle1); f32 comb = first + rot_mtx[1][2] * sinf(angle1); - tmp = comb; - *(s32*) &tmp &= 0x7FFFFFFF; - if (tmp < 1.1754944e-38F) { + if (fabsf_bitwise(comb) < 1.1754944e-38F) { if (rot_mtx[0][2] >= 0.0F) { angle3 = 1.5707964F; } else { @@ -573,6 +566,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Main particle emission loop */ + eps = 0.001F; while (gen->count >= 1.0F) { switch (gen->type & 0xF) { case 0: /* point, disc, cone, sphere, etc. */ @@ -597,9 +591,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 6: if (gen->angle < 0.0F) { cur_angle += angle_step; - tmp = sin_az; - *(s32*) &tmp &= 0x7FFFFFFF; - if (tmp < 1.1754944e-38F) { + if (fabsf_bitwise(sin_az) < 1.1754944e-38F) { if (gen->aux.cone.height >= 0.0F) { cone_angle = -gen->angle; } else { @@ -622,9 +614,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) cur_angle = cone_angle * rnd + cur_angle; cone_angle = radius * gen->angle; } - tmp = sin_az; - *(s32*) &tmp &= 0x7FFFFFFF; - if (tmp < 1.1754944e-38F) { + if (fabsf_bitwise(sin_az) < 1.1754944e-38F) { if (gen->aux.cone.height >= 0.0F) { cone_angle = gen->angle; } else { @@ -884,7 +874,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 8: /* sphere emission */ { f32 r0 = gen->aux.cone.height; - if (r0 == 0.0F || __fabs(r0 - M_PI) < (f64) 0.001F) { + if (r0 == 0.0F || __fabs(r0 - M_PI) < eps) { radius = HSD_Randf(); radius = sqrtf(radius); radius = (f32) (M_PI_2 * radius); From 3f9c7c0c01356ff669d7598bb655ce6deb5aa26e Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:13:04 -0700 Subject: [PATCH 43/64] Match generator frame allocation --- src/sysdolphin/baselib/generator.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index bb8c8c5a8a..ebc0b0a76a 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -354,6 +354,7 @@ HSD_Generator* hsd_8039D9C8(void) f32 hsd_8039DAD4(HSD_Generator* gen) { Vec3 vel_copy; + f32 tmp; Vec3 emit_pos; Vec3 tmpvec; Vec3 vec; @@ -590,7 +591,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) switch (gen->type & 0xF) { case 6: if (gen->angle < 0.0F) { - cur_angle += angle_step; + tmp = cur_angle + angle_step; + cur_angle = tmp; if (fabsf_bitwise(sin_az) < 1.1754944e-38F) { if (gen->aux.cone.height >= 0.0F) { cone_angle = -gen->angle; @@ -631,7 +633,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 7: if (gen->angle < 0.0F) { cone_angle = (f32) (M_PI_2 - gen->angle); - cur_angle += angle_step; + tmp = cur_angle + angle_step; + cur_angle = tmp; } else { { f32 min_angle = gen->aux.disc.minAngle; From 1a3a568fd9f6c8c037aa3430140629e0e8fa634b Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:23:41 -0700 Subject: [PATCH 44/64] Match generator projected velocity order --- src/sysdolphin/baselib/generator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index ebc0b0a76a..2f449977be 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -475,8 +475,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) sin_az = cosf(sin_az); { - f32 projected_z = vel_norm.z * sin_az; - projected_z += vel_norm.y * cos_az; + f32 projected_z = vel_norm.y * cos_az + vel_norm.z * sin_az; if (fabsf_bitwise(projected_z) < 1.1754944e-38F) { if (vel_norm.x >= 0.0F) { elevation = 1.5707964F; From 1022676f4409b046e8f151cb9241aa98a3962a80 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:46:16 -0700 Subject: [PATCH 45/64] Match generator scalar allocation --- src/sysdolphin/baselib/generator.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 2f449977be..468bf2a7c8 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -365,7 +365,10 @@ f32 hsd_8039DAD4(HSD_Generator* gen) Vec3 cross1; Vec3 vel_norm; Mtx trig_mtx; - f64 eps; + union { + f64 eps; + f64 angle; + } scalar; f32 vel_mag_sq; f32 angle1; f32 sin_az; @@ -558,7 +561,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } default: { f32 rnd = HSD_Randf(); - cur_angle = (f32) (2.0 * (M_PI * (f64) rnd)); + cur_angle = + (f32) ((scalar.angle = M_PI * (f64) rnd) * 2.0); angle_step = (f32) ((2.0 * M_PI) / (f64) (s32) gen->count); break; } @@ -566,7 +570,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Main particle emission loop */ - eps = 0.001F; + scalar.eps = 0.001F; while (gen->count >= 1.0F) { switch (gen->type & 0xF) { case 0: /* point, disc, cone, sphere, etc. */ @@ -876,7 +880,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 8: /* sphere emission */ { f32 r0 = gen->aux.cone.height; - if (r0 == 0.0F || __fabs(r0 - M_PI) < eps) { + if (r0 == 0.0F || __fabs(r0 - M_PI) < scalar.eps) { radius = HSD_Randf(); radius = sqrtf(radius); radius = (f32) (M_PI_2 * radius); From d95ce0f1de34f1c01fdd5288a3a1d2189cd17c4a Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:47:00 -0700 Subject: [PATCH 46/64] Match lbColl closest delta order --- src/melee/lb/lbcollision.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index 2b4ed58ac4..76ecc38306 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1014,7 +1014,7 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float broadphase_scale) { float hit_end_min_z; - float closest_delta_x; + float closest_delta_y; float hit_start_mid_x; float local_delta_x; float hurt_mid_z; @@ -1041,7 +1041,7 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float hurt_end_x; float hit_start_mid_y; float hit_param_candidate; - float closest_delta_y; + float closest_delta_x; float closest_dist_sq; float local_delta_y; float start_delta_x; @@ -1374,12 +1374,12 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, hurt_closest->x = (x_work * hurt_param) + hurt_start_copy.x; hurt_closest->y = (y_work * hurt_param) + hurt_start_y; hurt_closest->z = (hurt_delta_z * hurt_param) + hurt_start_z; - closest_delta_y = hit_closest->y - hurt_closest->y; closest_delta_x = hit_closest->x - hurt_closest->x; + closest_delta_y = hit_closest->y - hurt_closest->y; closest_delta_z = hit_closest->z - hurt_closest->z; closest_dist_sq = (closest_delta_z * closest_delta_z) + - ((closest_delta_y * closest_delta_y) + - (closest_delta_x * closest_delta_x)); + ((closest_delta_x * closest_delta_x) + + (closest_delta_y * closest_delta_y)); if (closest_dist_sq > 0.0F) { volatile float sp38; From 494e4f83f8f457f06abee44a34e45b66b32bd09d Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:55:06 -0700 Subject: [PATCH 47/64] Match generator emission allocation --- src/sysdolphin/baselib/generator.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 468bf2a7c8..0049128d0a 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -350,6 +350,15 @@ HSD_Generator* hsd_8039D9C8(void) return gen; } +#ifdef MUST_MATCH +static inline f32 hsd_8039DAD4_home(f32 value) +{ + return value; +} +#else +#define hsd_8039DAD4_home(value) (value) +#endif + /// @todo Only differs by register allocation. f32 hsd_8039DAD4(HSD_Generator* gen) { @@ -365,10 +374,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) Vec3 cross1; Vec3 vel_norm; Mtx trig_mtx; - union { - f64 eps; - f64 angle; - } scalar; + f64 eps; f32 vel_mag_sq; f32 angle1; f32 sin_az; @@ -380,7 +386,6 @@ f32 hsd_8039DAD4(HSD_Generator* gen) f32 elevation; f32 radius; f32 angle3; - angle3 = angle1 = 0.0F; if (gen->count < 1.0F) { return gen->count; @@ -562,7 +567,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) default: { f32 rnd = HSD_Randf(); cur_angle = - (f32) ((scalar.angle = M_PI * (f64) rnd) * 2.0); + (f32) ((eps = M_PI * (f64) hsd_8039DAD4_home(rnd)) * 2.0); angle_step = (f32) ((2.0 * M_PI) / (f64) (s32) gen->count); break; } @@ -570,7 +575,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } /* Main particle emission loop */ - scalar.eps = 0.001F; + eps = 0.001F; while (gen->count >= 1.0F) { switch (gen->type & 0xF) { case 0: /* point, disc, cone, sphere, etc. */ @@ -750,7 +755,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) cur_angle += angle_step; } else { f32 rnd = HSD_Randf(); - cur_angle = (f32) (2.0 * (M_PI * (f64) rnd)); + cur_angle = (f32) ( + 2.0 * (M_PI * (f64) hsd_8039DAD4_home(rnd))); } gen->aux.line.x2 = elevation; hsd_80398F0C(gen->linkNo, gen->bank, gen->kind | 4, gen->texGroup, @@ -880,7 +886,7 @@ f32 hsd_8039DAD4(HSD_Generator* gen) case 8: /* sphere emission */ { f32 r0 = gen->aux.cone.height; - if (r0 == 0.0F || __fabs(r0 - M_PI) < scalar.eps) { + if (r0 == 0.0F || __fabs(r0 - M_PI) < eps) { radius = HSD_Randf(); radius = sqrtf(radius); radius = (f32) (M_PI_2 * radius); @@ -897,7 +903,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } { cone_angle = HSD_Randf(); - cone_angle = (f32) (2.0 * (M_PI * (f64) cone_angle)); + cone_angle = (f32) ( + 2.0 * (M_PI * (f64) hsd_8039DAD4_home(cone_angle))); { f32 r2 = gen->radius; if (r2 < 0.0F) { From ed880caf75b6bf279b9f20e7eca55ca544d29dcc Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 20:55:31 -0700 Subject: [PATCH 48/64] Format generator match helper calls --- src/sysdolphin/baselib/generator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index 0049128d0a..df57e2b2b1 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -755,8 +755,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) cur_angle += angle_step; } else { f32 rnd = HSD_Randf(); - cur_angle = (f32) ( - 2.0 * (M_PI * (f64) hsd_8039DAD4_home(rnd))); + cur_angle = + (f32) (2.0 * (M_PI * (f64) hsd_8039DAD4_home(rnd))); } gen->aux.line.x2 = elevation; hsd_80398F0C(gen->linkNo, gen->bank, gen->kind | 4, gen->texGroup, @@ -903,8 +903,8 @@ f32 hsd_8039DAD4(HSD_Generator* gen) } { cone_angle = HSD_Randf(); - cone_angle = (f32) ( - 2.0 * (M_PI * (f64) hsd_8039DAD4_home(cone_angle))); + cone_angle = + (f32) (2.0 * (M_PI * (f64) hsd_8039DAD4_home(cone_angle))); { f32 r2 = gen->radius; if (r2 < 0.0F) { From 6dcdd45083ca68cc9b0fdafc5d348a549e743985 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 21:07:04 -0700 Subject: [PATCH 49/64] Link generator translation unit --- config/GALE01/symbols.txt | 108 ++++++++++++++--------------- configure.py | 2 +- src/sysdolphin/baselib/generator.c | 7 +- src/sysdolphin/baselib/particle.c | 14 +--- 4 files changed, 59 insertions(+), 72 deletions(-) diff --git a/config/GALE01/symbols.txt b/config/GALE01/symbols.txt index 195a258f53..003cb2a5ef 100644 --- a/config/GALE01/symbols.txt +++ b/config/GALE01/symbols.txt @@ -27,20 +27,20 @@ _bss_init_info = .init:0x800054F4; // type:object size:0x18 scope:global data:4b @etb_80005570 = extab:0x80005570; // type:object size:0x8 scope:local hidden @etb_80005578 = extab:0x80005578; // type:object size:0x8 scope:local hidden @etb_80005580 = extab:0x80005580; // type:object size:0x8 scope:local hidden -@etb_80005588 = extab:0x80005588; // type:object size:0x8 scope:local hidden -@etb_80005590 = extab:0x80005590; // type:object size:0x8 scope:local hidden -@etb_80005598 = extab:0x80005598; // type:object size:0x8 scope:local hidden -@etb_800055A0 = extab:0x800055A0; // type:object size:0x8 scope:local hidden -@etb_800055A8 = extab:0x800055A8; // type:object size:0x8 scope:local hidden -@etb_800055B0 = extab:0x800055B0; // type:object size:0x8 scope:local hidden -@etb_800055B8 = extab:0x800055B8; // type:object size:0x8 scope:local hidden -@etb_800055C0 = extab:0x800055C0; // type:object size:0x8 scope:local hidden -@etb_800055C8 = extab:0x800055C8; // type:object size:0x8 scope:local hidden -@etb_800055D0 = extab:0x800055D0; // type:object size:0x8 scope:local hidden -@etb_800055D8 = extab:0x800055D8; // type:object size:0x8 scope:local hidden -@etb_800055E0 = extab:0x800055E0; // type:object size:0x8 scope:local hidden -@etb_800055E8 = extab:0x800055E8; // type:object size:0x8 scope:local hidden -@etb_800055F0 = extab:0x800055F0; // type:object size:0x8 scope:local hidden +@225 = extab:0x80005588; // type:object size:0x8 scope:local hidden +@228 = extab:0x80005590; // type:object size:0x8 scope:local hidden +@258 = extab:0x80005598; // type:object size:0x8 scope:local hidden +@283 = extab:0x800055A0; // type:object size:0x8 scope:local hidden +@294 = extab:0x800055A8; // type:object size:0x8 scope:local hidden +@317 = extab:0x800055B0; // type:object size:0x8 scope:local hidden +@332 = extab:0x800055B8; // type:object size:0x8 scope:local hidden +@369 = extab:0x800055C0; // type:object size:0x8 scope:local hidden +@395 = extab:0x800055C8; // type:object size:0x8 scope:local hidden +@740 = extab:0x800055D0; // type:object size:0x8 scope:local hidden +@774 = extab:0x800055D8; // type:object size:0x8 scope:local hidden +@793 = extab:0x800055E0; // type:object size:0x8 scope:local hidden +@912 = extab:0x800055E8; // type:object size:0x8 scope:local hidden +@929 = extab:0x800055F0; // type:object size:0x8 scope:local hidden @etb_800055F8 = extab:0x800055F8; // type:object size:0x8 scope:local hidden @etb_80005600 = extab:0x80005600; // type:object size:0x8 scope:local hidden @etb_80005608 = extab:0x80005608; // type:object size:0x8 scope:local hidden @@ -77,20 +77,20 @@ _bss_init_info = .init:0x800054F4; // type:object size:0x18 scope:global data:4b @eti_80005738 = extabindex:0x80005738; // type:object size:0xC scope:local hidden @eti_80005744 = extabindex:0x80005744; // type:object size:0xC scope:local hidden @eti_80005750 = extabindex:0x80005750; // type:object size:0xC scope:local hidden -@eti_8000575C = extabindex:0x8000575C; // type:object size:0xC scope:local hidden -@eti_80005768 = extabindex:0x80005768; // type:object size:0xC scope:local hidden -@eti_80005774 = extabindex:0x80005774; // type:object size:0xC scope:local hidden -@eti_80005780 = extabindex:0x80005780; // type:object size:0xC scope:local hidden -@eti_8000578C = extabindex:0x8000578C; // type:object size:0xC scope:local hidden -@eti_80005798 = extabindex:0x80005798; // type:object size:0xC scope:local hidden -@eti_800057A4 = extabindex:0x800057A4; // type:object size:0xC scope:local hidden -@eti_800057B0 = extabindex:0x800057B0; // type:object size:0xC scope:local hidden -@eti_800057BC = extabindex:0x800057BC; // type:object size:0xC scope:local hidden -@eti_800057C8 = extabindex:0x800057C8; // type:object size:0xC scope:local hidden -@eti_800057D4 = extabindex:0x800057D4; // type:object size:0xC scope:local hidden -@eti_800057E0 = extabindex:0x800057E0; // type:object size:0xC scope:local hidden -@eti_800057EC = extabindex:0x800057EC; // type:object size:0xC scope:local hidden -@eti_800057F8 = extabindex:0x800057F8; // type:object size:0xC scope:local hidden +@226 = extabindex:0x8000575C; // type:object size:0xC scope:local hidden +@229 = extabindex:0x80005768; // type:object size:0xC scope:local hidden +@259 = extabindex:0x80005774; // type:object size:0xC scope:local hidden +@284 = extabindex:0x80005780; // type:object size:0xC scope:local hidden +@295 = extabindex:0x8000578C; // type:object size:0xC scope:local hidden +@318 = extabindex:0x80005798; // type:object size:0xC scope:local hidden +@333 = extabindex:0x800057A4; // type:object size:0xC scope:local hidden +@370 = extabindex:0x800057B0; // type:object size:0xC scope:local hidden +@396 = extabindex:0x800057BC; // type:object size:0xC scope:local hidden +@741 = extabindex:0x800057C8; // type:object size:0xC scope:local hidden +@775 = extabindex:0x800057D4; // type:object size:0xC scope:local hidden +@794 = extabindex:0x800057E0; // type:object size:0xC scope:local hidden +@913 = extabindex:0x800057EC; // type:object size:0xC scope:local hidden +@930 = extabindex:0x800057F8; // type:object size:0xC scope:local hidden @eti_80005804 = extabindex:0x80005804; // type:object size:0xC scope:local hidden @eti_80005810 = extabindex:0x80005810; // type:object size:0xC scope:local hidden @eti_8000581C = extabindex:0x8000581C; // type:object size:0xC scope:local hidden @@ -25934,13 +25934,13 @@ lbl_8040BFEC = .data:0x8040BFEC; // type:object size:0x22 scope:local data:strin lbl_8040C010 = .data:0x8040C010; // type:object size:0x9 scope:local data:string lbl_8040C01C = .data:0x8040C01C; // type:object size:0x27 scope:local data:string jumptable_8040C044 = .data:0x8040C044; // type:object size:0x200 scope:local -lbl_8040C248 = .data:0x8040C248; // type:object size:0xC scope:local data:string -lbl_8040C254 = .data:0x8040C254; // type:object size:0x9 scope:local data:string -jumptable_8040C260 = .data:0x8040C260; // type:object size:0x20 scope:local -jumptable_8040C280 = .data:0x8040C280; // type:object size:0x24 scope:local -lbl_8040C2A4 = .data:0x8040C2A4; // type:object size:0x9 scope:local data:string -lbl_8040C2B0 = .data:0x8040C2B0; // type:object size:0x27 scope:local data:string -jumptable_8040C2D8 = .data:0x8040C2D8; // type:object size:0x24 scope:local +@722 = .data:0x8040C248; // type:object size:0xC scope:local data:string +@723 = .data:0x8040C254; // type:object size:0x9 scope:local data:string +@738 = .data:0x8040C260; // type:object size:0x20 scope:local +@737 = .data:0x8040C280; // type:object size:0x24 scope:local +@791 = .data:0x8040C2A4; // type:object size:0x9 scope:local data:string +@792 = .data:0x8040C2B0; // type:object size:0x27 scope:local data:string +@911 = .data:0x8040C2D8; // type:object size:0x24 scope:local HSD_PSDisp_8040C300 = .data:0x8040C300; // type:object size:0x9 scope:local data:string HSD_PSDisp_8040C30C = .data:0x8040C30C; // type:object size:0x27 scope:local data:string HSD_PSDisp_8040C334 = .data:0x8040C334; // type:object size:0xC scope:local @@ -28289,8 +28289,8 @@ lbl_804D6350 = .sdata:0x804D6350; // type:object size:0x8 scope:local lbl_804D6358 = .sdata:0x804D6358; // type:object size:0x7 scope:local data:string lbl_804D6360 = .sdata:0x804D6360; // type:object size:0x5 scope:local data:string lbl_804D6368 = .sdata:0x804D6368; // type:object size:0x2 scope:local data:2byte -lbl_804D636C = .sdata:0x804D636C; // type:object size:0x7 scope:local data:string -lbl_804D6374 = .sdata:0x804D6374; // type:object size:0x5 scope:local data:string +@223 = .sdata:0x804D636C; // type:object size:0x7 scope:local data:string +@224 = .sdata:0x804D6374; // type:object size:0x5 scope:local data:string psFrameNum = .sdata:0x804D6380; // type:object size:0x1 scope:global data:byte HSD_PSDisp_804D6384 = .sdata:0x804D6384; // type:object size:0x2 scope:global data:string @104 = .sdata:0x804D6388; // type:object size:0x5 scope:local data:string @@ -35012,23 +35012,23 @@ lbl_804DE98C = .sdata2:0x804DE98C; // type:object size:0x4 scope:local align:4 d lbl_804DE990 = .sdata2:0x804DE990; // type:object size:0x4 scope:local align:4 data:float lbl_804DE998 = .sdata2:0x804DE998; // type:object size:0x8 scope:local align:8 data:double lbl_804DE9A0 = .sdata2:0x804DE9A0; // type:object size:0x8 scope:local align:8 data:double -lbl_804DE9A8 = .sdata2:0x804DE9A8; // type:object size:0x4 scope:local align:4 data:float -lbl_804DE9AC = .sdata2:0x804DE9AC; // type:object size:0x4 scope:local align:4 data:float -lbl_804DE9B0 = .sdata2:0x804DE9B0; // type:object size:0x8 scope:local align:8 data:double -lbl_804DE9B8 = .sdata2:0x804DE9B8; // type:object size:0x8 scope:local align:8 data:double -lbl_804DE9C0 = .sdata2:0x804DE9C0; // type:object size:0x4 scope:local align:4 data:float -lbl_804DE9C4 = .sdata2:0x804DE9C4; // type:object size:0x4 scope:local align:4 data:float -lbl_804DE9C8 = .sdata2:0x804DE9C8; // type:object size:0x4 scope:local align:4 data:float -lbl_804DE9CC = .sdata2:0x804DE9CC; // type:object size:0x4 scope:local align:4 data:float -lbl_804DE9D0 = .sdata2:0x804DE9D0; // type:object size:0x8 scope:local align:8 data:double -lbl_804DE9D8 = .sdata2:0x804DE9D8; // type:object size:0x8 scope:local align:8 data:double -lbl_804DE9E0 = .sdata2:0x804DE9E0; // type:object size:0x8 scope:local align:8 data:double -lbl_804DE9E8 = .sdata2:0x804DE9E8; // type:object size:0x8 scope:local align:8 data:double -lbl_804DE9F0 = .sdata2:0x804DE9F0; // type:object size:0x4 scope:local align:4 data:float -lbl_804DE9F8 = .sdata2:0x804DE9F8; // type:object size:0x8 scope:local align:8 data:double -lbl_804DEA00 = .sdata2:0x804DEA00; // type:object size:0x8 scope:local align:8 data:double -lbl_804DEA08 = .sdata2:0x804DEA08; // type:object size:0x4 scope:local align:4 data:float -lbl_804DEA0C = .sdata2:0x804DEA0C; // type:object size:0x4 scope:local align:4 data:float +@257 = .sdata2:0x804DE9A8; // type:object size:0x4 scope:local align:4 data:float +@719 = .sdata2:0x804DE9AC; // type:object size:0x4 scope:local align:4 data:float +@720 = .sdata2:0x804DE9B0; // type:object size:0x8 scope:local align:8 data:double +@721 = .sdata2:0x804DE9B8; // type:object size:0x8 scope:local align:8 data:double +@724 = .sdata2:0x804DE9C0; // type:object size:0x4 scope:local align:4 data:float +@725 = .sdata2:0x804DE9C4; // type:object size:0x4 scope:local align:4 data:float +@726 = .sdata2:0x804DE9C8; // type:object size:0x4 scope:local align:4 data:float +@727 = .sdata2:0x804DE9CC; // type:object size:0x4 scope:local align:4 data:float +@728 = .sdata2:0x804DE9D0; // type:object size:0x8 scope:local align:8 data:double +@729 = .sdata2:0x804DE9D8; // type:object size:0x8 scope:local align:8 data:double +@730 = .sdata2:0x804DE9E0; // type:object size:0x8 scope:local align:8 data:double +@731 = .sdata2:0x804DE9E8; // type:object size:0x8 scope:local align:8 data:double +@732 = .sdata2:0x804DE9F0; // type:object size:0x4 scope:local align:4 data:float +@733 = .sdata2:0x804DE9F8; // type:object size:0x8 scope:local align:8 data:double +@736 = .sdata2:0x804DEA00; // type:object size:0x8 scope:local align:8 data:double +@909 = .sdata2:0x804DEA08; // type:object size:0x4 scope:local align:4 data:float +@910 = .sdata2:0x804DEA0C; // type:object size:0x4 scope:local align:4 data:float HSD_PSDisp_804DEA10 = .sdata2:0x804DEA10; // type:object size:0x4 scope:global align:4 data:float HSD_PSDisp_804DEA14 = .sdata2:0x804DEA14; // type:object size:0x4 scope:global align:4 data:float HSD_PSDisp_804DEA18 = .sdata2:0x804DEA18; // type:object size:0x4 scope:global align:4 data:float diff --git a/configure.py b/configure.py index 8d6d7c948e..7bfae30ee8 100755 --- a/configure.py +++ b/configure.py @@ -1925,7 +1925,7 @@ def MatchingFor(*versions): extra_cflags=["-Cpp_exceptions on"], ), Object( - Linkable, + Matching, "sysdolphin/baselib/generator.c", extra_cflags=["-Cpp_exceptions on"], ), diff --git a/src/sysdolphin/baselib/generator.c b/src/sysdolphin/baselib/generator.c index df57e2b2b1..fac8f23ed9 100644 --- a/src/sysdolphin/baselib/generator.c +++ b/src/sysdolphin/baselib/generator.c @@ -350,16 +350,11 @@ HSD_Generator* hsd_8039D9C8(void) return gen; } -#ifdef MUST_MATCH static inline f32 hsd_8039DAD4_home(f32 value) { return value; } -#else -#define hsd_8039DAD4_home(value) (value) -#endif -/// @todo Only differs by register allocation. f32 hsd_8039DAD4(HSD_Generator* gen) { Vec3 vel_copy; @@ -1128,6 +1123,8 @@ HSD_Generator* hsd_8039F05C(s32 linkNo, s32 bank, s32 idx) gen->aux.line.y2 = ptclref_804D0E5C[bank][idx]->param2; gen->aux.line.z2 = ptclref_804D0E5C[bank][idx]->param3; break; + case 2: + break; case 6: case 7: { HSD_PSCmdList* c = ptclref_804D0E5C[bank][idx]; diff --git a/src/sysdolphin/baselib/particle.c b/src/sysdolphin/baselib/particle.c index 138002ee7d..cfbb652b09 100644 --- a/src/sysdolphin/baselib/particle.c +++ b/src/sysdolphin/baselib/particle.c @@ -845,12 +845,7 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) tga = psTexGroupArray[bank]; texGrp = tga[tgIdx]; - if (texGrp != NULL -#ifdef MUST_MATCH - && texGrp->texTable != NULL -#endif - ) - { + if (texGrp != NULL && texGrp->texTable != NULL) { if (texGrp->texTable[pp->poseNum] != NULL) { pp->kind |= DispTexture; } @@ -2028,12 +2023,7 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) tga = psTexGroupArray[bank]; texGrp = tga[tgIdx]; - if (texGrp != NULL -#ifdef MUST_MATCH - && texGrp->texTable != NULL -#endif - ) - { + if (texGrp != NULL && texGrp->texTable != NULL) { if (texGrp->texTable[pp->poseNum] != NULL) { pp->kind |= DispTexture; } From 290c21769fc96422c65e6e1504f5c679f2424971 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 21:07:10 -0700 Subject: [PATCH 50/64] Match ftCo_800A75DC --- src/melee/ft/chara/ftCommon/ftCo_0A01.c | 35 ++++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/melee/ft/chara/ftCommon/ftCo_0A01.c b/src/melee/ft/chara/ftCommon/ftCo_0A01.c index 30e5022934..892e672a34 100644 --- a/src/melee/ft/chara/ftCommon/ftCo_0A01.c +++ b/src/melee/ft/chara/ftCommon/ftCo_0A01.c @@ -1055,6 +1055,19 @@ void ftCo_800A1F3C(Fighter* fp, float arg1, float arg2, float arg3) } } +static inline void ftCo_800A75DC_set_target(Fighter* fp, int* x60, + float arg1, float arg2, + float arg3) +{ + struct Fighter_x1A88_t* data = &fp->x1A88; + if (*x60 == 0) { + data->x54.x = arg1; + data->x54.y = arg2; + data->x38 = arg3; + ftCo_800A1CC4(fp, ftCo_803C6594[stage_info.grkind]); + } +} + bool ftCo_800A1F98(int x, float y) { float slope; @@ -3599,9 +3612,8 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) return; } if (fp1->ground_or_air == GA_Air) { - s32 blocked; s32 result; - mp_UnkStruct0* island; + s32 blocked; fx = fp1->cur_pos.x; { f32 fx2 = fx; @@ -3628,8 +3640,11 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) } } if (result != 0) { + int* x60; + mp_UnkStruct0* island; island = mpIsland_8005AB54(line_id); if (ftCo_800A2718(island) == 0) { + x60 = &fp0->x1A88.x60; ftCo_800A1F3C(fp0, floor_pos.x, floor_pos.y, data->x56C + fp1->x1A88.x564); if (island != NULL) { @@ -3638,8 +3653,9 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) d = -d; } if (d < 5.0) { - ftCo_800A1F3C(fp0, island->x14.x - 5.0, island->x14.y, - data->x56C + fp1->x1A88.x564); + ftCo_800A75DC_set_target( + fp0, x60, island->x14.x - 5.0, island->x14.y, + data->x56C + fp1->x1A88.x564); } else { d = ABS(island->x8.x - data->x54.x); if (d < 5.0) { @@ -3657,10 +3673,12 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) } else if (ftCo_800A2718(mpIsland_8005AB54(fp1->coll_data.floor.index)) == 0) { + int* x60; mp_UnkStruct0* island; mp_UnkStruct0* fp0_island; s32 same_island; + x60 = &fp0->x1A88.x60; ftCo_800A1F3C(fp0, fp1->cur_pos.x, fp1->cur_pos.y, data->x56C + fp1->x1A88.x564); if (fp0->ground_or_air == GA_Air) { @@ -3685,8 +3703,9 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) { if (data->x54.x - fp0->cur_pos.x > 0.0) { if (fp0->cur_pos.x < island->x8.x) { - ftCo_800A1F3C(fp0, 5.0 + island->x8.x, island->x8.y, - data->x56C + fp1->x1A88.x564); + ftCo_800A75DC_set_target( + fp0, x60, 5.0 + island->x8.x, island->x8.y, + data->x56C + fp1->x1A88.x564); } } else { if (fp0->cur_pos.x > island->x14.x) { @@ -5290,7 +5309,6 @@ static inline void ftCo_800ABBA8_blk155144r(Fighter* fp, Fighter** target) *target = data->x44; } -#ifdef MUST_MATCH /* MSL sqrtf with caller-provided volatile slot (retail 0x34/0x38/0x40). */ static inline float sqrtf_store(float x, volatile float* y) { @@ -5304,9 +5322,6 @@ static inline float sqrtf_store(float x, volatile float* y) } return x; } -#else -#define sqrtf_store(x, y) sqrtf(x) -#endif void ftCo_800ABBA8(Fighter* fp) { From 93d452ca7412b34e11b46be4516d7a263f429362 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 21:13:26 -0700 Subject: [PATCH 51/64] Fix ftCo CI checks --- src/melee/ft/chara/ftCommon/ftCo_0A01.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/melee/ft/chara/ftCommon/ftCo_0A01.c b/src/melee/ft/chara/ftCommon/ftCo_0A01.c index 892e672a34..124f138692 100644 --- a/src/melee/ft/chara/ftCommon/ftCo_0A01.c +++ b/src/melee/ft/chara/ftCommon/ftCo_0A01.c @@ -1055,9 +1055,8 @@ void ftCo_800A1F3C(Fighter* fp, float arg1, float arg2, float arg3) } } -static inline void ftCo_800A75DC_set_target(Fighter* fp, int* x60, - float arg1, float arg2, - float arg3) +static inline void ftCo_800A75DC_set_target(Fighter* fp, const int* x60, + float arg1, float arg2, float arg3) { struct Fighter_x1A88_t* data = &fp->x1A88; if (*x60 == 0) { @@ -3653,9 +3652,9 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) d = -d; } if (d < 5.0) { - ftCo_800A75DC_set_target( - fp0, x60, island->x14.x - 5.0, island->x14.y, - data->x56C + fp1->x1A88.x564); + ftCo_800A75DC_set_target(fp0, x60, island->x14.x - 5.0, + island->x14.y, + data->x56C + fp1->x1A88.x564); } else { d = ABS(island->x8.x - data->x54.x); if (d < 5.0) { @@ -3703,9 +3702,9 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) { if (data->x54.x - fp0->cur_pos.x > 0.0) { if (fp0->cur_pos.x < island->x8.x) { - ftCo_800A75DC_set_target( - fp0, x60, 5.0 + island->x8.x, island->x8.y, - data->x56C + fp1->x1A88.x564); + ftCo_800A75DC_set_target(fp0, x60, 5.0 + island->x8.x, + island->x8.y, + data->x56C + fp1->x1A88.x564); } } else { if (fp0->cur_pos.x > island->x14.x) { @@ -5318,7 +5317,7 @@ static inline float sqrtf_store(float x, volatile float* y) guess = 0.5 * guess * (3.0 - guess * guess * x); guess = 0.5 * guess * (3.0 - guess * guess * x); *y = (float) (x * guess); - return *(volatile float*) y; + return *y; } return x; } From 3e6018f870af23fa55aec1d66e0a9ab91aee5f66 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 21:16:32 -0700 Subject: [PATCH 52/64] Restore existing ftCo match guard --- src/melee/ft/chara/ftCommon/ftCo_0A01.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/melee/ft/chara/ftCommon/ftCo_0A01.c b/src/melee/ft/chara/ftCommon/ftCo_0A01.c index 124f138692..be3533bce0 100644 --- a/src/melee/ft/chara/ftCommon/ftCo_0A01.c +++ b/src/melee/ft/chara/ftCommon/ftCo_0A01.c @@ -5308,6 +5308,7 @@ static inline void ftCo_800ABBA8_blk155144r(Fighter* fp, Fighter** target) *target = data->x44; } +#ifdef MUST_MATCH /* MSL sqrtf with caller-provided volatile slot (retail 0x34/0x38/0x40). */ static inline float sqrtf_store(float x, volatile float* y) { @@ -5317,10 +5318,13 @@ static inline float sqrtf_store(float x, volatile float* y) guess = 0.5 * guess * (3.0 - guess * guess * x); guess = 0.5 * guess * (3.0 - guess * guess * x); *y = (float) (x * guess); - return *y; + return *(volatile float*) y; } return x; } +#else +#define sqrtf_store(x, y) sqrtf(x) +#endif void ftCo_800ABBA8(Fighter* fp) { From 41ed110ac568d52ea51d5e79fea38de2fe6dd5eb Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 21:32:13 -0700 Subject: [PATCH 53/64] Keep match stack padding unconditional --- src/melee/ft/ftafterimage.c | 2 -- src/melee/lb/lbcollision.c | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/melee/ft/ftafterimage.c b/src/melee/ft/ftafterimage.c index d551a4c224..11c450e666 100644 --- a/src/melee/ft/ftafterimage.c +++ b/src/melee/ft/ftafterimage.c @@ -30,9 +30,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) { Fighter* fp; itSword_UnkBytes* params; -#ifdef MUST_MATCH UNUSED f32 inner_pad[1]; -#endif f32 cumDist[3]; AfterimageVtx vtx_buf[152]; f32* distPtr; diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index 76ecc38306..a3e13230fb 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1021,10 +1021,8 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, Vec3 hit_start_copy; Vec3 hurt_start_copy; Vec3 hit_delta; -#ifdef MUST_MATCH u8 operand_pad[4]; u8 frame_pad[32]; -#endif float start_delta_z; float hit_start_dot; float scaled_hurt_radius; @@ -1272,9 +1270,7 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, Vec3 a2; Vec3 d1; Vec3 c3; -#ifdef MUST_MATCH PAD_STACK(4); -#endif c3 = *hurt_start; hit_param = 0.0F; d1.x = hurt_end_x - hurt_start->x; From b3e6bd2016fa3b8ce9944e282e27f9efed1187da Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 21:32:20 -0700 Subject: [PATCH 54/64] Guard particle match-only array checks --- src/sysdolphin/baselib/particle.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/sysdolphin/baselib/particle.c b/src/sysdolphin/baselib/particle.c index cfbb652b09..138002ee7d 100644 --- a/src/sysdolphin/baselib/particle.c +++ b/src/sysdolphin/baselib/particle.c @@ -845,7 +845,12 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) tga = psTexGroupArray[bank]; texGrp = tga[tgIdx]; - if (texGrp != NULL && texGrp->texTable != NULL) { + if (texGrp != NULL +#ifdef MUST_MATCH + && texGrp->texTable != NULL +#endif + ) + { if (texGrp->texTable[pp->poseNum] != NULL) { pp->kind |= DispTexture; } @@ -2023,7 +2028,12 @@ void* hsd_8039930C(void* pp_arg, void* prev_arg) tga = psTexGroupArray[bank]; texGrp = tga[tgIdx]; - if (texGrp != NULL && texGrp->texTable != NULL) { + if (texGrp != NULL +#ifdef MUST_MATCH + && texGrp->texTable != NULL +#endif + ) + { if (texGrp->texTable[pp->poseNum] != NULL) { pp->kind |= DispTexture; } From a69dc27dc1a5326a48e811b7f968b87ea2223870 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 22:07:03 -0700 Subject: [PATCH 55/64] Model ifStock fighter match flags --- src/melee/gm/types.h | 60 +++++++++++++++++++++++++++--------------- src/melee/if/ifstock.c | 18 +++---------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/melee/gm/types.h b/src/melee/gm/types.h index 7f50bdb1a4..84aed1ec74 100644 --- a/src/melee/gm/types.h +++ b/src/melee/gm/types.h @@ -478,6 +478,44 @@ struct Placeholder_8016AE38_flags_2 { /* +2:7 */ u8 x2_b7 : 1; }; +struct lbl_8046B6A0_FighterMatchInfoFlags { + u8 x4_b0 : 1; ///< metal + u8 x4_b1 : 1; + u8 x4_b2 : 1; ///< invisible + u8 x4_b3 : 1; + u8 x4_b4 : 1; ///< Zelda/Sheik transforming on load + u8 x4_b5 : 1; + u8 x4_b6 : 1; + u8 x4_b7 : 1; +}; + +struct lbl_8046B6A0_FighterMatchInfo { + u8 x0; ///< CharacterKind + u8 x1; + u8 slot_type; + s8 spawn_point; + union { + struct { + u8 x4_b0 : 1; ///< metal + u8 x4_b1 : 1; + u8 x4_b2 : 1; ///< invisible + u8 x4_b3 : 1; + u8 x4_b4 : 1; ///< Zelda/Sheik transforming on load + u8 x4_b5 : 1; + u8 x4_b6 : 1; + u8 x4_b7 : 1; + }; + struct lbl_8046B6A0_FighterMatchInfoFlags flags; + }; + u8 x5; + u16 x6; + u8 x8; + u8 x9; + u8 respawn_timer; + u8 xB; + u16 xC; +}; + struct lbl_8046B6A0_t { /* 0x0000 */ u8 unk_0; ///< 0 During a match ///< 1 While GAME! or "TIMEOUT!" is displayed/match @@ -519,27 +557,7 @@ struct lbl_8046B6A0_t { /* 0x002E */ u16 unk_2E; /* 0x0030 */ u8 unk_30; /* 0x0034 */ f32 unk_34; - /* 0x0038 */ struct { - u8 x0; ///< CharacterKind - u8 x1; - u8 slot_type; - s8 spawn_point; - u8 x4_b0 : 1; ///< metal - u8 x4_b1 : 1; - u8 x4_b2 : 1; ///< invisible - u8 x4_b3 : 1; - u8 x4_b4 : 1; ///< Zelda/Sheik transforming on load - u8 x4_b5 : 1; - u8 x4_b6 : 1; - u8 x4_b7 : 1; - u8 x5; - u16 x6; - u8 x8; - u8 x9; - u8 respawn_timer; - u8 xB; - u16 xC; - } FighterMatchInfo[6]; + /* 0x0038 */ struct lbl_8046B6A0_FighterMatchInfo FighterMatchInfo[6]; /* 0x0038 */ char pad_8C[0x24C - 0x8C]; /* maybe part of unk_34[0x925]? */ /* 0x024C */ struct lbl_8046B6A0_24C_t x24C; /* 0x24C8 */ struct StartMeleeRules x24C8; diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 54047dd9bb..f35a4c3997 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -571,22 +571,10 @@ static inline HSD_JObj* ifStock_802F98E8_get_x3C(unsigned char player) return ifStock_804A1378.player[player].x3C; } -struct IfStockMatchInfo { - u8 x4_b0 : 1; - u8 x4_b1 : 1; - u8 x4_b2 : 1; - u8 x4_b3 : 1; - u8 x4_b4 : 1; - u8 x4_b5 : 1; - u8 x4_b6 : 1; - u8 x4_b7 : 1; -}; - -static inline struct IfStockMatchInfo* +static inline struct lbl_8046B6A0_FighterMatchInfoFlags* ifStock_802F98E8_get_match_info(lbl_8046B6A0_t* data, int player) { - return (struct IfStockMatchInfo*) ((u8*) &data->FighterMatchInfo[player] + - 4); + return &data->FighterMatchInfo[player].flags; } static inline unsigned char* @@ -742,7 +730,7 @@ void ifStock_802F98E8(unsigned char player, int b) HSD_JObjAnimAll(jobj); ae44 = gm_16AE_GetUnkData_1(); { - struct IfStockMatchInfo* match_info = + struct lbl_8046B6A0_FighterMatchInfoFlags* match_info = ifStock_802F98E8_get_match_info(ae44, player); if (match_info->x4_b1) { GXColor* color; From af00476dee9b0220732f2adf38b540062b6a3412 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Sun, 30 Aug 2026 23:06:04 -0700 Subject: [PATCH 56/64] Scope ifStock icon loop objects --- src/melee/if/ifstock.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index f35a4c3997..c982ea9bdf 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -670,7 +670,8 @@ void ifStock_802F98E8(unsigned char player, int b) HSD_JObjSetFlagsAll(ifStock_802F98E8_get_x3C(player), JOBJ_HIDDEN); for (i = 0; i < 7; i++, user_data++) { - icon_jobj = ifStock_804A1378.player[player].x4[i + 1]; + HSD_JObj* icon_jobj = + ifStock_804A1378.player[player].x4[i + 1]; if (i == 0) { user_data[5] = 0; } else { @@ -704,7 +705,8 @@ void ifStock_802F98E8(unsigned char player, int b) HSD_JObjSetFlagsAll(ifStock_804A1378.player[player].x3C, JOBJ_HIDDEN); for (i = 0; i < 7; i++, user_data++) { - icon_jobj = ifStock_804A1378.player[player].x4[i + 1]; + HSD_JObj* icon_jobj = + ifStock_804A1378.player[player].x4[i + 1]; if (i == 0) { user_data[5] = 0; } else { From ebd6ff479390f43515d890624eaf772bc856e244 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Mon, 31 Aug 2026 06:51:10 -0700 Subject: [PATCH 57/64] Model lbColl broadphase coordinates --- src/melee/lb/lbcollision.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/melee/lb/lbcollision.c b/src/melee/lb/lbcollision.c index a3e13230fb..3802105056 100644 --- a/src/melee/lb/lbcollision.c +++ b/src/melee/lb/lbcollision.c @@ -1064,11 +1064,11 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, float hit_end_x; float hit_len_sq; float hit_end_mid_x; - float hit_end_y; + float hit_start_y; float hit_start_max_z; float hit_start_min_z; float hurt_closest_z; - float hit_end_z; + float hit_start_z; float segment_dot; float hurt_end_y; float hit_param; @@ -1125,12 +1125,13 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, return 0; } block_13: - if (hit_start_copy.y > (hit_end_y = hit_end->y)) { - y_work = hit_start_copy.y + broadphase_radius; + hit_start_y = hit_start_copy.y; + if (hit_start_y > hit_end->y) { + y_work = hit_start_y + broadphase_radius; if ((y_work < hurt_start_copy.y) && (y_work < hurt_end->y)) { return 0; } - hit_end_min_y = hit_end_y - broadphase_radius; + hit_end_min_y = hit_end->y - broadphase_radius; if ((hit_end_min_y > hurt_start_copy.y) && (hit_end_min_y > hurt_end->y)) { @@ -1138,25 +1139,26 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, } goto block_26; } - hit_start_min_y = hit_start_copy.y - broadphase_radius; + hit_start_min_y = hit_start_y - broadphase_radius; if ((hit_start_min_y > hurt_start_copy.y) && (hit_start_min_y > hurt_end->y)) { return 0; } - hit_end_max_y = hit_end_y + broadphase_radius; + hit_end_max_y = hit_end->y + broadphase_radius; if ((hit_end_max_y < hurt_start_copy.y) && (hit_end_max_y < hurt_end->y)) { return 0; } block_26: - if (hit_start_copy.z > (hit_end_z = hit_end->z)) { - hit_start_max_z = hit_start_copy.z + broadphase_radius; + hit_start_z = hit_start_copy.z; + if (hit_start_z > hit_end->z) { + hit_start_max_z = hit_start_z + broadphase_radius; if ((hit_start_max_z < hurt_start_copy.z) && (hit_start_max_z < hurt_end->z)) { return 0; } - hit_end_min_z = hit_end_z - broadphase_radius; + hit_end_min_z = hit_end->z - broadphase_radius; if ((hit_end_min_z > hurt_start_copy.z) && (hit_end_min_z > hurt_end->z)) { @@ -1164,13 +1166,13 @@ bool lbColl_80006E58(Vec3* hit_start, Vec3* hit_end, Vec3* hurt_start, } goto block_39; } - hit_start_min_z = hit_start_copy.z - broadphase_radius; + hit_start_min_z = hit_start_z - broadphase_radius; if ((hit_start_min_z > hurt_start_copy.z) && (hit_start_min_z > hurt_end->z)) { return 0; } - hit_end_max_z = hit_end_z; + hit_end_max_z = hit_end->z; hit_end_max_z += broadphase_radius; if ((hit_end_max_z < hurt_start_copy.z) && (hit_end_max_z < hurt_end->z)) { return 0; From d2caa7703a17b4e97307f1bc63f5654811088382 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2026 03:52:28 -0700 Subject: [PATCH 58/64] Improve ifStock matching after upstream sync --- src/melee/if/ifstock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 47b0f0ce35..dd557d6950 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -659,8 +659,7 @@ void ifStock_802F98E8(unsigned char player, int b) (void) &stock->player[player = player]; #endif user_data = ((struct IfStockData*) stock)[player].x0; - *(user_data += sizeof(struct IfStockDataOffset) - - sizeof(struct IfStockData)) = player; + *(user_data += sizeof(struct IfStockDataOffset)) = player; stock->x204[player].x0[1] = b; stock->x204[player].x0[2] = 1; if (stock->player[player].x0 != NULL) { @@ -907,6 +906,7 @@ void ifStock_802FA5BC(int arg) lb_80011E24(jobj, &ifStock_804A1378.jobj, 0, 1, 2, 3, 4, 5, -1); } +#pragma dont_inline on void fn_802FA6C4(HSD_GObj* arg) { int i; @@ -949,6 +949,7 @@ void fn_802FA6C4(HSD_GObj* arg) ifStock_804A1774.x0 = 0; } } +#pragma dont_inline off void fn_802FA8C0(HSD_GObj* arg) { From a4ad43c93b708e4ff7de59f899e98924bb55d643 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2026 04:04:50 -0700 Subject: [PATCH 59/64] Restore exact ftCo floor target match --- src/melee/ft/chara/ftCommon/ftCo_0A01.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/melee/ft/chara/ftCommon/ftCo_0A01.c b/src/melee/ft/chara/ftCommon/ftCo_0A01.c index f3858212fd..279303becc 100644 --- a/src/melee/ft/chara/ftCommon/ftCo_0A01.c +++ b/src/melee/ft/chara/ftCommon/ftCo_0A01.c @@ -3668,7 +3668,7 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) Vec3 floor_normal; int line_id; u32 flags; - u8 _[0x14]; + u8 _[0x18]; Vec3 sp18; f32 fx; f32 fy; @@ -3686,11 +3686,24 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) f32 below; f32 above; fy = fp1->cur_pos.y; + blocked = 0; + line_id = -1; below = fy - 1000.0f; above = 10.0f + fy; - result = - ftCo_800A75DC_CheckFloor(fx2, above, fx, below, &floor_pos, - &line_id, &flags, &floor_normal); + result = mpCheckFloor(fx2, above, fx, below, 0.0f, &floor_pos, + &line_id, &flags, &floor_normal, -1, -1, -1, + NULL, (Fighter_GObj*) blocked); + } + if (result != 0) { + int line = line_id; + if (grBigBlue_801EF844(line) || grInishie1_801FCAAC(line) || + grCorneria_801E2D90(line) || grVenom_80206D10(line)) + { + blocked = 1; + } + if (blocked != 0) { + result = 0; + } } if (result != 0) { int* x60; @@ -3721,7 +3734,8 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) } } else { ftCo_800A4768(fp1, &sp18); - ftCo_800A1F3C(fp0, sp18.x, sp18.y, data->x56C + fp1->x1A88.x564); + ftCo_800A1F3C(fp0, sp18.x, sp18.y, + data->x56C + fp1->x1A88.x564); } } else if (ftCo_800A2718(mpIsland_8005AB54(fp1->coll_data.floor.index)) == 0) From fafa06f9f7372ec84f933096ada014da7a5c06aa Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2026 04:14:31 -0700 Subject: [PATCH 60/64] Fix CI checks after matching updates --- src/melee/ft/chara/ftCommon/ftCo_0A01.c | 3 +-- src/melee/if/ifstock.c | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/melee/ft/chara/ftCommon/ftCo_0A01.c b/src/melee/ft/chara/ftCommon/ftCo_0A01.c index 279303becc..d5dd74800e 100644 --- a/src/melee/ft/chara/ftCommon/ftCo_0A01.c +++ b/src/melee/ft/chara/ftCommon/ftCo_0A01.c @@ -3734,8 +3734,7 @@ void ftCo_800A75DC(Fighter* fp0, Fighter* fp1) } } else { ftCo_800A4768(fp1, &sp18); - ftCo_800A1F3C(fp0, sp18.x, sp18.y, - data->x56C + fp1->x1A88.x564); + ftCo_800A1F3C(fp0, sp18.x, sp18.y, data->x56C + fp1->x1A88.x564); } } else if (ftCo_800A2718(mpIsland_8005AB54(fp1->coll_data.floor.index)) == 0) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index dd557d6950..e13b555001 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -906,7 +906,9 @@ void ifStock_802FA5BC(int arg) lb_80011E24(jobj, &ifStock_804A1378.jobj, 0, 1, 2, 3, 4, 5, -1); } +#ifdef MUST_MATCH #pragma dont_inline on +#endif void fn_802FA6C4(HSD_GObj* arg) { int i; @@ -949,7 +951,9 @@ void fn_802FA6C4(HSD_GObj* arg) ifStock_804A1774.x0 = 0; } } +#ifdef MUST_MATCH #pragma dont_inline off +#endif void fn_802FA8C0(HSD_GObj* arg) { From 11549ab93d977358ae77262bb6354df6de47d3cd Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2026 07:51:09 -0700 Subject: [PATCH 61/64] Improve ifstock translation matches --- src/melee/if/ifstock.c | 54 +++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index e13b555001..816a3def3c 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -50,6 +50,31 @@ struct IfStockDataOffset { unsigned char x0[0x204]; }; +static char ifStock_802F98E8_scene_models[] = "Stc_scemdls"; +static char ifStock_802F98E8_translate[12] = "translate"; + +static inline void ifStock_SetTranslate(HSD_JObj* jobj, Vec3* translate) +{ + if (jobj == NULL) { + __assert("jobj.h", 916, "jobj"); + } + if (translate == NULL) { + __assert("jobj.h", 917, ifStock_802F98E8_translate); + } + jobj->translate = *translate; + if (!(jobj->flags & JOBJ_MTX_INDEP_SRT)) { + HSD_JObjSetMtxDirty(jobj); + } +} + +static inline void ifStock_GetTranslation(HSD_JObj* jobj, Vec3* translate) +{ + jobj ? (void) 0 : __assert("jobj.h", 979, "jobj"); + translate ? (void) 0 + : __assert("jobj.h", 980, ifStock_802F98E8_translate); + *translate = jobj->translate; +} + int ifStock_802F7EFC(int arg0, int arg1) { Vec3 pos; @@ -95,10 +120,10 @@ int ifStock_802F7EFC(int arg0, int arg1) } j = i != 0 ? stocks : 1; } - HSD_JObjGetTranslation(stock->player[arg1].x4[0], &pos); + ifStock_GetTranslation(stock->player[arg1].x4[0], &pos); HSD_JObjReqAnimAll(stock->player[arg1].x4[j], 0.0f); HSD_JObjAnimAll(stock->player[arg1].x4[j]); - HSD_JObjGetTranslation(stock->player[arg1].x4[j], + ifStock_GetTranslation(stock->player[arg1].x4[j], &arg1_data->anim[slot - 5].start); arg1_data->anim[slot - 5].start.x += pos.x; arg1_data->anim[slot - 5].start.y += pos.y; @@ -107,11 +132,11 @@ int ifStock_802F7EFC(int arg0, int arg1) j = i != 0 ? Player_GetStocks(arg0) : 0; { HSD_JObj* jobj = stock->player[arg0].x4[0]; - HSD_JObjGetTranslation(jobj, &pos); + ifStock_GetTranslation(jobj, &pos); } HSD_JObjReqAnimAll(stock->player[arg0].x4[j], 0.0f); HSD_JObjAnimAll(stock->player[arg0].x4[j]); - HSD_JObjGetTranslation(stock->player[arg0].x4[1], + ifStock_GetTranslation(stock->player[arg0].x4[1], &arg1_data->anim[slot - 5].end); arg1_data->anim[slot - 5].end.x += (2.4f * j) + pos.x; arg1_data->anim[slot - 5].end.y = arg1_data->anim[slot - 5].start.y; @@ -215,8 +240,8 @@ void ifStock_802F8298(HSD_GObj* gobj) if (ifStock_802F8298_get_data(stock)[user_data->player] .x0[i + 5] == 0) { - HSD_JObjGetTranslation(jobj, &vecA); - HSD_JObjGetTranslation( + HSD_JObjGetTranslation2(jobj, &vecA); + HSD_JObjGetTranslation2( stock->player[user_data->player].x4[i + 1], &vecB); vecB.x += vecA.x; vecB.y += vecA.y; @@ -284,12 +309,18 @@ void ifStock_802F8298(HSD_GObj* gobj) stock->x204[user_data->player].x0[anim_offset], &vecC, 0.1f * data[i + 5]); } - HSD_JObjGetTranslation(stock->player[user_data->player].x4[0], - &vecD); + HSD_JObjGetTranslation2( + stock->player[user_data->player].x4[0], &vecD); vecC.x -= vecD.x; vecC.y -= vecD.y; vecC.z -= vecD.z; - HSD_JObjSetTranslate(jobj2, &vecC); + if (jobj2 == NULL) { + __assert("jobj.h", 916, "jobj"); + } + jobj2->translate = vecC; + if (!(jobj2->flags & JOBJ_MTX_INDEP_SRT)) { + HSD_JObjSetMtxDirty(jobj2); + } if (stock->x204[user_data->player].x0[i + 5] == 1) { vecC.x = ((struct IfStockStealAnim*) &stock @@ -675,7 +706,8 @@ void ifStock_802F98E8(unsigned char player, int b) gm_8016895C(jobj, *stock->x0, 0); HSD_JObjReqAnimAll(jobj, 0.0f); HSD_GObj_SetupProc(gobj, fn_802F9410, 17); - HSD_JObjSetTranslate(jobj, ifAll_GetPlayerHUDPosition(player)); + ifStock_SetTranslate(jobj, + ifAll_GetPlayerHUDPosition(player)); lb_80011E24(jobj, ifStock_804A1378.player[player].x4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1); @@ -1099,7 +1131,7 @@ void ifStock_802FAEC4(void) memzero(&ifStock_804A1A8C, sizeof(ifStock_804A1A8C)); memzero(&ifStock_804A1774, sizeof(ifStock_804A1774)); lbArchive_LoadSections(*ifAll_GetArchive(), (void**) &scene_models, - "Stc_scemdls", 0); + ifStock_802F98E8_scene_models, 0); stock->x0 = scene_models; stock->x4 = scene_models[1]; ifStock_804A1ACC.x108 = NULL; From 97c45fd251a2d2b3253e87b9f46444f407a1a337 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2026 09:26:46 -0700 Subject: [PATCH 62/64] Use canonical JObj translation inlines --- src/melee/if/ifstock.c | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 816a3def3c..12880d6a6a 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -50,30 +50,7 @@ struct IfStockDataOffset { unsigned char x0[0x204]; }; -static char ifStock_802F98E8_scene_models[] = "Stc_scemdls"; -static char ifStock_802F98E8_translate[12] = "translate"; - -static inline void ifStock_SetTranslate(HSD_JObj* jobj, Vec3* translate) -{ - if (jobj == NULL) { - __assert("jobj.h", 916, "jobj"); - } - if (translate == NULL) { - __assert("jobj.h", 917, ifStock_802F98E8_translate); - } - jobj->translate = *translate; - if (!(jobj->flags & JOBJ_MTX_INDEP_SRT)) { - HSD_JObjSetMtxDirty(jobj); - } -} - -static inline void ifStock_GetTranslation(HSD_JObj* jobj, Vec3* translate) -{ - jobj ? (void) 0 : __assert("jobj.h", 979, "jobj"); - translate ? (void) 0 - : __assert("jobj.h", 980, ifStock_802F98E8_translate); - *translate = jobj->translate; -} +static char ifStock_SceneModels[] = "Stc_scemdls"; int ifStock_802F7EFC(int arg0, int arg1) { @@ -120,10 +97,10 @@ int ifStock_802F7EFC(int arg0, int arg1) } j = i != 0 ? stocks : 1; } - ifStock_GetTranslation(stock->player[arg1].x4[0], &pos); + HSD_JObjGetTranslation(stock->player[arg1].x4[0], &pos); HSD_JObjReqAnimAll(stock->player[arg1].x4[j], 0.0f); HSD_JObjAnimAll(stock->player[arg1].x4[j]); - ifStock_GetTranslation(stock->player[arg1].x4[j], + HSD_JObjGetTranslation(stock->player[arg1].x4[j], &arg1_data->anim[slot - 5].start); arg1_data->anim[slot - 5].start.x += pos.x; arg1_data->anim[slot - 5].start.y += pos.y; @@ -132,11 +109,11 @@ int ifStock_802F7EFC(int arg0, int arg1) j = i != 0 ? Player_GetStocks(arg0) : 0; { HSD_JObj* jobj = stock->player[arg0].x4[0]; - ifStock_GetTranslation(jobj, &pos); + HSD_JObjGetTranslation(jobj, &pos); } HSD_JObjReqAnimAll(stock->player[arg0].x4[j], 0.0f); HSD_JObjAnimAll(stock->player[arg0].x4[j]); - ifStock_GetTranslation(stock->player[arg0].x4[1], + HSD_JObjGetTranslation(stock->player[arg0].x4[1], &arg1_data->anim[slot - 5].end); arg1_data->anim[slot - 5].end.x += (2.4f * j) + pos.x; arg1_data->anim[slot - 5].end.y = arg1_data->anim[slot - 5].start.y; @@ -706,7 +683,7 @@ void ifStock_802F98E8(unsigned char player, int b) gm_8016895C(jobj, *stock->x0, 0); HSD_JObjReqAnimAll(jobj, 0.0f); HSD_GObj_SetupProc(gobj, fn_802F9410, 17); - ifStock_SetTranslate(jobj, + HSD_JObjSetTranslate(jobj, ifAll_GetPlayerHUDPosition(player)); lb_80011E24(jobj, ifStock_804A1378.player[player].x4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, @@ -1131,7 +1108,7 @@ void ifStock_802FAEC4(void) memzero(&ifStock_804A1A8C, sizeof(ifStock_804A1A8C)); memzero(&ifStock_804A1774, sizeof(ifStock_804A1774)); lbArchive_LoadSections(*ifAll_GetArchive(), (void**) &scene_models, - ifStock_802F98E8_scene_models, 0); + ifStock_SceneModels, 0); stock->x0 = scene_models; stock->x4 = scene_models[1]; ifStock_804A1ACC.x108 = NULL; From 26c730da73f2cc5c7b784d3982dcc6275649032f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2026 09:34:18 -0700 Subject: [PATCH 63/64] Fix ifstock formatting --- src/melee/if/ifstock.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/melee/if/ifstock.c b/src/melee/if/ifstock.c index 12880d6a6a..1a04cdf32c 100644 --- a/src/melee/if/ifstock.c +++ b/src/melee/if/ifstock.c @@ -286,8 +286,8 @@ void ifStock_802F8298(HSD_GObj* gobj) stock->x204[user_data->player].x0[anim_offset], &vecC, 0.1f * data[i + 5]); } - HSD_JObjGetTranslation2( - stock->player[user_data->player].x4[0], &vecD); + HSD_JObjGetTranslation2(stock->player[user_data->player].x4[0], + &vecD); vecC.x -= vecD.x; vecC.y -= vecD.y; vecC.z -= vecD.z; @@ -683,8 +683,7 @@ void ifStock_802F98E8(unsigned char player, int b) gm_8016895C(jobj, *stock->x0, 0); HSD_JObjReqAnimAll(jobj, 0.0f); HSD_GObj_SetupProc(gobj, fn_802F9410, 17); - HSD_JObjSetTranslate(jobj, - ifAll_GetPlayerHUDPosition(player)); + HSD_JObjSetTranslate(jobj, ifAll_GetPlayerHUDPosition(player)); lb_80011E24(jobj, ifStock_804A1378.player[player].x4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1); From 4ca75ee69d316d1bc62608a50b9fada3c5549758 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 1 Sep 2026 09:48:27 -0700 Subject: [PATCH 64/64] Restore afterimage match after master update --- src/melee/ft/ftafterimage.c | 103 +++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/src/melee/ft/ftafterimage.c b/src/melee/ft/ftafterimage.c index 11c450e666..aaa1de0cec 100644 --- a/src/melee/ft/ftafterimage.c +++ b/src/melee/ft/ftafterimage.c @@ -26,44 +26,9 @@ typedef struct AfterimageVtx { #define AFTERIMAGE_ANGLE_STEP 0.0872664600610733f -void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) +static inline itSword_UnkBytes* ftCo_800C2600_get_params(Fighter* fp) { - Fighter* fp; itSword_UnkBytes* params; - UNUSED f32 inner_pad[1]; - f32 cumDist[3]; - AfterimageVtx vtx_buf[152]; - f32* distPtr; - f32 d2; - - if (arg1 != 2) { - return; - } - - { - void* fighter = gobj->user_data; - fp = fighter; - } - - if ((s8) (u8) fp->x2100 <= 1) { - return; - } - - GXSetColorUpdate(1); - GXSetAlphaUpdate(0); - GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); - GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0); - GXSetZMode(1, GX_LEQUAL, 0); - GXSetZCompLoc(0); - GXSetNumTexGens(0); - GXSetTevClampMode(0, 0); - GXSetNumTevStages(1); - GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); - GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); - GXSetNumChans(1); - GXSetChanCtrl(GX_COLOR0A0, 0, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, - GX_AF_NONE); - GXSetCullMode(GX_CULL_NONE); if (fp->x2101_bits_8) { switch (itGetKind(fp->item_gobj)) { @@ -96,22 +61,67 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) break; case FTKIND_LINK: case FTKIND_CLINK: { - params = - (itSword_UnkBytes*) &((ftLk_DatAttrs*) fp->dat_attrs)->x64; + ftLk_DatAttrs* da = fp->dat_attrs; + params = (itSword_UnkBytes*) &da->x64; break; } case FTKIND_MARS: case FTKIND_EMBLEM: { - params = - (itSword_UnkBytes*) &((MarsAttributes*) fp->dat_attrs)->x78; + MarsAttributes* da = fp->dat_attrs; + params = (itSword_UnkBytes*) &da->x78; break; } default: break; } } + return params; +} + +void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) +{ + Fighter* fp; + itSword_UnkBytes* params; + f32 cumDist[3]; + AfterimageVtx vtx_buf[152]; + f32 d2; + f32* distPtr; + + if (arg1 != 2) { + return; + } + + { + void* fighter = gobj->user_data; + fp = fighter; + } + + if ((s8) (u8) fp->x2100 <= 1) { + return; + } + + GXSetColorUpdate(1); + GXSetAlphaUpdate(0); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0); + GXSetZMode(1, GX_LEQUAL, 0); + GXSetZCompLoc(0); + GXSetNumTexGens(0); + GXSetTevClampMode(0, 0); + GXSetNumTevStages(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + GXSetNumChans(1); + GXSetChanCtrl(GX_COLOR0A0, 0, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, + GX_AF_NONE); + GXSetCullMode(GX_CULL_NONE); + + params = ftCo_800C2600_get_params(fp); { + s32 remaining; + struct Fighter_x20B0_t* curEntry; + s32 nextIdx; f32 x20F8 = fp->x20F8; f32 x20FC = fp->x20FC; s32 ringIdx; @@ -119,7 +129,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) f32* dp; Vec3 prevPos, delta, crossProd, tempDir; - PAD_STACK(0x1C); + PAD_STACK(0x14); { s32 idx = fp->x2101_bits_0to6; @@ -141,7 +151,6 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) prevPos.x = prevPos.y = prevPos.z = 0.0f; for (i = (s8) (u8) fp->x2100 - 1; i >= 0; i--) { - s32 nextIdx; struct Fighter_x20B0_t* entry = &fp->x20B0[curIdx]; delta.x = entry->xC.x * x20FC + entry->x0.x - prevPos.x; @@ -171,9 +180,6 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) } { - s32 remaining; - struct Fighter_x20B0_t* curEntry; - s32 nextIdx; s32 numVerts; f32 scaleDiff; s32 curIdx2; @@ -208,6 +214,7 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) f32 outerScale, innerScale; s32 alpha; struct Fighter_x20B0_t* nextEntry; + s32 numSubdiv; curEntry = &fp->x20B0[curIdx2]; outerScale = interpFactor * outerDiff + blendedOuter; @@ -238,7 +245,6 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) if (remaining != 0) { s32 nextRingIdx; - s32 numSubdiv; if (curIdx2 != 0) { nextRingIdx = curIdx2 - 1; @@ -281,10 +287,9 @@ void ftCo_800C2600(Fighter_GObj* gobj, u32 arg1) basePosX = curEntry->x0.x; basePosY = curEntry->x0.y; - basePosZ = curEntry->x0.z; -#ifdef MUST_MATCH (void) basePosY; -#endif + basePosZ = curEntry->x0.z; + stepPosX = frac * (nextEntry->x0.x - basePosX); stepPosY = frac * (nextEntry->x0.y - basePosY); stepPosZ = frac * (nextEntry->x0.z - basePosZ);