ADR 0008 — v1.5.0: DAP onramp, complete CPU ROM coverage, host debug hooks¶
Status: Accepted
Release: v1.5.0 (2026-06-11; epics #402 multi-target DAP onramp + complete CPU ROM coverage, #419 host debug hooks)
Theme: Derisk the v2.0 TUI-via-DAP architecture, fuzz the CPU against every standard corpus, and expose opt-in hooks a downstream emulator builds a Mesen-class debugger on.
Context: the local TUI-as-DAP-client case (v2.0) needs zero-overhead transport; the server was already io.Reader/Writer-based.
Decision: unix-socket is just another net.Conn (-dap unix:PATH). The new piece is inproc: all server sends funnel through writeJSON, which consults an optional sink func(any); when set, Response/Event structs go straight to an InprocClient instead of being marshalled. NewInprocServer() + InprocClient.Request dispatch directly. Nil-args requests + all responses round-trip with zero serialization.
Consequences: inproc stepIn ≈ 0.34 µs vs ~30 µs over unix (~90×). The foundation for D2.
D2 — TUI panels read via DAP (Registers panel PoC)¶
Decision: the Registers panel renders from m.Regs (RegSnapshot), sourced by Source.Registers() over a single DAP variables round-trip — never direct cpu.CPU field access. LocalSource owns an in-process DAP server (D1) attached to the same CPU/RAM, so local mode reads through DAP too; RemoteSource reuses its wire client. Pattern written up in docs/dap-tui-migration.md.
Consequences: proves the v2.0 direction one panel at a time. Migrating the remaining panels (stack/flags/memory/disasm) is deferred to v2.0.
Decision: a server→client custom event pushed during a remote free-run (regs + a reserved dirtyRanges), throttled to 60 Hz in the run loop. The TUI updates m.Regs from it and skips polling when remote+running. Additive per the Mesen/DAP-extension convention — standard clients ignore unknown events.
Consequences: a remote run is event-driven, not per-frame polling. Streaming changed memory (dirtyRanges) is the v1.6 follow-up #440.
D4 — Complete CPU ROM coverage; reframe Visual6502 → Tom Harte bus traces¶
Decision: wire every standard 6502 corpus on the download-or-vendor pattern (ADR 0001 D11): AllSuiteA (sha-pinned), Wolfgang Lorenz CPU subset (vendored .prg + KERNAL-trap harness), Klaus interrupt (ca65 port — upstream ships as65 source only, with an active-low/-high feedback-port harness), Tom Harte ProcessorTests (256 opcodes × ~10k cases, state + cycle count). For the Visual6502 "per-cycle bus trace" goal, reframe to comparing chippy's per-cycle bus activity against Tom Harte's cycles field (~100× the coverage, no manual sourcing) — force-enable the per-cycle path (ADR 0004 D2) on VariantNMOS (so decimal stays intact) and record every Bus.Read/Write.
Consequences: 228/238 opcodes match bus-exact. Found + fixed a real JSR $20 stack/operand-overlap bug. Skip-listed: 12 JAM/KIL + 6 unstable illegals (state) + 10 per-cycle branch/JSR/RTS bus quirks (#428) + ARR-decimal (#424) + 65C02 (#426) → v1.6. Each corpus is its own CI job.