diff --git a/src/ov_SC01_001/ov_SC01_001_jr_8017D2DC.c b/src/ov_SC01_001/ov_SC01_001_jr_8017D2DC.c index 288d36c4c..ef5d11057 100644 --- a/src/ov_SC01_001/ov_SC01_001_jr_8017D2DC.c +++ b/src/ov_SC01_001/ov_SC01_001_jr_8017D2DC.c @@ -5106,7 +5106,70 @@ void func_801817BC(int param_1) void func_80181834(void) { } -INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001_jr_8017D2DC", func_8018183C); +#include "common.h" + +/* §200 alias: this TU spells func_8001D074 `void (s32,s32)` (lines 119/124), but the target + stores its $v0 into D_801EDA24 — the fleet's 5 rivals declare it s32. Bind our own + identifier to the same link name so the TU's spelling stays untouched. */ +extern s32 aF8001D074(s32, s32) __asm__("func_8001D074"); +extern void func_800233CC(void *, unsigned short); +extern void func_8001CD9C(int, void *); + +extern s32 D_801ED9B8; +extern s32 D_801ED9BC; +extern s32 D_801ED9C0; +extern s32 D_801ED9C4; +extern s32 D_801EDA24; +extern u8 D_80188A94; +extern u8 D_80188A95; +extern u8 D_80188A96; + +s32 func_8018183C(void) { + switch (D_801ED9B8) { + case 0: + D_801EDA24 = aF8001D074(0x3E, 0x7D); + D_801ED9C4 = 0x10; + if (D_801EDA24 != 0) { + func_800233CC(&D_80188A94, 0x10); + func_8001CD9C(D_801EDA24, &D_80188A94); + *(s32 *)(D_801EDA24 + 4) |= 0x50000040; + } + D_801ED9C0 = 0xFF; + D_801ED9BC = 0x10; + *(s16 *)(D_801EDA24 + 0xA) = -0x2E9; + *(s16 *)(D_801EDA24 + 0xC) = -0x2C; + *(s16 *)(D_801EDA24 + 0x8) = 0; + D_80188A94 = 0x10; + D_80188A95 = 0xFF; + D_80188A96 = 0xFF; + D_801ED9B8++; + break; + case 1: + func_800233CC(&D_80188A94, (u16)D_801ED9C4); + if (D_801ED9BC == 0) { + D_801ED9C0 -= 0x10; + if (D_801ED9C0 <= 0) { + D_801ED9C0 = 0; + } + D_80188A95 = D_801ED9C0; + D_80188A96 = D_801ED9C0; + D_801ED9C4 -= 4; + if (D_801ED9C4 < 0) { + D_801ED9C4 = 0; + } + if (D_801ED9C0 == 0) { + *(s16 *)(D_801EDA24 + 0x0) = 0; + return 1; + } + } else { + D_801ED9BC--; + } + *(u16 *)(D_801EDA24 + 0xA) = *(u16 *)(D_801EDA24 + 0xA) - 6; + break; + } + return 0; +} + extern s32 D_801EDA44; void func_80181A28(void) { diff --git a/src/ov_SC02_037/ov_SC02_037_jr_8017AE2C.c b/src/ov_SC02_037/ov_SC02_037_jr_8017AE2C.c index 46969cd22..37a88c573 100644 --- a/src/ov_SC02_037/ov_SC02_037_jr_8017AE2C.c +++ b/src/ov_SC02_037/ov_SC02_037_jr_8017AE2C.c @@ -5979,7 +5979,78 @@ void func_8017EB88(void *a0) { } -INCLUDE_ASM("asm/ov_SC02_037/nonmatchings/ov_SC02_037_jr_8017AE2C", func_8017EBC4); + + + + + + + + + +extern s32 D_80126B58; +extern s32 *D_80126B78; +extern s16 D_80126940; +extern u16 func_80148800(s32 *a0); +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern s32 func_8017EEC4(s32 arg0, void *arg1); + +void func_8017EBC4(s32 param_1) +{ + extern s16 D_8018784C[]; + Unaligned8 sp10; + s32 t; + register s32 u __asm__("$3"); + s32 a0; + register int zr __asm__("$0"); + + if (func_80148800(&D_80126B58) & 3) { + *(u8 *)(param_1 + 5) = (*(u8 *)(param_1 + 5) + 1) & 1; + *(s32 *)(param_1 + 0x14) = D_8018784C[*(u8 *)(param_1 + 5)]; + } + + sp10 = *(Unaligned8 *)&D_80126940; + + if (*(s16 *)(param_1 + 0xA0) == 0) { + t = -func_8004787C(*(s16 *)((s32)D_80126B78 + 0x12)); + if (t < 0) { + t += 0x1F; + } + *(s16 *)(param_1 + 0x2E) = t >> 5; + + t = -func_80047948(*(s16 *)((s32)D_80126B78 + 0x12)); + if (t < 0) { + t += 0x1F; + } + *(s16 *)(param_1 + 0x32) = t >> 5; + + *(s16 *)(param_1 + 0xA0) = 0x20; + } else { + *(s16 *)(param_1 + 0xA0) = *(s16 *)(param_1 + 0xA0) - 1; + } + + u = -0x500 - *(u16 *)(param_1 + 0x28); + a0 = u + zr; + if ((u << 16) >> 16 > *(s16 *)&sp10.a) { + *(s16 *)&sp10.a = a0; + } + + u = 0x500 - *(u16 *)(param_1 + 0x28); + a0 = u + zr; + if ((u << 16) >> 16 < *(s16 *)&sp10.a) { + *(s16 *)&sp10.a = a0; + } + + u = -0xA00 - *(u16 *)(param_1 + 0x2C); + a0 = u + zr; + if ((u << 16) >> 16 > *(s16 *)&sp10.b) { + *(s16 *)&sp10.b = a0; + } + + func_8017EEC4(param_1, &sp10); +} + extern s32 func_8017EEC4(s32 arg0, void *arg1); extern s32 D_80187850; @@ -6040,7 +6111,46 @@ void func_8017ED90(St_8017ED90 *arg0) } -INCLUDE_ASM("asm/ov_SC02_037/nonmatchings/ov_SC02_037_jr_8017AE2C", func_8017EEC4); +extern s32 func_80012C6C(s32 a0, s32 a1, s32 a2); +extern s32 func_80012ABC(s32 a0, s32 a1, s32 a2); +extern s32 func_800130D0(s32 a0, s32 a1, s32 a2); +extern void func_80049CAC(s32 a0, s32 a1); +extern void func_8012F14C(s32 a0, s32 a1, s32 a2); + + + + +s32 func_8017EEC4(s32 arg0, void *arg1) +{ + s16 *param_2 = (s16 *)arg1; + MATRIX m1; + SVECTOR svec_in; + SVECTOR svec_out; + + *(s32 *)(arg0 + 0x8) = (s16)func_80012C6C((s32)*(s16 *)(arg0 + 0x8), (s32)*(s16 *)(arg0 + 0xC), 4); + *(s32 *)(arg0 + 0x10) = (s16)func_80012C6C((s32)*(s16 *)(arg0 + 0x10), (s32)*(s16 *)(arg0 + 0x14), 4); + *(s16 *)(arg0 + 0x18) = func_80012ABC((s32)*(s16 *)(arg0 + 0x18), (s32)*(s16 *)(arg0 + 0x20), 4); + *(s16 *)(arg0 + 0x1A) = func_80012ABC((s32)*(s16 *)(arg0 + 0x1A), (s32)*(s16 *)(arg0 + 0x22), 4); + *(s16 *)(arg0 + 0x1C) = func_80012ABC((s32)*(s16 *)(arg0 + 0x1C), (s32)*(s16 *)(arg0 + 0x24), 4); + *(s16 *)(arg0 + 0x28) = func_800130D0((s32)*(s16 *)(arg0 + 0x28), (s32)*(s16 *)(arg0 + 0x2E), 4); + *(s16 *)(arg0 + 0x2A) = func_800130D0((s32)*(s16 *)(arg0 + 0x2A), (s32)*(s16 *)(arg0 + 0x30), 4); + *(s16 *)(arg0 + 0x2C) = func_800130D0((s32)*(s16 *)(arg0 + 0x2C), (s32)*(s16 *)(arg0 + 0x32), 4); + *(s32 *)(arg0 + 0x48) = (s32)*(s16 *)(arg0 + 0x28) + (s32)param_2[0]; + *(s32 *)(arg0 + 0x4C) = (s32)*(s16 *)(arg0 + 0x2A) + (s32)param_2[1]; + *(s32 *)(arg0 + 0x50) = (s32)*(s16 *)(arg0 + 0x2C) + (s32)param_2[2]; + func_80049CAC(arg0 + 0x18, (s32)&m1); + m1.t[0] = *(s16 *)(arg0 + 0x28) + param_2[0]; + m1.t[1] = *(s16 *)(arg0 + 0x2A) + param_2[1]; + m1.t[2] = *(s16 *)(arg0 + 0x2C) + param_2[2]; + svec_in.vx = 0; + svec_in.vy = 0; + svec_in.vz = *(s32 *)(arg0 + 0x10); + func_8012F14C((s32)&m1, (s32)&svec_in, (s32)&svec_out); + *(s32 *)(arg0 + 0x3C) = (s32)svec_out.vx; + *(s32 *)(arg0 + 0x40) = (s32)svec_out.vy; + *(s32 *)(arg0 + 0x44) = (s32)svec_out.vz; +} + extern void func_8017F07C(void); void func_8017F05C(void) { @@ -6099,7 +6209,87 @@ void func_8017F254(void *a0) { } -INCLUDE_ASM("asm/ov_SC02_037/nonmatchings/ov_SC02_037_jr_8017AE2C", func_8017F2B4); +extern void func_8001FC08(); + +void func_8017F2B4(s32 param_1_a0) +{ + register s32 param_1 __asm__("$6"); + s32 base; + s32 diff; + s32 quot; + register u8 val __asm__("$4"); + register u8 *p __asm__("$3"); + register s32 negc __asm__("$5"); + register u8 lo __asm__("$4"); + register u8 hi __asm__("$2"); + + param_1 = param_1_a0; + + if (*(s16 *)(param_1 + 0xA) < 0xC0) { + diff = 0xC0 - *(s16 *)(param_1 + 0xA); + quot = (diff * 63) / 0xC0; + __asm__("addiu %0, %1, 0x50" : "=r"(val) : "r"(quot)); + if (val >= 0x7F) { + val = 0x7F; + } + + base = *(s32 *)(*(s32 *)(*(s32 *)(param_1 + 0x20) + 0x24) + 0x0); + p = (u8 *)base; + __asm__("nop\n\taddiu %0, %1, 0x35" : "=r"(p) : "r"(p)); + *p = val; + __asm__("addiu %0, %1, 4" : "=r"(p) : "r"(p)); + *p = val; + __asm__("addiu %0, %1, 0x1C" : "=r"(p) : "r"(p)); + *p = val; + __asm__("addiu %0, %1, 4" : "=r"(p) : "r"(p)); + *p = val; + __asm__("addiu %0, %1, 0x1C" : "=r"(p) : "r"(p)); + *p = val; + __asm__("addiu %0, %1, 4" : "=r"(p) : "r"(p)); + *p = val; + __asm__("addiu %0, %1, 0x1C" : "=r"(p) : "r"(p)); + *p = val; + p[4] = val; + + { + s32 x = -(s32) * (u16 *)(param_1 + 0xA); + __asm__("addu %0, %1, $0" : "=r"(negc) : "r"(x)); + if ((s16)x > 0) { + negc = 0; + } + } + + { + s32 t0 = *(s32 *)(param_1 + 0x20); + s32 t1 = *(s32 *)(t0 + 0x24); + s32 loW, hiW; + __asm__ __volatile__("addu %0, %1, $0" : "=r"(loW) : "r"(negc)); + base = *(s32 *)(t1 + 0x0); + __asm__ __volatile__("srl %0, %1, 8" : "=r"(hiW) : "r"(negc)); + lo = (u8)loW; + hi = (u8)hiW; + } + p = (u8 *)base; + __asm__("addiu %0, %1, 0xCA" : "=r"(p) : "r"(p)); + *p = lo; + __asm__("addiu %0, %1, 1" : "=r"(p) : "r"(p)); + *p = hi; + __asm__("addiu %0, %1, 0x17" : "=r"(p) : "r"(p)); + *p = lo; + __asm__("addiu %0, %1, 1" : "=r"(p) : "r"(p)); + *p = hi; + __asm__("addiu %0, %1, 0xF" : "=r"(p) : "r"(p)); + *p = lo; + __asm__("addiu %0, %1, 1" : "=r"(p) : "r"(p)); + *p = hi; + __asm__("addiu %0, %1, 0xF" : "=r"(p) : "r"(p)); + *p = lo; + p[1] = hi; + + func_8001FC08(*(s32 *)(param_1 + 0x20)); + } +} + extern s32 func_8012C0EC(s32 a0); extern void func_8017F2B4(s32 a0); diff --git a/src/ov_SC03_002/ov_SC03_002_jr_8017D604.c b/src/ov_SC03_002/ov_SC03_002_jr_8017D604.c index 82d5606ed..b8f82e2cc 100644 --- a/src/ov_SC03_002/ov_SC03_002_jr_8017D604.c +++ b/src/ov_SC03_002/ov_SC03_002_jr_8017D604.c @@ -3160,7 +3160,67 @@ void func_8017D604(s32 arg0) } -INCLUDE_ASM("asm/ov_SC03_002/nonmatchings/ov_SC03_002_jr_8017D604", func_8017E4E4); +extern u16 D_80126B5E; +extern u16 D_80126B66; +extern u16 D_80126B96; +extern s16 D_80126B98; +extern s32 D_801892A0; + +extern s32 func_80132EF4(s32 a0, s32 a1); +extern void func_80129374(s32 a0, s32 a1); +extern s32 func_8017E708(s32 a0, s32 a1); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8017E68C(s32 a0); + +void func_8017E4E4(s32 arg0) +{ + s32 v1; + s16 dx, dy; + s32 v0; + s32 dist2, rem, vol; + u16 *p; + u16 t; + + v1 = D_80126B5E - *(u16 *)(arg0 + 0x6); + dx = v1; + if ((s16)v1 < 0) dx = -v1; + + v1 = D_80126B66 - *(u16 *)(arg0 + 0xE); + dy = v1; + if ((s16)v1 < 0) dy = -v1; + + if (dx < 0x201 && dy < 0x201) { + v0 = *(s32 *)(arg0 + 0x1C); + *(s32 *)(arg0 + 0x1C) = v0 + 1; + if (v0 & 1) { + s32 s0 = func_80132EF4(arg0, 0x22); + if (s0 != 0) { + func_80129374(s0, arg0); + *(s16 *)(s0 + 0x34) = 0x4000; + } + } + if (func_8017E708(arg0, (s32) &D_801892A0) != 0) { + p = &D_80126B96; + t = *p; + D_80126B98 = 0xC; + *p = t | 0x4000; + } + if ((*(s32 *)(arg0 + 0x1C) & 3) == 0) { + dist2 = dx * dx + dy * dy; + if (dist2 <= 0x30000) { + rem = 0x30000 - dist2; + vol = rem * 127 / 0x30000; + func_8002D4C8(0x644, (vol | 0x1000) & 0xFFFF); + *(s16 *)(arg0 + 0xFC) = 1; + } else { + func_8017E68C(arg0); + } + } + } else { + func_8017E68C(arg0); + } +} + extern void func_8002D4C8(s32 a0, s32 a1); @@ -3519,7 +3579,40 @@ void func_8017EF80(void *a0, void *a1, void *a2, void *a3) } -INCLUDE_ASM("asm/ov_SC03_002/nonmatchings/ov_SC03_002_jr_8017D604", func_8017F068); +extern void ApplyMatrixSV(void *a0, void *a1, void *a2); +extern void RotMatrixYXZ(void *a0, void *a1); +extern s32 rand(void); + +void func_8017F068(void *a0, void *a1, s16 a2, s16 a3) +{ + extern u8 *func_8012913C(s32 a0); + s16 i; + s16 rot[4]; + s32 mtx[8]; + u8 *ent; + + i = 0; + if (0 < a3) { + do { + ent = func_8012913C(0x46); + if (ent != 0) { + rot[0] = (rand() & 0x7F) * 8 + 0xF00; + rot[1] = a2 + (s16)((rand() & 0x7F00) >> 5); + rot[2] = 0; + RotMatrixYXZ(rot, mtx); + ApplyMatrixSV(mtx, a1, rot); + *(s16 *)(ent + 6) = *(s16 *)a0 + rot[0]; + *(s16 *)(ent + 10) = *(s16 *)((s8 *)a0 + 2) + rot[1]; + *(s16 *)(ent + 14) = *(s16 *)((s8 *)a0 + 4) + rot[2]; + *(s32 *)(ent + 0x10) = (s32)rot[0] << 12; + *(s32 *)(ent + 0x14) = (s32)rot[1] << 12; + *(s32 *)(ent + 0x18) = (s32)rot[2] << 12; + } + i = i + 1; + } while (i < a3); + } +} + extern void (*D_8018932C[])(void); @@ -4288,7 +4381,91 @@ INCLUDE_ASM("asm/ov_SC03_002/nonmatchings/ov_SC03_002_jr_8017D604", func_8018029 INCLUDE_ASM("asm/ov_SC03_002/nonmatchings/ov_SC03_002_jr_8017D604", func_801802F4); -INCLUDE_ASM("asm/ov_SC03_002/nonmatchings/ov_SC03_002_jr_8017D604", func_80180378); +#include "common.h" + +/* func_80180378 — per-frame tick for the SC03 cutscene actor at +0x200. + * + * Counts the actor's 0x200 timer down; while it has not underflowed past 0 the + * frame just re-runs the two idle helpers and returns. On the frame the counter + * reaches -1 the burst fires: reload the handler table, re-bind the actor to its + * script, read the actor's world position into a local SVECTOR, then emit six + * particle bursts from func_8017F068, walking the local vector between them + * (y -0x60, y -0x60, z -0x60, y +0x60, y +0x60) and re-rolling the per-burst + * amplitude in D_80189828 each time. Finally kick the six 0x8017F304 effects, + * the 0x842 sound, and hand the actor to func_80171990. + * + * Two levers, both required (this file's house style, §194-E neighbour + * func_80180570 + func_801806F0): + * (1) func_80147A84 IS CALLED WITH NO ARGUMENT — the jal's delay slot is `nop`, + * not `move $a0,$sN` (§263: an arg-register copy in a stolen delay slot is + * an ARITY fact). The TU prototypes it with one s32, so the call goes + * through the TU's cast-the-function-pointer idiom to drop the parameter. + * (2) D_80189828 IS ADDRESSED THROUGH A POINTER LOCAL, not by name. Written as + * `D_80189828 = ...` gcc materialises a fresh `lui $at` for every one of the + * six stores (+6 instructions) even though it already keeps &D_80189828 in + * $s0 for the $a1 argument. A `s16 *pv = &D_80189828;` gives the store and + * the argument one allocno, which is what the target's `sh $v0, 0x0($s0)` + * (and the final `sh $v0, 0x0($a1)`) actually is. + */ + +extern void func_80147A84(s32 arg0); +extern void func_801473EC(s32 *a0); +extern void func_8013C9C4(void *a0); +extern void func_80172358(u8 *a0, u8 *a1); +extern void func_80015978(s32 a0, s32 *a1); +extern s32 rand(void); +extern void func_8017F068(void*, void*, s16, s16); +extern void func_8017F304(s32 arg0); +extern void func_80147324(s32 a0); +extern s32 func_80171990(u8 *a0); + +extern u8 D_80189804[]; +extern u8 D_801897FC[]; +extern s16 D_80189828; + +void func_80180378(s32 arg0) { + u16 pos[4]; + s16 *pv; + + if (--*(s32 *)(arg0 + 0x200) != -1) { + ((void (*)(void))func_80147A84)(); + func_801473EC((s32 *)arg0); + return; + } + + func_8013C9C4(D_80189804); + func_80172358((u8 *)arg0, D_801897FC); + func_80015978(arg0 + 4, (s32 *)pos); + pv = &D_80189828; + + *pv = (rand() & 0x3F) + 0x40; + ((void (*)(void *, void *, s32, s32))func_8017F068)(pos, pv, 0xD50, 8); + pos[1] -= 0x60; + *pv = (rand() & 0x3F) + 0x40; + ((void (*)(void *, void *, s32, s32))func_8017F068)(pos, pv, 0xD50, 8); + pos[1] -= 0x60; + *pv = (rand() & 0x3F) + 0x40; + ((void (*)(void *, void *, s32, s32))func_8017F068)(pos, pv, 0xF00, 8); + pos[2] -= 0x60; + *pv = (rand() & 0x3F) + 0x40; + ((void (*)(void *, void *, s32, s32))func_8017F068)(pos, pv, 0xF00, 8); + pos[1] += 0x60; + *pv = (rand() & 0x3F) + 0x40; + ((void (*)(void *, void *, s32, s32))func_8017F068)(pos, pv, 0xF00, 8); + pos[1] += 0x60; + *pv = (rand() & 0x3F) + 0x40; + ((void (*)(void *, void *, s32, s32))func_8017F068)(pos, pv, 0xF00, 8); + + func_8017F304(0); + func_8017F304(1); + func_8017F304(2); + func_8017F304(3); + func_8017F304(4); + func_8017F304(5); + func_80147324(0x842); + func_80171990((u8 *)arg0); +} + extern void func_80147060(u8*); extern void func_80172358(u8*, u8*); diff --git a/src/ov_SC03_028/ov_SC03_028_jr_8017DF98.c b/src/ov_SC03_028/ov_SC03_028_jr_8017DF98.c index 8b7da32fe..657ff43e4 100644 --- a/src/ov_SC03_028/ov_SC03_028_jr_8017DF98.c +++ b/src/ov_SC03_028/ov_SC03_028_jr_8017DF98.c @@ -4444,7 +4444,166 @@ void func_80181414(void *a0) { } -INCLUDE_ASM("asm/ov_SC03_028/nonmatchings/ov_SC03_028_jr_8017DF98", func_8018150C); +#include "common.h" + +/* Card: func_8018150C (ov_SC03_028, jr_8017DF98 TU), 209 ins, lane=t5h. + * Fresh crack from the target asm — the pack's warm-start body was a DIFFERENT + * function (a 4-line +0x98/D_801EDA08 guard) and was discarded outright. + * + * Structural twin in this same TU: func_80182494 (grid of func_8012D5E4 hit + * tests -> squared-distance-vs-threshold escape gate). Its L3 (const-before-load) + * and L4 (alias-kill ordering) levers were reused verbatim and were right first + * try; everything below is what THAT card did not already cover. + * + * MATCH levers (84 -> 21 -> 9 -> 5 -> 2 -> 0): + * L1 (LENGTH, 210->209) gcc-2.7.2 loop.c hoists only the FIRST of two sibling + * loop-invariants of equal cost. The target has `sll $s4,$s0,11` in the + * preheader but `sll $v1,$s3,11` INSIDE the loop. Writing BOTH multipliers + * inline as `(x << 11)` / `(vz << 11)` reproduces that asymmetry exactly. + * Promoting either one to its own named variable makes the OTHER the first + * movable, so it gets hoisted too -> a 210th instruction. Do not "help" gcc + * by naming the shifted value. + * L2 (12 ins: whole callee-saved file permuted) `&sp18` must be a POINTER LOCAL + * assigned BEFORE the loop, not `(s32)&sp18` spelled at both call sites. + * Spelled inline, the post-loop `func_80133784` argument gets merged with the + * loop's hoisted address pseudo (`move $a2,$s7`), which stretches that + * allocno across the middle of the function, lowers its global-alloc priority + * (priority ~ n_refs/live_length) and shifts EVERY callee-saved assignment by + * one. With the pointer local the range dies at the loop and the target + * re-materializes `addiu $a2,$sp,0x18` on its own. + * L3 (4 ins: preheader emission order) the preheader emits source statements + * first, then loop.c's hoisted invariants in RTL first-use order. The target + * order is x, i, -0x10, &sp18, 1, 4, -0x40 — so the loop-init must come + * FIRST (`x = -0x50; i = 0;` hoisted out of the `for (;;)` header) and the + * -0x10 constant must be a named local placed just before the pointer. + * A pointer assignment written above the `for` init lands one slot early. + * L4 (3 ins: $a1 vs $a0 on the escape flag) §176-B addendum — it is not WHETHER + * you merge but WHICH allocno you merge into. A fresh `flag` local first-fits + * onto dy's dead $a1; writing the 0/1 through `dsq` ITSELF (if/else on the + * same variable) lands it in $a0, the register the target uses. gcc emits no + * extra `j` for this if/else — the arms are a single move each. + * A `register s32 flag __asm__("$4")` pin instead REGRESSED 5 -> 9 (it + * reserved $a0 function-wide and evicted dsq), and pinning dsq gave 7: + * §176-B4 / §72 confirmed again — reuse before pins. + * L5 (2 ins: $v0 vs $s0 on the cos term) same donor law, callee-saved side. + * `vx` as a fresh local dies before `jal func_80047948` (sched1 sinks the + * hoisted `sll` above the call), so local-alloc hands it call-clobbered $v0. + * Reusing the FIRST loop's induction variable `x` — already a global allocno + * living in $s0 because it spans loop 1's calls — donates $s0 to it, exactly + * as the target has it. `register s32 vx __asm__("$16")` instead exploded to + * 65 mismatches (it evicted $s1/the `a0` copy): §176-C's warning holds. + * + * Byte-proven: match_one MATCH 209/209, plus a law-1c relocation walk — + * all 21 relocations (12 R_MIPS_26 + 4 D_80126B96 + 2 D_801ADC24 HI16/LO16 + * pairs, counted as emitted) identical to the target .s in order. + */ + +extern s32 func_8012DEB8(s32 a0, s32 a1, s32 a2); +extern s32 func_8012D5E4(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_8012CBCC(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8012A828(s32 a0, void *a1); +extern s32 func_8004787C(s32 a0); +extern s32 func_80047948(s32 a0); +extern s32 func_80133784(s32 a0, void *a1, s32 a2); +extern s32 func_8012C658(s32 a0, s32 a1, s32 a2); +extern s32 rand(void); + +extern u16 D_80126B96; +extern u8 D_801ADC24[]; + +typedef struct { s16 vx, vy, vz, pad; } SV_8018150C; + +void func_8018150C(s32 a0) { + s32 s1 = a0; + SV_8018150C sp10; + SV_8018150C sp18; + s32 i; + s32 x; /* L5: also the cos term, to donate $s0 */ + s32 dz, dy, dsq, thresh; + s32 vz; + s32 prim; + SV_8018150C *q; /* L2 */ + s32 k; /* L3 */ + s16 t; + + t = *(s16 *)(s1 + 0x108); + if (t != 0) { + *(s16 *)(s1 + 0x108) = t - 1; + } else { + *(s16 *)(s1 + 0x108) = 7; + func_8002D4C8(0x6C1, 0); + } + + sp10.vz = -0x40; + sp18.vz = -0x60; + x = -0x50; + i = 0; + k = -0x10; + q = &sp18; + for (; i < 6; i++, x += 0x20) { + sp10.vx = x; + sp18.vx = x; + sp10.vy = k; + sp18.vy = k; + if (func_8012DEB8(s1, (s32)&sp10, (s32)q) == 1) { + D_80126B96 = 4; + } + sp10.vy = -0x40; + sp18.vy = -0x40; + if (func_8012D5E4(s1, (s32)&sp10, (s32)q, 0x18) == 1) { + D_80126B96 = 4; + } + } + + func_8012CBCC(s1); + + thresh = 0x14400; + dz = *(s16 *)(s1 + 0xE) - 0x3C0; + dsq = dz * dz; + dy = (s16)*(u16 *)(s1 + 6); + if (dsq < 0x1901) { + dsq += 0x4000; + } + dsq += dy * dy; + if (dsq < thresh) { + dsq = 0; /* L4: the escape flag IS dsq */ + } else { + dsq = 1; + *(s32 *)(s1 + 0x10) = 0; + *(s32 *)(s1 + 0x18) = 0; + *(u16 *)(s1 + 6) -= dy >> 5; + *(u16 *)(s1 + 0xE) -= dz >> 5; + } + if (dsq == 0) { + return; + } + + *(s16 *)(s1 + 2) = 5; + func_8012A828(s1, D_801ADC24); + *(s32 *)(s1 + 0x1C) = 1; + sp10.vx = *(u16 *)(s1 + 6); + sp10.vz = *(u16 *)(s1 + 0xE); + sp18.vx = *(u16 *)(s1 + 6) - ((func_8004787C(*(s16 *)(*(s32 *)(s1 + 0x20) + 0x12)) << 7) >> 12); + sp18.vz = *(u16 *)(s1 + 0xE) - ((func_80047948(*(s16 *)(*(s32 *)(s1 + 0x20) + 0x12)) << 7) >> 12); + if ((func_80133784(0x11, &sp10, (s32)&sp18) & 0x8000) == 0) { + return; + } + + x = (func_8004787C(*(s16 *)(*(s32 *)(s1 + 0x20) + 0x12)) << 6) >> 12; + vz = (func_80047948(*(s16 *)(*(s32 *)(s1 + 0x20) + 0x12)) << 6) >> 12; + for (i = 0; i < 0x10; i++) { + prim = func_8012C658(0xFE, 3, s1); + if (prim != 0) { + *(u16 *)(prim + 6) -= (func_8004787C(*(s16 *)(*(s32 *)(s1 + 0x20) + 0x12) + (rand() & 0x3FF) - 0x200) << 6) >> 12; + *(u16 *)(prim + 0xE) -= (func_80047948(*(s16 *)(*(s32 *)(s1 + 0x20) + 0x12) + (rand() & 0x3FF) - 0x200) << 6) >> 12; + *(s32 *)(prim + 0x10) = *(s32 *)(prim + 0x10) * (x << 11); + *(s32 *)(prim + 0x18) = *(s32 *)(prim + 0x18) * (vz << 11); + *(u16 *)(prim + 0xA) -= 0x7E; + } + } +} + INCLUDE_ASM("asm/ov_SC03_028/nonmatchings/ov_SC03_028_jr_8017DF98", func_80181850); 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 342e69f60..9da3b1c17 100644 --- a/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c +++ b/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c @@ -3633,7 +3633,28 @@ void func_8017E67C(s32 a0) { } -INCLUDE_ASM("asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_8017C8D0", func_8017E6C0); +#include "common.h" + +extern void func_801292C8(void); + +void func_8017E6C0(s32 a0) { + s32 s1; + s32 msk; + s32 pad[2]; + (void)&pad; + + s1 = *(s32 *)(a0 + 0x2C); + if (*(u16 *)s1 == 0) { + ((void (*)(s32))func_801292C8)(a0); + } + msk = 0x80000000; + if (*(s32 *)(*(s32 *)(s1 + 0x20) + 4) < 0) { + *(s32 *)(*(s32 *)(a0 + 0x20) + 4) |= msk; + } else { + *(s32 *)(*(s32 *)(a0 + 0x20) + 4) &= 0x7FFFFFFF; + } +} + extern void (*D_8018DED0[])(void); diff --git a/src/ov_SC03_116/ov_SC03_116_jr_8017AE2C.c b/src/ov_SC03_116/ov_SC03_116_jr_8017AE2C.c index 3c958566d..88d769657 100644 --- a/src/ov_SC03_116/ov_SC03_116_jr_8017AE2C.c +++ b/src/ov_SC03_116/ov_SC03_116_jr_8017AE2C.c @@ -4494,7 +4494,73 @@ void func_8018117C(s32 a0) INCLUDE_ASM("asm/ov_SC03_116/nonmatchings/ov_SC03_116_jr_8017AE2C", func_80181204); -INCLUDE_ASM("asm/ov_SC03_116/nonmatchings/ov_SC03_116_jr_8017AE2C", func_801812AC); +extern s32 func_80017758(void *a0, void *a1); +extern s32 func_80017DC4(void *a0, void *a1); + +typedef struct { s16 vx, vy, vz, pad; } SVec8_801812AC; +typedef struct { s16 m[3][3]; s32 t[3]; } Mtx_801812AC; +typedef struct { s16 x, y, z; } V3_801812AC; +typedef struct { u8 b[8]; } Blk8_801812AC; +typedef struct { + SVec8_801812AC v[4]; + s32 c[4]; + s32 code; +} Prim_801812AC; + +extern V3_801812AC D_80194EEC[]; +extern V3_801812AC D_80194FC0[]; +extern int (*D_8018633C[])(void); + +void func_801812AC(s32 a0, void *a1, void *a2, s32 a3, s32 a4) +{ + Mtx_801812AC mtx; + Prim_801812AC prim; + s32 pad[4]; + Prim_801812AC *pr; + V3_801812AC *p; + V3_801812AC *q; + s32 i; + + pr = &prim; + p = &D_80194EEC[((s16 *)a1)[0]]; + q = &D_80194FC0[((s16 *)a1)[0]]; + if (a3 != 0) { + func_80017DC4((void *)D_8018633C, &mtx); + } else { + func_80017DC4(a2, &mtx); + } + mtx.t[0] = 0; + mtx.t[1] = -0x100; + mtx.t[2] = 0x1EC0; + pr->code = 0x50000000; + pr->c[0] = pr->c[1] = a4; + pr->c[2] = pr->c[3] = 0; + for (i = ((s16 *)a1)[0]; i < ((s16 *)a1)[1]; i++) { + pr->v[0].vx = p[0].x; + pr->v[0].vy = p[0].y; + pr->v[0].vz = p[0].z; + pr->v[1].vx = p[1].x; + pr->v[1].vy = p[1].y; + pr->v[1].vz = p[1].z; + if (a3 == 0) { + pr->v[2].vx = q[0].x; + pr->v[2].vy = q[0].y; + pr->v[2].vz = q[0].z; + pr->v[3].vx = q[1].x; + pr->v[3].vy = q[1].y; + pr->v[3].vz = q[1].z; + } else { + *(Blk8_801812AC *)&pr->v[2] = *(Blk8_801812AC *)&pr->v[0]; + *(Blk8_801812AC *)&pr->v[3] = *(Blk8_801812AC *)&pr->v[1]; + pr->v[2].vz -= 8; + pr->v[3].vz -= 8; + } + func_80017758(pr, &mtx); + p++; + q++; + } +} + extern void (*D_80186344[])(void); 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 6953a6517..27324f3c3 100644 --- a/src/ov_SC04_016/ov_SC04_016_jr_8017BEBC.c +++ b/src/ov_SC04_016/ov_SC04_016_jr_8017BEBC.c @@ -3488,7 +3488,47 @@ void func_8017DD18(void *arg0) { } -INCLUDE_ASM("asm/ov_SC04_016/nonmatchings/ov_SC04_016_jr_8017BEBC", func_8017DDA0); +extern void func_8012B200(u8 *a0); +extern void func_8012B1B4(s32 a0, s32 a1); +extern void func_8012AD80(s32 a0); +extern s32 func_8012A828(void *a0, void *a1); +extern void func_8012B2CC(s32 a0); + +s32 func_8017DDA0(s32 param_1) +{ + short *psVar2; + s32 uVar1; + + psVar2 = *(short **)(param_1 + 0xdc); + uVar1 = 0; + if (psVar2 != (short *)0x0) { + if (*(s32 *)(param_1 + 0x1c) == 0) { + if (*psVar2 == 0) { + func_8012B200((u8 *)param_1); + if (*(s32 *)(param_1 + 0xec) != 0) { + func_8012A828((void *)param_1, *(void **)(param_1 + 0xec)); + } + *(s32 *)(param_1 + 0xec) = 0; + *(short **)(param_1 + 0xdc) = 0; + return 0; + } + *(s32 *)(param_1 + 0x1c) = *psVar2; + psVar2 += 1; + *(short *)(*(s32 *)(param_1 + 0x20) + 0x12) = *psVar2; + psVar2 += 1; + *(short *)(param_1 + 0xea) = *psVar2; + func_8012B2CC(param_1); + psVar2 += 1; + *(short **)(param_1 + 0xdc) = psVar2; + } + *(s32 *)(param_1 + 0x1c) = *(s32 *)(param_1 + 0x1c) + -1; + func_8012B1B4(param_1, param_1 + 0xe0); + func_8012AD80(param_1); + uVar1 = 1; + } + return uVar1; +} + extern u8 D_80184C6C[]; extern u8 D_80184C74[]; @@ -3833,7 +3873,112 @@ void func_8017E6A0(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_016/nonmatchings/ov_SC04_016_jr_8017BEBC", func_8017E6E0); +#include "common.h" + +extern u8 D_801ABB40[]; +extern u8 D_801ABB44[]; +extern void func_8001D074(s32, s32); +extern void func_800233CC(void *, unsigned short); +extern void func_8001CD9C(int, void *); + +s32 func_8017E6E0(void *arg0) { + /* [T51] scoped in from file scope: keep these decls local so a file-scope + decl of the same names cannot constrain the neighbours (cookbook §103). */ + extern u8 D_801ABB4C[]; + extern u8 D_801ABB4D[]; + extern u8 D_801ABB4E[]; + extern u8 D_801ABB50[]; + extern u8 D_801ABB51[]; + extern u8 D_801ABB52[]; + extern u8 D_80184C88[]; + extern u8 D_80184C8A[]; + extern u8 D_80184C8C[]; + s32 i; + s32 off; + s32 off2; + u8 *pk; + s32 *cnt; + s32 v; + s32 r; + s16 t; + s32 *pf; + s32 *pt; + s32 *pc; + u8 *q; + + i = 0; + pk = D_801ABB4C; + cnt = (s32 *)(pk - 4); + off = 0; + do { + if (*(s32 *)(D_801ABB40 + off) != 0) { + v = *cnt; + if (v > 0x10) { + v -= 4; + *cnt = v; + func_800233CC(pk, v & 0xFFFF); + } + } + pk += 0x4C; + cnt = (s32 *)((u8 *)cnt + 0x4C); + i++; + off += 0x4C; + } while (i < 0x14); + + if (*(s16 *)((u8 *)arg0 + 0x100) >= 0xC) { + return 1; + } + t = *(s16 *)((u8 *)arg0 + 0x102) - 1; + *(s16 *)((u8 *)arg0 + 0x102) = t; + if (t == -1) { + /* two explicit stores, NOT a ternary/temp: the cross-jumped tail is what + keeps the `sh 0x102` at the merge label instead of letting sched2 sink it */ + if (*(s16 *)((u8 *)arg0 + 0x100) < 4) { + *(s16 *)((u8 *)arg0 + 0x102) = 8; + } else { + *(s16 *)((u8 *)arg0 + 0x102) = 1; + } + i = 0; + pt = (s32 *)D_801ABB44; + pc = (s32 *)(D_801ABB44 + 4); + pf = (s32 *)(D_801ABB44 - 4); + off2 = 0; + *(s16 *)((u8 *)arg0 + 0x104) = *(s16 *)((u8 *)arg0 + 0x104) + 4; + do { + if (*pf == 0) { + r = ((s32 (*)(s32, s32))func_8001D074)(0x3E, 0x7D); + *pt = r; + if (r == 0) { + break; + } + *pf = 1; + q = D_801ABB4C + off2; + *pc = 0x80; + func_8001CD9C(*pt, q); + D_801ABB4D[off2] = 0xE0; + D_801ABB4C[off2] = 0; + D_801ABB4E[off2] = 0x88; + D_801ABB50[off2] = 0; + D_801ABB51[off2] = 0; + D_801ABB52[off2] = 0; + func_800233CC(q, *(u16 *)pc); + *(u16 *)(*pt + 8) = *(u16 *)(D_80184C88 + *(s16 *)((u8 *)arg0 + 0x100) * 8); + *(u16 *)(*pt + 0xA) = *(u16 *)(D_80184C8A + *(s16 *)((u8 *)arg0 + 0x100) * 8); + *(u16 *)(*pt + 0xC) = *(u16 *)(D_80184C8C + *(s16 *)((u8 *)arg0 + 0x100) * 8); + *(s32 *)(*pt + 4) |= 0x50000040; + *(s16 *)((u8 *)arg0 + 0x100) = *(s16 *)((u8 *)arg0 + 0x100) + 1; + break; + } + pt = (s32 *)((u8 *)pt + 0x4C); + pc = (s32 *)((u8 *)pc + 0x4C); + pf = (s32 *)((u8 *)pf + 0x4C); + i++; + off2 += 0x4C; + } while (i < 0x14); + } + return 0; +} + #include "common.h" diff --git a/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c b/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c index 9a1a1298f..580fc9a95 100644 --- a/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c +++ b/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c @@ -5412,7 +5412,79 @@ extern s16 D_8019F070; } -INCLUDE_ASM("asm/ov_SC07_002/nonmatchings/ov_SC07_002_jr_8017C8D0", func_80181A14); +extern s32 func_8012C1B8(void); +extern void func_8012CAE4(s32 a0); +extern void func_8001C214(s32 a0, s32 a1); +extern void func_80181F98(s32*, s32*); +extern void func_80181BD8(); +extern s32 func_8012C658(s32 a0, s32 a1, s32 a2); +extern void func_80181C80(a0); + +extern u16 D_8019FF8A; +extern s16 D_8019F070; + +extern s32 D_8018A3AC[]; +extern void (*D_8018A3D4[])(void); +extern u8 D_80196C04[]; +extern s32 D_80196BEC[]; + +typedef struct { u16 v; u16 pad; } Rec4; +extern Rec4 D_8018A3C0[]; +extern Rec4 D_8018A3C2[]; + +typedef struct { s32 v; s32 pad; } Rec8; +extern Rec8 D_8019F074[]; +extern Rec8 D_8019F078[]; + +void func_80181A14(int param_1) +{ + s32 v0; + u16 v1; + + v0 = func_8012C1B8(); + *(s32 *)(param_1 + 0x20) = v0; + if (v0 == 0) { + func_8012CAE4(param_1); + return; + } + + if (*(s16 *)(param_1 + 0x70) == 0) { + D_8019FF8A = 0; + D_8019F070 = 0; + } + + v1 = *(u16 *)(param_1 + 0x70); + if ((v1 & 0x100) == 0) { + func_8001C214(*(s32 *)(param_1 + 0x20), D_8018A3AC[(s16)v1]); + *(s32 *)(*(s32 *)(param_1 + 0x20) + 0x28) = 0xB000D0; + *(s32 *)(param_1 + 0x58) = (s32)D_8018A3D4 | 0x40000000; + *(u16 *)(param_1 + 0x5c) = 0xC800; + *(u8 *)(param_1 + 0x75) = 0; + ((void (*)(s32, s32))func_80181F98)(param_1, (s32)D_80196C04 + (*(s16 *)(param_1 + 0x70)) * 12); + + *(u16 *)(param_1 + 6) = *(u16 *)(param_1 + 6) + D_8018A3C0[*(s16 *)(param_1 + 0x70)].v; + *(u16 *)(param_1 + 0xE) = *(u16 *)(param_1 + 0xE) + D_8018A3C2[*(s16 *)(param_1 + 0x70)].v; + + if (*(s16 *)(param_1 + 0x70) == 0) { + s32 bi, bj; + for (bi = 0, bj = 0; bi < 0x14; bi += 4, bj += 8) { + *(s32 *)((u8 *)D_8019F078 + bj) = 0; + *(s32 *)((u8 *)D_8019F074 + bj) = *(s32 *)((u8 *)D_80196BEC + bi); + } + } + + func_80181BD8(param_1); + func_8012C658(0x4A, *(s16 *)(param_1 + 0x70), param_1); + } else { + v1 = v1 & 0xFF; + *(u16 *)(param_1 + 0x70) = v1; + func_8001C214(*(s32 *)(param_1 + 0x20), (s32)&D_8019F074[v1]); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x2c) = + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x2c) | 0x10; + ((void (*)(s32))func_80181C80)(param_1); + } +} +