mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
Add typed native-wide textured edge expansion
This commit is contained in:
committed by
Matthew Stanley
parent
4c50b9740e
commit
9a8cdb6772
@@ -0,0 +1,10 @@
|
||||
# Typed native-wide textured edge expansion
|
||||
|
||||
Source: [PSXRecomp PR #15](https://github.com/mstan/psxrecomp/pull/15),
|
||||
commit [`cab3946855e74918d3ce006062d3e1b843b155d6`](https://github.com/douglasjv/psxrecomp-tweaks/commit/cab3946855e74918d3ce006062d3e1b843b155d6).
|
||||
|
||||
This branch preserves the source feature for direct temperature testing. It is
|
||||
opt-in. The known review question is software-renderer parity: the GL path
|
||||
distinguishes outside-edge expansion from ordinary backdrop stretch, while the
|
||||
software path currently consumes the gate as a boolean. Signed bounds and
|
||||
title-specific configuration are excluded.
|
||||
@@ -780,6 +780,9 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
bool ws_clear_reveal = false;
|
||||
bool ws_nw_flat_backdrop = false;
|
||||
bool ws_nw_phase_backdrop = false;
|
||||
bool ws_nw_textured_edges = false;
|
||||
int ws_nw_textured_edge_scale = 0;
|
||||
bool ws_nw_full_mirror = false;
|
||||
bool ws_offered = true;
|
||||
bool ws_ultrawide_offered = false;
|
||||
if (cfg.contains("widescreen")) {
|
||||
@@ -836,6 +839,18 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
ws_nw_flat_backdrop = toml::find<bool>(ws, "nw_flat_backdrop");
|
||||
if (ws.contains("nw_phase_backdrop"))
|
||||
ws_nw_phase_backdrop = toml::find<bool>(ws, "nw_phase_backdrop");
|
||||
if (ws.contains("nw_textured_edges"))
|
||||
ws_nw_textured_edges = toml::find<bool>(ws, "nw_textured_edges");
|
||||
if (ws.contains("nw_textured_edge_scale")) {
|
||||
ws_nw_textured_edge_scale = toml::find<int>(ws, "nw_textured_edge_scale");
|
||||
if (ws_nw_textured_edge_scale != 0 &&
|
||||
(ws_nw_textured_edge_scale < 100 || ws_nw_textured_edge_scale > 400))
|
||||
throw std::runtime_error(fmt::format(
|
||||
"{}: [widescreen] nw_textured_edge_scale must be 0 or in [100, 400]",
|
||||
config_path.string()));
|
||||
}
|
||||
if (ws.contains("nw_full_mirror"))
|
||||
ws_nw_full_mirror = toml::find<bool>(ws, "nw_full_mirror");
|
||||
if (ws.contains("offer"))
|
||||
ws_offered = toml::find<bool>(ws, "offer");
|
||||
if (ws.contains("offer_ultrawide"))
|
||||
@@ -1026,6 +1041,9 @@ GameConfig load_game_config(const fs::path& config_path_in) {
|
||||
/*ws_clear_reveal*/ ws_clear_reveal,
|
||||
/*ws_nw_flat_backdrop*/ ws_nw_flat_backdrop,
|
||||
/*ws_nw_phase_backdrop*/ ws_nw_phase_backdrop,
|
||||
/*ws_nw_textured_edges*/ ws_nw_textured_edges,
|
||||
/*ws_nw_textured_edge_scale*/ ws_nw_textured_edge_scale,
|
||||
/*ws_nw_full_mirror*/ ws_nw_full_mirror,
|
||||
/*ws_offered*/ ws_offered,
|
||||
/*ws_ultrawide_offered*/ ws_ultrawide_offered,
|
||||
/*ws_bg2d_count_site*/ ws_bg2d_count_site,
|
||||
|
||||
@@ -559,6 +559,17 @@ struct GameConfig {
|
||||
// off by default because draw ordering is title-specific.
|
||||
bool ws_nw_phase_backdrop = false;
|
||||
|
||||
// Expand only textured polygon vertices that already lie beyond the
|
||||
// canonical 4:3 boundary. Useful for finite arena/background meshes while
|
||||
// leaving actors, HUD, sprites, and centre geometry untouched.
|
||||
bool ws_nw_textured_edges = false;
|
||||
int ws_nw_textured_edge_scale = 0; // percent; 0 = aspect-derived
|
||||
|
||||
// Render the complete wide mirror instead of splicing its centre from
|
||||
// canonical VRAM. Required when edge-crossing polygon interpolation is
|
||||
// transformed in the mirror.
|
||||
bool ws_nw_full_mirror = false;
|
||||
|
||||
// [widescreen] offer — whether the launcher OFFERS its EXPERIMENTAL
|
||||
// Widescreen toggle for this title. Default true. Set false while a
|
||||
// title's widescreen is unported/unvalidated (e.g. MMX4 at bring-up):
|
||||
|
||||
@@ -1185,6 +1185,12 @@ static int ws_tagged_anchor(int32_t *out_ax) {
|
||||
uint32_t g_ws_backdrop_lo = 0, g_ws_backdrop_hi = 0;
|
||||
static int ws_nw_phase_backdrop = 0;
|
||||
void gpu_ws_set_nw_phase_backdrop(int on) { ws_nw_phase_backdrop = on ? 1 : 0; }
|
||||
static int ws_nw_textured_edges = 0;
|
||||
int g_ws_tex_edge_pct = 0;
|
||||
void gpu_ws_set_nw_textured_edges(int on, int scale_pct) {
|
||||
ws_nw_textured_edges = on ? 1 : 0;
|
||||
g_ws_tex_edge_pct = scale_pct;
|
||||
}
|
||||
/* diag: per-frame min/max of the prim source addrs the GL gate sees */
|
||||
uint32_t g_bdg_src_lo = 0xFFFFFFFFu, g_bdg_src_hi = 0;
|
||||
static uint32_t bdg_src_frame = 0xFFFFFFFFu;
|
||||
@@ -1270,6 +1276,11 @@ int psx_ws_prim_in_backdrop(void) {
|
||||
if (gp0_cmd_source_addr > g_bdg_src_hi) g_bdg_src_hi = gp0_cmd_source_addr;
|
||||
}
|
||||
if (g_dbg_mode != 0) return dbg_gate_match(); /* correlation override */
|
||||
if (ws_nw_textured_edges) {
|
||||
uint32_t op = (gp0_cmd_buf[0] >> 24) & 0xFFu;
|
||||
if (op >= 0x20u && op <= 0x3Fu && (op & 0x04u))
|
||||
return 2; /* GL gate: expand only vertices beyond canonical edges */
|
||||
}
|
||||
if (ws_nw_phase_backdrop && !ws_bg_phase_over()) return 1;
|
||||
/* Real gate: stretch the 2D backdrop = sprite-tagged prims drawn in the
|
||||
* background phase (before the 3D world). Fills the native-wide void for both
|
||||
|
||||
@@ -754,7 +754,12 @@ static const char *GEO_VS =
|
||||
"uniform float u_xcenter;/* stretch centre in VRAM px; 0 canonical */\n"
|
||||
"noperspective out vec4 v_col;\n"
|
||||
"void main(){ v_col = a_col;\n"
|
||||
" float xb = (a_pos.x - u_xcenter)*u_xscale + u_xcenter;\n"
|
||||
" float xb = a_pos.x;\n"
|
||||
" if (u_xscale < 0.0) {\n"
|
||||
" float s = -u_xscale; float h = u_xhalf / s;\n"
|
||||
" float l = u_xcenter - h, r = u_xcenter + h;\n"
|
||||
" if (xb < l) xb = l + (xb-l)*s; else if (xb > r) xb = r + (xb-r)*s;\n"
|
||||
" } else xb = (xb - u_xcenter)*u_xscale + u_xcenter;\n"
|
||||
" gl_Position = vec4((xb+u_shift+u_xoff)/u_xhalf - 1.0, (a_pos.y+u_shift)/256.0 - 1.0, 0.0, 1.0); }\n";
|
||||
static const char *GEO_FS =
|
||||
"#version 330\n"
|
||||
@@ -798,7 +803,12 @@ static const char *TEX_VS =
|
||||
" v_limits = ivec4(floor(a_limits + 0.5));\n"
|
||||
" /* u_shift: align GL's center-sample grid with the PS1 integer grid (see\n"
|
||||
" * GEO_VS) so interpolated uv at a fragment equals the PS1 DDA value. */\n"
|
||||
" float xb = (a_pos.x - u_xcenter)*u_xscale + u_xcenter;\n"
|
||||
" float xb = a_pos.x;\n"
|
||||
" if (u_xscale < 0.0) {\n"
|
||||
" float s = -u_xscale; float h = u_xhalf / s;\n"
|
||||
" float l = u_xcenter - h, r = u_xcenter + h;\n"
|
||||
" if (xb < l) xb = l + (xb-l)*s; else if (xb > r) xb = r + (xb-r)*s;\n"
|
||||
" } else xb = (xb - u_xcenter)*u_xscale + u_xcenter;\n"
|
||||
" gl_Position = vec4((xb+u_shift+u_xoff)/u_xhalf - 1.0, (a_pos.y+u_shift)/256.0 - 1.0, 0.0, 1.0); }\n";
|
||||
static const char *TEX_FS =
|
||||
"#version 330\n"
|
||||
@@ -1370,13 +1380,19 @@ static int mirror_geo_center_only(const int *xs, int n) {
|
||||
|
||||
/* Set / clear the 2D-backdrop x-stretch for a wide-mirror draw, per the current
|
||||
* gate (s_bd_gate, set by the caller from bd_prim_gate / the batch gate). */
|
||||
static void wide_set_bd_scale(GLint uScale, GLint uCenter) {
|
||||
static void wide_set_bd_scale(GLint uScale, GLint uCenter) {
|
||||
extern int g_ws_tex_edge_pct;
|
||||
float scale = 1.0f, center = 0.0f;
|
||||
if (s_bd_gate && g_ws_bd_stretch_on && g_wide_w > 0) {
|
||||
int native_w = g_wide_w - 2 * g_wide_off;
|
||||
if (native_w > 0) {
|
||||
scale = g_ws_bd_stretch_pct > 0 ? (float)g_ws_bd_stretch_pct / 100.0f
|
||||
: (float)g_wide_w / (float)native_w;
|
||||
scale = g_ws_bd_stretch_pct > 0 ? (float)g_ws_bd_stretch_pct / 100.0f
|
||||
: (float)g_wide_w / (float)native_w;
|
||||
if (s_bd_gate == 2) {
|
||||
scale = g_ws_tex_edge_pct > 0
|
||||
? (float)g_ws_tex_edge_pct / 100.0f : scale;
|
||||
scale = -scale; /* shader: expand only beyond canonical edges */
|
||||
}
|
||||
center = (float)g_wide_cur_base + (float)native_w / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +346,7 @@ static bool g_ws_hud_sprt = false;
|
||||
/* Runtime-only transition cleanup; kept out of gpu.h because generated game
|
||||
* units include that ABI header and do not need this frontend-only setter. */
|
||||
extern "C" void gpu_ws_set_clear_reveal(int on);
|
||||
extern "C" void gpu_ws_set_nw_textured_edges(int on, int scale_pct);
|
||||
/* Widescreen engages at game entry (fntrace_is_game_started): the BIOS boot
|
||||
* — Sony logo, PS logo, shell — presents authentic 4:3 with no GTE squash.
|
||||
* Starts true when the configured aspect is already 4:3 (nothing to engage). */
|
||||
@@ -2844,6 +2845,9 @@ int main(int argc, char** argv) {
|
||||
/* [widescreen] nw_phase_backdrop — stretch only the textured
|
||||
* backdrop phase emitted before shaded 3D foreground geometry. */
|
||||
gpu_ws_set_nw_phase_backdrop(gc.ws_nw_phase_backdrop ? 1 : 0);
|
||||
gpu_ws_set_nw_textured_edges(gc.ws_nw_textured_edges ? 1 : 0,
|
||||
gc.ws_nw_textured_edge_scale);
|
||||
gl_renderer_set_wide_fast(gc.ws_nw_full_mirror ? 0 : 1);
|
||||
/* [widescreen] clear_reveal — enable opted-in scene/map-boundary
|
||||
* cleanup of synthetic native-wide margins. */
|
||||
gpu_ws_set_clear_reveal(gc.ws_clear_reveal ? 1 : 0);
|
||||
|
||||
Reference in New Issue
Block a user