Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

The headless debugger

A second, scriptable debugger (src/debugger.rs) is driven entirely by COPPERLINE_DBG_* environment variables and works in any run, including windowless --screenshot-after / --dump-frames captures. It is the main tool for timing and compatibility investigations: because the core is deterministic, a failing run can be replayed with progressively more instrumentation and every replay hits the same cycle.

Output goes through the log crate at info level, so set RUST_LOG=info (or debug) to see it.

RUST_LOG=info \
COPPERLINE_DBG_BREAK=C033C2 \
COPPERLINE_DBG_DUMP=C09580:4 \
COPPERLINE_DBG_SHOT=/tmp/hit \
./target/release/copperline --config copperline.example.toml --noaudio \
  --screenshot-after 30 /tmp/out.png

All addresses are hexadecimal, with or without a 0x prefix. Like every COPPERLINE_* knob, the variables are snapshotted once at startup and cannot change at runtime (see Architecture overview).

Variables

COPPERLINE_DBG_BREAK=PC[,PC...]
PC breakpoints. Each hit logs a DBG BREAK report: emulated time, frame, beam position (v=/h=), SR, PC, the full register file, any DBG_DUMP memory regions, and a screenshot if DBG_SHOT is set.
COPPERLINE_DBG_WATCH=ADDR[:LEN][,...]
Memory watchpoints (LEN in bytes, default 2). Logs when a watched word changes, whoever wrote it: DBG WATCH 0x00c09580 0012->0013 by pc=0x00c03374.
COPPERLINE_DBG_DUMP=ADDR:WORDS[,...]
Memory regions to hex-dump with every break/watch report (mem 0x00c09580: 0000 0001 0002 0003).
COPPERLINE_DBG_TRACE=1
Disassembled per-instruction trace while the debugger window (AFTER/UNTIL) is active, with key registers on each line. Capped at 200,000 lines per run as a flood guard.
COPPERLINE_DBG_TRACE_FULL=1
Like TRACE, but each line is a fixed-width, all-hex record of the entire register file (D0-D7/A0-A7) and the CCR, prefixed ft. Intended for diffing Copperline’s instruction stream against a reference 68000 (e.g. vAmiga) to isolate a mis-emulated instruction. Implies TRACE.
COPPERLINE_DBG_TRACE_LO=ADDR / COPPERLINE_DBG_TRACE_HI=ADDR
Restrict the trace to instructions whose PC is in [LO, HI]. This isolates a single routine (e.g. a depacker loop) and, by excluding interrupt handlers, yields a contiguous deterministic stream that lines up across emulators.
COPPERLINE_DBG_CATCH=SPEC[,SPEC...]
Exception catchpoints. SPEC can be a decimal vector number, vec N, irq N, or trap N; for example, COPPERLINE_DBG_CATCH="3,4,irq 3" reports address errors, illegal instructions, and VERTB interrupt entries.
COPPERLINE_DBG_CATCHALERT=1
Resolve ExecBase once AmigaOS is valid and report when execution reaches exec.library Alert(). Each hit includes the D7 alert code decoded with the same Guru table used by the interactive debugger.
COPPERLINE_DBG_RAMDUMP=ADDR:LEN:FILE
One-shot memory dump the first time the debugger activates: LEN bytes from hex address ADDR are written to FILE, read through the CPU’s own memory decode so chip-RAM mirrors resolve. Combined with AFTER, this captures bitplane or sample data exactly as displayed at a moment in time for offline analysis.
COPPERLINE_DBG_COPPER=auto | ADDR[:COUNT]
One-shot Copper-list disassembly the first time the debugger activates. auto reads the live COP1LC; an explicit address disassembles from there. COUNT defaults to 256 instructions (auto:64 works too).
COPPERLINE_DBG_AFTER=SECS / COPPERLINE_DBG_UNTIL=SECS
Activity window in emulated seconds. Outside the window the debugger is inert, which keeps traces focused and runs fast: combined with determinism, you can binary-search a failure in time.
COPPERLINE_DBG_MAXHITS=N
Stop reporting after N hits (default 200).
COPPERLINE_DBG_SHOT=PREFIX
Save a PNG of the last completed frame on every hit, as PREFIX-0000.png, PREFIX-0001.png, ...

Diagnostic knobs

Beyond the debugger, many subsystems have start-up diagnostic switches. They are read through src/envcfg.rs; grep its call sites for the authoritative list. The most useful ones:

VariableWhat it logs / does
COPPERLINE_DIAG_SLOTMAPPer-colour-clock chip-bus owner map for a frame (Refresh, Bitplane, Sprite, Disk, Audio, Copper, bLitter, cPu, . idle); COPPERLINE_DIAG_SLOTMAP_AT=SECS picks the frame and COPPERLINE_DIAG_SLOTMAP_RANGE=START:END picks printed beam rows
COPPERLINE_DIAG_BLT_SLOTSBlitter slot trace: one stderr line per blitter pipeline cycle (BLTP frame vpos hpos TICK phase bus=0/1), plus per-cck owner lines while a blit is in flight and START/END markers. Formatted for side-by-side diffing against a vAmiga build instrumented with the matching VAMIGA_BLT_PROBE hooks
COPPERLINE_DIAG_IPLCPU cycles spent per interrupt level
COPPERLINE_DIAG_PCSAMPLETop-50 executed-PC histogram every 50 frames
COPPERLINE_DIAG_PCHISTFull PC history (with COPPERLINE_DIAG_PCHIST_START=SECS)
COPPERLINE_DIAG_COPLENCopper list length (optionally at a given emulated time)
COPPERLINE_DIAG_COP_WRITESEvery Copper MOVE’s landing colour clock (beam position, register, value), for cross-emulator write-landing comparison against vAmiga’s VAMIGA_COP_PROBE trace
COPPERLINE_DIAG_CPU_BUSCPU chip-bus access request/grant/end slots for fetch, chip/slow RAM, and custom space; optional COPPERLINE_DIAG_CPU_BUS_ADDR=start:end[,start:end...] filters by CPU-visible addresses including custom registers such as 0xdff01e
COPPERLINE_DIAG_CPU_READSCPU custom-register reads’ granted chip-bus slot and returned value, plus the post-flush beam position; honors the same optional COPPERLINE_DIAG_CPU_BUS_ADDR filter as the bus trace
COPPERLINE_DIAG_CPU_SYNCCPU-internal cycle trace at pre-access sync points and instruction-boundary catch-up; optional COPPERLINE_DIAG_CPU_SYNC_PC=pc[,start:end...] filters by instruction PC
COPPERLINE_DIAG_CPU_WRITESEvery CPU custom-register write’s granted chip-bus slot and effect beam position (register, value), the CPU-side companion of COPPERLINE_DIAG_COP_WRITES for comparison against vAmiga’s VAMIGA_CPU_PROBE trace
COPPERLINE_DIAG_DISPLAYDisplay-register change log
COPPERLINE_DIAG_CAPROW=all, =V, or =START:END: per-line bitplane capture state at DDF start, including DMACON, current and DDF-anchor BPLCON0, FMODE/DIW/DDF, effective fetch window, unit/period/quantum, words/row, modulos, and all BPLxPTs -- separates wrong-pointer from wrong-decode display bugs
COPPERLINE_DIAG_PALETTE_ROW=all, =V, or =START:END: log beam-timed COLOR writes for selected beam lines, including source, framebuffer x, palette entry, LOCT, value, and BPLCON3; the setting is cached after first use
COPPERLINE_DIAG_HAM_PIXELS=BEAMY,X0,X1[,STEP]: sample DMA playfield HAM pixels on one beam line, including framebuffer/native x, selected bitplane index, active/fetched state, HAM hold colour before/after, output latch, plane count, fetched width, BPLCON1 delays, DIW/DDF, and display window; pairs with COPPERLINE_DBG_AFTER / COPPERLINE_DBG_UNTIL and is cached after first use
COPPERLINE_DIAG_MANUAL_BPL_PIXELS=BEAMY,X0,X1[,STEP]: sample CPU/Copper BPLDAT replay pixels on one beam line, including source x/native bit, selected index, HAM seed/output state, output latch, BPLCON0/BPLCON1, and display window; cached after first use
COPPERLINE_DIAG_FRAME_PIXELS=BEAMY,X0,X1[,STEP]: sample final framebuffer pixels after playfield, manual BPLDAT replay, sprites, and final blanking so post-decode overwrites can be isolated; cached after first use
COPPERLINE_DIAG_SPRITESSprite DMA fetch/render log
COPPERLINE_DIAG_SPRCAP=BEAMY or =all: log every captured sprite DMA line (frame, channel, hstart, attach, FMODE width, data words) on one beam line or all of them; also logs SPRxPT writes and active stream retargets
COPPERLINE_DIAG_MANUAL_SPRITES=BEAMY or =all: log manually replayed sprite intervals, sprite register writes with CPU/Copper source, BPLCON3/BPLCON4/FMODE/COLOR timing, sprite pointer alignment, and held wide-sprite words
COPPERLINE_DIAG_SPRITE_PIXELS=BEAMY[,STEP]: sample non-transparent sprite pixels on one beam line, including sprite or attached-pair index, palette entry, sprite RGB, final framebuffer RGB, playfield mask, priority/display gates, DIW, BPLCON2, BPLCON3, and BPLCON4; STEP defaults to 32 framebuffer pixels
COPPERLINE_EXP_NO_SPRITE_RENDERWith --features internal-diagnostics, skip sprite rendering in full-frame output while leaving playfield/manual-BPL rendering active; useful for isolating sprite-owned pixels in screenshots
COPPERLINE_DIAG_BLITREGS=START:END (emulated seconds): log the full blitter register set at every blit start (classic BLTSIZE and ECS BLTSIZH); pairs with COPPERLINE_DUMP_BLITMEM snapshots for offline blit verification
COPPERLINE_TRACE_BLITTERPath to a JSONL trace of blitter starts, forced finishes, DMACONR polls, and completion IRQ latches; start records include minterm/control registers, DMA/display context, FMODE, and all eight bitplane pointers
COPPERLINE_DIAG_DISKDisk DMA state changes (DSKLEN writes)
COPPERLINE_DIAG_AUDIO_NOTESPaula channel note on/off events
COPPERLINE_DIAG_CRASHCPU empty-RAM execution and low-memory blitter write context
COPPERLINE_DIAG_GAYLE / COPPERLINE_DIAG_CDTVGayle IDE / CDTV controller traffic
COPPERLINE_DIAG_A2091A2091 SCSI board register traffic (DMAC + WD33C93 accesses; the trace that brings up boot-ROM issues)
COPPERLINE_DIAG_CURSOROn every mouse-button press, log the raw host cursor position, the window’s scale factor and inner size, the texture supersample factor, the window_pos_to_pixel result, and which region (status bar / display / none) the click resolved to; for diagnosing mouse capture on DPI scale changes or mixed-scale monitors
COPPERLINE_DUMP_BLITMEM=START:END:LO:HIDump chip RAM [LO,HI) on every BLTSIZE write between START and END emulated seconds; output goes to $TMPDIR/copperline-blitdump unless COPPERLINE_DUMP_BLITMEM_DIR is set
COPPERLINE_DUMP_BUS_ACCOUNTINGPer-frame chip-bus slot accounting
COPPERLINE_DUMP_RENDER_META[_VERBOSE]Renderer event/fetch metadata

Timing-model knobs that pair well with the debugger:

Behavior-changing A/B switches such as COPPERLINE_NO_*, COPPERLINE_EXP_*, COPPERLINE_DISK_SPEED_DIV, and COPPERLINE_DBG_EXTCCK are compiled only with the internal-diagnostics feature. Normal builds ignore them so release runs stay hardware-derived and reproducible.

A worked example

A frame-pacing investigation is a template for using these tools together:

  1. Reproduce headlessly: --screenshot-after at a known-bad timestamp.

  2. Find the guest’s frame pacing: COPPERLINE_DIAG_PCSAMPLE to locate the hot loop, then COPPERLINE_DBG_BREAK on the loop head with COPPERLINE_DBG_DUMP of its counters.

  3. Narrow in time with COPPERLINE_DBG_AFTER/UNTIL, watch the interesting word with COPPERLINE_DBG_WATCH.

  4. Check the bus: COPPERLINE_DIAG_SLOTMAP_AT to see who owned every colour clock of the suspect frame, with COPPERLINE_DIAG_SLOTMAP_RANGE when only specific beam rows matter.

  5. Compare against real hardware with the timing-test/ disk when the question is “is this operation too fast/slow”.

For interactive sessions, the same instruction trace is available at runtime without environment variables: the The Console’s TRACE START [PATH] / TRACE STOP.