mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
Settings: an older launcher's Supersampling pick wins over a preset
A host built against a recomp-ui without the Internal resolution row (RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION undefined) still seeded internal_resolution on first boot and applied it after the launcher. From a fresh start the seed was "native", so a Supersampling pick of 3x was reset to 1x and "native" was saved; on the netplay soft-return the sticky preset was re-applied at session_reboot. The legacy row stopped working. Both launcher exits now go through two pure helpers in internal_resolution.h: - psx_ir_launcher_seed_supersampling: with the row, the factor as before; without it, the factor itself when no preset is configured (the historical round trip), else the preset's scale capped at the row's 4x. - psx_ir_adopt_launcher: with the row, the row's preset as before; without it, a pick in the Supersampling row drops the preset, and an untouched row keeps a preset the player cannot see (game.toml or a hand-edited settings.toml). It also returns what settings.toml saves: no internal_resolution key unless a preset is kept. internal_resolution_test drives seed -> launcher -> adopt for both launcher kinds, first boot and soft-return, against a model of the legacy row (clamp to 1..4, cycle); keeping the old sticky preset fails it. gl_internal_scale_guards pins both exits to the helpers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -478,6 +478,14 @@ same file still gets the nearest factor it supports. A legacy factor with no
|
||||
matching preset appears in the launcher as its own entry, for example
|
||||
"2x (480 lines)". `settings.toml` `window_width` accepts 640 to 7680.
|
||||
|
||||
A host built against a recomp-ui without the Internal resolution row keeps
|
||||
the legacy Supersampling row (1x to 4x) and that row stays in charge: with no
|
||||
preset configured the launcher round trip is exactly the historical one, and
|
||||
no `internal_resolution` key is written. A preset from `game.toml` or a
|
||||
hand-edited `settings.toml` starts the row on the nearest factor it can show
|
||||
and survives if the row is left alone; picking a different factor there
|
||||
drops the preset.
|
||||
|
||||
`PSX_INTERNAL_RESOLUTION=<preset or lines>` overrides every layer for one
|
||||
run (validation, and two local netplay peers that share one `settings.toml`).
|
||||
It is never written to `settings.toml`: the launcher shows and saves the
|
||||
|
||||
@@ -126,3 +126,70 @@ static inline int psx_ir_from_supersampling(int n, int ref_lines) {
|
||||
long lines = (long)ref_lines * n;
|
||||
return lines > PSX_IR_MAX_LINES ? PSX_IR_MAX_LINES : (int)lines;
|
||||
}
|
||||
|
||||
/* ---- The launcher round trip -------------------------------------------------
|
||||
* The host seeds the launcher with its video state, the player may change it,
|
||||
* and the host adopts what comes back. A recomp-ui built with the Internal
|
||||
* resolution row (RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION) owns the preset.
|
||||
* An older one only has the legacy Supersampling row, a 1x..4x cycle that
|
||||
* clamps whatever it is seeded with. There a pick in that row must win over
|
||||
* any preset, and a preset the player cannot see (game.toml, a hand-edited
|
||||
* settings.toml) must survive an untouched row. With no preset the round trip
|
||||
* is exactly the historical one: seed the factor, take the factor back. */
|
||||
#define PSX_IR_LEGACY_SS_MAX 4 /* the legacy row's range, and settings.toml's
|
||||
* supersampling for an older runtime */
|
||||
|
||||
/* The value seeded into the legacy Supersampling row. has_row: the launcher
|
||||
* shows the Internal resolution row instead (the factor passes through). */
|
||||
static inline int psx_ir_launcher_seed_supersampling(int has_row, int preset,
|
||||
int supersampling,
|
||||
int ref_lines,
|
||||
int display_px_h) {
|
||||
if (has_row || preset == PSX_IR_UNSET) return supersampling;
|
||||
/* The preset's scale, as near as the row can show it. */
|
||||
return psx_resolve_internal_scale(preset, ref_lines, display_px_h,
|
||||
PSX_IR_LEGACY_SS_MAX);
|
||||
}
|
||||
|
||||
typedef struct PsxIrAdopted {
|
||||
int preset; /* the preset kept (PSX_IR_UNSET: the factor stands) */
|
||||
int scale; /* the scale to request */
|
||||
int save_ss; /* settings.toml supersampling */
|
||||
int save_ir; /* settings.toml internal_resolution; PSX_IR_UNSET omits it */
|
||||
} PsxIrAdopted;
|
||||
|
||||
/* What the host adopts when the launcher returns.
|
||||
* has_row the launcher showed the Internal resolution row
|
||||
* preset the host's preset when it seeded the launcher
|
||||
* ss_seed what psx_ir_launcher_seed_supersampling returned
|
||||
* ss_result the Supersampling row's value on return
|
||||
* ir_result the Internal resolution row's value (has_row only)
|
||||
* s_max the chosen renderer's ceiling */
|
||||
static inline PsxIrAdopted psx_ir_adopt_launcher(int has_row, int preset,
|
||||
int ss_seed, int ss_result,
|
||||
int ir_result, int ref_lines,
|
||||
int display_px_h, int s_max) {
|
||||
PsxIrAdopted a;
|
||||
if (has_row) {
|
||||
if (psx_ir_value_valid(ir_result)) a.preset = ir_result;
|
||||
else if (preset != PSX_IR_UNSET) a.preset = preset;
|
||||
else a.preset = psx_ir_from_supersampling(ss_seed < 1 ? 1 : ss_seed, ref_lines);
|
||||
} else {
|
||||
int shown = ss_seed < 1 ? 1 : ss_seed > PSX_IR_LEGACY_SS_MAX
|
||||
? PSX_IR_LEGACY_SS_MAX : ss_seed;
|
||||
a.preset = (preset != PSX_IR_UNSET && ss_result == shown) ? preset
|
||||
: PSX_IR_UNSET;
|
||||
}
|
||||
if (a.preset == PSX_IR_UNSET) {
|
||||
a.scale = ss_result;
|
||||
a.save_ss = ss_result;
|
||||
a.save_ir = PSX_IR_UNSET;
|
||||
} else {
|
||||
a.scale = psx_resolve_internal_scale(a.preset, ref_lines, display_px_h, s_max);
|
||||
/* An older runtime reading settings.toml only knows supersampling
|
||||
* (1..4): leave it the nearest it can do. */
|
||||
a.save_ss = a.scale < PSX_IR_LEGACY_SS_MAX ? a.scale : PSX_IR_LEGACY_SS_MAX;
|
||||
a.save_ir = a.preset;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
+53
-34
@@ -96,6 +96,13 @@ extern "C" void psx_event_step_conservative_env_init(void);
|
||||
|
||||
#if defined(RECOMP_LAUNCHER)
|
||||
#include "recomp_launcher.h" /* shared recomp-ui Dear ImGui launcher */
|
||||
/* A recomp-ui that shows the Internal resolution row; an older one only has
|
||||
* the legacy Supersampling row (internal_resolution.h, launcher round trip). */
|
||||
#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)
|
||||
static constexpr int kLauncherHasInternalResolution = 1;
|
||||
#else
|
||||
static constexpr int kLauncherHasInternalResolution = 0;
|
||||
#endif
|
||||
#include "launcher_profile.h" /* per-system variant profile (theme/caps bundle) */
|
||||
#include "launcher_boot_timing.h" /* PSX_LAUNCHER_BOOT_TIMING stamps */
|
||||
#if defined(PSX_HAS_CODEGEN_SETUP_HOST)
|
||||
@@ -1228,6 +1235,9 @@ static int g_video_requested_scale = 1;
|
||||
static bool g_video_scale_applies = true;
|
||||
static bool g_video_hidpi_window = false;
|
||||
|
||||
static_assert(PSX_IR_LEGACY_SS_MAX == SW_MAX_INTERNAL_SCALE,
|
||||
"settings.toml supersampling for an older runtime is the software ceiling");
|
||||
|
||||
static int video_scale_ceiling(void) {
|
||||
return g_video_renderer == 1 ? GL_MAX_INTERNAL_SCALE : SW_MAX_INTERNAL_SCALE;
|
||||
}
|
||||
@@ -1251,7 +1261,7 @@ static void apply_internal_resolution(int display_px_h) {
|
||||
|
||||
/* The value the launcher row starts on: the preset, or the legacy factor shown
|
||||
* as the preset it matches (3 -> 720p) or as its own "Nx" entry. */
|
||||
static int internal_resolution_for_launcher(void) {
|
||||
[[maybe_unused]] static int internal_resolution_for_launcher(void) {
|
||||
if (g_video_internal_res != PSX_IR_UNSET) return g_video_internal_res;
|
||||
return psx_ir_from_supersampling(g_video_scale < 1 ? 1 : g_video_scale, g_video_ref_lines);
|
||||
}
|
||||
@@ -13904,9 +13914,19 @@ int main(int argc, char** argv) {
|
||||
std::filesystem::path match_session_bios_path;
|
||||
bool match_session_bios_set = false;
|
||||
seed.renderer = g_video_renderer; seed.has_renderer = true;
|
||||
seed.supersampling = g_video_scale; seed.has_supersampling = true;
|
||||
/* Internal resolution round trip (internal_resolution.h): only a
|
||||
* launcher with the row seeds and returns the preset. An older one
|
||||
* gets the legacy Supersampling row, and a pick there wins. */
|
||||
const int ir_preset_seeded = g_video_internal_res;
|
||||
const int ir_ss_seeded = psx_ir_launcher_seed_supersampling(
|
||||
kLauncherHasInternalResolution, g_video_internal_res, g_video_scale,
|
||||
g_video_ref_lines, psx_sdl_display_pixel_height(nullptr));
|
||||
seed.supersampling = ir_ss_seeded; seed.has_supersampling = true;
|
||||
int ir_row_result = PSX_IR_UNSET; /* the row's pick, when it has one */
|
||||
#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)
|
||||
seed.internal_resolution = internal_resolution_for_launcher();
|
||||
seed.has_internal_resolution = true;
|
||||
#endif
|
||||
seed.antialiasing = g_video_aa; seed.has_antialiasing = true;
|
||||
seed.texture_filter = g_video_texfilter; seed.has_texture_filter = true;
|
||||
seed.fmv_filter = g_video_fmv_filter; seed.has_fmv_filter = true;
|
||||
@@ -14407,10 +14427,7 @@ int main(int argc, char** argv) {
|
||||
seed.renderer = ls.renderer; seed.has_renderer = true;
|
||||
seed.supersampling = ls.supersampling; seed.has_supersampling = true;
|
||||
#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)
|
||||
if (psx_ir_value_valid(ls.internal_resolution)) {
|
||||
seed.internal_resolution = ls.internal_resolution;
|
||||
seed.has_internal_resolution = true;
|
||||
}
|
||||
ir_row_result = ls.internal_resolution;
|
||||
#endif
|
||||
seed.antialiasing = ls.antialiasing != 0; seed.has_antialiasing = true;
|
||||
seed.geometry_correction = ls.geometry_correction != 0;
|
||||
@@ -14645,15 +14662,16 @@ int main(int argc, char** argv) {
|
||||
g_netplay_from_lobby = 0;
|
||||
}
|
||||
g_video_renderer = seed.renderer;
|
||||
g_video_scale = seed.supersampling;
|
||||
if (seed.has_internal_resolution &&
|
||||
psx_ir_value_valid(seed.internal_resolution)) {
|
||||
g_video_internal_res = seed.internal_resolution;
|
||||
apply_internal_resolution(psx_sdl_display_pixel_height(nullptr));
|
||||
/* An older runtime reading this settings.toml only knows
|
||||
* supersampling (1..4): leave it the nearest it can do. */
|
||||
seed.supersampling = g_video_scale < SW_MAX_INTERNAL_SCALE
|
||||
? g_video_scale : SW_MAX_INTERNAL_SCALE;
|
||||
{
|
||||
const PsxIrAdopted ir = psx_ir_adopt_launcher(
|
||||
kLauncherHasInternalResolution, ir_preset_seeded, ir_ss_seeded,
|
||||
seed.supersampling, ir_row_result, g_video_ref_lines,
|
||||
psx_sdl_display_pixel_height(nullptr), video_scale_ceiling());
|
||||
g_video_internal_res = ir.preset;
|
||||
g_video_scale = ir.scale;
|
||||
seed.supersampling = ir.save_ss;
|
||||
seed.has_internal_resolution = ir.save_ir != PSX_IR_UNSET;
|
||||
seed.internal_resolution = ir.save_ir;
|
||||
}
|
||||
g_video_aa = seed.antialiasing;
|
||||
g_video_texfilter = seed.texture_filter;
|
||||
@@ -16250,7 +16268,12 @@ soft_return_lobby:
|
||||
ls.renderer = g_video_renderer;
|
||||
if (ls.renderer < 0 || ls.renderer > (vulkan_offered ? 2 : 1))
|
||||
ls.renderer = PSXRecompV4::DEFAULT_VIDEO_RENDERER;
|
||||
ls.supersampling = g_video_scale;
|
||||
/* Internal resolution round trip, as at first boot. */
|
||||
const int ir_preset_seeded = g_video_internal_res;
|
||||
const int ir_ss_seeded = psx_ir_launcher_seed_supersampling(
|
||||
kLauncherHasInternalResolution, g_video_internal_res, g_video_scale,
|
||||
g_video_ref_lines, psx_sdl_display_pixel_height(nullptr));
|
||||
ls.supersampling = ir_ss_seeded;
|
||||
#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)
|
||||
ls.internal_resolution = internal_resolution_for_launcher();
|
||||
#endif
|
||||
@@ -16534,6 +16557,15 @@ soft_return_lobby:
|
||||
player_deadzone[i] = ls.deadzone[i] * 32767 / 100;
|
||||
}
|
||||
}
|
||||
int ir_row_result = PSX_IR_UNSET;
|
||||
#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)
|
||||
ir_row_result = ls.internal_resolution;
|
||||
#endif
|
||||
const PsxIrAdopted ir = psx_ir_adopt_launcher(
|
||||
kLauncherHasInternalResolution, ir_preset_seeded, ir_ss_seeded,
|
||||
ls.supersampling, ir_row_result, g_video_ref_lines,
|
||||
psx_sdl_display_pixel_height(nullptr),
|
||||
ls.renderer == 1 ? GL_MAX_INTERNAL_SCALE : SW_MAX_INTERNAL_SCALE);
|
||||
/* Persist controller (and rematch video) choices without wiping
|
||||
* the rest of settings.toml — merge into the on-disk file. */
|
||||
{
|
||||
@@ -16597,19 +16629,10 @@ soft_return_lobby:
|
||||
}
|
||||
us.renderer = ls.renderer;
|
||||
us.has_renderer = true;
|
||||
us.supersampling = ls.supersampling;
|
||||
us.supersampling = ir.save_ss;
|
||||
us.has_supersampling = true;
|
||||
#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)
|
||||
if (psx_ir_value_valid(ls.internal_resolution)) {
|
||||
us.internal_resolution = ls.internal_resolution;
|
||||
us.has_internal_resolution = true;
|
||||
int s = psx_resolve_internal_scale(ls.internal_resolution, g_video_ref_lines,
|
||||
psx_sdl_display_pixel_height(nullptr),
|
||||
ls.renderer == 1 ? GL_MAX_INTERNAL_SCALE
|
||||
: SW_MAX_INTERNAL_SCALE);
|
||||
us.supersampling = s < SW_MAX_INTERNAL_SCALE ? s : SW_MAX_INTERNAL_SCALE;
|
||||
}
|
||||
#endif
|
||||
us.internal_resolution = ir.save_ir;
|
||||
us.has_internal_resolution = ir.save_ir != PSX_IR_UNSET;
|
||||
us.antialiasing = ls.antialiasing != 0;
|
||||
us.has_antialiasing = true;
|
||||
us.texture_filter = ls.texture_filter;
|
||||
@@ -16685,12 +16708,8 @@ soft_return_lobby:
|
||||
(void)PSXRecompV4::save_user_settings(settings_path, us);
|
||||
}
|
||||
g_video_renderer = ls.renderer;
|
||||
g_video_scale = ls.supersampling;
|
||||
#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)
|
||||
if (psx_ir_value_valid(ls.internal_resolution))
|
||||
g_video_internal_res = ls.internal_resolution;
|
||||
apply_internal_resolution(psx_sdl_display_pixel_height(nullptr));
|
||||
#endif
|
||||
g_video_internal_res = ir.preset;
|
||||
g_video_scale = ir.scale;
|
||||
g_video_aa = ls.antialiasing;
|
||||
g_video_texfilter = ls.texture_filter;
|
||||
g_video_fmv_filter = launcher_fmv_filter_to_cfg(ls.fmv_filter);
|
||||
|
||||
@@ -81,7 +81,8 @@ class InternalResolutionGuards(unittest.TestCase):
|
||||
def test_vocabulary_is_optional_abi(self):
|
||||
# Builds against an older recomp-ui must still compile: every use of
|
||||
# the new launcher fields sits behind the capability macro.
|
||||
for field in ("gi->internal_resolution_labels", "ls.internal_resolution"):
|
||||
for field in ("gi->internal_resolution_labels", "ls.internal_resolution",
|
||||
"= internal_resolution_for_launcher();"):
|
||||
for m in re.finditer(re.escape(field), MAIN):
|
||||
before = MAIN[:m.start()]
|
||||
opened = before.count("#if defined(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION)")
|
||||
@@ -94,6 +95,18 @@ class InternalResolutionGuards(unittest.TestCase):
|
||||
self.assertIn("if (preset == PSX_IR_UNSET) return;",
|
||||
body(MAIN, "static void apply_internal_resolution(int display_px_h)"))
|
||||
|
||||
def test_launcher_trips_use_the_round_trip_helpers(self):
|
||||
# Both launcher exits (first boot, netplay soft-return) seed and adopt
|
||||
# through internal_resolution.h, whose behaviour with and without the
|
||||
# Internal resolution row is unit-tested (internal_resolution_test).
|
||||
# A bare factor copy next to a sticky preset let the preset override
|
||||
# a pick in an older launcher's Supersampling row.
|
||||
self.assertEqual(MAIN.count("psx_ir_launcher_seed_supersampling("), 2)
|
||||
self.assertEqual(MAIN.count("psx_ir_adopt_launcher("), 2)
|
||||
self.assertEqual(MAIN.count("kLauncherHasInternalResolution, ir_preset_seeded, ir_ss_seeded,"), 2)
|
||||
self.assertNotRegex(MAIN, r"g_video_scale\s*=\s*(seed|ls)\.supersampling;")
|
||||
self.assertIn("g_video_internal_res = ir.preset;", MAIN)
|
||||
|
||||
def test_env_override_is_never_persisted(self):
|
||||
# PSX_INTERNAL_RESOLUTION wins for the run only: the launcher shows and
|
||||
# settings.toml saves the configured preset.
|
||||
|
||||
@@ -17,6 +17,129 @@ static void expect(const char* what, long long got, long long want) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Launcher round trip: seed -> launcher -> adopt -------------------------
|
||||
// A model of recomp-ui's legacy Supersampling row (before the Internal
|
||||
// resolution row): launcher_model clamps the seeded value to 1..4 on load and
|
||||
// each click cycles 1 -> 2 -> 3 -> 4 -> 1.
|
||||
static int legacy_row(int seeded, int clicks) {
|
||||
int v = seeded < 1 ? 1 : seeded > 4 ? 4 : seeded;
|
||||
for (int i = 0; i < clicks; i++) v = (v % 4) + 1;
|
||||
return v;
|
||||
}
|
||||
|
||||
struct Host { // the host's video state between launcher trips
|
||||
int preset; // g_video_internal_res
|
||||
int scale; // g_video_scale
|
||||
};
|
||||
|
||||
// One trip, the way main.cpp runs it at first boot and on the netplay
|
||||
// soft-return. has_row = RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION.
|
||||
// Legacy: ss_clicks cycles the Supersampling row. Row: row_pick > 0 picks a
|
||||
// preset in the Internal resolution row (0 leaves it).
|
||||
static PsxIrAdopted trip(Host& h, int has_row, int ss_clicks, int row_pick,
|
||||
int s_max = 32, int display_px_h = 2160) {
|
||||
const int seeded_preset = h.preset;
|
||||
const int ss_seed = psx_ir_launcher_seed_supersampling(has_row, h.preset, h.scale,
|
||||
240, display_px_h);
|
||||
const int ss_result = has_row ? ss_seed : legacy_row(ss_seed, ss_clicks);
|
||||
int ir_result = PSX_IR_UNSET;
|
||||
if (has_row) {
|
||||
const int shown = h.preset != PSX_IR_UNSET
|
||||
? h.preset : psx_ir_from_supersampling(h.scale, 240);
|
||||
ir_result = row_pick ? row_pick : shown;
|
||||
}
|
||||
PsxIrAdopted a = psx_ir_adopt_launcher(has_row, seeded_preset, ss_seed, ss_result,
|
||||
ir_result, 240, display_px_h, s_max);
|
||||
h.preset = a.preset;
|
||||
h.scale = a.scale;
|
||||
return a;
|
||||
}
|
||||
|
||||
static void launcher_round_trips() {
|
||||
// Older recomp-ui (no Internal resolution row), nothing configured: the
|
||||
// historical round trip. The player's Supersampling pick is what runs and
|
||||
// what is saved, and no internal_resolution key appears.
|
||||
{
|
||||
Host h{PSX_IR_UNSET, 1};
|
||||
PsxIrAdopted a = trip(h, 0, 2, 0); // 1x -> 3x
|
||||
expect("legacy pick scale", a.scale, 3);
|
||||
expect("legacy pick preset", a.preset, PSX_IR_UNSET);
|
||||
expect("legacy pick save ss", a.save_ss, 3);
|
||||
expect("legacy pick no ir key", a.save_ir, PSX_IR_UNSET);
|
||||
// Netplay soft-return: seeded with the running scale, picked again.
|
||||
a = trip(h, 0, 1, 0); // 3x -> 4x
|
||||
expect("legacy soft-return pick", a.scale, 4);
|
||||
expect("legacy soft-return no ir key", a.save_ir, PSX_IR_UNSET);
|
||||
a = trip(h, 0, 0, 0); // untouched
|
||||
expect("legacy untouched", a.scale, 4);
|
||||
}
|
||||
{
|
||||
Host h{PSX_IR_UNSET, 8}; // hand-edited 8
|
||||
PsxIrAdopted a = trip(h, 0, 0, 0);
|
||||
expect("legacy clamps like before", a.scale, 4); // the row returns 4
|
||||
expect("legacy clamps save", a.save_ss, 4);
|
||||
}
|
||||
// A settings.toml "native" written by a build with the row, then an older
|
||||
// launcher: the preset must not reset the player's pick (the reported bug).
|
||||
{
|
||||
Host h{PSX_IR_NATIVE, 1};
|
||||
PsxIrAdopted a = trip(h, 0, 2, 0); // 1x -> 3x
|
||||
expect("native preset yields to pick", a.scale, 3);
|
||||
expect("native preset dropped", a.preset, PSX_IR_UNSET);
|
||||
expect("native preset key dropped", a.save_ir, PSX_IR_UNSET);
|
||||
expect("native preset save ss", a.save_ss, 3);
|
||||
}
|
||||
// A preset the older launcher cannot show (game.toml or hand-edited 4K):
|
||||
// the row starts on the nearest it can show (4x) and an untouched row
|
||||
// keeps the preset, first boot and soft-return alike.
|
||||
{
|
||||
Host h{2160, 1};
|
||||
PsxIrAdopted a = trip(h, 0, 0, 0);
|
||||
expect("hidden preset kept", a.preset, 2160);
|
||||
expect("hidden preset scale", a.scale, 9);
|
||||
expect("hidden preset save ss", a.save_ss, 4);
|
||||
expect("hidden preset save ir", a.save_ir, 2160);
|
||||
a = trip(h, 0, 0, 0); // soft-return, running 9x
|
||||
expect("hidden preset soft-return kept", a.scale, 9);
|
||||
a = trip(h, 0, 1, 0); // 4x -> 1x
|
||||
expect("hidden preset replaced", a.scale, 1);
|
||||
expect("hidden preset replaced preset", a.preset, PSX_IR_UNSET);
|
||||
expect("hidden preset replaced key", a.save_ir, PSX_IR_UNSET);
|
||||
}
|
||||
{
|
||||
Host h{PSX_IR_DISPLAY, 1}; // 2160-px display
|
||||
PsxIrAdopted a = trip(h, 0, 0, 0);
|
||||
expect("display kept", a.scale, 9);
|
||||
a = trip(h, 0, 2, 0); // 4x -> 1x -> 2x
|
||||
expect("display replaced", a.scale, 2);
|
||||
}
|
||||
// Launcher with the row: the row owns the preset, as before.
|
||||
{
|
||||
Host h{PSX_IR_UNSET, 3};
|
||||
PsxIrAdopted a = trip(h, 1, 0, 0); // shows 720p, untouched
|
||||
expect("row untouched preset", a.preset, 720);
|
||||
expect("row untouched scale", a.scale, 3);
|
||||
expect("row untouched save", a.save_ir, 720);
|
||||
a = trip(h, 1, 0, 4320); // 8K
|
||||
expect("row 8k scale", a.scale, 18);
|
||||
expect("row 8k save ss", a.save_ss, 4);
|
||||
expect("row 8k save ir", a.save_ir, 4320);
|
||||
a = trip(h, 1, 0, 4320, 4); // software ceiling
|
||||
expect("row 8k software", a.scale, 4);
|
||||
a = trip(h, 1, 0, PSX_IR_NATIVE);
|
||||
expect("row native", a.scale, 1);
|
||||
expect("row native save", a.save_ir, PSX_IR_NATIVE);
|
||||
}
|
||||
// Invalid row values never reach the host: the seeded preset stands.
|
||||
{
|
||||
PsxIrAdopted a = psx_ir_adopt_launcher(1, 1080, 1, 1, 0, 240, 0, 32);
|
||||
expect("row invalid keeps preset", a.preset, 1080);
|
||||
a = psx_ir_adopt_launcher(1, PSX_IR_UNSET, 2, 2, -7, 240, 0, 32);
|
||||
expect("row invalid legacy factor", a.preset, 480);
|
||||
expect("row invalid legacy scale", a.scale, 2);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Presets at the NTSC 240-line reference (R4 races are 320x240).
|
||||
struct { const char* id; int s240; int s480; } table[] = {
|
||||
@@ -77,6 +200,8 @@ int main() {
|
||||
expect("legacy round trip",
|
||||
psx_resolve_internal_scale(psx_ir_from_supersampling(n, 240), 240, 0, 32), n);
|
||||
|
||||
launcher_round_trips();
|
||||
|
||||
if (g_failures) return 1;
|
||||
std::printf("internal_resolution: all checks passed\n");
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user