OXYGENHUB

SPEC: make conform-only a first-class adoption path; concrete Agon /regs shape 42c217d9aaf7

The FAB Agon emulator is Rust and conforms to the contract directly rather than
vendoring the C core. Document both adoption paths and add a concrete ADL /regs
example; conformance/ is the arbiter either way.

Git-Commit: 79c2f15dcc0193cf7415fcbb67a934a470bac4ac
Git-Author: Andy McCall <[email protected]>
Author
Andy McCall @andymccall <[email protected]>
When
· 2026-07-19 18:44 UTC
Signature
◈ sealed by Andy McCall
Hash
42c217d9aaf726fb8b0c38482e4b340e9257b19614b6c16006581b269ee42b2b
Depends on
961b3c610c66
Depended on by
67065eaa1a13 674b8447022b d44319b1e712
In bookmarks
main perf-6
Edits
6 atoms, 0 tree operations, 1 file

Browse the tree at this change

modified SPEC.md +29 −9
…
143 unchanged lines
144 144
- Framebuffer: native resolution per the emulator's video mode.
145 145
146 146
### Agon (Console8 / Light 2) — FAB Agon Emulator
147 +
- **Adoption:** conform-only (Rust emulator — keeps its own HTTP server, matches
148 +
  this contract rather than vendoring the C core).
147 149
- Flag: `--control-port <N>`.
148 150
- Address space: eZ80 24-bit, flat 16 MB (`addr` up to `0xFFFFFF`); `bank`
149 -
  ignored. Program load base `0x040000`.
150 -
- Registers (ADL): `af bc de hl ix iy sp pc mbase` + ADL-mode flag.
151 -
- Framebuffer: from `vgabuf` (the VDP output), server swizzles to PPM RGB.
151 +
  tolerated and ignored. Program load base `0x040000`.
152 +
- Registers (ADL) — `/regs` example (16-bit regs; `mbase` 8-bit; `adl` 0/1):
153 +
  ```json
154 +
  { "af":0, "bc":0, "de":0, "hl":0, "ix":0, "iy":0,
155 +
    "sp":0, "pc":262144, "mbase":0, "adl":1 }
156 +
  ```
157 +
- Framebuffer: from `vgabuf` (the VDP output); the offscreen path already keeps
158 +
  video alive (the FAB equivalent of x16's `SDL_VIDEODRIVER=dummy`).
152 159
153 160
---
154 161
155 -
## Reference implementations in this repo
162 +
## Adoption paths
156 163
157 -
- `core/retro_control.h` — the portable backend vtable each fork implements.
158 -
- `core/retro_control.c` — the shared server (socket loop, HTTP parse, PPM/JSON
159 -
  encode, command marshalling). Forks vendor/submodule this and call
160 -
  `retro_control_start(port, &backend)`. *(server .c lands next.)*
164 +
An emulator conforms by exposing exactly the HTTP surface above — nothing else
165 +
is required. Two ways to get there:
166 +
167 +
- **Vendor the shared core** (`core/retro_control.c` + `.h`) — for C/C++
168 +
  emulators. Implement the four backend callbacks, wire three loop hooks, call
169 +
  `retro_control_start(port, &backend)`; the socket loop, HTTP parsing, PPM/JSON
170 +
  encoding and pause/step control come for free. The Commander X16 fork does this.
171 +
- **Conform directly** — for emulators in other languages (the FAB Agon emulator
172 +
  is Rust). Keep your own HTTP server; just match the contract and pass the
173 +
  conformance suite. Sharing the C core is an optimization, not a requirement —
174 +
  the contract is the asset.
175 +
176 +
Either way, `conformance/` is the arbiter: pass it and you conform.
177 +
178 +
## In this repo
179 +
180 +
- `core/retro_control.{c,h}` — portable server + backend vtable (vendor path).
161 181
- `client/emu_control.py` — the shared pytest client.
162 -
- `conformance/` — tests an emulator runs to prove it conforms. *(next.)*
182 +
- `conformance/` — a platform-agnostic pytest that proves an emulator conforms.