Fix precise NCLIP on PGXP-backed GTE shadows

This commit is contained in:
Matthew Stanley
2026-08-15 21:46:47 -07:00
parent 696d05643d
commit 41c232fb47
3 changed files with 24 additions and 8 deletions
+4
View File
@@ -55,6 +55,10 @@ void pgxp_suppress_end(void);
* sees. Shifts the shadow FIFO exactly like push_sxy (regs 12..15). */
void pgxp_gte_push_sxy(int32_t x16, int32_t y16, uint16_t sz3, uint32_t packed);
/* Current SXY FIFO shadow (index 0..3 selects GTE data regs 12..15).
* Returns nonzero when the shadow is live and carries X/Y precision. */
int pgxp_get_gte_sxy(uint32_t index, int32_t *x16, int32_t *y16);
/* Guest write to a GTE data register outside gte_execute (MTC2/CTC2 handled
* by psx_pgxp_cop2; this is for direct gte_write_data paths): reg 15 performs
* the SXYP FIFO push on the shadows, others just invalidate/overwrite. */
+10 -8
View File
@@ -929,15 +929,17 @@ void gte_nclip(GTEState* gte, uint32_t instr) {
int32_t sy1 = static_cast<int16_t>(gte->SXY[1] >> 16);
int32_t sx2 = static_cast<int16_t>(gte->SXY[2] & 0xFFFF);
int32_t sy2 = static_cast<int16_t>(gte->SXY[2] >> 16);
int32_t px0 = 0, py0 = 0, px1 = 0, py1 = 0, px2 = 0, py2 = 0;
if (gpu_ws_precise_nclip_enabled() &&
s_precise_sxy[0].valid && s_precise_sxy[1].valid &&
s_precise_sxy[2].valid) {
sx0 = s_precise_sxy[0].x16 >> 16;
sy0 = s_precise_sxy[0].y16 >> 16;
sx1 = s_precise_sxy[1].x16 >> 16;
sy1 = s_precise_sxy[1].y16 >> 16;
sx2 = s_precise_sxy[2].x16 >> 16;
sy2 = s_precise_sxy[2].y16 >> 16;
pgxp_get_gte_sxy(0, &px0, &py0) &&
pgxp_get_gte_sxy(1, &px1, &py1) &&
pgxp_get_gte_sxy(2, &px2, &py2)) {
sx0 = px0 >> 16;
sy0 = py0 >> 16;
sx1 = px1 >> 16;
sy1 = py1 >> 16;
sx2 = px2 >> 16;
sy2 = py2 >> 16;
}
int64_t mac0 = (int64_t)sx0 * (sy1 - sy2) +
(int64_t)sx1 * (sy2 - sy0) +
+10
View File
@@ -644,6 +644,16 @@ extern "C" void pgxp_gte_push_sxy(int32_t x16, int32_t y16, uint16_t sz3,
s_gte[15] = *pv; /* SXYP mirrors SXY2 */
}
extern "C" int pgxp_get_gte_sxy(uint32_t index, int32_t *x16, int32_t *y16) {
if (index >= 4) return 0;
const PGXPValue *pv = &s_gte[12 + index];
if (!pv_live(pv) || (pv->flags & PGXP_F_VXY) != PGXP_F_VXY)
return 0;
if (x16) *x16 = pv->x16;
if (y16) *y16 = pv->y16;
return 1;
}
extern "C" void pgxp_gte_reg_written(int reg, uint32_t value) {
/* Invalidation-class bookkeeping: runs even with the engine disarmed so
* seeded/leftover shadows can never outlive a guest register write. Only