OXYGENHUB

No emulator implements the SPEC's boot-paused option, so early scenes cannot be tested issue #4 open andymccall opened this · 0 comments

andymccall

Summary

SPEC §POST /pause says:

A machine launched with a --control-pause-style option SHOULD boot paused so tests are deterministic.

Neither of the two emulators I can check implements one. Checked both argument parsers directly:

  • neo6502-firmware/emulator/src/core/sys_debugger.cpp:116 — DBGSaveArguments recognises scale= and rrdcport=. Nothing else.
  • x16-emulator/src/main.c:721 — -controlport <N>. No pause variant.

The consequence is that any scene shorter than the emulator's startup latency cannot be observed by a test at all.

Measured

Frame reported by GET /status at the moment the control port first answers, from a harness that connects as fast as it can:

Emulatorframe at first answer
Neo6502 (neo)~230
x16emu~98

My splash scene holds for 180 frames. On the Neo it has therefore always finished before a test can look at it — I have never once caught it live. On the X16 it is usually still up, but "usually" is not something to build a suite on.

Confirmed the machines really are free-running rather than merely reporting oddly:

status: {'contract': '0.5.0', 'emulator': 'neo', 'platform': 'neo6502',
         'frame': 230, 'paused': False, 'running': True}
frame 230 -> 292 after 1s  => FREE-RUNNING

Why the obvious workarounds do not cover it

  • POST /reset then step. Works on the Neo, which re-runs the loaded program from its entry point. Does not work on the X16: reset returns the machine to its own ROM (the BASIC READY. prompt), because -prg/-run apply at launch only. Verified — reset plus 600 stepped frames produced the BASIC banner and nothing else.

  • Connect faster. Shrinks the window, never closes it, and makes the suite sensitive to host load, which is the specific thing frame-addressable stepping exists to eliminate.

  • Cumulative state mirrors. What I actually did, and it works for state: a scenes_seen bitmask plus an enter/exit frame pair lets a test assert the splash happened and held for exactly its configured 180 frames, from a connection made 50 frames too late to watch it.

    It does not work for pixels. There is no way to screenshot a scene that is already over, so my splash's appearance is asserted by no test at all — it is covered by committed screenshots and by eye, and recorded as a known gap.

Suggested shape

A flag that sets the paused state before the first frame runs, so the sequence is: launch → machine paused at frame 0 → harness connects → /step from a known zero.

Naming: the SPEC says --control-pause, but neither emulator uses SPEC-style long options for the port either — the Neo takes rrdcport=<N> and x16emu takes -controlport <N>. So a flag matching each emulator's existing convention (rrdcpause=1, -controlpause) is probably more honest than making these two the only SPEC-conformant options in their parsers. Worth deciding here rather than per-fork.

Related and smaller: the SPEC documents --control-port <N> and the Neo emulator rejects that form, accepting only rrdcport=<N>. galaga-neo carries a note about this too. Either the SPEC or the emulator should move; right now every consumer hard-codes the divergence.

Who this affects

Every port's ability to test its earliest scenes — splash screens, boot sequences, anything that runs and finishes inside the first few hundred frames. contagion hit it on two platforms at once, which is the only reason it looked like a contract gap rather than a quirk of one emulator.


Imported from GitHub #8, opened by andymccall on 2026-08-03.

andymccall referenced by change 724e0ab8c620 on main ·