feat(phase-26): h_seq family sweep — 25 member-matches banked via remap_hseq

This commit is contained in:
Drew T
2026-08-17 21:04:21 -06:00
parent 3e859e75c2
commit 200ee2fbeb
10 changed files with 1881 additions and 35 deletions
+175 -2
View File
@@ -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)
+179 -2
View File
@@ -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);
+44 -1
View File
@@ -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
+44 -1
View File
@@ -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
+44 -1
View File
@@ -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
+186 -4
View File
@@ -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);
+152 -3
View File
@@ -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);
+152 -3
View File
@@ -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);
+523 -13
View File
@@ -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);
+382 -5
View File
@@ -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);