diff --git a/.run/s43/regress_ov_SC03_003.c b/.run/s43/regress_ov_SC03_003.c new file mode 100644 index 000000000..4502742a8 --- /dev/null +++ b/.run/s43/regress_ov_SC03_003.c @@ -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; +} diff --git a/.run/s43/regress_ov_SC04_021.c b/.run/s43/regress_ov_SC04_021.c new file mode 100644 index 000000000..9b2486289 --- /dev/null +++ b/.run/s43/regress_ov_SC04_021.c @@ -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; +} diff --git a/.run/s43/regress_ov_SC05_019.c b/.run/s43/regress_ov_SC05_019.c new file mode 100644 index 000000000..9b2486289 --- /dev/null +++ b/.run/s43/regress_ov_SC05_019.c @@ -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; +} diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index 5e3161321..5bbc8abaa 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -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 diff --git a/tools/family_remap.py b/tools/family_remap.py index 1477e5351..9c1a5d842 100644 --- a/tools/family_remap.py +++ b/tools/family_remap.py @@ -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_()` macro.