mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
5b7e69b441
The tier mis-compiled and has been hard-gated off since 2026-06-25; overlay
gaps fall to gcc/tcc shards and the dirty-RAM interpreter, unchanged.
Re-do on master of the removal validated on the stale branch (6da8c02),
reconciled with everything master grew since the fork:
- Delete overlay_sljit.{c,h}, overlay_compile_worker.{c,h}, lib/sljit,
runtime/tests/sljit_*.c, and the runtime.cmake sources/include-dirs.
- Strip the sljit provider/backend from code_provider.{c,h},
overlay_backend.{c,h} ("sljit" in overlay_backend/PSX_OVERLAY_BACKEND now
degrades to auto so stale configs still boot), main.cpp, debug_server.c
(sljit_status/sljit_async/sljit_try TCP commands), overlay_loader.{c,h}
(live policy, JIT-on-miss, persisted-shard cache, async worker glue,
psx_sljit_call/cop2/memx host helpers — reachable only via the removed
cpu->sljit_helpers table), and cpu_state.h (SLJIT_HLP_* enum + the
sljit_helpers[] member; CPUState layout change reshards via the cg tag).
- Master-only entanglement resolved before deletion: 28165d6's Einhander WS
player-X bound emit existed in three paths (gcc code_generator, sljit,
dirty_ram_interp). The gcc shard link contract now forwards
psx_ws_player_x_bound (ABI v13, previous commit), so deleting the sljit
emit path loses no widescreen behavior; ffc6688's game-dispatch block
inside the dead psx_sljit_call helper goes with it.
- Reword comments that described sljit as a live backend (gpu.{c,h},
ws_*_detect.h, cosim_state.c, dirty_ram_interp.c, autocompile.h,
boot_state.h, config_loader.h, compile_overlays.py, and the CPS marker
comments the recompiler emits).
recompiler psxrecomp-game builds clean; game runtimes rebuilt + boot-verified
separately.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
121 lines
5.5 KiB
C
121 lines
5.5 KiB
C
#ifndef PSX_WS_CULL_DETECT_H
|
|
#define PSX_WS_CULL_DETECT_H
|
|
/* ============================================================================
|
|
* Generic widescreen SCREEN-EXTENT CULL detector ([widescreen.cull]
|
|
* auto_screen_x)
|
|
*
|
|
* Self-contained (depends only on <stdint.h>) so ONE implementation is shared
|
|
* verbatim by the recompiler (C++) and the runtime interpreter
|
|
* (C) — the widen must be identical on every execution path or the backends
|
|
* diverge (same contract as ws_backdrop_detect.h).
|
|
*
|
|
* WHAT IT FINDS
|
|
* -------------
|
|
* A GTE render funnel trivially rejects a primitive whose projected vertices
|
|
* all fall outside the screen. Titles express the horizontal reject three ways
|
|
* (immediates are per-game: Tomba tests X < 0x140/0x141 on a 320 display, Ape
|
|
* Escape tests X < 0x181 on its 368 display — configured via
|
|
* [widescreen.cull] screen_w_imms / screen_h_imms):
|
|
*
|
|
* (1) UNSIGNED PER-VERTEX (Tomba, Ape sprite path):
|
|
* sltiu v, SX, W ; SX loaded lhu / masked andi 0xFFFF
|
|
* One compare covers both edges (off-left SX wraps to a large unsigned).
|
|
* Widened by psx_ws_cull_sltiu(): window [-m, W+m).
|
|
*
|
|
* (2) SIGNED MIN/MAX (Ape tri/quad funnel):
|
|
* bltz maxSX, reject ; all verts left of 0
|
|
* _slti v, minSX, W ; (delay slot) all verts right of W-1
|
|
* The right bound widens via psx_ws_cull_slti() (W+m); the LEFT bound is
|
|
* the bare bltz, widened via psx_ws_cull_bltz() (reject only when
|
|
* maxSX < -m). The X pair is discriminated from the identically-shaped Y
|
|
* pair by the delay-slot immediate (W-set vs H-set).
|
|
*
|
|
* (3) SIGNED CENTER±HALFWIDTH (Ape billboard funnel):
|
|
* addu t, cx, r
|
|
* bltz t, reject ; cx + r < 0 (fully left)
|
|
* _<any>
|
|
* subu t, cx, r
|
|
* slti v, t, W ; cx - r >= W (fully right)
|
|
* The bltz is recognised by the addu immediately before it whose (rs,rt)
|
|
* pair reappears in a subu feeding a W-immediate slti a few words later.
|
|
*
|
|
* A function/window QUALIFIES only when it contains BOTH a width compare
|
|
* (slti/sltiu, imm in the W set) and a height compare (imm in the H set) — the
|
|
* screen-extent signature. A lone width-immediate compare elsewhere stays
|
|
* vanilla.
|
|
*
|
|
* All widen helpers are identity at margin 0 (4:3 / boot / menu / FMV), so the
|
|
* transformed code is bit-for-bit the vanilla verdict outside native-wide.
|
|
* ========================================================================== */
|
|
#include <stdint.h>
|
|
|
|
static inline int psx_ws_cull_imm_in(uint32_t imm, const uint32_t *set, int n) {
|
|
for (int i = 0; i < n; i++)
|
|
if (set[i] == imm) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* is words[i] a slti (0x0A) or sltiu (0x0B) with an immediate in `set`? */
|
|
static inline int psx_ws_cull_is_slt_imm(uint32_t w, const uint32_t *set, int n) {
|
|
uint32_t op = w >> 26;
|
|
if (op != 0x0Au && op != 0x0Bu) return 0;
|
|
return psx_ws_cull_imm_in(w & 0xFFFFu, set, n);
|
|
}
|
|
|
|
/* Screen-extent signature over an instruction window: at least one W compare
|
|
* AND one H compare (slti or sltiu). Pure — identical verdicts on the
|
|
* recompiler's full-function scan and the runtime's ±window scan. */
|
|
static inline int psx_ws_cull_scan(const uint32_t *words, int n,
|
|
const uint32_t *w_imms, int nw,
|
|
const uint32_t *h_imms, int nh) {
|
|
int has_x = 0, has_y = 0;
|
|
for (int i = 0; i < n; i++) {
|
|
uint32_t w = words[i];
|
|
uint32_t op = w >> 26;
|
|
if (op != 0x0Au && op != 0x0Bu) continue;
|
|
uint32_t im = w & 0xFFFFu;
|
|
if (psx_ws_cull_imm_in(im, w_imms, nw)) has_x = 1;
|
|
else if (psx_ws_cull_imm_in(im, h_imms, nh)) has_y = 1;
|
|
if (has_x && has_y) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Classify words[idx] as an X LEFT-EDGE reject bltz (idiom 2 or 3 above).
|
|
* Caller must already have qualified the surrounding window via
|
|
* psx_ws_cull_scan. Returns 1 iff the bltz belongs to a width reject. */
|
|
static inline int psx_ws_cull_bltz_here(const uint32_t *words, int n, int idx,
|
|
const uint32_t *w_imms, int nw) {
|
|
if (idx < 0 || idx >= n) return 0;
|
|
uint32_t w = words[idx];
|
|
if ((w >> 26) != 0x01u || ((w >> 16) & 0x1Fu) != 0x00u) return 0; /* bltz only */
|
|
uint32_t bltz_rs = (w >> 21) & 0x1Fu;
|
|
|
|
/* Idiom 2: the width slti/sltiu sits in the bltz's delay slot. (The Y pair
|
|
* has the same shape with an H immediate — excluded by the W-set test.) */
|
|
if (idx + 1 < n && psx_ws_cull_is_slt_imm(words[idx + 1], w_imms, nw))
|
|
return 1;
|
|
|
|
/* Idiom 3: addu t,x,y immediately before; a subu with the same (x,y) pair
|
|
* within the next few words feeds a W-immediate slti/sltiu right after. */
|
|
if (idx >= 1) {
|
|
uint32_t p = words[idx - 1];
|
|
if ((p >> 26) == 0x00u && (p & 0x3Fu) == 0x21u && /* addu */
|
|
((p >> 11) & 0x1Fu) == bltz_rs) { /* rd feeds bltz */
|
|
uint32_t ax = (p >> 21) & 0x1Fu, ay = (p >> 16) & 0x1Fu;
|
|
for (int j = idx + 1; j <= idx + 4 && j < n; j++) {
|
|
uint32_t s = words[j];
|
|
if ((s >> 26) == 0x00u && (s & 0x3Fu) == 0x23u && /* subu */
|
|
((s >> 21) & 0x1Fu) == ax && ((s >> 16) & 0x1Fu) == ay) {
|
|
for (int k = j + 1; k <= j + 2 && k < n; k++)
|
|
if (psx_ws_cull_is_slt_imm(words[k], w_imms, nw))
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif /* PSX_WS_CULL_DETECT_H */
|