mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
dd5fdec6bb
Many PS1 renderers drop a primitive whose depth index falls past the end of their ordering table. Raising that limit can write past the table, so a title can now list such guards in game.toml with the register that carries the index and the last safe value. While a trusted mod has called psx_mod_set_draw_distance_clamp(1), generated main-EXE code clamps that register before the guard runs, so far geometry is kept in the farthest slot instead of popping in later. - Off by default and reset at every session start, so netplay and every title that lists no sites run unchanged; with no sites the generated code and declarations are byte-identical. - Main executable only: the full instruction word is the guard, generation fails on a mismatch or a load-delay hazard, captured overlay code keeps its own code (the sites are not part of the overlay config identity), and the dirty-RAM interpreter applies the clamp where the game's text image holds the listed word. - Compatibility: code_generator.cpp is a codegen-hash input, so the codegen hash and the overlay-cache tag change for every title, sites or not. Savestates from earlier builds are refused, and overlay shards rebuild once on first visit. Generated code and behaviour are unchanged for a title without sites or with the switch off. - Tests: draw_distance_codegen_test (config rules, emission, guards, declarations, overlay identity) and draw_distance_interp_test (store, switch, interpreted guards); the session-reset guard covers the switch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
2.8 KiB
C
72 lines
2.8 KiB
C
/* draw_distance.h - opt-in draw-distance clamps ([[draw_distance.clamp]]).
|
|
*
|
|
* Many PS1 renderers drop a primitive whose depth falls past the end of their
|
|
* ordering table: `sltiu t, z, N; beqz t, reject`. The limit protects the OT,
|
|
* so simply raising it can write past the table. A title lists such
|
|
* predicates in game.toml together with the register that carries the depth
|
|
* index and the last safe value:
|
|
*
|
|
* [[draw_distance.clamp]]
|
|
* address = "0x80061230"
|
|
* expected = "0x2C4A01C0" # sltiu t2, v0, 0x1C0
|
|
* reg = 2 # v0
|
|
* max = 0x1BF
|
|
*
|
|
* While a trusted mod has switched the clamps on, the listed register is
|
|
* clamped to `max` (signed) immediately before the listed instruction runs,
|
|
* so a far primitive is kept in the farthest OT slot instead of being
|
|
* dropped. Off (the default, reset at every session start) the sites run the
|
|
* original code. Main executable only: generated main-EXE code applies the
|
|
* clamp, captured overlay code at the same address keeps its own code, and
|
|
* the dirty-RAM interpreter applies it where the game's text image still
|
|
* holds the listed instruction.
|
|
*
|
|
* docs/config_schema.md "Draw-distance clamps" has the config rules.
|
|
*/
|
|
#ifndef PSX_DRAW_DISTANCE_H
|
|
#define PSX_DRAW_DISTANCE_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct PSXDrawDistanceClampSite {
|
|
uint32_t address; /* any segment; stored physical */
|
|
uint32_t expected; /* the complete instruction word at address */
|
|
uint32_t reg; /* 1..31: a source register of `expected` */
|
|
int32_t max; /* signed upper bound */
|
|
} PSXDrawDistanceClampSite;
|
|
|
|
#define PSX_DRAW_DISTANCE_CLAMP_SITES_MAX 256
|
|
|
|
/* Nonzero while the clamps are on. Generated main-EXE code reads it at every
|
|
* configured site. */
|
|
extern uint32_t g_psx_draw_distance_clamp;
|
|
/* On and at least one site configured: the interpreter's per-instruction
|
|
* gate. */
|
|
extern int g_psx_draw_distance_clamp_live;
|
|
|
|
/* The title's sites (game config). Copied, sorted, capped at
|
|
* PSX_DRAW_DISTANCE_CLAMP_SITES_MAX (a longer list is logged). Returns the
|
|
* number kept. */
|
|
int psx_draw_distance_set_clamp_sites(const PSXDrawDistanceClampSite *sites,
|
|
int count);
|
|
int psx_draw_distance_clamp_site_count(void);
|
|
/* The site at `pc` whose instruction is `insn`, or NULL. */
|
|
const PSXDrawDistanceClampSite *psx_draw_distance_clamp_find(uint32_t pc,
|
|
uint32_t insn);
|
|
|
|
/* The value the clamp leaves in the register. */
|
|
static inline uint32_t psx_draw_distance_clamp_value(uint32_t value,
|
|
int32_t max) {
|
|
return (int32_t)value > max ? (uint32_t)max : value;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* PSX_DRAW_DISTANCE_H */
|