diff --git a/src/ov_SC02_003/ov_SC02_003_jr_8017EA84.c b/src/ov_SC02_003/ov_SC02_003_jr_8017EA84.c index d277785d8..c38c7f525 100644 --- a/src/ov_SC02_003/ov_SC02_003_jr_8017EA84.c +++ b/src/ov_SC02_003/ov_SC02_003_jr_8017EA84.c @@ -3271,6 +3271,143 @@ void func_8017F5E4(s32 param_1) { } -INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017EA84", func_8017F62C); +// @class: jtbl-carve + switch binary-tree +// @stuck: none — remapped from the byte-proven twin ov_SC02_000:func_8017F62C (§193-A); +// the two .s bodies are instruction-identical (only the jtbl rodata block differs in +// extraction). All 16 symbols re-verified against THIS target's own relocation lines. +// jtbl_801E69EC = [F7D0, F830, F904, F858, F8B8]; entry 2 aims at the switch-end label, +// which is ALSO the out-of-range (sltiu 5) target => `case 2: break;` literally and NO +// `default:` clause (cookbook §206.2/§206.3). The 0x70 byte test is the neighbour +// func_8017EA84's own spelling ((s32)((u32)*(u16*)(a0+0x70) << 0x10) >> 0x18). +// `t == 0 || (t >= 3 && t <= 4)` folds to beqz + addiu -3 + sltiu 2 (build_range_check). +// Case 0/case 2 of the first switch are written out identically; gcc cross-jumps their +// tails to .L8017F68C by itself (§206.5). The func_8012C51C request block is spelled as +// a local anonymous struct so no engine_types.h definition can collide. + +extern s32 func_8012D5E4(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_8012F214(s32 a0, s32 a1, s32 a2); +extern s32 func_8012C51C(void *a0, s32 a1); +extern void func_8012B2CC(s32 a0); +extern s32 func_8012B8E4(s32 arg0, s32 arg1); +extern s32 func_8012BCCC(s32 a0); +extern s32 func_8012BEE8(s32 a0); +extern void func_8012A828(s32 a0, void *a1); +extern s32 func_8018A660(s32 a0, s32 a1); + + +void func_8017F62C(s32 a0) +{ + + extern u16 D_8018E66C[]; + extern void (*D_8018E6D4[])(void); + extern u8 D_801A629C; + extern char D_801A6754[]; + extern unsigned char D_801A73BC[]; + struct { + s16 f0, f2, f4, f6, f8, fA, fC, fE; + s32 f10; + } sp; + s16 vec[4]; + s32 t; + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + if (*(s32 *)(a0 + 0x1C) == 7) { + func_8012D5E4(a0, (s32) D_8018E6D4, (s32) &D_8018E6D4[2], 0xB); + } + break; + case 2: + if (*(s32 *)(a0 + 0x1C) == 0xA) { + func_8012D5E4(a0, (s32) D_8018E6D4, (s32) &D_8018E6D4[2], 0xB); + } + break; + case 3: + { + s32 p; + if (*(s32 *)(a0 + 0x1C) >= 0x19) { + s32 r = func_8012B8E4(a0, 4); + p = *(s32 *)(a0 + 0x20); + *(u16 *)(p + 0x12) = *(u16 *)(p + 0x12) + r; + } + if (*(s32 *)(a0 + 0x1C) == 0xC) { + s32 o; + func_8012F214(a0, (s32) D_8018E66C, (s32) &vec[0]); + sp.f6 = 0x20; + sp.f8 = 2; + sp.fA = 0; + sp.f10 = 0; + sp.fE = 0; + sp.f0 = vec[0]; + sp.f2 = vec[1]; + sp.f4 = vec[2]; + sp.fC = *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12); + o = func_8012C51C(&sp, a0); + if (o != 0) { + *(u16 *)(*(s32 *)(o + 0x20) + 0x12) = *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12); + func_8012B2CC(o); + } + } else if (*(s32 *)(a0 + 0x1C) == 0xF) { + func_8018A660(a0, (s32) D_8018E66C); + } + break; + } + } + + if (func_8012BEE8(a0) != 0) { + switch (*(u16 *)(a0 + 0x34)) { + case 0: + t = (s32) ((u32) *(u16 *)(a0 + 0x70) << 0x10) >> 0x18; + if (t == 0 || (t >= 3 && t <= 4)) { + if (func_8012BCCC(a0) <= 0x4000) { + *(u16 *)(a0 + 2) = 2; + *(u16 *)(a0 + 0x34) = 1; + func_8012A828(a0, &D_801A629C); + *(s32 *)(a0 + 0x1C) = 0xA; + return; + } + } + break; + case 1: + *(u16 *)(a0 + 2) = 2; + *(u16 *)(a0 + 0x34) = 2; + func_8012A828(a0, &D_801A6754); + *(s32 *)(a0 + 0x1C) = 0x18; + return; + case 2: + break; + case 3: + if (++*(u8 *)(a0 + 0x102) >= 3) { + *(u8 *)(a0 + 0x102) = 0; + *(u16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + func_8012A828(a0, &D_801A73BC); + } else { + *(u16 *)(a0 + 2) = 2; + *(u16 *)(a0 + 0x34) = 3; + func_8012A828(a0, &D_801A72C4); + } + *(s32 *)(a0 + 0x1C) = 0x1E; + return; + case 4: + if (func_8012BEE8(a0) != 0) { + if (func_8012BCCC(a0) <= 0x40000) { + *(u16 *)(a0 + 2) = 2; + *(u16 *)(a0 + 0x34) = 3; + func_8012A828(a0, &D_801A72C4); + *(s32 *)(a0 + 0x1C) = 0x1E; + } + } + break; + } + + *(u16 *)(a0 + 0x5C) = 0xAA10; + *(u16 *)(a0 + 2) = 1; + *(u16 *)(a0 + 0x34) = 2; + *(u16 *)(a0 + 0x5E) = 0; + *(s32 *)(a0 + 0x1C) = 0x1E; + func_8012A828(a0, &D_801A6534); + *(u16 *)(a0 + 0xFC) = 0; + } +} + INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017EA84", func_8017F950); diff --git a/src/ov_SC03_007/ov_SC03_007_jr_8017AE2C.c b/src/ov_SC03_007/ov_SC03_007_jr_8017AE2C.c index f19b82ae1..46ebce6b5 100644 --- a/src/ov_SC03_007/ov_SC03_007_jr_8017AE2C.c +++ b/src/ov_SC03_007/ov_SC03_007_jr_8017AE2C.c @@ -6871,7 +6871,95 @@ void func_80180F4C(s32 a0) { } -INCLUDE_ASM("asm/ov_SC03_007/nonmatchings/ov_SC03_007_jr_8017AE2C", func_801810E4); +#include "common.h" + +extern void func_8012B1B4(s32 a0, s32 a1); +extern s32 func_8012CBCC(s32 a0); +extern s32 func_8012B744(void *a0, void *a1); +extern s32 func_8012B608(s32 a0, s32 a1, s32 a2); +extern void func_8012A828(s32 a0, void *a1); +extern s32 func_800291B4(s32 arg); +extern void func_800291A0(s32, s32); +extern u8 D_8018C03C[]; +extern u16 D_8018C054[]; +extern u16 D_8018C05C[]; +extern u16 D_8018C064[]; +extern u16 D_8018C06C[]; +extern u8 D_801B0DD4[]; +extern u8 D_801B101C[]; +extern s16 D_80126CB4; +extern s16 D_80126CB6; +extern s16 D_80126CB8; + +void func_801810E4(s32 a0) { + s32 s0; + s32 v0; + s32 v1; + s32 dx; + s32 dz; + s32 ret; + struct { s16 vx, vy, vz, pad; } vec; + + s0 = a0; + func_8012B1B4(s0, (s32)D_8018C03C); + v1 = func_8012CBCC(s0); + if (v1 & 0x6000) { + *(s16 *)(s0 + 0x16) = -4; + } + if (v1 & 0x8000) { + v0 = (*(u16 *)(s0 + 0x104) + 1) & 0x3F; + *(u16 *)(s0 + 0x104) = v0; + if (v0 < 0x1F) { + *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12) = *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12) + 0x200; + } else { + *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12) = *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12) - 0x200; + } + } + + if (*(s16 *)(s0 + 0xFC)) { + vec.vx = D_8018C064[*(u8 *)(s0 + 0xFE)] + *(u16 *)(s0 + 0xDC); + vec.vy = 0; + vec.vz = D_8018C06C[*(u8 *)(s0 + 0xFE)] + *(u16 *)(s0 + 0xDE); + } else { + vec.vx = D_8018C054[*(u8 *)(s0 + 0xFE)] + *(u16 *)(s0 + 0xDC); + vec.vy = 0; + vec.vz = D_8018C05C[*(u8 *)(s0 + 0xFE)] + *(u16 *)(s0 + 0xDE); + } + + ret = func_8012B744((void *)(s0 + 4), &vec); + ret = func_8012B608(*(s16 *)(*(s32 *)(s0 + 0x20) + 0x12), ret, 4); + *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12) = *(u16 *)(*(s32 *)(s0 + 0x20) + 0x12) + ret; + + dx = *(s16 *)(s0 + 6) - vec.vx; + dz = *(s16 *)(s0 + 0xE) - vec.vz; + if (dx * dx + dz * dz < 0x400) { + if (*(s16 *)(s0 + 0xFC) != 0) { + if (*(u8 *)(s0 + 0xFF) != 0) { + *(s16 *)(s0 + 2) = 4; + func_8012A828(s0, D_801B0DD4); + *(s32 *)(s0 + 0x1C) = 0xF; + switch (func_800291B4(0xCC) & 0xFF) { + case 2: func_800291A0(0xCC, 3); break; + case 4: func_800291A0(0xCC, 5); break; + case 6: func_800291A0(0xCC, 7); break; + case 8: func_800291A0(0xCC, 9); break; + case 10: func_800291A0(0xCC, 0xB); break; + case 12: func_800291A0(0xCC, 0xD); break; + } + } else { + *(s16 *)(s0 + 2) = 1; + func_8012A828(s0, D_801B101C); + } + } else { + *(s16 *)(s0 + 0xFC) = *(s16 *)(s0 + 0xFC) + 1; + } + } + + D_80126CB4 = *(u16 *)(s0 + 6); + D_80126CB6 = *(u16 *)(s0 + 0xA); + D_80126CB8 = *(u16 *)(s0 + 0xE); +} + #include "common.h" diff --git a/src/ov_SC03_007/ov_SC03_007_jr_80183894.c b/src/ov_SC03_007/ov_SC03_007_jr_80183894.c index be5519172..243654368 100644 --- a/src/ov_SC03_007/ov_SC03_007_jr_80183894.c +++ b/src/ov_SC03_007/ov_SC03_007_jr_80183894.c @@ -3956,7 +3956,171 @@ void func_801848BC(s32 a0) { } -INCLUDE_ASM("asm/ov_SC03_007/nonmatchings/ov_SC03_007_jr_80183894", func_80184AFC); +#include "common.h" + +extern void func_8012A828(s32 a0, void * a1); +extern s32 func_80146A6C(s32 a0, void *a1, s32 a2, s32 a3, s32 a4, s32 a5, s32 a6); +extern void func_801858D4(s32 a0, s16 a1, s16 a2); +extern void func_80185948(s16 *a0); +extern s32 func_8012BB3C(s32 arg0, s32 arg1, u32 arg2, s32 arg3); +extern s32 func_80185DD8(void); +extern s32 func_8012BC60(void *a0, void *a1); +extern s32 func_8012B864(s32 a0); +extern s32 func_8012BD14(s32 a0); +extern void func_8012B200(u8 *a0); +extern void func_80185B48(s32 a0); +extern s32 func_8012BDBC(s32 a0, s32 a1); +extern s32 func_80185A24(s32 a0); +extern unsigned char D_8018C750[]; +extern void (*D_8018C588[])(void); +extern void (*D_8018C610[])(void); +extern s32 D_801EB14C; + +/* + * Three load-bearing details (byte-proven, single-axis A/B, pinned triple): + * + * 1. `s32 dead[4];` -- cookbook §162i1/§164-53 dead BLKmode local reserving the + * target's vars area (frame 0x48). Same device as func_80184E8C above. + * + * 2. `fire = ret + zr;` with `register s32 zr __asm__("$0");` -- cookbook RC-12's + * pin-free zero-register add. The target keeps a REAL `addu $v0,$s2,$zero` + * copy of the flag at the join before `beqz $v0` (reorg then steals it into the + * two `bnez`/`beqz` delay slots that branch there, so it is worth +2 ins and + * shifts every branch offset in the tail). A plain `if (ret != 0)` -- and a + * plain `fire = ret;` temp -- both lose the copy to cse's canon_reg: 226 ins, + * LENGTH-DRIFT/-2, closeness 69. The `+ zr` add is a real RTL insn cse cannot + * fold away. Pinning `ret` itself to `$18` instead REGRESSES (closeness 77). + * + * 3. `ang = -0xE - spd;` hoisted ABOVE the `*(s16 *)(a0 + 0x104) == 0` guard -- + * that source position is what makes gcc emit `addiu $v0,$zero,-0xE` early, + * fill the guard's delay slot with `subu $a1,$v0,$s1`, and re-home the + * func_8012B864 result into $a0 (`addu $a0,$v0,$zero`). Computing it inline at + * the call site instead: OPCODE-MIXED, closeness 12. + * Note the two constants really are different: the 0x12 store takes t - 0x800, + * the func_801858D4 argument takes -0xE - spd. + */ +void func_80184AFC(s32 a0) { + s32 dead[4]; + s32 ret; + s32 v; + s32 spd; + s32 t; + s16 rc; + register s32 zr __asm__("$0"); + s32 fire; + + ret = 0; + if ((*(u16 *)(a0 + 0x5C) & 0x200) != 0) { + if ((s16)func_80185DD8() != 0) { + *(u16 *)(a0 + 0x5C) = *(u16 *)(a0 + 0x5C) & 0xFDFF; + } + } + + func_80185A24(a0); + + v = *(s32 *)(a0 + 0x1C) - 1; + *(s32 *)(a0 + 0x1C) = v; + if (v != 0) { + if ((v & 3) == 0) { + if (func_8012BC60((void *)(a0 + 4), (void *)&D_801EB14C) < 0x900) { + *(s32 *)(a0 + 0x1C) = 1; + } + } + if (*(s16 *)(a0 + 0x106) == 0) { + s32 r; + s32 p; + s32 ang; + r = func_8012BB3C(a0 + 4, (s32)&D_801EB14C, + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12), 8); + p = *(s32 *)(a0 + 0x20); + *(u16 *)(p + 0x12) = *(u16 *)(p + 0x12) + r; + ang = -6 - *(u16 *)(a0 + 0x104); + func_801858D4(a0, (s16)ang, 0); + } + if (*(s16 *)(a0 + 0x104) != 0) { + if (*(s32 *)(a0 + 0x90) == (s32)&D_8018C610 && + (u32)*(s32 *)(a0 + 0x94) < 0xB) { + *(s32 *)(a0 + 0x94) = *(s32 *)(a0 + 0x94) + 1; + } + if ((*(s32 *)(a0 + 0x1C) & 3) == 0) { + ret = 1; + } + } + } else { + s16 u; + func_8012B200((u8 *)a0); + func_8012A828(a0, (void *)&D_8018C588); + *(s32 *)(a0 + 0x1C) = 0x14 - (*(s16 *)(a0 + 0x104) << 1); + if (func_8012BD14(a0) <= 0x23FFF) { + *(s16 *)(a0 + 0x102) = 0xA - *(u16 *)(a0 + 0x104); + } else { + *(s16 *)(a0 + 0x102) = 0; + } + u = *(s16 *)(a0 + 0x104); + if (u != 0) { + u = u - 4; + *(s16 *)(a0 + 0x104) = u; + if (u < 0) { + *(s16 *)(a0 + 0x104) = 0; + } + } + *(s16 *)(a0 + 2) = 3; + } + + rc = (s16)((s32 (*)(s32))func_80185B48)(a0); + if (rc != 0) { + if (rc < 0) { + return; + } + if (*(s16 *)(a0 + 0xFE) == 0) { + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = -*(u16 *)(a0 + 0x62); + func_801858D4(a0, -0x1E, 0); + func_80185948((s16 *)a0); + *(s16 *)(a0 + 0x104) = 0xA; + ret = 1; + } else { + *(u16 *)(a0 + 0x5C) = *(u16 *)(a0 + 0x5C) & 0xFDFF; + func_8012B200((u8 *)a0); + func_8012A828(a0, (void *)D_8018C750); + *(s32 *)(a0 + 0x1C) = 0x10; + *(s16 *)(a0 + 2) = 0xA; + return; + } + } else { + s32 d = func_8012BD14(a0); + if (d < 0x10000) { + spd = 0; + if (d >= 0x6400) { + spd = (func_8012BDBC(a0, 0x500) != 0) << 2; + } else if (d >= 0x2400) { + if (func_8012BDBC(a0, 0x680) != 0) { + spd = 7; + } + } else { + spd = 0xA; + } + if (spd != 0) { + s32 ang; + func_80185948((s16 *)a0); + t = func_8012B864(a0); + ang = -0xE - spd; + if (*(s16 *)(a0 + 0x104) == 0) { + ret = 1; + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = t - 0x800; + } + *(s16 *)(a0 + 0x104) = spd; + func_801858D4(a0, ang, 0); + } + } + } + + fire = ret + zr; + if (fire != 0) { + func_80146A6C(2, (void *)a0, 0, 0, 0, 3, + ((*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) + 0x800) & 0xFFF) | 0x30009000); + } +} + #include "common.h" diff --git a/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c b/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c index b64e19199..cb49a862f 100644 --- a/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c +++ b/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c @@ -4247,7 +4247,110 @@ void func_8017F234(s32 a0) { } -INCLUDE_ASM("asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_8017C8D0", func_8017F55C); +#include "common.h" + +extern s32 rand(void); +extern s32 func_8012BEE8(s32 a0); +extern s32 func_8012CBF4(s32 a0); +extern void func_8012AD80(s32 a0); +extern void func_8012C218(void *a0); +extern void func_8012B260(u8 *a0); +extern void func_8012E88C(u8 *a0); +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_80047948(s32 a0); +extern s32 func_8017FA90(s32 a0, s16 a1, s32 a2); +extern void func_8017FAE8(void *a0); + +typedef struct { u16 vx, vy, vz, pad; } UVEC_8017F55C; + +void func_8017F55C(s32 a0) { + s32 m1[8]; + UVEC_8017F55C in; + UVEC_8017F55C out; + s32 flags; + s32 t; + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + if (func_8012BEE8(a0) != 0) { + func_8012EC04(*(s32 *)(a0 + 0x64), 0, (s32 *)m1); + in.vx = *(u16 *)(a0 + 0x6); + in.vy = *(u16 *)(a0 + 0xA); + in.vz = *(u16 *)(a0 + 0xE); + func_8012F14C((s32)m1, (s32)&in, (s32)&out); + *(s16 *)(a0 + 0x6) = out.vx; + *(s16 *)(a0 + 0xA) = out.vy; + *(s16 *)(a0 + 0xE) = out.vz; + func_8012B260((u8 *)a0); + func_8012E88C((u8 *)a0); + *(s32 *)(a0 + 0x1C) = 0x80; + *(u16 *)(a0 + 0x34) += 1; + } + break; + case 1: + if (*(s16 *)(a0 + 0x70) & 0x8000) { + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x10) += *(u16 *)(a0 + 0xFC); + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) += *(u16 *)(a0 + 0xFE); + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x14) += *(u16 *)(a0 + 0x100); + } + flags = func_8012CBF4(a0); + if ((flags & 0xFF) == 0x19) { + *(s32 *)(a0 + 0x1C) = 8; + *(u16 *)(a0 + 0x34) += 1; + func_8017FA90(a0, (rand() % 3 + 3) << 12, 0xFFFA0000); + func_8017FAE8((void *)a0); + } else if (flags & 0x2000) { + *(s32 *)(a0 + 0x14) = 0xFFF80000; + *(u16 *)(a0 + 0x34) = 4; + *(s32 *)(a0 + 0x1C) = 0x20; + } else { + if (func_8012BEE8(a0) != 0) { + func_8012C218((void *)a0); + } + } + break; + case 2: + t = func_80047948((*(s32 *)(a0 + 0x1C) << 7) & 0x380); + *(s16 *)(a0 + 0x52) = -((t << 3) >> 12); + if (func_8012BEE8(a0) != 0) { + *(s32 *)(a0 + 0x1C) = 0x18; + *(s32 *)(a0 + 0x48) = 0x2000; + *(s32 *)(a0 + 0x10) = 0; + *(s32 *)(a0 + 0x14) = 0; + *(s32 *)(a0 + 0x18) = 0; + *(u16 *)(a0 + 0x34) += 1; + } + break; + case 3: + func_8012AD80(a0); + if (func_8012BEE8(a0) != 0) { + func_8012C218((void *)a0); + } + break; + case 4: + if (*(s16 *)(a0 + 0x70) & 0x8000) { + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x10) += *(u16 *)(a0 + 0xFC); + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) += *(u16 *)(a0 + 0xFE); + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x14) += *(u16 *)(a0 + 0x100); + } + flags = func_8012CBF4(a0); + if ((flags & 0xFF) == 0x19) { + *(s32 *)(a0 + 0x1C) = 8; + *(u16 *)(a0 + 0x34) = 2; + func_8017FA90(a0, (rand() % 3 + 3) << 12, 0xFFFC0000); + func_8017FAE8((void *)a0); + } else if (flags & 0x2000) { + func_8012C218((void *)a0); + } else { + if (func_8012BEE8(a0) != 0) { + func_8012C218((void *)a0); + } + } + break; + } +} + void func_8017F864(void) { } @@ -4892,7 +4995,7 @@ INCLUDE_ASM("asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_8017C8D0", func_80182DC extern u16 D_801BA628; extern u16 D_801BA62A; extern u16 D_801BA62C; -extern void func_801831E0(s32 a0); +extern void func_801831E0(); void func_80183174(s32 a0) { u16 *p = &D_801BA628; @@ -4911,7 +5014,94 @@ void func_80183174(s32 a0) { } -INCLUDE_ASM("asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_8017C8D0", func_801831E0); +#include "common.h" + +extern s32 rand(void); +extern s32 func_801850D8(); + +void func_801831E0(s32 arg0, s32 arg1) { + + extern u16 D_801BA6A0[]; + extern u16 D_801BA5E8; + extern u16 D_801BA5EA; + extern u16 D_801BA5EC; + extern s32 D_8018E59C[]; + u16 *w; + u16 *e; + u16 *m; + s32 ctr; + s32 q; + s32 ret; + s32 t; + + w = D_801BA6A0; + switch (arg1) { + case 0: + ctr = 0x17; + do { + w[0] = *(u16 *)(arg0 + 6); + w[1] = *(u16 *)(arg0 + 0xA); + w[2] = *(u16 *)(arg0 + 0xE); + ctr--; + w -= 4; + } while (ctr >= 0); + break; + case 1: + case 3: + D_801BA5E8 = *(u16 *)(arg0 + 6); + D_801BA5EA = *(u16 *)(arg0 + 0xA); + D_801BA5EC = *(u16 *)(arg0 + 0xE); + ctr = 0x17; + do { + m = w + 1; + e = w + 2; + *w = *(w - 4); + *m = *(w - 3); + *e = *(w - 2); + if ((D_800B99DA & 7) == 0 && (ctr & 1) != 0) { + q = rand() % 4096; + if ((rand() & 1) == 0) { + t = -q; + q = t + 0x4000; + } else { + q = q + 0x4000; + } + ret = func_801850D8(5, (s16)q, 0, 0, w, 0, *(s32 *)(((rand() & 1) << 2) + (s32)D_8018E59C), 0); + if (ret != 0) { + *(s32 *)(ret + 0x54) = arg1 - 1; + *(s32 *)(ret + 0x50) = (s32)w; + *(s32 *)(ret + 0x20) |= 0x200000; + } + } + ctr--; + w -= 4; + } while (ctr > 0); + break; + case 2: + ctr = 0x17; + do { + if ((D_800B99DA & 7) == 0 && (ctr & 1) != 0) { + q = rand() % 4096; + if ((rand() & 1) == 0) { + t = -q; + q = t + 0x4000; + } else { + q = q + 0x4000; + } + ret = func_801850D8(5, (s16)q, 0, 0, w, 0, D_8018E59C[rand() & 1], 0); + if (ret != 0) { + *(s32 *)(ret + 0x50) = (s32)w; + *(s32 *)(ret + 0x54) = arg1; + *(s32 *)(ret + 0x20) |= 0x200000; + } + } + ctr--; + w -= 4; + } while (ctr > 0); + break; + } +} + INCLUDE_ASM("asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_8017C8D0", func_801834A4); diff --git a/src/ov_SC03_105/ov_SC03_105_jr_80186B24.c b/src/ov_SC03_105/ov_SC03_105_jr_80186B24.c index c3dea183e..0c5e1130b 100644 --- a/src/ov_SC03_105/ov_SC03_105_jr_80186B24.c +++ b/src/ov_SC03_105/ov_SC03_105_jr_80186B24.c @@ -2895,7 +2895,7 @@ extern s32 func_8018233C(s32 arg0); extern u16 D_801BA628; extern u16 D_801BA62A; extern u16 D_801BA62C; -extern void func_801831E0(s32 a0); +extern void func_801831E0(); extern void func_80183174(s32 a0); extern s32 func_801850D8(); extern u8 D_8018E47C[]; diff --git a/src/ov_SC03_110/ov_SC03_110_jr_8017FBC8.c b/src/ov_SC03_110/ov_SC03_110_jr_8017FBC8.c index d1fdd961b..ddd30499b 100644 --- a/src/ov_SC03_110/ov_SC03_110_jr_8017FBC8.c +++ b/src/ov_SC03_110/ov_SC03_110_jr_8017FBC8.c @@ -3093,7 +3093,147 @@ void func_80180270(s32 param_1) { } -INCLUDE_ASM("asm/ov_SC03_110/nonmatchings/ov_SC03_110_jr_8017FBC8", func_8018035C); +/* func_8018035C — ov_SC03_110 / ov_SC03_110_jr_8017FBC8 + * 196 ins + a 5-entry compiler jump table (jtbl_801A0D90). + * Body is byte-correct in isolation AND in its real TU (rtu probe: MATCH 196/196). + * The 5 emitted .rodata words resolve to 801803BC/80180460/8018052C/80180588/801805AC, + * i.e. exactly the target's jtbl_801A0D90 entries; the surplus 6th word spimdisasm ran + * into that dlabel is not ours (§131 — the `sltiu 5` is ground truth; the planner clamps it). + * REMAINING BLOCKER IS THE CARVE, NOT THE C: jtbl_801A0D90 is still raw asm in + * asm/ov_SC03_110/data/tail18.data.s, so this needs the gate-time §8a tail carve + * (jtbl_carve --probe verdict: "tail — standard §8a carve at gate time", NOT plan-refused). + * House style per the TU neighbour func_8018076C: block-scope externs + the cast call sites. */ +void func_8018035C(s32 param_1) +{ + extern void func_80180C40(s32); + extern s32 func_8012CC64(s32 a0, void *a1); + extern s32 func_8012CC1C(s32 a0, void *a1); + extern void func_8012B23C(s32 a0); + extern void func_80131C78(s32 a0); + extern s32 func_80143B6C(s32 a0, s32 a1); + extern void func_80131E00(s32 a0, s32 a1); + extern void func_80180D2C(); + extern s32 D_8019C004; + + s32 iVar1; + + if (*(s16 *)(param_1 + 0xa) >= 0x10) { + ((void (*)(void *))func_80180C40)((void *)param_1); + return; + } + + switch (*(u16 *)(param_1 + 0x34)) { + case 0: + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x10) -= 0x100; + iVar1 = func_8012CC64(param_1, &D_8019C004); + if ((iVar1 & 0xff) == 0x1a) { + goto EXIT_80658; + } + if ((iVar1 & 0x2000) != 0) { + *(u16 *)(param_1 + 0x34) += 1; + *(s32 *)(param_1 + 0x1c) = 0; + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x10) = 0; + goto TAIL; + } + if ((iVar1 & 0x4000) == 0) { + goto L_B0; + } + *(u16 *)(param_1 + 0x34) = 4; + *(s32 *)(param_1 + 0x1c) = 0; + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x10) = 0; + func_8012B23C(param_1); + goto TAIL; + + L_B0: + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) < 0x3c) { + goto TAIL; + } + *(u16 *)(param_1 + 0x34) = 2; + goto TAIL; + + case 1: + *(s32 *)(param_1 + 0x10) = *(s32 *)(param_1 + 0x10) * 15 / 16; + *(s32 *)(param_1 + 0x18) = *(s32 *)(param_1 + 0x18) * 15 / 16; + iVar1 = func_8012CC1C(param_1, &D_8019C004); + if ((iVar1 & 0xff) == 0x1a) { + goto EXIT_80658; + } + if ((iVar1 & 0x6000) != 0) { + goto L_160; + } + *(s32 *)(param_1 + 0x1c) = 0; + *(u16 *)(param_1 + 0x34) += 1; + func_8012B23C(param_1); + goto TAIL; + + L_160: + if ((*(s32 *)(param_1 + 0x1c) & 3) == 0) { + func_80143B6C(param_1, 1); + } + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) < 0x10) { + goto TAIL; + } + goto L_25C; + + case 2: + iVar1 = func_8012CC64(param_1, &D_8019C004); + if ((iVar1 & 0x2000) != 0) { + func_80143B6C(param_1, 1); + goto L_25C; + } + if ((iVar1 & 0x4000) == 0) { + goto L_288; + } + *(u16 *)(param_1 + 0x34) = 4; + func_80143B6C(param_1, 1); + func_8012B23C(param_1); + goto TAIL; + + case 3: + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) >= 0x10) { + goto L_25C; + } + goto TAIL; + + case 4: + iVar1 = func_8012CC1C(param_1, &D_8019C004); + if ((iVar1 & 0xff) != 0x1a) { + goto L_254; + } + EXIT_80658: + ((void (*)(void *))func_80180C40)((void *)param_1); + return; + L_254: + if ((iVar1 & 0x2000) == 0) { + goto L_26C; + } + goto L_25C; + + L_25C: + func_80131C78(param_1); + goto TAIL; + + L_26C: + if ((*(s32 *)(param_1 + 0x1c) & 3) == 0) { + func_80143B6C(param_1, 1); + } + L_288: + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) < 0x3c) { + goto TAIL; + } + func_80131E00(param_1, 0xd); + } +TAIL: + ((s32 (*)(s32))func_80180D2C)(param_1); + if (0x100000 < *(s32 *)(param_1 + 0x14)) { + *(s32 *)(param_1 + 0x14) = 0x100000; + } +} + extern s32 D_8019BFAC; extern void func_80180D2C(); diff --git a/src/ov_SC03_121/ov_SC03_121_jr_8017BEBC.c b/src/ov_SC03_121/ov_SC03_121_jr_8017BEBC.c index b9112f9fa..baec43dc1 100644 --- a/src/ov_SC03_121/ov_SC03_121_jr_8017BEBC.c +++ b/src/ov_SC03_121/ov_SC03_121_jr_8017BEBC.c @@ -3669,7 +3669,173 @@ u32 func_8017D788(s32 arg0, s16 arg1, s16 arg2) { } -INCLUDE_ASM("asm/ov_SC03_121/nonmatchings/ov_SC03_121_jr_8017BEBC", func_8017D8D4); +/* func_8017D8D4 -- ov_SC03_121, TU ov_SC03_121_jr_8017BEBC.c. MATCH (212 ins) + * + * Per-frame state machine for an entity: a 5-arm `switch` on the u8 substate at + * +0xC2, dispatched through jtbl_801AD92C (`sltiu $v0,$v1,5` == the entry count, + * §206). Arms 0/1 fall through; arms 1 and 2 end in a byte-identical + * `if (D_801AECD0 & 0x8000)` tail that the source DUPLICATES and gcc's cross_jump + * merges back down to .L8017DAD8 (§298/§5a) -- writing it once with a `goto` + * is unnecessary, the duplicate reproduces the `j .L8017DAD8` exactly. + * + * a0 (bound to s0) : entity pointer. + * +0x02 : s16 state code +0x34 : s16 timer + * +0x06 : s16 pos X +0x3A : s16 home/anchor X + * +0x0A : s16 pos Y +0x3E : s16 home/anchor Y + * +0x0E : s16 pos Z +0x42 : s16 home/anchor Z + * +0x08 : s32 spawn/init flag +0xC2 : u8 substate (switch selector) + * +0x10 : s32 velocity X +0x10A : s16 flag cleared on init + * +0x14 : s32 velocity Y +0x18 : s32 velocity Z + * +0x1C : s32 arm-4 frame counter +0x20 : s32* sub-object (+0x12 = u16 angle) + * + * THREE things the .s forced that the Ghidra seed got wrong: + * + * 1. FRAME SIZE (6 of the 13 first-pass residuals). The target frame is 0x38: + * 16 outgoing-arg bytes + 32 bytes of locals + s0/ra. Three SVECTORs at + * sp+0x10 / +0x18 / +0x20 only account for 24, so a FOURTH 8-byte aggregate + * is declared last (sv3) and never referenced -- gcc-2.7.2 gives every + * aggregate local a frame slot whether or not it is used, and MIPS allocates + * them in declaration order upward from STARTING_FRAME_OFFSET, so a trailing + * dead vector is the only thing that lands 8 unused bytes at sp+0x28. + * + * 2. THE lwl/lwr + swl/swr BLOCK IS A PLAIN STRUCT ASSIGNMENT. `sv2 = sv1` on + * an SVECTOR (4x s16 => size 8, ALIGN 2) cannot use lw/sw, so gcc expands the + * inline unaligned move. Ghidra rendered it as hand-written byte arithmetic + * on `auStack_16 + 1`; that whole block is one `=`. + * + * 3. STATEMENT ORDER IN ARM 0 (the last 7 residuals, one contiguous window with + * an identical multiset == pure sched1, cookbook symptom index L29). + * `*(u8 *)(s0 + 0xC2) = 1;` must come FIRST, before the three vector loads -- + * the seed put it between vx and vy, which costs 7. Brute-forcing the four + * legal positions of that one statement through match_one found it in 4 runs. + * + * Decls (law 2): func_8012A828 is copied verbatim from this TU (lines 3675/3808) + * and D_8018D8AC from line 3688 (`extern s32`, addressed as `(s32)&D_8018D8AC`, + * exactly as line 3703 does). The rest are absent from this TU above the splice + * point, so the fleet-consensus spelling is used; where the consensus return type + * is `void` but the .s consumes $v0 (func_8012CC64, func_8012CBF4), the value is + * read through the established cast-the-pointer idiom rather than by contradicting + * the fleet prototype. func_8012B23C is called with NO argument: the .s sets up + * no $a0 for it (no `move $a0,$s0` anywhere before that jal, unlike every other + * call here), so an unspecified-parameter-list decl is required -- §SYS law 4. + * D_801AECD0 has no fleet spelling at all; typed raw from its sw/lw width. + * SVECTOR is typedef'd locally with engine_types.h's exact body so the draft + * compiles standalone; harvest_verify strips it on splice (the TU provides it). + */ + +#include "common.h" + + + +extern void func_8012B23C(); +extern s32 func_8012DBD0(s32 a0, s32 a1, s32 a2, s32 a3); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); +extern void func_8012CC64(s32 a0, s32 a1); +extern s32 func_80143B6C(s32 a0, s32 a1); +extern void func_8012CBF4(s32 a0); +extern void func_80131C78(s32 a0); +extern void func_8012A828(s32 a0, s32 a1); + +extern s32 D_801AECD0; +extern s32 D_8018D8AC; + +void func_8017D8D4(s32 a0) { + s32 s0; + SVECTOR sv0; + SVECTOR sv1; + SVECTOR sv2; + SVECTOR sv3; + s32 iVar1; + + s0 = a0; + if (*(s32 *)(s0 + 0x8) > 0) { + *(s16 *)(s0 + 0x6) = -0x103; + *(s16 *)(s0 + 0xA) = -0x182; + *(s16 *)(s0 + 0xE) = 0xE8; + *(s16 *)(s0 + 0x2) = 6; + *(s16 *)(s0 + 0x34) = 0; + *(s16 *)(s0 + 0x10A) = 0; + func_8012B23C(); + } + + sv0.vx = 0; + sv0.vy = 0x30; + sv0.vz = 0; + + func_8012DBD0(s0, 0xA, *(s16 *)(*(s32 *)(s0 + 0x20) + 0x12) + 0x800, 0x1D); + + switch (*(u8 *)(s0 + 0xC2)) { + case 0: + *(u8 *)(s0 + 0xC2) = 1; + sv1.vx = *(s16 *)(s0 + 0x3A); + sv1.vy = *(s16 *)(s0 + 0x3E); + sv1.vz = *(s16 *)(s0 + 0x42); + sv2 = sv1; + sv2.vx += sv0.vx; + sv2.vy += sv0.vy; + sv2.vz += sv0.vz; + func_8012CEB0((s32)&sv1, (s32)&sv2, 1); + sv2.vx -= sv0.vx; + sv2.vy -= sv0.vy; + sv2.vz -= sv0.vz; + *(s16 *)(s0 + 0x3A) = sv2.vx; + *(s16 *)(s0 + 0x3E) = sv2.vy; + *(s16 *)(s0 + 0x42) = sv2.vz; + *(s16 *)(s0 + 0x6) = sv2.vx; + *(s16 *)(s0 + 0xA) = sv2.vy; + *(s16 *)(s0 + 0xE) = sv2.vz; + /* fallthrough */ + case 1: + D_801AECD0 = ((s32 (*)(s32, SVECTOR *))func_8012CC64)(s0, &sv0); + if ((D_801AECD0 & 0x2000) != 0) { + *(u8 *)(s0 + 0xC2) = 2; + func_80143B6C(s0, 1); + *(s32 *)(s0 + 0x14) = 0xFFF30000; + } + if ((D_801AECD0 & 0x8000) != 0) { + *(u8 *)(s0 + 0xC2) = 3; + func_8012A828(s0, (s32)&D_8018D8AC); + } + break; + case 2: + D_801AECD0 = ((s32 (*)(s32, SVECTOR *))func_8012CC64)(s0, &sv0); + if ((D_801AECD0 & 0x2000) != 0) { + func_80143B6C(s0, 1); + *(s32 *)(s0 + 0x14) = 0xFFF60000; + *(u8 *)(s0 + 0xC2) = 3; + } + if ((D_801AECD0 & 0x8000) != 0) { + *(u8 *)(s0 + 0xC2) = 3; + func_8012A828(s0, (s32)&D_8018D8AC); + } + break; + case 3: + *(s32 *)(s0 + 0x10) = *(s32 *)(s0 + 0x10) * 0xF / 0x10; + *(s32 *)(s0 + 0x18) = *(s32 *)(s0 + 0x18) * 0xF / 0x10; + D_801AECD0 = ((s32 (*)(s32))func_8012CBF4)(s0); + if ((D_801AECD0 & 0x2000) != 0) { + *(u8 *)(s0 + 0xC2) = 4; + *(s32 *)(s0 + 0x14) = 0; + *(s32 *)(s0 + 0x1C) = 0; + func_80143B6C(s0, 1); + } + break; + case 4: + *(s32 *)(s0 + 0x10) = *(s32 *)(s0 + 0x10) * 0xF / 0x10; + *(s32 *)(s0 + 0x18) = *(s32 *)(s0 + 0x18) * 0xF / 0x10; + func_8012CBF4(s0); + if ((*(s32 *)(s0 + 0x1C) & 3) == 3) { + func_80143B6C(s0, 1); + } + iVar1 = *(s32 *)(s0 + 0x1C) + 1; + *(s32 *)(s0 + 0x1C) = iVar1; + if (iVar1 > 0x10) { + func_80131C78(s0); + } + break; + } +} + extern void func_8012CBCC(s32 a0); extern void func_8012A828(s32 a0, s32 a1); diff --git a/src/ov_SC03_121/ov_SC03_121_jr_8017E1D0.c b/src/ov_SC03_121/ov_SC03_121_jr_8017E1D0.c index cf7648afa..8a4a8e569 100644 --- a/src/ov_SC03_121/ov_SC03_121_jr_8017E1D0.c +++ b/src/ov_SC03_121/ov_SC03_121_jr_8017E1D0.c @@ -4168,7 +4168,113 @@ void func_80180B1C(s32 a0) { } -INCLUDE_ASM("asm/ov_SC03_121/nonmatchings/ov_SC03_121_jr_8017E1D0", func_80180E64); +/* ---- decls copied verbatim from the destination TU (wave law 2) ---------- */ +extern u8 D_80078E78[]; /* TU line 390 */ +extern s32 D_801151FC; /* TU line 735 */ +extern s32 D_80126B58; /* TU line 53 */ +extern s32 rand(void); /* TU line 954 */ +extern void func_800D0C48(s32 a0); /* TU line 1466 */ +extern s32 func_801726AC(s32 *a0); /* TU line 2221 */ +extern int func_80178970(void); /* TU line 2533 */ +extern s32 func_80178B18(s32 param_1, s32 param_2); /* TU line 2534 */ +extern void func_80178D18(void); /* TU line 2541 */ +extern int func_8001AAA0(void); /* TU line 2586 */ + +void func_80180E64(s32 a0) { + extern s32 D_801AECD8[]; /* 5 entity pointers, stride 4 */ + extern s32 D_801AECF0; /* single entity pointer */ + extern s16 D_8019BBF8; /* param block passed to func_80178B18 */ + + u8 *p = D_80078E78; + s16 c0; + register s32 f __asm__("$3"); + s32 i0; + s32 i1; + s32 i2; + s32 i3; + s32 r; + s32 d; + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + if ((rand() & 0x3F) == 0) { + r = rand() % 5; + if (*(u16 *)(D_801AECD8[r] + 2) == 1) { + *(s16 *)(D_801AECD8[r] + 0x10A) = 4; + } + } + if (*(s32 *)(a0 + 0x1C) != 0) { + *(s32 *)(a0 + 0x1C) -= 1; + } else { + c0 = 0; + for (i0 = 0; i0 < 5; i0++) { + if (*(s16 *)(D_801AECD8[i0] + 0x10A) != 0 && *(u8 *)(D_801AECD8[i0] + 0xC1) != 3) { + c0++; + } + } + if (c0 < 3) { + r = rand() % 5; + if (*(u16 *)(D_801AECD8[r] + 2) == 1) { + *(s16 *)(D_801AECD8[r] + 0x10A) = 1; + d = 0x1A4 - *(s16 *)(p + 0x1A); + *(s32 *)(a0 + 0x1C) = d; + if (d < 1) { + *(s32 *)(a0 + 0x1C) = 1; + } + } + } + } + if (*(s16 *)(p + 0x1A) > 0x1A2) { + func_800D0C48(1); + } + if (*(s16 *)(p + 0x1A) > 0x1A3 && func_801726AC(&D_80126B58) == 0) { + *(u16 *)(a0 + 0x34) += 1; + } + break; + + case 1: + f = 0; + /* §NNN: the zero-byte `"r"(i1)` keepalive adds the 5th reference to the + loop counter, which lifts its global_alloc priority above the + strength-reduced pointer giv's -- that is what puts the counter in + $a0 and the giv in $a1 (without it they swap). Emits no bytes. */ + for (i1 = 0; i1 < 5; i1++) { + __asm__ __volatile__("" :: "r"(i1)); + if (*(u16 *)(D_801AECD8[i1] + 2) == 5) { + f = 1; + } + } + if (D_801151FC == 0 && f != 1) { + func_80178B18(a0, (s32)&D_8019BBF8); + for (i2 = 0; i2 < 5; i2++) { + *(s16 *)(D_801AECD8[i2] + 0x10A) = 5; + *(s16 *)(D_801AECD8[i2] + 0x5C) = 0; + *(u8 *)(D_801AECD8[i2] + 0xC1) = 0; + } + *(u16 *)(a0 + 0x34) += 1; + *(s16 *)(D_801AECF0 + 2) = 6; + *(s16 *)(a0 + 0x100) = 1; + ((void (*)(s32))func_8001AAA0)(0x42); + } + break; + + case 2: + D_801151FC = 0; + if (((s32 (*)(s32))func_80178970)(a0) != 0) { + ((void (*)(s32))func_80178D18)(a0); + *(u16 *)(a0 + 0x34) = 0; + *(u16 *)(a0 + 2) += 1; + } + break; + } + + if (D_801151FC != 0) { + for (i3 = 0; i3 < 5; i3++) { + *(s16 *)(D_801AECD8[i3] + 0x10A) = 3; + } + } +} + extern void (*D_8019BC80[])(void); diff --git a/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c b/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c index 706a8e474..d75cbb758 100644 --- a/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c +++ b/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c @@ -5184,7 +5184,110 @@ void func_8017F8A0(int param_1) } -INCLUDE_ASM("asm/ov_SC04_000/nonmatchings/ov_SC04_000_jr_8017BEBC", func_8017F98C); +extern s32 func_8012B744(s32 a0, s32 a1); +extern s32 func_8012B608(s32 a0, s32 a1, s32 a2); +extern void func_8012B2CC(s32 a0); +extern void func_8012B1B4(s32 a0, s32 a1); +extern void func_8012A828(s32, s32); +extern s32 func_8012CBA4(s32 a0); +extern s32 func_8012BA10(s32 a0, s32 a1); +extern void func_800D0C48(s32 a0); +extern void func_8002AC00(s32 arg0); +extern int func_8001AAA0(void); +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_8012C218(void *a0); +extern u8 D_801995A4[]; +extern u8 D_801995AC[]; +extern u8 D_8019CF08[]; +extern u8 D_8019CF90[]; + +void func_8017ECC8(void); + +void func_8017F98C(s32 a0) { + s32 r; + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + break; + case 1: + r = func_8012B744(a0 + 4, (s32)D_801995A4); + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + + func_8012B608(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12), r, 4); + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF; + *(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) - 1; + if (*(s32 *)(a0 + 0x1C) == 0) { + *(s16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + func_8012B2CC(a0); + func_8012B1B4(a0, (s32)D_801995AC); + *(s32 *)(a0 + 0x1C) = 0xF; + func_8012A828(a0, (s32)D_8019CF08); + } + break; + case 2: + func_8012CBA4(a0); + break; + case 3: + func_8012CBA4(a0); + *(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) - 1; + if (*(s32 *)(a0 + 0x1C) == 0) { + *(s32 *)(a0 + 0x1C) = 0xF; + *(s16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + func_8012A828(a0, (s32)D_8019CF90); + } + break; + case 4: + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + func_8012BA10(a0, 4); + break; + case 5: + r = func_8012B744(a0 + 4, (s32)D_801995A4); + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + + func_8012B608(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12), r, 4); + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) & 0xFFF; + *(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) - 1; + if (*(s32 *)(a0 + 0x1C) == 0) { + *(s16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + func_8012B2CC(a0); + func_8012B1B4(a0, (s32)D_801995AC); + func_8012A828(a0, (s32)D_8019CF08); + } + break; + case 6: + func_8012CBA4(a0); + if (*(s16 *)(a0 + 0xE) < -0x398) { + *(s16 *)(a0 + 0xE) = -0x600; + *(s16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + func_800D0C48(1); + *(s32 *)(a0 + 0x1C) = 0x1E; + func_8002AC00(0x17); + } + break; + case 7: + *(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) - 1; + if (*(s32 *)(a0 + 0x1C) == 0) { + *(s16 *)(a0 + 0x34) = 0; + ((int (*)(s32))func_8001AAA0)(0x55); + *(u16 *)(a0 + 0xFC) |= 1; + } + break; + } + + if (*(s16 *)(a0 + 0xFC) < 2 && func_801789AC(a0) != 0) { + ((void (*)(s32))func_80178D18)(a0); + func_80029514(0x2F8); + *(u16 *)(a0 + 0xFC) |= 2; + func_8012A568(func_8017ECC8); + } + if (*(s16 *)(a0 + 0xFC) == 3) { + func_8012C218((void *)a0); + } +} + extern void (*D_80199760[])(void); diff --git a/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c b/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c index 27c49b2de..23de3cdd2 100644 --- a/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c +++ b/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c @@ -6034,7 +6034,128 @@ void func_801826E4(s32 param_1) } -INCLUDE_ASM("asm/ov_SC04_011/nonmatchings/ov_SC04_011_jr_8017D494", func_801827DC); +void func_801827DC(s32 param_1) +{ + extern void func_80186C1C(void); + extern void func_80183F10(void); + extern void func_8018BA9C(void); + extern void func_80183EA8(void); + extern void func_8018BAC4(void); + extern void func_80182D34(s32 a0); + extern void func_8018AC00(void *a0); + extern void func_8012BEE8(u8 *a0); + extern void func_8013C9C4(void *a0); + extern void func_8018637C(s32 arg0, s32 arg1); + extern void func_8002D4C8(s32 a0, s32 a1); + extern void func_8018B9D4(); + extern void func_80182AF8(); + /* §183: the TU spells D_80194500 as a flat void*[] elsewhere; reach the + row-of-3 view through an __asm__ label alias -- the TU's own idiom. */ + extern void *a4500[][3] __asm__("D_80194500"); + extern s32 aFC4C[] __asm__("D_801EFC4C"); + extern s32 D_801EFC54; + extern s32 D_801EFC5C; + extern s32 D_801EFC60; + extern s32 D_801EFC64[]; + extern s32 D_801EFC68; + extern s32 D_801EFD28; + extern u16 D_801EFD40; + extern u8 D_80190B88[]; + s32 r; + s32 obj; + u16 t; + u16 f; + + switch (*(u16 *)(param_1 + 0x34)) { + case 0: + case 1: + if (*(s16 *)(param_1 + 0x98) == 0) { + func_8018637C(param_1, (s32)a4500[*(s16 *)(param_1 + 0xE2)][*(u16 *)(param_1 + 0x34) + 1]); + goto incr; + } + goto draw; + case 2: + if (*(s32 *)(param_1 + 0x94) != 0xB) { + goto draw; + } + func_80186C1C(); + *(s16 *)(param_1 + 0x76) = 0x64; + *(s32 *)(param_1 + 0x1C) = 0x80; + *(s16 *)(param_1 + 0xF2) = 1; + *(s16 *)(param_1 + 0xE2) = (s16)*(u16 *)(param_1 + 0xE2) >> 1; + func_8013C9C4(D_80190B88); + func_8018AC00((void *)aFC4C[0]); + func_8018AC00((void *)D_801EFC54); + func_8018AC00((void *)D_801EFC5C); + func_8018AC00((void *)D_801EFC60); + func_8018AC00((void *)D_801EFC64[0]); + func_8018AC00((void *)D_801EFC68); + func_8002D4C8(0x907, 0); +incr: + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; +draw: + func_8018B9D4(D_801EFC54, *(s32 *)(param_1 + 0xD0)); + return; + case 3: + if (*(s16 *)(param_1 + 0x76) == 0) { + t = *(u16 *)(param_1 + 0xF6) - 1; + *(u16 *)(param_1 + 0xF6) = t; + *(s16 *)&D_801EFD28 = (s16)t * 100; + func_80183F10(); + obj = *(s32 *)(param_1 + 0xD0); + if (obj != 0) { + *(u16 *)(obj + 0x1A) = 0x800; + *(u16 *)(obj + 0x18) = 0x800; + } + func_8018BA9C(); + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + if (*(s16 *)(param_1 + 0xF6) == 0) { + f = D_801EFD40; + *(s32 *)(param_1 + 0x1C) = 8; + D_801EFD40 = f | 0x100; + return; + } + *(s32 *)(param_1 + 0x1C) = 0x10; + return; + } + r = ((s32 (*)(s32))func_8012BEE8)((s32)param_1); + if (r == 0) { + if (((*(s32 *)(param_1 + 0x1C) & 0xF) == 0) && (*(s16 *)(param_1 + 0xF2) != 0)) { + *(s16 *)(param_1 + 0xF2) = *(s16 *)(param_1 + 0xF2) - 1; + func_8013C9C4(D_80190B88); + } + func_8018B9D4(D_801EFC54, *(s32 *)(param_1 + 0xD0)); + if ((*(s32 *)(param_1 + 0x1C) & 1) != 0) { + return; + } + func_80183EA8(); + return; + } + goto L_af8; + case 4: + r = ((s32 (*)(s32))func_8012BEE8)((s32)param_1); + if (r != 0) { + if (*(s16 *)(param_1 + 0xF6) == 0) { + func_80182D34(param_1); + return; + } +L_af8: + func_80182AF8(param_1); + return; + } + obj = *(s32 *)(param_1 + 0xD0); + if (obj != 0) { + t = *(u16 *)(obj + 0x18) + 0x600; + *(u16 *)(obj + 0x18) = t; + *(u16 *)(obj + 0x1A) = t; + } + func_8018BAC4(); + return; + default: + return; + } +} + void func_80182AF8(s32 a0) { extern void func_80186EBC(); diff --git a/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c b/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c index 26b6dc9f1..8b5520363 100644 --- a/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c +++ b/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c @@ -4885,7 +4885,112 @@ void func_8017E4E4(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_015/nonmatchings/ov_SC04_015_jr_8017AE2C", func_8017E520); +extern void func_8001D074(s32, s32); +extern void func_8001CB00(s32 a0, void *a1, s32 a2, s32 a3); +extern void func_80128EA8(s32 a0, s32 a1, s32 a2); +extern s32 func_80128ED8(s32 param_1, s32 *param_2); +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern void func_8017E830(s32 a0); +extern u8 D_801885C8[]; +extern u8 D_801885D4[]; +extern s32 D_801C8B6C; +extern s16 D_801C8B70; +extern s16 D_801C8B74; + +void func_8017E520(s32 a0) { + s32 p; + s32 q; + s32 u; + s32 g; + s16 t; + + switch ((s16)(*(u16 *)(a0 + 0) - 1)) { + case 0: + p = ((s32 (*)(s32, s32))func_8001D074)(0x3E, 0x7D); + *(s32 *)(a0 + 4) = p; + func_8001CB00(p, D_801885C8, 0x340, 0x100); + *(u8 *)(*(s32 *)(a0 + 4) + 0x27) = 0x2F; + *(s32 *)(*(s32 *)(a0 + 4) + 4) |= 0x50000000; + *(s16 *)(*(s32 *)(a0 + 4) + 0x2C) = 2; + func_80128EA8(*(s32 *)(a0 + 4), a0 + 8, (s32)D_801885D4); + *(s16 *)(a0 + 0x14) = -0x5C; + *(s16 *)(a0 + 0x10) = (*(s16 *)(a0 + 0x18) - 4) * 24 + 0x18; + *(s16 *)(*(s32 *)(a0 + 4) + 0x14) = 0x400; + *(s16 *)(a0 + 0) = 4; + *(s16 *)(a0 + 0xC) = *(u16 *)(a0 + 0x18) & 7; + *(s16 *)(a0 + 2) = *(s16 *)(a0 + 0x18) * 4; + break; + case 1: + if (D_801C8B6C == 0) { + *(s16 *)(a0 + 2) = 8; + *(s16 *)(a0 + 0) = 3; + } else { + t = *(u16 *)(a0 + 2) + 1; + *(s16 *)(a0 + 2) = t; + *(s16 *)(a0 + 0x16) = (u32)func_8004787C((t & 0x3F) << 6) >> 10; + *(s16 *)(a0 + 0x12) = (u32)func_80047948((*(u16 *)(a0 + 2) & 0x3F) << 6) >> 11; + } + break; + case 3: + if (D_801C8B6C == 1) { + *(s16 *)(a0 + 2) = 8; + *(s16 *)(a0 + 0) = 5; + } else { + t = *(u16 *)(a0 + 2) + 1; + *(s16 *)(a0 + 2) = t; + *(s16 *)(a0 + 0x16) = (u32)func_8004787C((t & 0x3F) << 6) >> 10; + *(s16 *)(a0 + 0x12) = (u32)func_80047948((*(u16 *)(a0 + 2) & 0x3F) << 6) >> 11; + *(s16 *)(a0 + 0x16) = *(u16 *)(a0 + 0x16) - 0x40; + } + break; + case 2: + *(s16 *)(a0 + 0x16) = *(u16 *)(a0 + 0x16) - 8; + t = *(u16 *)(a0 + 2) - 1; + *(s16 *)(a0 + 2) = t; + if (t <= 0) { + *(s16 *)(a0 + 2) = 0; + *(s16 *)(a0 + 0) = 4; + } + break; + case 4: + *(s16 *)(a0 + 0x16) = *(u16 *)(a0 + 0x16) + 8; + t = *(u16 *)(a0 + 2) - 1; + *(s16 *)(a0 + 2) = t; + if (t <= 0) { + *(s16 *)(a0 + 2) = 0; + *(s16 *)(a0 + 0) = 2; + } + break; + case 5: + *(s16 *)(a0 + 0) = 7; + *(s16 *)(a0 + 2) = 0x20; + case 6: + t = *(u16 *)(a0 + 2) - 1; + *(s16 *)(a0 + 2) = t; + u = t; + if (u <= 0) { + g = D_801C8B70; + *(s16 *)(a0 + 2) = 0; + *(s16 *)(a0 + 0) = 0; + if (g == 0) { + D_801C8B74 = 1; + } + } else { + q = *(s32 *)(a0 + 4); + *(s16 *)(q + 0x1A) = u << 7; + *(s16 *)(q + 0x18) = u << 7; + *(s16 *)(a0 + 0x12) = (func_80047948((*(u16 *)(a0 + 2) & 0x1F) << 8) * 5) >> 12; + } + break; + } + + func_80128ED8(*(s32 *)(a0 + 4), (s32 *)(a0 + 8)); + *(s16 *)(*(s32 *)(a0 + 4) + 8) = *(u16 *)(a0 + 0x10) + *(u16 *)(a0 + 0x12); + *(s16 *)(*(s32 *)(a0 + 4) + 0xA) = *(u16 *)(a0 + 0x14) + *(u16 *)(a0 + 0x16); + func_8017E830(a0); +} + extern s32 AddPrim(s32, void *); extern void *func_80010A08(s32); diff --git a/src/ov_SC04_016/ov_SC04_016_jr_8017BEBC.c b/src/ov_SC04_016/ov_SC04_016_jr_8017BEBC.c index b9fdec1dc..9e1c61856 100644 --- a/src/ov_SC04_016/ov_SC04_016_jr_8017BEBC.c +++ b/src/ov_SC04_016/ov_SC04_016_jr_8017BEBC.c @@ -3327,7 +3327,199 @@ void func_8017D0EC(s32 *a0) { } -INCLUDE_ASM("asm/ov_SC04_016/nonmatchings/ov_SC04_016_jr_8017BEBC", func_8017D118); +#include "common.h" + +extern void func_8012C1B8(void); +extern void func_8001C2C4(s32); +extern s32 func_8012C51C(void *arg0, s32 arg1); +extern void func_8001C810(s32 a0, s32 a1); +extern s32 func_8001CA88(s32 a0, void *a1); +extern void func_8001C214(s32 a0, s32 a1); +extern void func_80143994(s32 a0, s32 a1); +extern s32 func_8012A828(void *a0, void *a1); +extern void func_800233CC(void *, unsigned short); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8017DF68(void); +extern void func_8017E6A0(void *a0); + +extern s32 D_80190580; +extern u8 D_8018490C; +extern s16 D_80198108; +extern s32 D_801840EC; +extern s32 D_8019E610; +extern s32 D_8018445C; +extern s32 D_801A1CA0; +extern s32 D_80184724; +extern s32 D_801A33C0; +extern s32 D_80180328; +extern unsigned char D_801A6B00; +extern unsigned char D_801A6B01; +extern unsigned char D_801A6B02; +extern unsigned char D_801A6B04; +extern unsigned char D_801A6B05; +extern unsigned char D_801A6B06; + +typedef struct { + s16 f0; + s16 f1; + s16 f2; + s16 f3; + s16 f4; + s16 f5; + s16 f6; + s16 f7; + s32 f8; +} St_8017D118; + +void func_8017D118(s32 a0) { + St_8017D118 st; + s32 state; + s32 p2; + s32 p3; + s32 val; + s32 t; + unsigned char *pk; + + if (*(s16 *)(a0 + 0x70) & 0x8000) { + t = ((s32 (*)(void))func_8012C1B8)(); + *(s32 *)(a0 + 0x20) = t; + if (t == 0) { + return; + } + func_8001C2C4(t); + st.f3 = 0x337; + st.f5 = 0; + st.f6 = 0; + st.f7 = 0; + st.f8 = 0; + if (*(s32 *)(a0 + 0xCC) == 0) { + st.f4 = 0; + st.f0 = -0x100; + st.f1 = -0x202; + st.f2 = 0; + *(s32 *)(a0 + 0xCC) = func_8012C51C(&st, a0); + } + if (*(s32 *)(a0 + 0xD4) == 0) { + st.f4 = 2; + st.f0 = -0xF8; + st.f1 = -0x502; + st.f2 = 0x60; + *(s32 *)(a0 + 0xD4) = func_8012C51C(&st, a0); + } + if (*(s32 *)(a0 + 0xD0) == 0) { + st.f4 = 1; + st.f0 = 0x1C0; + st.f1 = -0x202; + st.f2 = 0x160; + *(s32 *)(a0 + 0xD0) = func_8012C51C(&st, a0); + } + if (*(s32 *)(a0 + 0xD8) == 0) { + st.f4 = 3; + st.f0 = -0x100; + st.f1 = -0x202; + st.f2 = 0x60; + *(s32 *)(a0 + 0xD8) = func_8012C51C(&st, a0); + } + if (*(s32 *)(a0 + 0xF8) == 0) { + st.f4 = 4; + st.f0 = -0x100; + st.f1 = -0x202; + st.f2 = 0x60; + *(s32 *)(a0 + 0xF8) = func_8012C51C(&st, a0); + } + if (*(s32 *)(a0 + 0xF4) == 0) { + st.f4 = 5; + st.f0 = -0x100; + st.f1 = -0x252; + st.f2 = 0x60; + *(s32 *)(a0 + 0xF4) = func_8012C51C(&st, a0); + } + if (*(s32 *)(a0 + 0xCC) != 0 && *(s32 *)(a0 + 0xD0) != 0 && + *(s32 *)(a0 + 0xD4) != 0 && *(s32 *)(a0 + 0xD8) != 0 && + *(s32 *)(a0 + 0xF8) != 0 && *(s32 *)(a0 + 0xF4) != 0) { + *(u16 *)(a0 + 2) = *(u16 *)(a0 + 2) + 1; + } + } else { + t = ((s32 (*)(void))func_8012C1B8)(); + *(s32 *)(a0 + 0x20) = t; + if (t == 0) { + return; + } + switch (*(s16 *)(a0 + 0x70)) { + case 0: + p3 = (s32)&D_80190580; + p2 = (s32)&D_8018490C; + val = 0xC80; + state = 5; + break; + case 1: + p3 = (s32)&D_80198108; + p2 = (s32)&D_801840EC; + val = 0; + state = 6; + break; + case 2: + p3 = (s32)&D_8019E610; + p2 = (s32)&D_8018445C; + val = 0; + state = 7; + break; + case 3: + p3 = (s32)&D_801A1CA0; + p2 = (s32)&D_80184724; + val = 0; + func_8001C810(*(s32 *)(a0 + 0x20), p3); + *(s32 *)(*(s32 *)(a0 + 0x20) + 4) |= 0x50000000; + state = 8; + break; + case 4: + p3 = (s32)&D_801A33C0; + p2 = (s32)&D_80180328; + val = 0xC00; + func_8001C810(*(s32 *)(a0 + 0x20), p3); + *(s32 *)(*(s32 *)(a0 + 0x20) + 4) |= 0x70000000; + state = 9; + break; + case 5: + pk = &D_801A6B00; + D_801A6B02 = 0x20; + *pk = 0x20; + D_801A6B01 = 0x80; + D_801A6B04 = D_801A6B05 = D_801A6B06 = 0; + func_800233CC(pk, 0x30); + func_8001CA88(*(s32 *)(a0 + 0x20), pk); + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x1A) = 0x2000; + *(s32 *)(*(s32 *)(a0 + 0x20) + 4) |= 0x50000000; + val = 0; + p2 = 0; + state = 0xA; + break; + case 6: + func_8017DF68(); + func_8017E6A0((void *)a0); + func_8002D4C8(0xB90, 0); + state = 0xC; + break; + case 7: + func_8001C2C4(*(s32 *)(a0 + 0x20)); + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = 0xC00; + state = 0xD; + break; + } + if (*(s16 *)(a0 + 0x70) < 6) { + if (*(s16 *)(a0 + 0x70) < 3) { + func_8001C214(*(s32 *)(a0 + 0x20), p3); + func_80143994(a0, 0x3000); + } + if (p2 != 0) { + func_8012A828((void *)a0, (void *)p2); + } + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = val; + } + *(s16 *)(a0 + 2) = state; + } +} + void func_8017D588(void *a0) { extern s32 func_800149E0(s32); diff --git a/src/ov_SC05_001/ov_SC05_001_jr_80183508.c b/src/ov_SC05_001/ov_SC05_001_jr_80183508.c index a99fe602e..0d800b0d0 100644 --- a/src/ov_SC05_001/ov_SC05_001_jr_80183508.c +++ b/src/ov_SC05_001/ov_SC05_001_jr_80183508.c @@ -3192,7 +3192,206 @@ void func_80183BB0(s32 param_1) } -INCLUDE_ASM("asm/ov_SC05_001/nonmatchings/ov_SC05_001_jr_80183508", func_80183C9C); +#include "common.h" + +/* func_80183C9C — ov_SC05_001 `_jr_80183508`, 196 ins, frame 0x18. MATCH (match_one, masked). + * + * .venv/bin/python tools/match_one.py func_80183C9C \ + * --c .run/pool_1/opus/func_80183C9C.c \ + * --asm-subdir asm/ov_SC05_001/nonmatchings/ov_SC05_001_jr_80183508 + * + * Enemy state machine — the SAME shape as func_80183508 in this very TU (:2839): + * the `if (*(s16 *)(p+0xa) >= 0x10) { func_80184580(p); return; }` guard, a 5-entry + * jump table over `*(u16 *)(p + 0x34)`, the goto-label idiom, and the 0x100000 clamp + * tail. This one's tail additionally calls func_8018466C(p) before the clamp, and + * the default arm falls straight into it. + * + * jtbl_801B4850 (asm/ov_SC05_001/data/tail18.data.s:9) — minval 0 / maxval 4, no + * holes, default -> TAIL. Its five words are in strictly ASCENDING address order + * (80183CFC / DA0 / E6C / EC8 / EEC), so the arms are emitted in case order 0..4 + * and the source case order is the literal one. + * + * Four labels are reached from more than one arm and therefore MUST be written as + * gotos at exactly these source positions or the block order drifts: + * EXIT (.L80183F10, from cases 0/1 and case 4) -> func_80184580(p); return; + * HITSTUN (.L80183F28, from cases 1/2/3 and case 4) -> func_80131C78(p); + * L_F54 (.L80183F54, from case 2 and case 4) + * TAIL (.L80183F78, from every arm and the default) + * Per §162 the surviving copy of a merged tail is the LATER one, and every one of + * these `j`s is FORWARD into the last-emitted arm (case 4) — consistent with the + * canonical copy living inside case 4, which is how it is spelled below. + * + * ---- THE ONE LEVER (90 mismatched / LENGTH-DRIFT -7 -> MATCH) --------------- + * COOKBOOK §5a — cross-jump tail-merge, and it fires in the direction §5a warns + * about: MY build was SHORTER than the target. Case 1's counter tail + * x = ++p->0x1c; if (x < 0x10) goto TAIL; goto HITSTUN; + * is byte-identical to the WHOLE of case 3's body — same 9 instructions, same two + * exit labels — so gcc-2.7.2's `find_cross_jump` merged them (one copy survives, + * the other arm gets a `j` + delay nop: 18 -> 11, exactly the -7 drift). The + * original binary keeps BOTH copies. There is no `-fno-crossjumping` before gcc + * 3.3, so the only lever is §5a's zero-byte barrier: `find_cross_jump` sets + * `lose = 1` on ANY volatile asm, so one empty `__asm__ __volatile__("")` inside + * one twin makes the two RTL streams unequal and both copies survive. + * + * PLACEMENT IS LOAD-BEARING, and this is the part §5a does not spell out. The + * barrier must sit at the very END of the twin, immediately before the shared + * `goto TAIL` — i.e. INSIDE the `if`. find_cross_jump walks the two streams + * BACKWARD from the converging `j`, so a barrier at the TOP of the block is walked + * past: the seven insns below it still match and gcc merges those instead, leaving + * the drift only slightly smaller. Put at the bottom the walk fails at offset 0 + * and the suffix never reaches §50-B's `minimum` floor. Plain `("")` is used, not + * `("" ::: "memory")` — §5a's own note — because the memory clobber would pin the + * store ordering in the arms that schedule `sw 0x1c` against `sh 0x34`. + * Cost: zero bytes. A future reader WILL try to delete it; it is worth 7 ins. + * + * INTEGRATION SURFACE (§161c) — every block-scope decl below AGREES with this TU: + * func_80184580 DEFINED here `void (s32)` TU:3482 (+ file-scope decl TU:3457) + * — note func_80183508 (TU:2841) spells it `void (void *)` at ITS + * own block scope; block scopes do not conflict, and the (s32) + * spelling is the one that agrees with the definition. + * func_8018466C file-scope `s32 ()` TU:3150/3198 (unspecified — §195-A, + * never "fix" it; redeclared here exactly as func_801840AC does) + * func_8012CC64 block-scope `s32 (s32,void*)` TU:3253 + * func_8012CC1C block-scope `s32 (s32,void*)` TU:3254 + * func_8012B23C block-scope `void (s32)` TU:3256 + * func_80131C78 block-scope `void (s32)` TU:3257 + * func_80143B6C block-scope `s32 (s32,s32)` TU:3258 + * func_80131E00 block-scope `void (s32,s32)` TU:3259 (file-scope `void ()` at + * TU:2781/3146 — compatible, C89 unspecified-vs-prototype) + * D_801AE3A8 block-scope `s32` TU:3260, passed as &D_801AE3A8 + * + * SYMBOL AUDIT (law 1c — match_one masks jal/HI16/LO16, so this was checked by + * hand AND by diffing the object's reloc order against the target's): + * 80184580 jtbl D_801AE3A8 8012CC64 8012B23C | D_801AE3A8 8012CC1C 8012B23C + * 80143B6C | D_801AE3A8 8012CC64 80143B6C 80143B6C 8012B23C | D_801AE3A8 + * 8012CC1C 80184580 80131C78 80143B6C 80131E00 8018466C — identical, in order. + */ + +void func_80183C9C(s32 param_1) +{ + extern void func_80184580(s32 a0); + extern s32 func_8018466C(); + extern s32 func_8012CC64(s32 a0, void *a1); + extern s32 func_8012CC1C(s32 a0, void *a1); + extern void func_8012B23C(s32 a0); + extern void func_80131C78(s32 a0); + extern s32 func_80143B6C(s32 a0, s32 a1); + extern void func_80131E00(s32 a0, s32 a1); + extern s32 D_801AE3A8; + + s32 iVar1; + + if (*(s16 *)(param_1 + 0xa) >= 0x10) { + func_80184580(param_1); + return; + } + + switch (*(u16 *)(param_1 + 0x34)) { + case 0: + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x10) -= 0x100; + iVar1 = func_8012CC64(param_1, &D_801AE3A8); + if ((iVar1 & 0xff) == 0x1a) { + goto EXIT; + } + if ((iVar1 & 0x2000) != 0) { + *(u16 *)(param_1 + 0x34) += 1; + *(s32 *)(param_1 + 0x1c) = 0; + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x10) = 0; + goto TAIL; + } + if ((iVar1 & 0x4000) != 0) { + *(u16 *)(param_1 + 0x34) = 4; + *(s32 *)(param_1 + 0x1c) = 0; + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x10) = 0; + func_8012B23C(param_1); + goto TAIL; + } + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) >= 0x3c) { + *(u16 *)(param_1 + 0x34) = 2; + } + goto TAIL; + + case 1: + *(s32 *)(param_1 + 0x10) = *(s32 *)(param_1 + 0x10) * 15 / 16; + *(s32 *)(param_1 + 0x18) = *(s32 *)(param_1 + 0x18) * 15 / 16; + iVar1 = func_8012CC1C(param_1, &D_801AE3A8); + if ((iVar1 & 0xff) == 0x1a) { + goto EXIT; + } + if ((iVar1 & 0x6000) == 0) { + *(u16 *)(param_1 + 0x34) += 1; + *(s32 *)(param_1 + 0x1c) = 0; + func_8012B23C(param_1); + goto TAIL; + } + if ((*(s32 *)(param_1 + 0x1c) & 3) == 0) { + func_80143B6C(param_1, 1); + } + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) < 0x10) { + goto TAIL; + } + goto HITSTUN; + + case 2: + iVar1 = func_8012CC64(param_1, &D_801AE3A8); + if ((iVar1 & 0x2000) != 0) { + func_80143B6C(param_1, 1); + goto HITSTUN; + } + if ((iVar1 & 0x4000) == 0) { + goto L_F54; + } + *(u16 *)(param_1 + 0x34) = 4; + func_80143B6C(param_1, 1); + func_8012B23C(param_1); + goto TAIL; + + case 3: + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) < 0x10) { + /* §5a ZERO-BYTE CROSS-JUMP BARRIER — LOAD-BEARING, DO NOT DELETE. + * This whole arm is byte-identical to case 1's counter tail; without + * this line find_cross_jump merges the two and the function comes out + * 7 instructions short. Emits no machine code. See the header. */ + __asm__ __volatile__(""); + goto TAIL; + } + goto HITSTUN; + + case 4: + iVar1 = func_8012CC1C(param_1, &D_801AE3A8); + if ((iVar1 & 0xff) != 0x1a) { + goto L_F20; + } + EXIT: + func_80184580(param_1); + return; + L_F20: + if ((iVar1 & 0x2000) == 0) { + goto L_F38; + } + HITSTUN: + func_80131C78(param_1); + goto TAIL; + L_F38: + if ((*(s32 *)(param_1 + 0x1c) & 3) == 0) { + func_80143B6C(param_1, 1); + } + L_F54: + *(s32 *)(param_1 + 0x1c) += 1; + if (*(s32 *)(param_1 + 0x1c) >= 0x3c) { + func_80131E00(param_1, 0xd); + } + } +TAIL: + func_8018466C(param_1); + if (0x100000 < *(s32 *)(param_1 + 0x14)) { + *(s32 *)(param_1 + 0x14) = 0x100000; + } +} + extern s32 D_801AE350; extern s32 func_8018466C(); diff --git a/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c b/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c index 54d1231cf..251d23ecb 100644 --- a/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c +++ b/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c @@ -3359,9 +3359,331 @@ void func_80183274(s32 a0) { } -INCLUDE_ASM("asm/ov_SC05_010/nonmatchings/ov_SC05_010_jr_80181CDC", func_8018340C); -INCLUDE_ASM("asm/ov_SC05_010/nonmatchings/ov_SC05_010_jr_80181CDC", func_8018388C); + + + + + + +extern void func_8004914C(void *a0); +extern void func_800491AC(void *a0); +extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); +extern s32 func_8004787C(s32 a0); +extern s32 D_80126950; +extern void *func_80010A08(s32 size); +extern s32 GetTPage(s32 a0, s32 a1, s32 a2, s32 a3); +extern s32 func_8005A600(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4); +extern s32 AddPrim(s32 ot, void *prim); + +extern u8 D_800AF648; +extern s32 D_800A651C[]; +extern s16 D_800B9A02; +extern s16 D_80192CC0; +extern s16 D_80192CC4[]; +extern u8 D_80192CD0[]; +extern u8 D_80192CD1[]; +extern u8 D_80192CD2[]; +extern u8 D_80192CD3[]; +extern u8 D_80192CE0[]; +extern u8 D_80192CE1[]; +extern u8 D_80192CE2[]; +extern u8 D_80192CE3[]; +extern u8 D_80192CF0[]; +extern u8 D_80192CF1[]; +extern u8 D_80192CF2[]; +extern u8 D_80192CF3[]; + +void func_8018340C(void *a0) +{ + s32 tags[4]; /* sp+0x18 */ + s16 in[4]; /* sp+0x28 */ + s16 xs[8]; /* sp+0x30 */ + s16 ys[8]; /* sp+0x40 */ + struct { + u16 sxy[2]; /* sp+0x50 */ + s32 p; /* sp+0x54 */ + s32 flag; /* sp+0x58 */ + } o; + + s32 ot; + s32 m; + s32 d; + s32 e; + s32 x; + s32 y; + s32 t; + s32 u; + s32 ret; + u8 *prim; + u8 *pp; + u8 *base; + s16 *pal; + s32 i; + s32 k; + /* cookbook SS194-A: the zero-byte volatile-asm fence below keeps the + D_80126950 load from being hoisted into the imul latency gap (sched1 + priority, map sched.md S3). The three pins split the one collapsed + chain pseudo into the target's $t0/$v0/$a2 triple (local-alloc). */ + register s32 aa __asm__("$8"); + register s32 bb __asm__("$2"); + register s32 cc __asm__("$6"); + + in[0] = *(s16 *)((s8 *)a0 + 0x06); + in[1] = *(s16 *)((s8 *)a0 + 0x0A); + in[2] = *(s16 *)((s8 *)a0 + 0x0E); + + func_8004914C(&D_800AF648); + func_800491AC(&D_800AF648); + + ret = RotTransPers((s32)in, (s32)o.sxy, &o.p, &o.flag); + if ((ret > 0) && (o.flag >= 0)) { + ot = *(s32 *)((s8 *)&D_800A651C + (u16)D_800B9A02 * 0x14) + ret * 4; + m = D_80192CC0; + t = func_8004787C(*(s16 *)((s8 *)a0 + 0xDE)) * 3; + if (t < 0) { + t += 7; + } + t = (t >> 3) - 0x800; + if (t < 0) { + u = func_8004787C(*(s16 *)((s8 *)a0 + 0xDE)) * 3; + if (u < 0) { + u += 7; + } + t = 0x800 - (u >> 3); + } else { + t = func_8004787C(*(s16 *)((s8 *)a0 + 0xDE)) * 3; + if (t < 0) { + t += 7; + } + t = (t >> 3) - 0x800; + } + aa = t * m; + bb = aa >> 12; + cc = bb + 8; + __asm__ __volatile__(""); + d = cc * (D_80126950 + 500); + d = d / (ret * 4); + + x = o.sxy[0]; + y = o.sxy[1]; + e = (d * 179) >> 8; + + xs[2] = x; + ys[2] = y; + xs[0] = x - d; + xs[1] = x - e; + xs[3] = x + e; + xs[4] = x + d; + ys[0] = y - d; + ys[1] = y - e; + ys[3] = y + e; + ys[4] = y + d; + + prim = (u8 *)func_80010A08(0x9C); + if (prim != 0) { + s32 tp; + tp = GetTPage(0, 1, 0, 0); + func_8005A600((s32)prim, 0, 1, (u16)tp, 0); + + tags[0] = (s32)(prim + 0xC); + pp = prim + 0xC; + pal = D_80192CC4; + base = (u8 *)tags; + k = 0; + tags[1] = (s32)(prim + 0x30); + tags[2] = (s32)(prim + 0x54); + tags[3] = (s32)(prim + 0x78); + do { + i = k * 4; + *(u32 *)(pp + 0x04) = ((u32 *)pal)[D_80192CF0[i]]; + *(u32 *)(pp + 0x0C) = ((u32 *)pal)[D_80192CF1[i]]; + *(u32 *)(pp + 0x14) = ((u32 *)pal)[D_80192CF2[i]]; + *(u32 *)(pp + 0x1C) = ((u32 *)pal)[D_80192CF3[i]]; + *(u8 *)(pp + 0x03) = 8; + *(u8 *)(pp + 0x07) = 0x3A; + *(u16 *)(pp + 0x08) = *(u16 *)(base + 0x18 + D_80192CD0[i] * 2); + *(u16 *)(pp + 0x10) = *(u16 *)(base + 0x18 + D_80192CD1[i] * 2); + *(u16 *)(pp + 0x18) = *(u16 *)(base + 0x18 + D_80192CD2[i] * 2); + *(u16 *)(pp + 0x20) = *(u16 *)(base + 0x18 + D_80192CD3[i] * 2); + *(u16 *)(pp + 0x0A) = *(u16 *)(base + 0x28 + D_80192CE0[i] * 2); + *(u16 *)(pp + 0x12) = *(u16 *)(base + 0x28 + D_80192CE1[i] * 2); + *(u16 *)(pp + 0x1A) = *(u16 *)(base + 0x28 + D_80192CE2[i] * 2); + *(u16 *)(pp + 0x22) = *(u16 *)(base + 0x28 + D_80192CE3[i] * 2); + AddPrim(ot, pp); + k += 1; + pp += 0x24; + } while (k < 4); + AddPrim(ot, prim); + } + } +} + + +#include "common.h" + +/* Spellings copied from the destination TU src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c + * (L379 D_801202A0, L1245 func_801746DC, L1461 func_800D0C48, L2529 func_80178B18, + * L2581 func_8001AAA0, L2528 func_80178970, L2536 func_80178D18, L2392 func_80174774, + * L165 func_8014704C, L1785 D_80126B66, L3231 func_8012C218, L51 func_8002D4C8, + * L949 rand) — the `(void)`-declared callees are reached through the TU's own + * ((void (*)(s32))f)(x) cast idiom (func_801844AC L3710). */ +extern u8 D_801202A0[]; +extern u8 D_801923C4[]; +extern void func_801746DC(void); +extern s32 func_80178B18(s32 param_1, s32 param_2); +extern void func_800D0C48(s32 a0); +extern void func_8012C218(void *a0); +extern void func_8002D4C8(s32 a0, s32 a1); +extern s32 rand(void); +extern int func_8001AAA0(void); +extern int func_80178970(void); +extern void func_80178D18(void); +extern s16 func_80174774(void); /* TU decl says s16, but the target has NO + * sll/sra extension before the beqz -> the call site + * is reached through an s32-returning cast (below). */ +extern void func_8014704C(s32 *a0); +extern u16 D_80126B66; + +/* not declared in the TU */ +extern s32 func_8012C588(s32 a0, s32 a1); +extern s32 func_80132EF4(s32 a0, s32 a1); +extern void func_8013373C(s16 a0); +extern void func_8017C068(void); +extern void func_80187874(void); +extern void func_8002AC00(s32 a0); +extern s32 D_801C7E30[]; +extern s32 D_801C7E50[]; /* == &D_801C7E30[8]; the target .s relocates against THIS symbol */ +extern s32 D_801C7E4C; +extern s32 D_80192D64[]; +extern s32 D_80126B58; +extern s32 D_80126B60; + +void func_8018388C(s32 param_1) { + s32 i; + s32 obj; + u8 *q; + + switch (*(u16 *)(param_1 + 0x34)) { + case 0: + func_80178B18(param_1, (s32)D_801923C4); + func_801746DC(); + *(s32 *)(param_1 + 0x1C) = 0x80; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + func_800D0C48(4); + q = D_801202A0; + for (i = 0; i < 0x60; i++) { + if (*(u16 *)q == 0x2B5) { + func_8012C218(q); + } + q += 0x10C; + } + *(s32 *)(D_801C7E4C + 0xE0) = 0x10000000; + break; + + case 1: + *(s32 *)(param_1 + 0x1C) = *(s32 *)(param_1 + 0x1C) - 1; + if ((*(s32 *)(param_1 + 0x1C) & 0xF) == 0) { + obj = func_8012C588(0x2DE, param_1); + if (obj != 0) { + func_8002D4C8(0x8B8, 0); + *(u16 *)(obj + 0xA) = *(u16 *)(obj + 0xA) + 0x20; + if (*(s32 *)(param_1 + 0x1C) & 0x40) { + *(u16 *)(obj + 0xFC) = (*(s32 *)(param_1 + 0x1C) & 0x30) << 6; + } else { + *(u16 *)(obj + 0xFC) = ((*(s32 *)(param_1 + 0x1C) & 0x30) << 6) + 0x200; + } + *(u16 *)(obj + 0xFC) = *(u16 *)(obj + 0xFC) + (rand() & 0x1FF); + *(u16 *)(obj + 0xFE) = *(s32 *)(param_1 + 0x1C) + 0x60; + } + } + if (*(s32 *)(param_1 + 0x1C) == 0) { + *(s32 *)(param_1 + 0x1C) = 0x10; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + } + break; + + case 2: + if (*(s32 *)(param_1 + 0x1C) == 0) { + *(s32 *)(param_1 + 0x1C) = 0x3C; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + func_8012C588(0x2DC, D_801C7E30[0]); + func_80132EF4(D_801C7E30[0], 0x5F); + func_8002D4C8(0x8B9, 0); + } else { + *(s32 *)(param_1 + 0x1C) = *(s32 *)(param_1 + 0x1C) - 1; + } + break; + + case 3: + if (*(s16 *)(param_1 + 0x84) == 0) { + *(s16 *)(param_1 + 0x84) = ((s32 (*)(s32))func_8001AAA0)(0x6D); + } + if (*(s32 *)(param_1 + 0x1C) != 0) { + *(s32 *)(param_1 + 0x1C) = *(s32 *)(param_1 + 0x1C) - 1; + } else { + func_8012C218((void *)D_801C7E30[0]); + D_801C7E30[0] = 0; + for (i = 2; i < 8; i++) { + func_8012C218((void *)*(s32 *)(D_801C7E30[i] + 0x6C)); + func_8012C218((void *)D_801C7E30[i]); + D_801C7E30[i] = 0; + } + for (i = 8; i < 12; i++) { + func_8012C218((void *)D_801C7E50[i - 8]); + D_801C7E50[i - 8] = 0; + } + q = D_801202A0; + for (i = 0; i < 0x60; i++) { + if (*(u16 *)q == 0x275) { + func_8012C218(q); + } + q += 0x10C; + } + func_8014704C(&D_80126B58); + func_8013373C(0); + *(s16 *)(param_1 + 0xA) = 0x77; + *(s16 *)(param_1 + 0x6) = 0; + *(s16 *)(param_1 + 0xE) = 0; + D_80126B60 = 0x970000; + D_80126B66 = 0x90; + func_8012C588(0x2F7, param_1); + for (i = 0; i < 0x18; i++) { + obj = func_8012C588(0x2E3, param_1); + if (obj != 0) { + *(s32 *)(*(s32 *)(obj + 0x20) + 0x24) = D_80192D64[i]; + } + } + func_8017C068(); + func_80187874(); + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + } + break; + + case 4: + if (*(s16 *)(param_1 + 0x84) == 0) { + *(s16 *)(param_1 + 0x84) = ((s32 (*)(s32))func_8001AAA0)(0x6D); + } + break; + + case 5: + if (((s32 (*)(void))func_80174774)() != 0) { + *(u32 *)(*(s32 *)(param_1 + 0x20) + 4) |= 0x80000000; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + func_8002AC00(0x1E); + } + break; + + case 6: + break; + } + + if (((s32 (*)(s32))func_80178970)(param_1) != 0) { + ((void (*)(s32))func_80178D18)(param_1); + *(u16 *)(param_1 + 0x2) = 6; + } +} + extern s32 func_8004787C(s32 a0); extern void func_8018340C(void *a0); diff --git a/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c b/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c index 98301f4ec..0921a7377 100644 --- a/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c +++ b/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c @@ -4246,7 +4246,144 @@ void func_8017EA6C(s32 p) { } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_8017EBE8); +/* func_8017EBE8 (ov_SC06_022, ov_SC06_022_jr_8017BEBC) — match_one MATCH 252/252. + * + * Three levers, all byte-proven here (closeness 97 -> 9 -> 0 in three compiles): + * + * 1) THE ±d ARM PAIR MUST STORE FROM THE JOIN BLOCK, NOT FROM BOTH ARMS. + * Writing `if (rand()&1) *(s16*)(o+0xE)=v+d; else *(s16*)(o+0xE)=v-d;` leaves the `sh` + * at the bottom of each arm; cross_jump merges them (§193-C) so the arms LOOK right, but + * the merged `sh` then sits in the join block ALONE, ahead of the next statement's + * `lhu $v0,0xA($s2)`, and sched1 cannot hoist that load over a store it has a WAR on -> + * a load-delay `nop` and LENGTH-DRIFT +1. Assigning a temp in both arms and storing ONCE + * after the join puts the `sh` and the `lhu` in one basic block, where sched1 issues + * `lhu $v0,0xA` BEFORE `sh $v1,0xE` and fills the delay for free (idx 166-170). + * + * 2) EACH ±d SITE NEEDS ITS OWN TEMP (w1..w4). One shared `w` is one pseudo, so local-alloc + * gives it ONE hard reg for the whole function; the loop-2 0xE site legitimately needs + * $v1 (its live range overlaps the hoisted `lhu $v0,0xA` from lever 1), and that choice + * then infected the other three sites -> REGALLOC-PERM/$v1>$v0, 9 rows. Four distinct + * locals = four independent live ranges: $v0, $v0, $v0, $v1, exactly as the target. + * + * 3) `if (p->0xE0 != 0) {...} else func_8012C218(p);` — NOT the inverted spelling. The target + * puts the func_8012C218 call LAST (`beqz $v0,.L8017EFA8` + a `j` over it), which is the + * else-arm layout; the == 0 spelling emits the call first. + * + * Field widths read straight off the loads (house style of this TU, cf. func_8017DCA4): + * RMW-by-constant fields (0xA, 0xE in the tail, 0x2, 0x34) are `u16` -> lhu/addiu/sh; + * a field read into a variable that lives across a call (0x6, 0xE in the loops) is `s16` -> lh. + * `& ~0xF` (not `& 0xFFF0`) is what materialises `addiu $v1,$zero,-0x10` + `and`. + * + * Symbols re-checked against the .s relocation lines after MATCH (law 1c): 8 rand + 2 + * func_80132EF4 + 6 rand + func_8002D4C8/func_8012BEE8/func_8012E8C4/func_8012BEE8/ + * 2x func_8012C658/func_8012E8A8/func_8012C218, in that order; both internal `j`s land on + * the epilogue at +0x3C8 (§195-D — `j` destinations are masked by match_one). + */ +extern s32 rand(void); +extern void func_8002D4C8(s32 a0, s32 a1); +extern s32 func_8012BEE8(s32 a0); +extern s32 func_80132EF4(s32 a0, s32 a1); +extern s32 func_8012C658(s32 a0, s32 a1, s32 a2); +extern void func_8012E8C4(u8 *a0); +extern void func_8012E8A8(u8 *a0); +extern void func_8012C218(void *a0); + +void func_8017EBE8(s32 p) { + s32 obj; + s32 i; + s16 n; + s32 x; + s32 y; + s32 d; + s32 v; + s32 w1; + s32 w2; + s32 w3; + s32 w4; + s32 t; + + if (*(u16 *)(p + 0x34) == 0) { + if (*(s32 *)(p + 0x1C) >= 0x1F) { + n = rand() % 4; + for (i = 0; i < n; i++) { + obj = func_80132EF4(p, 0x23); + if (obj != 0) { + x = rand(); + y = rand(); + *(u16 *)(obj + 0x34) = ((x % 0x4000 + 0x2000) & ~0xF) | (y & 1); + *(u16 *)(obj + 0xA) -= 0x70; + d = rand() % 80; + v = *(s16 *)(obj + 6); + if ((rand() & 1) != 0) { + w1 = v + d; + } else { + w1 = v - d; + } + *(s16 *)(obj + 6) = w1; + d = rand() % 144; + v = *(s16 *)(obj + 0xE); + if ((rand() & 1) != 0) { + w2 = v + d; + } else { + w2 = v - d; + } + *(s16 *)(obj + 0xE) = w2; + } + } + n = rand() % 2; + for (i = 0; i < n; i++) { + obj = func_80132EF4(p, 0x22); + if (obj != 0) { + *(u16 *)(obj + 0x34) = rand() % 0x4000 + 0x2000; + d = rand() % 80; + v = *(s16 *)(obj + 6); + if ((rand() & 1) != 0) { + w3 = v + d; + } else { + w3 = v - d; + } + *(s16 *)(obj + 6) = w3; + d = rand() % 144; + v = *(s16 *)(obj + 0xE); + if ((rand() & 1) != 0) { + w4 = v + d; + } else { + w4 = v - d; + } + *(s16 *)(obj + 0xE) = w4; + *(u16 *)(obj + 0xA) -= 0x80; + *(s32 *)(obj + 0x14) = (rand() % 3) * -0x10000; + *(u32 *)(*(s32 *)(obj + 0x20) + 4) |= 0x40000000; + } + } + func_8002D4C8(0x9D6, 0); + } + if (func_8012BEE8(p) != 0) { + *(s32 *)(p + 0x1C) = 0x20; + *(u16 *)(p + 0x34) += 1; + } + } else { + func_8012E8C4((u8 *)p); + if (func_8012BEE8(p) != 0) { + t = func_8012C658(0x32, 1, p); + if (t != 0) { + *(u16 *)(t + 0xE) += 0x30; + } + t = func_8012C658(0x33, 1, p); + if (t != 0) { + *(u16 *)(t + 0xE) -= 0x30; + } + if (*(s32 *)(p + 0xE0) != 0) { + *(u16 *)(p + 2) += 1; + func_8012E8A8((u8 *)p); + *(u16 *)(p + 0x5C) = 0; + } else { + func_8012C218((void *)p); + } + } + } +} + void func_8017EFD8(void) { } diff --git a/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c b/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c index 08f4b7439..14a6dd017 100644 --- a/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c +++ b/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c @@ -4019,7 +4019,152 @@ void func_8017DBFC(s32 arg0) } -INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_8017BEBC", func_8017E1F0); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_80128D60(s32 a0, s32 *a1, s32 *a2); +extern s32 func_80128DB4(s32 a0, s32 *a1); +extern s32 func_8012BEE8(s32 a0); +extern void func_8012EC04(s32 a0, s32 a1, s32 *a2); +extern void func_8012F14C(s32 a0, s32 a1, s32 a2); +extern s32 func_8012C51C(void *a0, s32 a1); +extern s32 func_80132EF4(s32 a0, s32 a1); +extern s32 func_8012B608(s32 a0, s32 a1, s32 a2); +extern s32 rand(void); + +extern s32 D_801E1120[]; +extern s32 D_80193338; +extern s16 D_80193448[]; +extern u8 D_80193530[]; +extern s32 D_801E111C; +extern s32 D_801E1158; + +void func_8017E1F0(s32 param_) +{ + register s32 s1 __asm__("$17"); + register s32 ent __asm__("$16"); + register s32 i __asm__("$18"); + s32 k; + struct { + s16 m[16]; + s16 out[4]; + s16 ax, ay, az; + s16 w03; + s16 idx; + s16 f06; + s16 f07; + s16 f08; + s32 f09; + } frm; + s32 *pp; + s16 *cp; + s32 cnt; + s32 rnd; + s32 cur; + s32 ret; + s32 idx; + s32 tbl; + s32 tmp; + + s1 = param_; + switch (*(u16 *)(s1 + 0x34)) { + case 0: + *(s32 *)(s1 + 0x1C) = 0; + *(u16 *)(s1 + 0x34) = *(u16 *)(s1 + 0x34) + 1; + func_80128D60(0, D_801E1120, &D_80193338); + break; + case 1: + if (func_8012BEE8(s1) != 0) { + func_8002D4C8(0x956, 0); + *(u16 *)(s1 + 0x34) = *(u16 *)(s1 + 0x34) + 1; + } + break; + case 2: + pp = *(s32 **)(s1 + 0x20); + pp = (s32 *)*(s32 *)((s32)pp + 0x20); + i = 3; + cp = (s16 *)pp + 6; + do { + cp[3] = *(u16 *)(s1 + 0xFE); + cp += 6; + } while (--i >= 0); + *(u16 *)(s1 + 0xFE) = *(u16 *)(s1 + 0xFE) + 0x1E; + if (*(s16 *)(s1 + 0xFE) < 0x385) { + break; + } + *(u16 *)(s1 + 0xFE) = 900; + *(s32 *)(s1 + 0x1C) = 0; + *(s32 *)(s1 + 0xE0) = 0; + *(u16 *)(s1 + 0x34) = *(u16 *)(s1 + 0x34) + 1; + func_8002D4C8(4, 0x956); + func_8002D4C8(0x957, 0); + break; + case 3: + if (func_8012BEE8(s1) == 0) { + break; + } + tmp = D_801E1158; + frm.w03 = 0x2D5; + frm.f06 = 0; + frm.f09 = 0; + frm.f08 = 0; + frm.f07 = 0x7FFF; + *(u16 *)(s1 + 0x108) = 0; + func_8012EC04(s1, tmp, (s32 *)frm.m); + k = 0; + while (k < 4) { + func_8012F14C((s32)frm.m, (s32)&D_80193448[k * 4], (s32)frm.out); + frm.idx = k; + frm.ax = frm.out[0]; + frm.ay = frm.out[1]; + frm.az = frm.out[2]; + func_8012C51C(&frm.ax, s1); + ent = func_80132EF4(s1, 0x22); + if (ent != 0) { + *(u16 *)(ent + 0x34) = rand() & 1 | 0x2000; + *(u16 *)(*(s32 *)(ent + 0x20) + 0x2C) = 0xC006U; + frm.out[1] = frm.out[1] - 0x20; + *(s16 *)(ent + 6) = frm.out[0]; + *(s16 *)(ent + 0xA) = frm.out[1]; + *(s16 *)(ent + 0xE) = frm.out[2]; + } + k++; + } + func_8002D4C8(0x953, 0); + cnt = *(s32 *)(s1 + 0xE0) + 1; + *(s32 *)(s1 + 0xE0) = cnt; + if (cnt < 2) { + rnd = rand(); + cur = *(s16 *)(*(s32 *)(s1 + 0x20) + 0x12); + idx = rnd % 4; + tbl = cur + *(s16 *)&D_80193530[idx * 2]; + *(u16 *)(s1 + 0x34) = 5; + *(s32 *)(s1 + 0x1C) = 0x1E; + D_801E111C = tbl; + } else { + *(s32 *)(s1 + 0x1C) = 0; + *(u16 *)(s1 + 0x34) = *(u16 *)(s1 + 0x34) + 1; + } + break; + case 4: + if (func_8012BEE8(s1) != 0) { + *(u16 *)(s1 + 2) = 4; + *(u16 *)(s1 + 0x34) = 0; + func_8002D4C8(0x958, 0); + } + break; + case 5: + if (func_8012BEE8(s1) != 0) { + ret = func_8012B608(*(s16 *)(*(s32 *)(s1 + 0x20) + 0x12), D_801E111C, 8); + *(u16 *)(*(s32 *)(s1 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(s1 + 0x20) + 0x12) + ret; + if (ret == 0) { + *(u16 *)(s1 + 0x34) = 3; + } + } + break; + } + func_80128DB4(0, D_801E1120); +} + extern s32 func_80128DB4(s32, s32 *); extern void func_80128D60(s32, s32 *, s32 *); diff --git a/src/ov_SC06_030/ov_SC06_030_jr_8017C8D0.c b/src/ov_SC06_030/ov_SC06_030_jr_8017C8D0.c index 5afbed82f..9ea79d2e6 100644 --- a/src/ov_SC06_030/ov_SC06_030_jr_8017C8D0.c +++ b/src/ov_SC06_030/ov_SC06_030_jr_8017C8D0.c @@ -3986,4 +3986,146 @@ void func_8017F0A0(s32 a0) { } -INCLUDE_ASM("asm/ov_SC06_030/nonmatchings/ov_SC06_030_jr_8017C8D0", func_8017F268); +extern void func_8012A828(s32 a0, void *a1); +extern void func_8004914C(void *a0); +extern void func_800491AC(void *a0); +extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); +extern void func_8002D4C8(s32 a0, s32 a1); +extern s32 rand(void); +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern s32 func_80047D3C(s32 a0); +extern s32 func_8012BA10(s32 a0, s32 a1); +extern s32 func_8012BD14(s32 a0); +extern s32 func_8012B8A4(s32 a0); +extern s32 func_8012D624(s32 a0, s32 a1, s32 a2); +extern s32 func_80143C74(s32 a0, s32 a1); +extern s32 func_8012C658(s32 a0, s32 a1, s32 a2); +extern void func_80128EA8(s32 a0, s32 a1, s32 a2); + +extern u8 D_800AF648; +extern u8 D_8019F06C; +extern u8 D_8019EC8C; +extern u8 D_80185AC8; +extern s16 D_80185D62; +extern u16 D_80126B96; +extern s16 D_80126B9A; + +/* the repeated RTP + positional-sound block (cookbook §88a: LONGHAND, never factored) */ +#define RTP_SND(sndid) \ + L.v[0] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x48); \ + L.v[1] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4C); \ + L.v[2] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x50); \ + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_8004914C(r4); } \ + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_800491AC(r4); } \ + RotTransPers((s32)L.v, (s32)L.sxy, &L.z, &L.flag); \ + if (L.flag >= 0 && (u32)((L.sxy[0] + 0x9F) & 0xFFFF) < 0x13F \ + && (u32)((L.sxy[1] + 0x77) & 0xFFFF) < 0xEF) { \ + s32 vol = ((s16)L.sxy[0] * 0x80 + 0x5000) / 320; \ + if (vol < 0) { \ + vol = 0; \ + } \ + if (vol >= 0x80) { \ + vol = 0x7F; \ + } \ + func_8002D4C8(sndid, (vol | 0x2000) & 0xFFFF); \ + } + +/* the cross-jumped suffix shared by case 1 and case 3 -- written LONGHAND in both */ +#define CHK_TAIL \ + if (func_8012D624(a0, 0x48, 0x50) != 0) { \ + D_80126B96 = 0x4004; \ + D_80126B9A = func_8012B8A4(a0); \ + } + +void func_8017F268(s32 a0) { + s32 t; + struct { + s16 v[3]; /* sp+0x10 */ + s16 pad0; /* sp+0x16 */ + u16 sxy[2]; /* sp+0x18 */ + s32 z; /* sp+0x1C */ + s32 flag; /* sp+0x20 */ + s32 unused; /* sp+0x24 -- frame padding, vars must be 0x18 */ + } L; + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + func_8012A828(a0, &D_8019F06C); + *(s16 *)(a0 + 0x34) = 1; + func_8002D4C8(0xA8A, 0); + RTP_SND(0x93F) + break; + + case 1: + if (*(s32 *)(a0 + 0x94) >= 0x2C) { + D_80185D62 = 0x20; + func_8002D4C8(0xA8B, 0); + *(s16 *)(a0 + 0x34) = 2; + break; + } + CHK_TAIL + break; + + case 2: + if (*(s32 *)(a0 + 0x94) < 0x31) { + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + func_8012BA10(a0, 2); + break; + } + t = func_8012BD14(a0); + if (t <= 0xFFFF) { + *(s16 *)(a0 + 0x34) = 4; + break; + } + t = func_80047D3C(t) - 0x100; + if (t < 0) { + t = 0; + } + *(s32 *)(a0 + 0x10) = + func_8004787C(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12)) * t * 4; + *(s32 *)(a0 + 0x18) = + func_80047948(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12)) * t * 4; + *(s16 *)(a0 + 0x34) = 3; + *(s32 *)(a0 + 0x1C) = 0x10; + *(s32 *)(a0 + 0x44) = *(s32 *)(a0 + 0x10) >> 4; + *(s32 *)(a0 + 0x4C) = *(s32 *)(a0 + 0x18) >> 4; + func_8002D4C8(0xC65, 0); + break; + + case 3: + *(s32 *)(a0 + 0x04) = *(s32 *)(a0 + 0x04) - *(s32 *)(a0 + 0x10); + *(s32 *)(a0 + 0x10) = *(s32 *)(a0 + 0x10) - *(s32 *)(a0 + 0x44); + *(s32 *)(a0 + 0x0C) = *(s32 *)(a0 + 0x0C) - *(s32 *)(a0 + 0x18); + *(s32 *)(a0 + 0x18) = *(s32 *)(a0 + 0x18) - *(s32 *)(a0 + 0x4C); + t = func_80143C74(a0, 0); + if (t != 0) { + s32 q; + *(s32 *)(t + 0x18) = *(s32 *)(a0 + 0x18); + *(s16 *)(t + 0x16) = -((rand() & 3) + 4); + *(s32 *)(t + 0x10) = *(s32 *)(a0 + 0x10); + q = *(s32 *)(t + 0xCC); + *(s16 *)(q + 0x1A) = 0x6000; + *(s16 *)(q + 0x18) = 0x6000; + func_80128EA8(q, t + 0xD0, (s32)&D_80185AC8); + } + if (--*(s32 *)(a0 + 0x1C) == 0) { + *(s16 *)(a0 + 0x34) = 4; + func_8002D4C8(0x93F, 0); + } + CHK_TAIL + break; + + case 4: + func_8012C658(0x3DD, 0, a0); + if (*(s16 *)(a0 + 0x98) == 0) { + *(s16 *)(a0 + 2) = 2; + *(s32 *)(a0 + 0x1C) = 0x1E; + *(s16 *)(a0 + 0xFC) = 0; + func_8012A828(a0, &D_8019EC8C); + D_80185D62 = -0x50; + } + break; + } +} + diff --git a/src/ov_SC06_030/ov_SC06_030_jr_8017F65C.c b/src/ov_SC06_030/ov_SC06_030_jr_8017F65C.c index 211ee9ab9..c27eae554 100644 --- a/src/ov_SC06_030/ov_SC06_030_jr_8017F65C.c +++ b/src/ov_SC06_030/ov_SC06_030_jr_8017F65C.c @@ -3943,7 +3943,166 @@ s32 param_1; } -INCLUDE_ASM("asm/ov_SC06_030/nonmatchings/ov_SC06_030_jr_8017F65C", func_80181164); +#include "common.h" + +#define gte_SetRotMatrix_80181164(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +#define gte_SetTransMatrix_80181164(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +/* §202 DEF-SIDE ALIAS: this TU declares `extern void func_80181164(void);` + * at :4223 for its live caller func_80181DD4 (:4226). The target's asm + * proves an incoming $a0 (`lw $v0, 0x20($a0)` at 0x80181188), so a + * `(void)` definition is a `conflicting types` cc1 error. Define under the + * C identifier aF80181164 with __asm__("func_80181164"): the identifiers + * never collide, the emitted symbol is unchanged, and the body stays the + * byte-verified one (match_one MATCH, 265/265). */ +void aF80181164(void *a0) __asm__("func_80181164"); + +void aF80181164(void *a0) +{ + extern u8 D_801B4CA4[]; + extern u32 D_801B4CAC[]; + extern u8 D_801B4CB8[]; + extern u8 D_801B4CB9[]; + extern u8 D_801B4CBA[]; + extern u8 D_801B4CBB[]; + extern u8 D_801B4CC8[]; + extern u8 D_801B4CC9[]; + extern u8 D_801B4CCA[]; + extern u8 D_801B4CCB[]; + extern u8 D_801B4CD8[]; + extern u8 D_801B4CD9[]; + extern u8 D_801B4CDA[]; + extern u8 D_801B4CDB[]; + extern void *func_80010A08(s32); + extern s32 func_8005A600(s32, s32, s32, s32, s32); + extern s32 GetTPage(s32, s32, s32, s32); + extern s32 AddPrim(s32, void *); + extern void func_8004914C(void *a0); + extern void func_800491AC(void *a0); + extern void RotTransSV(void *a0, void *a1, void *a2); + extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); + extern s32 D_800A651C; + extern s16 D_800B9A02; + extern u8 D_800AF648; + extern s32 D_80126950; + + s32 tags[4]; /* sp+0x18 */ + s16 sv[4]; /* sp+0x28 */ + s16 xs[8]; /* sp+0x30 */ + s16 ys[8]; /* sp+0x40 */ + struct { + s32 flag; /* sp+0x50 */ + u16 sxy[2]; /* sp+0x54 */ + s32 pz; /* sp+0x58 */ + } o; + + s32 m; + void *pv; + s32 *pflag; + s32 ret; + s32 d; + s32 e; + s32 x; + s32 y; + s32 ot; + u8 *prim; + u8 *pp; + u8 *base; + u32 *pal; + s32 i; + s32 k; + + m = *(s32 *)((s32)a0 + 0x20) + 0x34; + gte_SetRotMatrix_80181164(m); + gte_SetTransMatrix_80181164(m); + + pv = (void *)sv; + pflag = &o.flag; + RotTransSV(D_801B4CA4, pv, pflag); + func_8004914C(&D_800AF648); + func_800491AC(&D_800AF648); + ret = RotTransPers((s32)pv, (s32)o.sxy, &o.pz, pflag); + if ((ret > 0) && (o.flag >= 0)) { + ret = ret * 4; + d = ((D_80126950 + 0x1F4) * 48) / ret; + x = o.sxy[0]; + y = o.sxy[1]; + ot = *(s32 *)((s8 *)&D_800A651C + ((u16)D_800B9A02 * 0x14)) + ret; + e = (d * 179) >> 8; + + xs[2] = x; + ys[2] = y; + xs[0] = x - d; + xs[1] = x - e; + xs[3] = x + e; + xs[4] = x + d; + ys[0] = y - d; + ys[1] = y - e; + ys[3] = y + e; + ys[4] = y + d; + + prim = (u8 *)func_80010A08(0x9C); + if (prim != 0) { + s32 tp; + tp = GetTPage(0, 1, 0, 0); + func_8005A600((s32)prim, 0, 0, (u16)tp, 0); + + tags[0] = (s32)(prim + 0xC); + pp = prim + 0xC; + pal = D_801B4CAC; + base = (u8 *)tags; + k = 0; + tags[1] = (s32)(prim + 0x30); + tags[2] = (s32)(prim + 0x54); + tags[3] = (s32)(prim + 0x78); + do { + i = k * 4; + *(u32 *)(pp + 0x04) = pal[D_801B4CD8[i]]; + *(u32 *)(pp + 0x0C) = pal[D_801B4CD9[i]]; + *(u32 *)(pp + 0x14) = pal[D_801B4CDA[i]]; + *(u32 *)(pp + 0x1C) = pal[D_801B4CDB[i]]; + *(u8 *)(pp + 0x03) = 8; + *(u8 *)(pp + 0x07) = 0x3A; + *(u16 *)(pp + 0x08) = *(u16 *)(base + 0x18 + D_801B4CB8[i] * 2); + *(u16 *)(pp + 0x10) = *(u16 *)(base + 0x18 + D_801B4CB9[i] * 2); + *(u16 *)(pp + 0x18) = *(u16 *)(base + 0x18 + D_801B4CBA[i] * 2); + *(u16 *)(pp + 0x20) = *(u16 *)(base + 0x18 + D_801B4CBB[i] * 2); + *(u16 *)(pp + 0x0A) = *(u16 *)(base + 0x28 + D_801B4CC8[i] * 2); + *(u16 *)(pp + 0x12) = *(u16 *)(base + 0x28 + D_801B4CC9[i] * 2); + *(u16 *)(pp + 0x1A) = *(u16 *)(base + 0x28 + D_801B4CCA[i] * 2); + *(u16 *)(pp + 0x22) = *(u16 *)(base + 0x28 + D_801B4CCB[i] * 2); + AddPrim(ot, pp); + k += 1; + pp += 0x24; + } while (k < 4); + AddPrim(ot, prim); + } + } +} +