fix(phase-30 S43): family_remap now carries TYPEDEFS (transitive, brace-aware) — the §146/§152 gap closed

- ROOT CAUSE PINNED, and my first hypothesis was WRONG (R14, corrected in the log): I wrote that a
  gate transform ate a `/*` opener and turned comment prose into code. REFUTED — cast_call_sites,
  sig_unify and reconcile_tu each run with the gate's real --src-file all preserve it. The real
  cause is family_remap's preamble backscan, whose accept-set (blank/extern/comment/typedef) HALTS
  AT THE FIRST `#define` and never reaches typedefs above the macro block. `_carry_macros` then
  re-attaches the macros, which HIDES the truncation — the unit looks complete and is not.
  "parse error before 'unsigned'" was that failure surfacing at the next token (the following
  `extern unsigned char` line): a misleading label, not a second defect.
- FIX: _carry_typedefs() — additive, TRANSITIVE (a carried typedef may name another; measured:
  carrying Vec8_80182FD4 alone then failed on SVECTOR_8016E7C8), and BRACE-AWARE (a `;`-terminated
  scan stops INSIDE the struct at its first member line, emitting a truncated unclosed typedef).
  Emits dependency-first for C89. Only types the unit actually names and does not already carry.
- VERIFIED: the 0x80182FD4 unit now carries its Prim_8016E7C8 block complete; the 0xECC family's
  remaps now carry the four typedefs I had prepended BY HAND before gating them — i.e. the fix
  automates the exact workaround that banked those three siblings. Residual isolated-compile failure
  on SVECTOR_8016E7C8 is a match_one artifact: that type lives in src/shared/engine_types.h, which
  the real TU includes — the typedef gap is fatal ONLY when the target TU lacks the type, which is
  why this class failed loudly for some families and silently succeeded for others.
This commit is contained in:
Drew T
2026-08-05 23:50:40 -06:00
parent 5c84ad5ada
commit 41a3de342d
5 changed files with 1461 additions and 8 deletions
+459
View File
@@ -0,0 +1,459 @@
typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2; } PF3_C6F4;
typedef struct { s16 vx, vy; } DVEC2_C6F4;
typedef struct { u8 *vtx; u32 f4; u32 xx, yy, zz; Prim126 *prim, *end; } Cell126;
typedef struct { u32 w0, w1, w2; } Prim126;
#define gte_ldv0(r0) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 )" \
: \
: "r"( r0 ) )
#define gte_ldv3(r0, r1, r2) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 );" \
"lwc2 $2, 0( %1 );" \
"lwc2 $3, 4( %1 );" \
"lwc2 $4, 0( %2 );" \
"lwc2 $5, 4( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) )
#define gte_ldv3c(r0) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 );" \
"lwc2 $2, 8( %0 );" \
"lwc2 $3, 12( %0 );" \
"lwc2 $4, 16( %0 );" \
"lwc2 $5, 20( %0 )" \
: \
: "r"( r0 ) )
#define gte_rtps() __asm__ volatile ("nop;nop;rtps")
#define gte_rtpt() __asm__ volatile ("nop;nop;rtpt")
#define gte_nclip() __asm__ volatile ("nop;nop;nclip")
#define gte_avsz3() __asm__ volatile ("nop;nop;avsz3")
#define gte_avsz4() __asm__ volatile ("nop;nop;avsz4")
#define gte_stsxy(r0) __asm__ volatile ( \
"swc2 $14, 0( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsxy3(r0, r1, r2) __asm__ volatile ( \
"swc2 $12, 0( %0 );" \
"swc2 $13, 0( %1 );" \
"swc2 $14, 0( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) \
: "memory" )
#define gte_stsxy3c(r0) __asm__ volatile ( \
"swc2 $12, 0( %0 );" \
"swc2 $13, 4( %0 );" \
"swc2 $14, 8( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsxy3_f3(r0) __asm__ volatile ( \
"swc2 $12, 8( %0 );" \
"swc2 $13, 12( %0 );" \
"swc2 $14, 16( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsz3(r0, r1, r2) __asm__ volatile ( \
"swc2 $17, 0( %0 );" \
"swc2 $18, 0( %1 );" \
"swc2 $19, 0( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) \
: "memory" )
#define gte_stsz4(r0, r1, r2, r3) __asm__ volatile ( \
"swc2 $16, 0( %0 );" \
"swc2 $17, 0( %1 );" \
"swc2 $18, 0( %2 );" \
"swc2 $19, 0( %3 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ), "r"( r3 ) \
: "memory" )
#define gte_stflg(r0) __asm__ volatile ( \
"cfc2 $12, $31;" \
"nop;" \
"sw $12, 0( %0 )" \
: \
: "r"( r0 ) \
: "$12", "memory" )
#define gte_stopz(r0) __asm__ volatile ( \
"swc2 $24, 0( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
void func_8017C6F4(s32 arg0)
{
extern s32 func_800491EC(void);
extern void func_800547D8(s32, MTX_C6F4 *);
extern void func_80052E38(MTX_C6F4 *);
extern void func_8017C014(void *, void *, s32);
extern u8 D_8018FA10[];
extern u8 *D_800A5E60;
extern u8 D_800A6610[];
extern short D_800B9A02;
s16 rect[4];
DVEC2_C6F4 tmpxy[4];
SVEC2_C6F4 box[8];
SVEC2_C6F4 sxy[8];
MTX_C6F4 mtx;
struct { long flag, opz, sz0, sz1, sz2, sz3; } g;
s32 cx0, cx1, cy0, cy1, y, col;
Cell126 **rowptr;
Cell126 **p;
Cell126 *cell;
Prim126 *prim;
Prim126 *end;
u8 *pkt;
u32 ot;
u8 *vtx;
u8 *va, *vb, *vc, *vd;
u32 w, code;
u32 wx, wy, wz;
u32 xlo, xhi, ylo, yhi, zlo, zhi;
s32 xa32, xb32, t32;
s32 xmn1, xmx1, xmn2, xmx2;
s32 ymn1, ymx1, ymn2, ymx2;
s32 my, mny, mx, mn;
func_800491EC();
func_800547D8(arg0 + 0x10, &mtx);
func_80052E38(&mtx);
func_8017C014(D_8018FA10, rect, *(s32 *)(arg0 + 0x60));
pkt = D_800A5E60;
ot = (u32)&D_800A6610[(*(u16 *)&D_800B9A02) << 14];
cx0 = (rect[0] + 0x4000) / 512;
cx1 = (rect[0] + rect[2] + 0x4000) / 512 + 2;
cx0 = (cx0 < 0) ? 0 : ((cx0 > 0x3F) ? 0x3F : cx0);
cx1 = (cx1 < 0) ? 0 : ((cx1 > 0x3F) ? 0x3F : cx1);
cy0 = (rect[1] + 0x4000) / 512 - 1;
cy1 = (rect[1] + rect[3] + 0x4000) / 512 + 2;
cy0 = (cy0 < 0) ? 0 : ((cy0 > 0x3F) ? 0x3F : cy0);
cy1 = (cy1 < 0) ? 0 : ((cy1 > 0x3F) ? 0x3F : cy1);
rowptr = (Cell126 **)(*(s32 *)(arg0 + 0xC)) + (cy0 * 64 + cx0);
for (y = cy0; y < cy1; y++, rowptr += 0x40) {
for (col = cx0, p = rowptr; col < cx1; col++, p++) {
cell = *p;
if (cell == 0) continue;
wx = cell->xx;
xlo = wx & 0xFFFF;
xhi = wx >> 16;
wy = cell->yy;
ylo = wy & 0xFFFF;
yhi = wy >> 16;
wz = cell->zz;
zlo = wz & 0xFFFF;
zhi = wz >> 16;
box[0].vx = xlo; box[0].vy = ylo; box[0].vz = zlo;
box[1].vx = xhi; box[1].vy = ylo; box[1].vz = zlo;
box[2].vx = xlo; box[2].vy = ylo; box[2].vz = zhi;
box[3].vx = xhi; box[3].vy = ylo; box[3].vz = zhi;
box[4].vx = xlo; box[4].vy = yhi; box[4].vz = zlo;
box[5].vx = xhi; box[5].vy = yhi; box[5].vz = zlo;
box[6].vx = xlo; box[6].vy = yhi; box[6].vz = zhi;
box[7].vx = xhi; box[7].vy = yhi; box[7].vz = zhi;
gte_ldv3c(&box[0]);
gte_rtpt();
gte_stsxy3(&sxy[0], &sxy[1], &sxy[2]);
gte_ldv0(&box[3]);
gte_rtps();
gte_stsxy(&sxy[3]);
gte_ldv3c(&box[4]);
gte_rtpt();
gte_stsxy3(&sxy[4], &sxy[5], &sxy[6]);
gte_ldv0(&box[7]);
gte_rtps();
gte_stsxy(&sxy[7]);
xa32 = sxy[0].vx;
xb32 = sxy[1].vx;
if (xb32 < xa32) { xmx1 = xa32; xmn1 = xb32; } else { xmn1 = xa32; xmx1 = xb32; }
t32 = sxy[2].vx;
if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32;
t32 = sxy[3].vx;
if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32;
xa32 = sxy[4].vx;
xb32 = sxy[5].vx;
if (xb32 < xa32) { xmx2 = xa32; xmn2 = xb32; } else { xmn2 = xa32; xmx2 = xb32; }
t32 = sxy[6].vx;
if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32;
t32 = sxy[7].vx;
if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32;
mn = xmn1;
if (xmn2 < mn) mn = xmn2;
mx = xmx1;
if (mx < xmx2) mx = xmx2;
if (mx < -0xA0) continue;
if (!(mn < 0xA1)) continue;
xa32 = sxy[0].vy;
xb32 = sxy[1].vy;
if (xb32 < xa32) { ymx1 = xa32; ymn1 = xb32; } else { ymn1 = xa32; ymx1 = xb32; }
t32 = sxy[2].vy;
if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32;
t32 = sxy[3].vy;
if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32;
xa32 = sxy[4].vy;
xb32 = sxy[5].vy;
if (xb32 < xa32) { ymx2 = xa32; ymn2 = xb32; } else { ymn2 = xa32; ymx2 = xb32; }
t32 = sxy[6].vy;
if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32;
t32 = sxy[7].vy;
if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32;
mny = ymn1;
if (ymn2 < mny) mny = ymn2;
my = ymx1;
if (my < ymx2) my = ymx2;
if (my < -0x78) continue;
if (!(mny < 0x79)) continue;
prim = cell->prim;
end = cell->end;
vtx = cell->vtx;
while (prim < end) {
w = prim->w1;
va = vtx + (w & 0xFFFF);
vb = vtx + (w >> 16);
w = prim->w2;
vc = vtx + (w & 0xFFFF);
w = w >> 16;
gte_ldv3(va, vb, vc);
gte_rtpt();
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_nclip();
code = w & 0xF;
vd = vtx + ((w & 0xFFF0) >> 1);
gte_stopz(&g.opz);
if (g.opz > 0) {
switch (code) {
case 4:
case 5:
gte_stsxy3_f3(pkt);
gte_stsz3(&g.sz0, &g.sz1, &g.sz2);
if (((PFT3_C6F4 *)pkt)->x0 > ((PFT3_C6F4 *)pkt)->x1) {
mx = ((PFT3_C6F4 *)pkt)->x0;
mn = ((PFT3_C6F4 *)pkt)->x1;
} else {
mn = ((PFT3_C6F4 *)pkt)->x0;
mx = ((PFT3_C6F4 *)pkt)->x1;
}
if (((PFT3_C6F4 *)pkt)->x2 > mx) mx = ((PFT3_C6F4 *)pkt)->x2;
else if (((PFT3_C6F4 *)pkt)->x2 < mn) mn = ((PFT3_C6F4 *)pkt)->x2;
if (mx >= -0xA0 && mn < 0xA1) {
if (((PFT3_C6F4 *)pkt)->y0 > ((PFT3_C6F4 *)pkt)->y1) {
my = ((PFT3_C6F4 *)pkt)->y0;
mny = ((PFT3_C6F4 *)pkt)->y1;
} else {
mny = ((PFT3_C6F4 *)pkt)->y0;
my = ((PFT3_C6F4 *)pkt)->y1;
}
if (((PFT3_C6F4 *)pkt)->y2 > my) my = ((PFT3_C6F4 *)pkt)->y2;
else if (((PFT3_C6F4 *)pkt)->y2 < mny) mny = ((PFT3_C6F4 *)pkt)->y2;
if (my >= -0x78 && mny < 0x79) {
s32 za;
u32 *otp;
if (g.sz0 > g.sz1) {
za = g.sz0;
if (za < g.sz2) za = g.sz2;
} else {
za = g.sz1;
if (za < g.sz2) za = g.sz2;
}
g.opz = za;
if (code != 4) g.opz = za + 0x200;
((PF3_C6F4 *)pkt)->rgbc = prim->w0;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x4000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x14;
}
}
break;
case 6:
case 7:
gte_stsxy3c(&tmpxy[0]);
gte_stsz3(&g.sz0, &g.sz1, &g.sz2);
if (tmpxy[0].vx > tmpxy[1].vx) {
mx = tmpxy[0].vx;
mn = tmpxy[1].vx;
} else {
mn = tmpxy[0].vx;
mx = tmpxy[1].vx;
}
if (tmpxy[2].vx > mx) mx = tmpxy[2].vx;
else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx;
if (mx >= -0xA0 && mn < 0xA1) {
if (tmpxy[0].vy > tmpxy[1].vy) {
my = tmpxy[0].vy;
mny = tmpxy[1].vy;
} else {
mny = tmpxy[0].vy;
my = tmpxy[1].vy;
}
if (tmpxy[2].vy > my) my = tmpxy[2].vy;
else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy;
if (my >= -0x78 && mny < 0x79) {
s32 za;
u32 *otp;
u32 *tp;
gte_avsz3();
if (g.sz0 > g.sz1) {
za = g.sz0;
if (za < g.sz2) za = g.sz2;
} else {
za = g.sz1;
if (za < g.sz2) za = g.sz2;
}
g.opz = za;
if (code != 6) g.opz = za + 0x200;
*(u32 *)&((PFT3_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0];
*(u32 *)&((PFT3_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1];
*(u32 *)&((PFT3_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2];
tp = (u32 *)prim->w0;
((PFT3_C6F4 *)pkt)->rgbc = tp[0];
((PFT3_C6F4 *)pkt)->uvc0 = tp[1];
((PFT3_C6F4 *)pkt)->uvp1 = tp[2];
((PFT3_C6F4 *)pkt)->uv2 = tp[3];
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x7000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x20;
}
}
break;
case 0:
case 1:
gte_stsxy3_f3(pkt);
gte_ldv0(vd);
gte_rtps();
if (((PF4_C6F4 *)pkt)->x0 > ((PF4_C6F4 *)pkt)->x1) {
mx = ((PF4_C6F4 *)pkt)->x0;
mn = ((PF4_C6F4 *)pkt)->x1;
} else {
mn = ((PF4_C6F4 *)pkt)->x0;
mx = ((PF4_C6F4 *)pkt)->x1;
}
if (((PF4_C6F4 *)pkt)->x2 > mx) mx = ((PF4_C6F4 *)pkt)->x2;
else if (((PF4_C6F4 *)pkt)->x2 < mn) mn = ((PF4_C6F4 *)pkt)->x2;
if (((PF4_C6F4 *)pkt)->y0 > ((PF4_C6F4 *)pkt)->y1) {
my = ((PF4_C6F4 *)pkt)->y0;
mny = ((PF4_C6F4 *)pkt)->y1;
} else {
mny = ((PF4_C6F4 *)pkt)->y0;
my = ((PF4_C6F4 *)pkt)->y1;
}
if (((PF4_C6F4 *)pkt)->y2 > my) my = ((PF4_C6F4 *)pkt)->y2;
else if (((PF4_C6F4 *)pkt)->y2 < mny) mny = ((PF4_C6F4 *)pkt)->y2;
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3);
gte_stsxy((long *)&((PF4_C6F4 *)pkt)->x3);
if (((PF4_C6F4 *)pkt)->x3 < mn) mn = ((PF4_C6F4 *)pkt)->x3;
else if (mx < ((PF4_C6F4 *)pkt)->x3) mx = ((PF4_C6F4 *)pkt)->x3;
if (mx >= -0xA0 && mn < 0xA1) {
if (((PF4_C6F4 *)pkt)->y3 < mny) mny = ((PF4_C6F4 *)pkt)->y3;
else if (my < ((PF4_C6F4 *)pkt)->y3) my = ((PF4_C6F4 *)pkt)->y3;
if (my >= -0x78 && mny < 0x79) {
s32 za, zb;
u32 *otp;
zb = g.sz2;
if (zb < g.sz3) zb = g.sz3;
za = g.sz0;
if (za < g.sz1) za = g.sz1;
if (za < zb) za = zb;
g.opz = za;
if (code != 0) g.opz = za + 0x200;
((PF4_C6F4 *)pkt)->rgbc = prim->w0;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x5000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x18;
}
}
}
break;
case 2:
case 3:
gte_stsxy3c(&tmpxy[0]);
gte_ldv0(vd);
gte_rtps();
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_stsxy(&tmpxy[3]);
gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3);
if (tmpxy[0].vx > tmpxy[1].vx) {
mx = tmpxy[0].vx;
mn = tmpxy[1].vx;
} else {
mn = tmpxy[0].vx;
mx = tmpxy[1].vx;
}
if (tmpxy[2].vx > mx) mx = tmpxy[2].vx;
else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx;
if (tmpxy[3].vx > mx) mx = tmpxy[3].vx;
else if (tmpxy[3].vx < mn) mn = tmpxy[3].vx;
if (mx >= -0xA0 && mn < 0xA1) {
if (tmpxy[0].vy > tmpxy[1].vy) {
my = tmpxy[0].vy;
mny = tmpxy[1].vy;
} else {
mny = tmpxy[0].vy;
my = tmpxy[1].vy;
}
if (tmpxy[2].vy > my) my = tmpxy[2].vy;
else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy;
if (tmpxy[3].vx > my) my = tmpxy[3].vx;
else if (tmpxy[3].vx < mny) mny = tmpxy[3].vx;
if (my >= -0x78 && mny < 0x79) {
s32 za, zb;
u32 *otp;
u32 *tp;
u32 uvw;
gte_avsz4();
zb = g.sz2;
if (zb < g.sz3) zb = g.sz3;
za = g.sz0;
if (za < g.sz1) za = g.sz1;
if (za < zb) za = zb;
g.opz = za;
if (code != 2) g.opz = za + 0x200;
*(u32 *)&((PFT4_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0];
*(u32 *)&((PFT4_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1];
*(u32 *)&((PFT4_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2];
*(u32 *)&((PFT4_C6F4 *)pkt)->x3 = *(u32 *)&tmpxy[3];
tp = (u32 *)prim->w0;
((PFT4_C6F4 *)pkt)->rgbc = tp[0];
((PFT4_C6F4 *)pkt)->uvc0 = tp[1];
((PFT4_C6F4 *)pkt)->uvp1 = tp[2];
uvw = tp[3];
((PFT4_C6F4 *)pkt)->uv2 = uvw;
((PFT4_C6F4 *)pkt)->uv3 = uvw >> 16;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x9000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x28;
}
}
}
break;
}
}
}
prim++;
}
}
}
D_800A5E60 = pkt;
}
+459
View File
@@ -0,0 +1,459 @@
typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2; } PF3_C6F4;
typedef struct { s16 vx, vy; } DVEC2_C6F4;
typedef struct { u8 *vtx; u32 f4; u32 xx, yy, zz; Prim126 *prim, *end; } Cell126;
typedef struct { u32 w0, w1, w2; } Prim126;
#define gte_ldv0(r0) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 )" \
: \
: "r"( r0 ) )
#define gte_ldv3(r0, r1, r2) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 );" \
"lwc2 $2, 0( %1 );" \
"lwc2 $3, 4( %1 );" \
"lwc2 $4, 0( %2 );" \
"lwc2 $5, 4( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) )
#define gte_ldv3c(r0) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 );" \
"lwc2 $2, 8( %0 );" \
"lwc2 $3, 12( %0 );" \
"lwc2 $4, 16( %0 );" \
"lwc2 $5, 20( %0 )" \
: \
: "r"( r0 ) )
#define gte_rtps() __asm__ volatile ("nop;nop;rtps")
#define gte_rtpt() __asm__ volatile ("nop;nop;rtpt")
#define gte_nclip() __asm__ volatile ("nop;nop;nclip")
#define gte_avsz3() __asm__ volatile ("nop;nop;avsz3")
#define gte_avsz4() __asm__ volatile ("nop;nop;avsz4")
#define gte_stsxy(r0) __asm__ volatile ( \
"swc2 $14, 0( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsxy3(r0, r1, r2) __asm__ volatile ( \
"swc2 $12, 0( %0 );" \
"swc2 $13, 0( %1 );" \
"swc2 $14, 0( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) \
: "memory" )
#define gte_stsxy3c(r0) __asm__ volatile ( \
"swc2 $12, 0( %0 );" \
"swc2 $13, 4( %0 );" \
"swc2 $14, 8( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsxy3_f3(r0) __asm__ volatile ( \
"swc2 $12, 8( %0 );" \
"swc2 $13, 12( %0 );" \
"swc2 $14, 16( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsz3(r0, r1, r2) __asm__ volatile ( \
"swc2 $17, 0( %0 );" \
"swc2 $18, 0( %1 );" \
"swc2 $19, 0( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) \
: "memory" )
#define gte_stsz4(r0, r1, r2, r3) __asm__ volatile ( \
"swc2 $16, 0( %0 );" \
"swc2 $17, 0( %1 );" \
"swc2 $18, 0( %2 );" \
"swc2 $19, 0( %3 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ), "r"( r3 ) \
: "memory" )
#define gte_stflg(r0) __asm__ volatile ( \
"cfc2 $12, $31;" \
"nop;" \
"sw $12, 0( %0 )" \
: \
: "r"( r0 ) \
: "$12", "memory" )
#define gte_stopz(r0) __asm__ volatile ( \
"swc2 $24, 0( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
void func_8017C6F4(s32 arg0)
{
extern s32 func_800491EC(void);
extern void func_800547D8(s32, MTX_C6F4 *);
extern void func_80052E38(MTX_C6F4 *);
extern void func_8017C014(void *, void *, s32);
extern u8 D_8018F9C0[];
extern u8 *D_800A5E60;
extern u8 D_800A6610[];
extern short D_800B9A02;
s16 rect[4];
DVEC2_C6F4 tmpxy[4];
SVEC2_C6F4 box[8];
SVEC2_C6F4 sxy[8];
MTX_C6F4 mtx;
struct { long flag, opz, sz0, sz1, sz2, sz3; } g;
s32 cx0, cx1, cy0, cy1, y, col;
Cell126 **rowptr;
Cell126 **p;
Cell126 *cell;
Prim126 *prim;
Prim126 *end;
u8 *pkt;
u32 ot;
u8 *vtx;
u8 *va, *vb, *vc, *vd;
u32 w, code;
u32 wx, wy, wz;
u32 xlo, xhi, ylo, yhi, zlo, zhi;
s32 xa32, xb32, t32;
s32 xmn1, xmx1, xmn2, xmx2;
s32 ymn1, ymx1, ymn2, ymx2;
s32 my, mny, mx, mn;
func_800491EC();
func_800547D8(arg0 + 0x10, &mtx);
func_80052E38(&mtx);
func_8017C014(D_8018F9C0, rect, *(s32 *)(arg0 + 0x60));
pkt = D_800A5E60;
ot = (u32)&D_800A6610[(*(u16 *)&D_800B9A02) << 14];
cx0 = (rect[0] + 0x4000) / 512;
cx1 = (rect[0] + rect[2] + 0x4000) / 512 + 2;
cx0 = (cx0 < 0) ? 0 : ((cx0 > 0x3F) ? 0x3F : cx0);
cx1 = (cx1 < 0) ? 0 : ((cx1 > 0x3F) ? 0x3F : cx1);
cy0 = (rect[1] + 0x4000) / 512 - 1;
cy1 = (rect[1] + rect[3] + 0x4000) / 512 + 2;
cy0 = (cy0 < 0) ? 0 : ((cy0 > 0x3F) ? 0x3F : cy0);
cy1 = (cy1 < 0) ? 0 : ((cy1 > 0x3F) ? 0x3F : cy1);
rowptr = (Cell126 **)(*(s32 *)(arg0 + 0xC)) + (cy0 * 64 + cx0);
for (y = cy0; y < cy1; y++, rowptr += 0x40) {
for (col = cx0, p = rowptr; col < cx1; col++, p++) {
cell = *p;
if (cell == 0) continue;
wx = cell->xx;
xlo = wx & 0xFFFF;
xhi = wx >> 16;
wy = cell->yy;
ylo = wy & 0xFFFF;
yhi = wy >> 16;
wz = cell->zz;
zlo = wz & 0xFFFF;
zhi = wz >> 16;
box[0].vx = xlo; box[0].vy = ylo; box[0].vz = zlo;
box[1].vx = xhi; box[1].vy = ylo; box[1].vz = zlo;
box[2].vx = xlo; box[2].vy = ylo; box[2].vz = zhi;
box[3].vx = xhi; box[3].vy = ylo; box[3].vz = zhi;
box[4].vx = xlo; box[4].vy = yhi; box[4].vz = zlo;
box[5].vx = xhi; box[5].vy = yhi; box[5].vz = zlo;
box[6].vx = xlo; box[6].vy = yhi; box[6].vz = zhi;
box[7].vx = xhi; box[7].vy = yhi; box[7].vz = zhi;
gte_ldv3c(&box[0]);
gte_rtpt();
gte_stsxy3(&sxy[0], &sxy[1], &sxy[2]);
gte_ldv0(&box[3]);
gte_rtps();
gte_stsxy(&sxy[3]);
gte_ldv3c(&box[4]);
gte_rtpt();
gte_stsxy3(&sxy[4], &sxy[5], &sxy[6]);
gte_ldv0(&box[7]);
gte_rtps();
gte_stsxy(&sxy[7]);
xa32 = sxy[0].vx;
xb32 = sxy[1].vx;
if (xb32 < xa32) { xmx1 = xa32; xmn1 = xb32; } else { xmn1 = xa32; xmx1 = xb32; }
t32 = sxy[2].vx;
if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32;
t32 = sxy[3].vx;
if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32;
xa32 = sxy[4].vx;
xb32 = sxy[5].vx;
if (xb32 < xa32) { xmx2 = xa32; xmn2 = xb32; } else { xmn2 = xa32; xmx2 = xb32; }
t32 = sxy[6].vx;
if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32;
t32 = sxy[7].vx;
if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32;
mn = xmn1;
if (xmn2 < mn) mn = xmn2;
mx = xmx1;
if (mx < xmx2) mx = xmx2;
if (mx < -0xA0) continue;
if (!(mn < 0xA1)) continue;
xa32 = sxy[0].vy;
xb32 = sxy[1].vy;
if (xb32 < xa32) { ymx1 = xa32; ymn1 = xb32; } else { ymn1 = xa32; ymx1 = xb32; }
t32 = sxy[2].vy;
if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32;
t32 = sxy[3].vy;
if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32;
xa32 = sxy[4].vy;
xb32 = sxy[5].vy;
if (xb32 < xa32) { ymx2 = xa32; ymn2 = xb32; } else { ymn2 = xa32; ymx2 = xb32; }
t32 = sxy[6].vy;
if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32;
t32 = sxy[7].vy;
if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32;
mny = ymn1;
if (ymn2 < mny) mny = ymn2;
my = ymx1;
if (my < ymx2) my = ymx2;
if (my < -0x78) continue;
if (!(mny < 0x79)) continue;
prim = cell->prim;
end = cell->end;
vtx = cell->vtx;
while (prim < end) {
w = prim->w1;
va = vtx + (w & 0xFFFF);
vb = vtx + (w >> 16);
w = prim->w2;
vc = vtx + (w & 0xFFFF);
w = w >> 16;
gte_ldv3(va, vb, vc);
gte_rtpt();
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_nclip();
code = w & 0xF;
vd = vtx + ((w & 0xFFF0) >> 1);
gte_stopz(&g.opz);
if (g.opz > 0) {
switch (code) {
case 4:
case 5:
gte_stsxy3_f3(pkt);
gte_stsz3(&g.sz0, &g.sz1, &g.sz2);
if (((PFT3_C6F4 *)pkt)->x0 > ((PFT3_C6F4 *)pkt)->x1) {
mx = ((PFT3_C6F4 *)pkt)->x0;
mn = ((PFT3_C6F4 *)pkt)->x1;
} else {
mn = ((PFT3_C6F4 *)pkt)->x0;
mx = ((PFT3_C6F4 *)pkt)->x1;
}
if (((PFT3_C6F4 *)pkt)->x2 > mx) mx = ((PFT3_C6F4 *)pkt)->x2;
else if (((PFT3_C6F4 *)pkt)->x2 < mn) mn = ((PFT3_C6F4 *)pkt)->x2;
if (mx >= -0xA0 && mn < 0xA1) {
if (((PFT3_C6F4 *)pkt)->y0 > ((PFT3_C6F4 *)pkt)->y1) {
my = ((PFT3_C6F4 *)pkt)->y0;
mny = ((PFT3_C6F4 *)pkt)->y1;
} else {
mny = ((PFT3_C6F4 *)pkt)->y0;
my = ((PFT3_C6F4 *)pkt)->y1;
}
if (((PFT3_C6F4 *)pkt)->y2 > my) my = ((PFT3_C6F4 *)pkt)->y2;
else if (((PFT3_C6F4 *)pkt)->y2 < mny) mny = ((PFT3_C6F4 *)pkt)->y2;
if (my >= -0x78 && mny < 0x79) {
s32 za;
u32 *otp;
if (g.sz0 > g.sz1) {
za = g.sz0;
if (za < g.sz2) za = g.sz2;
} else {
za = g.sz1;
if (za < g.sz2) za = g.sz2;
}
g.opz = za;
if (code != 4) g.opz = za + 0x200;
((PF3_C6F4 *)pkt)->rgbc = prim->w0;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x4000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x14;
}
}
break;
case 6:
case 7:
gte_stsxy3c(&tmpxy[0]);
gte_stsz3(&g.sz0, &g.sz1, &g.sz2);
if (tmpxy[0].vx > tmpxy[1].vx) {
mx = tmpxy[0].vx;
mn = tmpxy[1].vx;
} else {
mn = tmpxy[0].vx;
mx = tmpxy[1].vx;
}
if (tmpxy[2].vx > mx) mx = tmpxy[2].vx;
else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx;
if (mx >= -0xA0 && mn < 0xA1) {
if (tmpxy[0].vy > tmpxy[1].vy) {
my = tmpxy[0].vy;
mny = tmpxy[1].vy;
} else {
mny = tmpxy[0].vy;
my = tmpxy[1].vy;
}
if (tmpxy[2].vy > my) my = tmpxy[2].vy;
else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy;
if (my >= -0x78 && mny < 0x79) {
s32 za;
u32 *otp;
u32 *tp;
gte_avsz3();
if (g.sz0 > g.sz1) {
za = g.sz0;
if (za < g.sz2) za = g.sz2;
} else {
za = g.sz1;
if (za < g.sz2) za = g.sz2;
}
g.opz = za;
if (code != 6) g.opz = za + 0x200;
*(u32 *)&((PFT3_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0];
*(u32 *)&((PFT3_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1];
*(u32 *)&((PFT3_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2];
tp = (u32 *)prim->w0;
((PFT3_C6F4 *)pkt)->rgbc = tp[0];
((PFT3_C6F4 *)pkt)->uvc0 = tp[1];
((PFT3_C6F4 *)pkt)->uvp1 = tp[2];
((PFT3_C6F4 *)pkt)->uv2 = tp[3];
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x7000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x20;
}
}
break;
case 0:
case 1:
gte_stsxy3_f3(pkt);
gte_ldv0(vd);
gte_rtps();
if (((PF4_C6F4 *)pkt)->x0 > ((PF4_C6F4 *)pkt)->x1) {
mx = ((PF4_C6F4 *)pkt)->x0;
mn = ((PF4_C6F4 *)pkt)->x1;
} else {
mn = ((PF4_C6F4 *)pkt)->x0;
mx = ((PF4_C6F4 *)pkt)->x1;
}
if (((PF4_C6F4 *)pkt)->x2 > mx) mx = ((PF4_C6F4 *)pkt)->x2;
else if (((PF4_C6F4 *)pkt)->x2 < mn) mn = ((PF4_C6F4 *)pkt)->x2;
if (((PF4_C6F4 *)pkt)->y0 > ((PF4_C6F4 *)pkt)->y1) {
my = ((PF4_C6F4 *)pkt)->y0;
mny = ((PF4_C6F4 *)pkt)->y1;
} else {
mny = ((PF4_C6F4 *)pkt)->y0;
my = ((PF4_C6F4 *)pkt)->y1;
}
if (((PF4_C6F4 *)pkt)->y2 > my) my = ((PF4_C6F4 *)pkt)->y2;
else if (((PF4_C6F4 *)pkt)->y2 < mny) mny = ((PF4_C6F4 *)pkt)->y2;
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3);
gte_stsxy((long *)&((PF4_C6F4 *)pkt)->x3);
if (((PF4_C6F4 *)pkt)->x3 < mn) mn = ((PF4_C6F4 *)pkt)->x3;
else if (mx < ((PF4_C6F4 *)pkt)->x3) mx = ((PF4_C6F4 *)pkt)->x3;
if (mx >= -0xA0 && mn < 0xA1) {
if (((PF4_C6F4 *)pkt)->y3 < mny) mny = ((PF4_C6F4 *)pkt)->y3;
else if (my < ((PF4_C6F4 *)pkt)->y3) my = ((PF4_C6F4 *)pkt)->y3;
if (my >= -0x78 && mny < 0x79) {
s32 za, zb;
u32 *otp;
zb = g.sz2;
if (zb < g.sz3) zb = g.sz3;
za = g.sz0;
if (za < g.sz1) za = g.sz1;
if (za < zb) za = zb;
g.opz = za;
if (code != 0) g.opz = za + 0x200;
((PF4_C6F4 *)pkt)->rgbc = prim->w0;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x5000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x18;
}
}
}
break;
case 2:
case 3:
gte_stsxy3c(&tmpxy[0]);
gte_ldv0(vd);
gte_rtps();
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_stsxy(&tmpxy[3]);
gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3);
if (tmpxy[0].vx > tmpxy[1].vx) {
mx = tmpxy[0].vx;
mn = tmpxy[1].vx;
} else {
mn = tmpxy[0].vx;
mx = tmpxy[1].vx;
}
if (tmpxy[2].vx > mx) mx = tmpxy[2].vx;
else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx;
if (tmpxy[3].vx > mx) mx = tmpxy[3].vx;
else if (tmpxy[3].vx < mn) mn = tmpxy[3].vx;
if (mx >= -0xA0 && mn < 0xA1) {
if (tmpxy[0].vy > tmpxy[1].vy) {
my = tmpxy[0].vy;
mny = tmpxy[1].vy;
} else {
mny = tmpxy[0].vy;
my = tmpxy[1].vy;
}
if (tmpxy[2].vy > my) my = tmpxy[2].vy;
else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy;
if (tmpxy[3].vx > my) my = tmpxy[3].vx;
else if (tmpxy[3].vx < mny) mny = tmpxy[3].vx;
if (my >= -0x78 && mny < 0x79) {
s32 za, zb;
u32 *otp;
u32 *tp;
u32 uvw;
gte_avsz4();
zb = g.sz2;
if (zb < g.sz3) zb = g.sz3;
za = g.sz0;
if (za < g.sz1) za = g.sz1;
if (za < zb) za = zb;
g.opz = za;
if (code != 2) g.opz = za + 0x200;
*(u32 *)&((PFT4_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0];
*(u32 *)&((PFT4_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1];
*(u32 *)&((PFT4_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2];
*(u32 *)&((PFT4_C6F4 *)pkt)->x3 = *(u32 *)&tmpxy[3];
tp = (u32 *)prim->w0;
((PFT4_C6F4 *)pkt)->rgbc = tp[0];
((PFT4_C6F4 *)pkt)->uvc0 = tp[1];
((PFT4_C6F4 *)pkt)->uvp1 = tp[2];
uvw = tp[3];
((PFT4_C6F4 *)pkt)->uv2 = uvw;
((PFT4_C6F4 *)pkt)->uv3 = uvw >> 16;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x9000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x28;
}
}
}
break;
}
}
}
prim++;
}
}
}
D_800A5E60 = pkt;
}
+459
View File
@@ -0,0 +1,459 @@
typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2; } PF3_C6F4;
typedef struct { s16 vx, vy; } DVEC2_C6F4;
typedef struct { u8 *vtx; u32 f4; u32 xx, yy, zz; Prim126 *prim, *end; } Cell126;
typedef struct { u32 w0, w1, w2; } Prim126;
#define gte_ldv0(r0) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 )" \
: \
: "r"( r0 ) )
#define gte_ldv3(r0, r1, r2) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 );" \
"lwc2 $2, 0( %1 );" \
"lwc2 $3, 4( %1 );" \
"lwc2 $4, 0( %2 );" \
"lwc2 $5, 4( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) )
#define gte_ldv3c(r0) __asm__ volatile ( \
"lwc2 $0, 0( %0 );" \
"lwc2 $1, 4( %0 );" \
"lwc2 $2, 8( %0 );" \
"lwc2 $3, 12( %0 );" \
"lwc2 $4, 16( %0 );" \
"lwc2 $5, 20( %0 )" \
: \
: "r"( r0 ) )
#define gte_rtps() __asm__ volatile ("nop;nop;rtps")
#define gte_rtpt() __asm__ volatile ("nop;nop;rtpt")
#define gte_nclip() __asm__ volatile ("nop;nop;nclip")
#define gte_avsz3() __asm__ volatile ("nop;nop;avsz3")
#define gte_avsz4() __asm__ volatile ("nop;nop;avsz4")
#define gte_stsxy(r0) __asm__ volatile ( \
"swc2 $14, 0( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsxy3(r0, r1, r2) __asm__ volatile ( \
"swc2 $12, 0( %0 );" \
"swc2 $13, 0( %1 );" \
"swc2 $14, 0( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) \
: "memory" )
#define gte_stsxy3c(r0) __asm__ volatile ( \
"swc2 $12, 0( %0 );" \
"swc2 $13, 4( %0 );" \
"swc2 $14, 8( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsxy3_f3(r0) __asm__ volatile ( \
"swc2 $12, 8( %0 );" \
"swc2 $13, 12( %0 );" \
"swc2 $14, 16( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
#define gte_stsz3(r0, r1, r2) __asm__ volatile ( \
"swc2 $17, 0( %0 );" \
"swc2 $18, 0( %1 );" \
"swc2 $19, 0( %2 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ) \
: "memory" )
#define gte_stsz4(r0, r1, r2, r3) __asm__ volatile ( \
"swc2 $16, 0( %0 );" \
"swc2 $17, 0( %1 );" \
"swc2 $18, 0( %2 );" \
"swc2 $19, 0( %3 )" \
: \
: "r"( r0 ), "r"( r1 ), "r"( r2 ), "r"( r3 ) \
: "memory" )
#define gte_stflg(r0) __asm__ volatile ( \
"cfc2 $12, $31;" \
"nop;" \
"sw $12, 0( %0 )" \
: \
: "r"( r0 ) \
: "$12", "memory" )
#define gte_stopz(r0) __asm__ volatile ( \
"swc2 $24, 0( %0 )" \
: \
: "r"( r0 ) \
: "memory" )
void func_8017C6F4(s32 arg0)
{
extern s32 func_800491EC(void);
extern void func_800547D8(s32, MTX_C6F4 *);
extern void func_80052E38(MTX_C6F4 *);
extern void func_8017C014(void *, void *, s32);
extern u8 D_8018F9C0[];
extern u8 *D_800A5E60;
extern u8 D_800A6610[];
extern short D_800B9A02;
s16 rect[4];
DVEC2_C6F4 tmpxy[4];
SVEC2_C6F4 box[8];
SVEC2_C6F4 sxy[8];
MTX_C6F4 mtx;
struct { long flag, opz, sz0, sz1, sz2, sz3; } g;
s32 cx0, cx1, cy0, cy1, y, col;
Cell126 **rowptr;
Cell126 **p;
Cell126 *cell;
Prim126 *prim;
Prim126 *end;
u8 *pkt;
u32 ot;
u8 *vtx;
u8 *va, *vb, *vc, *vd;
u32 w, code;
u32 wx, wy, wz;
u32 xlo, xhi, ylo, yhi, zlo, zhi;
s32 xa32, xb32, t32;
s32 xmn1, xmx1, xmn2, xmx2;
s32 ymn1, ymx1, ymn2, ymx2;
s32 my, mny, mx, mn;
func_800491EC();
func_800547D8(arg0 + 0x10, &mtx);
func_80052E38(&mtx);
func_8017C014(D_8018F9C0, rect, *(s32 *)(arg0 + 0x60));
pkt = D_800A5E60;
ot = (u32)&D_800A6610[(*(u16 *)&D_800B9A02) << 14];
cx0 = (rect[0] + 0x4000) / 512;
cx1 = (rect[0] + rect[2] + 0x4000) / 512 + 2;
cx0 = (cx0 < 0) ? 0 : ((cx0 > 0x3F) ? 0x3F : cx0);
cx1 = (cx1 < 0) ? 0 : ((cx1 > 0x3F) ? 0x3F : cx1);
cy0 = (rect[1] + 0x4000) / 512 - 1;
cy1 = (rect[1] + rect[3] + 0x4000) / 512 + 2;
cy0 = (cy0 < 0) ? 0 : ((cy0 > 0x3F) ? 0x3F : cy0);
cy1 = (cy1 < 0) ? 0 : ((cy1 > 0x3F) ? 0x3F : cy1);
rowptr = (Cell126 **)(*(s32 *)(arg0 + 0xC)) + (cy0 * 64 + cx0);
for (y = cy0; y < cy1; y++, rowptr += 0x40) {
for (col = cx0, p = rowptr; col < cx1; col++, p++) {
cell = *p;
if (cell == 0) continue;
wx = cell->xx;
xlo = wx & 0xFFFF;
xhi = wx >> 16;
wy = cell->yy;
ylo = wy & 0xFFFF;
yhi = wy >> 16;
wz = cell->zz;
zlo = wz & 0xFFFF;
zhi = wz >> 16;
box[0].vx = xlo; box[0].vy = ylo; box[0].vz = zlo;
box[1].vx = xhi; box[1].vy = ylo; box[1].vz = zlo;
box[2].vx = xlo; box[2].vy = ylo; box[2].vz = zhi;
box[3].vx = xhi; box[3].vy = ylo; box[3].vz = zhi;
box[4].vx = xlo; box[4].vy = yhi; box[4].vz = zlo;
box[5].vx = xhi; box[5].vy = yhi; box[5].vz = zlo;
box[6].vx = xlo; box[6].vy = yhi; box[6].vz = zhi;
box[7].vx = xhi; box[7].vy = yhi; box[7].vz = zhi;
gte_ldv3c(&box[0]);
gte_rtpt();
gte_stsxy3(&sxy[0], &sxy[1], &sxy[2]);
gte_ldv0(&box[3]);
gte_rtps();
gte_stsxy(&sxy[3]);
gte_ldv3c(&box[4]);
gte_rtpt();
gte_stsxy3(&sxy[4], &sxy[5], &sxy[6]);
gte_ldv0(&box[7]);
gte_rtps();
gte_stsxy(&sxy[7]);
xa32 = sxy[0].vx;
xb32 = sxy[1].vx;
if (xb32 < xa32) { xmx1 = xa32; xmn1 = xb32; } else { xmn1 = xa32; xmx1 = xb32; }
t32 = sxy[2].vx;
if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32;
t32 = sxy[3].vx;
if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32;
xa32 = sxy[4].vx;
xb32 = sxy[5].vx;
if (xb32 < xa32) { xmx2 = xa32; xmn2 = xb32; } else { xmn2 = xa32; xmx2 = xb32; }
t32 = sxy[6].vx;
if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32;
t32 = sxy[7].vx;
if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32;
mn = xmn1;
if (xmn2 < mn) mn = xmn2;
mx = xmx1;
if (mx < xmx2) mx = xmx2;
if (mx < -0xA0) continue;
if (!(mn < 0xA1)) continue;
xa32 = sxy[0].vy;
xb32 = sxy[1].vy;
if (xb32 < xa32) { ymx1 = xa32; ymn1 = xb32; } else { ymn1 = xa32; ymx1 = xb32; }
t32 = sxy[2].vy;
if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32;
t32 = sxy[3].vy;
if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32;
xa32 = sxy[4].vy;
xb32 = sxy[5].vy;
if (xb32 < xa32) { ymx2 = xa32; ymn2 = xb32; } else { ymn2 = xa32; ymx2 = xb32; }
t32 = sxy[6].vy;
if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32;
t32 = sxy[7].vy;
if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32;
mny = ymn1;
if (ymn2 < mny) mny = ymn2;
my = ymx1;
if (my < ymx2) my = ymx2;
if (my < -0x78) continue;
if (!(mny < 0x79)) continue;
prim = cell->prim;
end = cell->end;
vtx = cell->vtx;
while (prim < end) {
w = prim->w1;
va = vtx + (w & 0xFFFF);
vb = vtx + (w >> 16);
w = prim->w2;
vc = vtx + (w & 0xFFFF);
w = w >> 16;
gte_ldv3(va, vb, vc);
gte_rtpt();
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_nclip();
code = w & 0xF;
vd = vtx + ((w & 0xFFF0) >> 1);
gte_stopz(&g.opz);
if (g.opz > 0) {
switch (code) {
case 4:
case 5:
gte_stsxy3_f3(pkt);
gte_stsz3(&g.sz0, &g.sz1, &g.sz2);
if (((PFT3_C6F4 *)pkt)->x0 > ((PFT3_C6F4 *)pkt)->x1) {
mx = ((PFT3_C6F4 *)pkt)->x0;
mn = ((PFT3_C6F4 *)pkt)->x1;
} else {
mn = ((PFT3_C6F4 *)pkt)->x0;
mx = ((PFT3_C6F4 *)pkt)->x1;
}
if (((PFT3_C6F4 *)pkt)->x2 > mx) mx = ((PFT3_C6F4 *)pkt)->x2;
else if (((PFT3_C6F4 *)pkt)->x2 < mn) mn = ((PFT3_C6F4 *)pkt)->x2;
if (mx >= -0xA0 && mn < 0xA1) {
if (((PFT3_C6F4 *)pkt)->y0 > ((PFT3_C6F4 *)pkt)->y1) {
my = ((PFT3_C6F4 *)pkt)->y0;
mny = ((PFT3_C6F4 *)pkt)->y1;
} else {
mny = ((PFT3_C6F4 *)pkt)->y0;
my = ((PFT3_C6F4 *)pkt)->y1;
}
if (((PFT3_C6F4 *)pkt)->y2 > my) my = ((PFT3_C6F4 *)pkt)->y2;
else if (((PFT3_C6F4 *)pkt)->y2 < mny) mny = ((PFT3_C6F4 *)pkt)->y2;
if (my >= -0x78 && mny < 0x79) {
s32 za;
u32 *otp;
if (g.sz0 > g.sz1) {
za = g.sz0;
if (za < g.sz2) za = g.sz2;
} else {
za = g.sz1;
if (za < g.sz2) za = g.sz2;
}
g.opz = za;
if (code != 4) g.opz = za + 0x200;
((PF3_C6F4 *)pkt)->rgbc = prim->w0;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x4000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x14;
}
}
break;
case 6:
case 7:
gte_stsxy3c(&tmpxy[0]);
gte_stsz3(&g.sz0, &g.sz1, &g.sz2);
if (tmpxy[0].vx > tmpxy[1].vx) {
mx = tmpxy[0].vx;
mn = tmpxy[1].vx;
} else {
mn = tmpxy[0].vx;
mx = tmpxy[1].vx;
}
if (tmpxy[2].vx > mx) mx = tmpxy[2].vx;
else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx;
if (mx >= -0xA0 && mn < 0xA1) {
if (tmpxy[0].vy > tmpxy[1].vy) {
my = tmpxy[0].vy;
mny = tmpxy[1].vy;
} else {
mny = tmpxy[0].vy;
my = tmpxy[1].vy;
}
if (tmpxy[2].vy > my) my = tmpxy[2].vy;
else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy;
if (my >= -0x78 && mny < 0x79) {
s32 za;
u32 *otp;
u32 *tp;
gte_avsz3();
if (g.sz0 > g.sz1) {
za = g.sz0;
if (za < g.sz2) za = g.sz2;
} else {
za = g.sz1;
if (za < g.sz2) za = g.sz2;
}
g.opz = za;
if (code != 6) g.opz = za + 0x200;
*(u32 *)&((PFT3_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0];
*(u32 *)&((PFT3_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1];
*(u32 *)&((PFT3_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2];
tp = (u32 *)prim->w0;
((PFT3_C6F4 *)pkt)->rgbc = tp[0];
((PFT3_C6F4 *)pkt)->uvc0 = tp[1];
((PFT3_C6F4 *)pkt)->uvp1 = tp[2];
((PFT3_C6F4 *)pkt)->uv2 = tp[3];
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x7000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x20;
}
}
break;
case 0:
case 1:
gte_stsxy3_f3(pkt);
gte_ldv0(vd);
gte_rtps();
if (((PF4_C6F4 *)pkt)->x0 > ((PF4_C6F4 *)pkt)->x1) {
mx = ((PF4_C6F4 *)pkt)->x0;
mn = ((PF4_C6F4 *)pkt)->x1;
} else {
mn = ((PF4_C6F4 *)pkt)->x0;
mx = ((PF4_C6F4 *)pkt)->x1;
}
if (((PF4_C6F4 *)pkt)->x2 > mx) mx = ((PF4_C6F4 *)pkt)->x2;
else if (((PF4_C6F4 *)pkt)->x2 < mn) mn = ((PF4_C6F4 *)pkt)->x2;
if (((PF4_C6F4 *)pkt)->y0 > ((PF4_C6F4 *)pkt)->y1) {
my = ((PF4_C6F4 *)pkt)->y0;
mny = ((PF4_C6F4 *)pkt)->y1;
} else {
mny = ((PF4_C6F4 *)pkt)->y0;
my = ((PF4_C6F4 *)pkt)->y1;
}
if (((PF4_C6F4 *)pkt)->y2 > my) my = ((PF4_C6F4 *)pkt)->y2;
else if (((PF4_C6F4 *)pkt)->y2 < mny) mny = ((PF4_C6F4 *)pkt)->y2;
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3);
gte_stsxy((long *)&((PF4_C6F4 *)pkt)->x3);
if (((PF4_C6F4 *)pkt)->x3 < mn) mn = ((PF4_C6F4 *)pkt)->x3;
else if (mx < ((PF4_C6F4 *)pkt)->x3) mx = ((PF4_C6F4 *)pkt)->x3;
if (mx >= -0xA0 && mn < 0xA1) {
if (((PF4_C6F4 *)pkt)->y3 < mny) mny = ((PF4_C6F4 *)pkt)->y3;
else if (my < ((PF4_C6F4 *)pkt)->y3) my = ((PF4_C6F4 *)pkt)->y3;
if (my >= -0x78 && mny < 0x79) {
s32 za, zb;
u32 *otp;
zb = g.sz2;
if (zb < g.sz3) zb = g.sz3;
za = g.sz0;
if (za < g.sz1) za = g.sz1;
if (za < zb) za = zb;
g.opz = za;
if (code != 0) g.opz = za + 0x200;
((PF4_C6F4 *)pkt)->rgbc = prim->w0;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x5000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x18;
}
}
}
break;
case 2:
case 3:
gte_stsxy3c(&tmpxy[0]);
gte_ldv0(vd);
gte_rtps();
gte_stflg(&g.flag);
if (!(g.flag & 0x7F85E000)) {
gte_stsxy(&tmpxy[3]);
gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3);
if (tmpxy[0].vx > tmpxy[1].vx) {
mx = tmpxy[0].vx;
mn = tmpxy[1].vx;
} else {
mn = tmpxy[0].vx;
mx = tmpxy[1].vx;
}
if (tmpxy[2].vx > mx) mx = tmpxy[2].vx;
else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx;
if (tmpxy[3].vx > mx) mx = tmpxy[3].vx;
else if (tmpxy[3].vx < mn) mn = tmpxy[3].vx;
if (mx >= -0xA0 && mn < 0xA1) {
if (tmpxy[0].vy > tmpxy[1].vy) {
my = tmpxy[0].vy;
mny = tmpxy[1].vy;
} else {
mny = tmpxy[0].vy;
my = tmpxy[1].vy;
}
if (tmpxy[2].vy > my) my = tmpxy[2].vy;
else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy;
if (tmpxy[3].vx > my) my = tmpxy[3].vx;
else if (tmpxy[3].vx < mny) mny = tmpxy[3].vx;
if (my >= -0x78 && mny < 0x79) {
s32 za, zb;
u32 *otp;
u32 *tp;
u32 uvw;
gte_avsz4();
zb = g.sz2;
if (zb < g.sz3) zb = g.sz3;
za = g.sz0;
if (za < g.sz1) za = g.sz1;
if (za < zb) za = zb;
g.opz = za;
if (code != 2) g.opz = za + 0x200;
*(u32 *)&((PFT4_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0];
*(u32 *)&((PFT4_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1];
*(u32 *)&((PFT4_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2];
*(u32 *)&((PFT4_C6F4 *)pkt)->x3 = *(u32 *)&tmpxy[3];
tp = (u32 *)prim->w0;
((PFT4_C6F4 *)pkt)->rgbc = tp[0];
((PFT4_C6F4 *)pkt)->uvc0 = tp[1];
((PFT4_C6F4 *)pkt)->uvp1 = tp[2];
uvw = tp[3];
((PFT4_C6F4 *)pkt)->uv2 = uvw;
((PFT4_C6F4 *)pkt)->uv3 = uvw >> 16;
otp = (u32 *)(((g.opz >> 2) << 2) + ot);
*(u32 *)pkt = (*otp & 0xFFFFFF) | 0x9000000;
*otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF);
pkt += 0x28;
}
}
}
break;
}
}
}
prim++;
}
}
}
D_800A5E60 = pkt;
}
+18 -8
View File
@@ -2462,14 +2462,24 @@ re-verified three ways: image SHA == locked SHA, stub gone, real definition pres
| ov_SC03_104 | func_80184934 | ov_SC04_007 | func_8017FF08 |
| ov_SC04_003 | func_8017E4F4 | | |
**THE DEFECT THIS PROVES:** `family_sweep --hseq` reported this family **0/5 with
`PLUMBING: parse error before 'unsigned'`** — but the remapped drafts are byte-CORRECT. The parse error
comes from the sweep's own **gate-pipeline transform**, not from the remap: the only `unsigned` in the
draft sits inside a comment, so a transform is eating a `/*` opener and turning comment text into code.
Isolated per-transform runs (`canon_resident_calls` / `cast_call_sites` / `sig_unify`, each on the draft
alone) all preserve it — so the corruption needs the gate's real invocation (with `--src-file`) to
reproduce. **NOT YET PINNED — and it is silently costing banks in every sweep it touches.** Next
session: run the three transforms with `--src-file` set to the target TU and diff the output.
**THE DEFECT, PINNED — and my first hypothesis was WRONG (R14, corrected in place).** I wrote that a
gate-pipeline transform was eating a `/*` opener and turning comment prose into code, because the only
`unsigned` in the draft sits inside a comment. **Refuted by test:** every ladder step —
`cast_call_sites`, `sig_unify`, `reconcile_tu`, each run with the gate's real `--src-file` — preserves
the comment intact.
**The real cause is the `family_remap` TYPEDEF-CARRY GAP (§146/§152), full stop.** The staged draft
fails as `` `Vec8_80182FD4' undeclared (first use this function) `` — the type the body needs was never
carried, because `family_remap`'s unit backscan halts at the first `#define`. `parse error before
'unsigned'` was simply that failure surfacing at the next recognizable token, the following
`extern unsigned char …` line. **A misleading label, not a second defect.**
**Why direct gating banked all 5 anyway:** the TARGET TUs already declare that type at file scope, so
the splice compiles even though the draft fails in isolation. **That is the rule worth keeping — the
typedef gap is fatal only when the target TU does not already declare the type**, which is exactly why
this family looked like an intractable "parse error" wall in the sweep and banked instantly when gated
directly. Fixing `family_remap`'s backscan (let it skip `#define` continuation blocks) closes the whole
class; until then, gate remapped drafts DIRECTLY rather than through `family_sweep`'s ladder.
**The workaround that banked them:** carry the exemplar's typedefs onto each remapped draft by hand
(the same `family_remap` `_carry_macros` gap as §146/§152) and gate directly, bypassing the sweep's
+66
View File
@@ -880,6 +880,9 @@ def extract_unit(ov, addr):
macros = _carry_macros(lines, start, end, unit_text) # gte_* etc. the body needs (T5)
if macros:
unit_text = "\n".join(macros) + "\n" + unit_text
tds = _carry_typedefs(lines, unit_text) # types above a #define (S43)
if tds:
unit_text = "\n".join(tds) + "\n" + unit_text
return unit_text, cf
if alias_ident:
# R32: we PROVED the function is defined here (the asm label binds the symbol) but could
@@ -891,6 +894,69 @@ def extract_unit(ov, addr):
return _macro_unit(addr)
_TD_NAME_RE = re.compile(r'^\s*typedef\b.*?([A-Za-z_]\w*)\s*(?:\[[^\]]*\])?\s*;', re.S)
def _carry_typedefs(lines, unit_text):
"""Carry any file-scope typedef the extracted unit actually USES but did not carry.
P30 S43. The preamble backscan's accept-set is blank/`extern`/comment/`typedef`, so it **halts at
the first `#define`** and never reaches typedefs declared above the macro block. `_carry_macros`
then re-attaches the macros, which hides the truncation — the unit looks complete and is not.
Measured on the 0x80182FD4 family: 16/16 gte macros carried, **0/10 typedefs**, silently; the
staged sibling failed as `` `Vec8_80182FD4' undeclared `` and the sweep booked it
`PLUMBING: parse error before 'unsigned'` (the error surfacing at the next token), which read as
an intractable wall. It banked instantly once the type was carried by hand.
Additive by construction: only typedefs whose NAME appears as a word in the unit and which are not
already present are prepended, so a unit that was already complete is byte-unchanged. Whether the
gap is fatal depends on whether the TARGET TU happens to declare the type itself — which is why
this failed loudly for some families and silently succeeded for others."""
# index every file-scope typedef once: name -> full (possibly multi-line) block
defs = []
for k, ln in enumerate(lines):
if not ln.lstrip().startswith("typedef"):
continue
# BRACE-AWARE block capture. A `;`-terminated scan stops INSIDE the struct — the first
# member line (`SVECTOR_8016E7C8 v[4];`) ends in `;` — yielding a truncated, unclosed
# typedef that cc1 reports at the member's type name. Close on the brace depth instead,
# then take the `;` that follows `}` (P30 S43, measured).
blk, j, depth, opened = ln, k, ln.count("{") - ln.count("}"), "{" in ln
while j + 1 < len(lines) and j - k < 60 and (
(opened and depth > 0) or (not opened and ";" not in blk)):
j += 1
blk += "\n" + lines[j]
depth += lines[j].count("{") - lines[j].count("}")
opened = opened or "{" in lines[j]
while opened and ";" not in blk.rsplit("}", 1)[-1] and j + 1 < len(lines) and j - k < 60:
j += 1
blk += "\n" + lines[j]
m = _TD_NAME_RE.match(blk)
if m:
defs.append((m.group(1), blk))
# TRANSITIVE closure: a carried typedef may itself name another typedef (measured — carrying
# `Vec8_80182FD4` alone then failed on `SVECTOR_8016E7C8`, which it references). Iterate to a
# fixpoint, emitting DEPENDENCY-FIRST so C89 sees each name before its use.
out, seen, want = [], set(), unit_text
for _ in range(12): # depth guard; real chains here are 2-3
added = False
for name, blk in defs:
if name in seen:
continue
if re.search(r'^\s*typedef\b[^\n]*\b' + re.escape(name) + r'\b', unit_text, re.M):
seen.add(name) # already carried by the backscan
continue
if re.search(r'\b' + re.escape(name) + r'\b', want):
seen.add(name)
out.insert(0, blk) # dependency-first: later finds precede earlier ones
want += "\n" + blk
added = True
if not added:
break
return out
def _macro_unit(addr):
r"""Fallback: reconstruct the unit from its SHARED `DEFINE_func_<ADDR>()` macro.