Code organisation

Where things live, what each package owns, and how the pieces build. Module path: github.com/stever/zxplay_go. Roughly 145k lines of Go across cmd/ and pkg/ (tests included; test code is close to half of it by volume).

Top level

cmd/zxplay_go/        all three surfaces + machine assembly + debugger backend
pkg/              the emulator proper (see below)
docs/             user docs + this architecture documentation
fuse/             vendored FUSE 1.6.0 source, cross-reference only
_tools/           GHDL testbenches and diff tooling (golden-vector capture)
roms/next/        user-installed licensed Next ROMs + SD content (gitignored)
LICENSES/         GPLv3 text + notice for the embedded tbblue_loader.rom

Key top-level documents: README.md, ROADMAP.md (state + backlog + invariants), VHDL_CONFORMANCE.md, DEBUGGER.md, CONTRIBUTING.md, COMPARISON.md, CHANGELOG.md.

cmd/zxplay_go

One package main holding the machine assembly and every surface.

AreaFilesNotes
Entry pointsentry_desktop.go, entry_js.go, gui_js.goBuild-tag split. main() is one line per tag.
Desktop GUIgui_desktop.go, main.goemulator struct (the machine assembly), run() frame loop (20 ms ticker), Fyne menus, CRT filter.
Headlessheadless.go, flags.go, debug.gorunHeadless, all --headless instrumentation, press-key scheduling, watchpoints, crash detect.
wasmwasm_js.go, wasm_debug_js.goEvery js.FuncOf export; the debug bridge.
Next assemblynext.go, next_directboot.go, fastboot.go, nexload_macro.go, warmboot.goWires pkg/next/* into the machine, boot paths, menu-typing macros.
Debugger backenddebugger.go + *_cmd.go filesremoteDebugger, handleCommand (single dispatch for GUI/telnet/wasm), time-travel, provenance, bisect, crash detect.
Dev diff modesbisect.go, lockstep/nrdiff/memdiff code pathsOurs-vs-reference divergence hunting.

pkg — core execution

PackageOwnsKey symbols
pkg/z80Z80/Z80N CPUCPU (z80.go), executeBaseInstruction and the prefix switches, z80n.go (Z80N ops), ExecuteFrame, StepInstructionWithIRQ, hook registries (AddPreFetchHook...), Variant, NextRegSink.
pkg/memorybanks, paging, contention, overlaysMemory, PageMemory ($7FFD), PageMemoryPlus3 ($1FFD), SetMMU/syncMMUFromPage, readValue/Write (the priority mux), ContendMemory/ContendPort, next.go (bootrom, config mode, Alt-ROM, Layer 2 paging, divMMC accessor).
pkg/ulaI/O hub, classic video, tape, audio eventsULA, ReadPort/WritePort (dispatch chains), Render, TapePlayer (tape.go, tzx.go), BeamPosition/ActiveVideoLine, the consumer-site Next interfaces (NextCompositor, NextDMA, NextDAC, BetaDisk, ...), dcblock.go.
pkg/keyboardkey matrixKeyboard, Scan, HandleKeyWithModifiers, TypeRune (layout-independent symbols), UseZX8xLayout, JSON overrides.
pkg/audiooutput pipelineAudioSystem, ring buffer (882 samples/frame), oto reader (desktop), PullMono (wasm), WAV recording, keep-alive.
pkg/ayAY-3-8912 / YM2149AY (FPGA ym2149.vhd port), Engine (3-chip Turbosound bank), measured volume tables.
pkg/audiodacSpecDrum/CovoxDAC, event-timed GenerateFrame.
pkg/romsembedded ROMs + model constants//go:embed data/*, ROMManager, SpectrumModel, FrameTStates().

pkg — machine stacks

PackageOwns
pkg/next/*The Spectrum Next. Children: nextregs (dispatcher), layer2, tilemap, sprite, lores, palette, compositor, copper, dma, ctc, divmmc, esxdos, sdcard, nex, rtc, uart, dac, keymap, mouse (Kempston mouse counters, $FADF/$FBDF/$FFDF), install. Umbrella files: wire.go (all NextReg wiring), nrdecode.go (the FPGA read-mux table + zero-reads for undecoded registers), im2.go (IM2 daisy-chain), im2block.go (hardware-IM2 vectored mode, NR$C0 bit 0: routes frame/line/CTC sources into the chain, supplies the generated vector at IM 2 acknowledge, ED 4D end-of-interrupt), inttiming.go + geometry.go (frame INT timing and the full per-NR$03/$05 frame-geometry table; WireFrameGeometry in wire.go pushes retunes live — #182), ctcblock.go (the four live CTC channels: port decode, NR$C5, pulse-mode INT line via z80.CPU.ExtIntFunc), mf.go (the Multiface enable/disable port pair driving the GHDL-golden pkg/multiface.Core). See next-fpga.md.
pkg/peripheralsPeripheralManager: one optional instance of each classic device, port-claim priority chain, the $0000-$3FFF overlay precedence (IF2 → Multiface → DISCiPLE → IF1).
pkg/plus3fdcµPD765A FDC + all disk image parsers (DSK/EDSK/UDI/MGT/IMG/SAD/TRD/D40/D80 readers live here and are reused by other controllers).
pkg/betadiskWD1793 + Beta interface + .TRD images. TR-DOS ROM auto-paging itself lives in pkg/memory (BetaPreFetch).
pkg/discipleMGT DISCiPLE: WD1772, GDOS ROM/RAM overlay, format-stream parsing.
pkg/if1, pkg/microdriveInterface 1 shadow-ROM traps + microdrive tape-loop model; .mdr cartridge format.
pkg/if216K ROM cartridge slot.
pkg/multifaceMF1/128/3: multiface.go (integration model) and core.go (clock-exact FPGA multiface.vhd transcription).
pkg/kempmouse, pkg/zxprinterKempston mouse; ZX Printer with cycle-accurate drum timing.
pkg/zx8xZX80/ZX81: CPU-generated display, R-bit-6 INT, SLOW-mode NMI, .P/.O loading.
pkg/sam, pkg/saa1099SAM Coupé ASIC (4 modes, line-accurate lazy renderer, ASIC contention tables, WD1772) and the SAA1099 sound chip.

pkg — formats and support

PackageOwns
pkg/snapshot.sna/.z80/.szx load and save, in-memory codecs for RZX embedding.
pkg/rzxRZX recording/playback (instruction counts + IN byte stream = determinism), autosave tiers, competition mode, DSA/SHA-1 signing (format-mandated).
pkg/debuggerVisual debugger widgets (//go:build !js) plus fyne-free core types: BreakpointSet (lock-free copy-on-write map), provider interfaces, bank access.
pkg/testharnessDeterministic scripted machine for integration tests: New(model), RunFrames, PressKey, ScreenText() (screen OCR), RunUntilText; next.go builds a full Next.
pkg/traceStructured event emitter behind --trace (JSON lines; no-op when disabled).
pkg/zxlogslog-based console formatting + banner.
pkg/configPersisted user settings (desktop only).
pkg/versionBuild metadata.

Test layout conventions

Build system