Gade SDL
March 14, 2026 · View on GitHub
Gade SDL
A SDL front end in Ada for Gade, intended as a minimal, easily portable reference implementation.
Usage
Build
This setup has been tested on MacOS 12 (Intel) and MacOS 26 (Apple Silicon) so far.
Build using Alire:
alr build
This should install the required Gade and SDLAda dependencies, along with the SDL2 libraries if your system has an Alire supported package manager.
The executable is generated at bin/gade.
Run
bin/gade [options] [rom_file]
If rom_file is omitted, the app starts and waits for a ROM to be dropped on the window.
Options
-u,--uncapped: run without frame-rate cap.-l=<level>,--log=<level>: SDL log priority (for exampledebug,info,warn,error).-h,--help: show help.
Examples
bin/gade path/to/game.gb
bin/gade --uncapped path/to/game.gb
bin/gade --log=debug path/to/game.gb
Controls
Z: AX: BEnter: StartBackspace: SelectArrow keys: D-PadSpace: Fast-forward (hold)
Audio Pipeline
The front end uses a form of Dynamic Rate Control to sync the audio to the video.
Runtime.Main_Loopproduces emulator audio in chunks (Producer_Chunk_Samples), insideGenerate.- It calls
Audio.IO.Queue_Asynchronouslyto hand off each chunk. Audio.IO.Queue_Asynchronouslywrites rawStereo_Sampledata intoSource_Ring(Buffers.Transactional_Ring.Transactional_Ring_Buffer).Audio.IO.Resampling_Taskruns concurrently:- reads from
Source_Ring, - computes fill error from
Output_Ringlevel (Audio.Callback.Level), - applies PI-based dynamic rate control (PID without the D/derivative: Proportional_Gain, Integral_Gain, clamped by
Max_Delta), - resamples via
Audio.Resampler(cubic interpolation), - writes float stereo frames into
Output_Ring(another transactional ring).
- reads from
Audio.Callback.SDL_Callbackis consumer-only:- drains output Ring into SDL’s output buffer,
- writes silence for any remainder (underrun protection).
So the data flow is:
flowchart LR
A[Main Loop<br/>Generate audio chunks] -->|Integer Samples| B
B[Source Ring<br/>Transactional Ring Buffer]
B --> C[Resampling Task<br/>PI-based Dynamic Rate Control]
C -->|Float Samples| D[Output Ring<br/>Transactional Ring Buffer]
D --> E[SDL Callback]
E --> F[SDL Audio Device]
D -- Output Ring Fill --> C