mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
widescreen: scope curved backdrop projection sites
This commit is contained in:
@@ -696,6 +696,7 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
bool ws_hud_sprt_squash = false;
|
||||
bool ws_full_2d = false;
|
||||
bool ws_gte_game_mode = false;
|
||||
bool ws_native_wide = true;
|
||||
bool ws_nw_hud_corners = false;
|
||||
uint32_t ws_nw_left_hud_packet_lo = 0;
|
||||
uint32_t ws_nw_left_hud_packet_hi = 0;
|
||||
@@ -726,6 +727,8 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
ws_full_2d = toml::find<bool>(ws, "full_2d");
|
||||
if (ws.contains("gte_game_mode"))
|
||||
ws_gte_game_mode = toml::find<bool>(ws, "gte_game_mode");
|
||||
if (ws.contains("native_wide"))
|
||||
ws_native_wide = toml::find<bool>(ws, "native_wide");
|
||||
if (ws.contains("nw_hud_corners"))
|
||||
ws_nw_hud_corners = toml::find<bool>(ws, "nw_hud_corners");
|
||||
const bool has_nw_left_hud_lo = ws.contains("nw_left_hud_packet_lo");
|
||||
@@ -864,6 +867,7 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
// (x_sites) + far-backdrop GTE un-squash (unsquash_funcs).
|
||||
std::vector<uint32_t> ws_backdrop_x_sites;
|
||||
std::vector<uint32_t> ws_backdrop_unsquash_funcs;
|
||||
std::vector<uint32_t> ws_dome_call_sites;
|
||||
if (cfg.contains("widescreen")) {
|
||||
const toml::value& ws = toml::find(cfg, "widescreen");
|
||||
if (ws.contains("backdrop")) {
|
||||
@@ -879,6 +883,19 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
}
|
||||
}
|
||||
|
||||
// Optional [widescreen.dome] block: exact projection calls belonging to
|
||||
// finite curved background meshes that retain authored 4:3 coverage.
|
||||
if (cfg.contains("widescreen")) {
|
||||
const toml::value& ws = toml::find(cfg, "widescreen");
|
||||
if (ws.contains("dome")) {
|
||||
const toml::value& dome = toml::find(ws, "dome");
|
||||
if (dome.contains("call_sites"))
|
||||
for (const auto& a : toml::find<std::vector<std::string>>(dome, "call_sites"))
|
||||
ws_dome_call_sites.push_back(
|
||||
parse_hex(a, "widescreen.dome.call_sites"));
|
||||
}
|
||||
}
|
||||
|
||||
return GameConfig{
|
||||
/*config_path*/ config_path,
|
||||
/*project_root*/ root,
|
||||
@@ -912,10 +929,12 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
/*ws_cull_h_imms*/ ws_cull_h_imms,
|
||||
/*ws_backdrop_x_sites*/ ws_backdrop_x_sites,
|
||||
/*ws_backdrop_unsquash_funcs*/ ws_backdrop_unsquash_funcs,
|
||||
/*ws_dome_call_sites*/ ws_dome_call_sites,
|
||||
/*ws_auto_screen_x_cull*/ ws_auto_screen_x_cull,
|
||||
/*ws_auto_backdrop_preload*/ ws_auto_backdrop_preload,
|
||||
/*ws_full_2d*/ ws_full_2d,
|
||||
/*ws_gte_game_mode*/ ws_gte_game_mode,
|
||||
/*ws_native_wide*/ ws_native_wide,
|
||||
/*ws_nw_hud_corners*/ ws_nw_hud_corners,
|
||||
/*ws_nw_left_hud_packet_lo*/ ws_nw_left_hud_packet_lo,
|
||||
/*ws_nw_left_hud_packet_hi*/ ws_nw_left_hud_packet_hi,
|
||||
|
||||
@@ -456,6 +456,10 @@ struct GameConfig {
|
||||
// frame instead of leaving edge void (8C). Main-EXE addresses; regen-class.
|
||||
std::vector<uint32_t> ws_backdrop_unsquash_funcs;
|
||||
|
||||
// [widescreen.dome] call_sites: exact guest JAL addresses whose GTE
|
||||
// projections belong to a finite curved backdrop mesh authored for 4:3.
|
||||
std::vector<uint32_t> ws_dome_call_sites;
|
||||
|
||||
// [widescreen.cull] auto_screen_x — automatic horizontal-FOV cull widening.
|
||||
// GTE-projected render funnels reject a primitive when ALL its vertices fall
|
||||
// off the 4:3 frame: a per-vertex `sltiu vN, SX, 0x140` (right edge) paired
|
||||
@@ -498,6 +502,11 @@ struct GameConfig {
|
||||
// pillarbox 4:3. Runtime-only — no regen required. Off by default.
|
||||
bool ws_gte_game_mode = false;
|
||||
|
||||
// [widescreen] native_wide — select the newer wide render-target path.
|
||||
// Defaults on for compatibility. Titles can keep the original GTE-squash
|
||||
// + stretched-present path when native-wide is not regression-free.
|
||||
bool ws_native_wide = true;
|
||||
|
||||
// [widescreen] nw_hud_corners — in native-wide, push outer-third screen-
|
||||
// space HUD sprites out to the true wide-frame corners (they otherwise sit
|
||||
// inset by the reveal offset). Runtime-only — no regen. Off by default.
|
||||
|
||||
@@ -184,6 +184,7 @@ extern void gte_execute(CPUState* cpu, uint32_t cmd);
|
||||
* wide aspect shows a wider field of view. */
|
||||
extern void gte_set_display_aspect(int num, int den);
|
||||
extern void gte_ws_set_suppress(int on); /* 8C: un-squash far backdrop draws */
|
||||
extern void gte_ws_configure_dome_sites(const uint32_t* sites, int count);
|
||||
extern uint32_t gte_read_data(CPUState* cpu, uint8_t reg);
|
||||
extern uint32_t gte_read_ctrl(CPUState* cpu, uint8_t reg);
|
||||
extern void gte_write_data(CPUState* cpu, uint8_t reg, uint32_t val);
|
||||
|
||||
+23
-3
@@ -243,6 +243,23 @@ extern "C" void gte_ws_set_dome_expand(int on, int aspect_num, int aspect_den) {
|
||||
// dome-expand bracket (the clean alternative to the scene-dependent depth gate).
|
||||
extern "C" { extern uint32_t g_debug_current_func_addr; }
|
||||
static uint32_t s_gte_caller_ra = 0; /* guest ra at gte_execute = return into the GAME fn that issued the projection (not the libgte leaf) */
|
||||
#define WS_DOME_CALL_SITES_MAX 32
|
||||
static uint32_t s_ws_dome_call_sites[WS_DOME_CALL_SITES_MAX];
|
||||
static int s_ws_dome_call_sites_n = 0;
|
||||
extern "C" void gte_ws_configure_dome_sites(const uint32_t* sites, int count) {
|
||||
if (count < 0) count = 0;
|
||||
if (count > WS_DOME_CALL_SITES_MAX) count = WS_DOME_CALL_SITES_MAX;
|
||||
s_ws_dome_call_sites_n = count;
|
||||
for (int i = 0; i < count; i++)
|
||||
s_ws_dome_call_sites[i] = sites[i] & 0x1FFFFFFFu;
|
||||
}
|
||||
static inline bool ws_dome_call_matches(void) {
|
||||
// JAL writes pc+8 to RA; config records the call instruction itself.
|
||||
const uint32_t call_pc = (s_gte_caller_ra - 8u) & 0x1FFFFFFFu;
|
||||
for (int i = 0; i < s_ws_dome_call_sites_n; i++)
|
||||
if (s_ws_dome_call_sites[i] == call_pc) return true;
|
||||
return false;
|
||||
}
|
||||
#define DOME_PROBE_SLOTS 48
|
||||
static struct { uint32_t func; uint32_t count; int32_t max_sz; } s_dome_probe[DOME_PROBE_SLOTS];
|
||||
static int s_dome_probe_on = 0;
|
||||
@@ -605,6 +622,11 @@ void gte_rtps_internal(GTEState* gte, int16_t* V, bool setMac0) {
|
||||
// full-2D screen), so content and present stay locked.
|
||||
int64_t xterm = (int64_t)gte->IR1 * h_div_sz;
|
||||
bool do_squash = (s_ws_xnum != s_ws_xden) && !gpu_ws_present_native_43();
|
||||
const bool dome_call = ws_dome_call_matches();
|
||||
// Curved backdrops are authored to cover the original 4:3 projection.
|
||||
// In classic widescreen, leave that projection intact and let the normal
|
||||
// final-frame stretch cover the wide output instead of shrinking it first.
|
||||
if (dome_call) do_squash = false;
|
||||
if (do_squash && s_ws_suppress) {
|
||||
/* Depth-gated: un-squash only FAR geometry (the backdrop); keep near
|
||||
* props squashed so they stay aligned. Record SZ stats for tuning. */
|
||||
@@ -616,9 +638,7 @@ void gte_rtps_internal(GTEState* gte, int16_t* V, bool setMac0) {
|
||||
}
|
||||
if (do_squash)
|
||||
xterm = xterm * s_ws_xnum / s_ws_xden;
|
||||
// Native-wide sky-dome expand: no squash active (identity), dome mode on,
|
||||
// this frame is stretched, and the vertex is far (sky). Scale X outward from
|
||||
// the projection centre so the finite dome mesh reaches the wider frame.
|
||||
// Native-wide dome expansion remains a diagnostic-only depth probe.
|
||||
else if (s_ws_dome_on && s_ws_dome_num != s_ws_dome_den &&
|
||||
!gpu_ws_present_native_43()) {
|
||||
int32_t sz = gte->SZ[3];
|
||||
|
||||
@@ -2394,6 +2394,9 @@ int main(int argc, char** argv) {
|
||||
gc.ws_bg2d_packet_cap);
|
||||
/* [widescreen] gte_game_mode — 3D-title gameplay detector (Ape). */
|
||||
gpu_ws_set_gte_game_mode(gc.ws_gte_game_mode ? 1 : 0);
|
||||
/* Keep titles with known native-wide regressions on the original
|
||||
* projection-squash + stretched-present widescreen path. */
|
||||
g_ws_native_wide = gc.ws_native_wide ? 1 : 0;
|
||||
/* [widescreen] nw_hud_corners — push HUD to the true wide corners. */
|
||||
gpu_ws_set_nw_hud_corners(gc.ws_nw_hud_corners ? 1 : 0);
|
||||
/* Targeted left-HUD packet range — avoids shifting 2D scenery. */
|
||||
@@ -2408,6 +2411,8 @@ int main(int argc, char** argv) {
|
||||
gpu_ws_set_explicit_cull_sites(
|
||||
gc.ws_cull_bias_sites.data(), (int)gc.ws_cull_bias_sites.size(),
|
||||
gc.ws_cull_slti_sites.data(), (int)gc.ws_cull_slti_sites.size());
|
||||
gte_ws_configure_dome_sites(
|
||||
gc.ws_dome_call_sites.data(), (int)gc.ws_dome_call_sites.size());
|
||||
/* [widescreen.cull] per-game gates + signature immediates for the
|
||||
* pattern-scanned interp/sljit widen hooks. A title that never
|
||||
* opted in must never have its live code scanned and rewritten. */
|
||||
|
||||
Reference in New Issue
Block a user