mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-26 21:36:06 -04:00
feat(phase-30 S48-T6): wave 4 tail — 9 more banked once the tree was clean
The 17 drafts that read 0/17 against the poisoned tree were never 17 codegen failures. Re-gated on a clean tree: 9 banked, then re-gated TOGETHER per binary (a draft that passes alone can still collide with a sibling in the same TU — which is exactly what `morph_lerp` and `struct V8` did) — 9 of 9 held. ov_SC03_118 func_80183D68 · ov_SC06_008 func_8017F8CC func_80183BF4 ov_SC06_011 func_8017EDA4 · ov_SC07_006 func_8017FDF8 ov_SC06_018 func_80184370 func_80184944 func_8018A974 func_8018EDB8 Wave 4 final: 40 targets -> 35 agent-MATCH -> 27 BANKED (68%). One stray comment in one draft had masked eight real matches.
This commit is contained in:
@@ -3981,7 +3981,158 @@ void func_80183C58(void *a0) {
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC03_118/nonmatchings/ov_SC03_118_jr_8017FB84", func_80183C94);
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC03_118/nonmatchings/ov_SC03_118_jr_8017FB84", func_80183D68);
|
||||
#include "common.h"
|
||||
|
||||
/* ---- integration surface: every decl below AGREES with the visible file-scope decl in
|
||||
* src/ov_SC03_118/ov_SC03_118_jr_8017FB84.c (the destination TU), lines noted. ---- */
|
||||
extern s32 func_8012BD14(void); /* not in TU */
|
||||
extern s32 func_80029178(s32 arg); /* TU:65 */
|
||||
extern void func_801746DC(void); /* TU:1253 */
|
||||
extern s32 func_80178B18(s32 param_1, s32 param_2); /* TU:2538 */
|
||||
extern s32 func_801789AC(s32 arg0); /* TU:2535 */
|
||||
extern void func_80178D18(void); /* TU:2545 -- called w/ arg via cast */
|
||||
extern s32 func_8014CB58(void); /* TU:561 */
|
||||
extern void func_8014B598(s32 a0, s32 a1); /* TU:472 */
|
||||
extern s32 func_8016F1AC(void); /* TU:351 */
|
||||
extern void func_80175454(void); /* TU:1105 */
|
||||
extern void func_800D0C48(s32 a0); /* TU:1469 */
|
||||
extern s32 func_8014CB2C(void); /* TU:560 */
|
||||
extern void func_8012A018(s32 a, s32 b); /* TU:2412 */
|
||||
extern void func_801842DC(s32 a0); /* TU:4023 INCLUDE_ASM (no decl) */
|
||||
extern s32 func_80183830(void); /* TU:3930 INCLUDE_ASM (no decl) */
|
||||
extern void func_80029124(s32, s32); /* TU:50 */
|
||||
extern s32 func_8016F0AC(); /* TU:1945 */
|
||||
extern void func_8012C588(s32 a0, s32 a1); /* not in TU */
|
||||
extern void func_8002959C(void); /* not in TU */
|
||||
extern void func_8018416C(s32 param_1); /* TU:3992 def (later) */
|
||||
extern void func_801841C0(s32 param_1); /* TU:4008 def (later) */
|
||||
extern void func_80184430(void *a0); /* TU:4030 def (later) */
|
||||
|
||||
extern s32 D_801151D4; /* TU:323 */
|
||||
extern M2C_UNK D_8018DA14; /* TU:2712 */
|
||||
extern u8 D_8018EBE8[];
|
||||
extern u8 D_8018EBF8[];
|
||||
extern u8 D_8018EBD8[];
|
||||
extern u8 D_8018EBC8[];
|
||||
extern u8 D_80126948[]; /* TU:667 */
|
||||
|
||||
extern s16 D_801D4348;
|
||||
extern s16 D_801D434A;
|
||||
extern s16 D_801D434C;
|
||||
extern s16 D_801D4350;
|
||||
extern s16 D_801D4352;
|
||||
extern s16 D_801D4354;
|
||||
extern s32 D_801D4358;
|
||||
extern s32 D_801D435C;
|
||||
|
||||
void func_80183D68(s32 a0) {
|
||||
s32 p;
|
||||
u16 t34;
|
||||
|
||||
if (func_8012BD14() < 0x401 || *(u16 *)(a0 + 0x34) == 1 || *(u16 *)(a0 + 0x34) == 2) {
|
||||
switch (*(u16 *)(a0 + 0x34)) {
|
||||
case 0:
|
||||
if ((func_80029178(0x8B) & 0xFF) == 0) {
|
||||
func_801746DC();
|
||||
func_80178B18(a0, (s32)D_8018EBE8);
|
||||
*(u16 *)(a0 + 0x34) = 2;
|
||||
} else {
|
||||
func_801746DC();
|
||||
func_80178B18(a0, (s32)D_8018EBF8);
|
||||
*(u16 *)(a0 + 0x34) = *(u16 *)(a0 + 0x34) + 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (func_801789AC(a0) == 1) {
|
||||
/* file-scope decl in the host TU is `void func_80178D18(void)` but the call
|
||||
site passes a0 -- call through a cast so the decl stays byte-compatible. */
|
||||
((void (*)(s32))func_80178D18)(a0);
|
||||
*(u16 *)(a0 + 0x34) = 3;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (func_801789AC(a0) == 1) {
|
||||
((void (*)(s32))func_80178D18)(a0);
|
||||
*(u16 *)(a0 + 0x34) = 4;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if ((func_80029178(0xB8) & 0xFF) == 0 && func_8014CB58() == 3) {
|
||||
func_8014B598(3, (s32)&D_8018DA14);
|
||||
if (func_8016F1AC() != 0 && (*(u16 *)(a0 + 0x100) & 4) == 0) {
|
||||
*(u16 *)(a0 + 0x100) |= 4;
|
||||
*(s32 *)(a0 + 0x1C) = 0;
|
||||
func_80175454();
|
||||
}
|
||||
if (*(u16 *)(a0 + 0x100) & 4) {
|
||||
*(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) + 1;
|
||||
}
|
||||
if ((*(u16 *)(a0 + 0x100) & 2) == 0 && *(s32 *)(a0 + 0x1C) == 0x5A) {
|
||||
*(u16 *)(a0 + 0x100) |= 2;
|
||||
func_800D0C48(0);
|
||||
}
|
||||
if ((*(u16 *)(a0 + 0x100) & 1) == 0 &&
|
||||
(func_8014CB2C() & 0x8000007F) == 0x80000003) {
|
||||
p = D_801151D4;
|
||||
t34 = *(u16 *)(a0 + 0x34) + 1;
|
||||
*(u16 *)(a0 + 0x100) |= 1;
|
||||
*(u16 *)(a0 + 0x34) = t34;
|
||||
D_801D4348 = *(s32 *)(p + 0x48);
|
||||
D_801D434A = *(s32 *)(p + 0x4C);
|
||||
D_801D434C = *(s32 *)(p + 0x50);
|
||||
D_801D4350 = *(s32 *)(p + 0x3C);
|
||||
D_801D4352 = *(s32 *)(p + 0x40);
|
||||
D_801D4358 = (s32)D_8018EBD8;
|
||||
D_801D4354 = *(s32 *)(p + 0x44);
|
||||
D_801D435C = (s32)&D_8018EBD8[8];
|
||||
func_8012A018((s32)func_80184430, 0);
|
||||
func_801842DC(p);
|
||||
*(s32 *)(a0 + 0x1C) = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((func_80029178(0x8B) & 0xFF) == 0) {
|
||||
return;
|
||||
}
|
||||
/* func_801841C0(a0) is written out on all three paths: gcc cross-jumps the common
|
||||
tail but leaves the three $a0 arg-setups, which then fill the three branch delay
|
||||
slots (a single shared call puts the move in the jal's own slot instead). */
|
||||
if (func_8014CB58() == 3) {
|
||||
func_8018416C(a0);
|
||||
func_801841C0(a0);
|
||||
} else {
|
||||
*(u8 *)(*(s32 *)(a0 + 0xCC) + 0x27) = 0x88;
|
||||
func_801841C0(a0);
|
||||
}
|
||||
} else {
|
||||
if ((func_80029178(0x8B) & 0xFF) == 0) {
|
||||
return;
|
||||
}
|
||||
*(u8 *)(*(s32 *)(a0 + 0xCC) + 0x27) = 0x88;
|
||||
func_801841C0(a0);
|
||||
}
|
||||
if (*(u16 *)(a0 + 0x100) & 1) {
|
||||
*(s32 *)(a0 + 0x1C) = *(s32 *)(a0 + 0x1C) + 1;
|
||||
if (*(s32 *)(a0 + 0x1C) == 0x78) {
|
||||
D_801D4358 = (s32)D_8018EBC8;
|
||||
D_801D435C = (s32)&D_8018EBC8[8];
|
||||
func_8012A018((s32)func_80184430, 0);
|
||||
func_801842DC((s32)D_80126948);
|
||||
}
|
||||
if (func_80183830() != 0) {
|
||||
func_80029124(0xB8, 1);
|
||||
*(u16 *)(a0 + 0x100) &= ~1;
|
||||
func_8016F0AC();
|
||||
func_8012C588(0x249, a0);
|
||||
*(u16 *)(a0 + 0x2) = 2;
|
||||
*(u8 *)(*(s32 *)(a0 + 0xCC) + 0x27) = 0x88;
|
||||
*(u8 *)(*(s32 *)(a0 + 0xD0) + 0x27) = 0x89;
|
||||
func_8002959C();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void func_80184164(void) {
|
||||
}
|
||||
|
||||
@@ -4192,7 +4192,83 @@ void func_8017F624(s32 param_1)
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_008/nonmatchings/ov_SC06_008_jr_8017C294", func_8017F8CC);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern s16 D_8019C91C[];
|
||||
extern u16 D_80126B5E;
|
||||
extern u16 D_80126B62;
|
||||
extern u16 D_80126B66;
|
||||
|
||||
void func_8017F8CC(s32 a0)
|
||||
{
|
||||
switch (*(u16 *)(a0 + 0x34)) {
|
||||
case 0:
|
||||
{
|
||||
s16 idx = *(s16 *)(a0 + 0x70);
|
||||
s16 *p = &D_8019C91C[(idx - 1) * 4];
|
||||
s16 gx = *(s16 *)&D_80126B5E;
|
||||
s16 gz;
|
||||
s32 p20;
|
||||
|
||||
if (!(*p < gx)) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
if (!(gx < *p)) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
gz = *(s16 *)&D_80126B66;
|
||||
if (!(*p < gz)) {
|
||||
break;
|
||||
}
|
||||
if (!(gz < p[1])) {
|
||||
break;
|
||||
}
|
||||
|
||||
p20 = *(s32 *)(a0 + 0x20);
|
||||
*(u32 *)(p20 + 4) = *(u32 *)(p20 + 4) & 0x7FFFFFFF;
|
||||
|
||||
{
|
||||
s32 t;
|
||||
|
||||
*(s16 *)(a0 + 0x88) = D_80126B5E;
|
||||
*(s16 *)(a0 + 0x6) = D_80126B5E;
|
||||
t = D_80126B62 - 0x80;
|
||||
*(s16 *)(a0 + 0x8A) = t;
|
||||
|
||||
t = *(u16 *)(a0 + 0x34);
|
||||
{
|
||||
register s16 z __asm__("$3");
|
||||
t = t + 1;
|
||||
z = D_80126B66;
|
||||
*(u16 *)(a0 + 0x34) = t;
|
||||
*(s16 *)(a0 + 0x8C) = z;
|
||||
*(s16 *)(a0 + 0xE) = z;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
s16 v;
|
||||
|
||||
v = *(u16 *)(a0 + 0xA) + 8;
|
||||
*(u16 *)(a0 + 0xA) = v;
|
||||
if (v < *(s16 *)(a0 + 0x8A)) {
|
||||
break;
|
||||
}
|
||||
*(s16 *)(a0 + 0x2) = 1;
|
||||
*(u16 *)(a0 + 0x34) = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_008/nonmatchings/ov_SC06_008_jr_8017C294", func_8017F9FC);
|
||||
|
||||
@@ -6444,7 +6520,64 @@ extern void func_8012B370(int a0);
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_008/nonmatchings/ov_SC06_008_jr_8017C294", func_80183BF4);
|
||||
#include "common.h"
|
||||
|
||||
extern void func_8012B23C(s32 a0);
|
||||
extern void func_8012CBCC(s32 a0);
|
||||
extern u8 *func_8012913C(s32 a0);
|
||||
extern void func_8012C218(void *a0);
|
||||
|
||||
void func_80183BF4(s32 a0)
|
||||
{
|
||||
s32 s0 = a0;
|
||||
s32 ret;
|
||||
u16 val;
|
||||
|
||||
if (*(u16 *)(s0 + 2) == 0) {
|
||||
*(u8 *)(s0 + 0xC0) = 1;
|
||||
*(u16 *)(s0 + 2) = *(u16 *)(s0 + 2) + 1;
|
||||
func_8012B23C(s0);
|
||||
*(s32 *)(s0 + 0x1C) = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
*(s32 *)(s0 + 0xDC) = *(s32 *)(s0 + 0x14);
|
||||
ret = ((s32 (*)(s32))func_8012CBCC)(s0);
|
||||
if (ret != 0 && (ret & 0x6000) != 0) {
|
||||
s32 cnt = *(s32 *)(s0 + 0x1C) - 1;
|
||||
*(s32 *)(s0 + 0x1C) = cnt;
|
||||
if (cnt == 0) {
|
||||
goto L80183CF4;
|
||||
}
|
||||
*(s32 *)(s0 + 0x14) = -*(s32 *)(s0 + 0xDC) >> 2;
|
||||
}
|
||||
|
||||
val = *(u16 *)(s0 + 0xFC) + 1;
|
||||
*(u16 *)(s0 + 0xFC) = val;
|
||||
if ((val & 1) != 0) {
|
||||
s32 np = (s32)func_8012913C(0x23);
|
||||
if (np != 0) {
|
||||
*(u16 *)(np + 6) = *(u16 *)(s0 + 6);
|
||||
*(u16 *)(np + 0xA) = *(u16 *)(s0 + 0xA);
|
||||
{
|
||||
u16 t = *(u16 *)(s0 + 0xE);
|
||||
*(u32 *)(np + 0x18) = 0;
|
||||
*(u32 *)(np + 0x14) = 0;
|
||||
*(u32 *)(np + 0x10) = 0;
|
||||
*(u16 *)(np + 0x34) = 0x3000;
|
||||
*(u16 *)(np + 0xE) = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*(s16 *)(s0 + 0xA) < 0x20) {
|
||||
return;
|
||||
}
|
||||
|
||||
L80183CF4:
|
||||
func_8012C218((void *)s0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern void func_80019064(void *a0);
|
||||
|
||||
@@ -3961,7 +3961,51 @@ void func_8017ED68(void *a0) {
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_011/nonmatchings/ov_SC06_011_jr_8017BEBC", func_8017EDA4);
|
||||
extern s32 func_8012C354(s32 a0, s32 a1);
|
||||
extern void func_8001C214(s32 a0, s32 a1);
|
||||
extern void func_8012A828(s32 *a0, s32 a1);
|
||||
extern void func_8012B23C(void *a0);
|
||||
|
||||
extern u8 D_8019E204[];
|
||||
extern s32 D_8019E238[];
|
||||
extern u8 D_8018077C[];
|
||||
|
||||
void func_8017EDA4(void *a0) {
|
||||
if (func_8012C354((s32)a0, (s32)D_8019E204) != 0) {
|
||||
u16 v1 = *(u16 *)((s32)a0 + 0x70);
|
||||
|
||||
if (v1 & 0x10) {
|
||||
u16 v0 = v1 & ~0x10;
|
||||
*(u16 *)((s32)a0 + 0x70) = v0;
|
||||
func_8001C214(*(s32 *)((s32)a0 + 0x20), D_8019E238[(s16)v0]);
|
||||
*(s32 *)(*(s32 *)((s32)a0 + 0x20) + 0x4) |= 0x60000040;
|
||||
} else {
|
||||
func_8001C214(*(s32 *)((s32)a0 + 0x20), D_8019E238[(s16)v1]);
|
||||
}
|
||||
|
||||
if (*(s16 *)((s32)a0 + 0x70) == 8 || *(s16 *)((s32)a0 + 0x70) == 0xA) {
|
||||
*(s16 *)((s32)a0 + 0x34) = 3;
|
||||
*(u16 *)((s32)a0 + 0x5C) = 0x8800;
|
||||
}
|
||||
if (*(s16 *)((s32)a0 + 0x70) == 9) {
|
||||
*(s16 *)((s32)a0 + 0x34) = 2;
|
||||
*(u16 *)((s32)a0 + 0x5C) = 0x8800;
|
||||
}
|
||||
if (*(s16 *)((s32)a0 + 0x70) == 0xB) {
|
||||
*(s16 *)((s32)a0 + 0x34) = 4;
|
||||
}
|
||||
|
||||
*(u8 *)((s32)a0 + 0xC0) = 1;
|
||||
*(s32 *)((s32)a0 + 0xB4) = -1;
|
||||
*(u8 *)((s32)a0 + 0x75) = 8;
|
||||
func_8012A828((s32 *)a0, (s32)D_8018077C);
|
||||
|
||||
*(u16 *)((s32)a0 + 0x2) = *(u16 *)((s32)a0 + 0x2) + 1;
|
||||
func_8012B23C(a0);
|
||||
*(s16 *)((s32)a0 + 0xAE) = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_011/nonmatchings/ov_SC06_011_jr_8017BEBC", func_8017EEEC);
|
||||
|
||||
|
||||
@@ -6800,7 +6800,53 @@ INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_801841E
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_8018431C);
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80184370);
|
||||
#include "common.h"
|
||||
|
||||
extern s32 func_80187130(s32 a0, s32 a1);
|
||||
extern u16 D_80126B96;
|
||||
extern s32 func_8018765C(s32 a0);
|
||||
extern u16 D_800B99DA;
|
||||
extern s32 func_80143B6C(s32 a0, s32 a1);
|
||||
extern void func_80189E60(s32 a0, s32 a1);
|
||||
extern s32 func_8012BEE8();
|
||||
|
||||
void func_80184370(s32 p)
|
||||
{
|
||||
s32 e;
|
||||
|
||||
if (func_80187130(p, 0x64) == 1) {
|
||||
D_80126B96 = 4;
|
||||
}
|
||||
|
||||
*(s32 *)(p + 0x10) = *(s32 *)(p + 0x10) * 31 / 32;
|
||||
*(s32 *)(p + 0x18) = *(s32 *)(p + 0x18) * 31 / 32;
|
||||
func_8018765C(p);
|
||||
|
||||
if ((u32)D_800B99DA % 6 == 0) {
|
||||
e = func_80143B6C(p, 0);
|
||||
if (e != 0) {
|
||||
*(s16 *)(*(s32 *)(e + 0xCC) + 0x18) = 0x5000;
|
||||
*(s16 *)(*(s32 *)(e + 0xCC) + 0x1A) = 0x5000;
|
||||
}
|
||||
}
|
||||
|
||||
if (*(s32 *)(p + 0x94) == 8) {
|
||||
func_80189E60(p, 0x8C0);
|
||||
}
|
||||
|
||||
if (*(u16 *)(p + 0x34) == 0) {
|
||||
if (*(s32 *)(p + 0x94) == 0xE) {
|
||||
*(u16 *)(p + 0x98) = 0;
|
||||
*(s32 *)(p + 0x1C) = 0x1E;
|
||||
*(u16 *)(p + 0x34) += 1;
|
||||
}
|
||||
} else {
|
||||
if (func_8012BEE8(p) != 0) {
|
||||
*(s16 *)(p + 2) = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_801844C0);
|
||||
|
||||
@@ -6945,7 +6991,61 @@ void func_80184904(s32 param_1)
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80184944);
|
||||
#include "common.h"
|
||||
|
||||
extern s32 func_8012BCCC(s32 a0);
|
||||
extern s32 func_8012B8E4(s32 a0, s32 a1);
|
||||
extern s32 func_8012BEE8();
|
||||
extern s32 func_8012B8A4(s16 *a0);
|
||||
extern s32 func_8012B608(s32 a0, s32 a1, s32 a2);
|
||||
extern void func_8012B178(s32 a0, s32 a1);
|
||||
extern s32 func_8018765C(s32 a0);
|
||||
extern void func_801877E4(s32 a0);
|
||||
extern s32 rand(void);
|
||||
|
||||
void func_80184944(s32 p)
|
||||
{
|
||||
s32 v;
|
||||
s32 r;
|
||||
s32 t;
|
||||
|
||||
v = func_8012BCCC(p);
|
||||
if (v > 0x144000) {
|
||||
*(s16 *)(p + 2) = 0x13;
|
||||
return;
|
||||
}
|
||||
|
||||
if (v > 0xC4000) {
|
||||
if ((*(u32 *)(p + 0xE0) & 0x40) == 0) {
|
||||
r = func_8012B8E4(p, 8);
|
||||
*(u16 *)(*(s32 *)(p + 0x20) + 0x12) += r;
|
||||
}
|
||||
} else {
|
||||
if ((u32)(v - 0x24000) <= 0xA0000) {
|
||||
*(s16 *)(p + 2) = 0x15;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((*(u32 *)(p + 0xE0) & 0x40) == 0) {
|
||||
if (func_8012BEE8(p) != 0) {
|
||||
t = func_8012B8A4((s16 *)p);
|
||||
*(u32 *)(p + 0xE8) = (t + 0x800) & 0xFFF;
|
||||
r = rand();
|
||||
*(s32 *)(p + 0x1C) = r % 0x40 + 0x40;
|
||||
}
|
||||
}
|
||||
|
||||
r = func_8012B608(*(s16 *)(*(s32 *)(p + 0x20) + 0x12), *(s32 *)(p + 0xE8), 8);
|
||||
*(u16 *)(*(s32 *)(p + 0x20) + 0x12) += r;
|
||||
}
|
||||
|
||||
func_8012B178(p, 0xFFF9C000);
|
||||
*(u32 *)(p + 0xE0) &= 0xFFFFFFBF;
|
||||
if (func_8018765C(p) == 0) {
|
||||
func_801877E4(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80184AA8);
|
||||
|
||||
|
||||
@@ -4358,7 +4358,145 @@ INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018A7C
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018A86C);
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018A974);
|
||||
/* func_8018A974 — allocates a semi-trans LineF2 GPU packet, projects two
|
||||
* world-space points via RotTransPers, and (if both are on-screen with
|
||||
* non-negative depth-clip flags) links the packet into the current
|
||||
* double-buffer's OT at the first point's depth, then notifies via
|
||||
* func_80016638.
|
||||
*
|
||||
* STEP 0 sibling search (§160g) — three already-MATCHED exemplars supplied
|
||||
* the whole shape, none needed independent discovery:
|
||||
*
|
||||
* 1. src/shared/engine_core.h DEFINE_func_8012D3B4() — identical prologue
|
||||
* (temp_v0=func_80010A08(0x10); word4=arg2; func_8004914C/func_800491AC
|
||||
* (&D_800AF648); two RotTransPers calls with the exact
|
||||
* `(d>0) && (flag>=0) && (RotTransPers(...)>0) && (flag>=0)` guard) but
|
||||
* calls a real `SetLineF2()` (code 0x40, no semi-trans) and a real
|
||||
* `AddPrim()` (single evaluation). Our target's asm has NEITHER a
|
||||
* `jal SetLineF2` NOR a `jal AddPrim` — both are fully inlined, which
|
||||
* is the key structural difference this draft encodes (code 0x42 =
|
||||
* semi-trans LineF2 needs hand-set fields; AddPrim needs the classic
|
||||
* macro body since a *variable* depth offset appears nowhere in the
|
||||
* real AddPrim()-calling siblings).
|
||||
*
|
||||
* 2. src/ov_SC03_119/ov_SC03_119_jr_8017FB84.c func_80185944 — byte-MATCH
|
||||
* (177/177 ins). Its header names this exact tail idiom: "link-ins
|
||||
* the packet into the current double-buffer's OT (the PSY-Q `addPrim`
|
||||
* macro pair) and calls func_80016638", with `func_80016638(&D_800A6518
|
||||
* [*bidx*20], depth, 1)` as its literal call form (there depth=0x10
|
||||
* constant, here depth=temp_v0_2). Confirms the "3 lhu D_800B9A02,
|
||||
* address cached / value reloaded" shape and the general addPrim(ot,p)
|
||||
* == setaddr(p,getaddr(ot)); setaddr(ot,p) reading.
|
||||
*
|
||||
* 3. src/ov_SC03_119/ov_SC03_119_jr_8017FB84.c func_801860E8 (same TU,
|
||||
* just above func_80185944) — its own header documents **Lever B**,
|
||||
* byte-measured: "THE OT TABLE MUST BE AN ARRAY_REF (`D_800A651C[i].a`),
|
||||
* NOT `*(s32*)((u8*)&D_800A651C + i*20)`. With the pointer-arith
|
||||
* spelling gcc allocates a phantom 8-byte stack temp that is never
|
||||
* referenced... The temp only appears when the SAME lookup expression
|
||||
* occurs in two statements; the ARRAY_REF form kills it." This was the
|
||||
* load-bearing fix for this draft too — confirmed empirically here via
|
||||
* the `cpp|cc1 … | grep '.frame'` pipeline (§162i's own diagnostic
|
||||
* method): pointer-arith form gave `vars=16` (0x38 frame, +8 over
|
||||
* target's 0x30); switching every `D_800A651C` reference to
|
||||
* `D_800A651C[idx].a` ARRAY_REF form (using the `OtBlk` shape from
|
||||
* engine_types.h:525, local-suffixed here since match_one compiles
|
||||
* standalone) dropped it straight to `vars=8` (0x30, exact). This
|
||||
* generalizes §162i1's "only a BLKmode local reserves frame space" law
|
||||
* to a second, distinct anonymous-temp source (a raw-pointer-arith
|
||||
* symbol expression repeated in 2 statements) — worth a cookbook
|
||||
* addendum since §162i1 as written only covers dead-local pads.
|
||||
*
|
||||
* REGISTER-ALLOCATION LEVERS (found empirically, byte-verified against this
|
||||
* function's own .frame/.s, not inherited from the exemplars above):
|
||||
* - `bidx` pinned to $8 ($t0): natural (unpinned) allocation put the
|
||||
* shared D_800B9A02-address pointer in $a3 instead, cascading a
|
||||
* one-register shift through the whole mask/index register set.
|
||||
* - `mask1` (0xFFFFFF) pinned to $7 ($a3); `tag0` (the packet's old tag
|
||||
* word, read once before the first addPrim half) pinned to $4 ($a0) —
|
||||
* both needed to reproduce the target's exact a2/a3/t0/t1 register
|
||||
* picks for the addPrim RMW pair. `mask2` (0xFF000000) and `depth4`
|
||||
* (temp_v0_2*4) are explicitly NOT pinned — pinning them re-introduced a
|
||||
* 2-instruction schedule swap between the depth<<2 and the 0xFF000000
|
||||
* `lui`; left as plain (named, for depth4) / literal (for mask2)
|
||||
* locals, natural allocation lands them correctly.
|
||||
* - `rgb` (arg2, the color word) pinned to $16 ($s0): unpinned, arg2 and
|
||||
* the &D_800AF648 matrix address land in $s1/$s0 (swapped from target).
|
||||
* `rgb`'s single SET made it a sched1 "birthing insn"
|
||||
* (`birthing_insn_p`: `reg_n_sets==1`) — boosted to max priority in
|
||||
* sched1's BACKWARD scan, which schedules a boosted insn late (cookbook
|
||||
* "birthing-boost prologue-order" lever). A zero-byte non-volatile
|
||||
* re-tie `__asm__("" : "=r"(rgb) : "0"(rgb));` placed immediately after
|
||||
* `rgb = arg2;` gives it a 2nd SET (boost dead) with zero emitted code,
|
||||
* and the 3-instruction prologue cluster (save $s0 / set $s0=arg2 / set
|
||||
* $a0=0x10 for the alloc call) reorders to the target's exact sequence.
|
||||
*
|
||||
* INTEGRATION SURFACE (checked against destination TU
|
||||
* src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c):
|
||||
* func_80010A08, func_8004914C, func_800491AC, RotTransPers, D_800AF648,
|
||||
* D_800B9A02, D_800A6518 all match the TU's own existing extern spellings
|
||||
* verbatim (grepped at TU lines 2448/2632-2633/4674 and the
|
||||
* func_8018F694/func_8018F060 block). D_800A651C and func_80016638 have NO
|
||||
* file-scope declaration anywhere in the TU (only ever appear inside other
|
||||
* INCLUDE_ASM'd/unbanked functions) — declared here exactly as the
|
||||
* func_801860E8/func_80185944 MATCHed precedent declares them: `OtBlk
|
||||
* D_800A651C[]` (locally as `OtBlk_8018A974` — match_one compiles
|
||||
* standalone without ../shared/engine_core.h; at bank time this collapses
|
||||
* onto the TU's own already-visible `OtBlk` from engine_types.h:525,
|
||||
* identical layout, a copy-edit not a fresh investigation) and
|
||||
* `void func_80016638(void *a0, s32 a1, s32 a2)`.
|
||||
*/
|
||||
|
||||
typedef struct { s32 a; s32 b[4]; } OtBlk_8018A974; /* == engine_types.h OtBlk (0x14) */
|
||||
|
||||
void func_8018A974(s32 arg0, s32 arg1, s32 arg2)
|
||||
{
|
||||
extern void *func_80010A08(s32);
|
||||
extern void func_8004914C(void *);
|
||||
extern void func_800491AC(void *);
|
||||
extern s32 RotTransPers(s32, s32, s32 *, s32 *);
|
||||
extern u8 D_800AF648;
|
||||
extern OtBlk_8018A974 D_800A651C[];
|
||||
extern u8 D_800A6518[];
|
||||
extern short D_800B9A02;
|
||||
extern void func_80016638(void *a0, s32 a1, s32 a2);
|
||||
|
||||
s32 sp10;
|
||||
s32 sp14;
|
||||
s32 temp_v0_2;
|
||||
void *temp_v0;
|
||||
s32 ot;
|
||||
s32 depth4;
|
||||
register u16 *bidx __asm__("$8");
|
||||
register u32 mask1 __asm__("$7");
|
||||
register s32 rgb __asm__("$16");
|
||||
register u32 tag0 __asm__("$4");
|
||||
|
||||
rgb = arg2;
|
||||
__asm__("" : "=r"(rgb) : "0"(rgb)); /* zero-byte 2nd SET: kills the sched1 birthing boost */
|
||||
temp_v0 = func_80010A08(0x10);
|
||||
*(u8 *)((u8 *)temp_v0 + 3) = 3;
|
||||
*(s32 *)((u8 *)temp_v0 + 4) = rgb;
|
||||
*(u8 *)((u8 *)temp_v0 + 7) = 0x42;
|
||||
func_8004914C(&D_800AF648);
|
||||
func_800491AC(&D_800AF648);
|
||||
temp_v0_2 = RotTransPers(arg0, temp_v0 + 8, &sp10, &sp14);
|
||||
if ((temp_v0_2 > 0) && (sp14 >= 0) &&
|
||||
(RotTransPers(arg1, temp_v0 + 0xC, &sp10, &sp14) > 0) && (sp14 >= 0)) {
|
||||
/* addPrim(otp, p) == setaddr(p, getaddr(otp)), setaddr(otp, p) */
|
||||
mask1 = 0xFFFFFF;
|
||||
bidx = (u16 *)&D_800B9A02;
|
||||
depth4 = temp_v0_2 * 4;
|
||||
tag0 = *(u32 *)temp_v0;
|
||||
*(u32 *)temp_v0 = (tag0 & 0xFF000000) |
|
||||
(*(u32 *)(depth4 + D_800A651C[*bidx].a) & mask1);
|
||||
ot = D_800A651C[*bidx].a;
|
||||
*(u32 *)(depth4 + ot) =
|
||||
(*(u32 *)(depth4 + ot) & 0xFF000000) | ((u32)temp_v0 & mask1);
|
||||
func_80016638(&D_800A6518[*bidx * 20], temp_v0_2, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018AB00);
|
||||
|
||||
@@ -5757,7 +5895,159 @@ void func_8018E9BC(void *arg) {
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80187AEC", func_8018EDB8);
|
||||
#include "common.h"
|
||||
|
||||
/* func_8018EDB8 — ov_SC06_018 / ov_SC06_018_jr_80187AEC
|
||||
*
|
||||
* Direct structural sibling of func_8018E188 (SAME TU, banked MATCH,
|
||||
* src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c:5255). Shares VERBATIM:
|
||||
* - the 0x60 gate + 0x1D snapshot block,
|
||||
* - the 0x78/0x60 decrement block (AND form — see E188's @stuck note),
|
||||
* - the 0x82&1 finisher, the C8/C9 pokes,
|
||||
* - the two 8-iteration spawn loops (0x281 / 0x23).
|
||||
* Diverges: no leading func_8002D4C8 in the 0x76<0 arm, E188's CC/D0/D4
|
||||
* particle reseed is replaced by a "hand off to the 0x64 owner" block
|
||||
* (5C/60/5E/D8/76/62 pokes + func_8018D870), and the else arm gains a
|
||||
* leading func_8002D4C8(0x9B7, 0).
|
||||
*
|
||||
* Regalloc target (identical to E188): p pinned $s1, e/spawn-ptr coalesce
|
||||
* on $s0, loop counter $s2, the hoisted constant 2 on $s3.
|
||||
*
|
||||
* @class: regalloc-order
|
||||
* @stuck: none — MATCH (170 ins), iteration 3. Body was E188 verbatim on
|
||||
* iteration 1; both residuals were in the 12-insn 0x64 hand-off tail:
|
||||
* (1) `-0xA` stored through a `u16 *` folds to the unsigned 0xFFF6 and emits
|
||||
* `ori $v0,$zero,0xfff6`; the target's `addiu $v0,$zero,-0xA` needs the
|
||||
* store spelled `*(s16 *)(q + 0x76)` (§162k-adjacent width law, applied
|
||||
* to a CONSTANT rather than a load).
|
||||
* (2) the tail pointer lives in TWO registers — $s0 (the `lw 0x20` base) and
|
||||
* $a0 (every store base + the func_8018D870 arg). Spelling that as
|
||||
* `register s32 q __asm__("$4"); q = iv;` alone is NOT enough: with the
|
||||
* 0x20 load left BELOW the copy, local-alloc's `optimize_reg_copy_1`
|
||||
* (§162j1) rewrites that surviving use $s0 -> $a0, and the now-$a0-based
|
||||
* load can no longer be scheduled above the $a0-based stores (they may
|
||||
* alias), costing two load-delay nops = the +2 LENGTH-DRIFT.
|
||||
* LEVER: `optimize_reg_copy_1`'s substitution scan runs FORWARD from the copy
|
||||
* only, so hoisting the surviving use ABOVE `q = iv` in SOURCE order puts it
|
||||
* out of reach — `sv = *(s32 *)(iv + 0x20);` before the copy. It keeps $s0,
|
||||
* and being source-first it also legally precedes the store block, which is
|
||||
* what recovers the target's schedule (lw / sh / sh / lhu interleave). This
|
||||
* is a second, zero-side-effect defeat for §162j1 that works where its
|
||||
* in-place-SET lever cannot: the surviving use here is a LOAD, which has no
|
||||
* way to also SET its own base register.
|
||||
*/
|
||||
|
||||
extern s32 rand(void);
|
||||
extern void func_8016AA50(s32, s32);
|
||||
extern s32 func_8016B428(s32);
|
||||
extern void func_80019064(void *);
|
||||
extern void func_8002A520(int);
|
||||
extern void func_8002A790(int);
|
||||
extern void func_8002D4C8(s32, s32);
|
||||
extern s32 func_8012C588(s32, s32);
|
||||
extern u8 *func_8012913C(s32);
|
||||
extern void func_8012C218(void *);
|
||||
extern void func_8018D870(void *);
|
||||
extern u8 D_801D1210;
|
||||
|
||||
void func_8018EDB8(void *arg) {
|
||||
register u8 *p __asm__("$17"); /* $s1 */
|
||||
s32 e;
|
||||
s32 i;
|
||||
s32 iv;
|
||||
|
||||
p = (u8 *)arg;
|
||||
e = *(u8 *)(p + 0x5E);
|
||||
|
||||
if (*(s16 *)(p + 0x60) != 0) {
|
||||
if (e == 0x1D) {
|
||||
*(u16 *)(p + 0x82) = 0;
|
||||
*(u16 *)(p + 0x7C) = *(u16 *)(p + 0x06);
|
||||
*(u16 *)(p + 0x7E) = *(u16 *)(p + 0x0A);
|
||||
*(u16 *)(p + 0x80) = *(u16 *)(p + 0x0E);
|
||||
}
|
||||
{
|
||||
s32 dec;
|
||||
s32 q = *(s32 *)(p + 0x78);
|
||||
if (q != 0 && *(s16 *)(p + 0x60) != 0) {
|
||||
dec = ((s32)*(s16 *)(p + 0x60) * (s32)*(s16 *)(q + 0x30)) >> 12;
|
||||
if (dec < 1) dec = 1;
|
||||
} else {
|
||||
dec = *(s16 *)(p + 0x60);
|
||||
}
|
||||
*(u16 *)(p + 0x76) = *(u16 *)(p + 0x76) - dec;
|
||||
((void (*)(void *, s32))func_8016AA50)(p, dec);
|
||||
}
|
||||
if (*(u16 *)(p + 0x82) & 1) {
|
||||
((void (*)(void *))func_8016B428)(p);
|
||||
func_80019064(&D_801D1210);
|
||||
}
|
||||
}
|
||||
|
||||
if (e != 0x1D) {
|
||||
if (*(u8 *)(p + 0xC8)) func_8002A520(p);
|
||||
if (*(u8 *)(p + 0xC9)) func_8002A790(p);
|
||||
}
|
||||
|
||||
if (*(s16 *)(p + 0x76) < 0) {
|
||||
i = 0;
|
||||
do {
|
||||
iv = ((s32 (*)(s32, void *))func_8012C588)(0x281, p);
|
||||
if (iv != 0) {
|
||||
*(s32 *)(iv + 0x1C) = 2;
|
||||
*(u16 *)(iv + 0x12) = (rand() & 0x1F) - 0x10;
|
||||
*(u16 *)(iv + 0x16) = -((rand() & 0x0F) + 0x10);
|
||||
*(u16 *)(iv + 0x1A) = (rand() & 0x1F) - 0x10;
|
||||
}
|
||||
i++;
|
||||
} while (i < 8);
|
||||
i = 0;
|
||||
do {
|
||||
iv = (s32)func_8012913C(0x23);
|
||||
if (iv != 0) {
|
||||
s32 r;
|
||||
s32 sv;
|
||||
r = rand();
|
||||
*(u16 *)(iv + 0x06) = *(u16 *)(p + 0x06) + (r & 0x3F) - 0x20;
|
||||
r = rand();
|
||||
*(u16 *)(iv + 0x0A) = *(u16 *)(p + 0x0A) - (r & 0x3F) - 0x20;
|
||||
r = rand();
|
||||
sv = *(u16 *)(p + 0x0E);
|
||||
*(s32 *)(iv + 0x18) = 0;
|
||||
*(s32 *)(iv + 0x14) = 0;
|
||||
*(s32 *)(iv + 0x10) = 0;
|
||||
*(u16 *)(iv + 0x0E) = sv + (r & 0x3F) - 0x20;
|
||||
r = rand();
|
||||
*(u16 *)(iv + 0x34) = (r & 0x17FF) + 0x1800;
|
||||
}
|
||||
i++;
|
||||
} while (i < 8);
|
||||
|
||||
{
|
||||
register s32 q __asm__("$4");
|
||||
s32 sv;
|
||||
iv = *(s32 *)(p + 0x64);
|
||||
sv = *(s32 *)(iv + 0x20);
|
||||
q = iv;
|
||||
*(u16 *)(q + 0x5C) = 1;
|
||||
*(u16 *)(q + 0x60) = 0;
|
||||
sv = *(u16 *)(sv + 0x12);
|
||||
*(u16 *)(q + 0x5E) = 0x1D;
|
||||
*(s32 *)(q + 0xD8) = 0;
|
||||
*(s16 *)(q + 0x76) = -0xA;
|
||||
*(u16 *)(q + 0x62) = sv - 0x800;
|
||||
func_8018D870((void *)q);
|
||||
}
|
||||
func_8012C218(p);
|
||||
} else {
|
||||
func_8002D4C8(0x9B7, 0);
|
||||
*(u16 *)(p + 0x5C) = 0x8800;
|
||||
*(u16 *)(p + 0x60) = 0;
|
||||
*(u8 *)(p + 0xC1) = 0;
|
||||
*(u8 *)(p + 0xC2) = 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @class: none
|
||||
// @stuck: none — MATCH (397/397 ins, match_one + rtu_match).
|
||||
|
||||
@@ -4085,7 +4085,165 @@ INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_8017F5D
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_8017F9AC);
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_8017FDF8);
|
||||
#include "common.h"
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* func_8017FDF8 (ov_SC07_006 / jr_8017BEBC) — 317 ins, MATCH.
|
||||
*
|
||||
* A 5x-expanded 16-colour CLUT cross-fade: for each of five 16-entry 5:5:5
|
||||
* palettes, lerp channel-wise between a "from" table and a "to" table by
|
||||
* t = (x - 0x800) * 2 (clamped at 0), then hand the built CLUT to
|
||||
* func_800599B8(tbl, clut). The alpha/STP bit is COPIED (not lerped) from
|
||||
* whichever endpoint is dominant (t < 0x800 -> the "from" table).
|
||||
*
|
||||
* ===========================================================================
|
||||
* INTEGRATION SURFACE (§161c) — this draft needs NO edit to the host TU.
|
||||
* ===========================================================================
|
||||
* Host TU: src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c, INCLUDE_ASM at line 4088.
|
||||
*
|
||||
* - func_800599B8 takes TWO args here, but the host carries a ONE-arg
|
||||
* prototype `extern void func_800599B8(u16 *);` at FILE SCOPE, line 609,
|
||||
* visible at the INCLUDE_ASM slot. This draft keeps that exact prototype
|
||||
* (byte-identical text) so the decl AGREES with the host and is free, and
|
||||
* defuses the arity clash with a call-site cast — the same idiom already
|
||||
* used by matched code at src/ov_SC03_099/ov_SC03_099_jr_8013C98C.c:1439
|
||||
* and src/ov_SC06_008/ov_SC06_008_jr_8013C98C.c:1439.
|
||||
*
|
||||
* BYTE-PROVEN, this wave, on the two alternatives that avoid the cast:
|
||||
* (A) add `extern void func_800599B8();` beside host line 609
|
||||
* -> CC1 FAIL, "too many arguments to function" x5. A non-prototype
|
||||
* decl does NOT override an already-visible prototype; gcc-2.7.2
|
||||
* forms the composite type and the prototype wins.
|
||||
* (B) put `extern void func_800599B8();` at BLOCK scope inside
|
||||
* func_8017FDF8, host line 609 untouched
|
||||
* -> CC1 FAIL, identical errors. Block scope does not shadow a
|
||||
* visible file-scope prototype for arity checking here.
|
||||
* So the empty-paren form only works if host line 609 is REPLACED (not
|
||||
* added beside). That variant is also byte-verified MATCH and is kept at
|
||||
* probes/E_widen_decl.c if the cleaner source shape is preferred; it costs
|
||||
* a one-line decl edit to the host (byte-neutral — the host has no other
|
||||
* reference to func_800599B8, grep: line 609 is decl-only).
|
||||
*
|
||||
* - All fifteen data symbols declared below have ZERO occurrences in the host
|
||||
* TU (verified by grep), so no type conflicts. `pal_lerp` likewise has 0
|
||||
* occurrences (no clash with the host's existing `morph_lerp` inline).
|
||||
* Names that DO appear elsewhere in src/ (D_801F60C0, D_8018DF60..80) are
|
||||
* all in other overlays' TUs, never in this host.
|
||||
*
|
||||
* - src/shared/engine_core.h:27426 also declares `extern void
|
||||
* func_800599B8(u16 *);` but inside a macro body, so it only reaches block
|
||||
* scope at an expansion site — it does not add a file-scope decl here.
|
||||
*
|
||||
* ===========================================================================
|
||||
* LOAD-BEARING SOURCE SHAPES (all independently re-verified this wave)
|
||||
* ===========================================================================
|
||||
* 1. D_801F60A0 MUST stay ONE array symbol indexed [0]/[16]/[32]/[48]/[64].
|
||||
* cse's use_related_value is what emits the `addiu $s0, $s0, 0x20` that
|
||||
* seeds each following block's loop pointer from the pointer just passed
|
||||
* to func_800599B8. REFUTED this wave: five separate externs
|
||||
* D_801F60A0/C0/E0/6100/6120 give 319 ins vs 317, 258 mismatched (the two
|
||||
* extra instructions are the lost related-value adds).
|
||||
*
|
||||
* 2. The nr/ng/nb named temps are load-bearing — do NOT inline them back.
|
||||
* All three `mult` result pseudos carry `pref LO_REG` and tie in
|
||||
* allocno_compare, so the tie breaks on allocno number: the lowest-numbered
|
||||
* product takes $lo, reload spills $lo, and retry_global_alloc re-places it
|
||||
* on the LAST free register, shifting every loop-carried pseudo one register
|
||||
* down. Writing the three channels into named temps re-orders sched1's
|
||||
* output (not the final sched2 order), which re-orders reg_live_length and
|
||||
* hence the allocno priorities, so the blue product keeps $lo and lands on
|
||||
* $v1 while red/green take $t1/$t0. Alternatives, same 317 ins, all
|
||||
* NON-matching: fully inlined 104 diffs; hoist dr,dg 35; hoist raw products
|
||||
* pr,pg,pb 104; hoist unmasked sums sr,sg 114; hoist nr / nr,ng 104 / 114.
|
||||
* Register pins are NOT the lever here (cf. §162j1) — this is a global.c
|
||||
* priority/tie problem; statement granularity is the lever.
|
||||
*
|
||||
* 3. Branch polarity: the loop-invariant `slti $t7, $a3, 0x800` is LICM-hoisted
|
||||
* and the target branches with `bnez` (on the TRUE arm). That requires the
|
||||
* source to spell the condition INVERTED with swapped arms — `if (t >=
|
||||
* 0x800) hi = *a...; else hi = *b...;`. The intuitive `if (t < 0x800)`
|
||||
* with unswapped arms emits `beqz` and is a 5-instruction structural miss.
|
||||
*
|
||||
* FAMILY REACH x2: the second binary templates mechanically — identical shape,
|
||||
* only the ten source-table symbols and the five func_800599B8 arg tables
|
||||
* change. Note for the remap: constraint (1) means the sibling's five
|
||||
* destination CLUTs must likewise be one base symbol at 0x20 stride.
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
extern void func_800599B8(u16 *);
|
||||
|
||||
extern u16 D_801F60A0[];
|
||||
|
||||
extern u16 D_801CACA8[];
|
||||
extern u16 D_801CAD48[];
|
||||
extern u16 D_801CAD28[];
|
||||
extern u16 D_801CADA8[];
|
||||
extern u16 D_801CAD08[];
|
||||
extern u16 D_801CAD88[];
|
||||
extern u16 D_801CAC68[];
|
||||
extern u16 D_801CACE8[];
|
||||
extern u16 D_801CAC88[];
|
||||
extern u16 D_801CACC8[];
|
||||
|
||||
extern u8 D_8018DF60[];
|
||||
extern u8 D_8018DF68[];
|
||||
extern u8 D_8018DF70[];
|
||||
extern u8 D_8018DF78[];
|
||||
extern u8 D_8018DF80[];
|
||||
|
||||
/* MUST be `inline` — 5 expansions, 0 jal, and the caller's frame is 0x20. */
|
||||
static inline void pal_lerp(u16 *dst, u16 *b, u16 *a, s32 x)
|
||||
{
|
||||
s32 t;
|
||||
s32 i;
|
||||
s32 hi;
|
||||
s32 r;
|
||||
s32 g;
|
||||
s32 bl;
|
||||
s32 nr;
|
||||
s32 ng;
|
||||
s32 nb;
|
||||
|
||||
t = (x - 0x800) * 2;
|
||||
if (t < 0) {
|
||||
t = 0;
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* NOTE the polarity: `>= 0x800` (not `< 0x800` with swapped arms) —
|
||||
LICM hoists the slti and gcc branches on the TRUE arm, giving the
|
||||
target's `bnez` rather than a `beqz`. */
|
||||
if (t >= 0x800) {
|
||||
hi = *a & 0x8000;
|
||||
} else {
|
||||
hi = *b & 0x8000;
|
||||
}
|
||||
r = *b & 0x1F;
|
||||
g = *b & 0x3E0;
|
||||
bl = *b & 0x7C00;
|
||||
nr = (r + ((((*a & 0x1F) - r) * t) >> 12)) & 0x1F;
|
||||
ng = (g + ((((*a & 0x3E0) - g) * t) >> 12)) & 0x3E0;
|
||||
nb = (bl + ((((*a & 0x7C00) - bl) * t) >> 12)) & 0x7C00;
|
||||
*dst = hi | nr | ng | nb;
|
||||
b++;
|
||||
a++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
void func_8017FDF8(s32 x)
|
||||
{
|
||||
pal_lerp(&D_801F60A0[0], D_801CACA8, D_801CAD48, x);
|
||||
((void (*)(u8 *, u16 *))func_800599B8)(D_8018DF60, &D_801F60A0[0]);
|
||||
pal_lerp(&D_801F60A0[16], D_801CAD28, D_801CADA8, x);
|
||||
((void (*)(u8 *, u16 *))func_800599B8)(D_8018DF68, &D_801F60A0[16]);
|
||||
pal_lerp(&D_801F60A0[32], D_801CAD08, D_801CAD88, x);
|
||||
((void (*)(u8 *, u16 *))func_800599B8)(D_8018DF70, &D_801F60A0[32]);
|
||||
pal_lerp(&D_801F60A0[48], D_801CAC68, D_801CACE8, x);
|
||||
((void (*)(u8 *, u16 *))func_800599B8)(D_8018DF78, &D_801F60A0[48]);
|
||||
pal_lerp(&D_801F60A0[64], D_801CAC88, D_801CACC8, x);
|
||||
((void (*)(u8 *, u16 *))func_800599B8)(D_8018DF80, &D_801F60A0[64]);
|
||||
}
|
||||
|
||||
|
||||
/* func_801802EC — banked from the S40 wave-1 draft.
|
||||
* The draft carried the TYPES, the six SVECTOR2 externs and `static inline morph_lerp` so that
|
||||
|
||||
Reference in New Issue
Block a user