Commit Graph

994 Commits

Author SHA1 Message Date
Matthew Stanley 3e923b97d1 Carry prior four-title validation NCLIP compatibility API 2026-10-14 23:57:33 -07:00
Matthew Stanley dd3499ff87 Validation: integrate PR597 for current-head regression review 2026-10-14 23:51:54 -07:00
Matthew Stanley dfd4555d09 Include fixed scaled-charge batching profile in netplay compatibility 2026-10-14 23:51:49 -07:00
Matthew Stanley 80edb2e5b8 Validation: integrate PR666 for current-head regression review 2026-10-14 23:49:57 -07:00
Matthew Stanley 28dfd163c3 Validation: integrate PR664 for current-head regression review 2026-10-14 23:49:52 -07:00
Matthew Stanley 09df30e47d Validation: integrate PR609 for current-head regression review 2026-10-14 23:49:45 -07:00
Matthew Stanley e05b6329a2 Validation: integrate PR597 for current-head regression review 2026-10-14 23:49:35 -07:00
Matthew Stanley fe209438cd Validation: integrate PR593 for current-head regression review 2026-10-14 23:49:29 -07:00
Matthew Stanley 2947916215 Detect active gamepad sessions without hijacking Deck Desktop Mode 2026-10-14 23:49:26 -07:00
Matthew Stanley 1e8197a030 Validation: integrate PR593 with graphics preset sources 2026-10-14 23:49:23 -07:00
Matthew Stanley 5b218fa76a Validation: integrate PR591 for current-head regression review 2026-10-14 23:48:08 -07:00
Matthew Stanley ab0bac7d31 Validation: integrate PR590 for current-head regression review 2026-10-14 23:48:02 -07:00
Yves 99dd1eee46 Add head-facing billboard surfaces with shared stereo orientation 2026-10-15 05:17:38 +08:00
Yves 890fed78f5 Add frame-local positioned RGBA surfaces to stereo rendering 2026-10-15 05:17:37 +08:00
Yves 062d6e39e0 Add isolated render capture with staged RGBA readback 2026-10-15 05:17:37 +08:00
Shokunin 9575de1ad8 psx_menu_host.h: feature macro for default_selection
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:17:30 -07:00
Shokunin c3a2f2c068 Menu host follow-ups: restart bits for touched groups, local return, default provider
- Restart bits: a group waits only when the edit touches it (next differs
  from the live value) and the result differs from boot. Dynamic
  resolution moves the live internal resolution off boot, so an in-game
  texture filter change relaunched the game. test_menu_video_snapshot
  covers both cases.
- Return to the frontend from a local game opens the launcher as at
  boot; only a lobby match start (the runtime's pending-launch exit, or
  the provider's lobby view asking once its match started) keeps the
  launch and resumes the room.
- Default provider: with no title choice, the UI library's provider is
  used when it ships one (recomp_ui_psx_menu.h), so recomp-ui stays the
  default; PsxMenuHost.default_selection tells it to keep the title's
  default presentation.
- Debug: menu_host reports provider, open, pause, capture and snapshot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:17:18 -07:00
Matthew Stanley a36754b7ee feat(renderer): allow guarded opaque sprite backgrounds in native wide 2026-10-14 12:11:10 -07:00
Matt Stanley d3db61b199 Merge pull request #598 from RetroPortingToolKit/feat/host-pause
Host pause API (in-game overlay P1)
2026-10-14 11:55:36 -07:00
Matt Stanley 12152ecc77 Merge pull request #661 from RetroPortingToolKit/fix/depth24-hold-vblank
GPU: count the depth24 present hold down at guest VBlank
2026-10-14 11:33:00 -07:00
Matthew Stanley 8d3ab09b45 Bring the BIOS ABI and SetLoc correction onto current master 2026-10-14 11:21:51 -07:00
Matt Stanley 2fca087a1b Merge pull request #657 from RetroPortingToolKit/work/final-bout-cd-sector
fix(cdrom): preserve requested sector bytes across pending interrupts
2026-10-14 11:20:09 -07:00
Shokunin 0d096e2858 GPU: carry the depth24 held-VBlank flag in the snap; executable hold regression
Review follow-up on #661 (#636):
- test_depth24_present_hold_vblank.py reads sources as UTF-8 (cp1252 on
  native Windows Python raised UnicodeDecodeError).
- The present skip is now guest state: set at guest VBlank, read (not
  consumed) by the present and packed into the GPU snap's hold word (bit 8;
  older snaps derive it from the count). The executable test showed the
  host-side latch made the present of a restored tick differ from live on
  the last held VBlank (hold 0, skip 1), exposing stale trailing FMV
  columns after a rollback load.
- Depth24 scanout staging and trailing-column blanking move from main.cpp
  into gpu_depth24_stage_scanout (gpu.c), so the test renders through the
  same code every CPU depth24 present runs.
- New depth24_present_hold_exec_test: drives real gpu.c through a 15-bit to
  24-bit FMV, GP1(07h) retargets and mode transitions; compares hold, skip,
  upload span and snapshot bytes across windowed/headless/deferred presents,
  rollback replay from every tick and disk loads, and checks staged frames
  never show stale movie pixels while the new movie stays visible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:53:21 -07:00
Shokunin 83f1468860 In-game menu host: a provider-neutral contract (psx_menu_host.h)
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>
2026-10-13 15:02:57 -07:00
Shokunin 5b454f3db0 Live mod options: psx_mod_save_selection writes state.toml without re-planning
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:02:57 -07:00
Shokunin a32471d5fd Live mod options: restart-only changes do not reach the running plugin
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:02:57 -07:00
Shokunin 00671ce845 Live mod options: psx_mod_option_live_capable
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:02:57 -07:00
Shokunin f739d1feb7 Live mod option changes (in-game overlay P5)
psx_mod_set_option_live records a session override for a committed
feature's option and calls the plugin's new option-changed callback in
that plugin's context; psx_mod_option_value answers the override. It
returns 1 when applied live, 0 when the change waits for a restart, -1
during netplay (the plan is negotiated between peers). Nothing changes
unless an overlay calls it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:02:57 -07:00
Shokunin 3534e21aa5 Live video apply: use master's texture-filter enum (#655) instead of a copy
#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>
2026-10-13 15:02:57 -07:00
Shokunin 0f09935c23 Live video apply: one texture-filter enum for settings, handoff and menu
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>
2026-10-13 15:02:57 -07:00
Shokunin 09144c8c31 Live video apply: netplay guard, persist every field, build in Release
Review (#601):
- psx_video_apply_live had no netplay guard. In a match only presentation
  (fullscreen, scanlines, linear present) applies live; dynamic resolution,
  frame generation and the filters are saved and reported with the new
  PSX_VIDEO_RESTART_NETPLAY bit (next session).
- internal_resolution and present_thread are written to UserSettings like
  the other restart-only fields, so the choice survives a restart.
- The live-apply code sat inside #ifndef PSX_NO_DEBUG_TOOLS but is used by
  the launcher path, so Release + launcher did not compile. It now lives
  outside the debug-tools block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:02:57 -07:00
Shokunin ca3994e86d Live video apply (in-game overlay P4)
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>
2026-10-13 15:02:57 -07:00
Shokunin e21226feb7 Overlay input sink and UI capture gate (in-game overlay P3)
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>
2026-10-13 14:33:32 -07:00
Shokunin facdf01ac6 Overlay draw callback: unregister waits for in-flight draws (lifetime contract)
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>
2026-10-13 14:33:29 -07:00
Shokunin 153279824a Overlay draw callback (in-game overlay P2)
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>
2026-10-13 14:33:29 -07:00
Shokunin 138b44a58e Host pause API (in-game overlay P1)
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>
2026-10-13 14:33:17 -07:00
Shokunin 74bb133b50 quality presets: source comments match the rules (Low/Ultra, unknown Medium, High manual)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin c79f5d8c84 gcs batch: publish on the guest clock alone
The batched scaled charge fell through to the scale-1 batch path, which
also defers while g_psx_cyc_bb_defer is nonzero and routes through the VLC
local sink. Both are host call-stack state (a longjmp escape leaks or
resets the depth), so which charge published the batch -- and so which
clock each device saw -- differed between hosts. R4 2P rollback Mac<->PC
with modern controls split by a few cycles in live play (clk/tim fork at
~3296 with cpu/ram equal), then baseline mismatches and a realign storm
dropped the match; with the batch off the same pair matched.

The scaled path now batches on the guest clock only (device deadline or
the 64-cycle soft cap). New check: the service log is identical with
bb_defer 0 or 338 and with a local sink installed (fails before). Re-stamp
the OpenBIOS emitter sha (psx_cyc.h is in the codegen hash).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin 09ee810fbd quality presets: an unrecognised GPU gets Medium, not Ultra; honest docs
Nothing is measured about an unknown GPU, so the fallback no longer assumes
Ultra's extra work (supersampling above the display, title Ultra extras);
Low would drop Smooth motion and the PGXP extras on what is usually capable
new hardware. Medium keeps the display's resolution with dynamic
resolution under it. Covers unnamed renderers, Linux with only an AMD PCI
id, and unnamed nouveau chips. docs/QUALITY_PRESETS.md states plainly that
autodetect is a static heuristic over name, threads and memory with no
benchmark, and that the dynamic systems keep the frame rate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin 43afb3bb16 timing: opt-in batching of the scaled CPU charge
With [timing] guest_cycle_scale active, every one-cycle psx_cyc_charge went
straight to psx_cpu_charge and psx_advance_cycles, bypassing the batch the
scale-1 path uses. [timing] guest_cycle_scale_batch (PSX_GCS_BATCH=0/1)
scales the charge in place, with the same fractional carry and order as
psx_cpu_charge, then batches it like the scale-1 path. It flushes at the same
observation points. Default off.

R4 exactness, frame_fingerprint off vs on, 9000 frames each: headless boot
through intro, title and attract; a 1P Grand Prix race; and a 2P VS race.
cyc, mmio, mc and qc are identical on every frame. sp, wr, pc and ws are
identical at the end. The only differences are single-frame VBlank straddles
of wc/sc (never two frames in a row). 0 dispatch misses.

Speed, release builds, races at 60 Hz:
- M4 (macOS sample): psx_cpu_charge 4.3 % -> 0 % of emulation-thread samples;
  busy 46.0 -> 44.4 % (2 pairs).
- 9800X3D: no measurable change (30.0 vs 30.5 %; one core 44.6 vs 44.2 %).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin f99a318999 quality presets: review fixes (headless, persistence, Linux, renderer table)
1. Detection never runs under --headless / --hidden-window (CI, scripted
   runs): a saved preset applies, else the title's [video]; nothing is
   written. A detection is saved only when the GL probe succeeded; a result
   from the OS name alone is used for that run and the next launch probes
   again (a failed probe could otherwise pin "unknown GPU" -> Ultra).
2. Linux without a GL probe: the classifier now reads the sysfs PCI id
   (Steam Deck parts, Intel integrated vs Arc, NVIDIA).
3. AMD/Intel rules rewritten against real renderer strings: "Radeon RX
   Vega 11 Graphics" and other Vega/"Radeon Graphics"/R5-R7/680M-890M APUs
   are integrated (Low); RX/Pro/W cards and Strix Halo are Ultra; the Intel
   Arc iGPU is Low, Arc A/B cards Ultra. quality_presets_test holds a
   44-row table of Windows, Mesa (incl. Steam Deck LCD/OLED, zink) and macOS
   GL_RENDERER strings, plus probe-failure and headless cases.
5. generated/OpenBIOS.emitter.sha re-stamped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin 35e55efb08 quality presets: Ultra by default; step down only classes that cannot hold 60 Hz at the dynamic floor
Owner decision: Ultra on first launch, with dynamic resolution, Smooth
motion from surplus and the adaptive aspect as the live safety net. Apple
silicon, discrete GPUs, unknown GPUs and 8 GB machines now detect as Ultra;
software GL, Steam Deck, mobile, Intel HD/UHD and small AMD iGPUs stay Low,
mid iGPUs Medium; fewer than 4 threads or under 6 GB still caps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin d5fc43d802 Graphics presets with hardware detection (opt-in per title)
A title may declare [quality.low|medium|high|ultra] tables of [video] keys.
On first launch, and when the hardware fingerprint changes while a preset is
in force, psxrecomp detects the CPU, threads, RAM and GPU (OS facts; a hidden
1x1 GL window reads GL_RENDERER only when a detection is due and the OS did
not name the GPU), picks the matching preset and saves quality_preset,
quality_base, quality_hardware and quality_detected to settings.toml.

- Each preset is the whole game.toml re-parsed with its keys over [video], so
  every [video] key works in a preset with its usual validation.
- A preset in force owns its keys: saved settings.toml values for them are
  ignored. Custom (the player changed a governed setting in the launcher)
  applies the player's values over quality_base and is never overridden;
  new hardware under Custom is only reported.
- Launcher: GameInfo.quality_* (offered mask, detected preset, hardware
  summary, quality_apply / quality_redetect callbacks) and
  Settings.quality_preset/quality_base, behind RECOMP_LAUNCHER_HAS_QUALITY_PRESETS.
- PSX_QUALITY=<preset> for one run, PSX_QUALITY_REDETECT=1.
- Titles without [quality.*] are unchanged.

Rules (quality_tier.c) and the decision are unit-tested in
quality_presets_test; docs/QUALITY_PRESETS.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin 7a4a1a004a idle_skip store counters: only audited sites (idle_skip_store_counter_sites)
The detector cannot prove a loop has no later counter-dependent exit, so
the extension now skips only at block-edge PCs the title lists after an
audit. Unlisted sites are never skipped; an empty list disables it. Docs
record R4's v_wait audit as the reference; tests cover unlisted sites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:25 -07:00
Shokunin f2570a8f76 idle_skip store counters: review fixes, exactness from boot, pinning test
- Last-store tracking: memory.c owns the record and writes it only while
  the extension is on (g_psx_track_last_store); main.cpp hands it and the
  host writer (psx_host_write_word) to psx_cycles.c through
  psx_idle_skip_set_store_tracker / _set_host_writer, so psx_cycles.c no
  longer references memory.c (fixes the tests that link one without the
  other).
- Exact from boot: the device distance is now measured from the current
  cycle (devices report it from their last service, up to a few hundred
  cycles behind), and several edges per pass are accepted only together
  with a counter store. Before this, R4's boot diverged at frame 962 (an
  OpenBIOS multi-edge poll and a late VBlank IRQ after a v_wait skip).
- tests/test_idle_skip_store_counter.c: a v_wait trace skips (whole
  passes, counter lowered by the host writer, never to the timeout, lands
  before the event); an extra store, an MMIO read, a decrement of 2, a
  store to MMIO, the option off and no host writer do not.
- generated/OpenBIOS.emitter.sha re-stamped.

R4 frame_fingerprint off vs on, 9000 frames each: boot through intro and
attract, a 1P race and a 2P VS race: cyc, mmio, mc, sp, sc and qc
identical on every frame, 0 dispatch misses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:25 -07:00
Matthew Stanley 348545a49f fix(cdrom): latch requested sector bytes independently of pending IRQs 2026-10-13 10:50:30 -07:00
Matthew Stanley 1473c66772 Merge validated renderer fixes into generic post-effect pipeline 2026-10-13 10:18:03 -07:00
Matt Stanley 6eaf078699 Merge pull request #584 from RetroPortingToolKit/feat/gl-dithering
GL: PS1 dithering by default (native grid), elective fine/off modes
2026-10-13 10:10:53 -07:00
Matt Stanley a042ed00c8 Merge pull request #610 from RetroPortingToolKit/feat/netplay-host-output
Mod plugins: netplay = "host_output" (read-only hooks stay on online)
2026-10-13 10:09:37 -07:00
Matt Stanley 2095249191 Merge pull request #640 from RetroPortingToolKit/fix/display-ring-full-frame
display_ring_get: whole display (480i, depth24) from the frame VRAM snapshot
2026-10-13 10:09:30 -07:00