Reference Implementation (x16emu)
The Commander X16 fork is the worked example every other port can copy. It's a
minimal, self-contained integration of the shared core, now at contract 0.5.0
(all fourteen 0.1–0.5 callbacks). The enhanced X16 emulator follows the
same shape and adds 0.6's /perf (see the end of this page).
What was touched
src/control/retro_control.{c,h}— the shared core (vendored; convert to a submodule once stable — do not edit the copy).src/control_backend.c— the four x16 callbacks:read_mem→debug_read6502(addr, 0, bank)(bank<0 = current).get_regs_json→regs.a/xl/yl/sp/pc/status+memory_get_ram_bank/rom_bank.get_framebuffer→video_get_framebuffer(), formatRETRO_PIX_BGRA8888.get_frame_count→video_get_frame_count().
src/video.c/src/video.h— added accessorsvideo_get_framebuffer()andvideo_get_frame_count()(theframebuffer[]array is file-static).src/main.c— a-controlport Nargument;x16_control_start()before the emulator loop; and the three hooks insideemulator_loop():retro_control_service(), theretro_control_running()gate, andretro_control_on_frame()whenvideo_step()reports a new frame.CMakeLists.txt— the two new sources added toX16_SOURCES(pthread was already linked).
Build
make # CMake ≥ 3.x + SDL2 dev; produces build/x16emu
Run
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
build/x16emu -rom rom.bin -warp -controlport 8080
Verified
All five endpoints pass against a live boot (see the repo's smoke test):
/status→ contract 0.5.0, platformx16/regs→ full register set/mem→ 16 bytes @$0000; banked read @$A000 bank=1/screenshot→ 640×480 RGB PPM/step→ deterministic:step(3)advances the frame counter by exactly 3
Porting to another emulator
Copy the shape of control_backend.c and the main.c hooks. The only real work
is: expose a debug-read, format the registers as JSON, expose the framebuffer +
frame counter, and gate your CPU loop on retro_control_running(). See
Adopting in an Emulator.
The enhanced X16 emulator: contract 0.6
enhanced-x16-emulator vendors the core as an oxy submodule
(src/extern/retro-remote-debug-controller) and ports the fork's backend
(src/control_backend.c), its pads driven through the emulator's own virtual
joysticks. It adds get_perf/set_perf, answered from the measurements its
ImGui Performance panel and DAP x16/perfStats already make; the JSON is
built once (src/perf_json.c) for both. /perf needs cJSON, as DAP does;
without it the backend serves 0.5.
cmake -S . -B build && cmake --build build
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
build/x16emu -rom rom.bin -controlport 8391
Verified: the conformance suite, 27 of 27, the 0.6 tests among them.