mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
7a786f8e84
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>
83 lines
4.0 KiB
Markdown
83 lines
4.0 KiB
Markdown
# Frame rate: presentation above the guest's cadence
|
|
|
|
A game-owned mod can present a PS1 title at a higher rate than it renders
|
|
(60, 120, 240 Hz, the display's refresh, ...) without changing how fast the
|
|
game runs. Guest VBlanks, timers, CD, SPU and game logic stay at their stock
|
|
cadence; only what the OpenGL presenter shows between guest VBlanks changes.
|
|
Never use `psx_mod_set_native_vblank_rate` for this: it speeds up the whole
|
|
machine.
|
|
|
|
## Enabling it (mod_plugins.h)
|
|
|
|
From a trusted plugin's activation callback:
|
|
|
|
```c
|
|
psx_mod_set_frame_interpolation_source(PSX_MOD_FRAME_SOURCE_FLIP); /* optional */
|
|
psx_mod_set_frame_interpolation_blend(PSX_MOD_FRAME_INTERPOLATION_LINEAR);
|
|
psx_mod_set_frame_interpolation(120); /* 0 = follow the display refresh */
|
|
```
|
|
|
|
`psx_mod_set_frame_interpolation` accepts 0 or 60..1000, selects the OpenGL
|
|
renderer and turns vsync off (the presenter paces itself with a sleep+spin
|
|
schedule on the emulation thread). Blend and source are reset to their
|
|
defaults at every session start (first boot and the lobby rematch), so a
|
|
netplay session or a later offline one never inherits them.
|
|
|
|
Because the presenter owns vsync while it runs, the mod's manifest declares
|
|
`vsync = "off"` on the feature (format 11, docs/MOD_PACKAGES.md): the
|
|
launcher then shows its VSync row overridden by that feature instead of a
|
|
choice that would not apply. A feature that does not declare it is named on
|
|
stdout the first time its activation forces vsync off.
|
|
|
|
The presenter uses the high-resolution host timer for microsecond waits,
|
|
leaving only a short final spin for scheduling jitter. Whole-millisecond
|
|
waits previously spent up to almost two milliseconds spinning per output,
|
|
which could starve game execution on a CPU-constrained host at high refresh.
|
|
The presentation deadlines and guest cadence remain unchanged.
|
|
|
|
## Blend modes
|
|
|
|
| Mode | Output between two source frames |
|
|
|---|---|
|
|
| `LINEAR` (default) | crossfade `mix(prev, cur, a)` |
|
|
| `MOTION_ADAPTIVE` | crossfade small changes, switch large changes at a = 0.5 |
|
|
| `HOLD` | no crossfade: repeat the newest frame (for titles whose plugin supplies in-between images with render passes) |
|
|
|
|
Blending never invents motion: moving objects ghost, and the image is one
|
|
source frame behind the newest one. True in-between frames need the game's
|
|
own draw code: see [RENDER_PASSES.md](RENDER_PASSES.md).
|
|
|
|
## Blend source: every VBlank or real flips
|
|
|
|
The presenter plans one output schedule per guest VBlank present.
|
|
|
|
- `PSX_MOD_FRAME_SOURCE_VBLANK` (default, and the historical behaviour):
|
|
every guest VBlank is a new source frame. Right for games that flip every
|
|
VBlank.
|
|
- `PSX_MOD_FRAME_SOURCE_FLIP`: a VBlank is a new source frame only when the
|
|
game really flipped -- the displayed VRAM origin moved, or the displayed
|
|
rect was redrawn. The presenter tracks the flip period P (VBlanks between
|
|
flips, clamped 1..4) and gives VBlank k after a flip the blend window
|
|
[k/P, (k+1)/P], so one crossfade spans the whole game frame. A 30 Hz game
|
|
(P = 2) would otherwise blend for one VBlank and hold for the next. A frame
|
|
that arrives late holds at a = 1; one that arrives early restarts from the
|
|
frame that was fully shown.
|
|
|
|
`gl_interp` (TCP) reports `source`, `flip_period`, `captures` (new frames)
|
|
and `duplicates` (VBlanks that re-presented the same frame); a 30 Hz game in
|
|
FLIP mode shows about 30 captures and 30 duplicates per second.
|
|
|
|
## Limits
|
|
|
|
- OpenGL only; a command-line `--renderer` override after activation drops
|
|
it. Netplay sessions run without mods, so without interpolation.
|
|
- FMV (MDEC / 24-bit) frames suspend it, as does rewind.
|
|
- Vsync is off: on a fixed-refresh panel pick the display refresh rate.
|
|
|
|
Tests: `frame_interpolation_schedule_test` (runtime ctest) covers the phase
|
|
windows, the flip tracker, the new-frame decision and output counts per rate
|
|
at 30 Hz. `frame_interpolation_flip_source` (source guard, recompiler ctest)
|
|
pins the wiring no unit test reaches: the session-start hand-off of the
|
|
source to the renderer, and `interp_capture`'s FLIP branch (origin and redraw
|
|
into the decision, an early return on a duplicate).
|