Files
psxrecomp/docs/NETPLAY.md
T
Alex Vanderveen 33c9901497 buiild with ICE
2026-08-07 03:56:32 -04:00

165 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Netplay with recomp-net (psxrecomp)
This is the **feature overview** for rollback-capable multiplayer in PSX
title projects that opt into `-DPSX_NETPLAY=ON` and ship `lib/recomp-net`
(plus lobby client). It describes what we are introducing for players and
title developers — not the internal soak checklist.
Deeper / implementation docs:
| Doc | Role |
|-----|------|
| [`NETPLAY_TOPOLOGY.md`](NETPLAY_TOPOLOGY.md) | Locked online vs LAN topology |
| [`ROLLBACK_MOTK_HOOKUP.md`](ROLLBACK_MOTK_HOOKUP.md) | MotK rollback integration notes |
| [`config_schema.md`](config_schema.md) `[netplay]` | Disc gate fields (`require_cue`, tracks, fingerprint) |
| [`lib/recomp-net/README.md`](../lib/recomp-net/README.md) | Transport / session library |
| Lobby server `WS_LOBBY.md` (recomp-net-server) | WebSocket lobby + SFU policy |
Opt-in at configure time: see [`GAME_PROJECT_SETUP.md`](GAME_PROJECT_SETUP.md)
(`PSX_NETPLAY`, `ENABLE_NETPLAY_IF_PRESENT`). The launcher NETPLAY button only
appears when the host advertises `GameInfo.netplay_supported`.
---
## Rollback netcode
Default match mode for opted-in titles is **rollback** (GGPO-style tip
prediction + resimulation), with **delay-sync** still available as an opt-out
(“Disable Rollback” in lobby settings, or `PSX_NET_MODE=delay`).
- Peers exchange pad tips over the session; missing remote input is
predicted for a short horizon, then corrected by resim when the real tip
arrives.
- Input delay (D) and prediction depth (P) can be auto-derived from RTT or
set manually in the lobby.
- Savestate / snapshot rings and AV digests keep peers aligned; FMV / media
paths use lockstep-friendly rules so digests stay meaningful.
Rollback is the product default for titles that ship it (e.g. MotK). Delay-sync
remains useful for debugging and for hosts that prefer fixed lag.
---
## Hybrid graphics (determinism + present quality)
Netplay must keep **guest simulation identical** across peers. Present quality
is separate.
When **OpenGL** is selected and netplay is active, psxrecomp can run a
**dual-raster** path:
| Layer | Scale | Role |
|-------|-------|------|
| Software rasterizer | **1×** (headless authority) | Deterministic VRAM / digests / rollback snaps |
| OpenGL | Player supersampling (e.g. 2×–4×) | Window present quality only |
Cost: extra CPU for the 1× SW pass. Benefit: peers can use different GL
settings without desyncing the sim. SW-only netplay forces scale 1 for the
whole path. Offline play keeps full supersampling with no dual-raster tax.
---
## Connectivity: ICE, TURN, SFU, LAN
### Online lobbies (WebSocket + SFU)
Online matches go through the lobby at **netplay.retcomm.net**
(WebSocket control plane). Match **UDP pad traffic** for online rooms uses an
**SFU star** (selective forwarding unit on the lobby server): every peer sends
to the SFU; the SFU fans out to other seats. Peers do **not** mesh each other
for game data online.
Current lobby policy prefers **always SFU** for online starts so CGNAT /
asymmetric NAT does not strand players on failed ICE attempts.
### ICE + TURN
**ICE** (with **TURN** relay via the project’s coturn on
`netplay.retcomm.net`) remains part of the stack for discovery,
signaling, and fallbacks. With `PSX_NETPLAY=ON`, `runtime.cmake` defaults
`RNET_ENABLE_ICE=ON` (libjuice) before adding `recomp-net`. Pass
`-DRNET_ENABLE_ICE=OFF` only for LAN-only / no-FetchContent builds.
“Force TURN” in the UI can raise delay floors for relay-heavy paths; it
does not replace the SFU online architecture above.
### LAN / Direct IP (P2P star)
Without a lobby start (LAN or Direct IP):
- **2 players:** peer-to-peer UDP.
- **3+ players:** **host-as-relay** local star — the session host fans out
tips to other seats (same star shape as online SFU, but the game host is
the hub).
Sim authority: pad **slot 0** is the session host (`START`, state transfer).
Guests rearrange among seats **1..N−1**.
---
## Multitap + seat ceiling
| Item | Value |
|------|--------|
| Library / lobby / UI ceiling | **8** seats (`RNET_MAX_SLOTS`, dual SCPH-1070) |
| Per-title cap | `game.toml` `players` / `PSX_MAX_PLAYERS` (e.g. MotK=2, Bomberman Party=5) |
Rollback and delay-sync both carry multitap pad bytes. Offline and netplay
share the same multitap arming rules (game-started gate, `multitap_port` in
`game.toml`). Empty tap seats are fine — not every slot needs a device.
---
## Disc identity for multi-track titles
Netplay is **dump-strict** for titles that declare it. Peers must run the
**same playable image geometry**, not “any USA ISO.”
Typical `[netplay]` in `game.toml` (MotK example):
```toml
[netplay]
require_cue = true
required_tracks = 17
# optional: required_disc_fp = "…" # TOC fingerprint
```
| Rule | Why |
|------|-----|
| Prefer / require **`.cue` + sibling `.bin` track files** | Multi-track Redump layout (data + XA/audio) |
| Exact **track count** when `required_tracks > 0` | Track-01-only dumps desync CDDA/XA vs full cues |
| Reject bare incomplete mounts when `require_cue` | Cue→bin fallback cannot invent missing tracks |
| Optional **TOC fingerprint** (`required_disc_fp`) | Same track count still wrong dump |
Generate & rebuild / prepare flows should point at the **`.cue`**, not a lone
`.bin`. See [`config_schema.md`](config_schema.md) and the release checklist in
[`GAME_PROJECT_SETUP.md`](GAME_PROJECT_SETUP.md).
---
## Related product pieces
- **Lobby UI** (recomp-ui): host/join, room settings, rollback toggles, FORCE
TURN, player names — only when `PSX_NETPLAY` is on and the title advertises
netplay.
- **VERSION / lobby match pin:** peers should run the same release pin so
generated code and protocol stay compatible.
- **Mods:** netplay launches prefer a vanilla / synced mod plan (title-specific;
see launcher `commit_netplay` hooks).
---
## Enabling for a new title
1. Vendor or submodule `recomp-net` under `psxrecomp/lib/recomp-net` (or set
`RECOMP_NET_ROOT`).
2. Before `include(runtime.cmake)`: `set(PSX_NETPLAY ON CACHE BOOL … FORCE)`.
3. `psxrecomp_add_game_runtime(… ENABLE_NETPLAY_IF_PRESENT …)` with
`MAX_PLAYERS` / `game.toml` `players` set correctly.
ICE (libjuice) defaults ON with `PSX_NETPLAY`; override with
`-DRNET_ENABLE_ICE=OFF` if needed.
4. Fill `[netplay]` disc gates for multi-track games.
5. Test LAN 2P, then online lobby; soak rollback + FMV if the title uses media.
This document will grow as N-way rollback confirmation, SFU soak on 5P titles,
and further ICE/SFU policy land.