diff --git a/src/ov_SC01_077/ov_SC01_077_jr_80183CF4.c b/src/ov_SC01_077/ov_SC01_077_jr_80183CF4.c index 6a846afa5..78dacb3b1 100644 --- a/src/ov_SC01_077/ov_SC01_077_jr_80183CF4.c +++ b/src/ov_SC01_077/ov_SC01_077_jr_80183CF4.c @@ -4230,7 +4230,106 @@ INCLUDE_ASM("asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_80183CF4", func_80185BA INCLUDE_ASM("asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_80183CF4", func_80185E68); -INCLUDE_ASM("asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_80183CF4", func_80186078); +extern void func_8012A828(s32 a0, void * a1); +extern s32 func_8012BEE8(s32 a0); +extern void func_8012C218(void *a0); +extern s32 func_8012C588(s32 a0, s32 a1); +extern void func_8012F214(s32 a0, s32 a1, s32 a2); +extern void func_80186330(void *arg0); +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_C59C_80186078; + +void func_80186078(s32 arg0) { + + extern s32 D_801DA988; + extern s16 D_801DA98A[]; + extern s32 D_801DA98C; + extern s16 D_801DA98E[]; + extern s32 D_801DA990; + extern s16 D_801DA992[]; + extern s32 D_801D55AC[]; + extern u8 D_801D5568; + extern u8 D_801D5558; + + u16 in[4]; /* sp+0x10 */ + u16 out[4]; /* sp+0x18 */ + s32 *p1; + s32 *p2; + s32 *p3; + s32 t; + s32 o; + s32 base; + s32 idx; + u16 *dst; + + *(s32 *)(*(s32 *)(arg0 + 0x20) + 0x48) = *(s16 *)(arg0 + 0xDC); + *(s32 *)(*(s32 *)(arg0 + 0x20) + 0x50) = *(s16 *)(arg0 + 0xDE); + in[0] = (*(s32 *)(arg0 + 0x1C) & 1) << 2; + in[2] = 0; + in[1] = 0; + func_8012F214(arg0, (s32)&in[0], (s32)&out[0]); + + *(u16 *)(arg0 + 6) = out[0]; + *(u16 *)(arg0 + 0xE) = out[2]; + *(s16 *)(arg0 + 0x98) = 0; + base = *(s32 *)(*(s32 *)(arg0 + 0x90)); + idx = *(s16 *)(arg0 + 0xFC); + *(s32 *)(arg0 + 0x10) += *(s32 *)(arg0 + 0x44); + *(s32 *)(arg0 + 0x14) += *(s32 *)(arg0 + 0x48); + *(s32 *)(arg0 + 0x18) += *(s32 *)(arg0 + 0x4C); + + p1 = &D_801DA988; + *p1 += *(s32 *)(arg0 + 0x10); + p2 = &D_801DA98C; + *p2 += *(s32 *)(arg0 + 0x14); + p3 = &D_801DA990; + *p3 += *(s32 *)(arg0 + 0x18); + + dst = (u16 *)(base + idx * 12); + dst[0] = *(u16 *)D_801DA98A - in[0]; + dst[1] = *(u16 *)D_801DA98E; + dst[2] = *(u16 *)D_801DA992 - in[2]; + + if (*(s32 *)(arg0 + 0x1C) >= 0xB) { + o = func_8012C588(0x24, arg0); + if (o != 0) { + in[0] = dst[0]; + in[1] = dst[1]; + in[2] = dst[2]; + func_8012F214(arg0, (s32)&in[0], (s32)&out[0]); + *(u16 *)(o + 6) = out[0]; + *(u16 *)(o + 0xA) = out[1]; + *(u16 *)(o + 0xE) = out[2]; + } + } + + if (func_8012BEE8(arg0) != 0) { + if (*(s16 *)(arg0 + 0x76) <= 0) { + if (*(s16 *)(arg0 + 0x70) == 4) { + func_8012C218((void *)arg0); + } else { + func_80186330((void *)arg0); + } + } else { + ((void (*)(s32, s32))func_8012A828)(arg0, D_801D55AC[*(s16 *)(arg0 + 0x76)]); + *(s16 *)(arg0 + 2) = 1; + if (*(s16 *)(arg0 + 0x70) == 4) { + *(s32 *)(arg0 + 0x58) = (s32)&D_801D5568; + } else { + *(s32 *)(arg0 + 0x58) = (s32)&D_801D5558; + } + *(u32 *)(arg0 + 0x58) |= 0x60000000; + t = *(s32 *)(arg0 + 0x20); + *(u16 *)(t + 0x1C) = 0x1C00; + *(u16 *)(t + 0x1A) = 0x1C00; + *(u16 *)(t + 0x18) = 0x1C00; + *(u16 *)(arg0 + 0x5E) = 0; + *(u16 *)(arg0 + 0x5C) |= 0x8800; + *(u16 *)(arg0 + 6) = *(u16 *)(arg0 + 0xDC); + *(u16 *)(arg0 + 0xE) = *(u16 *)(arg0 + 0xDE); + } + } +} + extern void func_8001C214(s32 a0, s32 a1); extern void func_8012A828(s32 a0, void *a1); @@ -4350,7 +4449,81 @@ void func_80186574(int param_1) } } -INCLUDE_ASM("asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_80183CF4", func_801865EC); +typedef struct { s16 vx, vy; } DVEC2_C59C_801865EC; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C59C_801865EC; +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_801865EC; + +/* Declarations copied verbatim from src/ov_SC01_080/ov_SC01_080_jr_8017AE2C.c (law 2) */ +extern s32 rand(void); +extern void func_8012C1B8(void); +extern void func_8012CAE4(void *a0); +extern void func_8001C214(s32 a0, s32 a1); +extern void func_8012A828(s32 a0, void *a1); + +/* new to this TU */ +extern void func_8012B21C(void *a0); + +void func_801865EC(s32 arg0) { + + extern s32 D_801D5638[]; + s32 ret; + s32 obj; + s32 base; + s32 ang; + s32 v; + + ret = ((s32 (*)(void))func_8012C1B8)(); + *(s32 *)(arg0 + 0x20) = ret; + if (ret == 0) { + func_8012CAE4((void *)arg0); + } else { + func_8001C214(*(s32 *)(arg0 + 0x20), D_801D5638[rand() % 3]); + if (*(s16 *)(arg0 + 0x70) != 0) { + s32 addr = arg0 + 0x24; + ang = -*(s16 *)(arg0 + 0xE); + base = ang + 0x400; + *(s16 *)(arg0 + 0x2A) = -2; + *(s16 *)(arg0 + 0x24) = base * 48 / 2048; + *(s16 *)(arg0 + 0x26) = base * 96 / 2048; + *(s16 *)(arg0 + 0x28) = base / 64; + obj = *(s32 *)(arg0 + 0x20); + *(u16 *)(obj + 0x2C) = *(u16 *)(obj + 0x2C) | 0x80; + *(s32 *)(*(s32 *)(arg0 + 0x20) + 0x80) = addr; + } + obj = *(s32 *)(arg0 + 0x20); + *(u16 *)(obj + 0x2C) = *(u16 *)(obj + 0x2C) | 0x10; + obj = *(s32 *)(arg0 + 0x20); + *(u16 *)(obj + 0x1C) = 0x2000; + *(u16 *)(obj + 0x1A) = 0x2000; + *(u16 *)(obj + 0x18) = 0x2000; + func_8012A828(arg0, &D_80186E48); + *(s16 *)(arg0 + 2) = 1; + func_8012B21C((void *)arg0); + *(s32 *)(arg0 + 0x48) = 0x18000; + v = rand() << 4; + if ((rand() & 1) == 0) { + v = -v; + } + *(s32 *)(arg0 + 0x10) = v; + v = rand() << 4; + if ((rand() & 1) == 0) { + v = -v; + } + *(s32 *)(arg0 + 0x18) = v; + if (*(s16 *)(arg0 + 0x70) == 0) { + *(s32 *)(arg0 + 0x14) = -(rand() << 4); + } else { + *(s32 *)(arg0 + 0x14) = -0x80000 - (rand() << 5); + } + *(s32 *)(arg0 + 0x1C) = 0x32; + } +} + // @class: struct // @stuck: none — MATCH expected (fn-pointer-table dispatch, lhu+2 index, %lo-folded lw) diff --git a/src/ov_SC02_031/ov_SC02_031_jr_8017AE2C.c b/src/ov_SC02_031/ov_SC02_031_jr_8017AE2C.c index 34e75477f..dd4463fad 100644 --- a/src/ov_SC02_031/ov_SC02_031_jr_8017AE2C.c +++ b/src/ov_SC02_031/ov_SC02_031_jr_8017AE2C.c @@ -6826,7 +6826,86 @@ extern s32 func_800D0CE0(void); } -INCLUDE_ASM("asm/ov_SC02_031/nonmatchings/ov_SC02_031_jr_8017AE2C", func_80183BB0); + +extern u8 *func_8012913C(s32 a0); +extern void func_8012B0B4(unsigned int *param_1, int param_2, int param_3); +extern s32 rand(void); + +/* Per-frame emitter: every 8th tick spawn one type-0x6C particle at a random + * polar offset around the owner, with two randomized 16.16 velocities and a + * randomized downward gravity term. + * + * Matching notes (S54 wave V, second pass): + * - The two `rand() % 4` magnitudes are written HAND-EXPANDED (copy / +3 / + * sra 2 / sll 2 / subu) instead of with the `%` operator. With `%`, + * expand_divmod's own t1 = copy_to_mode_reg(op0) dies BEFORE op0 (the + * `subu` is op0's last use), so cse's make_regs_eqv leaves op0 canonical + * and the compare reads $v0 -- freeing reorg to put the copy in the branch + * delay slot. Writing `m = (rand() % 4) << 16;` in C gives that same RTL + * but allocates the chain to $v0/$v1 and costs a duplicated `sra` in the + * delay slot (+1 insn per block, 119 vs 117). Spelling the chain out with + * a temp `n` whose last use is the SAME insn as `q`'s reproduces the + * canonicalization (`bgez $v0`, `addiu $s0,$v0,3`) and the filled slot. + * - `n` is pinned to $s0: it crosses no call, so global_alloc's find_reg + * hands it the lowest already-used free reg ($v1); the target reuses $s0 + * (which `m` owns and which `n` does not conflict with). Cookbook §17. + * - The `ent+0x2C = a0` store must come AFTER the `ent+0x14` store: it + * lengthens a0's live range just enough to drop its allocno_compare + * priority below `ent`'s, which is what puts a0 in $s2 and ent in $s1. + */ +void func_80183BB0(s32 a0) { + s32 p; + s32 ent; + s32 t; + s32 m; + s32 q; + register s32 n __asm__("$16"); + unsigned int sp10; + + p = *(s32 *)(a0 + 0x20); /* owner's actor */ + *(u16 *)(p + 0x14) = *(u16 *)(p + 0x14) + 0x200; + + *(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) + 1; /* tick counter */ + if ((*(s32 *)(a0 + 0x1C) & 7) != 0) { + return; + } + ent = (s32)func_8012913C(0x6C); /* alloc particle */ + if (ent == 0) { + return; + } + /* polar scatter: angle in [0,0x1000), radius in [0, actor_r*3/512) */ + func_8012B0B4(&sp10, rand() % 0x1000, + rand() % ((*(s16 *)(*(s32 *)(a0 + 0x20) + 0x18) * 3) >> 9)); + t = (s32)sp10; /* packed dx (lo16) / dz (hi16) */ + *(u16 *)(ent + 6) = *(u16 *)(a0 + 6) + t; /* X */ + *(u16 *)(ent + 0xA) = *(u16 *)(a0 + 0xA); /* Y */ + *(u16 *)(ent + 0xE) = *(u16 *)(a0 + 0xE) + (t >> 16); /* Z */ + + /* vel X = +/- (rand() % 4) << 16 */ + q = rand(); + n = q; + if (q < 0) n = q + 3; + n = n >> 2; + n = n << 2; + m = (q - n) << 16; + if ((rand() & 1) == 0) m = -m; + *(s32 *)(ent + 0x10) = m; + + /* vel Z = +/- (rand() % 4) << 16 */ + q = rand(); + n = q; + if (q < 0) n = q + 3; + n = n >> 2; + n = n << 2; + m = (q - n) << 16; + if ((rand() & 1) == 0) m = -m; + *(s32 *)(ent + 0x18) = m; + + /* vel Y = (-12 - rand() % 9) << 16 (0x38E38E39 magic /9) */ + *(s32 *)(ent + 0x14) = -0xC0000 - ((rand() % 9) << 16); + *(s32 *)(ent + 0x2C) = a0; /* owner backref */ +} + extern void (*D_80189420[])(void); @@ -6836,7 +6915,105 @@ void func_80183D84(void *a0) { } -INCLUDE_ASM("asm/ov_SC02_031/nonmatchings/ov_SC02_031_jr_8017AE2C", func_80183DC0); +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_80183DC0; +extern void func_8012931C(struct vec *a0); +extern void func_801292C8(u8 *a0); +extern void func_8012EFB8(s32 a0); /* TU spelling (line 329) — cast at use */ +extern s32 rand(void); + +void func_80183DC0(void *a0) { + u16 in3[3]; /* 0x10 */ + s16 out2[2]; /* 0x18 */ + struct { s32 vx, vy, vz, pad; } d; /* 0x20 — same body as the TU's LVec1CDC, + * left ANONYMOUS so banking cannot collide + * with engine_types.h's typedef (§183.1/law 8) */ + s32 v; + void *tgt = *(void **)((s32)a0 + 0x2C); + + d.vx = *(s16 *)((s32)a0 + 0x6) - *(s16 *)((s32)tgt + 0x6); + d.vy = 0; + d.vz = *(s16 *)((s32)a0 + 0xE) - *(s16 *)((s32)tgt + 0xE); + /* The target INLINES the GTE square (lwc2 IR1..IR3 / sqr 0 / swc2 MAC1..MAC3) + * off ONE base register instead of calling Square0 — same idiom already used + * in src/ov_SC03_099/ov_SC03_099_jr_8012ACE0.c:2737. */ + { + s32 *p = &d.vx; + __asm__ __volatile__( + "lwc2 $9, 0(%0)\n" + "lwc2 $10, 4(%0)\n" + "lwc2 $11, 8(%0)\n" + "nop\n" + "nop\n" + "sqr 0\n" + : : "r"(p) : "$9", "$10", "$11", "memory"); + __asm__ __volatile__( + "swc2 $25, 0(%0)\n" + "swc2 $26, 4(%0)\n" + "swc2 $27, 8(%0)\n" + : : "r"(p) : "memory"); + } + + if (*(s16 *)((s32)a0 + 0x36) == 0) { + /* the pointer is re-loaded per statement: each `sh` kills the CSE + * of `*(s32 *)(a0+0x20)` (§193-E), which is why the target has three + * `lw $a0,0x20($s0)`. */ + *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x10) += *(u16 *)((s32)a0 + 0x30); + *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x12) += *(u16 *)((s32)a0 + 0x32); + *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x14) += *(u16 *)((s32)a0 + 0x34); + + if (d.vx + d.vz > 0x9000) { + *(s32 *)((s32)a0 + 0x14) = 0x18000; + *(s32 *)((s32)a0 + 0x18) = 0; + *(s32 *)((s32)a0 + 0x10) = 0; + *(u16 *)((s32)a0 + 0x36) += 1; + } + } else { + *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x10) += 0x80; + *(u16 *)(*(s32 *)((s32)a0 + 0x20) + 0x14) += 0x80; + + if (d.vx + d.vz < 0x4001) { + /* its OWN pseudo: sharing `v` with the abs() block below gives the + * merged pseudo a whole-function live range, and global_alloc then + * seats it in $a0 instead of $v0 (§186c). */ + s32 t = rand(); + *(s16 *)((s32)a0 + 0x36) = 0; + *(s32 *)((s32)a0 + 0x14) = -0x100000 - ((t % 9) << 16); + } + } + + func_8012931C((struct vec *)a0); + + in3[0] = *(u16 *)((s32)a0 + 0x6); + in3[1] = *(u16 *)((s32)a0 + 0xA); + in3[2] = *(u16 *)((s32)a0 + 0xE); + ((void (*)(u16 *, s16 *))func_8012EFB8)(in3, out2); + + /* CALL unless (|out2[0]| < 0xB5 && |out2[1]| < 0x8D && obj->y < 0x10). + * Written as a nested if with an early `return` so the call is emitted + * ONCE (a duplicated tail would need cross_jump to refund it, §193-C). */ + v = out2[0]; + if (v < 0) { + v = -v; + } + if (v < 0xB5) { + v = out2[1]; + if (v < 0) { + v = -v; + } + if (v < 0x8D) { + if (*(s16 *)((s32)a0 + 0xA) < 0x10) { + return; + } + } + } + func_801292C8((u8 *)a0); +} + extern void (*D_80189438[])(void); diff --git a/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c b/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c index 9b2e769d7..9d7967701 100644 --- a/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c +++ b/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c @@ -3515,7 +3515,50 @@ void func_8017EF48(void *a0) { } -INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_8017EF84); + +extern s32 func_8012C438(s32 a0, s32 a1); +extern void func_8012A828(s32 a0, s32 a1); +extern s32 func_8012C588(s32 a0, s32 a1); +extern void func_8001D0E8(s32 arg0, s32 arg1, s32 arg2); + +void func_8017EF84(s32 a0) { + extern u8 D_80199C90[]; + extern u8 D_8018564C[]; + extern u16 D_80199D94[]; + extern u16 D_80199D96[]; + extern u16 D_80199D98[]; + extern u16 D_80199D9A[]; + + s32 v0 = *(u16 *)(a0 + 0x70) & 0xF; + u16 flag; + + if (func_8012C438(a0, (s32)(D_80199C90 + v0 * 52)) != 0) { + func_8012A828(a0, (s32)D_8018564C); + *(u8 *)(a0 + 0x75) = 0; + *(u32 *)(*(s32 *)(a0 + 0x20) + 0x4) |= 0x8040; + + *(u16 *)(a0 + 0xFE) = D_80199D94[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x100) = D_80199D96[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x102) = D_80199D98[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x104) = D_80199D9A[*(s16 *)(a0 + 0xFC) * 4]; + func_8001D0E8(*(s32 *)(a0 + 0x20), 0x104, 0xDC); + + flag = *(u16 *)(a0 + 0x70) & 0xF0; + switch (flag) { + case 0: + *(s16 *)(a0 + 0x2) = 1; + break; + case 0x10: + *(s16 *)(a0 + 0x2) = 2; + break; + case 0x20: + *(s16 *)(a0 + 0x2) = 3; + break; + } + func_8012C588(0x1C4, a0); + } +} + // @class: struct diff --git a/src/ov_SC03_099/ov_SC03_099_jr_8017BEBC.c b/src/ov_SC03_099/ov_SC03_099_jr_8017BEBC.c index 325579853..2c95f4aa7 100644 --- a/src/ov_SC03_099/ov_SC03_099_jr_8017BEBC.c +++ b/src/ov_SC03_099/ov_SC03_099_jr_8017BEBC.c @@ -4417,7 +4417,50 @@ void func_8017F094(void *a0) { } -INCLUDE_ASM("asm/ov_SC03_099/nonmatchings/ov_SC03_099_jr_8017BEBC", func_8017F0D0); + +extern s32 func_8012C438(s32 a0, s32 a1); +extern void func_8012A828(s32*, s32); +extern s32 func_8012C588(s32 a0, s32 a1); +extern void func_8001D0E8(s32 arg0, s32 arg1, s32 arg2); + +void func_8017F0D0(s32 a0) { + extern u8 D_8019A9C8[]; + extern u8 D_8018374C[]; + extern u16 D_8019AACC[]; + extern u16 D_8019AACE[]; + extern u16 D_8019AAD0[]; + extern u16 D_8019AAD2[]; + + s32 v0 = *(u16 *)(a0 + 0x70) & 0xF; + u16 flag; + + if (func_8012C438(a0, (s32)(D_8019A9C8 + v0 * 52)) != 0) { + ((void (*)(s32, s32))func_8012A828)(a0, (s32)D_8018374C); + *(u8 *)(a0 + 0x75) = 0; + *(u32 *)(*(s32 *)(a0 + 0x20) + 0x4) |= 0x8040; + + *(u16 *)(a0 + 0xFE) = D_8019AACC[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x100) = D_8019AACE[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x102) = D_8019AAD0[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x104) = D_8019AAD2[*(s16 *)(a0 + 0xFC) * 4]; + func_8001D0E8(*(s32 *)(a0 + 0x20), 0x104, 0xDC); + + flag = *(u16 *)(a0 + 0x70) & 0xF0; + switch (flag) { + case 0: + *(s16 *)(a0 + 0x2) = 1; + break; + case 0x10: + *(s16 *)(a0 + 0x2) = 2; + break; + case 0x20: + *(s16 *)(a0 + 0x2) = 3; + break; + } + func_8012C588(0x1C4, a0); + } +} + // @class: struct diff --git a/src/ov_SC03_100/ov_SC03_100_jr_8017D898.c b/src/ov_SC03_100/ov_SC03_100_jr_8017D898.c index 2050b8907..3734b3813 100644 --- a/src/ov_SC03_100/ov_SC03_100_jr_8017D898.c +++ b/src/ov_SC03_100/ov_SC03_100_jr_8017D898.c @@ -4451,7 +4451,50 @@ void func_80180AC0(void *a0) { } -INCLUDE_ASM("asm/ov_SC03_100/nonmatchings/ov_SC03_100_jr_8017D898", func_80180AFC); + +extern s32 func_8012C438(s32 a0, s32 a1); +extern void func_8012A828(s32, void*); +extern s32 func_8012C588(s32 a0, s32 a1); +extern void func_8001D0E8(s32 arg0, s32 arg1, s32 arg2); + +void func_80180AFC(s32 a0) { + extern u8 D_801A2494[]; + extern u8 D_80184C18[]; + extern u16 D_801A2598[]; + extern u16 D_801A259A[]; + extern u16 D_801A259C[]; + extern u16 D_801A259E[]; + + s32 v0 = *(u16 *)(a0 + 0x70) & 0xF; + u16 flag; + + if (func_8012C438(a0, (s32)(D_801A2494 + v0 * 52)) != 0) { + ((void (*)(s32, s32))func_8012A828)(a0, (s32)D_80184C18); + *(u8 *)(a0 + 0x75) = 0; + *(u32 *)(*(s32 *)(a0 + 0x20) + 0x4) |= 0x8040; + + *(u16 *)(a0 + 0xFE) = D_801A2598[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x100) = D_801A259A[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x102) = D_801A259C[*(s16 *)(a0 + 0xFC) * 4]; + *(u16 *)(a0 + 0x104) = D_801A259E[*(s16 *)(a0 + 0xFC) * 4]; + func_8001D0E8(*(s32 *)(a0 + 0x20), 0x104, 0xDC); + + flag = *(u16 *)(a0 + 0x70) & 0xF0; + switch (flag) { + case 0: + *(s16 *)(a0 + 0x2) = 1; + break; + case 0x10: + *(s16 *)(a0 + 0x2) = 2; + break; + case 0x20: + *(s16 *)(a0 + 0x2) = 3; + break; + } + func_8012C588(0x1C4, 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 760e4c4ef..57257378e 100644 --- a/src/ov_SC03_108/ov_SC03_108_jr_8017BEBC.c +++ b/src/ov_SC03_108/ov_SC03_108_jr_8017BEBC.c @@ -52,7 +52,6 @@ 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); extern s32 func_80029000(void); extern s32 func_80028D9C(void); @@ -360,7 +359,6 @@ extern s32 func_801498E0(s32 *a0); extern void func_8012E5CC(s32 param_1, u16 param_2, u16 param_3); extern void func_80147364(u16 a0, s32 a1); extern s32 func_800CCF28(s32 a0); -extern u8 D_80126B5C; extern s32 func_80149954(s32 s0); extern s32 func_80149A64(s32 *a0); extern void func_8015DAC4(s32 *a0); @@ -3480,7 +3478,101 @@ void func_8017D898(int param_1) INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017D8E8); -INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017D96C); + +/* §183 SIGNATURE-cast-at-call: house style (3240 sites) is the void spelling, + * called through an (s32(*)(void)) cast. Adopted to agree with the sibling + * draft func_8017EA20 landing in the same TU. Byte-neutral (re-verified). */ +extern void func_8012C1B8(void); +extern void func_8012CAE4(void *a0); +extern void func_8001C810(s32 a0, s32 a1); +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void func_8001C2C4(s32 a0); +extern void func_8001C1E4(s32 a0, s32 a1); +extern s32 func_8012AD50(void *arg0); + + +void func_8017D96C(void *a0) +{ + + extern u8 D_8019C94C[]; + extern u8 D_8019D3AC[]; + extern u8 D_801847B0[]; + register void *s0 __asm__("$16") = a0; + s32 v0 = ((s32 (*)(void))func_8012C1B8)(); + + *(s32 *)((u8 *)s0 + 0x20) = v0; + + if (!v0) { + func_8012CAE4(s0); + } else { + s32 mode = *(u16 *)((u8 *)s0 + 0x70) & 3; + s32 v1; + s32 e; + s32 argmode; + s32 callarg0; + + *(s16 *)((u8 *)s0 + 0xFE) = mode; + v1 = mode; + __asm__("" : "=r"(v1) : "0"(v1)); + + if (v1 == 1) + goto case1; + if (v1 >= 2) + goto check4; + if (v1 == 0) + goto case0; + goto tail; + + check4: + if (v1 >= 4) + goto tail; + goto case23; + + case0: + func_8001C810(*(s32 *)((u8 *)s0 + 0x20), (s32)D_8019C94C); + callarg0 = 0x199; + e = *(s32 *)((u8 *)s0 + 0x20); + __asm__("" : "=r"(e) : "0"(e)); + argmode = 2; + goto shared; + + case1: + func_8001C810(*(s32 *)((u8 *)s0 + 0x20), (s32)D_8019D3AC); + callarg0 = 0x199; + e = *(s32 *)((u8 *)s0 + 0x20); + __asm__("" : "=r"(e) : "0"(e)); + argmode = 3; + + shared: + { + s32 t = *(s32 *)(e + 4); + t |= 0x8040; + *(s32 *)(e + 4) = t; + func_8012C658(callarg0, argmode, (s32)s0); + } + goto tail; + + case23: + func_8001C2C4(*(s32 *)((u8 *)s0 + 0x20)); + v0 = *(s32 *)((u8 *)s0 + 0x64); + func_8001C1E4(*(s32 *)((u8 *)s0 + 0x20), *(s32 *)(v0 + 0x20)); + *(s16 *)((u8 *)s0 + 0xA) = 0x90; + *(s32 *)((u8 *)s0 + 0x58) = (s32)D_801847B0 | 0x40000000; + *(s16 *)((u8 *)s0 + 0x5C) = 0x4400; + *(s16 *)((u8 *)s0 + 0x6) = 0; + *(s16 *)((u8 *)s0 + 0xE) = 0; + *(u8 *)((u8 *)s0 + 0x75) = 4; + + tail: + v0 = *(u16 *)((u8 *)s0 + 0x70) & 0xFF0; + *(s16 *)((u8 *)s0 + 0x100) = v0; + e = *(s32 *)((u8 *)s0 + 0x20); + v0 = *(s32 *)(e + 4) | 0x8000; + *(s32 *)(e + 4) = v0; + func_8012AD50(s0); + } +} + extern void (*D_801847C0[])(void); @@ -3514,7 +3606,97 @@ INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017E27 INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017E3F8); -INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017E508); +typedef struct { s32 flag; u16 xy[2]; s32 sp1c; } Out_8017E910_8017E508; +typedef struct { s16 a, b, c, d; } SV4_8017E910_8017E508; + +/* --- callees (spelled from asm/ov_SC02_039/nonmatchings/.../func_8017E508.s) --- */ +extern void func_8012C1B8(void); +extern void func_8012CAE4(void *a0); /* §183 SIGNATURE-cast-at-call: dominant spelling (3780) */ +extern void func_8001C214(s32 a0, s32 a1); +extern void func_8012B2CC(s32 a0); +extern void func_800484EC(s32 a0, s32 a1, s32 a2); +extern s32 func_8012AD50(void *a0); /* §183 SIGNATURE-cast-at-call: dominant spelling (1341+412) */ +extern s32 rand(void); + +/* --- data (raw forms, cast at use site — law 4) --- */ + +void func_8017E508(s32 param_1) { + + extern s32 D_8019DE28; /* address only: passed to func_8001C214 */ + extern u8 D_801847E8[][16]; /* stride-0x10 record table, address-of form */ + extern s32 D_801847F4[][4]; /* == D_801847E8 + 0xC : lw, stride 0x10 */ + extern s16 D_8018481A[][4]; /* stride 0x8 halfword table: lh */ + extern u8 D_80184858[]; /* address only: OR'd with two flag bits */ + s32 obj; + s32 n; + + /* §194-F: the COMBINED `*p = obj = f()` form is a store_expr pseudo SPLITTER and + * costs an extra `move $a0,$v0` in bb0. Separate statements keep ONE pseudo in + * $v0 all the way down to the func_8001C214 argument copy. */ + obj = ((s32 (*)(void))func_8012C1B8)(); + *(s32 *)(param_1 + 0x20) = obj; + if (obj == 0) { + func_8012CAE4((void *)param_1); + return; + } + func_8001C214(obj, (s32)&D_8019DE28); + + n = *(u16 *)(param_1 + 0x70) & 0xF; + *(s16 *)(param_1 + 0x102) = n; + if (n != 0) { + /* §186c: block-local => local_alloc owns it => the rand result stays in $v0 */ + s32 r = rand() & 0xFF; + s32 h = D_801847F4[*(s16 *)(param_1 + 0x102)][0]; + s32 o; + /* first CSE interval: read+write of 0x2C shares one base load */ + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x2C) = + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x2C) | 0x10; + /* the store killed the base (§193-E); second interval is named */ + o = *(s32 *)(param_1 + 0x20); + *(s16 *)(o + 0x1C) = h + r; + *(s16 *)(o + 0x1A) = h + r; + *(s16 *)(o + 0x18) = h + r; + } + + *(s32 *)(param_1 + 0x48) = 0x18000; + *(s16 *)(param_1 + 0x100) = 0x1000 / D_8018481A[*(s16 *)(param_1 + 0x102)][0]; + + { + s32 t = *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x18); + /* branch sense: target jumps to the (0x1400-t)>>4 arm, so THAT is the else */ + if (t >= 0x1000) { + *(s16 *)(param_1 + 0x100) = 0x40; + } else { + *(s16 *)(param_1 + 0x100) = (0x1400 - t) >> 4; + } + } + + /* branch sense: target `beq` jumps to the (rand&1) arm, so THAT is the else */ + if (*(s16 *)(param_1 + 0x102) != 2) { + s32 r = rand() & 0xFF; + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(*(s32 *)(param_1 + 0x64) + 0x20) + 0x12) + r - 0x80; + } else { + s32 r = rand() & 1; + *(s16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(*(s32 *)(param_1 + 0x64) + 0x20) + 0x12) + r * 0x1C0 - 0xE0; + } + + func_8012B2CC(param_1); + func_800484EC(*(s32 *)(param_1 + 0x20) + 0x34, + (s32)D_801847E8[*(s16 *)(param_1 + 0x102)], + param_1 + 0x10); + + { + s32 r = rand(); + *(s32 *)(param_1 + 0x58) = ((u32)D_80184858 | 0x20000000) | 0x40000000; + *(u16 *)(param_1 + 0x5C) = 0xC000; + *(u8 *)(param_1 + 0x75) = 0; + *(s16 *)(param_1 + 0xE) = *(u16 *)(param_1 + 0xE) - (r & 0x1F); + } + func_8012AD50((void *)param_1); +} + INCLUDE_ASM("asm/ov_SC03_108/nonmatchings/ov_SC03_108_jr_8017BEBC", func_8017E71C); diff --git a/src/ov_SC04_008/ov_SC04_008_jr_8017AE2C.c b/src/ov_SC04_008/ov_SC04_008_jr_8017AE2C.c index 75378327a..429727896 100644 --- a/src/ov_SC04_008/ov_SC04_008_jr_8017AE2C.c +++ b/src/ov_SC04_008/ov_SC04_008_jr_8017AE2C.c @@ -356,7 +356,6 @@ extern s32 func_801498E0(s32 *a0); extern void func_8012E5CC(s32 param_1, u16 param_2, u16 param_3); extern void func_80147364(u16 a0, s32 a1); extern s32 func_800CCF28(s32 a0); -extern u8 D_80126B5C; extern s32 func_80149954(s32 s0); extern s32 func_80149A64(s32 *a0); extern void func_8015DAC4(s32 *a0); @@ -4016,7 +4015,84 @@ void func_8017D740(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_008/nonmatchings/ov_SC04_008_jr_8017AE2C", func_8017D77C); + +extern void func_80015978(s32 a0, s32 *a1); +extern u8 *func_801290DC(s32 a0, u8 *a1); +extern void func_8017DCB4(s32 a0); /* slate-wide spelling (func_80184278); cast at call */ +extern void func_8012AD50(s32); +extern s32 rand(void); + +/* MATCH (82 ins, relocation-masked; all 27 relocs verified against the target .s). + * + * The whole 17-instruction entry-block residual of the first pass was ONE alias fact, + * not scheduling or regalloc: + * + * sched.c:817 true_dependence()/anti_dependence() drop the dependence between a + * MEM_IN_STRUCT_P reference at a VARYING address (non-QImode) and a non-MEM_IN_STRUCT + * reference at a FIXED address. The four D_801EB1xx stores are plain extern scalars + * (fixed SYMBOL_REF address, MEM_IN_STRUCT_P == 0), so if the a0-derived reads carry + * MEM_IN_STRUCT_P the scheduler may hoist ALL of them above ALL of the stores -- which + * is exactly the target's opening block (lh 0xFC / lh 0x70 / lw 0xDC all before the + * first store, three simultaneously-live temps in $v0/$v1/$a2, and the a1 arg setup + * free to float to the top of the block). + * + * expr.c:4567-4577 sets MEM_IN_STRUCT_P on an INDIRECT_REF only when the address + * TREE is a PLUS_EXPR. `*(s16 *)(a0 + 0x70)` is INDIRECT_REF(NOP_EXPR(PLUS_EXPR)) -- + * the NOP sits on top, so the flag is NOT set and every load stays pinned below the + * preceding store. `((s16 *)a0)[0x70/2]` is build_array_ref -> INDIRECT_REF(PLUS_EXPR) + * with the NOP inside, so the flag IS set. Identical addressing bytes, opposite + * scheduling freedom. Rewriting the three entry-block reads in the [] form took the + * residual 17 -> 4; the last 4 were the $v0/$a2 assignment of the two independent + * stores, fixed by emitting D_80193340 before D_80193344 in source order. + * + * The loads inside the loop are deliberately left in the raw `*(T *)(p + K)` form -- that + * region was already byte-identical and granting them MEM_IN_STRUCT_P would re-open it. + */ +void func_8017D77C(s32 a0) { + + extern u8 D_80126B5C; + extern s32 D_80193340; + extern s16 D_80193344; + extern s32 D_80193348; + extern s32 D_8019334C; + extern u8 D_8018253C[]; + extern u8 D_80182544[]; + extern s8 D_80191EF0; + extern s8 D_80191F3F; + + s16 buf[4]; + s32 i; + s8 *p; + u8 *obj; + + /* [] form (not *(T *)(a0 + K)) -- see the MEM_IN_STRUCT_P note above. */ + D_80193340 = ((s16 *)a0)[0xFC / 2]; + D_80193344 = ((s32 *)a0)[0xDC / 4]; + D_80193348 = (s32)(D_8018253C + ((s16 *)a0)[0x70 / 2] * 4); + D_8019334C = (s32)(D_80182544 + ((s16 *)a0)[0x70 / 2] * 8); + + func_80015978((s32)&D_80126B5C, (s32 *)buf); + buf[1] = *(u16 *)(a0 + 0xA); + + p = &D_80191F3F; + for (i = 0x4F; i >= 0; i--) { + *p = 0; + p--; + } + + for (i = 0; i < D_80193340; i++) { + obj = func_801290DC(0x61, (u8 *)buf); + if (obj != 0) { + *(&D_80191EF0 + i) = 1; + *(s32 *)(obj + 0x34) = i; + func_8017DCB4((s32)obj); + *(u16 *)(obj + 0xA) += (rand() & 0xF) * 3 * 16; + } + } + + ((s32 (*)(void *))func_8012AD50)((void *)a0); +} + INCLUDE_ASM("asm/ov_SC04_008/nonmatchings/ov_SC04_008_jr_8017AE2C", func_8017D8C4); @@ -4028,7 +4104,80 @@ void func_8017D990(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_008/nonmatchings/ov_SC04_008_jr_8017AE2C", func_8017D9CC); +typedef struct { s16 vx, vy; } DVEC2_C59C_8017D9CC; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C59C_8017D9CC; +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_8017D9CC; + +extern void func_8001CD9C(int, void *); +extern void func_800233CC(void *, unsigned short); +extern void func_8017DCB4(s32); +extern s32 rand(void); + +void func_8017D9CC(int param_1) +{ + + extern u8 D_80191F40[]; + extern s32 D_8019334C; + s32 p; + s32 idx; + s32 dst; + s32 ptr; + s32 r; + s32 v; + s32 c1, c2, c3, c4; + s32 s0v; + s32 v1a; + + p = *(s32 *)(param_1 + 0x20); + idx = *(s32 *)(param_1 + 0x34); + dst = (s32)(D_80191F40 + idx * 0x40); + + func_8001CD9C(p, (void *)dst); + func_800233CC((void *)dst, 0x10); + + r = rand(); + r = (r & 7) + 1; + *(s32 *)(dst + 0) = (r << 7) | ((r << 23) | (r << 15)); + *(s32 *)(dst + 4) = 0; + + *(s32 *)(p + 4) = *(s32 *)(p + 4) | 0x50000000; + + func_8017DCB4(param_1); + + r = rand(); + v = (r & 3) * 1365; + ptr = D_8019334C; + *(s16 *)(p + 0x1A) = v; + *(s16 *)(p + 0x18) = v; + + *(s16 *)(param_1 + 0x12) = *(u16 *)(param_1 + 6) + *(u16 *)(ptr + 2); + __asm__ __volatile__(""); + v1a = *(u16 *)(param_1 + 0xE) + *(u16 *)(ptr + 6); + *(s16 *)(param_1 + 0x10) = 0; + *(s16 *)(param_1 + 0x18) = 0; + *(s16 *)(param_1 + 0x1A) = v1a; + + c1 = rand(); + c2 = rand(); + c3 = rand(); + c4 = rand(); + + s0v = ((c1 & 3) << 10) + ((c2 & 0x1F) << 5) + ((c3 & 3) << 8) + (c4 & 0xFF); + *(s16 *)(p + 0x12) = s0v; + + r = rand(); + *(s16 *)(param_1 + 0x2E) = (r & 7) * 11; + + r = rand(); + *(s16 *)(param_1 + 0x2C) = (r & 0x1F) + 4; + *(s16 *)(param_1 + 2) = *(u16 *)(param_1 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC04_008/nonmatchings/ov_SC04_008_jr_8017AE2C", func_8017DB64); diff --git a/src/ov_SC04_012/ov_SC04_012_jr_8017AE2C.c b/src/ov_SC04_012/ov_SC04_012_jr_8017AE2C.c index 0d9f671b4..b6ec7db54 100644 --- a/src/ov_SC04_012/ov_SC04_012_jr_8017AE2C.c +++ b/src/ov_SC04_012/ov_SC04_012_jr_8017AE2C.c @@ -356,7 +356,6 @@ extern s32 func_801498E0(s32 *a0); extern void func_8012E5CC(s32 param_1, u16 param_2, u16 param_3); extern void func_80147364(u16 a0, s32 a1); extern s32 func_800CCF28(s32 a0); -extern u8 D_80126B5C; extern s32 func_80149954(s32 s0); extern s32 func_80149A64(s32 *a0); extern void func_8015DAC4(s32 *a0); @@ -4009,7 +4008,84 @@ void func_8017D960(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_012/nonmatchings/ov_SC04_012_jr_8017AE2C", func_8017D99C); + +extern void func_80015978(s32 a0, s32 *a1); +extern u8 *func_801290DC(s32 a0, u8 *a1); +extern void func_8017DED4(s32 a0); /* slate-wide spelling (func_80184278); cast at call */ +extern s32 func_8012AD50(void *a0); +extern s32 rand(void); + +/* MATCH (82 ins, relocation-masked; all 27 relocs verified against the target .s). + * + * The whole 17-instruction entry-block residual of the first pass was ONE alias fact, + * not scheduling or regalloc: + * + * sched.c:817 true_dependence()/anti_dependence() drop the dependence between a + * MEM_IN_STRUCT_P reference at a VARYING address (non-QImode) and a non-MEM_IN_STRUCT + * reference at a FIXED address. The four D_801EB1xx stores are plain extern scalars + * (fixed SYMBOL_REF address, MEM_IN_STRUCT_P == 0), so if the a0-derived reads carry + * MEM_IN_STRUCT_P the scheduler may hoist ALL of them above ALL of the stores -- which + * is exactly the target's opening block (lh 0xFC / lh 0x70 / lw 0xDC all before the + * first store, three simultaneously-live temps in $v0/$v1/$a2, and the a1 arg setup + * free to float to the top of the block). + * + * expr.c:4567-4577 sets MEM_IN_STRUCT_P on an INDIRECT_REF only when the address + * TREE is a PLUS_EXPR. `*(s16 *)(a0 + 0x70)` is INDIRECT_REF(NOP_EXPR(PLUS_EXPR)) -- + * the NOP sits on top, so the flag is NOT set and every load stays pinned below the + * preceding store. `((s16 *)a0)[0x70/2]` is build_array_ref -> INDIRECT_REF(PLUS_EXPR) + * with the NOP inside, so the flag IS set. Identical addressing bytes, opposite + * scheduling freedom. Rewriting the three entry-block reads in the [] form took the + * residual 17 -> 4; the last 4 were the $v0/$a2 assignment of the two independent + * stores, fixed by emitting D_801930C0 before D_801930C4 in source order. + * + * The loads inside the loop are deliberately left in the raw `*(T *)(p + K)` form -- that + * region was already byte-identical and granting them MEM_IN_STRUCT_P would re-open it. + */ +void func_8017D99C(s32 a0) { + + extern u8 D_80126B5C; + extern s32 D_801930C0; + extern s16 D_801930C4; + extern s32 D_801930C8; + extern s32 D_801930CC; + extern u8 D_80182290[]; + extern u8 D_80182298[]; + extern s8 D_80191C70; + extern s8 D_80191CBF; + + s16 buf[4]; + s32 i; + s8 *p; + u8 *obj; + + /* [] form (not *(T *)(a0 + K)) -- see the MEM_IN_STRUCT_P note above. */ + D_801930C0 = ((s16 *)a0)[0xFC / 2]; + D_801930C4 = ((s32 *)a0)[0xDC / 4]; + D_801930C8 = (s32)(D_80182290 + ((s16 *)a0)[0x70 / 2] * 4); + D_801930CC = (s32)(D_80182298 + ((s16 *)a0)[0x70 / 2] * 8); + + func_80015978((s32)&D_80126B5C, (s32 *)buf); + buf[1] = *(u16 *)(a0 + 0xA); + + p = &D_80191CBF; + for (i = 0x4F; i >= 0; i--) { + *p = 0; + p--; + } + + for (i = 0; i < D_801930C0; i++) { + obj = func_801290DC(0x61, (u8 *)buf); + if (obj != 0) { + *(&D_80191C70 + i) = 1; + *(s32 *)(obj + 0x34) = i; + func_8017DED4((s32)obj); + *(u16 *)(obj + 0xA) += (rand() & 0xF) * 3 * 16; + } + } + + func_8012AD50((void *)a0); +} + INCLUDE_ASM("asm/ov_SC04_012/nonmatchings/ov_SC04_012_jr_8017AE2C", func_8017DAE4); @@ -4021,7 +4097,80 @@ void func_8017DBB0(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_012/nonmatchings/ov_SC04_012_jr_8017AE2C", func_8017DBEC); +typedef struct { s16 vx, vy; } DVEC2_C59C_8017DBEC; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C59C_8017DBEC; +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_8017DBEC; + +extern void func_8001CD9C(int, void *); +extern void func_800233CC(void *, unsigned short); +extern void func_8017DED4(s32); +extern s32 rand(void); + +void func_8017DBEC(int param_1) +{ + + extern u8 D_80191CC0[]; + extern s32 D_801930CC; + s32 p; + s32 idx; + s32 dst; + s32 ptr; + s32 r; + s32 v; + s32 c1, c2, c3, c4; + s32 s0v; + s32 v1a; + + p = *(s32 *)(param_1 + 0x20); + idx = *(s32 *)(param_1 + 0x34); + dst = (s32)(D_80191CC0 + idx * 0x40); + + func_8001CD9C(p, (void *)dst); + func_800233CC((void *)dst, 0x10); + + r = rand(); + r = (r & 7) + 1; + *(s32 *)(dst + 0) = (r << 7) | ((r << 23) | (r << 15)); + *(s32 *)(dst + 4) = 0; + + *(s32 *)(p + 4) = *(s32 *)(p + 4) | 0x50000000; + + func_8017DED4(param_1); + + r = rand(); + v = (r & 3) * 1365; + ptr = D_801930CC; + *(s16 *)(p + 0x1A) = v; + *(s16 *)(p + 0x18) = v; + + *(s16 *)(param_1 + 0x12) = *(u16 *)(param_1 + 6) + *(u16 *)(ptr + 2); + __asm__ __volatile__(""); + v1a = *(u16 *)(param_1 + 0xE) + *(u16 *)(ptr + 6); + *(s16 *)(param_1 + 0x10) = 0; + *(s16 *)(param_1 + 0x18) = 0; + *(s16 *)(param_1 + 0x1A) = v1a; + + c1 = rand(); + c2 = rand(); + c3 = rand(); + c4 = rand(); + + s0v = ((c1 & 3) << 10) + ((c2 & 0x1F) << 5) + ((c3 & 3) << 8) + (c4 & 0xFF); + *(s16 *)(p + 0x12) = s0v; + + r = rand(); + *(s16 *)(param_1 + 0x2E) = (r & 7) * 11; + + r = rand(); + *(s16 *)(param_1 + 0x2C) = (r & 0x1F) + 4; + *(s16 *)(param_1 + 2) = *(u16 *)(param_1 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC04_012/nonmatchings/ov_SC04_012_jr_8017AE2C", func_8017DD84); diff --git a/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c b/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c index a7b39aad4..352600311 100644 --- a/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c +++ b/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c @@ -403,7 +403,6 @@ extern s32 func_8014C2B0(void *a0, void *a1, s32 a2); extern s32 func_8014A238(s32 arg0); extern s32 func_8014A2E4(s32 a0); extern void func_8014A380(s32 a0, s32 a1); -extern s16 D_801152B0; extern s16 D_801152B4; extern s32 func_8014A3E0(struct S_8014A3E0 *a0); extern s32 func_8014A454(s32 a0); @@ -598,7 +597,7 @@ extern s32 func_8014E284(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014E048(s32 a0, u16 *a1, u16 *a2); /* u16*: def lhu semantics (T5b reconcile; ptr param type codegen-neutral for the caller) */ extern s32 func_80135A4C(s32 a0, s32 a1, s32 *a2, s32 a3); extern s32 func_80133784(s32 a0, void *a1, s32 a2); -extern u8 D_801152A8[]; /* canonical TU type (engine_core) — read via *(u16*) cast */ +/* canonical TU type (engine_core) — read via *(u16*) cast */ extern s16 D_801152AC; extern s32 func_8014E048(s32 param_1, u16 * param_2, u16 * param_3); extern void func_8014E48C(s32 a0); @@ -614,7 +613,6 @@ extern s32 func_8014E83C(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014E934(s32 _arg0); extern s32 func_8014EA4C(void *a0, void *a1, void *a2, s32 a3); extern s32 func_8014E98C(void *a0); -extern u16 D_800B99DA; extern s32 D_801150D8; extern s16 D_801152AA; extern u8 D_80126720[]; @@ -634,7 +632,6 @@ extern s32 func_8014F468(void); extern int func_8014F74C(); extern int func_8014F6F4(void); extern u8 D_800D3918[]; -extern u8 D_801152A8[]; extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); @@ -1128,7 +1125,6 @@ extern void func_8002850C(s32, s32, s32); extern void func_80028620(s32, void *); extern s16 D_800B9AAC[]; extern s16 D_800B9B00; -extern u16 D_801270C0; extern u32 D_800AFAE8[]; extern char D_8018484C[]; extern s32 func_801596F0(s32 param_1); @@ -3711,13 +3707,70 @@ s32 func_8017F6E8(u32 a0v) INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017F794); -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017F840); + +extern s32 func_8012C354(s32 a0, s32 a1); +extern void func_8001C97C(s32 a0); +extern s32 func_8012B030(u8 *a0); +extern void func_80143994(s32 a0, s32 a1); + +void func_8017F840(void *a0) { + + extern u8 D_801A6068[]; + extern u8 D_801A6140[]; + extern s32 D_801A60D8[]; + + s16 flag; + + if (func_8012C354((s32)a0, (s32)(D_801A6068 + (*(u16 *)((s32)a0 + 0x70) & 0xF) * 0x34)) == 0) { + return; + } + + *(u8 *)((s32)a0 + 0xC0) = 1; + *(s32 *)((s32)a0 + 0xBC) = (s32)D_801A6140; + *(s32 *)((s32)a0 + 0xB4) = 0xFFFF5FFF; + *(s32 *)((s32)a0 + 0xC4) |= 3; + + func_8001C97C(D_801A60D8[*(u16 *)((s32)a0 + 0x70) & 0xF]); + + if ((*(u16 *)((s32)a0 + 0x70) & 1) != 0) { + *(s16 *)((s32)a0 + 0xAE) = -0x81; + *(u8 *)((s32)a0 + 0x75) = 2; + flag = *(s16 *)((s32)a0 + 0x70); + + if ((flag & 0x8000) != 0) { + *(s16 *)((s32)a0 + 0x2) = 6; + *(s16 *)((s32)a0 + 0x76) = 1; + return; + } + if ((flag & 0x4000) != 0) { + *(s16 *)((s32)a0 + 0x2) = 8; + *(s16 *)((s32)a0 + 0x76) = 1; + return; + } + if ((flag & 0x2000) != 0) { + *(s16 *)((s32)a0 + 0x2) = 0xA; + *(s16 *)((s32)a0 + 0x76) = 1; + } else { + *(s16 *)((s32)a0 + 0x2) = 3; + func_8012B030((u8 *)a0); + } + } else { + *(s16 *)((s32)a0 + 0xAE) = 0xC; + *(s16 *)((s32)a0 + 0x2) = 1; + } + + func_80143994((s32)a0, 0x4000); +} + extern void func_8012A828(s32 arg0, s32 arg1); -extern s32 D_801AB1CC; void func_8017F988(void *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 s32 D_801AB1CC; ((void (*)(void *, void *))func_8012A828)(arg0, &D_801AB1CC); *(s16 *)((u8 *)arg0 + 0x2) = 0x2; } @@ -3727,7 +3780,71 @@ INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017F9C INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017FA1C); -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017FABC); + +/* callee spellings adopted from the ov_SC05_003 sibling TUs / src/shared canon (law 2) */ +extern s32 func_8012B608(s32 a0, s32 a1, s32 a2); +extern void func_8012B178(s32 a0, s32 a1); +extern void func_8012CBA4(s32 a0); /* canonical void; $v0 used -> cast at use site */ +extern void func_8012ADE4(u8 *a0); +extern void func_80180F60(s32 a0); /* same-TU INCLUDE_ASM neighbour */ +extern s32 func_8012B8E4(s32 arg0, s32 arg1); +extern s32 func_8012BEE8(s32 a0); +extern s32 rand(void); + +void func_8017FABC(s32 param_1) { + extern u16 D_800B99DA; + extern s32 D_801A60D8[]; + s32 p = param_1; + s32 t; + s32 n; + s32 off; + s32 base; + s32 nv; + + /* 0x20 -> sub-object, +0x12 = u16 angle/timer */ + *(u16 *)(*(s32 *)(p + 0x20) + 0x12) += + func_8012B608(*(s16 *)(*(s32 *)(p + 0x20) + 0x12), *(s32 *)(p + 0xE0), 0xA); + func_8012B178(p, 0xFFF80000); + + if ((((s32 (*)(s32))func_8012CBA4)(p) & 0xFF00) != 0x2000) { + func_8012ADE4((u8 *)p); + n = *(s32 *)(p + 0xE8) + 1; + *(s32 *)(p + 0xE8) = n; + if (n >= 0x80) { + func_80180F60(p); + } else { + *(s32 *)(p + 0xE4) |= 1; + } + } else { + *(s32 *)(p + 0xE8) = 0; + *(s32 *)(p + 0xE4) &= ~1; + } + + t = *(s32 *)(p + 0xE4); + if (t & 2) { + *(s16 *)(p + 2) = 5; + *(s32 *)(*(s32 *)(p + 0x20) + 0x24) = D_801A60D8[*(u16 *)(p + 0x70) & 0xF]; + *(s32 *)(p + 0xE4) &= ~2; + } else if ((t & 1) == 0) { + if ((D_800B99DA & 0x3F) == 0) { + *(s32 *)(p + 0xE0) += func_8012B8E4(p, 8); + } + if (func_8012BEE8(p) == 1) { + off = rand() % 1024; + base = *(s32 *)(p + 0xE0); + if ((rand() & 1) != 0) { + nv = base + off; + } else { + nv = base - off; + } + *(s32 *)(p + 0xE0) = nv; + *(s32 *)(p + 0x1C) = rand() % 32 + 0x40; + } + } else { + *(s32 *)(p + 0xE0) += 0x21; + } +} + INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017FCA4); @@ -3742,11 +3859,169 @@ INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017FF4 INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8017FFC8); -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_80180068); + +/* func_80180068 — 4-state handler on the u16 state word at +0x34. + * Symbols spelled from asm/ov_SC05_003/nonmatchings/ov_SC05_003_jr_8017BEBC/func_80180068.s + * + * TU-adopted declarations (law 2): + * func_8012AD80 / func_8012C218 / func_80012C6C / func_80180F3C come from + * src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c verbatim; func_80180F3C is + * DEFINED there with one parameter, so its 3-arg use is a call-site cast + * (same idiom the TU already uses for ApplyMatrixSV / func_8012CBCC). + */ + +extern void func_8012AD80(struct vec *a0); +extern void func_8012C218(void *a0); +extern s32 func_80012C6C(s32 a0, s32 a1, s32 a2); +extern void func_80180F3C(void*); + +extern s32 func_801809F0(s32 a0, void *a1, s32 a2, s32 a3); +extern s32 func_80180D4C(s32 a0, void *a1, s32 a2); + +extern void func_8012B21C(void *a0); +extern void func_8012B178(s32 a0, s32 a1); +extern s32 func_8012B744(void *a0, void *a1); +extern s32 func_8012B608(s32 a0, s32 a1, s32 a2); +extern void func_8012CBA4(s32 a0); +extern void func_8012CBCC(s32 a0); +extern s32 func_80013478(s32 a0, s32 a1); /* 2nd arg is the +0xCC record: the + * copy-suggestion that puts it in $a1 + * (see the note at the use site) */ + + +void func_80180068(s32 a0) { + + extern u8 D_801A60E8[]; /* two 0x10-byte records: +0x00 and +0x10 */ + SV3_8012CC88 sp10; /* sp+0x10, 8 bytes -> 0x28 frame */ + s32 r; + + switch (*(u16 *)(a0 + 0x34)) { + case 0: + func_8012AD80((struct vec *)a0); + ((void (*)(s32, void *, void *))func_80180F3C)(a0, &D_801A60E8[0], &sp10); + func_801809F0(a0, &sp10, 1, 1); + ((void (*)(s32, void *, void *))func_80180F3C)(a0, &D_801A60E8[0x10], &sp10); + if (func_80180D4C(a0, &sp10, 1) & 0x2000) { + func_8012B21C((void *)a0); + *(u16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + } + break; + + /* case 1: the second read of *(s32 *)(a0 + 0xCC) is ALSO func_80013478's + * arg1. local-alloc's copy-suggestion then homes that pseudo in $a1 and + * deletes the redundant `move $a1,$a1`, which is why the target loads + * `lw $a1, 0xCC($s1)` and the `lh` lands in $v1 instead of reusing the base. + * Writing the call with one argument compiles to 152/152 with those exact + * two instructions in $v1 (only a `register __asm__("$5")` pin recovers it, + * and a pin would forfeit the h_seq family). */ + case 1: + if (*(s16 *)(*(s32 *)(a0 + 0xCC) + 6) != -1) { + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x10) = + func_80012C6C(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x10), 0, 8); + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) + + func_8012B608(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x12), + func_8012B744((void *)(a0 + 4), + (void *)*(s32 *)(a0 + 0xCC)), + 8); + } + func_8012B178(a0, 0xFFF80000); + r = ((s32 (*)(s32))func_8012CBA4)(a0) & 0x8000; + if (*(s16 *)(*(s32 *)(a0 + 0xCC) + 6) != -1) { + if (func_80013478(a0 + 4, *(s32 *)(a0 + 0xCC)) < 0x100) { + *(s32 *)(a0 + 0xCC) = *(s32 *)(a0 + 0xCC) + 8; + } + } else if (r != 0) { + *(u16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + } + break; + + case 2: + *(s16 *)(*(s32 *)(a0 + 0x20) + 0x10) = + func_80012C6C(*(s16 *)(*(s32 *)(a0 + 0x20) + 0x10), -0x400, 8); + func_8012B178(a0, 0xFFF80000); + func_8012CBCC(a0); + *(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) + 1; + if (*(s32 *)(a0 + 0x1C) >= 0x21) { + *(s32 *)(a0 + 0x48) = 0; + *(u16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + } + break; + + case 3: + func_8012AD80((struct vec *)a0); + ((void (*)(s32, void *, void *))func_80180F3C)(a0, &D_801A60E8[0], &sp10); + if ((func_801809F0(a0, &sp10, 1, 1) & 0xE000) == 0) { + func_8012C218((void *)a0); + } + break; + } +} + INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801802C8); -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_80180338); + +extern s32 func_8012B864(s32 a0); +extern s32 func_8012B608(s32 a0, s32 a1, s32 a2); +extern void func_8012A828(s32 arg0, s32 arg1); +extern s32 func_8012BEE8(s32 a0); + + +void func_80180338(s32 arg0) { + + extern s32 D_801AB264; + extern s32 D_801AB2EC; + extern s32 D_801AB1CC; + extern s32 D_801A60D0[]; + s32 v0; + s32 p; + u16 mode; + s32 idx; + s32 q; + + v0 = func_8012B864(arg0); + v0 = func_8012B608(*(s16 *)(*(s32 *)(arg0 + 0x20) + 0x12), v0 + 0x800, 10); + p = *(s32 *)(arg0 + 0x20); + *(u16 *)(p + 0x12) = *(u16 *)(p + 0x12) + v0; + + mode = *(u16 *)(arg0 + 0x34); + switch (mode) { + case 0: + if ((*(u16 *)(arg0 + 0x72) & 0x4000) != 0) { + func_8012A828(arg0, (s32) &D_801AB264); + v0 = *(u16 *)(arg0 + 0x34) + 1; + *(u16 *)(arg0 + 0x34) = v0; + } + break; + case 1: + if ((*(u16 *)(arg0 + 0x72) & 0x4000) != 0) { + v0 = *(s32 *)(arg0 + 0x1C) + 1; + *(s32 *)(arg0 + 0x1C) = v0; + if (v0 >= 4) { + func_8012A828(arg0, (s32) &D_801AB2EC); + *(u16 *)(arg0 + 0x34) += 1; + } + } + break; + case 2: + if ((*(u16 *)(arg0 + 0x72) & 0x4000) != 0) { + func_8012A828(arg0, (s32) &D_801AB1CC); + *(s32 *)(arg0 + 0x1C) = 0x1E; + *(u16 *)(arg0 + 0x34) += 1; + } + break; + case 3: + if (func_8012BEE8(arg0) != 0) { + idx = *(u16 *)(arg0 + 0x70) & 0xF; + *(u16 *)(arg0 + 0x2) = 1; + q = *(s32 *)(arg0 + 0x20); + *(s32 *)(q + 0x24) = D_801A60D0[idx]; + } + break; + } +} + INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801804C0); @@ -3761,7 +4036,91 @@ void func_8018068C(void *a0) { INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801806A0); -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801806EC); + +extern s32 func_8012BEE8(s32 a0); +extern s32 func_80132EF4(s32 a0, s32 a1); +extern s32 func_80180D4C(s32 a0, void *a1, s32 a2); +extern void func_80180F3C(void*); +extern void func_8012E8C4(s32 a0); +extern void func_80130D48(s32 a0); +extern void func_80180900(u8*); +extern s32 func_80047D3C(s32 a0); +extern s32 ratan2(s32 dx, s32 dy); + +/* a0 = actor base (state u16 at +0x34, mode s32 at +0x1C). + * case 0/1/2 dispatch on the actor's state field; case 0 additionally spawns + * a sub-object via func_80132EF4(a0, 0x50) and, depending on flag bits + * returned by func_80180D4C, aims it using a table entry (D_801152B0 / + * D_801152A8) via ratan2 + func_80047D3C (hypot-like). */ +void func_801806EC(s32 a0) { + + extern s16 D_801152B0; + extern u8 D_801152A8[]; + extern u8 D_801A60E8[]; + s32 state; + s32 s2; + void *s1; + s16 buf[4]; + s32 flags; + s32 v0; + s32 t0; + s32 t1; + s16 tmp; + + state = *(u16 *)(a0 + 0x34); + switch (state) { + case 0: + if (func_8012BEE8(a0) == 0) { + return; + } + *(s32 *)(a0 + 0x1C) = 0x80; + *(u16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + s2 = func_80132EF4(a0, 0x50); + if (s2 == 0) { + return; + } + s1 = 0; + ((void (*)())func_80180F3C)(a0, D_801A60E8, buf); + flags = func_80180D4C(a0, buf, 1); + if (flags & 0xC000) { + s1 = &D_801152B0; + } else if (flags & 0x2000) { + s1 = D_801152A8; + } + if (s1 != 0) { + v0 = ratan2(*(s16 *)((u8 *)s1 + 4), *(s16 *)((u8 *)s1 + 2)); + *(s16 *)(*(s32 *)(s2 + 0x20) + 0x10) = v0 + 0x400; + tmp = *(s16 *)((u8 *)s1 + 4); + t0 = tmp * tmp; + tmp = *(s16 *)((u8 *)s1 + 2); + t1 = tmp * tmp; + v0 = func_80047D3C(t0 + t1); + v0 = ratan2(*(s16 *)((u8 *)s1 + 0), -v0); + *(s16 *)(*(s32 *)(s2 + 0x20) + 0x12) = v0; + } else { + *(s16 *)(*(s32 *)(s2 + 0x20) + 0x10) = 0x400; + } + return; + case 1: + if (func_8012BEE8(a0) == 0) { + return; + } + *(s32 *)(a0 + 0x1C) = 0x20; + *(u16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1; + return; + case 2: + func_8012E8C4(a0); + if (func_8012BEE8(a0) == 0) { + return; + } + func_80130D48(a0); + ((void (*)(s32))func_80180900)(a0); + return; + default: + return; + } +} + INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801808A4); @@ -3812,7 +4171,98 @@ INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_8018122 INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801812F4); -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801813B4); + +/* Callees / globals — spelled exactly as this TU's own declarations + * (law 2/2b). See src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c for the + * canonical spellings this draft adopted: + * - D_801270C0 : extern u16 D_801270C0; (line 1129) read via *(s16*)& cast + * (idiom seen at src/ov_SC03_006/ov_SC03_006_jr_80140608.c:1778) + * - D_801152B0 : extern s16 D_801152B0; (line 405) + * - D_801152A8 : extern u8 D_801152A8[]; (line 600/635) + * - func_8012C218 : extern void func_8012C218(void *a0); (line 4730, used by + * the in-TU neighbour func_80182470 at line 4739) + * - func_8012CBF4 : canonical decl is `void func_8012CBF4(s32 a0)` (see + * src/shared/engine_core.h DEFINE_func_8012CBF4); callers + * that need its $v0 side value cast the call, e.g. + * src/ov_SC03_099/ov_SC03_099_jr_8017BEBC.c:4793. + * - func_80132EF4 : extern s32 func_80132EF4(s32 a0, s32 a1); (used earlier + * in this same TU, e.g. line 4553/4586). + * - ratan2, func_80047D3C : per this TU's own externs (lines 247/270 area). + * - func_80181DE4 : DEFINED earlier in this same TU (line 4454) as + * `s32 func_80181DE4(s32 a0, s32 a1)`. + * - func_8012D5E4 : extern s32 func_8012D5E4(s32 a0, s32 a1, s32 a2, s32 a3); + * (repo-wide idiom `(s32)D_x, (s32)D_x + 8` — e.g. + * src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c:6765). + * - D_80126B96 : not declared in this TU yet; repo-wide canonical is + * `extern u16 D_80126B96;`. + * - D_801A62A8 : brand-new symbol (no other TU references it). Declared + * raw array per the func_8012D5E4-table idiom + * `extern u8 D_x[];`. + */ + +extern void func_8012C218(void *a0); +extern void func_8012CBF4(s32 a0); +extern s32 func_80132EF4(s32 a0, s32 a1); +extern s32 ratan2(s32 a0, s32 a1); +extern s32 func_80047D3C(s32 a0); +extern s32 func_80181DE4(s32 a0, s32 a1); +extern s32 func_8012D5E4(s32 a0, s32 a1, s32 a2, s32 a3); + +void func_801813B4(s32 a0) { + + extern u16 D_801270C0; + extern s16 D_801152B0; + extern u8 D_801152A8[]; + extern u16 D_80126B96; + extern u8 D_801A62A8[]; + s32 obj = a0; + s16 v1; + s16 *s1; + s32 s0; + s32 i; + s32 pad[2]; /* dead-local frame pad (cookbook §162i1); target frame is 8 + * bytes larger than this body's live locals account for. */ + + if (*(s16 *)(obj + 0xA) >= 0x10) { + func_8012C218((void *)a0); + __asm__ __volatile__("" ::: "memory"); /* zero-byte cross-jump barrier (cookbook §5a) */ + return; + } + + s1 = 0; + __asm__ __volatile__(""); + if (*(s16 *)&D_801270C0 == 2) { + return; + } + + v1 = ((s32 (*)(s32))func_8012CBF4)(obj); + if (v1 & 0xC000) { + s1 = &D_801152B0; + } else if (v1 & 0x2000) { + s1 = (s16 *)D_801152A8; + } + + if (s1 != 0) { + for (i = 0; i < 6; i++) { + func_80132EF4(obj, 0x51); + } + s0 = func_80132EF4(obj, 0x50); + if (s0 != 0) { + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x10) = + ratan2(s1[2], s1[1]) + 0x400; + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x12) = + ratan2(s1[0], -func_80047D3C(s1[2] * s1[2] + s1[1] * s1[1])); + *(s16 *)(*(s32 *)(s0 + 0x20) + 0x14) = 0; + } + func_80181DE4(obj, 0x7FB); + func_8012C218((void *)obj); + } else { + if (func_8012D5E4(obj, (s32)D_801A62A8, (s32)D_801A62A8 + 8, 0x18) == 1) { + D_80126B96 = 0x4014; + } + } +} + INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_80181540); @@ -3858,7 +4308,67 @@ void func_80181984(void *a0) { } -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801819C0); +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_801819C0; + +extern s32 rand(void); +extern void func_80049CAC(s32 a0, s32 a1); +extern void func_800484EC(s32 a0, s32 a1, s32 a2); + +void func_801819C0(s32 arg0) { + + extern s32 D_801A62DC; + s32 p; + s32 tmp; + s32 t2, t3, t4, t5; + s32 rem128; + s32 signed_rem; + SVECTOR sv; + MATRIX m; + VECTOR v; + + p = *(s32 *)(arg0 + 0x20); + *(s32 *)(p + 0x20) = (s32)&D_801A62DC; + *(u8 *)(p + 0x27) = 0x52; + *(u16 *)(p + 0x28) = 0x2D0; + *(u16 *)(p + 0x2A) = 0x100; + + tmp = rand() % 0x1000 + 0x800; + *(u16 *)(p + 0x1A) = tmp; + *(u16 *)(p + 0x18) = tmp; + + t2 = rand(); + rem128 = t2 % 128; + + t3 = rand(); + if (!(t3 & 1)) { + signed_rem = -rem128 - 0x300; + } else { + signed_rem = rem128 - 0x300; + } + sv.vx = signed_rem; + + t4 = rand(); + sv.vy = t4 % 0x1000; + + sv.vz = 0; + v.vy = 0; + v.vx = 0; + + t5 = rand(); + v.vz = -0x60000 - ((t5 % 4) << 16); + + func_80049CAC((s32)&sv, (s32)&m); + func_800484EC((s32)&m, (s32)&v, arg0 + 0x10); + + *(s32 *)(arg0 + 0x1C) = 0x2D; + *(u16 *)(arg0 + 2) = *(u16 *)(arg0 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_80181B10); 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 45205c2f8..e378f8e14 100644 --- a/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c +++ b/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c @@ -3933,7 +3933,77 @@ extern void func_8012AD44(s32 *a0, s16 a1); } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_8017FEF8); + +/* Declarations matching this TU's existing spellings (law 2): + * func_8002D4C8 : file-scope L58 extern void func_8002D4C8(s32 a0, s32 a1); + * func_8012BEE8 : file-scope L3473 extern s32 func_8012BEE8(s32 a0); + * func_801804BC : DEFINED in this TU, L4439: void func_801804BC(s32 a0, s32 a1, s32 a2, s32 a3); + * func_80143640 / func_801437D8 : not declared in this TU; typed by cross-TU precedent + * (src/ov_SC07_007/ov_SC07_007_jr_8015B950.c:965-966): (s32,s32,s32,s32). + * D_801AD3A4 / D_801AD3AC : not declared anywhere else; only ever used as a raw address + * (loaded into a register and passed through as an s32 arg) -- declared as a scalar and + * passed via &sym per law 4 (rawest form, cast at use site). + */ +extern void func_8002D4C8(s32 a0, s32 a1); +extern s32 func_8012BEE8(s32 a0); +extern void func_80143640(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_801437D8(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_801804BC(s32 a0, s32 a1, s32 a2, s32 a3); + +void func_8017FEF8(s32 p) { + + extern s32 D_801AD3A4; + extern s32 D_801AD3AC; + s16 buf[4]; + u16 disc = *(u16 *)(p + 0x34); + + switch (disc) { + case 0: + if (*(s16 *)(*(s32 *)(p + 0x64) + 0x106) < 2) { + if ((*(u16 *)(p + 0x102) & 3) == 0) { + func_8002D4C8(0x951, 0); + } + } + + buf[1] = *(u16 *)(p + 0xA); + buf[2] = *(u16 *)(p + 0xE) - 0x30; + buf[3] = 0x4001; + if (*(s16 *)(p + 0x70) == 1) { + buf[0] = *(u16 *)(p + 6) + 0x88; + } else { + buf[0] = *(u16 *)(p + 6) - 0x88; + } + + func_801437D8(p + 0x102, (s32)buf, (s32)&D_801AD3A4, 0); + func_80143640(p + 0x104, (s32)buf, (s32)&D_801AD3A4, 0); + + if (func_8012BEE8(p) != 0) { + (*(u16 *)(*(s32 *)(p + 0x64) + 0x106))++; + (*(u16 *)(p + 0x34))++; + } + break; + case 1: { + s32 local[4]; + + buf[1] = *(u16 *)(p + 0xA); + buf[2] = *(u16 *)(p + 0xE) - 0x30; + buf[3] = 0x3001; + if (*(s16 *)(p + 0x70) == 1) { + buf[0] = *(u16 *)(p + 6) + 0x88; + } else { + buf[0] = *(u16 *)(p + 6) - 0x88; + } + + local[1] = 0xFFFC0000; + local[2] = 0; + local[0] = 0; + local[3] = 3; + func_801804BC(p + 0x104, (s32)buf, (s32)&D_801AD3AC, (s32)local); + break; + } + } +} + extern void func_8012AD44(s32 *a0, s16 a1); @@ -3942,7 +4012,81 @@ extern void func_8012AD44(s32 *a0, s16 a1); } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_801800CC); + +/* 8-byte-stride tables split by splat into four per-field labels. + * D_801AD2DC[i*4] / D_801AD2DE[i*4] / D_801AD2E0[i*4] : u16 deltas + * D_801AD2E2[i*4] : s16 (sign-extended into 0x1C) */ + + +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8012AD44(s32 *a0, s16 a1); + +void func_801800CC(s32 a0) { + + extern u16 D_801AD2DC[]; + extern u16 D_801AD2DE[]; + extern u16 D_801AD2E0[]; + extern s16 D_801AD2E2[]; + extern u8 D_801AD318[]; /* 0x10-byte stride */ + extern u8 D_801AD348[]; + extern u8 D_801AD360[]; + extern u8 D_801AD394[]; + *(u16 *)(a0 + 0x6) += D_801AD2DC[*(s16 *)(a0 + 0x70) * 4]; + *(u16 *)(a0 + 0xA) += D_801AD2DE[*(s16 *)(a0 + 0x70) * 4]; + *(u16 *)(a0 + 0xE) += D_801AD2E0[*(s16 *)(a0 + 0x70) * 4]; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x28) = 0x2000100; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x2C) |= 0x90; + *(s32 *)(*(s32 *)(a0 + 0x20) + 0x80) = (s32)D_801AD394; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x18) = 0x1040; + + switch (*(s16 *)(a0 + 0x70)) { + case 1: + case 2: + *(s32 *)(a0 + 0x78) = (s32)D_801AD360; + *(u8 *)(a0 + 0xC0) = 1; + *(s32 *)(a0 + 0xBC) = (s32)D_801AD348; + *(u8 *)(a0 + 0x75) = 8; + *(u16 *)(a0 + 0x76) = 0x708; + *(s32 *)(a0 + 0xB4) = 0; + *(u8 *)(a0 + 0xC1) = 0; + *(u16 *)(a0 + 0x5C) = 0; + *(s32 *)(a0 + 0xC4) |= 2; + *(s32 *)(a0 + 0x58) = (s32)&D_801AD318[*(s16 *)(a0 + 0x70) * 0x10]; + if (*(s16 *)(a0 + 0x70) == 1) { + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) = 0x800; + } + /* fallthrough */ + case 3: + case 4: + if (*(s16 *)(a0 + 0x70) == 4) { + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x10) = 0x800; + } + *(u16 *)(a0 + 0xFE) = 0; + *(s32 *)(a0 + 0x1C) = D_801AD2E2[*(s16 *)(a0 + 0x70) * 4]; + if (*(s16 *)(a0 + 0x70) == 0) { + if (*(s32 *)(a0 + 0xCC) != 0) { + func_801800CC(*(s32 *)(a0 + 0xCC)); + } + if (*(s32 *)(a0 + 0xD0) != 0) { + func_801800CC(*(s32 *)(a0 + 0xD0)); + } + if (*(s32 *)(a0 + 0xD4) != 0) { + func_801800CC(*(s32 *)(a0 + 0xD4)); + } + if (*(s32 *)(a0 + 0xD8) != 0) { + func_801800CC(*(s32 *)(a0 + 0xD8)); + } + *(s32 *)(a0 + 0x58) = (s32)D_801AD318; + *(u16 *)(a0 + 0x5C) = 0x800; + *(u8 *)(a0 + 0x75) = 8; + *(u16 *)(a0 + 0x106) = 0; + func_8002D4C8(0x94F, 0); + } + ((void (*)(s32, s32))func_8012AD44)(a0, 2); + break; + } +} + extern void (*D_801AD3B4[])(void); @@ -3994,11 +4138,183 @@ INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_8018068 INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_80180700); -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_80180838); + +/* TU declarations adopted from src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c + * (func_801801D8 @ L3514-3515, and the "integration surface" block @ L4270-4293 + * that precedes func_80182074). */ +extern s32 func_8012BEE8(s32 a0); +extern void func_8012C218(void*); +extern void func_800183E0(s32 a0); +extern void func_80180CD0(s32 a0); + +/* D_801AD3F8: per-overlay pointer table, asm/ov_SC06_024/data/tail.data.s. + * Indexed *4 (sll 2) then loaded as a 32-bit word and passed straight to + * func_800183E0(s32), so a raw s32 array is the rawest-form spelling (law 4). */ + +void func_80180838(void *a0) +{ + + extern s32 D_801AD3F8[]; + void *s0 = a0; + s16 tmp; + + switch (*(u16 *)((s32)s0 + 0x34)) { + case 0: + if (func_8012BEE8((s32)s0) == 0) { + return; + } + *(s32 *)((s32)s0 + 0x1C) = 2; + if (*(s16 *)((s32)s0 + 0x70) == 0) { + func_800183E0(D_801AD3F8[*(s16 *)((s32)s0 + 0x100)]); + } + tmp = *(u16 *)((s32)s0 + 0x100) + 1; + *(u16 *)((s32)s0 + 0x100) = tmp; + if (tmp == 7) { + *(u16 *)((s32)s0 + 0x34) += 1; + } + return; + case 1: + if (*(s32 *)((s32)s0 + 0x6C) != 0) { + if (*(s16 *)((s32)s0 + 0x70) == 0) { + *(s16 *)(*(s32 *)((s32)s0 + 0x6C) + 0x6) = + *(u16 *)(*(s32 *)((s32)s0 + 0x64) + 0x6) + 0x90; + } else { + *(s16 *)(*(s32 *)((s32)s0 + 0x6C) + 0x6) = + *(u16 *)(*(s32 *)((s32)s0 + 0x64) + 0x6) - 0x90; + } + *(s16 *)(*(s32 *)((s32)s0 + 0x6C) + 0x6) = + *(u16 *)(*(s32 *)((s32)s0 + 0x6C) + 0x6) + 4; + *(s16 *)(*(s32 *)((s32)s0 + 0x6C) + 0xA) = + *(u16 *)(*(s32 *)((s32)s0 + 0x64) + 0xA); + *(s16 *)(*(s32 *)((s32)s0 + 0x6C) + 0xE) = + *(u16 *)(*(s32 *)((s32)s0 + 0x64) + 0xE); + func_80180CD0(*(s32 *)((s32)s0 + 0x6C)); + } + *(u16 *)((s32)s0 + 0x34) += 1; + return; + case 2: + if (*(s32 *)(*(s32 *)(*(s32 *)((s32)s0 + 0x64) + 0x20) + 0x4) < 0) { + ((void (*)(s32))func_8012C218)((s32)s0); + } + return; + } +} + INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_801809D4); -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_801809F4); + +/* ---- callees (TU canon: src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c L3514/3515) ---- */ +extern s32 func_8012BEE8(s32 a0); +extern void func_8012C218(void*); +extern void func_8012B77C(void *out, s32 from, void *to); + +/* same-TU INCLUDE_ASM neighbours -- no decl in the TU, free */ +extern void func_80180F30(s32 target, u16 *cur, s32 step); /* DEFINED in TU L4503 */ +extern void func_80180FB4(s32 a0); +extern void func_801810C0(s32 a0); +extern void func_80180EE0(s32 a0); + +/* ---- data ---- */ + +/* 4-byte records: +0 = u16 delta, +2 = s16 flags/duration word */ + +void func_801809F4(s32 p) { + + extern u8 D_80126B5C; /* canonical engine_core.h spelling; s32 view at use site */ + extern s32 D_80126B60; + extern s32 D_80126B64; + extern u16 D_801AD414[]; + extern s16 D_801AD416[]; + s32 vec[3]; + s32 out[2]; + s32 e; + s32 r; + + e = *(s32 *)(p + 0xCC); + + switch (*(u16 *)(p + 0x34)) { + case 0: + if (func_8012BEE8(p) == 0) { + break; + } + *(s16 *)(p + 0x100) = -1; + *(s16 *)(p + 0xFE) = 0; + *(s16 *)(p + 0x34) = *(u16 *)(p + 0x34) + 1; + break; + + case 1: + *(u16 *)(*(s32 *)(p + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(p + 0x20) + 0x12) + *(u16 *)(p + 0xFE); + if (func_8012BEE8(p) == 0) { + break; + } + if (*(s16 *)(p + 0x100) >= 0 && + (D_801AD416[*(s16 *)(p + 0x100) * 2] & 0x8000) != 0) { + if (*(s16 *)(p + 0x70) == 5) { + *(s16 *)(p + 0x102) = 0x20; + } else { + *(s16 *)(p + 0x102) = 0x70; + } + *(s16 *)(p + 0x34) = *(u16 *)(p + 0x34) + 1; + break; + } + *(s16 *)(p + 0x100) = *(u16 *)(p + 0x100) + 1; + *(u16 *)(p + 0xFE) = D_801AD414[*(s16 *)(p + 0x100) * 2]; + *(s32 *)(p + 0x1C) = (u8)D_801AD416[*(s16 *)(p + 0x100) * 2]; + if (*(s16 *)(p + 0x70) == 5) { + *(s16 *)(p + 0xFE) = -*(u16 *)(p + 0xFE); + } + break; + + case 2: + vec[0] = *(s32 *)&D_80126B5C; + vec[1] = D_80126B60 - 0x480000; + vec[2] = D_80126B64; + func_8012B77C(out, *(s32 *)(p + 0x64) + 4, vec); + *(s32 *)(p + 0xE0) = out[0]; + func_80180F30(*(s16 *)(p + 0xE0), (u16 *)(*(s32 *)(p + 0x20) + 0x10), 0x20); + func_80180F30(*(s16 *)(p + 0xE2), (u16 *)(*(s32 *)(p + 0x20) + 0x12), 0x20); + if (*(s16 *)(p + 0x102) != 0) { + *(s16 *)(p + 0x102) = *(s16 *)(p + 0x102) - 1; + } else { + func_80180FB4(p); + r = *(s32 *)(p + 0xD0); + if (r != 0) { + *(s16 *)(r + 0x54) = 0x10; + } + *(s32 *)(p + 0x1C) = 3; + *(s16 *)(p + 0x34) = *(u16 *)(p + 0x34) + 1; + } + if (*(s16 *)(e + 0x76) != 0) { + break; + } + func_801810C0(p); + if (*(s32 *)(p + 0xD0) != 0) { + ((void (*)(s32))func_8012C218)(*(s32 *)(p + 0xD0)); + } + ((void (*)(s32))func_8012C218)(p); + return; + + case 3: + if (func_8012BEE8(p) == 0) { + break; + } + r = *(s32 *)(p + 0xD0); + if (r != 0) { + *(s16 *)(r + 0x54) = 0; + } + *(s16 *)(p + 0x102) = 0xA0; + *(s16 *)(p + 0x34) = *(u16 *)(p + 0x34) - 1; + break; + + default: + break; + } + + func_80180EE0(p); +} + extern void func_8012AD44(s32 *a0, s16 a1); void func_80180CB0(s32 arg0) { @@ -4060,7 +4376,68 @@ void func_80181168(void *a0) { } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_801811A4); + +extern void func_8012C1B8(void); +extern void func_8012CAE4(void*); +extern void func_8001C214(s32 a0, s32 a1); +extern void func_801812F8(s32 a0); + +void func_801811A4(s32 param_1) { + /* The four u16 tables all share one 8-byte stride -- they are the four + halfword members of a single 8-byte record based at 0x801AC5AC. + Spelling each as an ARRAY OF AN 8-BYTE RECORD (wanted halfword at + offset 0) keeps the exact symbol names the target relocates against + AND stops gcc-2.7.2 force_reg'ing a second copy of the bare SYMBOL_REF + for D_801AD46E (which is read twice). That orphaned address pseudo is + what reserves a dead 8-byte stack slot ("phantom frame", cookbook 5): + it survives to alter_reg with reg_n_refs>0 and no hard reg, so + assign_stack_local grows var_size by 8 with nothing ever stored there. + Byte-checked: pointer-arith spelling -> frame 0x20, this -> frame 0x18. */ + struct Row8_8018367C_801811A4 { u16 h; u16 pad[3]; }; + extern struct Row8_8018367C_801811A4 D_801AD46E[]; + extern struct Row8_8018367C_801811A4 D_801AD468[]; + extern struct Row8_8018367C_801811A4 D_801AD46A[]; + extern struct Row8_8018367C_801811A4 D_801AD46C[]; + extern u32 D_801AD454[]; + + /* the entry call's result doubles as func_8001C214's first argument, so it + owns $a0 for its whole live range (target: addu $a0,$v0,$zero at entry) */ + register s32 v0 __asm__("$4"); + s32 v1; + s32 mask; + + *(s32 *)(param_1 + 0x20) = v0 = ((s32 (*)(void))func_8012C1B8)(); + if (v0 == 0) { + ((void (*)(s32))func_8012CAE4)(param_1); + return; + } + + func_8001C214(v0, D_801AD454[D_801AD46E[*(s16 *)(param_1 + 0x70)].h & 7]); + + v1 = *(s32 *)(param_1 + 0x20); + *(u16 *)(v1 + 0x2C) = *(u16 *)(v1 + 0x2C) | 0x10; + + v1 = *(s32 *)(param_1 + 0x20); + mask = D_801AD46E[*(s16 *)(param_1 + 0x70)].h & 0xFFF0; + *(u16 *)(v1 + 0x1A) = mask; + *(u16 *)(v1 + 0x18) = mask; + + v1 = *(s32 *)(param_1 + 0x20); + *(u16 *)(v1 + 0x1C) = 0x400; + + *(s16 *)(param_1 + 0x6) = *(u16 *)(*(s32 *)(param_1 + 0x64) + 0x6) + + D_801AD468[*(s16 *)(param_1 + 0x70)].h; + + *(s16 *)(param_1 + 0xA) = *(u16 *)(*(s32 *)(param_1 + 0x64) + 0xA) + + D_801AD46A[*(s16 *)(param_1 + 0x70)].h; + + *(s16 *)(param_1 + 0xE) = *(u16 *)(*(s32 *)(param_1 + 0x64) + 0xE) + + D_801AD46C[*(s16 *)(param_1 + 0x70)].h; + + *(s16 *)(param_1 + 0xE0) = *(u16 *)(*(s32 *)(param_1 + 0x64) + 0xA) + 0x140; + func_801812F8(param_1); +} + extern void func_8012B23C(); extern s32 rand(void);