From 45aad382eafbd3ae31e7bd92d8f0dcf82ca38b7e Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Mon, 17 Aug 2026 12:25:38 -0600 Subject: [PATCH] =?UTF-8?q?feat(phase-26):=20h=5Fseq=20family=20sweep=20?= =?UTF-8?q?=E2=80=94=2043=20member-matches=20banked=20via=20remap=5Fhseq?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ov_SC02_026/ov_SC02_026_jr_8017C180.c | 204 +++++++- src/ov_SC02_028/ov_SC02_028_jr_8017D898.c | 369 +++++++++++++- src/ov_SC02_028/ov_SC02_028_jr_80184BD8.c | 227 ++++++++- src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c | 591 +++++++++++++++++++++- src/ov_SC03_015/ov_SC03_015_jr_801848E4.c | 246 ++++++++- src/ov_SC03_024/ov_SC03_024_jr_8017DF84.c | 49 +- src/ov_SC03_092/ov_SC03_092_jr_8017AE2C.c | 83 ++- src/ov_SC03_108/ov_SC03_108_jr_8017BEBC.c | 141 +++++- src/ov_SC03_110/ov_SC03_110_jr_8017D898.c | 141 +++++- src/ov_SC04_004/ov_SC04_004_jr_8017AE2C.c | 206 +++++++- src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c | 374 +++++++++++++- src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c | 236 ++++++++- src/ov_SC05_001/ov_SC05_001_jr_8017BEBC.c | 141 +++++- src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c | 289 ++++++++++- 14 files changed, 3240 insertions(+), 57 deletions(-) diff --git a/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c b/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c index 0a8dfa824..d6d267d0a 100644 --- a/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c +++ b/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c @@ -1789,9 +1789,7 @@ extern void func_8016A700(void *a0); extern s32 func_8016A73C(s32 arg0); extern s32 func_8016A8FC(s32 a0); extern void func_8016A890(s32 arg0); -extern u16 D_80126B5E; extern u16 D_80126B62; -extern u16 D_80126B66; extern void func_8016AA50(s32 param_1, s32 param_2); extern void (*D_80189288[])(void); extern void func_8016AB30(void *a0); @@ -3474,7 +3472,88 @@ INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8017C180", func_8017D9D INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8017C180", func_8017DA5C); -INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8017C180", func_8017DAB8); + typedef struct { u8 b[8]; } Blk8_8017DAB8; +typedef struct { + s32 a; /* 0x00 -> D_801DA750 */ + s32 b; /* 0x04 -> D_801DA754 */ +} Pair8_8017DDC4_80182244_8017DAB8; + +/* Sibling shape in the SAME TU: func_80182244 (already banked, line ~3980) + * uses the identical idiom for the same actor kind: void *a0, raw + * (s32)a0+offset field access, func_8012C1B8 cast-called as (s32(*)(void)), + * func_8012CAE4, func_8001C214, and the 0x70-indexed table lookup + 0x1000000 + * OR-flag pattern at (*(s32*)(sub+4)) |= 0x1000000. Adopted as a structural + * hint only (law 1) — none of its per-location symbols are reused here. */ + +extern void func_8012C1B8(void); +extern void func_8012CAE4(void *a0); +extern s32 func_80029178(s32 a0); +extern void func_8001C214(s32 a0, s32 a1); +extern s32 func_8012AD50(void *a0); + +/* idx = *(s16*)(a0+0x70): lhu direct load, 2-byte stride -> u16 table */ + +/* address-of only in the target (lui/addiu, no load/store through it here) */ + +void func_8017DAB8(s32 a0) +{ + + extern u16 D_801A429C[]; + extern u8 D_801A428C; + extern u8 D_801A427C; + if ((*(s32 *)(a0 + 0x20) = ((s32 (*)(void))func_8012C1B8)()) == 0) { + func_8012CAE4((void *)a0); + return; + } + + if ((func_80029178((s32)D_801A429C[*(s16 *)(a0 + 0x70)]) & 0xFF) != 0) { + register s32 s0 __asm__("$16") = *(s32 *)(a0 + 0xDC); + if (s0 != 0) { + s32 a1 = *(s32 *)(s0 + 0x4); + if (a1 != 0) { + func_8001C214(*(s32 *)(a0 + 0x20), a1); + if (*(s32 *)(s0 + 0xC) != 0) { + s32 v1 = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4); + v1 |= 0x1000000; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4) = v1; + } + } + } + func_8012AD50((void *)a0); + goto tail; + } + + { + register s32 s0 __asm__("$16") = *(s32 *)(a0 + 0xDC); + register s32 flag __asm__("$2") = 1; + if (s0 != 0) { + s32 a1 = *(s32 *)s0; + if (a1 != 0) { + func_8001C214(*(s32 *)(a0 + 0x20), a1); + if (*(s32 *)(s0 + 0xC) != 0) { + s32 v1 = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4); + v1 |= 0x1000000; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4) = v1; + } + flag = 1; + } + } + *(u8 *)(a0 + 0xC0) = flag; + } + + *(s32 *)(a0 + 0xBC) = (s32)&D_801A428C; + *(s32 *)(a0 + 0x58) = (s32)&D_801A427C | 0x40000000; + *(u16 *)(a0 + 0x5C) = 0x8800; + *(s32 *)(a0 + 0xB4) = 0; + *(u8 *)(a0 + 0xC1) = 0; + *(u16 *)(a0 + 0xAE) = 0x7FFF; + *(u8 *)(a0 + 0x75) = 0; + *(s32 *)(a0 + 0xC4) |= 0x2; + +tail: + func_8012AD50((void *)a0); +} + // @class: struct @@ -3638,7 +3717,124 @@ INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8017C180", func_8017E59 INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8017C180", func_8017E654); -INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8017C180", func_8017E72C); + typedef struct { u8 b[8]; } Blk8_8017E72C; + typedef struct { + u8 c[8]; + } Blk8_80186594_8017E72C; +typedef struct { + s32 a; /* 0x00 -> D_801DA750 */ + s32 b; /* 0x04 -> D_801DA754 */ +} Pair8_8017DDC4_80182244_8017E72C; + +/* func_8017E72C -- ov_SC02_027, subseg ov_SC02_027_jr_8017D898 (106 ins). + * Mass-lane fresh crack. Nearest exemplar ov_SC02_026:func_8017E72C is still + * unmatched (INCLUDE_ASM), so no cousin body to adapt -- built straight from + * the target .s. + * + * Symbol provenance: + * func_8012E9C0 NOT declared anywhere in this TU (only inside the + * engine_core.h DEFINE_func_8012E9C0 macro, unexpanded + * here) -> declared fresh, `void (int)`, no conflict. + * func_8002A520 NOT declared in this TU; matches the sibling-TU form + * seen in ov_SC03_006/099 etc's jr_8012ACE0.c: `void (void*)`. + * func_8002A790 same as above, `void (void*)`. + * D_80126B5E TU col-0 decl (this file:1789), adopted verbatim `extern u16` + * D_80126B62 TU local-scope decl (this file:4233/6455/6538), + * adopted verbatim `extern u16` + * D_80126B66 TU col-0 decl (this file:1790), adopted verbatim `extern u16` + * VectorNormalSS TU col-0 decl (this file:1846), adopted verbatim `s32 (void*,void*)` + * func_80131E00 TU local-scope decl (this file:6734/6813/6981), + * adopted verbatim `void (void*, s32)` + * func_8012A828 TU col-0/local decl (this file:4380 et al), adopted + * verbatim `void (s32, s32)` + * D_801A9D90 not declared anywhere in-tree yet; passed as a bare + * lui/addiu address (no load) -> declared as u8[] here. + * + * Residual-class note: field 0x76 is read (u16, for the decrement), stored, + * then read AGAIN (s16, for the <=0 test). A plain second dereference of the + * same `(u8*)a0+0x76` expression lets gcc-2.7.2's cse.c reuse the just-stored + * HImode value and synthesize the sign test via `sll $r,16` instead of a + * genuine `lh` -- confirmed by isolated probes (adds 1 spurious instruction, + * every time another independent load/store shares the block, regardless of + * source statement order or an intervening asm memory-clobber). Fix: (1) an + * `__asm__ __volatile__("" ::: "memory")` between the store and the reload + * to pin ordering, AND (2) drop the named `cnt`/`flags` locals in favor of + * inlining both the 0x5C read-modify-write and the 0x76 compare directly at + * their use sites -- naming the intermediate values reintroduces the same + * cse fold even behind the barrier. Both edits were required together. + */ + +extern void func_8012E9C0(int param_1); +extern void func_8002A520(void *a0); +extern void func_8002A790(void *a0); +extern s32 VectorNormalSS(void *a0, void *a1); +extern void func_80131E00(void *a0, s32 a1); +extern void func_8012A828(s32 a0, s32 a1); + +void func_8017E72C(void *a0) { + + extern u16 D_80126B5E; + extern u16 D_80126B66; + extern u8 D_801A9D90[]; + u16 sv[4]; + s32 speed; + + func_8012E9C0((s32)a0); + + if (*(u16 *)((u8 *)a0 + 0x5E) != 0x1D) { + if (*(u8 *)((u8 *)a0 + 0xC8)) { + func_8002A520(a0); + } + if (*(u8 *)((u8 *)a0 + 0xC9)) { + func_8002A790(a0); + } + } + + { + s32 base = *(s32 *)((u8 *)a0 + 0x78); + speed = (*(s16 *)((u8 *)a0 + 0x60) * *(s16 *)(base + 0x30)) >> 12; + } + if (speed <= 0) { + speed = 1; + } + + *(u16 *)((u8 *)a0 + 0x76) = *(u16 *)((u8 *)a0 + 0x76) - speed; + __asm__ __volatile__("" ::: "memory"); + + { + *(u16 *)((u8 *)a0 + 0x5C) = *(u16 *)((u8 *)a0 + 0x5C) & 0xFFFE; + if (*(s16 *)((u8 *)a0 + 0x76) <= 0) { + *(u16 *)((u8 *)a0 + 0x5C) = 0; + func_80131E00(a0, 0xE); + } else { + if (speed > 0x10) { + speed = 0x10; + } + + sv[0] = *(u16 *)((u8 *)a0 + 6) - D_80126B5E; + sv[1] = *(u16 *)((u8 *)a0 + 0xA) - D_80126B62; + sv[2] = *(u16 *)((u8 *)a0 + 0xE) - D_80126B66; + VectorNormalSS(sv, (u8 *)a0 + 0x102); + + speed += 8; + { + s32 p0 = speed * *(s16 *)((u8 *)a0 + 0x102); + s32 p1 = speed * *(s16 *)((u8 *)a0 + 0x104); + s32 p2 = speed * *(s16 *)((u8 *)a0 + 0x106); + *(s32 *)((u8 *)a0 + 0x1C) = 0x10; + *(s16 *)((u8 *)a0 + 0x102) = p0 >> 12; + *(s16 *)((u8 *)a0 + 0x104) = p1 >> 12; + *(s16 *)((u8 *)a0 + 0x106) = p2 >> 12; + } + } + } + + *(s16 *)((u8 *)a0 + 6) = *(u16 *)((u8 *)a0 + 0x88); + *(s16 *)((u8 *)a0 + 0xA) = *(u16 *)((u8 *)a0 + 0x8A); + *(s16 *)((u8 *)a0 + 0xE) = *(u16 *)((u8 *)a0 + 0x8C); + func_8012A828((s32)a0, (s32)D_801A9D90); +} + INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8017C180", func_8017E8D4); diff --git a/src/ov_SC02_028/ov_SC02_028_jr_8017D898.c b/src/ov_SC02_028/ov_SC02_028_jr_8017D898.c index 6fcc63748..f57204394 100644 --- a/src/ov_SC02_028/ov_SC02_028_jr_8017D898.c +++ b/src/ov_SC02_028/ov_SC02_028_jr_8017D898.c @@ -3766,7 +3766,88 @@ void func_8017FF68(void *a0, s32 a1) INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_8017FFC8); -INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_80180040); + typedef struct { u8 b[8]; } Blk8_80180040; +typedef struct { + s32 a; /* 0x00 -> D_801DA750 */ + s32 b; /* 0x04 -> D_801DA754 */ +} Pair8_8017DDC4_80182244_80180040; + +/* Sibling shape in the SAME TU: func_80182244 (already banked, line ~3980) + * uses the identical idiom for the same actor kind: void *a0, raw + * (s32)a0+offset field access, func_8012C1B8 cast-called as (s32(*)(void)), + * func_8012CAE4, func_8001C214, and the 0x70-indexed table lookup + 0x1000000 + * OR-flag pattern at (*(s32*)(sub+4)) |= 0x1000000. Adopted as a structural + * hint only (law 1) — none of its per-location symbols are reused here. */ + +extern void func_8012C1B8(void); +extern void func_8012CAE4(void *a0); +extern s32 func_80029178(s32 a0); +extern void func_8001C214(s32 a0, s32 a1); +extern s32 func_8012AD50(void *a0); + +/* idx = *(s16*)(a0+0x70): lhu direct load, 2-byte stride -> u16 table */ + +/* address-of only in the target (lui/addiu, no load/store through it here) */ + +void func_80180040(s32 a0) +{ + + extern u16 D_801A4C1C[]; + extern u8 D_801A4C0C; + extern u8 D_801A4BFC; + if ((*(s32 *)(a0 + 0x20) = ((s32 (*)(void))func_8012C1B8)()) == 0) { + func_8012CAE4((void *)a0); + return; + } + + if ((func_80029178((s32)D_801A4C1C[*(s16 *)(a0 + 0x70)]) & 0xFF) != 0) { + register s32 s0 __asm__("$16") = *(s32 *)(a0 + 0xDC); + if (s0 != 0) { + s32 a1 = *(s32 *)(s0 + 0x4); + if (a1 != 0) { + func_8001C214(*(s32 *)(a0 + 0x20), a1); + if (*(s32 *)(s0 + 0xC) != 0) { + s32 v1 = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4); + v1 |= 0x1000000; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4) = v1; + } + } + } + func_8012AD50((void *)a0); + goto tail; + } + + { + register s32 s0 __asm__("$16") = *(s32 *)(a0 + 0xDC); + register s32 flag __asm__("$2") = 1; + if (s0 != 0) { + s32 a1 = *(s32 *)s0; + if (a1 != 0) { + func_8001C214(*(s32 *)(a0 + 0x20), a1); + if (*(s32 *)(s0 + 0xC) != 0) { + s32 v1 = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4); + v1 |= 0x1000000; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4) = v1; + } + flag = 1; + } + } + *(u8 *)(a0 + 0xC0) = flag; + } + + *(s32 *)(a0 + 0xBC) = (s32)&D_801A4C0C; + *(s32 *)(a0 + 0x58) = (s32)&D_801A4BFC | 0x40000000; + *(u16 *)(a0 + 0x5C) = 0x8800; + *(s32 *)(a0 + 0xB4) = 0; + *(u8 *)(a0 + 0xC1) = 0; + *(u16 *)(a0 + 0xAE) = 0x7FFF; + *(u8 *)(a0 + 0x75) = 0; + *(s32 *)(a0 + 0xC4) |= 0x2; + +tail: + func_8012AD50((void *)a0); +} + // @class: struct @@ -3934,7 +4015,98 @@ INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_801808D INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_80180930); -INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_80180970); + typedef struct { u8 b[8]; } Blk8_80180970; +typedef struct { + s32 a; /* 0x00 -> D_801DA750 */ + s32 b; /* 0x04 -> D_801DA754 */ +} Pair8_8017DDC4_80182244_80180970; + +/* stride-8 tables, only the field-0 short of each record is ever read by + * this function; each is a SEPARATE relocation symbol in the target .s + * (D_801A4D0C/672/674/676 are 2/4/6/8 bytes apart but referenced as four + * independently-based arrays, never as one array + constant offset). */ +typedef struct { u16 v; u16 pad[3]; } Stride8_u16_80182868_80180970; +typedef struct { s16 v; s16 pad[3]; } Stride8_s16_80182868_80180970; + +void func_80180970(void *a0) +{ + extern void func_8012C1B8(void); + extern void func_8012CAE4(void *a0); + extern void func_8001C214(s32 a0, s32 a1); + extern s32 func_80029178(s32); + extern void func_80180B4C(void *a0); + + extern s32 D_801A6578; + extern s32 D_801A4CFC[]; + extern Stride8_u16_80182868_80180970 D_801A4D0C[]; + extern Stride8_u16_80182868_80180970 D_801A4D0E[]; + extern Stride8_u16_80182868_80180970 D_801A4D10[]; + extern Stride8_s16_80182868_80180970 D_801A4D12[]; + extern s16 D_801A4CC0[]; + + s32 v0; + s16 state; + s16 i; + s16 id; + + if ((*(s32 *)((s32)a0 + 0x20) = v0 = ((s32 (*)(void))func_8012C1B8)()) == 0) { + func_8012CAE4(a0); + return; + } + + /* §67: launder v0 at the statement where the target's `addu a0,v0,zero` + * copy actually lands (the func_8001C214 call site), not right after + * func_8012C1B8 returns -- an unconstrained copy gets hoisted early. */ + __asm__ __volatile__("" : "=r"(v0) : "0"(v0)); + func_8001C214(v0, (s32)&D_801A6578); + + *(u32 *)(*(s32 *)((s32)a0 + 0x20) + 0x28) = 0x2000200; + + *(u32 *)((s32)a0 + 0x58) = (s32)D_801A4CFC | 0x10000000; + + *(u8 *)((s32)a0 + 0x75) = 0; + if (*(s16 *)((s32)a0 + 0x70) == 1) { + *(s32 *)(*(s32 *)((s32)a0 + 0x20) + 0x4) |= 0x80000000; + *(u16 *)((s32)a0 + 0x5C) = 0; + } else { + *(u16 *)((s32)a0 + 0x5C) = 0xCC00; + } + + *(s16 *)((s32)a0 + 0x6) = D_801A4D0C[*(s16 *)((s32)a0 + 0x70)].v; + *(s16 *)((s32)a0 + 0xA) = D_801A4D0E[*(s16 *)((s32)a0 + 0x70)].v; + *(s16 *)((s32)a0 + 0xE) = D_801A4D10[*(s16 *)((s32)a0 + 0x70)].v; + func_80180B4C(a0); + + if (*(s16 *)((s32)a0 + 0x70) == 3) { + *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x10) = 0x800; + } + + if ((func_80029178(0xAE) & 0xFF) == 0) { + return; + } + + if (D_801A4CC0[0] != 0) { + state = *(s16 *)((s32)a0 + 0x70); + i = 0; + for (;;) { + id = D_801A4CC0[i + 1]; + if (id == state) { + if (id >= 2) { + if (D_801A4D12[id].v != 0) { + *(s16 *)((s32)a0 + 0x6) -= 0x200; + } else { + *(s16 *)((s32)a0 + 0x6) += 0x200; + } + } + } + i += 2; + if (D_801A4CC0[i] == 0) { + break; + } + } + } +} + INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_80180B4C); @@ -3998,7 +4170,65 @@ INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_801814A INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_80181520); -INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_801815F0); + +extern void func_8012C1B8(void); +extern void func_8012CAE4(void *a0); +extern void func_8001C810(s32 a0, s32 a1); +extern void func_80178B18(s32, s32); +extern void func_801817B8(void *arg0); +extern void func_80181760(void *arg0); +extern void func_80181A20(void *arg0); + +void func_801815F0(void *a0) +{ + extern u16 D_801A4DD4[][4]; + extern u16 D_801A4DD6[][4]; + extern u16 D_801A4DD8[][4]; + extern u16 D_801A4DDA[][4]; + extern s32 D_801A6958; + extern s32 D_801A4DE4; + extern s32 D_801A4DF4; + + s32 v0; + + /* §162-style: fold the store AND the test into ONE expression so cc1 + * keeps the call's return value live in $v0 for the following call. */ + if ((v0 = *(s32 *)((s32)a0 + 0x20) = ((s32 (*)(void))func_8012C1B8)()) == 0) { + func_8012CAE4(a0); + return; + } + + func_8001C810(v0, (s32)&D_801A6958); + + *(s32 *)(*(s32 *)((s32)a0 + 0x20) + 0x4) |= 0x8040; + *(s16 *)(*(s32 *)((s32)a0 + 0x20) + 0x12) = + D_801A4DDA[*(s16 *)((s32)a0 + 0x70)][0]; + + if (*(s16 *)((s32)a0 + 0x70) < 2) { + *(s32 *)((s32)a0 + 0x58) = (s32)&D_801A4DE4 | 0x40000000; + *(u16 *)((s32)a0 + 0x5C) = 0xC400; + *(u8 *)((s32)a0 + 0x75) = 0; + *(s16 *)((s32)a0 + 0x6) = + D_801A4DD4[*(s16 *)((s32)a0 + 0x70)][0]; + *(s16 *)((s32)a0 + 0xA) = + D_801A4DD6[*(s16 *)((s32)a0 + 0x70)][0]; + *(s16 *)((s32)a0 + 0xE) = + D_801A4DD8[*(s16 *)((s32)a0 + 0x70)][0]; + + if (*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x100) == 0) { + ((s32 (*)(s32, s32))func_80178B18)((s32)a0, (s32)&D_801A4DF4); + *(s16 *)((s32)a0 + 0xFE) = 1; + *(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0xFE) = 2; + func_80181760(a0); + } else { + *(u16 *)((s32)a0 + 0xA) = *(u16 *)((s32)a0 + 0xA) + 0x280; + func_801817B8(a0); + } + } else { + func_80181A20(a0); + } +} + extern void func_8012AD44(s32 *a0, s16 a1); void func_80181760(void * arg0) { @@ -4017,7 +4247,138 @@ extern void func_8012AD44(s32 *a0, s16 a1); INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_801817B8); -INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_8017D898", func_80181824); + typedef struct { u8 b[8]; } Blk8_80181824; + typedef struct { + u8 c[8]; + } Blk8_80186594_80181824; +typedef struct { + s32 a; /* 0x00 -> D_801DA750 */ + s32 b; /* 0x04 -> D_801DA754 */ +} Pair8_8017DDC4_80182244_80181824; + +/* Declarations copied VERBATIM from the destination TU + * (src/ov_SC02_027/ov_SC02_027_jr_8017D898.c): + * func_8014C088 TU:511 `s32 (s32,s32)` + * func_8002A088 TU:2350 `void (s32)` + * func_8002A2D4 TU:2351 `void (s32)` + * func_8002A544 TU:2352 `void (s32)` + * func_8002A7B4 TU:2353 `void (s32)` + * func_8016AA50 TU:1791 `void (s32,s32)` + * func_80178970 TU:2526 `int (void)` + * func_80178B18 TU:2527 `s32 (s32,s32)` + * func_80178D18 TU:2534 `void (void)` + * func_80029124 TU:500 `void (s32,s32)` + * func_8012BEE8 TU:3912 `s32 (s32)` + * func_801819F0 TU:4178 defined in this TU as `void (s32 *)` + * func_8002D4C8 TU:3708 `void (s32,s32)` + * + * D_801A4DFC / D_801A4DC4 are NOT declared anywhere in this TU yet. + * Declared here in the rawest form the access widths demand (law 4): + * D_801A4DFC is only ever address-of'd (la), never dereferenced by + * this function -> raw scalar is enough. + * D_801A4DC4 is indexed by a signed s16 (sll #1 -> 2-byte stride) and + * read with lhu -> u16 array. + */ +extern s32 func_8014C088(s32 a0, s32 a1); +extern void func_8002A088(s32); +extern void func_8002A2D4(s32); +extern void func_8002A544(s32); +extern void func_8002A7B4(s32); +extern void func_8016AA50(s32 param_1, s32 param_2); +extern int func_80178970(void); +extern void func_80178B18(s32, s32); +extern void func_80178D18(void); +extern void func_80029124(s32 a0, s32 a1); +extern s32 func_8012BEE8(s32 a0); +extern void func_801819F0(void*); +extern void func_8002D4C8(s32 a0, s32 a1); + + +void func_80181824(void *a0) { + + extern void *D_801A4DFC; + extern s32 D_801A4DC4; + u16 sub; + + if (*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0xFE) == 2) { + goto L801838C0; + } + + sub = *(u16 *)((s32)a0 + 0x34); + switch (sub) { + case 1: + goto L8018384C; + case 0: + goto L8018377C; + case 2: + goto L801838B0; + } + return; + +L8018377C: + if (*(s16 *)((s32)a0 + 0x102) != 0) { + goto L801837B0; + } + if (func_8014C088(0, 0xA) != 0) { + *(s16 *)((s32)a0 + 0x102) = 1; + *(u16 *)((s32)a0 + 0x100) = *(u16 *)((s32)a0 + 0x100) + 1; + } + goto L801837DC; + +L801837B0: + if (func_8014C088(0, 0xA) != 0) { + goto L801837DC; + } + *(s16 *)((s32)a0 + 0x102) = 0; + if (*(s16 *)((s32)a0 + 0xFC) != *(s16 *)((s32)a0 + 0x106)) { + *(s16 *)((s32)a0 + 0x104) = 1; + } + +L801837DC: + if (*(s16 *)((s32)a0 + 0xFC) != 0) { + return; + } + if (*(s16 *)((s32)a0 + 0x104) != 0) { + goto L8018382C; + } + func_8002A088(0x64); + func_8002A2D4(0x64); + func_8002A544(0x64); + func_8002A7B4(0x64); + func_8016AA50((s32)a0, -1); + +L8018382C: + *(u16 *)((s32)a0 + 0x34) = *(u16 *)((s32)a0 + 0x34) + 1; + ((s32 (*)(s32, s32))func_80178B18)((s32)a0, (s32)&D_801A4DFC); + return; + +L8018384C: + /* The TU's file-scope decls are `int func_80178970(void)` / `void + * func_80178D18(void)`, but the target fills BOTH call delay slots with + * `addu $a0,$s0,$zero` -- i.e. the original source passed the object + * pointer. Same resolution already banked in the sibling overlay + * (src/ov_SC03_006/ov_SC03_006_jr_8017AE2C.c:4104/4107, func_8017D058): + * keep the TU's declaration and cast AT THE USE (law 4 / §181.4). */ + if (((s32 (*)(s32))func_80178970)((s32)a0) == 0) { + return; + } + ((void (*)(s32))func_80178D18)((s32)a0); + *(u16 *)((s32)a0 + 0x34) = *(u16 *)((s32)a0 + 0x34) + 1; + *(u16 *)(*(s32 *)((s32)a0 + 0x64) + 0x100) = 1; + func_80029124(((u16 *)&D_801A4DC4)[*(s16 *)(*(s32 *)((s32)a0 + 0x64) + 0x70)], 1); + *(s32 *)((s32)a0 + 0x1C) = 0xA0; + return; + +L801838B0: + if (func_8012BEE8((s32)a0) == 0) { + return; + } + +L801838C0: + ((void (*)(s32 *))func_801819F0)((s32 *)a0); + func_8002D4C8(0x6CA, 0); +} + extern void func_8012AD44(s32 *a0, s16 a1); void func_801819F0(void *a0) { diff --git a/src/ov_SC02_028/ov_SC02_028_jr_80184BD8.c b/src/ov_SC02_028/ov_SC02_028_jr_80184BD8.c index a2244bd8e..209f4014b 100644 --- a/src/ov_SC02_028/ov_SC02_028_jr_80184BD8.c +++ b/src/ov_SC02_028/ov_SC02_028_jr_80184BD8.c @@ -1778,8 +1778,6 @@ extern void func_8016A700(void *a0); extern s32 func_8016A73C(s32 arg0); extern s32 func_8016A8FC(s32 a0); extern void func_8016A890(s32 arg0); -extern u16 D_80126B5E; -extern u16 D_80126B66; extern void func_8016AA50(s32 param_1, s32 param_2); extern void (*D_8018E5B0[])(void); extern void func_8016AB30(void *a0); @@ -3600,7 +3598,125 @@ INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_80184BD8", func_801865A INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_80184BD8", func_80186668); -INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_80184BD8", func_80186740); + typedef struct { u8 b[8]; } Blk8_80186740; + typedef struct { + u8 c[8]; + } Blk8_80186594_80186740; +typedef struct { + s32 a; /* 0x00 -> D_801DA750 */ + s32 b; /* 0x04 -> D_801DA754 */ +} Pair8_8017DDC4_80182244_80186740; + +/* func_80186740 -- ov_SC02_027, subseg ov_SC02_027_jr_8017D898 (106 ins). + * Mass-lane fresh crack. Nearest exemplar ov_SC02_026:func_8017E72C is still + * unmatched (INCLUDE_ASM), so no cousin body to adapt -- built straight from + * the target .s. + * + * Symbol provenance: + * func_8012E9C0 NOT declared anywhere in this TU (only inside the + * engine_core.h DEFINE_func_8012E9C0 macro, unexpanded + * here) -> declared fresh, `void (int)`, no conflict. + * func_8002A520 NOT declared in this TU; matches the sibling-TU form + * seen in ov_SC03_006/099 etc's jr_8012ACE0.c: `void (void*)`. + * func_8002A790 same as above, `void (void*)`. + * D_80126B5E TU col-0 decl (this file:1789), adopted verbatim `extern u16` + * D_80126B62 TU local-scope decl (this file:4233/6455/6538), + * adopted verbatim `extern u16` + * D_80126B66 TU col-0 decl (this file:1790), adopted verbatim `extern u16` + * VectorNormalSS TU col-0 decl (this file:1846), adopted verbatim `s32 (void*,void*)` + * func_80131E00 TU local-scope decl (this file:6734/6813/6981), + * adopted verbatim `void (void*, s32)` + * func_8012A828 TU col-0/local decl (this file:4380 et al), adopted + * verbatim `void (s32, s32)` + * D_801AE3A8 not declared anywhere in-tree yet; passed as a bare + * lui/addiu address (no load) -> declared as u8[] here. + * + * Residual-class note: field 0x76 is read (u16, for the decrement), stored, + * then read AGAIN (s16, for the <=0 test). A plain second dereference of the + * same `(u8*)a0+0x76` expression lets gcc-2.7.2's cse.c reuse the just-stored + * HImode value and synthesize the sign test via `sll $r,16` instead of a + * genuine `lh` -- confirmed by isolated probes (adds 1 spurious instruction, + * every time another independent load/store shares the block, regardless of + * source statement order or an intervening asm memory-clobber). Fix: (1) an + * `__asm__ __volatile__("" ::: "memory")` between the store and the reload + * to pin ordering, AND (2) drop the named `cnt`/`flags` locals in favor of + * inlining both the 0x5C read-modify-write and the 0x76 compare directly at + * their use sites -- naming the intermediate values reintroduces the same + * cse fold even behind the barrier. Both edits were required together. + */ + +extern void func_8012E9C0(int param_1); +extern void func_8002A520(void *a0); +extern void func_8002A790(void *a0); +extern s32 VectorNormalSS(void *a0, void *a1); +extern void func_80131E00(void *a0, s32 a1); +extern void func_8012A828(s32 a0, s32 a1); + +void func_80186740(void *a0) { + + extern u16 D_80126B5E; + extern u16 D_80126B66; + extern u8 D_801AE3A8[]; + extern u16 D_80126B62; + u16 sv[4]; + s32 speed; + + func_8012E9C0((s32)a0); + + if (*(u16 *)((u8 *)a0 + 0x5E) != 0x1D) { + if (*(u8 *)((u8 *)a0 + 0xC8)) { + func_8002A520(a0); + } + if (*(u8 *)((u8 *)a0 + 0xC9)) { + func_8002A790(a0); + } + } + + { + s32 base = *(s32 *)((u8 *)a0 + 0x78); + speed = (*(s16 *)((u8 *)a0 + 0x60) * *(s16 *)(base + 0x30)) >> 12; + } + if (speed <= 0) { + speed = 1; + } + + *(u16 *)((u8 *)a0 + 0x76) = *(u16 *)((u8 *)a0 + 0x76) - speed; + __asm__ __volatile__("" ::: "memory"); + + { + *(u16 *)((u8 *)a0 + 0x5C) = *(u16 *)((u8 *)a0 + 0x5C) & 0xFFFE; + if (*(s16 *)((u8 *)a0 + 0x76) <= 0) { + *(u16 *)((u8 *)a0 + 0x5C) = 0; + func_80131E00(a0, 0xE); + } else { + if (speed > 0x10) { + speed = 0x10; + } + + sv[0] = *(u16 *)((u8 *)a0 + 6) - D_80126B5E; + sv[1] = *(u16 *)((u8 *)a0 + 0xA) - D_80126B62; + sv[2] = *(u16 *)((u8 *)a0 + 0xE) - D_80126B66; + VectorNormalSS(sv, (u8 *)a0 + 0x102); + + speed += 8; + { + s32 p0 = speed * *(s16 *)((u8 *)a0 + 0x102); + s32 p1 = speed * *(s16 *)((u8 *)a0 + 0x104); + s32 p2 = speed * *(s16 *)((u8 *)a0 + 0x106); + *(s32 *)((u8 *)a0 + 0x1C) = 0x10; + *(s16 *)((u8 *)a0 + 0x102) = p0 >> 12; + *(s16 *)((u8 *)a0 + 0x104) = p1 >> 12; + *(s16 *)((u8 *)a0 + 0x106) = p2 >> 12; + } + } + } + + *(s16 *)((u8 *)a0 + 6) = *(u16 *)((u8 *)a0 + 0x88); + *(s16 *)((u8 *)a0 + 0xA) = *(u16 *)((u8 *)a0 + 0x8A); + *(s16 *)((u8 *)a0 + 0xE) = *(u16 *)((u8 *)a0 + 0x8C); + func_8012A828((s32)a0, (s32)D_801AE3A8); +} + INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_80184BD8", func_801868E8); @@ -3964,9 +4080,110 @@ s32 func_80187780(s16 *a0, s32 a1, s32 a2, s32 a3) { INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_80184BD8", func_801879E8); -INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_80184BD8", func_80187AD4); -INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028_jr_80184BD8", func_80187C6C); +extern s32 func_8012C354(s32 a0, s32 a1); +extern void func_8012A828(s32 a0, s32 a1); +extern void func_80143970(void *a0); +extern void func_8012B23C(void *a0); + + + +void func_80187AD4(s32 a0) { + + extern u8 D_801AE418[]; + extern u8 D_801AF438[]; + extern u8 D_801AE44C[]; + extern u16 D_801AE3B8[]; + extern u16 D_801AE3BA[]; + extern u16 D_801AE3BC[]; + s32 v1; + s16 idx; + + if (func_8012C354(a0, (s32)D_801AE418) != 0) { + *(u8 *)(a0 + 0xC0) = 1; + *(s32 *)(a0 + 0xB4) = -0x201; + *(s32 *)(a0 + 0xBC) = (s32)D_801AE44C; + func_8012A828(a0, (s32)D_801AF438); + + *(s16 *)(a0 + 0x2) = 1; + func_80143970((void *)a0); + + func_8012B23C((void *)a0); + + *(s16 *)(a0 + 0xFE) = (rand() & 0x1F) + 0x20; + *(s16 *)(a0 + 0x100) = (rand() & 0x1F) + 0x20; + + v1 = *(s32 *)(a0 + 0x64); + if (*(s16 *)(*(s32 *)(v1 + 0x20) + 0x12) != 0) { + idx = *(s16 *)(a0 + 0x70); + *(s16 *)(a0 + 0x6) = *(u16 *)(a0 + 0x6) - + *(u16 *)((u8 *)D_801AE3B8 + idx * 8); + idx = *(s16 *)(a0 + 0x70); + *(s16 *)(a0 + 0xA) = *(u16 *)(a0 + 0xA) + + *(u16 *)((u8 *)D_801AE3BA + idx * 8); + idx = *(s16 *)(a0 + 0x70); + *(s16 *)(a0 + 0xE) = *(u16 *)(a0 + 0xE) - + *(u16 *)((u8 *)D_801AE3BC + idx * 8); + } else { + idx = *(s16 *)(a0 + 0x70); + *(s16 *)(a0 + 0x6) = *(u16 *)(a0 + 0x6) + + *(u16 *)((u8 *)D_801AE3B8 + idx * 8); + idx = *(s16 *)(a0 + 0x70); + *(s16 *)(a0 + 0xA) = *(u16 *)(a0 + 0xA) + + *(u16 *)((u8 *)D_801AE3BA + idx * 8); + idx = *(s16 *)(a0 + 0x70); + *(s16 *)(a0 + 0xE) = *(u16 *)(a0 + 0xE) + + *(u16 *)((u8 *)D_801AE3BC + idx * 8); + } + + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(*(s32 *)(a0 + 0x64) + 0x20) + 0x12); + } +} + + + +extern s32 func_80047948(s32 a0); + + +void func_80187C6C(void *arg0) { + + extern u16 D_801AE3B8[]; + extern u16 D_801AE3BA[]; + extern u16 D_801AE3BC[]; + s32 s0 = (s32)arg0; + s32 v1 = *(s32 *)(s0 + 0x64); + s16 a0v; + + if (*(s16 *)(*(s32 *)(v1 + 0x20) + 0x12) != 0) { + *(s16 *)(s0 + 0x6) = *(u16 *)(v1 + 0x6) - + *(u16 *)((u8 *)D_801AE3B8 + *(s16 *)(s0 + 0x70) * 8); + + *(s16 *)(s0 + 0xA) = *(u16 *)(*(s32 *)(s0 + 0x64) + 0xA) + + *(u16 *)((u8 *)D_801AE3BA + *(s16 *)(s0 + 0x70) * 8); + + *(s16 *)(s0 + 0xE) = *(u16 *)(*(s32 *)(s0 + 0x64) + 0xE) - + *(u16 *)((u8 *)D_801AE3BC + *(s16 *)(s0 + 0x70) * 8); + } else { + *(s16 *)(s0 + 0x6) = *(u16 *)(v1 + 0x6) + + *(u16 *)((u8 *)D_801AE3B8 + *(s16 *)(s0 + 0x70) * 8); + + *(s16 *)(s0 + 0xA) = *(u16 *)(*(s32 *)(s0 + 0x64) + 0xA) + + *(u16 *)((u8 *)D_801AE3BA + *(s16 *)(s0 + 0x70) * 8); + + *(s16 *)(s0 + 0xE) = *(u16 *)(*(s32 *)(s0 + 0x64) + 0xE) + + *(u16 *)((u8 *)D_801AE3BC + *(s16 *)(s0 + 0x70) * 8); + } + + a0v = (*(u16 *)(s0 + 0x102) + *(u16 *)(s0 + 0xFE)) & 0xFFF; + *(u16 *)(s0 + 0x102) = a0v; + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x10) = func_80047948(a0v) >> 5; + + a0v = (*(u16 *)(s0 + 0x104) + *(u16 *)(s0 + 0x100)) & 0xFFF; + *(u16 *)(s0 + 0x104) = a0v; + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x14) = func_80047948(a0v) >> 5; +} + typedef struct { u8 b[8]; } Blk8_80187DE4; typedef struct { diff --git a/src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c b/src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c index 6bda8b8e9..099881a06 100644 --- a/src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c +++ b/src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c @@ -80,7 +80,6 @@ extern s32 *D_80126B78; extern u8 D_80078EC1; extern s32 D_80078EC8; extern s32 D_80126B9C; -extern s32 D_8011F730; extern u16 D_801152B8; extern u16 D_8012693A; extern u8 D_80126BE0[]; @@ -321,7 +320,6 @@ extern s32 func_80012B04(s32 a0, s32 a1, s32 a2); extern void func_801490F8(s32 a0, s32 a1); extern s32 func_801491C4(s32 a0); extern s32 func_80149184(s32 a0); -extern s32 D_801151D4; extern void func_80149204(s32 *a0); extern void func_80149210(s32 a0, s32 a1); extern s32 func_80149284(s32 *a0, s32 a1); @@ -3187,7 +3185,101 @@ void func_8017CDF4(s32 a0) { INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8017CE3C); -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8017CEF4); +typedef struct { short a, b, c; } SV3_80181D44_8017CEF4; /* == the TU's own `SV3` (engine_types.h:612); renamed only because +typedef struct { s16 vx, vy, vz, pad; } SV_8017D7C0_8017F19C_8017CEF4; /* 8 bytes, align 2 */ + +/* Callee externs — spellings copied from src/ov_SC04_002/ov_SC04_002_jr_8017BEBC.c + * (law 2). func_8017D098 is DEFINED later in that same TU as `void func_8017D098(void)` + * (a trivial wrapper around func_80151664()); our call site sets $a0 before the jal but + * the real body ignores it, so we declare it unprototyped (K&R style) to accept the + * dead argument without a conflicting-prototype error against the later definition. */ +extern void func_80149020(s32 *a0); +extern void func_80147A84(s32 arg0); +extern void func_801473EC(s32 *a0); +extern void func_80148038(s32 a0, s32 a1); +extern void func_80147460(s32 a0); +extern s32 func_801535F4(void *arg0); +extern void func_8017D098(); +extern void func_80159B3C(void *a0); +extern void func_8015BF48(s32 *a0); +extern s32 func_80146E98(s32 a0); +extern s32 func_80146A6C(s32 a0, void *a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); +extern void func_80165718(s32 a0); + +/* 16-byte-stride table at D_801887C0, indexed by the actor's 0xF2 animation/state id + * (signed s16); only the table row's first word (offset 0) is read. */ +typedef struct { + s32 f0; + u8 pad[12]; +} Tbl16_8018BDE4_8017CEF4; + +void func_8017CEF4(s32 a0) { + + extern Tbl16_8018BDE4_8017CEF4 D_801887C0[]; + s32 s0; + s16 s1; + s32 ret; + + s0 = *(s32 *)(a0 + 0x20); + func_80149020((s32 *)a0); + + s1 = *(s16 *)(s0 + 0x12); + *(s16 *)(s0 + 0x12) = *(u16 *)(a0 + 0x244); + func_80147A84(a0); + + func_801473EC((s32 *)a0); + func_80148038(a0, D_801887C0[*(s16 *)(a0 + 0xF2)].f0); + func_80147460(a0); + + *(s16 *)(s0 + 0x12) = s1; + + if (*(s32 *)(a0 + 0x234) == 0) { + if (*(s32 *)(a0 + 0x34) >= 0) { + if ((*(u16 *)(a0 + 0xB8) & 0x8000) != 0) { + __asm__ __volatile__("" ::: "memory"); + *(u16 *)(a0 + 0xB8) = *(u16 *)(a0 + 0xBA); + *(s32 *)(a0 + 0x234) = *(s32 *)(a0 + 0x234) + 1; + } + } + } + + ret = func_801535F4((void *)a0); + + if (ret == 1) { + goto L_case1; + } + if (ret < 2) { + goto L_default; + } + if (ret == 2) { + goto L_case2; + } + goto L_default; + +L_case1: + func_8017D098(a0); + func_80159B3C((void *)a0); + func_80146A6C(2, (void *)a0, 0, 0, 0, 1, 0); + func_80165718(a0); + return; + +L_case2: + func_8017D098(a0); + func_8015BF48((s32 *)a0); + func_80146A6C(2, (void *)a0, 0, 0, 0, 1, 0); + func_80165718(a0); + return; + +L_default: + if (func_80146E98(a0) == 0) { + return; + } + func_8017D098(a0); + func_80159B3C((void *)a0); + func_80146A6C(2, (void *)a0, 0, 0, 0, 1, 0); + func_80165718(a0); +} + extern void func_80151664(void); void func_8017D098(void) { @@ -4821,7 +4913,47 @@ void func_8017F314(int a, s16 *b, SVECTOR_8017E6D8 *c, SVECTOR_8017E6D8 *d, -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8017F690); +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_8017D7C0_8017F19C_8017F690; /* 0x20 bytes, align 4 */ + +typedef struct { u16 x, y, z, w; } V8_80181368_8017F690; + +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern s32 func_80133784(s32 a0, void *a1, s32 a2); + +s32 func_8017F690(s32 a0, s32 a1) { + V8_80181368_8017F690 sp10; + V8_80181368_8017F690 sp18; + s32 t; + s32 r; + + sp10.x = *(u16 *)(a0 + 0x6); + sp10.y = *(u16 *)(a0 + 0xA) - 0x20; + sp10.z = *(u16 *)(a0 + 0xE); + t = func_8004787C(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + r = (s16)a1; + sp18.y = sp10.y; + sp18.x = sp10.x - ((t * r) >> 12); + t = func_80047948(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + sp18.z = sp10.z - ((t * r) >> 12); + if ((func_80133784(1, &sp10, (s32)&sp18) & 0x8000) == 0) { + t = func_8004787C(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + sp10.x = *(u16 *)(a0 + 0x6) - ((t * 8) >> 12); + sp10.y = *(u16 *)(a0 + 0xA) - 0x10; + t = func_80047948(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + sp10.z = *(u16 *)(a0 + 0xE) - ((t * 8) >> 12); + sp18.x = sp10.x; + sp18.y = sp10.y + 0x20; + sp18.z = sp10.z; + if (func_80133784(1, &sp10, (s32)&sp18) & 0x6000) { + return 0; + } + } + *(s32 *)(a0 + 0x4) = *(s32 *)(a0 + 0x38); + *(s32 *)(a0 + 0xC) = *(s32 *)(a0 + 0x40); + return 1; +} + INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8017F81C); @@ -4847,10 +4979,13 @@ INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8017FF4 // @class: plumbing // @stuck: none — MATCH (18 ins): if((b&1) && p!=&sym) call(param,&sym); $a0 live, $a1=&sym fall out extern void func_8012A828(s32 a0, void *a1); -extern void D_801AB8A8; void func_8017FFB8(s32 arg0) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern void D_801AB8A8; if ((M2C_FIELD(arg0, u8 *, 0xC3) & 1) && (M2C_FIELD(arg0, void **, 0x90) != &D_801AB8A8)) { func_8012A828(arg0, &D_801AB8A8); } @@ -4873,9 +5008,12 @@ void func_8018008C(s32 a0) { #include "common.h" extern void func_8012A828(s32 a0, void *a1); -extern void D_801AB8A8; void func_801800CC(s32 a0) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern void D_801AB8A8; *(s16 *)(a0 + 0x2) = 3; func_8012A828(a0, &D_801AB8A8); *(u16 *)(a0 + 0x5C) = 0xAA10; @@ -4940,11 +5078,160 @@ void func_80180228(s32 *a0) { } -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8018023C); +typedef struct { s16 f0, f2, f4, f6, f8, fA, fC, fE; s32 f10; } St_80182784_80185DA8_8018023C; +typedef struct { s16 vx, vy, vz, pad; } SV_8017D7C0_8017F19C_8018023C; /* 8 bytes, align 2 */ +typedef struct { + s32 f0; + u8 pad[12]; +} Tbl16_8018BDE4_8018023C; +typedef struct { + SVECTOR_8016E7C8 v[4]; /* 0x00 */ + s32 f0, f1, f2, f3, f4, f5; /* 0x20..0x37 */ + u8 f6; /* 0x38 */ + u8 pad[7]; /* -> 0x40 */ +} Prim_8016E7C8_8018023C; + +extern s32 func_8012D5E4(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_8012EC04(s32 param_1, s32 param_2, s32 *param_3); +extern void func_8012F14C(s32 a0, s32 a1, s32 a2); +extern s32 func_8012C51C(void *a0, s32 a1); +extern void func_8012EFB8(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); +extern s32 func_8012BEE8(s32 a0); +extern void func_8012A828(s32 a0, void *a1); + +void func_8018023C(void *a0) { + + extern void D_801AB8A8; + if (*(s32 *)((char *)a0 + 0x1C) == 9) { + extern u8 D_801A3DAC[]; + extern u8 D_801A3DBC[]; + + func_8012D5E4((s32)a0, (s32)D_801A3DAC, (s32)(D_801A3DAC + 8), 0x10); + + if (*(s16 *)((char *)a0 + 0x70) & 0x8000) { + u16 out[4]; + struct { s16 f0, f2, f4, f6, f8, fA, fC, fE; s32 f10; } s; + s32 buf[8]; + + func_8012EC04((s32)a0, 0, buf); + ((void (*)(s32 *, u8 *, u16 *))func_8012F14C)(buf, D_801A3DBC, out); + + s.f6 = 0x23E; + s.f0 = out[0]; + s.f2 = out[1]; + s.f4 = out[2]; + s.fA = 0; + s.fC = 0x7FFF; + + s.fE = *(u16 *)(*(s32 *)((char *)a0 + 0x20) + 0x12); + func_8012C51C(&s, (s32)a0); + s.fE = *(u16 *)(*(s32 *)((char *)a0 + 0x20) + 0x12) + 0x100; + func_8012C51C(&s, (s32)a0); + s.fE = *(u16 *)(*(s32 *)((char *)a0 + 0x20) + 0x12) - 0x100; + func_8012C51C(&s, (s32)a0); + } + + { + u16 in3[3]; + s16 out2[2]; + s32 v; + + in3[0] = *(u16 *)((char *)a0 + 0x6); + in3[1] = *(u16 *)((char *)a0 + 0xA); + in3[2] = *(u16 *)((char *)a0 + 0xE); + + ((u32 (*)(u16 *, s16 *))func_8012EFB8)(in3, out2); + + v = out2[0]; + if (v < 0) { + v = -v; + } + if (v < 0xB5) { + v = out2[1]; + if (v < 0) { + v = -v; + } + if (v < 0xA1) { + func_8002D4C8(0x98B, 0); + } + } + } + } + + if (func_8012BEE8((s32)a0) != 0) { + *(s16 *)((char *)a0 + 0x2) = 3; + func_8012A828((s32)a0, &D_801AB8A8); + *(u16 *)((char *)a0 + 0x5C) = 0xAA10; + *(s16 *)((char *)a0 + 0x5E) = 0; + *(s16 *)((char *)a0 + 0xDC) = 0; + *(s32 *)((char *)a0 + 0x1C) = 0x2D; + } +} + INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_801803F0); -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_80180438); + +/* Fresh mass-lane crack (Phase-31 wave T). No banked twin was found for this + * skeleton (grepped D_801B9548 / D_801A3D6C / D_801A3D8C / D_801A3DC4 / the + * jal callees across src/ -- only extern decls / INCLUDE_ASM stubs turned up, + * all for unrelated overlay-local reuses of the same address). The dispatch + * head (D_801A3DC4[*(u16*)(a0+2)]();) mirrors the ALREADY-BANKED + * func_8017EC70 in THIS SAME TU (D_8018C074[*(u16*)((s32)a0+2)]();) -- same + * idiom, used as a hint per law 1 (never copied its symbols). */ + +extern s32 func_8012C044(s32 a0); +extern void func_8002A04C(s32 a0); +extern void func_8012C098(void); +extern void func_8012E8A8(u8 *a0); +extern void func_800183E0(s32 a0); + +void func_80180438(void *a0) { + + extern void (*D_801A3DC4[])(void); + extern u16 D_800B99DA; + extern u16 D_801A3D6C[]; + extern u16 D_801B9548[]; + extern u8 D_801A3D8C[]; + void *s0 = a0; + + D_801A3DC4[*(u16 *)((u8 *)s0 + 0x2)](); + + if (func_8012C044((s32)s0)) { + *(s16 *)((u8 *)s0 + 0x100) = 1; + __asm__ __volatile__("" ::: "memory"); + *(s16 *)((u8 *)s0 + 0x76) = 0; + if (*(s16 *)((u8 *)s0 + 0x100) == 0) { + func_8002A04C((s32)s0); + } + if (*(s16 *)((u8 *)s0 + 0xFE) == 0) { + ((void (*)(void *))func_8012C098)(s0); + } else { + *(s16 *)((u8 *)s0 + 0x2) = 6; + func_8012E8A8((u8 *)s0); + *(s16 *)((u8 *)s0 + 0x5C) = 0; + *(u8 *)((u8 *)s0 + 0xC1) = 0; + } + } + + if (*(s16 *)((u8 *)s0 + 0xFE) != 0) { + u16 *src = D_801A3D6C; + s32 shift = D_800B99DA & 0xF; + u16 *dst = &D_801B9548[shift]; + s32 i; + + for (i = 0; i < 0xF - shift; i++) { + *dst++ = *src++; + } + dst = D_801B9548; + for (i = 0; i < shift; i++) { + *dst++ = *src++; + } + func_800183E0((s32)D_801A3D8C); + } +} + extern void (*D_801A3DE8[])(void); @@ -5054,7 +5341,53 @@ void func_80180A5C(int param_1) } -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_80180ACC); + +typedef struct { s16 a, b, c; } SV3x_80180ACC; /* 6-byte, align-2 triple of s16 */ +typedef struct { s16 a, b, c, d; } SV4x_80180ACC; /* 8-byte, align-2 quad of s16 */ + +extern void func_8012C218(void *a0); +extern void func_8012F214(s32 a0, s32 a1, s32 a2); + + +void func_80180ACC(void *a0) { + + extern s32 D_801ABE80; + extern s32 D_801A3DE0; + s32 s0 = (s32)a0; + s32 s1; + SV3x_80180ACC out; + + s1 = *(s32 *)(s0 + 0x64); + + if (*(s16 *)(s0 + 0xFE) == 0x7FFF) { + *(s16 *)(s0 + 0xFE) = *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12); + } + + if (*(s16 *)(s0 + 0xFC) != *(s16 *)(s1 + 0x36)) { + func_8012C218((void *)s0); + return; + } + + *(SV4x_80180ACC *)(*(s32 *)(s0 + 0x20) + 0x10) = *(SV4x_80180ACC *)(*(s32 *)(s1 + 0x20) + 0x10); + + if (*(s32 *)(s1 + 0x90) != (s32)&D_801ABE80) { + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x12) = *(s16 *)(s0 + 0xFE); + *(s32 *)(s0 + 0x4) = *(s32 *)(s1 + 0x4); + *(s32 *)(s0 + 0x8) = *(s32 *)(s1 + 0x8); + *(s32 *)(s0 + 0xC) = *(s32 *)(s1 + 0xC); + } else { + func_8012F214(s1, (s32)&D_801A3DE0, (s32)&out); + *(s16 *)(s0 + 0x6) = out.a; + *(s16 *)(s0 + 0xA) = out.b; + *(s16 *)(s0 + 0xE) = out.c; + } + + *(SV4x_80180ACC *)(*(s32 *)(s0 + 0x20) + 0x18) = *(SV4x_80180ACC *)(*(s32 *)(s1 + 0x20) + 0x18); + + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x2C) = *(s16 *)(*(s32 *)(s1 + 0x20) + 0x2C); + *(s32 *)(*(s32 *)(s0 + 0x20) + 0x4) = *(s32 *)(*(s32 *)(s1 + 0x20) + 0x4); +} + #include "common.h" @@ -5734,7 +6067,6 @@ typedef struct { u16 x, y, z, w; } V8_80182044; extern s32 D_80126B58; extern s32 D_80126B84; -extern s32 D_8011F730; extern void func_8012A828(s32 a0, void *a1); extern void func_8012A8E8(void); @@ -5744,6 +6076,10 @@ extern s32 func_80182F20(s32 a0); extern s32 func_80133784(s32 a0, void *a1, s32 a2); void func_80182044(s32 a0) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 D_8011F730; extern u8 D_801B5D9C[]; extern u8 D_801B61D4[]; @@ -5807,7 +6143,79 @@ void func_8018227C(s32 a0) { } -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_801822C0); + +extern void func_80182D80(s32 a0); +extern s32 func_80029DB4(void); +extern s32 func_80029E30(void); +extern s32 func_80182BAC(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_8012A828(s32 a0, void *a1); +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void func_8012CBCC(s32 a0); + +void func_801822C0(s32 a0) { + + extern s32 D_8011F730; + extern u8 D_801B61D4[]; + extern s32 D_801B5E24; + extern s32 D_801B5E8C; + extern s32 D_801B6074; + extern u8 D_801AD1B8[]; + extern u8 D_801AD1D8[]; + + s32 state; + s32 g; + s32 v0; + s32 arg0, arg1; + + func_80182D80(a0); + state = *(u16 *)(a0 + 0x34); + + switch (state) { + case 0: + g = D_8011F730; + if (g == 2) { + *(u16 *)(a0 + 0x34) = 3; + func_8012A828(a0, D_801B61D4); + return; + } else if (g == 3) { + *(u16 *)(a0 + 0x34) = 1; + func_8012A828(a0, &D_801B5E24); + return; + } else if (g == 4) { + *(u16 *)(a0 + 0x34) = 2; + func_8012A828(a0, &D_801B5E8C); + return; + } + goto tail_short; + case 1: + v0 = func_80029DB4(); + func_80182BAC(a0, (s32)D_801AD1B8, 7, v0); + arg0 = 0x1EB; + arg1 = 0; + break; + case 2: + v0 = func_80029E30(); + func_80182BAC(a0, (s32)D_801AD1D8, 6, v0); + arg0 = 0x1EB; + arg1 = 1; + break; + case 3: + goto tail_short; + default: + return; + } + + func_8012C658(arg0, arg1, a0); + if (*(u16 *)(a0 + 0x72) & 0x4000) { + func_8012A828(a0, &D_801B6074); + } + +tail_short: + if (((s32 (*)(s32))func_8012CBCC)(a0) & 0x2000) { + *(u16 *)(a0 + 0x2) = 1; + } +} + INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_80182444); @@ -6195,7 +6603,88 @@ INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_80182F2 INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_80183014); -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8018317C); +extern s32 func_80132EF4(s32 a0, s32 a1); +typedef struct { short a, b, c; } SV3_80181D44_8018317C; /* == the TU's own `SV3` (engine_types.h:612); renamed only because + +extern s32 func_80132EF4(s32 a0, s32 a1); +extern s32 rand(void); +/* func_801832F8 is the NEXT stub in this same TU (INCLUDE_ASM at the line below + * func_8018317C's). Its own .s takes TWO args ($a0 = entity-owner, $a1 = id): + * do NOT adopt the 1-arg `void f(void*)` spelling that the *unrelated* overlay + * ov_SC03_001 uses for its own different function at the same address. */ +extern void func_801832F8(s32 a0, s32 a1); + +/* Spawn a 0x4F entity for `a0`, then jitter its three s16 fields at +0x6/+0xA/+0xE + * by a random amount (mod 28 / 32 / 28, sign picked by a second rand()), flip the + * substruct at *(s32*)(entity+0x20) fields 0x18/0x1A/0x1C to +/-0x2000, and notify. */ +s32 func_8018317C(s32 a0) { + s32 s2; + + s2 = func_80132EF4(a0, 0x4F); + if (s2 == 0) { + return 0; + } + + *(s16 *)(s2 + 0xA) = *(u16 *)(s2 + 0xA) - 0x28; + + /* NOTE (this is the whole match, do not "tidy" it): each block MUST own its + * own r/val/base locals. With one shared `r` across all three blocks, the + * /32 block's remainder pseudo conflicts with the rand()-result pseudo, so + * global.c's expand_preferences() cannot merge their preferences (it needs + * a non-conflicting REG_DEAD copy). The result pseudo then has NO hard-reg + * preference of its own, prune_preferences() puts $v1 into its + * regs_someone_prefers set, and find_reg's pass 0 skips $v1 and lands the + * value in $a0 instead of the target's $v1 (4 wrong instructions). */ + { + s32 r, val, base; + r = rand() % 28; + base = *(s16 *)(s2 + 0x6); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0x6) = val; + } + { + s32 r, val, base; + r = rand() % 32; + base = *(s16 *)(s2 + 0xA); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0xA) = val; + } + { + s32 r, val, base; + r = rand() % 28; + base = *(s16 *)(s2 + 0xE); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0xE) = val; + } + + { + s32 v0, v1; + + if (rand() & 1) { + v1 = *(s32 *)(s2 + 0x20); + v0 = -0x2000; + *(s16 *)(v1 + 0x1C) = v0; + } else { + v1 = *(s32 *)(s2 + 0x20); + v0 = 0x2000; + *(s16 *)(v1 + 0x1C) = v0; + } + *(s16 *)(v1 + 0x1A) = v0; + *(s16 *)(v1 + 0x18) = v0; + } + + /* Zero-byte scheduling fence (§190-C). Without it BOTH sched1 and sched2 + * independently hoist the call's `move $a0,$s3` + `li $a1,0x7F3` above the + * two trailing `sh` stores (they feed the jal, so they carry the higher + * INSN_PRIORITY), and reorg then fills the delay slot with `sh 0x18` + * instead of the target's `addiu $a1`. -fno-schedule-insns{,2} alone does + * not reproduce the target order -- only both together do, hence a real + * barrier rather than a statement reorder. */ + __asm__ __volatile__("" ::: "memory"); + func_801832F8(a0, 0x7F3); + return s2; +} + INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_801832F8); @@ -6915,7 +7404,83 @@ void func_80183FE0(s32 a0, s32 a1, s32 a2) } -INCLUDE_ASM("asm/ov_SC02_041/nonmatchings/ov_SC02_041_jr_8017BEBC", func_8018428C); +typedef struct { s16 vx, vy, vz, pad; } SV_8017D7C0_8017F19C_8018428C; /* 8 bytes, align 2 */ + +/* func_8018428C (ov_SC04_002, ov_SC04_002_jr_8017BEBC, 83 ins) + * + * Sibling family (skeleton group, remapped mechanically once this banks): + * ov_SC02_041:func_8018428C, ov_SC04_005:func_80186C80, ov_SC04_007:func_801832EC + * + * Two conflicting local extern decls exist for this function in the TU + * (func_8018739C uses `void *a1, MATRIX *a3`; func_80187604 uses `s32 a1, + * void *a3`) -- neither is dereferenced structurally inside this function's + * own body (a3 is only ever forwarded as an opaque pointer argument), so the + * definition-side signature below (s32 a1, void *a3) is chosen freely and is + * compatible with both call sites' own local prototypes. + */ +void func_8018428C(s32 a0, s32 a1, s32 a2, void *a3) +{ + extern s32 D_801151D4; + extern void func_8012EC04(s32 param_1, s32 param_2, s32 *param_3); + extern void func_8012F14C(s32 a0, s32 a1, s32 a2); + extern void func_800D20C0(void *a0, void *a1, s32 a2); + extern void func_80017E68(void *a0, void *a1); + extern void func_800D23D0(void *a0); + extern void ApplyMatrixSV(void *a0, void *a1, void *a2); + extern void RotMatrixYXZ(void *a0, void *a1); + extern void ApplyTransposeMatrixLV(void *a0, void *a1, void *a2); + extern s32 ratan2(s32 a0, s32 a1); + + s32 mtx1[8]; /* sp+0x10, 0x20 bytes: scratch MATRIX */ + s16 buf2[4]; /* sp+0x30, 8 bytes: vx,vy,vz,pad */ + s16 vec[4]; /* sp+0x38, 8 bytes: vx,vy,vz,pad */ + s32 diff[3]; /* sp+0x40 */ + s32 base; + s32 v0; + s32 v1; + + base = D_801151D4; + + func_8012EC04(a0, a2, (s32 *)mtx1); + + func_8012F14C((s32)mtx1, a1 + 0x18, (s32)buf2); + + func_800D20C0((void *)buf2, (void *)vec, 8); + + func_80017E68((void *)buf2, a3); + + v0 = *(u16 *)(a1 + 0x8); + v1 = *(u16 *)(a1 + 0x10); + v0 = v0 - v1; + vec[0] = v0; + v0 = *(u16 *)(a1 + 0xA); + v1 = *(u16 *)(a1 + 0x12); + v0 = v0 - v1; + vec[1] = v0; + v0 = *(u16 *)(a1 + 0xC); + v1 = *(u16 *)(a1 + 0x14); + v0 = v0 - v1; + vec[2] = v0; + + ApplyMatrixSV((void *)mtx1, (void *)vec, (void *)vec); + + func_800D23D0((void *)vec); + + RotMatrixYXZ((void *)vec, a3); + + diff[0] = *(s32 *)(base + 0x5C) - buf2[0]; + diff[1] = *(s32 *)(base + 0x60) - buf2[1]; + diff[2] = *(s32 *)(base + 0x64) - buf2[2]; + + ApplyTransposeMatrixLV(a3, (void *)diff, (void *)diff); + + v0 = ratan2(diff[0], diff[1]); + + vec[2] = -v0; + + RotMatrixYXZ((void *)vec, a3); +} + #include "common.h" diff --git a/src/ov_SC03_015/ov_SC03_015_jr_801848E4.c b/src/ov_SC03_015/ov_SC03_015_jr_801848E4.c index a8e4aa0bb..fa478eb41 100644 --- a/src/ov_SC03_015/ov_SC03_015_jr_801848E4.c +++ b/src/ov_SC03_015/ov_SC03_015_jr_801848E4.c @@ -43,7 +43,6 @@ extern void func_80162120(void); extern void func_80029124(s32, s32); extern s32 func_80165A50(s32); extern void func_80029514(s32); -extern u8 D_800AF630[]; extern u8 D_80078EC0; extern s32 D_80126B58; extern s32 func_80028FBC(void); @@ -2823,7 +2822,115 @@ void func_80185144(void *a0) { INCLUDE_ASM("asm/ov_SC03_015/nonmatchings/ov_SC03_015_jr_801848E4", func_80185180); -INCLUDE_ASM("asm/ov_SC03_015/nonmatchings/ov_SC03_015_jr_801848E4", func_80185380); +typedef struct { + s16 m[3][3]; + s16 pad; + s32 t[3]; +} MtxLocal_80185380; +typedef struct { + SVECTOR_8016E7C8 v[4]; /* 0x00 */ + s32 f0, f1, f2, f3, f4, f5; /* 0x20..0x37 */ + u8 f6; /* 0x38 */ + u8 pad[7]; /* -> 0x40 */ +} Prim_8016E7C8_80185380; + + +extern void func_8012C218(void *a0); +extern s32 func_8012B8A4(s16 *a0); +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern s32 func_80178B18(s32 param_1, s32 param_2); +extern s32 func_801789AC(s32 arg0); +extern void func_80178D18(void); +extern void func_80029514(s32); +extern void func_8012A568(void (*a0)(void)); +extern void func_80183980(void); + + +void func_80185380(s32 param_1) { + + extern u16 D_80126B5E; + extern u16 D_80126B62; + extern u16 D_80126B66; + extern u16 D_80190048; + extern u16 D_8019004A; + extern u16 D_8019004C; + extern u16 D_8019005A; + extern u16 D_8019005C; + extern s32 D_80190344; + u16 state; + s32 obj; + + state = *(u16 *)(param_1 + 0x34); + switch (state) { + case 0: + obj = *(s32 *)(param_1 + 0x6C); + if (*(s16 *)(obj + 0x76) > 0) { + return; + } + *(u16 *)(param_1 + 0x34) = state + 1; + func_8012C218((void *)*(s32 *)(param_1 + 0xCC)); + func_8012C218((void *)*(s32 *)(param_1 + 0xD0)); + + { + register s32 o __asm__("$2"); + u16 v6; + register u16 *p10 __asm__("$3"); + + o = *(s32 *)(param_1 + 0x6C); + v6 = *(u16 *)(o + 0x6); + __asm__ __volatile__("" : "=r"(v6) : "0"(v6) : "memory"); + p10 = &D_80190048; + __asm__ __volatile__("" : "=r"(p10) : "0"(p10) : "memory"); + *p10 = v6; + + o = *(s32 *)(param_1 + 0x6C); + D_8019004A = *(u16 *)(o + 0xA) - 0x40; + + o = *(s32 *)(param_1 + 0x6C); + { + u16 g5e = D_80126B5E; + D_8019004C = *(u16 *)(o + 0xE); + *(u16 *)((u8 *)p10 + 0x10) = g5e; + } + } + + D_8019005A = D_80126B62 - 0x40; + D_8019005C = D_80126B66; + + { + s32 v; + s32 a1val; + s32 sinv; + s32 angleDelta; + s32 tmp; + s32 *p; + + v = func_8012B8A4((s16 *)param_1); + a1val = func_8004787C(v); + + p = &D_80190344; + angleDelta = (*(s16 *)(param_1 + 0x6) - (((a1val * 3) << 5) >> 12)) & 0xFFFF; + *p = angleDelta; + + sinv = func_80047948(v); + tmp = (*(s32 *)(param_1 + 0xC) - ((sinv * 3) << 9)) & 0xFFFF0000; + *p = *p | tmp; + func_80178B18(param_1, (s32)((u8 *)p - 0x4C)); + } + break; + case 1: + if (func_801789AC(param_1) != 0) { + ((void (*)(void *))func_80178D18)((void *)param_1); + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + *(u16 *)(*(s32 *)(param_1 + 0xD8) + 0x34) = 1; + func_80029514(0x2DA); + func_8012A568(func_80183980); + } + break; + } +} + DEFINE_func_8018553C() /* dedup: shared engine-core @0x8018553C (src/shared) */ @@ -3230,13 +3337,144 @@ void func_80185EF8(s32 a0) { } -INCLUDE_ASM("asm/ov_SC03_015/nonmatchings/ov_SC03_015_jr_801848E4", func_801863B8); + typedef struct { s32 a; s32 b[4]; } Ot_8018B23C_801863B8; + +/* Declarations adopted verbatim from src/ov_SC03_014/ov_SC03_014_jr_801848E4.c + * (law 2). D_801E2CE8 and D_80190538 are first uses in this TU, declared in + * the raw form matching how their addresses are consumed here (never + * dereferenced in this function; passed on as a pointer arg only). */ +extern s32 func_8012CBCC(s32 a0); +extern s32 func_8012BA10(s32 a0, s32 a1); +extern void func_8012A828(s32 a0, void *a1); +extern void func_8012F14C(s32 a0, s32 a1, s32 a2); +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void func_8002D4C8(s32 a0, s32 a1); + + +void func_801863B8(s32 a0) { + + extern u8 D_801E2CE8[]; + extern u8 D_80190538[]; + s32 obj; + s32 s1; + s32 msg; + u16 sp[3]; + + func_8012CBCC(a0); + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) += func_8012BA10(a0, 4); + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + if (!(*(u16 *)(a0 + 0x72) & 0x4000)) { + break; + } + *(u16 *)(a0 + 0x34) = 1; + func_8012A828(a0, D_801E2CE8); + msg = 0xA7E; + goto tail; + + case 1: + if (*(s32 *)(a0 + 0x94) != 0xF) { + break; + } + *(u16 *)(a0 + 0x34) = 2; + func_8012F14C(*(s32 *)(a0 + 0x20) + 0x34, (s32)D_80190538, (s32)sp); + for (s1 = -0x200; s1 < 0x300; s1 += 0x200) { + obj = func_8012C658(0x265, 1, a0); + if (obj != 0) { + *(u16 *)(obj + 0xFE) = + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + s1; + *(u16 *)(*(s32 *)(obj + 0x20) + 0x14) = + *(u16 *)(obj + 0xFC) + 0x200; + *(u16 *)(obj + 0x6) = sp[0]; + *(u16 *)(obj + 0xA) = sp[1]; + *(u16 *)(obj + 0xE) = sp[2]; + } + } + msg = 0xA35; + tail: + func_8002D4C8(msg, 0); + break; + + case 2: + if (!(*(u16 *)(a0 + 0x72) & 0x4000)) { + break; + } + *(u16 *)(a0 + 0x2) = 1; + func_8012A828(a0, D_801E2170); + break; + } +} + DEFINE_func_8018655C() /* dedup: shared engine-core @0x8018655C (src/shared) */ DEFINE_func_801867F8() /* dedup: shared engine-core @0x801867F8 (src/shared) */ -INCLUDE_ASM("asm/ov_SC03_015/nonmatchings/ov_SC03_015_jr_801848E4", func_80186A74); + +/* Declarations matched verbatim to src/ov_SC03_014/ov_SC03_014_jr_801848E4.c + * where that TU already declares the symbol (law 2/1b). Fresh raw-form decls + * (u8[]) for the two data symbols the TU does not yet mention. */ +extern s32 func_8012CBCC(s32 a0); +extern s32 func_8012BA10(s32 a0, s32 a1); +extern void func_8012F14C(s32 a0, s32 a1, s32 a2); +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void func_8012A828(s32 a0, void *a1); +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); + + +void func_80186A74(s32 a0) { + + extern u8 D_801E2B50[]; + extern u8 D_80190540[]; + s16 sp10[3]; + s32 s0; + + func_8012CBCC(a0); + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) += func_8012BA10(a0, 4); + if (*(u16 *)(a0 + 0x72) & 0x4000) { + *(u16 *)(a0 + 0x34) = 1; + func_8012A828(a0, D_801E2B50); + func_8002D4C8(0xA81, 0); + } + break; + case 1: + if (*(s32 *)(a0 + 0x94) == 0xF) { + *(u16 *)(a0 + 0x34) = 2; + func_8012F14C(*(s32 *)(a0 + 0x20) + 0x34, (s32)D_80190540, (s32)sp10); + s0 = func_8012C658(0x265, 3, a0); + if (s0 != 0) { + *(u16 *)(*(s32 *)(s0 + 0x20) + 0x14) = + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12); + *(s32 *)(s0 + 0x10) = + -(func_8004787C(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12)) << 8); + *(s32 *)(s0 + 0x18) = + -(func_80047948(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12)) << 8); + *(u16 *)(s0 + 0x6) = sp10[0]; + *(u16 *)(s0 + 0xA) = sp10[1]; + *(u16 *)(s0 + 0xE) = sp10[2]; + } + func_8002D4C8(0xA36, 0); + } + break; + case 2: + if (*(u16 *)(a0 + 0x72) & 0x4000) { + *(u16 *)(a0 + 0xFC) = 0x1E; + *(u16 *)(a0 + 0x2) = 9; + func_8012A828(a0, D_801E2170); + *(u16 *)(a0 + 0xAE) = 0x2900; + } + break; + } + + func_8012C658(0x3DE, 0, a0); +} + /* func_80186C4C — ov_SC03_014 / ov_SC03_014_jr_801848E4. MATCH 273/273. diff --git a/src/ov_SC03_024/ov_SC03_024_jr_8017DF84.c b/src/ov_SC03_024/ov_SC03_024_jr_8017DF84.c index a75174d5f..f5a5c83ca 100644 --- a/src/ov_SC03_024/ov_SC03_024_jr_8017DF84.c +++ b/src/ov_SC03_024/ov_SC03_024_jr_8017DF84.c @@ -4927,7 +4927,54 @@ void func_80181D74(void *a0) { INCLUDE_ASM("asm/ov_SC03_024/nonmatchings/ov_SC03_024_jr_8017DF84", func_80181DB0); -INCLUDE_ASM("asm/ov_SC03_024/nonmatchings/ov_SC03_024_jr_8017DF84", func_80181F7C); +extern void func_8013CABC(void); +extern void func_8018282C(s32*); +extern s32 func_8012BEE8(s32 a0); +extern void func_801821D4(s32 a0); +extern void func_80182108(s32 a0); +extern void func_80181070(void); +extern int func_80178970(void); +void func_80181F7C(s32 a0) { + + extern s32 D_801C1358; + s32 self; + self = a0; + if (*(s32 *)(self + 0x1C) == 0x30) { + func_8013CABC(); + } else if (*(s32 *)(self + 0x1C) == 0x10) { + ((void (*)(void *))func_8018282C)((void *)*(s32 *)(self + 0xD0)); + } + if (*(u16 *)(self + 0x84) & 1) { + *(u16 *)(*(s32 *)(self + 0x64) + 6) = *(u16 *)(*(s32 *)(self + 0x64) + 6) - 3; + *(u16 *)(*(s32 *)(*(s32 *)(self + 0x64) + 0x20) + 8) = + *(u16 *)(*(s32 *)(*(s32 *)(self + 0x64) + 0x20) + 8) - 3; + *(u16 *)(self + 6) = *(u16 *)(self + 6) - 3; + } else { + *(u16 *)(*(s32 *)(self + 0x64) + 6) = *(u16 *)(*(s32 *)(self + 0x64) + 6) + 3; + *(u16 *)(*(s32 *)(*(s32 *)(self + 0x64) + 0x20) + 8) = + *(u16 *)(*(s32 *)(*(s32 *)(self + 0x64) + 0x20) + 8) + 3; + *(u16 *)(self + 6) = *(u16 *)(self + 6) + 3; + } + { + s32 t; + t = D_801C1358; + *(u16 *)(self + 0x84) = *(u16 *)(self + 0x84) + 1; + if (t == 0) { + D_801C1358 = ((s32 (*)(void))func_80181070)(); + } + } + if (func_8012BEE8(self) && D_801C1358) { + func_801821D4(self); + } else { + if (*(s32 *)(self + 0x1C) < 0x48) { + if ((*(u16 *)(self + 0x84) & 3) == 0) { + func_80182108(self); + } + } + } + ((void (*)(s32))func_80178970)(self); +} + INCLUDE_ASM("asm/ov_SC03_024/nonmatchings/ov_SC03_024_jr_8017DF84", func_80182108); diff --git a/src/ov_SC03_092/ov_SC03_092_jr_8017AE2C.c b/src/ov_SC03_092/ov_SC03_092_jr_8017AE2C.c index 7f0aa0aca..39beeecc0 100644 --- a/src/ov_SC03_092/ov_SC03_092_jr_8017AE2C.c +++ b/src/ov_SC03_092/ov_SC03_092_jr_8017AE2C.c @@ -5162,7 +5162,88 @@ INCLUDE_ASM("asm/ov_SC03_092/nonmatchings/ov_SC03_092_jr_8017AE2C", func_80180B2 void func_80180BF4(void) { } -INCLUDE_ASM("asm/ov_SC03_092/nonmatchings/ov_SC03_092_jr_8017AE2C", func_80180BFC); + typedef struct { u8 b[8]; } Blk8_80180BFC; +typedef struct { + s32 a; /* 0x00 -> D_801DA750 */ + s32 b; /* 0x04 -> D_801DA754 */ +} Pair8_8017DDC4_80182244_80180BFC; + +/* Sibling shape in the SAME TU: func_80182244 (already banked, line ~3980) + * uses the identical idiom for the same actor kind: void *a0, raw + * (s32)a0+offset field access, func_8012C1B8 cast-called as (s32(*)(void)), + * func_8012CAE4, func_8001C214, and the 0x70-indexed table lookup + 0x1000000 + * OR-flag pattern at (*(s32*)(sub+4)) |= 0x1000000. Adopted as a structural + * hint only (law 1) — none of its per-location symbols are reused here. */ + +extern void func_8012C1B8(void); +extern void func_8012CAE4(void *a0); +extern s32 func_80029178(s32 a0); +extern void func_8001C214(s32 a0, s32 a1); +extern s32 func_8012AD50(void *a0); + +/* idx = *(s16*)(a0+0x70): lhu direct load, 2-byte stride -> u16 table */ + +/* address-of only in the target (lui/addiu, no load/store through it here) */ + +void func_80180BFC(s32 a0) +{ + + extern u16 D_801AC610[]; + extern u8 D_801AC600; + extern u8 D_801AC5F0; + if ((*(s32 *)(a0 + 0x20) = ((s32 (*)(void))func_8012C1B8)()) == 0) { + func_8012CAE4((void *)a0); + return; + } + + if ((func_80029178((s32)D_801AC610[*(s16 *)(a0 + 0x70)]) & 0xFF) != 0) { + register s32 s0 __asm__("$16") = *(s32 *)(a0 + 0xDC); + if (s0 != 0) { + s32 a1 = *(s32 *)(s0 + 0x4); + if (a1 != 0) { + func_8001C214(*(s32 *)(a0 + 0x20), a1); + if (*(s32 *)(s0 + 0xC) != 0) { + s32 v1 = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4); + v1 |= 0x1000000; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4) = v1; + } + } + } + func_8012AD50((void *)a0); + goto tail; + } + + { + register s32 s0 __asm__("$16") = *(s32 *)(a0 + 0xDC); + register s32 flag __asm__("$2") = 1; + if (s0 != 0) { + s32 a1 = *(s32 *)s0; + if (a1 != 0) { + func_8001C214(*(s32 *)(a0 + 0x20), a1); + if (*(s32 *)(s0 + 0xC) != 0) { + s32 v1 = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4); + v1 |= 0x1000000; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4) = v1; + } + flag = 1; + } + } + *(u8 *)(a0 + 0xC0) = flag; + } + + *(s32 *)(a0 + 0xBC) = (s32)&D_801AC600; + *(s32 *)(a0 + 0x58) = (s32)&D_801AC5F0 | 0x40000000; + *(u16 *)(a0 + 0x5C) = 0x8800; + *(s32 *)(a0 + 0xB4) = 0; + *(u8 *)(a0 + 0xC1) = 0; + *(u16 *)(a0 + 0xAE) = 0x7FFF; + *(u8 *)(a0 + 0x75) = 0; + *(s32 *)(a0 + 0xC4) |= 0x2; + +tail: + func_8012AD50((void *)a0); +} + // @class: struct diff --git a/src/ov_SC03_108/ov_SC03_108_jr_8017BEBC.c b/src/ov_SC03_108/ov_SC03_108_jr_8017BEBC.c index 9029de0f1..7285557f3 100644 --- a/src/ov_SC03_108/ov_SC03_108_jr_8017BEBC.c +++ b/src/ov_SC03_108/ov_SC03_108_jr_8017BEBC.c @@ -3829,7 +3829,78 @@ L_end: } -INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017F140); + +/* Sibling pattern for the func_8012C354(a0, &D_xxx) gate + s0+0xC0/s0+0x2 flag + * writes is func_8017F3F4 in this same TU (ov_SC03_112_jr_8017C294.c, ~L3892): + * it declares the target-only data symbol as `extern M2C_UNK D_xxx;` and passes + * `(s32)&D_xxx` as the gate's second arg. Followed here for D_8019E640. + * + * func_8012C354(s32,s32)->s32 : TU decl at L3911 (verbatim, adopted). + * func_8001CD9C(int,void*) : TU decl at L1818 (verbatim, adopted); defined + * void at src/800.c:5936 as (s32,s32) -- the TU's + * own extern spelling wins per law 2/8. + * func_8012C194(void)->s32, func_80143994(s32,s32)->s32, func_8012E8A8(u8*)->void + * : not declared in this TU; typed by the majority project-wide spelling. + */ + +extern s32 func_8012C354(s32 a0, s32 a1); +extern void func_8001CD9C(int, void *); +extern s32 func_8012C194(void); +extern s32 func_80143994(s32 a0, s32 a1); +extern void func_8012E8A8(u8 *a0); + + +void func_8017F140(s32 a0) { + + extern M2C_UNK D_8019E640; + extern M2C_UNK D_8019E674; + extern M2C_UNK D_8019E6BC; + extern M2C_UNK D_8019E70C; + s32 s0; + s32 v1; + u16 v0; + + if (func_8012C354(a0, (s32)&D_8019E640)) { + v1 = *(s32 *)(a0 + 0x20); + *(u16 *)(v1 + 0x2C) |= 0x30; + v1 = *(s32 *)(a0 + 0x20); + *(void **)(v1 + 0x80) = &D_8019E674; + *(s32 *)(a0 + 0xE8) = 0x40; + s0 = func_8012C194(); + if (s0 != 0) { + *(s32 *)(a0 + 0xD0) = s0; + func_8001CD9C((int)s0, (void *)&D_8019E6BC); + *(s16 *)(s0 + 0x18) = 0x555; + *(s16 *)(s0 + 0x1A) = 0x555; + *(s32 *)(s0 + 0x4) |= 0x50000000; + } + + v0 = *(u16 *)(a0 + 0x70); + if (v0 & 0x2) { + *(u16 *)(a0 + 0x2) = 0x8; + *(u8 *)(a0 + 0xC0) = 1; + *(void **)(a0 + 0xBC) = &D_8019E70C; + *(s32 *)(a0 + 0xB4) = -0x249D; + *(s32 *)(a0 + 0xC4) |= 0x2; + func_8012E8A8((u8 *)a0); + return; + } + + if (v0 & 0x1) { + *(u16 *)(a0 + 0x2) = 6; + *(u16 *)(a0 + 0x5C) &= 0x5FFF; + } else { + *(u8 *)(a0 + 0xC0) = 1; + *(void **)(a0 + 0xBC) = &D_8019E70C; + *(s32 *)(a0 + 0xB4) = -0x249D; + *(u16 *)(a0 + 0x2) = 1; + *(s32 *)(a0 + 0xC4) |= 0x2; + } + + *(s32 *)(a0 + 0xCC) = func_80143994(a0, 0x1000); + } +} + INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017F29C); @@ -4006,6 +4077,72 @@ TAIL_5DC: } -INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017F640); +typedef struct { + SVECTOR_8016E7C8 v[4]; /* 0x00 */ + s32 f0, f1, f2, f3, f4, f5; /* 0x20..0x37 */ + u8 f6; /* 0x38 */ + u8 pad[7]; /* -> 0x40 */ +} Prim_8016E7C8_8017F640; + +extern s32 func_8012BCCC(s32 a0); +extern s32 func_8004787C(s32 a0); +extern s32 func_8012B8E4(s32 a0, s32 a1); + +void func_8017F640(s32 param_1) +{ + extern void func_801808B4(s32 a0); + extern s32 func_8012BDBC(s32 a0, s32 a1); + extern void func_8012B178(s32 a0, s32 a1); + extern s32 func_8012CBA4(s32 a0); + extern void func_8012ADE4(u8 *a0); + + s32 dist; + s32 angle; + s32 iVar1; + s32 a1; + + if (*(s16 *)(param_1 + 0xa) >= 0x10) { + func_801808B4(param_1); + goto end; + } + + dist = func_8012BCCC(param_1); + if (func_8012BDBC(param_1, 0x400) == 0) { + *(s16 *)(param_1 + 2) = 1; + goto end; + } + if (dist > 0x24000) { + *(s16 *)(param_1 + 2) = 1; + goto end; + } + if (dist < 0x4001) { + *(s16 *)(param_1 + 2) = 4; + goto end; + } + + angle = func_8004787C((*(s32 *)(param_1 + 0xe4) << 7) & 0x780); + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x1a) = (angle >> 1) + 0x800; + iVar1 = func_8012B8E4(param_1, 0xa); + { + s32 ptr = *(s32 *)(param_1 + 0x20); + s32 v = *(u16 *)(ptr + 0x12) + iVar1; + *(u16 *)(ptr + 0x12) = v; + if (0x1000 - angle >= 0) { + a1 = 0xFFFF0000 - ((0x1000 - angle) << 7); + } else { + a1 = 0xFFFF0000 - ((angle - 0x1000) << 7); + } + } + func_8012B178(param_1, a1); + iVar1 = func_8012CBA4(param_1); + if ((iVar1 & 0x6000) == 0) { + func_8012ADE4((u8 *)param_1); + } + *(s32 *)(param_1 + 0xe4) += 1; + +end: + return; +} + INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017F788); diff --git a/src/ov_SC03_110/ov_SC03_110_jr_8017D898.c b/src/ov_SC03_110/ov_SC03_110_jr_8017D898.c index e6c9e3a74..d19d9511e 100644 --- a/src/ov_SC03_110/ov_SC03_110_jr_8017D898.c +++ b/src/ov_SC03_110/ov_SC03_110_jr_8017D898.c @@ -3421,7 +3421,78 @@ L_end: } -INCLUDE_ASM("asm/ov_SC03_110/nonmatchings/ov_SC03_110_jr_8017D898", func_8017F4CC); + +/* Sibling pattern for the func_8012C354(a0, &D_xxx) gate + s0+0xC0/s0+0x2 flag + * writes is func_8017F3F4 in this same TU (ov_SC03_112_jr_8017C294.c, ~L3892): + * it declares the target-only data symbol as `extern M2C_UNK D_xxx;` and passes + * `(s32)&D_xxx` as the gate's second arg. Followed here for D_8019BF40. + * + * func_8012C354(s32,s32)->s32 : TU decl at L3911 (verbatim, adopted). + * func_8001CD9C(int,void*) : TU decl at L1818 (verbatim, adopted); defined + * void at src/800.c:5936 as (s32,s32) -- the TU's + * own extern spelling wins per law 2/8. + * func_8012C194(void)->s32, func_80143994(s32,s32)->s32, func_8012E8A8(u8*)->void + * : not declared in this TU; typed by the majority project-wide spelling. + */ + +extern s32 func_8012C354(s32 a0, s32 a1); +extern void func_8001CD9C(int, void *); +extern s32 func_8012C194(void); +extern s32 func_80143994(s32 a0, s32 a1); +extern void func_8012E8A8(u8 *a0); + + +void func_8017F4CC(s32 a0) { + + extern M2C_UNK D_8019BF40; + extern M2C_UNK D_8019BF74; + extern M2C_UNK D_8019BFBC; + extern M2C_UNK D_8019C00C; + s32 s0; + s32 v1; + u16 v0; + + if (func_8012C354(a0, (s32)&D_8019BF40)) { + v1 = *(s32 *)(a0 + 0x20); + *(u16 *)(v1 + 0x2C) |= 0x30; + v1 = *(s32 *)(a0 + 0x20); + *(void **)(v1 + 0x80) = &D_8019BF74; + *(s32 *)(a0 + 0xE8) = 0x40; + s0 = func_8012C194(); + if (s0 != 0) { + *(s32 *)(a0 + 0xD0) = s0; + func_8001CD9C((int)s0, (void *)&D_8019BFBC); + *(s16 *)(s0 + 0x18) = 0x555; + *(s16 *)(s0 + 0x1A) = 0x555; + *(s32 *)(s0 + 0x4) |= 0x50000000; + } + + v0 = *(u16 *)(a0 + 0x70); + if (v0 & 0x2) { + *(u16 *)(a0 + 0x2) = 0x8; + *(u8 *)(a0 + 0xC0) = 1; + *(void **)(a0 + 0xBC) = &D_8019C00C; + *(s32 *)(a0 + 0xB4) = -0x249D; + *(s32 *)(a0 + 0xC4) |= 0x2; + func_8012E8A8((u8 *)a0); + return; + } + + if (v0 & 0x1) { + *(u16 *)(a0 + 0x2) = 6; + *(u16 *)(a0 + 0x5C) &= 0x5FFF; + } else { + *(u8 *)(a0 + 0xC0) = 1; + *(void **)(a0 + 0xBC) = &D_8019C00C; + *(s32 *)(a0 + 0xB4) = -0x249D; + *(u16 *)(a0 + 0x2) = 1; + *(s32 *)(a0 + 0xC4) |= 0x2; + } + + *(s32 *)(a0 + 0xCC) = func_80143994(a0, 0x1000); + } +} + INCLUDE_ASM("asm/ov_SC03_110/nonmatchings/ov_SC03_110_jr_8017D898", func_8017F628); @@ -3600,6 +3671,72 @@ TAIL_5DC: } -INCLUDE_ASM("asm/ov_SC03_110/nonmatchings/ov_SC03_110_jr_8017D898", func_8017F9CC); +typedef struct { + SVECTOR_8016E7C8 v[4]; /* 0x00 */ + s32 f0, f1, f2, f3, f4, f5; /* 0x20..0x37 */ + u8 f6; /* 0x38 */ + u8 pad[7]; /* -> 0x40 */ +} Prim_8016E7C8_8017F9CC; + +extern s32 func_8012BCCC(s32 a0); +extern s32 func_8004787C(s32 a0); +extern s32 func_8012B8E4(s32 a0, s32 a1); + +void func_8017F9CC(s32 param_1) +{ + extern void func_80180C40(s32 a0); + extern s32 func_8012BDBC(s32 a0, s32 a1); + extern void func_8012B178(s32 a0, s32 a1); + extern s32 func_8012CBA4(s32 a0); + extern void func_8012ADE4(u8 *a0); + + s32 dist; + s32 angle; + s32 iVar1; + s32 a1; + + if (*(s16 *)(param_1 + 0xa) >= 0x10) { + func_80180C40(param_1); + goto end; + } + + dist = func_8012BCCC(param_1); + if (func_8012BDBC(param_1, 0x400) == 0) { + *(s16 *)(param_1 + 2) = 1; + goto end; + } + if (dist > 0x24000) { + *(s16 *)(param_1 + 2) = 1; + goto end; + } + if (dist < 0x4001) { + *(s16 *)(param_1 + 2) = 4; + goto end; + } + + angle = func_8004787C((*(s32 *)(param_1 + 0xe4) << 7) & 0x780); + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x1a) = (angle >> 1) + 0x800; + iVar1 = func_8012B8E4(param_1, 0xa); + { + s32 ptr = *(s32 *)(param_1 + 0x20); + s32 v = *(u16 *)(ptr + 0x12) + iVar1; + *(u16 *)(ptr + 0x12) = v; + if (0x1000 - angle >= 0) { + a1 = 0xFFFF0000 - ((0x1000 - angle) << 7); + } else { + a1 = 0xFFFF0000 - ((angle - 0x1000) << 7); + } + } + func_8012B178(param_1, a1); + iVar1 = func_8012CBA4(param_1); + if ((iVar1 & 0x6000) == 0) { + func_8012ADE4((u8 *)param_1); + } + *(s32 *)(param_1 + 0xe4) += 1; + +end: + return; +} + INCLUDE_ASM("asm/ov_SC03_110/nonmatchings/ov_SC03_110_jr_8017D898", func_8017FB14); diff --git a/src/ov_SC04_004/ov_SC04_004_jr_8017AE2C.c b/src/ov_SC04_004/ov_SC04_004_jr_8017AE2C.c index db916a403..f853f7cf9 100644 --- a/src/ov_SC04_004/ov_SC04_004_jr_8017AE2C.c +++ b/src/ov_SC04_004/ov_SC04_004_jr_8017AE2C.c @@ -6326,10 +6326,13 @@ INCLUDE_ASM("asm/ov_SC04_004/nonmatchings/ov_SC04_004_jr_8017AE2C", func_801832A // @class: plumbing // @stuck: none — MATCH (18 ins): if((b&1) && p!=&sym) call(param,&sym); $a0 live, $a1=&sym fall out extern void func_8012A828(s32 a0, void *a1); -extern void D_801B0750; void func_80183318(s32 arg0) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern void D_801B0750; if ((M2C_FIELD(arg0, u8 *, 0xC3) & 1) && (M2C_FIELD(arg0, void **, 0x90) != &D_801B0750)) { func_8012A828(arg0, &D_801B0750); } @@ -6406,11 +6409,160 @@ void func_80183588(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_004/nonmatchings/ov_SC04_004_jr_8017AE2C", func_8018359C); +typedef struct { s16 f0, f2, f4, f6, f8, fA, fC, fE; s32 f10; } St_80182784_80185DA8_8018359C; +typedef struct { s16 vx, vy, vz, pad; } SV_8017D7C0_8017F19C_8018359C; /* 8 bytes, align 2 */ +typedef struct { + s32 f0; + u8 pad[12]; +} Tbl16_8018BDE4_8018359C; +typedef struct { + SVECTOR_8016E7C8 v[4]; /* 0x00 */ + s32 f0, f1, f2, f3, f4, f5; /* 0x20..0x37 */ + u8 f6; /* 0x38 */ + u8 pad[7]; /* -> 0x40 */ +} Prim_8016E7C8_8018359C; + +extern s32 func_8012D5E4(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_8012EC04(s32 param_1, s32 param_2, s32 *param_3); +extern void func_8012F14C(s32 a0, s32 a1, s32 a2); +extern s32 func_8012C51C(void *a0, s32 a1); +extern void func_8012EFB8(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); +extern s32 func_8012BEE8(s32 a0); +extern void func_8012A828(s32 a0, void *a1); + +void func_8018359C(void *a0) { + + extern void D_801B0750; + if (*(s32 *)((char *)a0 + 0x1C) == 9) { + extern u8 D_801A8C54[]; + extern u8 D_801A8C64[]; + + func_8012D5E4((s32)a0, (s32)D_801A8C54, (s32)(D_801A8C54 + 8), 0x10); + + if (*(s16 *)((char *)a0 + 0x70) & 0x8000) { + u16 out[4]; + struct { s16 f0, f2, f4, f6, f8, fA, fC, fE; s32 f10; } s; + s32 buf[8]; + + func_8012EC04((s32)a0, 0, buf); + ((void (*)(s32 *, u8 *, u16 *))func_8012F14C)(buf, D_801A8C64, out); + + s.f6 = 0x23E; + s.f0 = out[0]; + s.f2 = out[1]; + s.f4 = out[2]; + s.fA = 0; + s.fC = 0x7FFF; + + s.fE = *(u16 *)(*(s32 *)((char *)a0 + 0x20) + 0x12); + func_8012C51C(&s, (s32)a0); + s.fE = *(u16 *)(*(s32 *)((char *)a0 + 0x20) + 0x12) + 0x100; + func_8012C51C(&s, (s32)a0); + s.fE = *(u16 *)(*(s32 *)((char *)a0 + 0x20) + 0x12) - 0x100; + func_8012C51C(&s, (s32)a0); + } + + { + u16 in3[3]; + s16 out2[2]; + s32 v; + + in3[0] = *(u16 *)((char *)a0 + 0x6); + in3[1] = *(u16 *)((char *)a0 + 0xA); + in3[2] = *(u16 *)((char *)a0 + 0xE); + + ((u32 (*)(u16 *, s16 *))func_8012EFB8)(in3, out2); + + v = out2[0]; + if (v < 0) { + v = -v; + } + if (v < 0xB5) { + v = out2[1]; + if (v < 0) { + v = -v; + } + if (v < 0xA1) { + func_8002D4C8(0x98B, 0); + } + } + } + } + + if (func_8012BEE8((s32)a0) != 0) { + *(s16 *)((char *)a0 + 0x2) = 3; + func_8012A828((s32)a0, &D_801B0750); + *(u16 *)((char *)a0 + 0x5C) = 0xAA10; + *(s16 *)((char *)a0 + 0x5E) = 0; + *(s16 *)((char *)a0 + 0xDC) = 0; + *(s32 *)((char *)a0 + 0x1C) = 0x2D; + } +} + INCLUDE_ASM("asm/ov_SC04_004/nonmatchings/ov_SC04_004_jr_8017AE2C", func_80183750); -INCLUDE_ASM("asm/ov_SC04_004/nonmatchings/ov_SC04_004_jr_8017AE2C", func_80183798); + +/* Fresh mass-lane crack (Phase-31 wave T). No banked twin was found for this + * skeleton (grepped D_801B3AC0 / D_801A8C14 / D_801A8C34 / D_801A8C6C / the + * jal callees across src/ -- only extern decls / INCLUDE_ASM stubs turned up, + * all for unrelated overlay-local reuses of the same address). The dispatch + * head (D_801A8C6C[*(u16*)(a0+2)]();) mirrors the ALREADY-BANKED + * func_8017EC70 in THIS SAME TU (D_8018C074[*(u16*)((s32)a0+2)]();) -- same + * idiom, used as a hint per law 1 (never copied its symbols). */ + +extern s32 func_8012C044(s32 a0); +extern void func_8002A04C(s32 a0); +extern void func_8012C098(void); +extern void func_8012E8A8(u8 *a0); +extern void func_800183E0(s32 a0); + +void func_80183798(void *a0) { + + extern void (*D_801A8C6C[])(void); + extern u16 D_800B99DA; + extern u16 D_801A8C14[]; + extern u16 D_801B3AC0[]; + extern u8 D_801A8C34[]; + void *s0 = a0; + + D_801A8C6C[*(u16 *)((u8 *)s0 + 0x2)](); + + if (func_8012C044((s32)s0)) { + *(s16 *)((u8 *)s0 + 0x100) = 1; + __asm__ __volatile__("" ::: "memory"); + *(s16 *)((u8 *)s0 + 0x76) = 0; + if (*(s16 *)((u8 *)s0 + 0x100) == 0) { + func_8002A04C((s32)s0); + } + if (*(s16 *)((u8 *)s0 + 0xFE) == 0) { + ((void (*)(void *))func_8012C098)(s0); + } else { + *(s16 *)((u8 *)s0 + 0x2) = 6; + func_8012E8A8((u8 *)s0); + *(s16 *)((u8 *)s0 + 0x5C) = 0; + *(u8 *)((u8 *)s0 + 0xC1) = 0; + } + } + + if (*(s16 *)((u8 *)s0 + 0xFE) != 0) { + u16 *src = D_801A8C14; + s32 shift = D_800B99DA & 0xF; + u16 *dst = &D_801B3AC0[shift]; + s32 i; + + for (i = 0; i < 0xF - shift; i++) { + *dst++ = *src++; + } + dst = D_801B3AC0; + for (i = 0; i < shift; i++) { + *dst++ = *src++; + } + func_800183E0((s32)D_801A8C34); + } +} + extern void (*D_801A8C90[])(void); @@ -6520,7 +6672,53 @@ void func_80183DBC(int param_1) } -INCLUDE_ASM("asm/ov_SC04_004/nonmatchings/ov_SC04_004_jr_8017AE2C", func_80183E2C); + +typedef struct { s16 a, b, c; } SV3x_80183E2C; /* 6-byte, align-2 triple of s16 */ +typedef struct { s16 a, b, c, d; } SV4x_80183E2C; /* 8-byte, align-2 quad of s16 */ + +extern void func_8012C218(void *a0); +extern void func_8012F214(s32 a0, s32 a1, s32 a2); + + +void func_80183E2C(void *a0) { + + extern s32 D_801B0D28; + extern s32 D_801A8C88; + s32 s0 = (s32)a0; + s32 s1; + SV3x_80183E2C out; + + s1 = *(s32 *)(s0 + 0x64); + + if (*(s16 *)(s0 + 0xFE) == 0x7FFF) { + *(s16 *)(s0 + 0xFE) = *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12); + } + + if (*(s16 *)(s0 + 0xFC) != *(s16 *)(s1 + 0x36)) { + func_8012C218((void *)s0); + return; + } + + *(SV4x_80183E2C *)(*(s32 *)(s0 + 0x20) + 0x10) = *(SV4x_80183E2C *)(*(s32 *)(s1 + 0x20) + 0x10); + + if (*(s32 *)(s1 + 0x90) != (s32)&D_801B0D28) { + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x12) = *(s16 *)(s0 + 0xFE); + *(s32 *)(s0 + 0x4) = *(s32 *)(s1 + 0x4); + *(s32 *)(s0 + 0x8) = *(s32 *)(s1 + 0x8); + *(s32 *)(s0 + 0xC) = *(s32 *)(s1 + 0xC); + } else { + func_8012F214(s1, (s32)&D_801A8C88, (s32)&out); + *(s16 *)(s0 + 0x6) = out.a; + *(s16 *)(s0 + 0xA) = out.b; + *(s16 *)(s0 + 0xE) = out.c; + } + + *(SV4x_80183E2C *)(*(s32 *)(s0 + 0x20) + 0x18) = *(SV4x_80183E2C *)(*(s32 *)(s1 + 0x20) + 0x18); + + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x2C) = *(s16 *)(*(s32 *)(s1 + 0x20) + 0x2C); + *(s32 *)(*(s32 *)(s0 + 0x20) + 0x4) = *(s32 *)(*(s32 *)(s1 + 0x20) + 0x4); +} + extern void (*D_801B0DF4[])(void); diff --git a/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c b/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c index ce9f44e1e..a0c85ff0e 100644 --- a/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c +++ b/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c @@ -317,7 +317,6 @@ extern s32 func_80012B04(s32 a0, s32 a1, s32 a2); extern void func_801490F8(s32 a0, s32 a1); extern s32 func_801491C4(s32 a0); extern s32 func_80149184(s32 a0); -extern s32 D_801151D4; extern void func_80149204(s32 *a0); extern void func_80149210(s32 a0, s32 a1); extern s32 func_80149284(s32 *a0, s32 a1); @@ -3175,7 +3174,101 @@ void func_8017CDF4(s32 a0) { INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_8017CE3C); -INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_8017CEF4); +typedef struct { short a, b, c; } SV3_80181D44_8017CEF4; /* == the TU's own `SV3` (engine_types.h:612); renamed only because +typedef struct { s16 vx, vy, vz, pad; } SV_8017D7C0_8017F19C_8017CEF4; /* 8 bytes, align 2 */ + +/* Callee externs — spellings copied from src/ov_SC04_002/ov_SC04_002_jr_8017BEBC.c + * (law 2). func_8017D098 is DEFINED later in that same TU as `void func_8017D098(void)` + * (a trivial wrapper around func_80151664()); our call site sets $a0 before the jal but + * the real body ignores it, so we declare it unprototyped (K&R style) to accept the + * dead argument without a conflicting-prototype error against the later definition. */ +extern void func_80149020(s32 *a0); +extern void func_80147A84(s32 arg0); +extern void func_801473EC(s32 *a0); +extern void func_80148038(s32 a0, s32 a1); +extern void func_80147460(s32 a0); +extern s32 func_801535F4(void *arg0); +extern void func_8017D098(); +extern void func_80159B3C(void *a0); +extern void func_8015BF48(s32 *a0); +extern s32 func_80146E98(s32 a0); +extern s32 func_80146A6C(s32 a0, void *a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); +extern void func_80165718(s32 a0); + +/* 16-byte-stride table at D_8018B4E8, indexed by the actor's 0xF2 animation/state id + * (signed s16); only the table row's first word (offset 0) is read. */ +typedef struct { + s32 f0; + u8 pad[12]; +} Tbl16_8018BDE4_8017CEF4; + +void func_8017CEF4(s32 a0) { + + extern Tbl16_8018BDE4_8017CEF4 D_8018B4E8[]; + s32 s0; + s16 s1; + s32 ret; + + s0 = *(s32 *)(a0 + 0x20); + func_80149020((s32 *)a0); + + s1 = *(s16 *)(s0 + 0x12); + *(s16 *)(s0 + 0x12) = *(u16 *)(a0 + 0x244); + func_80147A84(a0); + + func_801473EC((s32 *)a0); + func_80148038(a0, D_8018B4E8[*(s16 *)(a0 + 0xF2)].f0); + func_80147460(a0); + + *(s16 *)(s0 + 0x12) = s1; + + if (*(s32 *)(a0 + 0x234) == 0) { + if (*(s32 *)(a0 + 0x34) >= 0) { + if ((*(u16 *)(a0 + 0xB8) & 0x8000) != 0) { + __asm__ __volatile__("" ::: "memory"); + *(u16 *)(a0 + 0xB8) = *(u16 *)(a0 + 0xBA); + *(s32 *)(a0 + 0x234) = *(s32 *)(a0 + 0x234) + 1; + } + } + } + + ret = func_801535F4((void *)a0); + + if (ret == 1) { + goto L_case1; + } + if (ret < 2) { + goto L_default; + } + if (ret == 2) { + goto L_case2; + } + goto L_default; + +L_case1: + func_8017D098(a0); + func_80159B3C((void *)a0); + func_80146A6C(2, (void *)a0, 0, 0, 0, 1, 0); + func_80165718(a0); + return; + +L_case2: + func_8017D098(a0); + func_8015BF48((s32 *)a0); + func_80146A6C(2, (void *)a0, 0, 0, 0, 1, 0); + func_80165718(a0); + return; + +L_default: + if (func_80146E98(a0) == 0) { + return; + } + func_8017D098(a0); + func_80159B3C((void *)a0); + func_80146A6C(2, (void *)a0, 0, 0, 0, 1, 0); + func_80165718(a0); +} + extern void func_80151664(void); void func_8017D098(void) { @@ -6242,7 +6335,47 @@ INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_8018242 INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_801824F0); -INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_8018259C); +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_8017D7C0_8017F19C_8018259C; /* 0x20 bytes, align 4 */ + +typedef struct { u16 x, y, z, w; } V8_80181368_8018259C; + +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern s32 func_80133784(s32 a0, void *a1, s32 a2); + +s32 func_8018259C(s32 a0, s32 a1) { + V8_80181368_8018259C sp10; + V8_80181368_8018259C sp18; + s32 t; + s32 r; + + sp10.x = *(u16 *)(a0 + 0x6); + sp10.y = *(u16 *)(a0 + 0xA) - 0x20; + sp10.z = *(u16 *)(a0 + 0xE); + t = func_8004787C(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + r = (s16)a1; + sp18.y = sp10.y; + sp18.x = sp10.x - ((t * r) >> 12); + t = func_80047948(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + sp18.z = sp10.z - ((t * r) >> 12); + if ((func_80133784(1, &sp10, (s32)&sp18) & 0x8000) == 0) { + t = func_8004787C(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + sp10.x = *(u16 *)(a0 + 0x6) - ((t * 8) >> 12); + sp10.y = *(u16 *)(a0 + 0xA) - 0x10; + t = func_80047948(*(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF); + sp10.z = *(u16 *)(a0 + 0xE) - ((t * 8) >> 12); + sp18.x = sp10.x; + sp18.y = sp10.y + 0x20; + sp18.z = sp10.z; + if (func_80133784(1, &sp10, (s32)&sp18) & 0x6000) { + return 0; + } + } + *(s32 *)(a0 + 0x4) = *(s32 *)(a0 + 0x38); + *(s32 *)(a0 + 0xC) = *(s32 *)(a0 + 0x40); + return 1; +} + INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80182728); @@ -7044,7 +7177,79 @@ void func_80184A38(s32 a0) { INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80184C70); -INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80184CB4); + +extern void func_80185774(s32 a0); +extern s32 func_80029DB4(void); +extern s32 func_80029E30(void); +extern s32 func_801855A0(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_8012A828(s32, s32); +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void func_8012CBCC(s32 a0); + +void func_80184CB4(s32 a0) { + + extern s32 D_8011F730; + extern u8 D_801BE9EC[]; + extern s32 D_801BE63C; + extern s32 D_801BE6A4; + extern s32 D_801BE88C; + extern u8 D_801B59D0[]; + extern u8 D_801B59F0[]; + + s32 state; + s32 g; + s32 v0; + s32 arg0, arg1; + + func_80185774(a0); + state = *(u16 *)(a0 + 0x34); + + switch (state) { + case 0: + g = D_8011F730; + if (g == 2) { + *(u16 *)(a0 + 0x34) = 3; + ((void (*)(s32, void *))func_8012A828)(a0, D_801BE9EC); + return; + } else if (g == 3) { + *(u16 *)(a0 + 0x34) = 1; + ((void (*)(s32, void *))func_8012A828)(a0, &D_801BE63C); + return; + } else if (g == 4) { + *(u16 *)(a0 + 0x34) = 2; + ((void (*)(s32, void *))func_8012A828)(a0, &D_801BE6A4); + return; + } + goto tail_short; + case 1: + v0 = func_80029DB4(); + func_801855A0(a0, (s32)D_801B59D0, 7, v0); + arg0 = 0x1EB; + arg1 = 0; + break; + case 2: + v0 = func_80029E30(); + func_801855A0(a0, (s32)D_801B59F0, 6, v0); + arg0 = 0x1EB; + arg1 = 1; + break; + case 3: + goto tail_short; + default: + return; + } + + func_8012C658(arg0, arg1, a0); + if (*(u16 *)(a0 + 0x72) & 0x4000) { + ((void (*)(s32, void *))func_8012A828)(a0, &D_801BE88C); + } + +tail_short: + if (((s32 (*)(s32))func_8012CBCC)(a0) & 0x2000) { + *(u16 *)(a0 + 0x2) = 1; + } +} + INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80184E38); @@ -7360,7 +7565,88 @@ INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_8018591 INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80185A08); -INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80185B70); +extern s32 func_80132EF4(s32 a0, s32 a1); +typedef struct { short a, b, c; } SV3_80181D44_80185B70; /* == the TU's own `SV3` (engine_types.h:612); renamed only because + +extern s32 func_80132EF4(s32 a0, s32 a1); +extern s32 rand(void); +/* func_80185CEC is the NEXT stub in this same TU (INCLUDE_ASM at the line below + * func_80185B70's). Its own .s takes TWO args ($a0 = entity-owner, $a1 = id): + * do NOT adopt the 1-arg `void f(void*)` spelling that the *unrelated* overlay + * ov_SC03_001 uses for its own different function at the same address. */ +extern void func_80185CEC(s32 a0, s32 a1); + +/* Spawn a 0x4F entity for `a0`, then jitter its three s16 fields at +0x6/+0xA/+0xE + * by a random amount (mod 28 / 32 / 28, sign picked by a second rand()), flip the + * substruct at *(s32*)(entity+0x20) fields 0x18/0x1A/0x1C to +/-0x2000, and notify. */ +s32 func_80185B70(s32 a0) { + s32 s2; + + s2 = func_80132EF4(a0, 0x4F); + if (s2 == 0) { + return 0; + } + + *(s16 *)(s2 + 0xA) = *(u16 *)(s2 + 0xA) - 0x28; + + /* NOTE (this is the whole match, do not "tidy" it): each block MUST own its + * own r/val/base locals. With one shared `r` across all three blocks, the + * /32 block's remainder pseudo conflicts with the rand()-result pseudo, so + * global.c's expand_preferences() cannot merge their preferences (it needs + * a non-conflicting REG_DEAD copy). The result pseudo then has NO hard-reg + * preference of its own, prune_preferences() puts $v1 into its + * regs_someone_prefers set, and find_reg's pass 0 skips $v1 and lands the + * value in $a0 instead of the target's $v1 (4 wrong instructions). */ + { + s32 r, val, base; + r = rand() % 28; + base = *(s16 *)(s2 + 0x6); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0x6) = val; + } + { + s32 r, val, base; + r = rand() % 32; + base = *(s16 *)(s2 + 0xA); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0xA) = val; + } + { + s32 r, val, base; + r = rand() % 28; + base = *(s16 *)(s2 + 0xE); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0xE) = val; + } + + { + s32 v0, v1; + + if (rand() & 1) { + v1 = *(s32 *)(s2 + 0x20); + v0 = -0x2000; + *(s16 *)(v1 + 0x1C) = v0; + } else { + v1 = *(s32 *)(s2 + 0x20); + v0 = 0x2000; + *(s16 *)(v1 + 0x1C) = v0; + } + *(s16 *)(v1 + 0x1A) = v0; + *(s16 *)(v1 + 0x18) = v0; + } + + /* Zero-byte scheduling fence (§190-C). Without it BOTH sched1 and sched2 + * independently hoist the call's `move $a0,$s3` + `li $a1,0x7F3` above the + * two trailing `sh` stores (they feed the jal, so they carry the higher + * INSN_PRIORITY), and reorg then fills the delay slot with `sh 0x18` + * instead of the target's `addiu $a1`. -fno-schedule-insns{,2} alone does + * not reproduce the target order -- only both together do, hence a real + * barrier rather than a statement reorder. */ + __asm__ __volatile__("" ::: "memory"); + func_80185CEC(a0, 0x7F3); + return s2; +} + INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80185CEC); @@ -7923,7 +8209,83 @@ void func_801869D4(s32 a0, s32 a1, s32 a2) } -INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80186C80); +typedef struct { s16 vx, vy, vz, pad; } SV_8017D7C0_8017F19C_80186C80; /* 8 bytes, align 2 */ + +/* func_80186C80 (ov_SC04_002, ov_SC04_002_jr_8017BEBC, 83 ins) + * + * Sibling family (skeleton group, remapped mechanically once this banks): + * ov_SC02_041:func_8018428C, ov_SC04_005:func_80186C80, ov_SC04_007:func_801832EC + * + * Two conflicting local extern decls exist for this function in the TU + * (func_8018739C uses `void *a1, MATRIX *a3`; func_80187604 uses `s32 a1, + * void *a3`) -- neither is dereferenced structurally inside this function's + * own body (a3 is only ever forwarded as an opaque pointer argument), so the + * definition-side signature below (s32 a1, void *a3) is chosen freely and is + * compatible with both call sites' own local prototypes. + */ +void func_80186C80(s32 a0, s32 a1, s32 a2, void *a3) +{ + extern s32 D_801151D4; + extern void func_8012EC04(s32 param_1, s32 param_2, s32 *param_3); + extern void func_8012F14C(s32 a0, s32 a1, s32 a2); + extern void func_800D20C0(void *a0, void *a1, s32 a2); + extern void func_80017E68(void *a0, void *a1); + extern void func_800D23D0(void *a0); + extern void ApplyMatrixSV(void *a0, void *a1, void *a2); + extern void RotMatrixYXZ(void *a0, void *a1); + extern void ApplyTransposeMatrixLV(void *a0, void *a1, void *a2); + extern s32 ratan2(s32 a0, s32 a1); + + s32 mtx1[8]; /* sp+0x10, 0x20 bytes: scratch MATRIX */ + s16 buf2[4]; /* sp+0x30, 8 bytes: vx,vy,vz,pad */ + s16 vec[4]; /* sp+0x38, 8 bytes: vx,vy,vz,pad */ + s32 diff[3]; /* sp+0x40 */ + s32 base; + s32 v0; + s32 v1; + + base = D_801151D4; + + func_8012EC04(a0, a2, (s32 *)mtx1); + + func_8012F14C((s32)mtx1, a1 + 0x18, (s32)buf2); + + func_800D20C0((void *)buf2, (void *)vec, 8); + + func_80017E68((void *)buf2, a3); + + v0 = *(u16 *)(a1 + 0x8); + v1 = *(u16 *)(a1 + 0x10); + v0 = v0 - v1; + vec[0] = v0; + v0 = *(u16 *)(a1 + 0xA); + v1 = *(u16 *)(a1 + 0x12); + v0 = v0 - v1; + vec[1] = v0; + v0 = *(u16 *)(a1 + 0xC); + v1 = *(u16 *)(a1 + 0x14); + v0 = v0 - v1; + vec[2] = v0; + + ApplyMatrixSV((void *)mtx1, (void *)vec, (void *)vec); + + func_800D23D0((void *)vec); + + RotMatrixYXZ((void *)vec, a3); + + diff[0] = *(s32 *)(base + 0x5C) - buf2[0]; + diff[1] = *(s32 *)(base + 0x60) - buf2[1]; + diff[2] = *(s32 *)(base + 0x64) - buf2[2]; + + ApplyTransposeMatrixLV(a3, (void *)diff, (void *)diff); + + v0 = ratan2(diff[0], diff[1]); + + vec[2] = -v0; + + RotMatrixYXZ((void *)vec, a3); +} + typedef struct { u32 addr : 24; u32 len : 8; } PTag_801843D8_80186DCC; #define gte_ldv3_801843D8(r0, r1, r2) __asm__ volatile ( \ diff --git a/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c b/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c index e0f7f1e92..898be30a8 100644 --- a/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c +++ b/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c @@ -318,7 +318,6 @@ extern s32 func_80012B04(s32 a0, s32 a1, s32 a2); extern void func_801490F8(s32 a0, s32 a1); extern s32 func_801491C4(s32 a0); extern s32 func_80149184(s32 a0); -extern s32 D_801151D4; extern void func_80149204(s32 *a0); extern void func_80149210(s32 a0, s32 a1); extern s32 func_80149284(s32 *a0, s32 a1); @@ -5751,7 +5750,79 @@ void func_801810A4(s32 a0) { INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_801812DC); -INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80181320); + +extern void func_80181DE0(s32 a0); +extern s32 func_80029DB4(void); +extern s32 func_80029E30(void); +extern s32 func_80181C0C(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_8012A828(s32, s32); +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void func_8012CBCC(s32 a0); + +void func_80181320(s32 a0) { + + extern s32 D_8011F730; + extern u8 D_801A1094[]; + extern s32 D_801A0CE4; + extern s32 D_801A0D4C; + extern s32 D_801A0F34; + extern u8 D_80198078[]; + extern u8 D_80198098[]; + + s32 state; + s32 g; + s32 v0; + s32 arg0, arg1; + + func_80181DE0(a0); + state = *(u16 *)(a0 + 0x34); + + switch (state) { + case 0: + g = D_8011F730; + if (g == 2) { + *(u16 *)(a0 + 0x34) = 3; + ((void (*)(s32, void *))func_8012A828)(a0, D_801A1094); + return; + } else if (g == 3) { + *(u16 *)(a0 + 0x34) = 1; + ((void (*)(s32, void *))func_8012A828)(a0, &D_801A0CE4); + return; + } else if (g == 4) { + *(u16 *)(a0 + 0x34) = 2; + ((void (*)(s32, void *))func_8012A828)(a0, &D_801A0D4C); + return; + } + goto tail_short; + case 1: + v0 = func_80029DB4(); + func_80181C0C(a0, (s32)D_80198078, 7, v0); + arg0 = 0x1EB; + arg1 = 0; + break; + case 2: + v0 = func_80029E30(); + func_80181C0C(a0, (s32)D_80198098, 6, v0); + arg0 = 0x1EB; + arg1 = 1; + break; + case 3: + goto tail_short; + default: + return; + } + + func_8012C658(arg0, arg1, a0); + if (*(u16 *)(a0 + 0x72) & 0x4000) { + ((void (*)(s32, void *))func_8012A828)(a0, &D_801A0F34); + } + +tail_short: + if (((s32 (*)(s32))func_8012CBCC)(a0) & 0x2000) { + *(u16 *)(a0 + 0x2) = 1; + } +} + INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_801814A4); @@ -6057,7 +6128,88 @@ INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80181F8 INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80182074); -INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_801821DC); +extern s32 func_80132EF4(s32 a0, s32 a1); +typedef struct { short a, b, c; } SV3_80181D44_801821DC; /* == the TU's own `SV3` (engine_types.h:612); renamed only because + +extern s32 func_80132EF4(s32 a0, s32 a1); +extern s32 rand(void); +/* func_80182358 is the NEXT stub in this same TU (INCLUDE_ASM at the line below + * func_801821DC's). Its own .s takes TWO args ($a0 = entity-owner, $a1 = id): + * do NOT adopt the 1-arg `void f(void*)` spelling that the *unrelated* overlay + * ov_SC03_001 uses for its own different function at the same address. */ +extern void func_80182358(s32 a0, s32 a1); + +/* Spawn a 0x4F entity for `a0`, then jitter its three s16 fields at +0x6/+0xA/+0xE + * by a random amount (mod 28 / 32 / 28, sign picked by a second rand()), flip the + * substruct at *(s32*)(entity+0x20) fields 0x18/0x1A/0x1C to +/-0x2000, and notify. */ +s32 func_801821DC(s32 a0) { + s32 s2; + + s2 = func_80132EF4(a0, 0x4F); + if (s2 == 0) { + return 0; + } + + *(s16 *)(s2 + 0xA) = *(u16 *)(s2 + 0xA) - 0x28; + + /* NOTE (this is the whole match, do not "tidy" it): each block MUST own its + * own r/val/base locals. With one shared `r` across all three blocks, the + * /32 block's remainder pseudo conflicts with the rand()-result pseudo, so + * global.c's expand_preferences() cannot merge their preferences (it needs + * a non-conflicting REG_DEAD copy). The result pseudo then has NO hard-reg + * preference of its own, prune_preferences() puts $v1 into its + * regs_someone_prefers set, and find_reg's pass 0 skips $v1 and lands the + * value in $a0 instead of the target's $v1 (4 wrong instructions). */ + { + s32 r, val, base; + r = rand() % 28; + base = *(s16 *)(s2 + 0x6); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0x6) = val; + } + { + s32 r, val, base; + r = rand() % 32; + base = *(s16 *)(s2 + 0xA); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0xA) = val; + } + { + s32 r, val, base; + r = rand() % 28; + base = *(s16 *)(s2 + 0xE); + val = (rand() & 1) ? (base + r) : (base - r); + *(s16 *)(s2 + 0xE) = val; + } + + { + s32 v0, v1; + + if (rand() & 1) { + v1 = *(s32 *)(s2 + 0x20); + v0 = -0x2000; + *(s16 *)(v1 + 0x1C) = v0; + } else { + v1 = *(s32 *)(s2 + 0x20); + v0 = 0x2000; + *(s16 *)(v1 + 0x1C) = v0; + } + *(s16 *)(v1 + 0x1A) = v0; + *(s16 *)(v1 + 0x18) = v0; + } + + /* Zero-byte scheduling fence (§190-C). Without it BOTH sched1 and sched2 + * independently hoist the call's `move $a0,$s3` + `li $a1,0x7F3` above the + * two trailing `sh` stores (they feed the jal, so they carry the higher + * INSN_PRIORITY), and reorg then fills the delay slot with `sh 0x18` + * instead of the target's `addiu $a1`. -fno-schedule-insns{,2} alone does + * not reproduce the target order -- only both together do, hence a real + * barrier rather than a statement reorder. */ + __asm__ __volatile__("" ::: "memory"); + func_80182358(a0, 0x7F3); + return s2; +} + INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80182358); @@ -6620,7 +6772,83 @@ void func_80183040(s32 a0, s32 a1, s32 a2) } -INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_801832EC); +typedef struct { s16 vx, vy, vz, pad; } SV_8017D7C0_8017F19C_801832EC; /* 8 bytes, align 2 */ + +/* func_801832EC (ov_SC04_002, ov_SC04_002_jr_8017BEBC, 83 ins) + * + * Sibling family (skeleton group, remapped mechanically once this banks): + * ov_SC02_041:func_8018428C, ov_SC04_005:func_80186C80, ov_SC04_007:func_801832EC + * + * Two conflicting local extern decls exist for this function in the TU + * (func_8018739C uses `void *a1, MATRIX *a3`; func_80187604 uses `s32 a1, + * void *a3`) -- neither is dereferenced structurally inside this function's + * own body (a3 is only ever forwarded as an opaque pointer argument), so the + * definition-side signature below (s32 a1, void *a3) is chosen freely and is + * compatible with both call sites' own local prototypes. + */ +void func_801832EC(s32 a0, s32 a1, s32 a2, void *a3) +{ + extern s32 D_801151D4; + extern void func_8012EC04(s32 param_1, s32 param_2, s32 *param_3); + extern void func_8012F14C(s32 a0, s32 a1, s32 a2); + extern void func_800D20C0(void *a0, void *a1, s32 a2); + extern void func_80017E68(void *a0, void *a1); + extern void func_800D23D0(void *a0); + extern void ApplyMatrixSV(void *a0, void *a1, void *a2); + extern void RotMatrixYXZ(void *a0, void *a1); + extern void ApplyTransposeMatrixLV(void *a0, void *a1, void *a2); + extern s32 ratan2(s32 a0, s32 a1); + + s32 mtx1[8]; /* sp+0x10, 0x20 bytes: scratch MATRIX */ + s16 buf2[4]; /* sp+0x30, 8 bytes: vx,vy,vz,pad */ + s16 vec[4]; /* sp+0x38, 8 bytes: vx,vy,vz,pad */ + s32 diff[3]; /* sp+0x40 */ + s32 base; + s32 v0; + s32 v1; + + base = D_801151D4; + + func_8012EC04(a0, a2, (s32 *)mtx1); + + func_8012F14C((s32)mtx1, a1 + 0x18, (s32)buf2); + + func_800D20C0((void *)buf2, (void *)vec, 8); + + func_80017E68((void *)buf2, a3); + + v0 = *(u16 *)(a1 + 0x8); + v1 = *(u16 *)(a1 + 0x10); + v0 = v0 - v1; + vec[0] = v0; + v0 = *(u16 *)(a1 + 0xA); + v1 = *(u16 *)(a1 + 0x12); + v0 = v0 - v1; + vec[1] = v0; + v0 = *(u16 *)(a1 + 0xC); + v1 = *(u16 *)(a1 + 0x14); + v0 = v0 - v1; + vec[2] = v0; + + ApplyMatrixSV((void *)mtx1, (void *)vec, (void *)vec); + + func_800D23D0((void *)vec); + + RotMatrixYXZ((void *)vec, a3); + + diff[0] = *(s32 *)(base + 0x5C) - buf2[0]; + diff[1] = *(s32 *)(base + 0x60) - buf2[1]; + diff[2] = *(s32 *)(base + 0x64) - buf2[2]; + + ApplyTransposeMatrixLV(a3, (void *)diff, (void *)diff); + + v0 = ratan2(diff[0], diff[1]); + + vec[2] = -v0; + + RotMatrixYXZ((void *)vec, a3); +} + typedef struct { u32 addr : 24; u32 len : 8; } PTag_801843D8_80183438; #define gte_ldv3_801843D8(r0, r1, r2) __asm__ volatile ( \ diff --git a/src/ov_SC05_001/ov_SC05_001_jr_8017BEBC.c b/src/ov_SC05_001/ov_SC05_001_jr_8017BEBC.c index 81ebf3c01..19951ff2a 100644 --- a/src/ov_SC05_001/ov_SC05_001_jr_8017BEBC.c +++ b/src/ov_SC05_001/ov_SC05_001_jr_8017BEBC.c @@ -5624,7 +5624,78 @@ L_end: } -INCLUDE_ASM("asm/ov_SC05_001/nonmatchings/ov_SC05_001_jr_8017BEBC", func_80182E0C); + +/* Sibling pattern for the func_8012C354(a0, &D_xxx) gate + s0+0xC0/s0+0x2 flag + * writes is func_8017F3F4 in this same TU (ov_SC03_112_jr_8017C294.c, ~L3892): + * it declares the target-only data symbol as `extern M2C_UNK D_xxx;` and passes + * `(s32)&D_xxx` as the gate's second arg. Followed here for D_801AE2E4. + * + * func_8012C354(s32,s32)->s32 : TU decl at L3911 (verbatim, adopted). + * func_8001CD9C(int,void*) : TU decl at L1818 (verbatim, adopted); defined + * void at src/800.c:5936 as (s32,s32) -- the TU's + * own extern spelling wins per law 2/8. + * func_8012C194(void)->s32, func_80143994(s32,s32)->s32, func_8012E8A8(u8*)->void + * : not declared in this TU; typed by the majority project-wide spelling. + */ + +extern s32 func_8012C354(s32 a0, s32 a1); +extern void func_8001CD9C(int, void *); +extern s32 func_8012C194(void); +extern s32 func_80143994(s32 a0, s32 a1); +extern void func_8012E8A8(u8 *a0); + + +void func_80182E0C(s32 a0) { + + extern M2C_UNK D_801AE2E4; + extern M2C_UNK D_801AE318; + extern M2C_UNK D_801AE360; + extern M2C_UNK D_801AE3B0; + s32 s0; + s32 v1; + u16 v0; + + if (func_8012C354(a0, (s32)&D_801AE2E4)) { + v1 = *(s32 *)(a0 + 0x20); + *(u16 *)(v1 + 0x2C) |= 0x30; + v1 = *(s32 *)(a0 + 0x20); + *(void **)(v1 + 0x80) = &D_801AE318; + *(s32 *)(a0 + 0xE8) = 0x40; + s0 = func_8012C194(); + if (s0 != 0) { + *(s32 *)(a0 + 0xD0) = s0; + func_8001CD9C((int)s0, (void *)&D_801AE360); + *(s16 *)(s0 + 0x18) = 0x555; + *(s16 *)(s0 + 0x1A) = 0x555; + *(s32 *)(s0 + 0x4) |= 0x50000000; + } + + v0 = *(u16 *)(a0 + 0x70); + if (v0 & 0x2) { + *(u16 *)(a0 + 0x2) = 0x8; + *(u8 *)(a0 + 0xC0) = 1; + *(void **)(a0 + 0xBC) = &D_801AE3B0; + *(s32 *)(a0 + 0xB4) = -0x249D; + *(s32 *)(a0 + 0xC4) |= 0x2; + func_8012E8A8((u8 *)a0); + return; + } + + if (v0 & 0x1) { + *(u16 *)(a0 + 0x2) = 6; + *(u16 *)(a0 + 0x5C) &= 0x5FFF; + } else { + *(u8 *)(a0 + 0xC0) = 1; + *(void **)(a0 + 0xBC) = &D_801AE3B0; + *(s32 *)(a0 + 0xB4) = -0x249D; + *(u16 *)(a0 + 0x2) = 1; + *(s32 *)(a0 + 0xC4) |= 0x2; + } + + *(s32 *)(a0 + 0xCC) = func_80143994(a0, 0x1000); + } +} + INCLUDE_ASM("asm/ov_SC05_001/nonmatchings/ov_SC05_001_jr_8017BEBC", func_80182F68); @@ -5803,6 +5874,72 @@ TAIL_5DC: } -INCLUDE_ASM("asm/ov_SC05_001/nonmatchings/ov_SC05_001_jr_8017BEBC", func_8018330C); +typedef struct { + SVECTOR_8016E7C8 v[4]; /* 0x00 */ + s32 f0, f1, f2, f3, f4, f5; /* 0x20..0x37 */ + u8 f6; /* 0x38 */ + u8 pad[7]; /* -> 0x40 */ +} Prim_8016E7C8_8018330C; + +extern s32 func_8012BCCC(s32 a0); +extern s32 func_8004787C(s32 a0); +extern s32 func_8012B8E4(s32 a0, s32 a1); + +void func_8018330C(s32 param_1) +{ + extern void func_80184580(s32 a0); + extern s32 func_8012BDBC(s32 a0, s32 a1); + extern void func_8012B178(s32 a0, s32 a1); + extern s32 func_8012CBA4(s32 a0); + extern void func_8012ADE4(u8 *a0); + + s32 dist; + s32 angle; + s32 iVar1; + s32 a1; + + if (*(s16 *)(param_1 + 0xa) >= 0x10) { + func_80184580(param_1); + goto end; + } + + dist = func_8012BCCC(param_1); + if (func_8012BDBC(param_1, 0x400) == 0) { + *(s16 *)(param_1 + 2) = 1; + goto end; + } + if (dist > 0x24000) { + *(s16 *)(param_1 + 2) = 1; + goto end; + } + if (dist < 0x4001) { + *(s16 *)(param_1 + 2) = 4; + goto end; + } + + angle = func_8004787C((*(s32 *)(param_1 + 0xe4) << 7) & 0x780); + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x1a) = (angle >> 1) + 0x800; + iVar1 = func_8012B8E4(param_1, 0xa); + { + s32 ptr = *(s32 *)(param_1 + 0x20); + s32 v = *(u16 *)(ptr + 0x12) + iVar1; + *(u16 *)(ptr + 0x12) = v; + if (0x1000 - angle >= 0) { + a1 = 0xFFFF0000 - ((0x1000 - angle) << 7); + } else { + a1 = 0xFFFF0000 - ((angle - 0x1000) << 7); + } + } + func_8012B178(param_1, a1); + iVar1 = func_8012CBA4(param_1); + if ((iVar1 & 0x6000) == 0) { + func_8012ADE4((u8 *)param_1); + } + *(s32 *)(param_1 + 0xe4) += 1; + +end: + return; +} + INCLUDE_ASM("asm/ov_SC05_001/nonmatchings/ov_SC05_001_jr_8017BEBC", func_80183454); diff --git a/src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c b/src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c index 3e1ac1e5a..8e1e891a1 100644 --- a/src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c +++ b/src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c @@ -4452,7 +4452,93 @@ void func_8018A0B8(s32 param_1) { INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018A170); -INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018A28C); +typedef struct { s32 a; s32 b[4]; } OtBlk_8018A974_8018EB08_8018A28C; /* == engine_types.h OtBlk (0x14) */ + +/* func_8018A28C — ov_SC06_032 / ov_SC06_032_jr_80182890, 122 ins. + * + * State entry dispatcher: switch on (flags@0x70 & 3), where cases {0,2} take the + * "spawn child object" arm and cases {1,3} take the "allocate display object" arm; + * both then fall into a shared tail that primes the display object at +0x20. + * + * The 4-way compare tree (beq 1 / slti 2 / beqz 0 / beq 2 / beq 3 / j default) is + * gcc-2.7.2's balanced case tree for the four labels 0..3 with two shared bodies. + */ + + +extern int func_8012C354(); +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void func_8012C1B8(void); +extern void func_8012CAE4(); +extern void func_8001C214(); +extern s32 func_8012AD50(void *arg0); +extern void func_8018C310(void); +extern void func_8018AB00(void); +extern void func_8018A474(void *arg0); + +void func_8018A28C(s32 param_1) { + + extern u8 D_801CD3B0[]; + extern u8 D_801CD3C0[]; + extern u8 D_801CD3D8[]; + extern u8 D_801D1094[]; + s32 obj; + s32 g; + + switch (*(u16 *)(param_1 + 0x70) & 3) { + case 0: + case 2: + if (((s32 (*)(s32, u8 *))func_8012C354)(param_1, D_801CD3D8) == 0) { + return; + } + *(s32 *)(param_1 + 0xCC) = + func_8012C658(0x2E4, (*(u16 *)(param_1 + 0x70) & 2) | 1, param_1); + *(u16 *)(param_1 + 0x104) = *(u16 *)(param_1 + 0x70) & 0x102; + *(u16 *)(param_1 + 0x70) = *(u16 *)(param_1 + 0x70) & 1; + if (*(u16 *)(param_1 + 0x104) & 0x100) { + func_8018C310(); + func_8018AB00(); + } + *(u8 *)(param_1 + 0xC0) = 1; + *(u8 **)(param_1 + 0xBC) = D_801CD3C0; + *(s32 *)(param_1 + 0xB4) = 0; + *(u8 *)(param_1 + 0xC1) = 0; + *(s16 *)(param_1 + 0xAE) = 0x6918; + *(u32 *)(param_1 + 0xC4) |= 2; + break; + + case 1: + case 3: + obj = ((s32 (*)(void))func_8012C1B8)(); + *(s32 *)(param_1 + 0x20) = obj; + if (obj == 0) { + ((void (*)(s32))func_8012CAE4)(param_1); + return; + } + ((void (*)(s32, u8 *))func_8001C214)(obj, D_801D1094); + *(u16 *)(param_1 + 0x104) = *(u16 *)(param_1 + 0x70) & 2; + *(u16 *)(param_1 + 0x70) = *(u16 *)(param_1 + 0x70) & 1; + *(u16 *)(param_1 + 0xA) = *(u16 *)(param_1 + 0xA) - 0xA0; + break; + } + + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x2C) |= 0x10; + /* one cached base for the three 0xE00 stores: the target loads 0x20($s0) + * only once here, so the source must hold it in a pseudo (any indirect + * store invalidates the CSE of the load in gcc-2.7.2). */ + g = *(s32 *)(param_1 + 0x20); + *(s16 *)(g + 0x1C) = 0xE00; + *(s16 *)(g + 0x1A) = 0xE00; + *(s16 *)(g + 0x18) = 0xE00; + *(u8 *)(param_1 + 0x75) = 0; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x2C) |= 0x80; + *(u8 **)(*(s32 *)(param_1 + 0x20) + 0x80) = D_801CD3B0; + if (*(s16 *)(param_1 + 0x70) != 0 && *(s16 *)(param_1 + 0x104) != 0) { + func_8018A474((void *)param_1); + } else { + func_8012AD50((void *)param_1); + } +} + extern void func_8012AD44(s32 *a0, s16 a1); void func_8018A474(void *arg0) { @@ -4671,7 +4757,6 @@ INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018AE6 // `addiu $a0,$sp,0x10` at each use site. -extern Blk20_8018AF88 D_800AE620; extern s32 D_801CD498; extern s32 func_8012B8A4(s16 *a0); @@ -4682,6 +4767,10 @@ extern s32 rand(void); void func_8018AF88(s32 param_1) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern Blk20_8018AF88 D_800AE620; Blk20_8018AF88 local_30; Blk20_8018AF88 *m; s32 iVar1; @@ -4705,9 +4794,117 @@ void func_8018AF88(s32 param_1) INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018B060); -INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018B1D8); +typedef struct { s32 a; s32 b[4]; } OtBlk_8018A974_8018EB08_8018B1D8; /* == engine_types.h OtBlk (0x14) */ + +/* Local standins for the shared types (src/shared/engine_types.h) that the real TU pulls in via + * "../shared/engine_core.h" -- match_one's -Iinclude can't reach src/shared/, so these are typed + * identically for the standalone compile only; the real TU already has both. */ + + + +/* STEP 0 magic-literal grep: aD800AE620_8018B1D8 / D_801CD40C / ApplyMatrixSV / func_8012AD44 turned up the + * banked sibling func_80186160 (same TU) which establishes: the whole-struct + * `local = aD800AE620_8018B1D8;` idiom (typed Blk20_8018AF88_80186160, from src/shared/engine_types.h), the + * address of that local cached into a POINTER LOCAL (forced into $s1 because it's live across the + * RotMatrixY call and reused as ApplyMatrixSV's a0), and the `func_8012AD44((s32 *)param_1, N)` + * call-through form. D_801CD40C here is a per-overlay array of SVECTOR (indexed *8 = sizeof(SVECTOR)), + * unrelated to the scalar u8 D_801CD40C seen in ov_SC03_104 (different overlay, same address). + */ + +extern void RotMatrixY(s32 a0, void *a1); +extern void ApplyMatrixSV(void *a0, void *a1, void *a2); +extern void func_8012AD44(s32 *a0, s16 a1); +extern s32 rand(void); + +void func_8018B1D8(s32 param_1) +{ + + extern Blk20_8018AF88_80186160 aD800AE620_8018B1D8 __asm__("D_800AE620"); + extern SVECTOR D_801CD40C[]; + Blk20_8018AF88_80186160 local_38; + Blk20_8018AF88_80186160 *m; + SVECTOR out; + s32 rotY; + s32 t; + s16 v1; + + local_38 = aD800AE620_8018B1D8; + rotY = rand() & 0x1F0; + m = &local_38; + RotMatrixY(rotY, m); + ApplyMatrixSV(m, &D_801CD40C[*(s16 *)(param_1 + 0x70)], &out); + + *(u16 *)(param_1 + 6) = *(u16 *)(*(s32 *)(param_1 + 0x64) + 6) + (u16)out.vx; + *(u16 *)(param_1 + 0xA) = *(u16 *)(*(s32 *)(param_1 + 0x64) + 0xA) + (u16)out.vy; + *(u16 *)(param_1 + 0xE) = *(u16 *)(*(s32 *)(param_1 + 0x64) + 0xE) + (u16)out.vz; + + *(s32 *)(param_1 + 0x10) = (s32)out.vx << 12; + t = -(((rand() & 0x3F) << 12) + 0x200000); + *(s32 *)(param_1 + 0x14) = t; + *(s32 *)(param_1 + 0xE0) = t; + *(s32 *)(param_1 + 0x18) = (s32)out.vz << 12; + + *(u16 *)(param_1 + 0x106) = rand() & 0xF0; + *(u16 *)(param_1 + 0x108) = rand() & 0xF0; + v1 = *(s16 *)(param_1 + 0x70); + *(u16 *)(param_1 + 0xFE) = v1; + + func_8012AD44((s32 *)param_1, 2); +} + + + +extern void func_8012CC40(s32 arg0, s32 arg1); /* fleet-canonical: void; $v0 used -> cast at use */ +extern s32 func_8012BEE8(s32 a0); +extern void func_8012C218(void *a0); +extern void func_8018B714(s32 a0); + +void func_8018B330(s32 param_1) +{ + + extern s32 D_801CD4A8; + s32 iVar; + + switch (*(u16 *)(param_1 + 0x34)) { + case 0: + iVar = ((s32 (*)(s32, s32))func_8012CC40)(param_1, (s32)&D_801CD4A8); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x10) = + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x10) + *(u16 *)(param_1 + 0x106); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x14) = + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x14) + *(u16 *)(param_1 + 0x108); + if (iVar != 0) { + u16 ns = *(u16 *)(param_1 + 0x34) + 1; + *(s32 *)(param_1 + 0x14) = *(s32 *)(param_1 + 0xE0) >> 1; + *(s32 *)(param_1 + 0x10) = *(s32 *)(param_1 + 0x10) >> 1; + *(s32 *)(param_1 + 0x18) = *(s32 *)(param_1 + 0x18) >> 1; + *(u16 *)(param_1 + 0x34) = ns; + } + func_8018B714(param_1); + break; + case 1: + iVar = ((s32 (*)(s32, s32))func_8012CC40)(param_1, (s32)&D_801CD4A8); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x10) = + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x10) + *(u16 *)(param_1 + 0x106); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x14) = + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x14) + *(u16 *)(param_1 + 0x108); + if (iVar != 0) { + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + *(s32 *)(param_1 + 0x1C) = 0x10; + } + func_8018B714(param_1); + break; + case 2: + if (func_8012BEE8(param_1) != 0) { + func_8012C218((void *)param_1); + } else if (*(s32 *)(param_1 + 0x1C) & 1) { + *(s32 *)(*(s32 *)(param_1 + 0x20) + 4) |= 0x80000000; + } else { + *(s32 *)(*(s32 *)(param_1 + 0x20) + 4) &= 0x7FFFFFFF; + } + break; + } +} -INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018B330); INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018B4D8); @@ -4761,7 +4958,89 @@ void func_8018BC40(s32 param_1) } -INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018BCC4); +typedef struct { s32 a; s32 b[4]; } OtBlk_8018A974_8018EB08_8018BCC4; /* == engine_types.h OtBlk (0x14) */ + +/* func_8018BCC4 -- MATCH (185 ins, relocation-masked). + * + * Three load-bearing spellings, all verified by byte-diff: + * + * (a) `pad_lo[4]` -- the target's var area starts 0x20 BELOW `sv`. Without a + * 32-byte leading local the frame is 0x98 instead of 0xB8 and every + * sp-relative offset is short by 0x20 (134/185 mismatched). gcc-2.7.2 + * still reserves the slot for an unreferenced aggregate, so any 32-byte + * aggregate declared first reproduces the layout. + * + * (b) 4th param declared `u32 col` (a SCALAR whose address is taken), NOT a + * 4-byte struct by value, together with the `arg0->mtx` COMPONENT_REF. + * Both spellings emit identical instructions, but they change gcc-2.7.2's + * alias heuristic in alias.c:true_dependence -- "a varying struct ref does + * not conflict with a fixed scalar ref". With a struct param the 0xC4 home + * slot MEM is MEM_IN_STRUCT_P, so `sw $a3,0xC4($sp)` stays dependent on + * `lw 0x20($s1)` and sched1 cannot sink it (3 mismatched at idx 11-13). + * Scalar-param home slot (not in-struct, non-varying) + struct-member load + * (in-struct, varying) => independent => the store sinks to idx 13. MATCH. + * + * (c) SVec/CVec have alignment 2 / 1, which is what makes the plain struct + * assignments lower to lwl/lwr + swl/swr block moves (cookbook 48-C2). + */ + +extern void func_8004914C(void *a0); +extern void func_800491AC(void *a0); +extern void RotTransSV(void *a0, void *a1, void *a2); +extern void func_8018C090(void *a0); + +typedef struct { s16 vx, vy, vz, pad; } SVec_80186E9C_8018BCC4; /* 8 bytes, align 2 -> lwl/lwr block move */ +typedef struct { u8 r, g, b, cd; } CVec_80186E9C_8018BCC4; /* 4 bytes, align 1 */ +typedef struct { + /* 0x00 */ SVec_80186E9C_8018BCC4 v[4]; + /* 0x20 */ CVec_80186E9C_8018BCC4 col; + /* 0x24 */ u32 code; +} Quad_80186E9C_8018BCC4; + +typedef struct { u8 pad00[0x20]; /* 0x20 */ u8 *mtx; } Ent_80186E9C_8018BCC4; + + +void func_8018BCC4(Ent_80186E9C_8018BCC4 *arg0, s32 arg1, u16 *arg2, u32 col) +{ + + extern SVec_80186E9C_8018BCC4 D_801CD4E0[]; + SVec_80186E9C_8018BCC4 pad_lo[4]; /* unused 32-byte leading local (frame filler) */ + SVec_80186E9C_8018BCC4 sv; + SVec_80186E9C_8018BCC4 out[6]; + Quad_80186E9C_8018BCC4 q; + long flag; + SVec_80186E9C_8018BCC4 *p; + s32 i; + + func_8004914C(arg0->mtx + 0x34); + func_800491AC(arg0->mtx + 0x34); + + p = &D_801CD4E0[(arg1 & 1) * 3]; + + for (i = 0; i < 3; i++) { + sv.vx = p[i].vx; + sv.vy = p[i].vy; + sv.vz = -arg2[0]; + RotTransSV(&sv, &out[i], &flag); + } + for (i = 0; i < 3; i++) { + sv.vx = p[i].vx; + sv.vy = p[i].vy; + sv.vz = -arg2[1]; + RotTransSV(&sv, &out[i + 3], &flag); + } + + q.col = *(CVec_80186E9C_8018BCC4 *)&col; + q.code = 0x50000000; + + q.v[0] = out[0]; q.v[1] = out[1]; q.v[2] = out[3]; q.v[3] = out[4]; + func_8018C090(&q); + q.v[0] = out[1]; q.v[1] = out[2]; q.v[2] = out[4]; q.v[3] = out[5]; + func_8018C090(&q); + q.v[0] = out[2]; q.v[1] = out[0]; q.v[2] = out[5]; q.v[3] = out[3]; + func_8018C090(&q); +} + extern s32 ratan2(s32 a0, s32 a1);