mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
bd65c814f7
The lobby rematch re-enters the emulator through goto session_reboot, below the first-boot session block. After its commit (offline) or netplay clear it reset mod-owned presentation state, but it never ran mod_runtime_activate_plugins() or the controller, load-acceleration and disc-speed resets. So an offline rematch with mods enabled applied the plan's main-EXE and disc patches and ran its VBlank callbacks, but no activation callback ran, and the function-entry hook table, which the commit empties and only activation rebuilds, stayed empty. It also mounted the stock disc even when the plan had built a derived disc image. start_mod_session() now holds the first-boot sequence, unchanged: clear the controller-mode overrides and presentation policies, load acceleration and disc speed; run reset_mod_owned_presentation(); activate; then apply the netplay local viewport, the controller-mode overrides and load acceleration. The first boot and the rematch both call it after their commit or netplay clear, and both then take the mounted disc from session_disc_path(), which returns the plan's derived image when there is one and otherwise the stock disc. Activation still precedes renderer and window creation on the rematch, because those happen after session_reboot on every session. The rematch re-applies its 4:3 Settings clamp before the session start, so a plugin's activation or the netplay local viewport can still set the aspect. A netplay rematch clears the plan, so activating it runs nothing and the match stays vanilla. The first boot's behaviour is unchanged. Tests: test_mod_owned_display_controls.py now requires activation and the mod-owned reset to happen only inside start_mod_session, in the order reset, activate, apply. It requires both paths to call it after their commit and before the disc mount, and the rematch 4:3 clamp to come before it. mod_runtime_test adds the lobby rematch sequence: activating after a netplay clear runs no callback, VBlank plugin or hook; the offline rematch's commit and activation re-run the activation callback and VBlank plugin and arm exactly the plan's hook. test_mod_load_acceleration.py follows the reset block into the lambda body. Two comments that said a soft return never re-applies the controller-mode override are corrected: test_launcher_pad_mode_wiring.py and test_launcher_pad_mode_resolve.cpp. MOD_PACKAGES.md now describes the rematch as a full session start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
89 lines
4.3 KiB
Python
89 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Guard mod-owned, bounded load acceleration and its launcher migration."""
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
MAIN = (ROOT / "runtime/src/main.cpp").read_text(encoding="utf-8")
|
|
HEADER = (ROOT / "runtime/include/mod_plugins.h").read_text(encoding="utf-8")
|
|
FNTRACE = (ROOT / "runtime/src/fntrace.c").read_text(encoding="utf-8")
|
|
DIRTY_INTERP = (ROOT / "runtime/src/dirty_ram_interp.c").read_text(encoding="utf-8")
|
|
CDROM = (ROOT / "runtime/src/cdrom.c").read_text(encoding="utf-8")
|
|
CONFIG_H = (ROOT / "recompiler/src/config_loader.h").read_text(encoding="utf-8")
|
|
CONFIG_CPP = (ROOT / "recompiler/src/config_loader.cpp").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
|
|
assert "psx_mod_set_load_acceleration" in HEADER
|
|
# The accepted range was widened from 2..16 to 1..PSX_MOD_LOAD_ACCEL_MAX (the
|
|
# bound is there to reject nonsense, not to curate "blessed" speeds), so pin the
|
|
# contract by its symbolic bound rather than the old literals.
|
|
assert "wall_clock_multiplier accepts 1..PSX_MOD_LOAD_ACCEL_MAX" in HEADER
|
|
assert "#define PSX_MOD_LOAD_ACCEL_MAX" in HEADER
|
|
assert "zero is the precise/speedrun-safe policy" in HEADER
|
|
assert "psx_mod_set_disc_speed" in HEADER
|
|
assert "this changes" in HEADER
|
|
|
|
# The legacy generic Turbo loads switch is retired: acceleration is mod-only.
|
|
# Both config keys are still PARSED (so old game.toml/settings.toml load), but
|
|
# neither is honoured, and no title can offer the generic switch any more.
|
|
assert "bool offer_turbo_loads = false;" in CONFIG_H
|
|
assert "DEPRECATED AND IGNORED" in CONFIG_H
|
|
assert 'runtime.contains("offer_turbo_loads")' in CONFIG_CPP
|
|
assert "rt.has_turbo_loads = true;" in CONFIG_CPP
|
|
assert "constexpr bool turbo_loads_offered = false;" in MAIN
|
|
assert "turbo_loads_offered = gc.runtime.offer_turbo_loads;" not in MAIN
|
|
assert "gi->has_turbo_loads = turbo_loads_offered_b ? 1 : 0;" in MAIN
|
|
assert "Turbo loads is mod-owned on PSX" in MAIN
|
|
|
|
# game.toml [runtime] turbo_loads must not enable anything, only warn.
|
|
assert "g_turbo_loads_enabled = 1;\n std::fprintf" not in MAIN
|
|
assert '"psxrecomp: game.toml [runtime] %s%s%s is DEPRECATED and "' in MAIN
|
|
assert '"Fast Loading (host pacing)\\" mod' in MAIN
|
|
|
|
# A stale settings.toml value is neither restored nor written back out, so it
|
|
# cannot latch: the launcher draws no row for it, which made a persisted value
|
|
# both authoritative and unreachable (MegaManX6Recomp#14).
|
|
assert "g_turbo_loads_enabled = us.turbo_loads" not in MAIN
|
|
assert "settings.toml [video] turbo_loads = true is " in MAIN
|
|
assert 'f << "turbo_loads = "' not in CONFIG_CPP
|
|
|
|
# The in-game Settings apply path reads a launcher snapshot taken BEFORE mod
|
|
# activation, so it must not write either mod-owned global.
|
|
assert "if (turbo_loads_offered) g_turbo_loads_enabled = ls.turbo_loads ? 1 : 0;" in MAIN
|
|
assert "if (skip_fmv_offered) g_auto_skip_fmv = ls.auto_skip_fmv ? 1 : 0;" in MAIN
|
|
|
|
# These run inside main.cpp's start_mod_session(), which every session start
|
|
# (first boot and lobby rematch) calls, hence the lambda-body indentation.
|
|
reset = """g_mod_load_wall_multiplier = -1;
|
|
g_mod_load_release_frames = -1;"""
|
|
disc_reset = """g_mod_disc_speed_divisor = -1;
|
|
g_mod_disc_instant_rate = -1;"""
|
|
disable_mod_owned_baseline = """if (!turbo_loads_offered)
|
|
g_turbo_loads_enabled = 0;"""
|
|
activate = "mod_runtime_activate_plugins();"
|
|
apply = "if (g_mod_load_wall_multiplier >= 0) {"
|
|
assert reset in MAIN
|
|
assert disc_reset in MAIN
|
|
assert disable_mod_owned_baseline in MAIN
|
|
assert apply in MAIN
|
|
assert (
|
|
MAIN.index(reset)
|
|
< MAIN.index(disable_mod_owned_baseline)
|
|
< MAIN.index(activate)
|
|
< MAIN.index(apply)
|
|
)
|
|
|
|
assert "release_run = g_turbo_load_release_frames;" in MAIN
|
|
assert ("g_frame_period_ms / (double)g_turbo_load_wall_multiplier" in MAIN or "present_effective_frame_period_ms() / (double)g_turbo_load_wall_multiplier" in MAIN)
|
|
assert "if (!manual_turbo_active && !turbo_load_paced && present_should_wall_pace())" in MAIN
|
|
assert "if (g_mod_disc_speed_divisor >= 0)" in MAIN
|
|
assert "fntrace_maybe_mark_game_started(cpu, addr);" in DIRTY_INTERP
|
|
assert "dirty_ram_text_image_registered()" in FNTRACE
|
|
assert "psx_game_address_in_text(addr) && psx_game_text_native_ok(addr)" in FNTRACE
|
|
assert "mode_reg & 0x48u" in CDROM
|
|
assert "if (xa_stream_active || (mode_reg & 0x68u)) return delay;" not in CDROM
|
|
|
|
print("mod-owned load acceleration guard passed")
|