Skip to content

Conversation

@nchapman
Copy link
Collaborator

@nchapman nchapman commented Dec 13, 2025

Fixed #70.

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.
Copilot AI review requested due to automatic review settings December 13, 2025 03:33
Copy link

Copilot AI left a 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.

@nchapman nchapman merged commit d6f4b7a into develop Dec 13, 2025
4 checks passed
@nchapman nchapman deleted the feature/pace-the-frames branch December 13, 2025 03:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement frame pacing for non-60Hz displays (M17 72Hz issue)

2 participants