mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
a87277bdad
The lobby rematch is the only in-process second session: an offline session ends the process, and only a netplay match launched from the lobby soft-returns (netplay_soft_exit -> psx_request_return_to_lobby). The rematch path re-enters via goto session_reboot, below the first-boot session block, so it reset no mod-owned state at all. The reachable leak: a match with [netplay] local_viewport_aspect = "adaptive" leaves Fit (g_ws_adaptive_view) on, and an offline rematch then runs adaptive widescreen. The launcher also round-trips the match's fixed aspect (16:9/21:9 from the local viewport) through ls.aspect_index. reset_mod_owned_presentation() runs immediately before activation in the first-boot session block (absorbing the existing blend reset) and in the rematch path after its commit or netplay clear. Every call clears Fit, the world and retained scene predicates, the adaptive backdrop preload, bezel artwork, the blend mode and native VBlank pacing. Later calls also restore vsync, frame interpolation and its rate, and automatic FMV skipping to their first-session values, and clear the 8 MiB RAM request (memory_init() re-latches it at session_reboot) and the texture-bank resolver and batching flag. Netplay clears the plan, so no plugin has activated before a rematch; everything past Fit is defensive. The renderer and fixed aspect are launcher controls and process-lifetime allocations are left alone (documented in MOD_PACKAGES.md). The first-call capture lives in mod_session_baseline.h: its first call records the pre-activation values (settings.toml, PSX_VSYNC, launcher) and writes nothing back, so the first session, and every run that never soft-returns, is unchanged. A static_assert keeps the restore honest: it is only valid while interpolation and Skip FMVs have no launcher control. Function-entry hooks need nothing here: the commit or netplay clear empties the hook table and only activation rebuilds it. The rematch path also re-applies the Settings aspect clamp (4:3 while widescreen is mod-owned) before apply_netplay_local_viewport_aspect, so a netplay rematch still gets its local viewport. The first-boot path keeps the launcher/lobby aspect as before. Not changed here: the rematch path still skips activation and the controller, load and disc-speed resets of the first-boot block, so an offline rematch with mods enabled applies the plan's patches and runs its VBlank callbacks without activation. Tests: mod_session_baseline_test (new, CTest) drives the first-call capture and later restore with vsync on and off; it fails if the first call writes anything. test_mod_owned_display_controls.py guards the reset list, both call sites, reset-before-activation on the rematch path and the rematch 4:3 re-clamp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
2.2 KiB
C
59 lines
2.2 KiB
C
#ifndef PSXRECOMP_MOD_SESSION_BASELINE_H
|
|
#define PSXRECOMP_MOD_SESSION_BASELINE_H
|
|
|
|
/*
|
|
* First-call capture / later-call restore for the scalar host settings a
|
|
* trusted plugin's psx_mod_* setters can change and no launcher control owns
|
|
* (vsync, frame interpolation and its rate, automatic FMV skipping, and the
|
|
* frame periods native VBlank pacing overrides). reset_mod_owned_presentation()
|
|
* in main.cpp runs this at every session start; it lives here so a unit test
|
|
* (runtime/tests/test_mod_session_baseline.c) drives the same code.
|
|
*
|
|
* The first call records the live values -- settings.toml, environment
|
|
* overrides such as PSX_VSYNC, and the launcher are resolved by then -- and
|
|
* writes nothing back, so the first session keeps exactly what the player
|
|
* configured. Later calls write that record back over the live values.
|
|
*/
|
|
|
|
typedef struct PSXModSessionScalars {
|
|
int video_vsync;
|
|
int frame_interpolation;
|
|
int frame_interpolation_fps;
|
|
int auto_skip_fmv;
|
|
double guest_frame_period_ms;
|
|
double frame_period_ms;
|
|
} PSXModSessionScalars;
|
|
|
|
typedef struct PSXModSessionBaseline {
|
|
int captured;
|
|
PSXModSessionScalars values;
|
|
} PSXModSessionBaseline;
|
|
|
|
/*
|
|
* native_vblank_forced: psx_mod_set_native_vblank_rate() owns the frame
|
|
* periods. Only then are they restored; otherwise the video-standard follower
|
|
* owns them (the guest's GP1(08h) mode), and a restore would undo a PAL/NTSC
|
|
* switch. Returns 1 when this call captured (nothing written), 0 when it
|
|
* restored.
|
|
*/
|
|
static inline int psx_mod_session_baseline_apply(PSXModSessionBaseline* base,
|
|
PSXModSessionScalars* live,
|
|
int native_vblank_forced) {
|
|
if (!base->captured) {
|
|
base->captured = 1;
|
|
base->values = *live;
|
|
return 1;
|
|
}
|
|
live->video_vsync = base->values.video_vsync;
|
|
live->frame_interpolation = base->values.frame_interpolation;
|
|
live->frame_interpolation_fps = base->values.frame_interpolation_fps;
|
|
live->auto_skip_fmv = base->values.auto_skip_fmv;
|
|
if (native_vblank_forced) {
|
|
live->guest_frame_period_ms = base->values.guest_frame_period_ms;
|
|
live->frame_period_ms = base->values.frame_period_ms;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif
|