diff --git a/src/ov_SC03_124/ov_SC03_124_jr_80188544.c b/src/ov_SC03_124/ov_SC03_124_jr_80188544.c index 4055d8c924..2c50eaa228 100644 --- a/src/ov_SC03_124/ov_SC03_124_jr_80188544.c +++ b/src/ov_SC03_124/ov_SC03_124_jr_80188544.c @@ -3730,7 +3730,156 @@ s32 func_80189D4C(s32 a0, s16 a1, s16 a2) { } -INCLUDE_ASM("asm/ov_SC03_124/nonmatchings/ov_SC03_124_jr_80188544", func_80189F00); +typedef struct { s16 vx, vy; } DVEC2_C974_8017BA3C_80189F00; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C974_8017BA3C_80189F00; +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_C974_80189F00; + + +/* func_80189F00 -- ov_SC03_107 / ov_SC03_107_jr_801789AC (212 ins) + * + * Decls chosen to agree VERBATIM with the destination TU + * (src/ov_SC03_107/ov_SC03_107_jr_801789AC.c): + * func_8002D4C8 TU:168/3781/5786/5823/6444/8084 `extern void (s32,s32)` (also `(int,int)` @999) + * func_8012B030 TU:357/4991 `extern s32 (u8 *)` + * func_8012CBCC TU:452 `extern void (s32)`, TU:631 `extern void (s32)` + * -> VOID in the TU, so the return value is read through the + * §161c function-pointer cast, never through a re-decl. + * func_80131C78 TU:565 `extern void (s32)` + * func_80143B6C TU:581/1143 `extern s32 (s32,s32)` + * func_800291C8 TU:983 `extern void (s32,s32)` + * func_80189D4C DEFINED at TU:7981 as `s32 func_80189D4C(s32,s16,s16)` -- + * the definition is above this slot, so the decl below agrees. + * D_801E2440 / D_801E2444 are declared nowhere in the TU (free choice). + */ + +extern void func_8002D4C8(s32 a0, s32 a1); +extern s32 func_8012B030(u8 *a0); +extern void func_8012CBCC(s32); +extern void func_80131C78(s32 a0); +extern s32 func_80143B6C(s32 a0, s32 a1); +extern void func_800291C8(s32, s32); +extern s32 func_80189D4C(s32 a0, s16 a1, s16 a2); + + +void func_80189F00(s32 a0) { + + extern s32 D_801E2440; + extern s32 D_801E2444; + /* §162i1 dead-local pad: target frame 0x28 = args 0x10 + vars 0x10 + 4*2 regs; + * the raw draft compiles vars=0. Never read, never &-taken, >=2 elements. */ + s32 pad[4]; + + if (*(s16 *)(a0 + 0xA) >= 0x10) { + func_80131C78(a0); + *(s16 *)(a0 + 0x2) = 2; + *(s32 *)(a0 + 0x1C) = 1; + } + + switch (*(u8 *)(a0 + 0xC2)) { + case 0: + D_801E2440 = ((s32 (*)(s32))func_8012CBCC)(a0); + if (D_801E2440 & 0x6000) { + if (D_801E2440 & 0x1000) { + *(s16 *)(a0 + 0x2) = 2; + *(u8 *)(a0 + 0xC1) = 0; + *(s16 *)(a0 + 0x5E) = 0; + *(s32 *)(a0 + 0x1C) = 0x30; + func_8002D4C8(0x531, 0); + func_800291C8(0xA, *(s16 *)(a0 + 0xFE)); + return; + } + func_80143B6C(a0, 1); + func_8002D4C8(0x754, 0); + *(u8 *)(a0 + 0xC2) = 1; + *(s32 *)(a0 + 0x14) = 0xFFF30000; + *(s32 *)(a0 + 0x1C) = 0; + *(s32 *)(a0 + 0x10) = *(s32 *)(a0 + 0x10) >> 2; + *(s32 *)(a0 + 0x18) = *(s32 *)(a0 + 0x18) >> 2; + } + *(s32 *)(a0 + 0x1C) += 1; + if (*(s32 *)(a0 + 0x1C) >= 0x78) { + func_80131C78(a0); + *(s16 *)(a0 + 0x2) = 2; + *(s32 *)(a0 + 0x1C) = 1; + } + break; + + case 1: + D_801E2444 = *(s32 *)(a0 + 0x14); + D_801E2440 = ((s32 (*)(s32))func_8012CBCC)(a0); + if (D_801E2440 & 0x6000) { + if (D_801E2440 & 0x1000) { + *(s16 *)(a0 + 0x2) = 2; + *(u8 *)(a0 + 0xC1) = 0; + *(s16 *)(a0 + 0x5E) = 0; + *(s32 *)(a0 + 0x1C) = 0x30; + func_8002D4C8(0x531, 0); + func_800291C8(0xA, *(s16 *)(a0 + 0xFE)); + return; + } + { + /* The read of D_801E2444 MUST precede the two pointer stores in the + * source: gcc-2.7.2's scheduler cannot hoist a symbol_ref load above a + * store through a register base (may-alias), so writing it inline in the + * `-D_801E2444` expression leaves the load-delay slot unfilled -> a nop, + * and the function is 1 instruction long. */ + s32 t; + func_8002D4C8(0x754, 0); + func_80143B6C(a0, 1); + t = D_801E2444; + *(u8 *)(a0 + 0xC2) = 2; + *(s32 *)(a0 + 0x1C) = 0; + *(s32 *)(a0 + 0x14) = -t; + } + } + *(s32 *)(a0 + 0x1C) += 1; + if (*(s32 *)(a0 + 0x1C) >= 0x28) { + func_80131C78(a0); + *(s16 *)(a0 + 0x2) = 2; + *(s32 *)(a0 + 0x1C) = 1; + } + break; + + case 2: + *(s32 *)(a0 + 0x10) = *(s32 *)(a0 + 0x10) * 15 / 16; + *(s32 *)(a0 + 0x18) = *(s32 *)(a0 + 0x18) * 15 / 16; + D_801E2440 = ((s32 (*)(s32))func_8012CBCC)(a0); + if (D_801E2440 & 0x6000) { + *(s32 *)(a0 + 0x14) = 0; + if (D_801E2440 & 0x1000) { + *(s16 *)(a0 + 0x2) = 2; + *(u8 *)(a0 + 0xC1) = 0; + *(s16 *)(a0 + 0x5E) = 0; + *(s32 *)(a0 + 0x1C) = 0x30; + func_8002D4C8(0x531, 0); + func_800291C8(0xA, *(s16 *)(a0 + 0xFE)); + return; + } + if (!(*(u16 *)(a0 + 0x84) & 1)) { + *(u16 *)(a0 + 0x84) |= 1; + func_8002D4C8(0x754, 0); + } + if ((*(s32 *)(a0 + 0x1C) & 3) == 3) { + func_80143B6C(a0, 1); + } + *(s32 *)(a0 + 0x1C) += 1; + if (*(s32 *)(a0 + 0x1C) >= 0x11) { + func_80131C78(a0); + func_8012B030((u8 *)a0); + *(s16 *)(a0 + 0x2) = 1; + *(u16 *)(a0 + 0x84) &= 0xFFFE; + } + } + break; + } + + func_80189D4C(a0, -0x28, 1); + *(s16 *)(a0 + 0x108) = *(u16 *)(a0 + 0x108) - 1; + if (*(s16 *)(a0 + 0x108) == 0) { + func_800291C8(0xA, *(s16 *)(a0 + 0xFE)); + } +} + INCLUDE_ASM("asm/ov_SC03_124/nonmatchings/ov_SC03_124_jr_80188544", func_8018A250);