-
Notifications
You must be signed in to change notification settings - Fork 0
Add comprehensive frame pacing support #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Adds Bresenham-style frame pacing to decouple emulation from display refresh rate. Handles any mismatch: 60fps on 72Hz (M17), 50fps PAL games on 60Hz displays, etc. Core algorithm (frame_pacer.c): - Q16.16 fixed-point accumulator (no float drift) - Direct mode bypass for mismatches ≤2% (handled by audio rate control) - 2% tolerance based on RetroArch rate control research (Arntzen 2012) Platform API additions: - PLAT_getDisplayHz() - returns panel refresh rate - PLAT_measureVsyncInterval() - for future adaptive measurement - PLAT_clearBlit() - switches from game to UI rendering mode Also refactors M17 platform.c to use shared render_sdl2 backend.
Dual-mode audio/video synchronization with compile-time selection:
Vsync mode (default):
- Frame pacing via Bresenham accumulator
- Dual-timescale PI audio rate control
- Non-blocking audio writes
Audioclock mode (M17):
- Audio hardware clock drives timing
- Blocking audio writes (up to 10ms when buffer full)
- No frame pacing or rate control needed
Changes:
- Add minarch_loop_{vsync,audioclock}.inc with mode-specific main loops
- Dual SND_batchSamples() implementation in api.c
- Increase SND_CHUNK_SAMPLES 256→512 (benefits all platforms)
- Enable audioclock mode for M17 via -DSYNC_MODE_AUDIOCLOCK
Fixes audio stuttering on M17 where unstable vsync caused underruns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds comprehensive frame pacing support to decouple emulation timing from display refresh rates, enabling smooth gameplay on devices with non-60Hz displays (e.g., M17's 73Hz panel). It introduces two sync modes: vsync-driven with Bresenham-style frame pacing (default) and audio-driven timing (for unstable vsync devices like M17).
Key changes:
- New frame pacing system using Q16.16 fixed-point arithmetic to avoid floating-point drift
- Two compilation modes: vsync-driven (default) with frame repeats for non-matching Hz, and audioclock mode (SYNC_MODE_AUDIOCLOCK) with audio hardware timing
- M17 platform refactored to use shared render_sdl2 backend and configured for audioclock mode due to unstable vsync
Reviewed changes
Copilot reviewed 32 out of 32 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| workspace/all/minarch/frame_pacer.h | Frame pacer API with Q16.16 fixed-point Bresenham algorithm |
| workspace/all/minarch/frame_pacer.c | Frame pacer implementation with direct mode bypass and accumulator logic |
| workspace/all/minarch/minarch_loop_vsync.inc | Vsync-driven main loop with frame pacing (default mode) |
| workspace/all/minarch/minarch_loop_audioclock.inc | Audio-driven main loop with blocking writes (SYNC_MODE_AUDIOCLOCK) |
| workspace/all/minarch/minarch.c | Updated to use conditional compilation for sync modes, added frame pacer state |
| workspace/all/minarch/minarch_cpu.c | Added scaling_disabled flag to skip CPU scaling on single-frequency devices |
| workspace/all/minarch/minarch_cpu.h | Added scaling_disabled field to CPU state |
| workspace/all/common/api.c | Added audioclock mode with blocking audio writes and fixed 1.0 resampling ratio |
| workspace/all/common/api.h | Added PLAT_getDisplayHz and PLAT_measureVsyncInterval API declarations |
| workspace/all/common/defines.h | Increased audio chunk size from 256 to 512 samples for more stable timing |
| workspace/all/common/render_sdl2.c | Added clearBlit, getDisplayHz, and measureVsyncInterval implementations |
| workspace/all/common/render_sdl2.h | Added function declarations for new SDL2 rendering functions |
| workspace/m17/platform/platform.c | Refactored to use render_sdl2 backend, returns 73.0 Hz for display rate |
| workspace/m17/platform/platform.h | Corrected display specs (273→272 height, 7.0→4.3 diagonal) |
| workspace/m17/platform/makefile.env | Added SYNC_MODE_AUDIOCLOCK flag for unstable vsync |
| workspace/m17/README.md | Updated hardware specs and added exFAT filesystem requirement |
| workspace/desktop/platform/platform.c | Added clearBlit, getDisplayHz (60.0), and measureVsyncInterval (returns 0) |
| workspace/zero28/platform/platform.c | Added clearBlit, getDisplayHz, and measureVsyncInterval using SDL2 backend |
| workspace/tg5040/platform/platform.c | Added clearBlit, getDisplayHz, and measureVsyncInterval using SDL2 backend |
| workspace/rgb30/platform/platform.c | Added clearBlit, getDisplayHz, and measureVsyncInterval using SDL2 backend |
| workspace/rg35xxplus/platform/platform.c | Added clearBlit, getDisplayHz, and measureVsyncInterval using SDL2 backend |
| workspace/rg35xx/platform/platform.c | Added clearBlit, returns 60.0 Hz, implements ioctl-based vsync measurement |
| workspace/my355/platform/platform.c | Added clearBlit, getDisplayHz, and measureVsyncInterval using SDL2 backend |
| workspace/my282/platform/platform.c | Added clearBlit, getDisplayHz, and measureVsyncInterval using SDL2 backend |
| workspace/miyoomini/platform/platform.c | Added clearBlit, returns 60.0 Hz, implements SDL_Flip-based vsync measurement |
| workspace/magicmini/platform/platform.c | Added clearBlit, getDisplayHz, and measureVsyncInterval using SDL2 backend |
| workspace/trimuismart/platform/platform.c | Added clearBlit, returns 60.0 Hz, implements ioctl-based vsync measurement |
| tests/unit/all/common/test_frame_pacer.c | Comprehensive unit tests for frame pacing algorithm (385 lines, 24 tests) |
| tests/unit/all/common/test_minarch_cpu.c | Added tests for scaling_disabled scenarios |
| workspace/all/minarch/makefile | Added frame_pacer.c to build |
| makefile.qa | Added frame_pacer_test to test executables |
| skeleton/BASE/README.md | Added exFAT filesystem requirement for M17 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fixed #70.