Commit Graph

677 Commits

Author SHA1 Message Date
Matthew Stanley d110d0a423 Integrate current master for reviewed PR597 and retain canonical BIOS stamp 2026-10-15 00:36:07 -07:00
Matt Stanley d550ddf2e9 Merge pull request #590 from RetroPortingToolKit/feat/idle-skip-store-counters
idle_skip: elide store-counter wait loops (PsyQ v_wait), opt-in
2026-10-15 00:34:00 -07:00
Matt Stanley 9521343200 Merge pull request #664 from RetroPortingToolKit/fix/menu-host-followups
Menu host follow-ups: restart bits for touched groups, local return, recomp-ui default provider
2026-10-15 00:33:44 -07:00
Matthew Stanley d946aec09a Integrate current master for reviewed PR597 and retain canonical BIOS stamp 2026-10-15 00:00:06 -07:00
Matthew Stanley 80674e4d9f Integrate current master for reviewed PR593 and retain canonical BIOS stamp 2026-10-14 23:59:50 -07:00
Matthew Stanley e0800a28e0 Integrate current master for reviewed PR590 and retain canonical BIOS stamp 2026-10-14 23:58:57 -07:00
Matthew Stanley dfd4555d09 Include fixed scaled-charge batching profile in netplay compatibility 2026-10-14 23:51:49 -07:00
Matthew Stanley 2947916215 Detect active gamepad sessions without hijacking Deck Desktop Mode 2026-10-14 23:49:26 -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
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
Matthew Stanley f4c5d6c93f Draw paused host menus even before the first held game frame 2026-10-14 11:47:04 -07:00
Matthew Stanley 934e6c96b6 Synchronize shared menu video and netplay getters across runtime threads 2026-10-14 11:29:13 -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 594d365060 GPU: count the depth24 present hold down at guest VBlank
GP1(07h) arms s_d24_present_hold to skip a few Swaps after a depth24
display-band retarget. The hold is in the GPU snap, but it counted down
only at host present: a headless run (and any path that skips the present)
left it stuck, and a rollback snap load zeroed it. In R4's 4-seat rollback
self-test the replayed saves then differed from the live saves of the same
ticks in the GPU section (hold 3 live, 0 replay; #636).

The count now moves at guest VBlank (gpu_vblank_tick), which also latches
whether the following present skips its Swap; the present only consumes
that latch. A rollback snap load keeps the restored count. A disk
savestate load still clears it so the restored VRAM shows at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 17:19:25 -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 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 4cda11d207 Input sink: the netplay admit wait routes events to the overlay first
The admit barrier polls SDL every frame of a netplay match and treated
Esc as "leave the match" before the in-game overlay saw it, so opening
the menu online could end the session (netplay_barrier_escape).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:02:57 -07:00
Shokunin c73b34d578 Overlay input: service the overlay in the low-latency re-drain
Review (#600): with low_latency_input on, the re-drain after the pacer
wait sampled the pad without host_pause_service, so ui_capture was a frame
stale and the overlay's opening chord (Start+Select) could reach the guest
for one frame. The re-drain now services the overlay before the sample.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:33:32 -07:00
Shokunin 475a3ad6c5 Debug host_mouse: inject a click or wheel step at a window point
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:33:32 -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 5c8a0c2d60 Host pause: re-anchor pacing on resume; hold the guest headless too
Review (#598): resuming left the frame pacer's deadline in the past, so it
paid a pause back as up to ~12 unpaced frames. Resume now runs
present_session_reset, an audio cycle resync and a dynamic-resolution hold,
as a savestate load does. host_pause on=1 headless was a no-op that answered
ok; the headless frame path now enters host_pause_loop too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:33:17 -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 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 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
Shokunin 9515cb7dfe idle_skip: elide store-counter wait loops (PsyQ v_wait)
idle_skip only skipped loops with zero stores and a single interrupt-check
edge, so it never fired on PsyQ libetc's v_wait -- the VSync(0)/VSync(n)
spin most PsyQ titles run each frame -- which decrements a stack timeout
word every pass and crosses two block edges.

New opt-in on top of idle_skip, [runtime] idle_skip_store_counters
(PSX_IDLE_SKIP_EXT=0/1 for one run):
- an iteration may span up to 8 block edges; the first edge is the anchor
  and the edge count must be stable;
- one word store per iteration to the same RAM/scratchpad address whose
  value drops by exactly 1 (a register holding it may drop with it).
Skips lower the counter by k (never to <= 1) and, for multi-edge loops, land
on the anchor strictly before the next device event so an IRQ is taken at
the same edge as without the skip. memory.c records the last word store's
address and value for the detector.

R4 race, 3600 frames from one savestate, held input: cyc, mmio, mc, sp, sc
and qc identical every frame; wc differs only by the elided counter stores.
Release build on an Apple M4: emulation-thread busy 47.5% -> 34.9% at 60 Hz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:25 -07:00
Matthew Stanley 1473c66772 Merge validated renderer fixes into generic post-effect pipeline 2026-10-13 10:18:03 -07:00
Shokunin abbae48947 Dithering on by default with explicit per-primitive eligibility
Maintainer review of #584: PS1 dithering is hardware behaviour, so it is
now on by default whenever the guest sets GP0(E1h) bit 9 ([video]
dithering = "on"; "scaled" stays opt-in, "off" is the old true-colour
output).

Eligibility is decided per primitive from its command and carried in the
vertex instead of being inferred from the colour:
- Gouraud polygons and shaded lines: geometry vertex a_col.a + 2*131072
  (decoded in GEO_VS, v_dith);
- texture-modulated polygons: a_semi + 8 (v_dith in TEX_VS);
- flat polygons/lines, raw-texture polygons and every rectangle: never.
This fixes the two reproduced bugs (Gouraud with 5-bit-exact colours was
skipped; textured rectangles were dithered). Bit changes no longer flush:
eligibility is fixed when the primitive is queued; mode changes still drain.

gl_dithering_test covers each case (Gouraud incl. equal colours, shaded
line, modulated and neutral-modulated textured polys dithered; flat tri,
flat rect, flat line, raw poly, modulated and raw textured rects never;
bit clear and off unchanged), plus scaled 4x == 1x, render thread, PGXP
depth, native-wide and the accurate-blending basis. OpenBIOS stamp
regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:18:29 -07:00
Shokunin 023af6d9d4 GL: opt-in PS1 dithering ([video] dithering = off|on|scaled)
The OpenGL renderer has always drawn shaded and texture-modulated pixels
at 8 bits per channel with no dither pattern (true colour). That stays the
default. 'on' applies the PS1 4x4 offset matrix and 5-bit truncation per
internal-resolution pixel; 'scaled' puts the pattern on the native grid,
so it reads like the console at any scale and the native VRAM is the same
at every internal resolution.

GP0(E1h) bit 9 reaches the backend through a new optional facade hook
(gr_set_dither) recorded for the render thread and Smooth motion redraws.
With the mode off nothing flushes and no uniform changes. Flat, raw and
other 5-bit-exact pixels are never touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:18:29 -07:00
Shokunin 18e10693c4 post effects: MinGW build fix, generated frames reuse bloom's glow, no glGet in marking
- config: [video] post_shader is a std::filesystem::path (like memcard_dir);
  the frontend turns it into UTF-8 bytes for the GL API. Assigning the path
  to a std::string did not compile on MinGW.
- .pfx `generated reuse`: a Smooth motion generated frame keeps that pass's
  target from the last real frame. The bloom preset marks its bright and
  blur passes so; generated frames run only the masked composite (over their
  own picture and mask). bloom debug reports real/generated pass times and
  reused passes.
- Mask marking no longer queries GL state per batch: each call site puts
  back the blend and mask-bit stencil it set (no driver round trips on the
  render thread).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:15:46 -07:00
Shokunin 74dadc6004 GL: one post-effect pipeline; bloom and FXAA as built-in chains, user chains via [video] post_shader
Post effects now run as chains of full-screen fragment passes on one
executor (gl_postfx.inc), as asked in review. A chain is a small .pfx preset
(postfx_chain.c, GL-free): passes with a shader (a file next to the preset or
builtin:<name>), inputs (source, the optional primitive-derived mask,
previous or a named earlier pass), a scale, format, filter and uniforms.
The executor owns target allocation and lifetime, program build/cache,
uniform binding (u_rcp, u_size, u_org) and GL state save/restore.

Stages, in order, each from a fresh copy of the image: the built-in "bloom"
chain ([video] bloom), a user chain ([video] post_shader / PSX_POST_SHADER,
elective, off by default), and the built-in "fxaa"/"fxaa_hq" chain
([video] antialiasing_mode). FXAA folds in as a one-pass chain and its
output is byte-identical to the former fixed pass; it still runs on real
frames only. Generated (Smooth motion) frames run bloom and the user chain.

The "may glow" mask is an optional pipeline input: draws keep stencil bit 1
only while an active chain reads `mask`, and the window-sized mask texture is
built once per present for the chains that use it.

Tests: postfx_chain_test (format, built-ins, errors, file import, no GL);
gl_bloom_test gains an imported two-pass chain (byte-exact invert), the mask
input (HUD unlit, 3D lit), a bad preset, a pass that does not compile, and GL
state restored with bloom + a mask chain + FXAA on, all on the caller thread
and the render thread. docs/POST_EFFECTS.md documents the format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:15:46 -07:00
Shokunin e730e03a8a GL: opt-in bloom ([video] bloom), sourced from 3D and additive primitives only
[video] bloom = 0.0 (off, default) .. 2.0 adds a glow around lights on the
OpenGL backend. PSX_BLOOM overrides it for one run; {"cmd":"bloom"} reads or
changes strength, threshold and a debug view live. It is a plain [video] key,
so [quality.*] presets can switch it off on low-end machines.

The HUD never glows: with bloom on every textured and untextured draw is
followed by two stencil-only passes of the same vertices that keep a
"may glow" mark in stencil bit 1 (bit 0 stays the mask-bit mirror). Opaque
primitives clear it under their coverage, then PGXP-proven 3D primitives and
additive semi-transparent texels/primitives (modes 1 and 3) set it, painter
ordered like the colour; 3D and non-3D primitives never share a batch while
bloom is on. Semi-transparent primitives leave the mark alone and the PGXP
depth-clear pass (colour writes off) marks nothing. Without PGXP geometry only
additive primitives glow.

The pass runs on the composed game image before AA and the OSD: the presented
surface's marks are blitted into a quarter-resolution stencil, a soft-knee
bright pass runs under it, three separable Gaussian iterations spread it and a
screen blend adds it back. The marks follow the picture: native-wide centre
copies and Smooth motion surfaces (redraw and reprojection) copy stencil with
colour, and generated frames get the same pass. Off: nothing runs, no state
changes, and the composed frame is byte-identical to master.

test_gl_bloom (gl_bloom_test): off is byte-identical before/after bloom and
with --dump against master; on, a bright 2D panel and a panel over a lit 3D
polygon are byte-identical to off, an additive and a 3D polygon glow; guest
VRAM is unchanged; on this thread and on the render thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:15:46 -07:00
Shokunin f6c86b01cd Game Mode: keep only the gamescope signals and SteamDeck=1
SteamGamepadUI=1 is also set when Steam launches from Big Picture on an
ordinary desktop, which is broader than Steam Deck / gamescope. Detection is
now XDG_CURRENT_DESKTOP=gamescope, GAMESCOPE_WAYLAND_DISPLAY or SteamDeck=1
(plus --game-mode / PSX_GAME_MODE); game_mode_test and docs updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:51:59 -07:00
Shokunin 477bb188b4 Game Mode: Steam Deck / gamescope boots straight into the game, fullscreen
Detected from a gamescope session (XDG_CURRENT_DESKTOP, GAMESCOPE_WAYLAND_DISPLAY)
or Steam's gamepad UI (SteamGamepadUI=1); --game-mode / --no-game-mode and
PSX_GAME_MODE override. When on and a disc is set up, the launcher is
skipped and the game opens borderless fullscreen for that run (the saved
Fullscreen choice is untouched); the first run still shows the launcher so
the disc can be picked. Desktop sessions, --headless and --hidden-window are
unchanged. game_mode_test covers detection and precedence; docs/GAME_MODE.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:51:59 -07:00
Shokunin 47fb2af915 Launcher handoff: keep the texture filter enum (xBR no longer becomes bilinear)
The seed path collapsed ls.texture_filter to a boolean, so a launcher's
xBR (3) was saved and applied as bilinear, and the rematch paths passed
the raw value through unchecked. psx_texture_filter_from_ui is now the
one translation (in-range values pass, others are nearest). Test:
video_texture_filter_test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:06:00 -07:00
Alex Vanderveen c47f7391e8 fix netplay 2026-10-11 16:16:33 -04:00
Matthew Stanley 7dfef44598 Reconcile current master with validated X4 co-op support for PR23 playtest 2026-10-10 20:49:35 -07:00
Matt Stanley 19785e9f51 fix: guard ICE waiting-room helpers in offline builds (#625) 2026-10-10 12:55:50 -07:00
Matthew Stanley 4b96c039f6 Integrate current ICE lobby transports and preserve settled LAN boot settings 2026-10-10 10:53:54 -07:00
Shokunin 0b0641cbae Lobby: honour transport "ice" launches (same-NAT peers no longer dial themselves)
The lobby server starts a 2-player room the host relay cannot carry on ICE
(recomp-net-server start_transport, launch transport "ice"). This client
knew only "host" and the legacy server relay. It inferred a relay from
equal host/guest endpoints -- which is exactly what two peers behind one NAT
advertise -- and each peer dialled its own public address: the match stayed
at "linking" forever.

- psx_lobby_launch_transport.h: one pure decision (host / ice / relay /
  direct) with a unit test covering ICE, same-NAT endpoints, host relay and
  the legacy relay cases.
- PsxLobbyJoinInfo.transport_ice; the launch handler records it and never
  turns it into a relay; launch fill and resolve_use_ice start ICE p2p
  (signalled over the lobby) for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 10:37:31 -07:00
Matt Stanley 8cb420660e Merge pull request #624 from RetroPortingToolKit/fix/pgxp-qualified-defaults-20261010
Use dataflow-only PGXP defaults automatically in hook builds
2026-10-10 09:52:57 -07:00
Matt Stanley f17a946e6a Merge pull request #623 from RetroPortingToolKit/fix/native-wide-default-clipping-20261010
Make camera-plane clipping automatic with native-wide projection correction
2026-10-10 09:52:51 -07:00
Alex Vanderveen 1a8994ac0b Merge feat/ice-hub-relay: host relay over ICE for online rooms
Resolved against master: resolve_transport keeps master's single-agent
transport=ice launch (2-player rooms) ahead of psx_transport_decide; match_caps
JSON keeps the mod-plan fields and adds relay_via=ice; recomp-net bumped to
a48d355 (host_ice).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 04:20:24 -04:00
Matthew Stanley e7a059643c fix: select dataflow-only PGXP defaults in hook builds 2026-10-10 00:48:22 -07:00
Matthew Stanley ddbb979f18 fix: enable camera-plane clipping with native-wide projection correction 2026-10-10 00:48:17 -07:00
Matt Stanley 6fd3d1c326 Merge pull request #587 from RetroPortingToolKit/feat/gl-accurate-blending
GL: correct PS1 blending by default + blend/mask accuracy test
2026-10-09 23:56:33 -07:00
Matthew Stanley 1dd2afec07 Merge master and enable PS1 blend correction by default 2026-10-09 23:55:29 -07:00
Alex Vanderveen 50b53cc6d0 Merge master into fix/lobby-ice-launch
Keep both new test targets in runtime/CMakeLists.txt.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 02:22:03 -04:00