mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
Dynamic resolution floor "display": the output's own lines
dynamic_resolution_min = "display" (game.toml, settings.toml, PSX_DYNRES_MIN) floors the controller at the selected internal resolution without the supersample factor, so with supersample > 1 it only trades supersampling and never renders below the output. psx_dynres_floor_scale in internal_resolution.h, tested in test_internal_resolution. OpenBIOS emitter stamp regenerated (config_loader changed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -622,6 +622,21 @@ ordered-grid SSAA of everything, 2D included. Native and the legacy
|
||||
its ceiling and steps under it as before. `PSX_SUPERSAMPLE=<factor>` overrides
|
||||
it for one run.
|
||||
|
||||
To make supersampling the elastic part only, set the dynamic resolution floor
|
||||
to the output: `dynamic_resolution_min = "display"` (also `PSX_DYNRES_MIN=display`
|
||||
and settings.toml) means the selected internal resolution *without* the
|
||||
supersample factor, i.e. the monitor's own lines under Match display or the
|
||||
preset's lines otherwise. Dynamic resolution then steps between the
|
||||
supersampled ceiling and the output and never renders below it:
|
||||
|
||||
```toml
|
||||
[video]
|
||||
internal_resolution = "display"
|
||||
supersample = 2.0
|
||||
dynamic_resolution = true
|
||||
dynamic_resolution_min = "display"
|
||||
```
|
||||
|
||||
`antialiasing_mode` filters the composed game image on OpenGL: after the game
|
||||
quad (4:3, native-wide, Smooth motion and generated frames alike) and before
|
||||
hold-last capture, the OSD, screenshots and the swap. It reads only output
|
||||
|
||||
@@ -1 +1 @@
|
||||
be426241e46d80c1d2ca130c73f12b453e31df1c3f20d252196f3c2cecc9f4b6
|
||||
0a499298b6a38126d2945801a6e24786e7bb1b83a89248de70d8b28bfdc287c8
|
||||
|
||||
@@ -715,8 +715,7 @@ static RuntimeConfig parse_runtime_block(const toml::value& cfg, const fs::path&
|
||||
int value = 0;
|
||||
bool ok = false;
|
||||
if (ir.is_string()) {
|
||||
ok = psx_ir_parse(ir.as_string().str.c_str(), &value) != 0 &&
|
||||
value != PSX_IR_DISPLAY;
|
||||
ok = psx_ir_parse(ir.as_string().str.c_str(), &value) != 0;
|
||||
} else if (ir.is_integer()) {
|
||||
const auto n = ir.as_integer();
|
||||
ok = n >= PSX_IR_MIN_LINES && n <= PSX_IR_MAX_LINES;
|
||||
@@ -725,7 +724,7 @@ static RuntimeConfig parse_runtime_block(const toml::value& cfg, const fs::path&
|
||||
if (!ok) {
|
||||
throw std::runtime_error(
|
||||
"[video] dynamic_resolution_min must be native, 720p, 1080p, "
|
||||
"1440p, 4k, 5k, 8k, or a number of lines");
|
||||
"1440p, 4k, 5k, 8k, display, or a number of lines");
|
||||
}
|
||||
rt.video_dynamic_resolution_min = value;
|
||||
}
|
||||
@@ -2801,8 +2800,7 @@ UserSettings load_user_settings(const fs::path& path) {
|
||||
const toml::value& ir = toml::find(v, "dynamic_resolution_min");
|
||||
int value = 0;
|
||||
if (ir.is_string()) {
|
||||
if (psx_ir_parse(ir.as_string().str.c_str(), &value) &&
|
||||
value != PSX_IR_DISPLAY) {
|
||||
if (psx_ir_parse(ir.as_string().str.c_str(), &value)) {
|
||||
s.dynamic_resolution_min = value; s.has_dynamic_resolution_min = true;
|
||||
}
|
||||
} else if (ir.is_integer()) {
|
||||
@@ -3211,8 +3209,7 @@ bool save_user_settings(const fs::path& path, const UserSettings& s) {
|
||||
if (s.has_dynamic_resolution)
|
||||
f << "dynamic_resolution = " << (s.dynamic_resolution ? "true" : "false") << "\n";
|
||||
if (s.has_dynamic_resolution_min &&
|
||||
psx_ir_value_valid(s.dynamic_resolution_min) &&
|
||||
s.dynamic_resolution_min != PSX_IR_DISPLAY) {
|
||||
psx_ir_value_valid(s.dynamic_resolution_min)) {
|
||||
const char* id = psx_ir_id_for(s.dynamic_resolution_min);
|
||||
if (id)
|
||||
f << "dynamic_resolution_min = \"" << id << "\"\n";
|
||||
|
||||
@@ -241,3 +241,17 @@ static inline PsxIrAdopted psx_ir_adopt_launcher(int has_row, int preset,
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* ---- Dynamic resolution floor ([video] dynamic_resolution_min) -------------
|
||||
* A preset or line count resolves as usual. "display" (PSX_IR_DISPLAY) is the
|
||||
* output's own lines: the selected internal resolution WITHOUT the supersample
|
||||
* factor (Match display = the monitor's pixel height). With supersample > 1
|
||||
* the controller then trades only supersampling and never drops below the
|
||||
* output. Clamped to [1, ceiling]. */
|
||||
static inline int psx_dynres_floor_scale(int min_value, int selected_ir, int ref_lines,
|
||||
int display_px_h, int ceiling) {
|
||||
const int v = (min_value == PSX_IR_DISPLAY && selected_ir != PSX_IR_UNSET)
|
||||
? selected_ir : min_value;
|
||||
int s = psx_resolve_internal_scale(v, ref_lines, display_px_h, ceiling);
|
||||
return s > ceiling ? ceiling : s;
|
||||
}
|
||||
|
||||
+11
-5
@@ -9334,9 +9334,15 @@ static void dynres_setup(void) {
|
||||
"dual raster)\n");
|
||||
return;
|
||||
}
|
||||
int floor_s = psx_resolve_internal_scale(dynres_min_value(), g_video_ref_lines,
|
||||
psx_sdl_display_pixel_height(nullptr),
|
||||
ceiling);
|
||||
/* Floor "display": the output's own lines, i.e. the selected internal
|
||||
* resolution without the supersample factor (Match display = the
|
||||
* monitor's pixel height). Dynamic resolution then only gives back
|
||||
* supersampling and never renders below the output. */
|
||||
int floor_s = psx_dynres_floor_scale(dynres_min_value(),
|
||||
effective_internal_resolution(),
|
||||
g_video_ref_lines,
|
||||
psx_sdl_display_pixel_height(nullptr),
|
||||
ceiling);
|
||||
if (floor_s > ceiling) floor_s = ceiling;
|
||||
DynresParams params;
|
||||
dynres_default_params(¶ms);
|
||||
@@ -18089,9 +18095,9 @@ session_reboot:
|
||||
g_video_dynres_env = (*e && *e != '0') ? 1 : 0;
|
||||
if (const char* e = std::getenv("PSX_DYNRES_MIN")) {
|
||||
int v = 0;
|
||||
if (psx_ir_parse(e, &v) && v != PSX_IR_DISPLAY) g_video_dynres_min_env = v;
|
||||
if (psx_ir_parse(e, &v)) g_video_dynres_min_env = v;
|
||||
else std::fprintf(stdout, "psxrecomp: PSX_DYNRES_MIN=%s not understood "
|
||||
"(native, 720p, 1080p, 1440p, 4k, 5k, 8k, or lines)\n", e);
|
||||
"(native, 720p, 1080p, 1440p, 4k, 5k, 8k, display, or lines)\n", e);
|
||||
}
|
||||
{
|
||||
/* Per-backend ceiling. OpenGL allocates its hr surface at context init
|
||||
|
||||
@@ -206,6 +206,13 @@ int main() {
|
||||
expect("ss parse 4", psx_ss_parse_milli("4"), 4000);
|
||||
expect("ss reject 0.5", psx_ss_parse_milli("0.5"), 0);
|
||||
expect("ss reject 5", psx_ss_parse_milli("5"), 0);
|
||||
// Dynamic resolution floor "display": the output's lines, no supersample.
|
||||
expect("floor display 1080 MD", psx_dynres_floor_scale(PSX_IR_DISPLAY, PSX_IR_DISPLAY, 240, 1080, 9), 5);
|
||||
expect("floor display 1440 MD", psx_dynres_floor_scale(PSX_IR_DISPLAY, PSX_IR_DISPLAY, 240, 1440, 12), 6);
|
||||
expect("floor display preset", psx_dynres_floor_scale(PSX_IR_DISPLAY, 1080, 240, 2160, 9), 5);
|
||||
expect("floor display unset", psx_dynres_floor_scale(PSX_IR_DISPLAY, PSX_IR_UNSET, 240, 1080, 9), 5);
|
||||
expect("floor display clamp", psx_dynres_floor_scale(PSX_IR_DISPLAY, PSX_IR_DISPLAY, 240, 2160, 4), 4);
|
||||
expect("floor 720p", psx_dynres_floor_scale(720, PSX_IR_DISPLAY, 240, 1080, 9), 3);
|
||||
expect("ss reject junk", psx_ss_parse_milli("2y"), 0);
|
||||
expect("ss 1.0 is the plain resolve",
|
||||
psx_resolve_internal_scale_ss(PSX_IR_DISPLAY, 240, 1080, 32, 1000), 5);
|
||||
|
||||
Reference in New Issue
Block a user