mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-26 13:33:34 -04:00
feat(decomp): parallel gate — 6 fns across 5 binaries (12 workers)
ov_SC04_015 func_8017EB78 ov_SC05_008 func_8017E464 ov_SC06_032 func_80185F4C ov_SC06_029 func_8017EF34 func_80185D44 ov_SC07_010 func_80180E68
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 /
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user