diff --git a/src/ov_SC02_011/ov_SC02_011_jr_8017AE2C.c b/src/ov_SC02_011/ov_SC02_011_jr_8017AE2C.c index c6956fce8..342f846d0 100644 --- a/src/ov_SC02_011/ov_SC02_011_jr_8017AE2C.c +++ b/src/ov_SC02_011/ov_SC02_011_jr_8017AE2C.c @@ -8162,7 +8162,130 @@ void func_801826D8(void *a0) { } -INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_80182714); +/* func_80182714 (ov_SC02_011) — MATCH, 189 ins (match_one closeness 0). + * + * Levers (S71a, fable): + * §209 `mode` and `ang` are 16-BIT locals. The target's `addu $v1,$s3` before the + * mode `beq`s and `addu $v1,$s4` before the 0x800/0xB01/0x210 tests are the + * deferred sign-extension copies of s16 locals; `angle` has ONE set + * (`ratan2() & 0xFFF`), so combine proves the sign bit clear and each + * `sign_extend` collapses to a move. `ang = angle` itself is the HImode + * truncation copy ($s4 = $s0) that plain s32 copies coalesce away — no asm + * tie needed (the earlier draft's "=r"/"0" trick and fence are gone). + * §48-A global-alloc priority: with the copies in place ang and mode both have 5 + * refs, and their post-sched1 live lengths tie within one insn (107 vs 108, + * ang first -> ang=$s3, mode=$s4, close=13). Writing `ang = angle;` BEFORE + * the `dist = func_80013294()` call lengthens ang to 109 (zero bytes: sched1 + * still parks the copy in the bnez delay slot) so mode allocates first and + * takes $s3, ang/q share $s4, dist $s5 — byte-exact. + * §199-G/§222/§256 (carried from the s67o2 draft): mode dispatch is a `switch`; + * the redundant `ang >= 0x800` re-test reproduces `beqz $a0,.L80182930`. + */ +#include "common.h" + +void func_80182714(s32 param_1) { + typedef struct { s16 x0, x1, x2, x3; } Blk8S16; + extern s32 D_801E9DA8; + extern s32 D_80126B58; + extern s16 D_80195058[]; + extern s16 D_80126940; + extern s16 D_80126942; + extern s16 D_80126944; + extern u16 func_80148800(s32 *a0); + extern s32 ratan2(s32 dx, s32 dy); + extern s32 func_80013294(void *a0, void *a1); + extern void func_8018B5A8(s32 a0, void *a1, void *a2); + extern void func_80182B88(s32 a0, s32 a1, s32 a2, s32 a3); + + u16 buf[8]; + s16 *base; + u16 *p; + u16 *q; + s32 angle; + s16 ang; + s16 dist; + s16 mode; + + *(Blk8S16 *)&buf[4] = *(Blk8S16 *)&D_801E9DA8; + q = &buf[4]; + mode = 0; + if ((func_80148800(&D_80126B58) & 3) != 0) { + *(u8 *)(param_1 + 5) = (*(u8 *)(param_1 + 5) + 1) & 1; + } + *(s32 *)(param_1 + 0x14) = D_80195058[*(u8 *)(param_1 + 5)]; + base = &D_80126940; + angle = ratan2(*base << 16, D_80126944 << 16) & 0xFFF; + *(Blk8S16 *)&buf[0] = *(Blk8S16 *)base; + p = &buf[0]; + buf[5] = D_80126942; + ang = angle; + dist = func_80013294(p, q); + if (dist >= 0xA01) { + buf[0] = 0; + buf[1] = D_80126942; + buf[2] = 0xA00; + func_8018B5A8(angle, p, p); + buf[0] = (s32)(s16)buf[0] >> 3; + buf[1] = (s32)(s16)buf[1] >> 3; + buf[2] = (s32)(s16)buf[2] >> 3; + } else { + *(s16 *)(param_1 + 0x20) = 0x1C7; + *(s16 *)(param_1 + 0x22) = 0; + *(s16 *)(param_1 + 0x24) = 0; + *(s16 *)(param_1 + 0x2E) = 0; + *(s16 *)(param_1 + 0x30) = 0; + *(s16 *)(param_1 + 0x32) = 0; + } + if (ang >= 0x800) { + if (ang >= 0xB01) goto checks; + if (ang >= 0x800) goto set1c7; + } + if (ang >= 0x210) goto set1c7; +checks: + if (dist < 0x3C1) goto set1c7; + if (*(s16 *)&buf[1] < -0x2FF) goto set1c7; + if (ang < 0xD01) goto arm1; + if (dist < 0x500) { + *(s16 *)(param_1 + 0x20) = 0x31C; + mode = 2; + goto after; + } + mode = 2; + *(s16 *)(param_1 + 0x20) = 0x38E; + *(s32 *)(param_1 + 0x14) = 0x4B0; + goto after; +arm1: + mode = 1; + goto after; +set1c7: + *(s16 *)(param_1 + 0x20) = 0x1C7; +after: + if (dist < 0x200) { + *(s16 *)(param_1 + 0x20) = 0xE3; + *(s16 *)(param_1 + 0x22) = 0; + *(s16 *)(param_1 + 0x24) = 0; + *(s16 *)(param_1 + 0x2E) = 0; + *(s16 *)(param_1 + 0x30) = -0xC0; + *(s16 *)(param_1 + 0x32) = 0; + } + if (dist >= 0x981) { + *(s32 *)(param_1 + 0x14) = 0x384; + } + switch (mode) { + case 1: + *(s16 *)(param_1 + 0x20) = 0x2AA; + *(s32 *)(param_1 + 0x14) = 0x4B0; + break; + case 2: + *(s32 *)(param_1 + 0x14) = 0x4B0; + break; + } + if ((u32)(ang - 0xD01) < 0xFF && (u16)(dist - 0x481) < 0x29F) { + *(s16 *)(param_1 + 0x20) = 0x1C7; + } + func_80182B88(param_1, ang, (s32)&buf[0], (s32)&buf[0]); +} + void func_80182A08(void *a0) { extern s32 ratan2(s32 dx, s32 dy); diff --git a/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c b/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c index fe58ddc82..a7da6192b 100644 --- a/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c +++ b/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c @@ -4880,7 +4880,145 @@ void func_80180AB4(struct Ent_80180AB4 *arg0) { } -INCLUDE_ASM("asm/ov_SC04_011/nonmatchings/ov_SC04_011_jr_8017D494", func_80180B24); +/* func_80180B24 — S71a_1 fable. Body = .run/pool_1/opus (standalone MATCH 215/215); + * integration fix: D_80126B58 spelled through the TU's house __asm__ alias (the TU also + * declares it `u8 []` at block scope in func_80184978, so a file-scope `s32` decl conflicts). */ +struct Ent_80180B24 { + /* 0x00 */ u8 pad00[0x34]; + /* 0x34 */ u16 unk34; + /* 0x36 */ u8 pad36[0xBC]; + /* 0xF2 */ u16 unkF2; + /* 0xF4 */ u16 unkF4; +}; +extern u16 D_801EFD20; +extern u16 D_801EFD40; +extern s32 aB58_80180B24[1] __asm__("D_80126B58"); +extern s32 aFC4C[] __asm__("D_801EFC4C"); +extern u8 D_80194470[]; +extern void func_80183880(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); +extern void func_8012BEE8(u8 *a0); +extern void func_80183564(s32 a0, s16 *a1); +extern void func_801833D4(int a0, int a1); +extern s32 func_80183A28(u8 *a0); +extern void func_80180E80(u8 *self); +extern void func_80183BAC(u8 *a0); +extern void func_801837C4(s32, s32); + +void func_80180B24(s32 s0) +{ + /* BLOCK scope on purpose (house style, TU l.5019/5156): the TU defines + * `void func_80183BD0(s32 a0)` at ~l.7238 and its earlier block-scope `(u8 *a0)` externs + * sit in limbo; a FILE-scope decl here would let gcc-2.7.2's pushdecl merge that + * prototype into the global (different_binding_level) and the definition then errors + * `conflicting types for func_80183BD0` -- measured on a spliced-TU cc1 run. */ + extern void func_80183BD0(u8 *a0); + struct Ent_80180B24 *p; + s32 a; + s32 ta; + s32 tb; + s32 tc; + s32 s1; + s32 s3; + s16 x; + s16 y; + s16 buf[3]; + + p = (struct Ent_80180B24 *)s0; + s3 = (s32)&aB58_80180B24[0]; + if (*(u16 *)(s0 + 0x34) == 4) { + s1 = aFC4C[D_801EFD20]; + x = *(u16 *)(*(s32 *)(s1 + 0x20) + 0x12) & 0xFFF; + if (x >= 0x800) { + x |= 0xF000; + } + func_80183880((s32)s0); + y = *(u16 *)(*(s32 *)(s1 + 0x20) + 0x12) & 0xFFF; + if (y >= 0x800) { + y |= 0xF000; + } + if ((x < -0x200 && -0x201 < y) || (-0x200 < x && y < -0x1FF)) { + func_8002D4C8(0x9C3, 0); + } + if (((s32 (*)(u8 *))func_8012BEE8)((u8 *)s0) != 0) { + buf[0] = *(u16 *)(s3 + 6); + buf[1] = *(u16 *)(s3 + 0xA) - 0x50; + buf[2] = *(u16 *)(s3 + 0xE); + func_80183BD0((u8 *)s0); + func_80183564((s32)s0, buf); + *(u16 *)(s0 + 0xE0) = 0x10; + *(u16 *)(s0 + 0x34) = 0; + } + return; + } + if (((s32 (*)(int, int))func_801833D4)((int)s0, 0) != 0) { + switch (*(u16 *)(s0 + 0x34)) { + case 0: + /* §49-variant/§30#3: zero-byte re-ties set reg_n_sets=2, killing sched1's + * birthing_insn_p LAUNCH_PRIORITY boost that glued each add to its store; + * yields the target's load*3 / add*3 / store*3 order. */ + ta = *(u16 *)(s0 + 0xF4) + 1; + tb = *(u16 *)(s0 + 0xF2) + 1; + __asm__("" : "=r"(ta) : "0"(ta)); + __asm__("" : "=r"(tb) : "0"(tb)); + *(u16 *)(s0 + 0xF4) = ta; + *(u16 *)(s0 + 0xF2) = tb; + *(u16 *)(s0 + 0x34) = *(u16 *)(s0 + 0x34) + 1; + func_8002D4C8(0x992, 0); + break; + case 1: + /* struct-member spelling (MEM_IN_STRUCT_P) on the s0 fields defeats the false + * alias against the D_801EFD40 store. */ + D_801EFD40 = D_801EFD40 & 0xFFFE; + a = p->unkF4 + 1; + p->unkF4 = a + (p->unkF2 & 1); + tc = p->unk34 + 1; + __asm__("" : "=r"(tc) : "0"(tc)); + p->unk34 = tc; + break; + case 2: + if (*(s16 *)(s0 + 0x76) == 0) { + func_80180E80((u8 *)s0); + return; + } + *(u16 *)(s0 + 0xF4) = 0; + func_80183BAC((u8 *)s0); + *(u16 *)(s0 + 0x34) = 3; + break; + case 3: + ((void (*)(s32))func_801837C4)(s0); + func_80183BAC((u8 *)s0); + *(s32 *)(s0 + 0x1C) = 0x80; + *(u16 *)(s0 + 0x100) = 0; + *(u16 *)(s0 + 0x34) = 4; + return; + } + func_80183564((s32)s0, (s16 *)(D_80194470 + (*(s16 *)(s0 + 0xF4) * 8))); + *(u16 *)(s0 + 0xE0) = 0x10; + } else { + /* store 0xE0 in BOTH arms: cross_jump merges the sh at the join, and the s16 local + * yields the un-coalesced addu $v1,$v0,$zero that stops reorg stealing the decrement. */ + s16 v0 = *(s16 *)(s0 + 0xE0); + if (v0 != 0) { + *(s16 *)(s0 + 0xE0) = v0 - 1; + } else { + func_80183A28((u8 *)s0); + *(s16 *)(s0 + 0xE0) = 0x10; + } + if (*(u16 *)(s0 + 0x34) == 0) { + u16 flag = D_801EFD40; + if (!(flag & 1)) { + s1 = aFC4C[D_801EFD20]; + if ((u16)(((*(u16 *)(s0 + 0x106) & 0xFFF) - + (*(u16 *)(*(s32 *)(s1 + 0x20) + 0x12) & 0xFFF)) - 0x180) >= 0xD01) { + D_801EFD40 = flag | 1; + func_8002D4C8(0x7E3, 0); + } + } + } + } +} + extern void func_80183564(s32 a0, s16 *a1); extern s32 func_80186710(void);