Skip to content

ADR 0004 — v1.2.0: Public 6502 library, per-cycle accuracy, nessy carve-out

  • Status: Accepted
  • Release: v1.2.0 (2026-05-29)
  • Theme: Promote the shared core to a public library with a semver contract; reach cycle accuracy for the NES path; split nessy into its own repo.

D1 — Promote the 6502 core out of internal/ into public packages

  • Context: the future standalone nessy repo can't import internal/.
  • Decision: move cpu / dap / symbols / peripheral / expr / loader / trace to public top-level paths; keep internal/tui (chippy-only) and internal/nes (nessy-only) private. Document a stability/semver contract (docs/api.md): cpu.Bus/Peripheral/Ticker/Variant are the major-version contract types.
  • Consequences: third parties + nessy can pin the library; bare vX.Y.Z tags become library semver. The opcode-init lex-order invariant (ADR 0001 D2) is preserved through the move.

D2 — Per-cycle CPU↔PPU interleave for VariantNES (Mesen2 master-clock model)

  • Context: instruction-stepped timing can't pass the Blargg/nesdev accuracy ROMs (vbl/NMI races, sub-cycle DMA, frame-counter).
  • Decision: for VariantNES, Step runs in lockstep — every bus access ticks the chain one cycle (PPU 3 dots / APU / cart) before the access, with the 6502's dummy cycles per addressing template; ported Mesen2's ProcessPendingDma, the branch IRQ-poll quirk, and the NTSC frame-counter intervals. NMOS/CMOS keep the instruction-stepped batch tick (byte-identical).
  • Consequences: all NES accuracy ROMs pass. Because this path is VariantNES-gated and that variant disables decimal, later NMOS per-cycle bus-trace validation force-enables the path on VariantNMOS (ADR 0008 D4). The per-cycle path also asserts an exact tick budget — a constraint every later per-cycle change honors.

D3 — Carve nessy into its own repository

  • Context: with the public API stable, the monorepo's NES code is dead weight for a 6502-library consumer.
  • Decision: carve internal/nes + cmd/nessy* into github.com/nkane/nessy (git history preserved via filter-repo, nessy-v* tags → v*). chippy keeps only the library + TUI debugger.
  • Consequences: chippy is a clean general 6502 library; nessy depends on it. v1.2.0 is the last release with nessy in-tree.

D4 — Accuracy ROM harness with knownFail gating

  • Decision: a rolling accuracy tracker runs Blargg/nesdev ROMs in CI, gating regressions; a ROM is knownFail until fixed, then becomes a hard gate.
  • Consequences: the model chippy later reuses for its own CPU corpora (Klaus interrupt, AllSuiteA, Lorenz, Tom Harte — ADR 0008 D4).