mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 19:07:47 -04:00
78bec7b55e
Two generic explicit cull-site kinds for native-wide titles whose screen-X rejects the existing keys cannot express exactly: - bgez_sites: `bgez SX, keep` in a signed per-vertex left-edge chain (`bgez x0,keep; ...; bltz xN,reject`). Emitted through psx_ws_cull_bgez (keep while SX >= -margin). bltz_sites alone still rejects a primitive whose first vertices sit in the revealed band; with both kinds the chain rejects exactly when every vertex is left of -margin. - clip_edge_x_load_sites (+ clip_edge_width, default screen_w_imms[0]): lh/lhu/lw of a clip-rectangle X bound. psx_ws_clip_edge_x moves a loaded 0 to -margin and a loaded width to width+margin and leaves interior bounds (mirrors, split-screen halves) unchanged. xclip_load_sites is lw-only and upper-bound-only, so it cannot express this. Both are identity at 4:3, emit nothing when empty, and fail main-EXE generation on an opcode mismatch (overlay variants stay vanilla). They enter the overlay-cache hash only when non-empty, so every existing title keeps its hash (pinned in the test against the previous layout). Interpreter parity: the dirty-RAM interpreter now also honours explicit bltz_sites, bgez_sites, branch_keep_sites and clip_edge_x_load_sites. Its explicit site lists are stored sorted (binary-search lookup), the cap rises from 64 to 256 per key, and an over-long list is logged instead of being silently truncated. Shared math lives in runtime/include/ws_cull_edge.h. New ctest ws_cull_edge_codegen_test covers parsing, hash identity, emitted code, the opcode guards and the helper math. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
65 lines
2.5 KiB
C
65 lines
2.5 KiB
C
#ifndef PSX_WS_CULL_EDGE_H
|
|
#define PSX_WS_CULL_EDGE_H
|
|
/* ============================================================================
|
|
* Exact screen-X edge widening for two explicit [widescreen.cull] site kinds
|
|
*
|
|
* Self-contained (depends only on <stdint.h>) so one implementation is shared
|
|
* by the runtime helpers in gpu.c (native code and the dirty-RAM interpreter
|
|
* both call those) and by the recompiler's unit test.
|
|
*
|
|
* `m` is the live per-side reveal, psx_ws_x_margin(): zero at 4:3, so both
|
|
* functions are the identity there and faithful builds are unchanged.
|
|
*
|
|
* bgez_sites -- `bgez SX, keep` in a signed per-vertex left-edge chain:
|
|
*
|
|
* bgez x0, keep ; any vertex with SX >= 0 keeps the primitive
|
|
* bgez x1, keep
|
|
* bgez x2, keep
|
|
* bltz x3, reject ; only reached when x0..x2 < 0
|
|
*
|
|
* The final `bltz` is the existing bltz_sites kind (reject iff SX < -m). On
|
|
* its own it is not exact: a quad with x0 in [-m, 0) and x3 < -m is still
|
|
* rejected, although vertex 0 lies in the revealed band. Widening every
|
|
* `bgez` to SX >= -m restores "reject iff every vertex is left of -m".
|
|
*
|
|
* clip_edge_x_load_sites -- a load of a screen-X clip bound (lh/lhu/lw) that
|
|
* a renderer compares its projected vertices against:
|
|
*
|
|
* lh xmax, 0x70(a0) ; e.g. a scratchpad clip rectangle
|
|
* slt at, xmax, SX ; ... reject if every SX > xmax
|
|
*
|
|
* A bound equal to the screen's left edge (0) moves to -m and one equal to
|
|
* its right edge (W) moves to W+m. Any other value is an interior viewport
|
|
* edge (a rear-view mirror, one half of a split screen) and stays unchanged,
|
|
* so interior viewports keep their vanilla culls while full-width viewports
|
|
* widen on each side that touches the display edge.
|
|
* ========================================================================== */
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* bgez predicate (1 = branch taken = keep) for a signed screen X. */
|
|
static inline int psx_ws_cull_bgez_value(int32_t v, int32_t m)
|
|
{
|
|
return v >= -(m > 0 ? m : 0);
|
|
}
|
|
|
|
/* Widened clip bound. `v` is the loaded value as the guest sees it
|
|
* (sign-extended for lh, zero-extended for lhu). The result is a signed
|
|
* 32-bit screen X in two's complement. */
|
|
static inline uint32_t psx_ws_clip_edge_x_value(uint32_t v, uint32_t w,
|
|
int32_t m)
|
|
{
|
|
if (m <= 0) return v;
|
|
if (v == 0u) return (uint32_t)(-m);
|
|
if (v == w) return (uint32_t)((int32_t)w + m);
|
|
return v;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* PSX_WS_CULL_EDGE_H */
|