CRT Filter, Image Filtering, Enhanced Audio and Rewind become default-off mods (netplay = host_only,
outside the plan fingerprint); Internal resolution gains Auto in place of dynamic resolution.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Keep the requested internal resolution / supersample (shown and saved)
apart from what the backend last applied. When the live change is
unavailable (no GL, windowed high-resolution mode, CPU-authoritative dual
rendering, no context) or refused, the session scale is left as applied and
PSX_VIDEO_RESTART_RESOLUTION stays set, in both psx_video_apply_live and
the menu's restart bits (psx_host_video_restart_bits_backend, unit-tested
for the capable and refused cases). video_set rejects invalid presets and
factors without applying or saving, and reports applied values, capability
and pending restart. TCP command index regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changing the internal resolution in the in-game menu did nothing until a
relaunch: ovl_video_from() never copied it, and the restart bits forced
a relaunch for it anyway. Supersampling (the [video] supersample
multiplier) had no player setting at all.
- PsxHostVideoSettings gains supersample_milli; internal resolution and
supersample are live changes (PSX_VIDEO_LIVE_RESOLUTION). Only the
legacy integer supersampling factor still needs a relaunch.
- psx_video_apply_live resolves the new scale and calls
gl_renderer_set_internal_scale_live(): it moves the step ceiling
(clamped like the boot scale) and queues the step through the dynamic
resolution machinery, recorded in stream order with the render thread.
The dynamic-resolution controller is retargeted to the new ceiling.
- settings.toml [video] supersample is the player's pick (1.0..4.0).
- The in-game menu round-trips internal_resolution and, with a launcher
that has RECOMP_LAUNCHER_HAS_SUPERSAMPLE, supersample_milli.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A title can draw its own heads-up display on the host side (ImGui, like the
in-game overlay provider), once per presented frame -- real and generated
frames -- under the in-game menu and with the same thread and GL rules as
psx_host_overlay_set_draw_cb. Registered once at title activation; NULL
unregisters. No callback registered: no change in behaviour.
Used by a modern race HUD for R4 (lap, timing, tachometer, track map) drawn
at window resolution instead of the 320x240 native one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rkyma8rbyPiccs9n2bkyG6
psxrecomp owns the contract between the runtime and any in-game menu
frontend. A provider (PsxMenuProvider: attach, event, is_open, set_open,
draw, detach) is registered by the title with psx_menu_set_provider();
none is registered by default, so a title's UI and pin are unchanged.
The runtime offers every provider the same host (PsxMenuHost): pause
(P1, refused in netplay), video get/apply on PsxHostVideoSettings (P4),
mod switch/option set (P5, via the new psx_mod_feature_enable /
psx_mod_feature_set_option shared with the launcher ABI provider),
reload bindings, exit (quit, back to the frontend loop in-process, or a
quick relaunch with the original arguments), disc/tray slots filled by
the tray policy (psx_menu_set_disc_ops), and optional helpers on the
shared launcher ABI both frontends already speak (game info with the
mod catalogue and lobby, settings get/apply with the handoff's filter
translations).
Policies live here, the same for every provider: the lobby is pumped
during play and a started match ends the local session and starts in
the frontend loop (pending launch, seats and signals kept, pumping
stopped so the match port stays free), the menu is closed and its pause
dropped first; the provider detaches before its GL context goes away at
session teardown and attaches to the next one. --launcher sets
RECOMP_LAUNCHER_PREGAME for frontends that boot into the game;
PSX_HIDDEN_WINDOW is a hidden-window test hook that keeps the frontend.
Nothing here includes or names a frontend's own headers or types.
Tests: psx_menu_host_test, host_overlay_test (relaunch quoting).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#655 landed the same PSX_TEXTURE_FILTER_* enum and translation in
video_texture_filter.h/.c; drop this PR's duplicate (link error) and
include that header.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review (#601/#603): the live path and the launcher handoff both collapsed
the texture filter to a boolean (value ? 1 : 0), so neither could carry xBR
(#586) and they could drift from settings.toml. PSX_TEXTURE_FILTER_* is now
the one enum (equal to [video] texture_filtering / gr_set_texture_filter),
and psx_texture_filter_from_ui is the one translation used by the launcher
handoff (seed, UserSettings, live globals) and the in-game apply. Unit-
tested in host_overlay_test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
psx_video_apply_live applies the [video] keys a running game can change
(fullscreen, texture and FMV filter, scanlines, linear present, dynamic
resolution, frame generation) through the existing live setters, saves
them to settings.toml, and reports renderer / internal resolution /
thread changes as restart-only. Nothing calls it without a provider.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
psx_host_set_input_sink: an overlay provider sees host SDL events first,
in the event drain and the host pause loop, and may consume them.
psx_host_set_ui_capture: while on, local game input reads released and
centred (netplay included, so peers receive "nothing pressed") and the
external-input gate stays closed. Debug builds gain host_key, which pushes
a real SDL key event for scripted runs. Inert without a provider.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review (#599): who keeps the callback context alive until render-thread
calls are quiescent. Draw calls now run inside an in-flight count, and
set_draw_cb (replace or NULL) swaps the record and waits until no call
that read the old one is running, then frees it. When it returns, the
registrant may free ctx and its GL objects; it must unregister before
destroying them or the context. A change from inside the callback does
not wait. Documented in host_overlay.h. Tests: a reader thread drawing
while the owner unregisters and frees (300 rounds; fails without the
wait), and self-unregister from the callback.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review (#599): fn and ctx were two separate stores read on the render
thread, so an unregister could pair a live fn with a NULL ctx. They are now
one immutable record behind an acquire/release atomic pointer. The GL
fixture runners compile a fixed source list; gpu_gl_renderer.c now calls
psx_host_overlay_draw, so every run_gl_*.py links host_overlay.c.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
psx_host_overlay_set_draw_cb: the OpenGL backend calls it after the game
frame and host OSD layers are composed, before present_shot capture and
the swap, on the thread that owns the GL context. Without a registered
callback nothing changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
psx_host_pause_push/pop: a nesting, host-owned pause. While it is held the
runtime freezes the guest at the vblank present (as the save-state menu
does), keeps presenting the last frame and pauses audio. Push refuses
during netplay. Nothing pushes unless an overlay provider (or the debug
server's new host_pause command) asks, so behaviour is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>