diff --git a/config/overlays.mk b/config/overlays.mk index 90279f26b..760eb82b9 100644 --- a/config/overlays.mk +++ b/config/overlays.mk @@ -4592,6 +4592,7 @@ build/src/ov_SC06_029/ov_SC06_029_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC06_029/ov_SC06_029_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC06_029/ov_SC06_029_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC06_029/ov_SC06_029_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 +build/src/ov_SC06_029/ov_SC06_029_jr_8017C954.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC06_029/ov_SC06_029_o0c.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC06_029_CHECK_SHA := config/check.ov_SC06_029.sha ov_SC06_029_SYMBOLS := config/symbols.ov_SC06_029.txt diff --git a/config/splat.ov_SC06_029.yaml b/config/splat.ov_SC06_029.yaml index 74198f832..e80dfb08b 100644 --- a/config/splat.ov_SC06_029.yaml +++ b/config/splat.ov_SC06_029.yaml @@ -164,7 +164,7 @@ segments: - [0xb3468, .rodata, ov_SC06_029_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0xb347c, data, tail18] - [0xb35b4, .rodata, ov_SC06_029_jr_8017C954] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0xb35d4, data, tail19] + - [0xb3608, data, tail19] - [0xBA034, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0xBA037] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c b/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c index 0e4db2617..519820f60 100644 --- a/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c +++ b/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c @@ -5151,7 +5151,66 @@ void func_8017EB14(void) } -INCLUDE_ASM("asm/ov_SC04_015/nonmatchings/ov_SC04_015_jr_8017AE2C", func_8017EB78); +extern s32 AddPrim(s32, void *); +extern void *func_80010A08(s32); +extern s32 GetClut(s32, s32); +extern s32 GetTPage(s32, s32, s32, s32); +extern s32 D_800A651C; +extern s16 D_800B9A02; + +void func_8017EB78(void *arg0) +{ + /* frame: vars = 0x50 - ROUND8(args 0x10) - ROUND8(4*5 regs) = 0x28 (cookbook 164-53/162i1) */ + s32 pad[10]; + u8 *s; + u8 *p; + s32 X, Y; + s32 u; + s32 tA, tB, u2; + u8 u_lo, y_lo; + + s = (u8 *)arg0; + X = *(s16 *)(s + 0x10); + __asm__(""); + Y = *(s16 *)(s + 0x12); + + p = (u8 *)func_80010A08(0x28); + *(u16 *)(p + 0xE) = GetClut(*(s16 *)(s + 0x18), *(s16 *)(s + 0x1A)); + *(u16 *)(p + 0x16) = GetTPage(0, 0, X & -0x40, Y & -0x100); + + p[3] = 9; + *(u32 *)(p + 4) = 0x808080; + p[7] = 0x2C; + + u = (X & 0x3F) << 2; + u_lo = u; + y_lo = Y; + p[0xC] = u_lo; + p[0xD] = y_lo; + tA = u + s[0x14]; + p[0x14] = tA; + p[0x15] = y_lo; + p[0x1C] = u_lo; + tB = Y + s[0x16]; + p[0x1D] = tB; + u2 = u; + u2 += s[0x14]; + p[0x24] = u2; + Y += s[0x16]; + p[0x25] = Y; + + *(s16 *)(p + 0x8) = *(u16 *)(s + 0x0); + *(s16 *)(p + 0xA) = *(u16 *)(s + 0x2); + *(s16 *)(p + 0x10) = *(u16 *)(s + 0x4); + *(s16 *)(p + 0x12) = *(u16 *)(s + 0x6); + *(s16 *)(p + 0x18) = *(u16 *)(s + 0x8); + *(s16 *)(p + 0x1A) = *(u16 *)(s + 0xA); + *(s16 *)(p + 0x20) = *(u16 *)(s + 0xC); + *(s16 *)(p + 0x22) = *(u16 *)(s + 0xE); + + AddPrim(*(s32 *)((u8 *)&D_800A651C + ((u16)D_800B9A02 * 0x14)) + 4, p); +} + extern void func_80016714(void *a0, s32 a1); extern s32 D_801C8C64; diff --git a/src/ov_SC05_008/ov_SC05_008_jr_8017AE2C.c b/src/ov_SC05_008/ov_SC05_008_jr_8017AE2C.c index 3ca11cbfd..6abadaa2e 100644 --- a/src/ov_SC05_008/ov_SC05_008_jr_8017AE2C.c +++ b/src/ov_SC05_008/ov_SC05_008_jr_8017AE2C.c @@ -4629,7 +4629,147 @@ void func_8017E354(s32 param_1) { } -INCLUDE_ASM("asm/ov_SC05_008/nonmatchings/ov_SC05_008_jr_8017AE2C", func_8017E464); +void func_8017E464(s32 param_1) { + /* [T51/§103] decls scoped into the body: this TU already declares + func_8017E6A4()/func_8017EAE4(s32)/D_801A10xx at file scope above the + INCLUDE_ASM, and defines func_8017E850(s32,s32)/func_8017EAB0(s32) + BELOW it -- so every spelling here is the TU's own (law 2). */ + extern s32 D_80126B58; + extern s32 D_801A1080[]; + extern s32 D_801A1084; + extern s32 D_801A1088; + extern s32 D_801A108C; + extern u8 func_8014BFD4(void); + extern void func_8014BF8C(u8 arg0); + extern void func_8002D4C8(s32 a0, s32 a1); + extern void func_80015978(s32 a0, s32 *a1); + extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); + extern void func_8017E850(); + extern void func_8017E6A4(); + extern void func_8017EAB0(); + extern void func_8017EAE4(s32); + extern void func_80182694(s32 a0, s32 a1); + extern s32 rand(void); + + register s32 p __asm__("$17"); + register s32 *q __asm__("$19"); + register s32 *flag __asm__("$2"); + register s32 aa __asm__("$4"); + register s32 nn __asm__("$5"); + register s32 pp __asm__("$6"); + s32 s0; + s32 t; + s32 i; + s16 v; + /* §137/§176-B: the tail read-modify-write group is transcribed through + four hard-register pins. Unpinned it schedules right but first-fits + $a0/$a1 (REGALLOC-PERM/$a0>$a1>$a2); two pins alone give the registers + but float the $a1 load to the block head. Pinning the WHOLE group -- + both halves reusing $2/$3 -- fixes schedule and allocation together. */ + register u16 b0 __asm__("$2"); + register u16 e0 __asm__("$3"); + register u16 c1 __asm__("$5"); + register u16 c2 __asm__("$6"); + u16 buf[4]; + u16 d[4]; + + p = param_1; + func_8017E850(); + func_8017E6A4(p); + func_8017EAB0(p, 0); + func_8017EAB0(p, 1); + func_8017EAE4(p); + + v = *(s16 *)(p + 0xFC); + q = &D_80126B58; + if (v == 0) { + if (*(s16 *)(p + 0xFE) != 0) { + s0 = func_8014BFD4(); + switch (s0) { + case 4: + aa = 0x209; + nn = 0; + pp = p; + flag = D_801A1080; + goto tail; + case 3: + aa = 0x209; + nn = 1; + pp = p; + flag = &D_801A1084; + goto tail; + case 2: + aa = 0x209; + nn = 2; + pp = p; + flag = &D_801A1088; + goto tail; + case 1: + aa = 0x209; + nn = 3; + pp = p; + flag = &D_801A108C; + tail: + *flag |= 0x1000000; + func_8012C658(aa, nn, pp); + func_8002D4C8(0x8BB, 0); + break; + } + *(s16 *)(p + 0xFC) = 0x3C; + s0 = s0 - 1; + if (s0 < 0) { + s0 = 0; + } + func_8014BF8C(s0); + } + } else { + *(s16 *)(p + 0xFC) = v - 1; + i = 0; + do { + i = i + 1; + s0 = rand(); + t = rand(); + s0 &= 0xF; + s0 <<= 2; + t = (t & 0x1F) - 0x30; + s0 = s0 + t; + d[0] = s0; + s0 = rand(); + t = rand(); + s0 &= 0xF; + s0 <<= 2; + t = (t & 0x1F) - 0x30; + s0 = s0 + t; + d[1] = s0; + s0 = rand(); + t = rand(); + aa = (s32)(q + 1); + nn = (s32)buf; + __asm__ __volatile__("" ::: "memory"); + s0 &= 0x1F; + s0 <<= 2; + t = (t & 0x1F) - 0x50; + s0 = s0 + t; + d[2] = s0; + func_80015978(aa, (s32 *)nn); + b0 = buf[0]; + e0 = d[0]; + c1 = d[1]; + c2 = d[2]; + b0 = b0 + e0; + buf[0] = b0; + b0 = buf[1]; + e0 = buf[2]; + b0 = b0 + c1; + e0 = e0 + c2; + buf[1] = b0; + buf[2] = e0; + func_80182694((s32)buf, *(s16 *)(p + 0x100)); + } while (i < 0xA); + } + *(s16 *)(p + 0xFE) = 0; +} + // @class: align-1 block move + sched1 load-delay fence // The 8-byte sp+0x10 -> D_80126BE0 copy is an ALIGN-1 STRUCT ASSIGN (cookbook §160a / diff --git a/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c b/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c index d61569bf8..3bdd5dc3b 100644 --- a/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c +++ b/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c @@ -4263,7 +4263,154 @@ void func_8017EF04(s32 a0) { } -INCLUDE_ASM("asm/ov_SC06_029/nonmatchings/ov_SC06_029_jr_8017C954", func_8017EF34); +/* func_8017EF34 — ov_SC06_029 / ov_SC06_029_jr_8017C954 (243 ins, 13-way jtbl switch). + * Every symbol below is spelled from this .s's own relocation lines. Cases 8/0xA read + * D_801DDB30..3C, written here as D_801DDB2C[1..4] (the TU's §183 TYPE-adopted s32[5]; + * %hi/%lo(D_801DDB2C+4k) resolve to identical bytes). Callee decls copied verbatim from + * the TU: func_80181170 / func_8012BEE8 are `void (void)` there, so the a0-passing calls + * go through the TU's own function-pointer casts. + * Shape levers (Attempt-1 record): duplicate the shared tails per case and let + * cross-jumping re-merge them; case 1 as sequential guarded ifs; init pointer before the + * counter with `p++; i++`; one shared counter + a distinct pointer var per loop; the AND + * mask in an explicit local between `i = 0` and the pointer init. */ +void func_8017EF34(s32 param_1) { + extern s32 D_801DDB2C[]; + extern s32 rand(void); + extern void func_8002D4C8(s32 a0, s32 a1); + extern void func_8012BEE8(void); + extern s32 func_80180FE0(s32 a0, s32 a1); + extern void func_80181170(void); + extern s32 func_801812AC(s32 a0); + extern s32 func_80181334(void); + + s32 i; + s32 m; + s32 *p1; + s32 *p2; + s32 *p3; + s32 *p4; + + switch (*(u16 *)(param_1 + 0x34)) { + case 0: + i = 0; + p1 = D_801DDB2C; + do { + *(s32 *)(*p1 + 0xE0) |= 2; + p1 = p1 + 1; + i = i + 1; + } while (i < 5); + *(s32 *)(param_1 + 0x1C) = 0x180; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + func_8002D4C8(0x936, 0); + break; + + case 1: + case 5: + case 9: + if (func_801812AC(0) == 0) { + goto L2E0; + } + func_80180FE0(param_1, rand() % 5); + if ((*(s32 *)(param_1 + 0xE0) & 0x800) == 0) { + if (*(s16 *)(param_1 + 0xFE) >= 3) { + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + } + goto L2E0; + } + if (*(s16 *)(param_1 + 0x104) != *(s16 *)(param_1 + 0xFE)) { + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + goto L2E0; + } + if (((s32 (*)(void *))func_8012BEE8)((void *)param_1) != 0) { + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + ((void (*)(s32))func_80181170)(param_1); + } + goto L2E0; + + case 2: + i = 0; + m = ~2; + p2 = D_801DDB2C; + do { + *(s32 *)(*p2 + 0xE0) &= m; + p2 = p2 + 1; + i = i + 1; + } while (i < 5); + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + break; + + case 3: + case 7: + case 0xB: + if (func_80181334() == 1) { + *(u16 *)(param_1 + 0x34) = 0xC; + *(s32 *)(param_1 + 0x1C) = 0x20; + func_8002D4C8(4, 0x936); + ((void (*)(s32))func_80181170)(param_1); + } + break; + + case 4: + i = 0; + p3 = D_801DDB2C; + do { + *(s32 *)(*p3 + 0xE0) |= 1; + p3 = p3 + 1; + i = i + 1; + } while (i < 5); + *(s32 *)(param_1 + 0x1C) = 0x180; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + func_8002D4C8(0x936, 0); + break; + + case 6: + i = 0; + m = ~1; + p4 = D_801DDB2C; + do { + *(s32 *)(*p4 + 0xE0) &= m; + p4 = p4 + 1; + i = i + 1; + } while (i < 5); + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + break; + + case 8: + *(s32 *)(D_801DDB2C[0] + 0xE0) |= 1; + *(s32 *)(D_801DDB2C[1] + 0xE0) |= 2; + *(s32 *)(D_801DDB2C[2] + 0xE0) |= 1; + *(s32 *)(D_801DDB2C[3] + 0xE0) |= 2; + *(s32 *)(D_801DDB2C[4] + 0xE0) |= 1; + *(s32 *)(param_1 + 0x1C) = 0x180; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + func_8002D4C8(0x936, 0); + break; + + case 0xA: + *(s32 *)(D_801DDB2C[0] + 0xE0) &= ~1; + *(s32 *)(D_801DDB2C[1] + 0xE0) &= ~2; + *(s32 *)(D_801DDB2C[2] + 0xE0) &= ~1; + *(s32 *)(D_801DDB2C[3] + 0xE0) &= ~2; + *(s32 *)(D_801DDB2C[4] + 0xE0) &= ~1; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + break; + + case 0xC: + if (((s32 (*)(void *))func_8012BEE8)((void *)param_1) != 0) { + if ((*(s32 *)(param_1 + 0xE0) & 0x800) == 0) { + *(s16 *)(param_1 + 2) = 6; + } else { + *(s16 *)(param_1 + 2) = 0xA; + *(u16 *)(param_1 + 0x102) = *(u16 *)(param_1 + 0x102) + 1; + } + } + break; + } + +L2E0: + *(u16 *)(param_1 + 0x104) = *(u16 *)(param_1 + 0xFE); +} + void func_8017F300(s32 a0) { *(s16 *)(a0 + 0x2) = 7; @@ -7953,7 +8100,63 @@ void func_80185C88(void *arg0) { } -INCLUDE_ASM("asm/ov_SC06_029/nonmatchings/ov_SC06_029_jr_8017C954", func_80185D44); +#include "common.h" + +extern void *D_801DDBF4; /* §183 TYPE-adopted-TU */ +extern u8 D_801A0734[]; /* no fleet decl; spelled like the TU's D_801A0720 */ + +extern s32 func_8012C1B8(void); /* §183 SIGNATURE-adopted-TU */ +extern void func_8012CAE4(void *a0); +extern void func_8001C214(s32 a0, s32 a1); /* §183 SIGNATURE-adopted-TU */ + +/* The `m` split + zero-byte re-tie is a SCHEDULING lever, not semantics. + * sched1 is a BACKWARD list scheduler: picked-first == placed-last, and at equal + * INSN_PRIORITY the tie-break is INSN_LUID with the HIGHER luid picked first + * (sched.c rank_for_schedule:2428, ready[0] taken at :3747). The mask's + * `lui`/`ori` normally arrive as ONE insn that sched1's own try_split (:4830) + * splits into two LUID-ADJACENT halves, so no source order can put the `lui` + * dead-last in the pick order (block position 0) while the `ori` still wins the + * contest against `t = -2` seven picks earlier — the target needs + * luid(lui) < luid(t=0x80) < luid(t=-2) < luid(ori), which adjacency forbids. + * Writing the two halves as two statements with a non-volatile re-tie between + * them (§30#3) keeps cse/combine from re-folding the constant, breaks the + * adjacency, and gives each half its own luid. `t` is deliberately ONE 2-set + * s16 (§49-variant / §199-A): that kills the birthing boost on both constants, + * so `t = -2` is picked after the `ori` instead of the instant it is ready. */ +void func_80185D44(void *a0) { + s32 v0; + s32 v1; + s32 m; + s16 t; + u8 *p; + + v0 = func_8012C1B8(); + *(s32 *)((s32)a0 + 0x20) = v0; + if (v0 == 0) { + func_8012CAE4(a0); + return; + } + func_8001C214(v0, (s32)D_801A0734); + m = 0x7FFF0000; + __asm__("" : "=r"(m) : "0"(m)); + t = 0x80; + *(s16 *)((s32)a0 + 0xE0) = t; + *(s16 *)((s32)a0 + 0xDE) = t; + *(s16 *)((s32)a0 + 0xDC) = t; + t = -2; + *(s16 *)((s32)a0 + 0xE2) = t; + p = (u8 *)D_801DDBF4; + v1 = *(s32 *)((s32)a0 + 0x20); + *(u16 *)(v1 + 0x2C) |= 0x80; + v1 = *(s32 *)((s32)a0 + 0x20); + *(s32 *)(v1 + 0x80) = (s32)a0 + 0xDC; + *(s16 *)(p + 0x1A) = 0x800; + *(s16 *)(p + 0x18) = 0x800; + m |= 0xFFFF; + *(s32 *)(p + 4) &= m; + *(u16 *)((s32)a0 + 2) = *(u16 *)((s32)a0 + 2) + 1; +} + #include "common.h" diff --git a/src/ov_SC06_032/ov_SC06_032_jr_80182890.c b/src/ov_SC06_032/ov_SC06_032_jr_80182890.c index 78e535cf6..53c497a6c 100644 --- a/src/ov_SC06_032/ov_SC06_032_jr_80182890.c +++ b/src/ov_SC06_032/ov_SC06_032_jr_80182890.c @@ -5244,7 +5244,90 @@ void func_80185EAC(s32 param_1) } -INCLUDE_ASM("asm/ov_SC06_032/nonmatchings/ov_SC06_032_jr_80182890", func_80185F4C); +/* func_80185F4C — ov_SC06_032, 60 ins. MATCH (match_one closeness 0, 60/60 ins); + * all 7 relocations verified byte-for-byte against the target .s (law 1c): + * 0x18/0x1C HI16/LO16 D_800AE620 · 0x74 jal func_8012C658 · 0x9C jal RotMatrixY · + * 0xA8/0xAC HI16/LO16 D_801BEF1C · 0xB0 jal func_800484EC. + * + * ===== THE LEVER: §30#3 / §350 BIRTHING-BOOST KILL, APPLIED TO THE CALL-RESULT COPY ===== + * + * Six earlier attempts plateaued at closeness 5/4 with the SAME residual: `addiu $s2,$sp,0x10` + * (= &local) sat in the *jal* delay slot instead of the *beqz* delay slot: + * mine ... move $s1,$a3 ; jal ; [slot addiu $s2,$sp,16] ; move $s0,$v0 ; beqz ; [slot sll] + * tgt ... addu $a2,$v0 ; jal ; [slot addu $s1,$a3] ; addu $s0,$v0 ; beqz ; [slot addiu $s2] + * Every one of them blamed cse (expand_block_move's copy_addr_to_reg minting &local before the + * struct copy, then cse_end_of_basic_block carrying the table past the branch and unifying the + * if-body's `&local` onto it) and hunted for a zero-byte way to BREAK THE CSE BLOCK. That whole + * diagnosis is a red herring: the cse unification is also what the TARGET does. Read the sched + * dump (`cc1 -dS`, block 0 ready-list trace) and the residual is one rank_for_schedule tie: + * + * ;; ready list at T-2: 23 (7f000001) 41 (7f000001), now 41 23 + * + * insn 23 = `reg81 = fp+16` (&local), insn 41 = `reg80 = $v0` (the call result). sched1 runs each + * bb BACKWARD, so the T-2 pick is placed second-from-last, i.e. immediately before the beqz — + * exactly the slot the target fills. BOTH insns carry 0x7f000001 = LAUNCH_PRIORITY, handed out by + * sched.c:adjust_priority -> birthing_insn_p (pre-reload only) to any insn whose dest reg has + * reg_n_sets == 1. With both boosted the tie falls to rank_for_schedule's class/LUID keys and 41 + * (higher LUID, data-dep on the branch => class 3) wins; &local is pushed one pick earlier, lands + * before the jal, and reorg eats it into the CALL's slot. + * + * So the fix is not to move &local at all — it is to DEMOTE ITS RIVAL. `__asm__("" : "=r"(e) : + * "0"(e));` gives the call-result local a second SET, `reg_n_sets(e) == 2` kills its birthing + * boost, insn 41 drops to priority 1, and &local wins T-2 unopposed: + * T-2:23(&local) T-3:41(result copy) T-4:39(jal) T-5:14(move $s1,$a3) + * which reorg then fills as jal-slot=`addu $s1,$a3` / beqz-slot=`addiu $s2,$sp,0x10`. The re-tie + * is non-volatile and zero-byte (no scheduling barrier, no bytes); it must sit in the if-body so + * its output stays live (a re-tie after the last use of `e` is dead and gets deleted, taking + * reg_n_sets back to 1). Placing it as the FIRST statement of the body and placing it just before + * the final store both MATCH; the head position is kept as the more obvious one. + * + * NEW vs. the cookbook (worth banking): §30#3/§350 are both written as "kill the boost ON THE + * VALUE THAT IS SCHEDULED WRONG". Here the mis-scheduled value is unfixable (cse has already + * collapsed the named pointer onto the block-move address pseudo — six attempts proved every + * cse-side lever inert, and the do{}while(0) cse-break that does work costs a save/restore pair + * and only re-poses the same tie inside the if-body). The boost is a RANKING between competitors: + * when the insn you want cannot be promoted, un-boost the insn that is beating it. Diagnostic + * recipe: `cc1 -dS`, read the losing bb's `;; ready list at T-N:` line, and any 0x7f000001 on the + * rival is a reg_n_sets==1 that a zero-byte re-tie can delete. + * + * The declarations follow this TU's house style (sibling func_80186160, same file): block-scope + * externs for the per-overlay D_ symbols, the shared Blk20_8018AF88_80186160 spelling for the + * 32-byte D_800AE620 template, and the s32×4 signature the TU's own forward decl already carries + * (ov_SC06_032_jr_80182890.c:5229) with the (s16) narrowing done at the use sites. + */ + +/* Local standin for the shared type (src/shared/engine_types.h:1406) that the real TU pulls in via + * "../shared/engine_core.h" -- match_one's -Iinclude can't reach src/shared/, so it is typed + * identically for the standalone compile only; DROP THIS LINE when splicing into the TU. */ + + +extern s32 func_8012C658(s32 arg0, s32 arg1, s32 arg2); +extern void RotMatrixY(s32 a0, void *a1); +extern void func_800484EC(s32 a0, s32 a1, s32 a2); + +void func_80185F4C(s32 a0, s32 a1, s32 a2, s32 a3) +{ + extern Blk20_8018AF88_80186160 D_800AE620; + extern s32 D_801BEF1C; + Blk20_8018AF88_80186160 local; + Blk20_8018AF88_80186160 *m; + s32 vec[3]; + s32 e; + + local = D_800AE620; + e = func_8012C658((s16)a1, (s16)a2, a0); + if (e != 0) { + __asm__("" : "=r"(e) : "0"(e)); + m = &local; + *(u16 *)(e + 0xA) = *(u16 *)(e + 0xA) - 0x80; + RotMatrixY((s16)a3, m); + func_800484EC((s32)m, (s32)&D_801BEF1C, (s32)vec); + *(s32 *)(e + 0x10) = vec[0]; + *(s32 *)(e + 0x14) = 0xFFD80000; + *(s32 *)(e + 0x18) = vec[2]; + } +} + extern void func_8012C1B8(void); extern void func_8012CAE4(s32 a0); diff --git a/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c b/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c index 8c049ac3f..7a8e38273 100644 --- a/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c +++ b/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c @@ -6546,7 +6546,104 @@ void func_80180DC4(A801593E4 *a0) { } -INCLUDE_ASM("asm/ov_SC07_010/nonmatchings/ov_SC07_010_jr_8017AE2C", func_80180E68); +#include "common.h" + +extern void func_801811C8(s32 a0); +extern void func_801325B8(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4); +extern void func_801810F8(void *a0); +extern void func_8017DCB8(s32 a0); +extern s32 func_8012AD50(void *a0); +extern s32 D_801151D4; +extern u8 D_8019F5EC; +extern u8 D_8019F8F4; +extern u8 D_8019FBF4; +extern u8 D_801A9287; +extern s32 D_801A9288; +extern u8 D_801A928C; +extern u8 D_801A928D; +extern u8 D_801A928E; +extern u8 D_801A928F; +extern u8 D_801A9290; +extern s16 D_801A9292; +extern u8 D_801A9294; +extern u8 D_801A9295; +extern s16 D_801A9296; +extern s16 D_801A9298; +extern s16 D_801A929A; +extern u8 D_801A929F; +extern s32 D_801A92A0; +extern u8 D_801A92A4; +extern u8 D_801A92A5; +extern u8 D_801A92A6; +extern u8 D_801A92A7; +extern s16 D_801A92A8; +extern s16 D_801A92AA; +extern u8 D_801A92AC; +extern u8 D_801A92AD; +extern s16 D_801A92AE; +extern s16 D_801A92B0; +extern s16 D_801A92B2; + +void func_80180E68(s32 a0) { + s32 obj; + s32 ws; + s32 v; + s16 t; + + obj = *(s32 *)(a0 + 0x20); + + v = *(s16 *)(a0 + 0xFC) * 286 / 60 + 0xD6; + ws = D_801151D4; + *(s32 *)(ws + 0x10) = v; + *(s32 *)(ws + 0x14) = v; + + v = *(s16 *)(a0 + 0xFC) * 0x800 / 60 + 0x400; + *(s16 *)(obj + 0x12) = v; + *(s16 *)(obj + 0x1A) = *(s16 *)(a0 + 0xFC) * 1463 / 60 + 0x249; + func_801811C8(a0); + func_801325B8((s32)&D_8019F5EC, (s32)&D_8019F8F4, (s32)&D_8019FBF4, 0, + *(s16 *)(a0 + 0xFC) * 0x1000 / 60); + + t = *(u16 *)(a0 + 0xFC) + 1; + *(u16 *)(a0 + 0xFC) = t; + if (t >= 0x3D) { + *(s16 *)(a0 + 0xFC) = 0x3C; + *(s32 *)(obj + 4) |= 0x80000000; + func_801810F8((void *)a0); + func_8017DCB8(9); + + D_801A9287 = 5; + D_801A9288 = 0xE10000BB; + D_801A928F = 0x66; + D_801A928E = 0x80; + D_801A928D = 0x80; + D_801A928C = 0x80; + *(s16 *)&D_801A9290 = -0x80; + D_801A9292 = -0x10; + D_801A9294 = 0; + D_801A9295 = 0xE0; + D_801A9296 = 0x7FC0; + D_801A9298 = 0x100; + D_801A929A = 0x20; + + D_801A929F = 5; + D_801A92A0 = 0xE10000BB; + D_801A92A7 = 0x66; + D_801A92A6 = 0x80; + D_801A92A5 = 0x80; + D_801A92A4 = 0x80; + D_801A92A8 = -0x80; + D_801A92AA = -0x10; + D_801A92AC = 0; + D_801A92AD = 0xE0; + D_801A92AE = 0x7FC0; + D_801A92B0 = 0x100; + D_801A92B2 = 0x20; + + func_8012AD50((void *)a0); + } +} + extern s32 func_8017DCC8(void); extern void func_8012C098(void *a0);