runtime: add title-scoped exact NCLIP branches

This commit is contained in:
tetrisgm
2026-08-27 16:03:16 -07:00
parent f3986617a0
commit 81ebee1346
12 changed files with 185 additions and 24 deletions
+4
View File
@@ -150,6 +150,10 @@ struct CodeGenConfig {
// widescreen reveals extra world. 4:3 keeps the original branch predicate.
std::set<uint32_t> ws_cull_nclip_keep_sites;
// Exact `bltz MAC0, reject`-style NCLIP/backface sites that consume the
// validated precise sign while wide, without changing guest-visible MAC0.
std::set<uint32_t> ws_cull_nclip_exact_sites;
// Exact branch PCs whose reject target is suppressed while widescreen
// reveals extra world. 4:3 keeps the original branch predicate.
std::set<uint32_t> ws_cull_branch_keep_sites;
+3
View File
@@ -784,6 +784,9 @@ std::string CodeGenerator::generate_branch_condition(uint32_t instr, uint32_t ad
if (regimm_op == 0x00 && config_.ws_cull_nclip_keep_sites.count(addr))
return fmt::format("psx_ws_x_margin() > 0 ? 0 : ((int32_t){} < 0) /* ws nclip keep */",
reg_name(rs));
if (regimm_op == 0x00 && config_.ws_cull_nclip_exact_sites.count(addr))
return fmt::format("psx_ws_x_margin() > 0 ? gte_nclip_precise_bltz((int32_t){}) : ((int32_t){} < 0) /* ws exact nclip */",
reg_name(rs), reg_name(rs));
return keep_branch_if_wide(
fmt::format("(int32_t){} < 0", reg_name(rs)));
} else { // bgez family (incl. bgezal + undefined mirrors)
+4
View File
@@ -73,6 +73,7 @@ uint32_t overlay_codegen_config_hash(const GameConfig& c) {
h.words("cull_plane_nx", c.ws_cull_plane_nx_sites);
h.words("cull_xclip_load", c.ws_cull_xclip_load_sites);
h.words("cull_nclip_keep", c.ws_cull_nclip_keep_sites);
h.words("cull_nclip_exact", c.ws_cull_nclip_exact_sites);
h.words("cull_branch_keep", c.ws_cull_branch_keep_sites);
h.words("cull_w_imms", c.ws_cull_w_imms);
h.words("cull_h_imms", c.ws_cull_h_imms);
@@ -1697,6 +1698,7 @@ GameConfig load_game_config(const fs::path& config_path_in) {
std::vector<uint32_t> ws_cull_plane_nx_sites;
std::vector<uint32_t> ws_cull_xclip_load_sites;
std::vector<uint32_t> ws_cull_nclip_keep_sites;
std::vector<uint32_t> ws_cull_nclip_exact_sites;
std::vector<uint32_t> ws_cull_branch_keep_sites;
std::vector<WidescreenCullKeepSite> ws_cull_keep_sites;
std::vector<WidescreenCullWidenSite> ws_cull_widen_sites;
@@ -1733,6 +1735,7 @@ GameConfig load_game_config(const fs::path& config_path_in) {
load_sites("plane_nx_sites", ws_cull_plane_nx_sites);
load_sites("xclip_load_sites", ws_cull_xclip_load_sites);
load_sites("nclip_keep_sites", ws_cull_nclip_keep_sites);
load_sites("nclip_exact_sites", ws_cull_nclip_exact_sites);
load_sites("branch_keep_sites", ws_cull_branch_keep_sites);
if (cull.contains("keep")) {
std::set<uint32_t> seen;
@@ -2214,6 +2217,7 @@ GameConfig load_game_config(const fs::path& config_path_in) {
/*ws_cull_plane_nx_sites*/ ws_cull_plane_nx_sites,
/*ws_cull_xclip_load_sites*/ ws_cull_xclip_load_sites,
/*ws_cull_nclip_keep_sites*/ ws_cull_nclip_keep_sites,
/*ws_cull_nclip_exact_sites*/ ws_cull_nclip_exact_sites,
/*ws_cull_branch_keep_sites*/ ws_cull_branch_keep_sites,
/*ws_cull_keep_sites*/ ws_cull_keep_sites,
/*ws_cull_widen_sites*/ ws_cull_widen_sites,
+3
View File
@@ -999,6 +999,9 @@ struct GameConfig {
// not-taken only while widescreen reveals extra world. This is deliberately
// separate from bltz_sites, whose helper adjusts screen-X edge thresholds.
std::vector<uint32_t> ws_cull_nclip_keep_sites;
// Exact NCLIP/backface branch sites that use the validated tracked sign
// only while wide. Guest MAC0 remains native and 4:3 remains bit-exact.
std::vector<uint32_t> ws_cull_nclip_exact_sites;
// Exact branch PCs whose reject path is forced not-taken only while
// widescreen reveals extra world. Use only after screenshot-validated
// evidence that the target is a visibility reject.
+4
View File
@@ -210,6 +210,7 @@ int main(int argc, char** argv) {
std::set<uint32_t> ws_cull_plane_nx; // [widescreen.cull] plane_nx_sites
std::set<uint32_t> ws_cull_xclip_load; // [widescreen.cull] xclip_load_sites
std::set<uint32_t> ws_cull_nclip_keep; // [widescreen.cull] nclip_keep_sites
std::set<uint32_t> ws_cull_nclip_exact; // [widescreen.cull] nclip_exact_sites
std::set<uint32_t> ws_cull_branch_keep; // [widescreen.cull] branch_keep_sites
std::vector<PSXRecompV4::WidescreenCullKeepSite> ws_cull_keep;
std::vector<PSXRecompV4::WidescreenCullWidenSite> ws_cull_widen;
@@ -274,6 +275,7 @@ int main(int argc, char** argv) {
ws_cull_plane_nx.insert(cfg.ws_cull_plane_nx_sites.begin(), cfg.ws_cull_plane_nx_sites.end());
ws_cull_xclip_load.insert(cfg.ws_cull_xclip_load_sites.begin(), cfg.ws_cull_xclip_load_sites.end());
ws_cull_nclip_keep.insert(cfg.ws_cull_nclip_keep_sites.begin(), cfg.ws_cull_nclip_keep_sites.end());
ws_cull_nclip_exact.insert(cfg.ws_cull_nclip_exact_sites.begin(), cfg.ws_cull_nclip_exact_sites.end());
ws_cull_branch_keep.insert(cfg.ws_cull_branch_keep_sites.begin(), cfg.ws_cull_branch_keep_sites.end());
ws_cull_keep = cfg.ws_cull_keep_sites;
ws_cull_widen = cfg.ws_cull_widen_sites;
@@ -370,6 +372,7 @@ int main(int argc, char** argv) {
ws_cull_plane_nx.insert(wscfg.ws_cull_plane_nx_sites.begin(), wscfg.ws_cull_plane_nx_sites.end());
ws_cull_xclip_load.insert(wscfg.ws_cull_xclip_load_sites.begin(), wscfg.ws_cull_xclip_load_sites.end());
ws_cull_nclip_keep.insert(wscfg.ws_cull_nclip_keep_sites.begin(), wscfg.ws_cull_nclip_keep_sites.end());
ws_cull_nclip_exact.insert(wscfg.ws_cull_nclip_exact_sites.begin(), wscfg.ws_cull_nclip_exact_sites.end());
ws_cull_branch_keep.insert(wscfg.ws_cull_branch_keep_sites.begin(), wscfg.ws_cull_branch_keep_sites.end());
if (ws_cull_keep.empty()) ws_cull_keep = wscfg.ws_cull_keep_sites;
if (ws_cull_widen.empty()) ws_cull_widen = wscfg.ws_cull_widen_sites;
@@ -1235,6 +1238,7 @@ int main(int argc, char** argv) {
codegen_config.ws_cull_plane_nx_sites = ws_cull_plane_nx;
codegen_config.ws_cull_xclip_load_sites = ws_cull_xclip_load;
codegen_config.ws_cull_nclip_keep_sites = ws_cull_nclip_keep;
codegen_config.ws_cull_nclip_exact_sites = ws_cull_nclip_exact;
codegen_config.ws_cull_branch_keep_sites = ws_cull_branch_keep;
codegen_config.ws_cull_keep_sites = ws_cull_keep;
codegen_config.ws_cull_widen_sites = ws_cull_widen;
@@ -245,6 +245,15 @@ branch_keep_sites = ["0x80012340"]
std::vector<uint32_t>{0x80012340u},
"parser preserves branch keep sites");
const auto nclip_exact = write_config(root, "nclip-exact", R"toml(
[widescreen.cull]
nclip_exact_sites = ["0x80012340"]
)toml");
const auto nclip_exact_config = PSXRecompV4::load_game_config(nclip_exact);
check(nclip_exact_config.ws_cull_nclip_exact_sites ==
std::vector<uint32_t>{0x80012340u},
"parser preserves exact NCLIP branch sites");
const auto vxrange = write_config(root, "vxrange", R"toml(
[widescreen.cull]
vxrange_sites = ["0x80012340"]
@@ -729,6 +738,16 @@ void codegen_tests() {
branch_keep.find("ws branch keep") != std::string::npos,
"codegen emits guarded branch keep predicate");
PSXRecomp::CodeGenConfig nclip_exact_config;
nclip_exact_config.ws_cull_nclip_exact_sites.insert(0x80010000u);
const std::string nclip_exact = generate_first_instruction(
0x04400002u, {}, false, nclip_exact_config); // bltz v0,+2
check(nclip_exact.find(
"gte_nclip_precise_bltz((int32_t)cpu->gpr[2])") !=
std::string::npos &&
nclip_exact.find("ws exact nclip") != std::string::npos,
"codegen emits title-scoped exact NCLIP predicate");
PSXRecomp::CodeGenConfig plane_nx_config;
plane_nx_config.ws_cull_plane_nx_sites.insert(0x80010000u);
const std::string plane_nx = generate_first_instruction(
+8 -4
View File
@@ -220,11 +220,15 @@ extern uint32_t gte_geometry_correction_hits(void);
extern void gte_geometry_correction_stats(uint32_t *lookups, uint32_t *hits,
uint32_t *miss_unrecorded,
uint32_t *miss_ambiguous);
/* Exact-sign NCLIP coverage: precise = all three SXY shadows live and
* word-validated; fallback = integer sign decided (the widescreen thin-face
* flicker regime); corrected = sign disagreements actually fixed. */
/* Exact NCLIP audit coverage: precise = all three SXY shadows are coherent and
* word-validated; fallback = native integer-only; disagreements counts cases
* where sub-pixel and guest-visible integer signs differ. MAC0 stays native. */
extern void gte_nclip_precise_stats(uint64_t *hits, uint64_t *fallbacks,
uint64_t *corrected);
uint64_t *disagreements);
/* Title-scoped widescreen cull consumer. Returns the exact tracked NCLIP sign
* only when it belongs to the supplied native MAC0; otherwise preserves the
* native comparison. This does not change guest-visible GTE state. */
extern int gte_nclip_precise_bltz(int32_t native_mac0);
/* pc=0 escape journal (traps.c). Every runtime site that publishes a null PC
* (the "continue the native chain below" convention) or rescues one records
+5
View File
@@ -58,6 +58,11 @@ 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);
/* Validate-on-read variant: check!=0 additionally requires the shadow's packed
* word to equal expect (the live guest SXY word). Sign consumers must use this
* form so stale FIFO shadows fail closed to native integer behavior. */
int pgxp_get_gte_sxy_checked(uint32_t index, uint32_t expect, int check,
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
+16 -5
View File
@@ -221,7 +221,13 @@ static int ws_gameplay_state_value_count = 0;
* this many consecutive frames (save/options/memory-card) — reverts to 4:3. */
#define WS_GTE_GAME_MODE_HYSTERESIS 45u
void gpu_ws_set_gte_game_mode(int on) { ws_gte_game_mode_cfg = on ? 1 : 0; }
void gpu_ws_set_precise_nclip(int on) { ws_precise_nclip_cfg = on ? 1 : 0; }
void gpu_pgxp_rederive_enable(void);
void gpu_ws_set_precise_nclip(int on) {
ws_precise_nclip_cfg = on ? 1 : 0;
/* Exact NCLIP consumes PGXP transport shadows even when every visual
* PGXP correction is disabled. Re-derive the internal transport arm. */
gpu_pgxp_rederive_enable();
}
int gpu_ws_precise_nclip_enabled(void) { return ws_precise_nclip_cfg && ws_active(); }
void gpu_ws_set_gameplay_state_gate(uint32_t addr,
const uint32_t *values, int nvalues) {
@@ -3448,12 +3454,17 @@ static int s_texture_correction_enabled = 0;
extern int gte_precision_load_word(uint32_t addr, uint32_t packed,
int32_t *x16, int32_t *y16, uint16_t *z);
/* Arm the PGXP dataflow transport for any consumer. Exact NCLIP is an internal
* sign source only; this does not enable geometry or texture correction. */
void gpu_pgxp_rederive_enable(void) {
pgxp_set_enabled(s_texture_correction_enabled ||
gte_geometry_correction_enabled() ||
ws_precise_nclip_cfg);
}
void gpu_texture_correction_set(int enabled) {
s_texture_correction_enabled = enabled ? 1 : 0;
/* The PGXP dataflow engine feeds BOTH corrections; arm it while either
* is on (geometry correction is toggled in gte.cpp, so re-derive here). */
pgxp_set_enabled(s_texture_correction_enabled ||
gte_geometry_correction_enabled());
gpu_pgxp_rederive_enable();
}
int gpu_texture_correction_enabled(void) {
+57 -15
View File
@@ -312,6 +312,8 @@ static inline int64_t geom_slot(uint32_t packed) {
return (int64_t)(y + GEOM_BIAS) * GEOM_AXIS + (x + GEOM_BIAS);
}
extern "C" void gpu_pgxp_rederive_enable(void);
extern "C" void gte_geometry_correction_set(int enabled) {
s_geom_enabled = enabled ? 1 : 0;
s_geom_hits = 0;
@@ -324,6 +326,7 @@ extern "C" void gte_geometry_correction_set(int enabled) {
if (!s_geom_cache) s_geom_enabled = 0; /* fail closed: stay faithful */
}
gte_geom_generation_advance();
gpu_pgxp_rederive_enable();
}
/* Lookup census for the debug server: attempted, hit, and the two miss classes.
@@ -888,9 +891,15 @@ void gte_rtps_internal(GTEState* gte, int16_t* V, bool setMac0, uint32_t instr)
int64_t sx = sx16 >> 16;
int64_t sy = sy16 >> 16;
gte->push_sxy(sx, sy);
if (!s_gte_replay_sandbox)
pgxp_gte_push_sxy((int32_t)sx16, (int32_t)sy16, gte->SZ[3],
if (!s_gte_replay_sandbox) {
/* Bound the 16.16 transport so an extreme projection cannot wrap an
* int32 and masquerade as a valid on-screen shadow. */
const int64_t kLim = (int64_t)4096 << 16;
int64_t cx16 = sx16 < -kLim ? -kLim : (sx16 > kLim - 1 ? kLim - 1 : sx16);
int64_t cy16 = sy16 < -kLim ? -kLim : (sy16 > kLim - 1 ? kLim - 1 : sy16);
pgxp_gte_push_sxy((int32_t)cx16, (int32_t)cy16, gte->SZ[3],
(uint32_t)gte->SXY[2]);
}
geom_note((uint32_t)gte->SXY[2], sx16, sy16);
// Step 5: Depth cueing (MAC0/IR0) — only for last vertex of RTPT or RTPS
@@ -921,6 +930,24 @@ void gte_rtpt(GTEState* gte, uint32_t instr) {
// ---------------------------------------------------------------------------
// NCLIP (0x06) — Normal Clipping (2D cross product for backface culling)
// ---------------------------------------------------------------------------
static uint64_t s_nclip_precise_hits = 0;
static uint64_t s_nclip_fallbacks = 0;
static uint64_t s_nclip_disagreements = 0;
static int32_t s_nclip_last_native = 0;
static int8_t s_nclip_last_precise_sign = 0;
static bool s_nclip_last_precise_valid = false;
extern "C" void gte_nclip_precise_stats(uint64_t *hits, uint64_t *fallbacks,
uint64_t *disagreements) {
if (hits) *hits = s_nclip_precise_hits;
if (fallbacks) *fallbacks = s_nclip_fallbacks;
if (disagreements) *disagreements = s_nclip_disagreements;
}
extern "C" int gte_nclip_precise_bltz(int32_t native_mac0) {
if (!s_nclip_last_precise_valid || native_mac0 != s_nclip_last_native)
return native_mac0 < 0;
return s_nclip_last_precise_sign < 0;
}
void gte_nclip(GTEState* gte, uint32_t instr) {
gte->FLAG = 0;
int32_t sx0 = static_cast<int16_t>(gte->SXY[0] & 0xFFFF);
@@ -929,23 +956,36 @@ 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() &&
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) +
(int64_t)sx2 * (sy0 - sy1);
gte->check_mac0_overflow(mac0);
gte->MAC0 = static_cast<int32_t>(mac0);
int32_t out = static_cast<int32_t>(mac0);
s_nclip_last_native = out;
s_nclip_last_precise_valid = false;
/* Compute an exact 16.16 determinant for configured branch consumers, but
* preserve native guest-visible MAC0 for every architectural reader. */
int32_t px0, py0, px1, py1, px2, py2;
if (gpu_ws_precise_nclip_enabled() &&
!s_gte_replay_sandbox && s_speculative_depth == 0 &&
pgxp_get_gte_sxy_checked(0, gte->SXY[0], 1, &px0, &py0) &&
pgxp_get_gte_sxy_checked(1, gte->SXY[1], 1, &px1, &py1) &&
pgxp_get_gte_sxy_checked(2, gte->SXY[2], 1, &px2, &py2)) {
s_nclip_precise_hits++;
const int64_t dx10 = (int64_t)px1 - px0;
const int64_t dy10 = (int64_t)py1 - py0;
const int64_t dx20 = (int64_t)px2 - px0;
const int64_t dy20 = (int64_t)py2 - py0;
const int64_t cross = dx10 * dy20 - dy10 * dx20;
s_nclip_last_precise_sign = cross < 0 ? -1 : (cross > 0 ? 1 : 0);
s_nclip_last_precise_valid = true;
if ((cross > 0 && out <= 0) || (cross < 0 && out >= 0))
s_nclip_disagreements++;
} else if (gpu_ws_precise_nclip_enabled() &&
!s_gte_replay_sandbox && s_speculative_depth == 0) {
s_nclip_fallbacks++;
}
gte->MAC0 = out;
gte->set_error_flag();
}
@@ -1543,11 +1583,13 @@ extern "C" int gte_replay_side_effects_begin(void) {
if (s_gte_replay_sandbox) return 0;
s_gte_replay_saved_caller_ra = s_gte_caller_ra;
s_gte_replay_sandbox = 1;
pgxp_suppress_begin();
return 1;
}
extern "C" void gte_replay_side_effects_end(void) {
using namespace PSXRecomp::GTE;
if (!s_gte_replay_sandbox) return;
pgxp_suppress_end();
s_gte_caller_ra = s_gte_replay_saved_caller_ra;
s_gte_replay_sandbox = 0;
}
+12
View File
@@ -104,6 +104,7 @@ extern "C" void pgxp_invalidate_all(void) {
}
extern "C" void pgxp_set_enabled(int enabled) {
int resized = 0;
if (enabled) {
/* Cover the REAL guest RAM, not the stock 2 MB. With the 8 MB mod the
* extension is real memory, and a 2 MB-wrapped shadow aliased every
@@ -129,11 +130,15 @@ extern "C" void pgxp_set_enabled(int enabled) {
std::free(s_ram);
s_ram = fresh;
s_ram_words = want;
resized = 1;
} else if (!s_ram) {
enabled = 0; /* fail closed: stay faithful */
}
}
}
/* Re-applying configuration must not invalidate every live shadow. */
if (s_enabled == (enabled ? 1 : 0) && !resized)
return;
s_enabled = enabled ? 1 : 0;
pgxp_invalidate_all();
recompute_active();
@@ -724,10 +729,17 @@ extern "C" void pgxp_gte_push_sxy(int32_t x16, int32_t y16, uint16_t sz3,
}
extern "C" int pgxp_get_gte_sxy(uint32_t index, int32_t *x16, int32_t *y16) {
return pgxp_get_gte_sxy_checked(index, 0u, 0, x16, y16);
}
extern "C" int pgxp_get_gte_sxy_checked(uint32_t index, uint32_t expect,
int check, 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 (check && pv->value != expect)
return 0;
if (x16) *x16 = pv->x16;
if (y16) *y16 = pv->y16;
return 1;
@@ -44,6 +44,12 @@ extern "C" void gte_test_execute_reference(CPUState *cpu, uint32_t cmd);
/* gte.cpp runtime dependencies that are irrelevant to register-transfer tests. */
extern "C" int gpu_ws_present_native_43(void) { return 0; }
static int g_test_precise_nclip_enabled;
extern "C" int gpu_ws_precise_nclip_enabled(void) {
return g_test_precise_nclip_enabled;
}
extern "C" void gpu_pgxp_rederive_enable(void) {}
extern "C" uint32_t memory_get_ram_bytes(void) { return 2u * 1024u * 1024u; }
extern "C" void psx_ws_note_gte_project(int) {}
extern "C" {
uint64_t s_frame_count = 0;
@@ -549,6 +555,49 @@ int test_precise_sxy_invalidation() {
return 0;
}
int test_precise_nclip_is_title_scoped() {
CPUState cpu{};
gte_precision_tracking_set(1);
g_test_precise_nclip_enabled = 1;
/* Native determinant is +1. The validated 16.16 positions have a negative
* exact determinant, so only the title-scoped branch helper may see it. */
const uint32_t packed[3] = {0x00000001u, 0xFFFFFFFEu, 0xFFFFFFFFu};
const int32_t x16[3] = {101245, -109694, -34340};
const int32_t y16[3] = {19509, -59658, -20365};
for (uint32_t i = 0; i < 3; ++i) {
cpu.gte_data[12 + i] = packed[i];
gte_test_seed_precise_projection(i, packed[i], x16[i], y16[i], 100);
}
uint64_t hit0 = 0, fallback0 = 0, disagree0 = 0;
gte_nclip_precise_stats(&hit0, &fallback0, &disagree0);
gte_execute(&cpu, 0x06u);
uint64_t hit1 = 0, fallback1 = 0, disagree1 = 0;
gte_nclip_precise_stats(&hit1, &fallback1, &disagree1);
if (cpu.gte_data[24] != 1u || hit1 != hit0 + 1u ||
fallback1 != fallback0 || disagree1 != disagree0 + 1u)
return fail_value("precise NCLIP preserves guest MAC0", 0, 0x06u,
0, 1u, cpu.gte_data[24]);
if (!gte_nclip_precise_bltz(1) || gte_nclip_precise_bltz(2))
return fail_value("title-scoped precise NCLIP predicate", 0, 0x06u,
0, 1u, 0u);
/* A stale packed-word shadow must fail closed to the native sign and count
* as a fallback, never as a precise hit. */
gte_test_seed_precise_projection(0, packed[0] ^ 1u,
x16[0], y16[0], 100);
gte_execute(&cpu, 0x06u);
uint64_t hit2 = 0, fallback2 = 0, disagree2 = 0;
gte_nclip_precise_stats(&hit2, &fallback2, &disagree2);
g_test_precise_nclip_enabled = 0;
if (cpu.gte_data[24] != 1u || hit2 != hit1 ||
fallback2 != fallback1 + 1u || disagree2 != disagree1 ||
gte_nclip_precise_bltz(1))
return fail_value("stale precise NCLIP falls back natively", 0, 0x06u,
0, 1u, cpu.gte_data[24]);
return 0;
}
int test_precision_speculative_transaction() {
constexpr uint32_t address = 0x00123450u;
constexpr uint32_t packed = 0x00420021u;
@@ -661,6 +710,7 @@ int main() {
if (int rc = test_command_marshaling()) return rc;
if (int rc = test_command_timing_hook()) return rc;
if (int rc = test_precise_sxy_invalidation()) return rc;
if (int rc = test_precise_nclip_is_title_scoped()) return rc;
if (int rc = test_precision_speculative_transaction()) return rc;
std::puts("PASS: canonical GTE register helpers match GTEState transfer oracle");
return 0;