MCPcopy Index your code
hub / github.com/LinuxJedi/Copperline

github.com/LinuxJedi/Copperline @v0.9.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.9.0 ↗ · + Follow
5,527 symbols 21,366 edges 147 files 1,121 documented · 20%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Copperline

Website: copperline.dev

An Amiga emulator written in Rust, built around a vendored copy of the pure-Rust m68k CPU core, with a pixels + winit window for video and stdout for serial. It started life with the modest goal of booting DiagROM far enough to show a menu; it now boots Kickstart and runs timing-sensitive OCS and AGA software from the regression set at real speed.

It covers OCS, ECS, and AGA (independent Agnus/Denise revisions, programmable blanking, machine profiles from the A500 to the A1200, CDTV, and CD32, with Gayle IDE, A2091 SCSI, and the AGA display path: 8 bitplanes, 256-entry palette, HAM8, FMODE wide fetch; remaining gaps are recorded in the internals docs). The timing model is taken seriously: the chip bus is arbitrated per colour clock, the Copper and blitter are scheduled per DMA slot with hardware bus sequences, and 68000 interrupt-recognition latency is modelled. The source is organized so the hardware model can be read and extended without chasing title-specific patches.

Background

It began as a two-part experiment: could I build an Amiga emulator that is easy to drive from the command line, and could I give it the tooling to feed debugging data and screenshots back to an AI agent automatically, so issues could be investigated from a timestamp or a snapshot? It grew into a larger emulator whose development was AI-driven, guided by books, my own knowledge of Amiga internals, and test disks generated to compare timings against real hardware.

Features

  • Cycle-driven timing core. The chip bus is arbitrated per colour clock between refresh, display/sprite/disk/audio DMA, the Copper, the blitter, and CPU accesses; the Copper and blitter are scheduled per DMA slot with the hardware per-word bus sequences, and 68000 interrupt-recognition latency is modelled. Real-hardware reference numbers come from the cross-emulator disk in timing-test/.
  • OCS, ECS, and AGA, with independent Agnus/Denise revisions and machine profiles from the A500 to the A1200, plus CDTV and CD32. Boots the bundled AROS ROM out of the box, as well as Kickstart 1.3 / 2.05 / 3.1 and DiagROM v2.0, and runs the current timing-sensitive OCS and AGA regression set at real speed.
  • Configurable CPU (68000 / 68EC020 / 68020 / 68030 / 68040) and clock, with an optional 68881/68882 FPU (default-on for the 68040).
  • Peripherals: a bit-timed keyboard (6500/1 MCU), mouse, USB gamepad (via the pure-Rust gilrs, no SDL2), 4-channel Paula audio, floppy (ADF / ADZ / DMS, read-only SCP), Gayle IDE, A2091 SCSI, and CDTV/CD32 CD.
  • Tooling: an in-window debugger, an interactive chip-bus frame analyzer, remote GDB support, deterministic save states, input recording/replay, and headless screenshot/frame-dump capture -- the deterministic core makes every replay byte-identical.

Requirements

  • Rust 1.87+ (stable). Tested with Rust 1.96.
  • Fedora build dependencies: sudo dnf install alsa-lib-devel systemd-devel.
  • No SDL2 dependency. Developed and tested on macOS; the Linux and Windows paths are expected to work but are currently untested.
  • Linux requires a Vulkan driver. The display is presented with wgpu via the Vulkan backend; the OpenGL fallback is not usable (see "Linux: Vulkan required" below). Any GPU from roughly Intel Skylake / 2015 onward has a hardware Vulkan driver. Older hardware (or a headless/VM host) can use the software lavapipe ICD: vulkan-swrast on Arch, mesa-vulkan-drivers on Debian/Ubuntu/Fedora. macOS (Metal) and Windows (DX12) are unaffected.

Install (macOS, Homebrew)

brew tap LinuxJedi/copperline https://github.com/LinuxJedi/Copperline
brew install copperline

This builds from source on your machine, so the binary is not subject to macOS Gatekeeper quarantine -- there is no Security & Privacy override to click through. Use brew install --HEAD copperline to build the latest main instead of the most recent tagged release. Then run copperline from the terminal.

Install (Linux)

flatpak install flathub dev.copperline.Copperline   # any distribution

Or grab the single-file Copperline-*.AppImage from the releases page, chmod +x it and run. Both bundle the AROS boot ROM. Packaging sources are in packaging/.

Linux: Vulkan required

On Linux the display is presented through wgpu's Vulkan backend. The OpenGL fallback is deliberately disabled: wgpu creates its EGL instance without a display handle, so it silently selects Mesa's "surfaceless" platform, which cannot be paired with an on-screen window. The symptom on a Vulkan-less machine is the window flashing open and then exiting with:

ERROR copperline::video::window] pixels init failed: No suitable `wgpu::Adapter` found.

If you hit this, install a Vulkan driver:

  • Hardware Vulkan (recommended): any GPU from roughly Intel Skylake / 2015 onward ships one. Update your mesa/GPU driver package.
  • Software fallback (older hardware, headless, or a VM) -- the lavapipe ICD:
  • Arch: sudo pacman -S vulkan-swrast
  • Debian/Ubuntu: sudo apt install mesa-vulkan-drivers
  • Fedora: sudo dnf install mesa-vulkan-drivers

Copperline does all rendering on the CPU and only asks the GPU to blit one framebuffer per frame, so software Vulkan (lavapipe) is perfectly adequate. The Flatpak runtime already includes lavapipe, so the Flatpak works without any extra package. Setting WGPU_BACKEND overrides the backend selection if you need to force a specific one for debugging.

Build and run

cargo build --release
./target/release/copperline

The binary looks for ./copperline.toml; if it isn't present, built-in defaults are used (68000 at ~7.09 MHz, OCS, PAL, real speed, and the bundled AROS ROM on a 1 MB A500: 512 KiB chip plus 512 KiB trapdoor slow RAM). Boot your own ROM with a positional argument, or point at a config file:

./target/release/copperline path/to/kickstart.rom
./target/release/copperline --config path/to/copperline.toml

Essential shortcuts use Cmd on macOS and Alt on Linux/Windows: Cmd+Q / Alt+Q closes the window, Esc passes through to the Amiga (or closes an open menu/window), Cmd+S / Alt+S saves a screenshot, and Cmd+B / Alt+B opens the debugger. Cmd+J / Alt+J (or the status-bar icon) toggles joystick input between gamepad-only and keyboard emulation. The status bar, pop-up menu, tool windows (debugger and frame analyzer), overlay panels, save/load state, input recording, and the full shortcut list are documented in the user guide.

Configuration

Copy copperline.example.toml to copperline.toml and edit; every field is optional and missing fields use documented defaults.

rom = "kickstart205.rom"

[cpu]
model = "68000"       # 68000, 68EC020, 68020, 68030, 68040
# fpu = true          # fit a 68881/68882 (default-on for the 68040)
# clock_mhz = 14.0    # defaults to the model's stock speed

[memory]
chip = "512K"         # OCS 512K, ECS/AGA up to 2M
fast = "0"            # Zorro II autoconfig fast RAM, up to 8M
slow = "512K"         # A500 trapdoor RAM at $C00000, up to 512K

[chipset]
revision = "OCS"      # OCS, ECS, or AGA (picks the Agnus/Denise revisions)
video = "PAL"         # PAL or NTSC

[floppy]
# drives = 2           # wired mechanisms, 1-4; default is DF0 only

[floppy.df0]
path = "AmigaTestKit.adf"   # DD ADF / ADZ / DMS / SCP; omit for no disk

The full reference -- every key, machine profiles, Zorro boards, CD/HDD images, validation rules, and audio options -- is in the configuration guide.

Documentation

User and developer documentation -- getting started, the UI and shortcuts, headless capture, save states, input recording, the debugger frontends (window, headless, and remote GDB), the configuration reference, and the internals (timing model, chipset, CPU, video pipeline) -- is published at copperline.dev and lives under docs/ as a MyST project you can also build locally:

npm install -g mystmd
cd docs && myst build --html      # static site in docs/_build/html

See docs/README.md for conventions and PDF output.

Packaging

Copperline is distributed from source. On macOS this repository doubles as a Homebrew tap (Formula/); on Linux it builds as a Flatpak for Flathub (packaging/flatpak/) and as a portable AppImage (packaging/appimage/). It is not on crates.io: Cargo.toml sets publish = false because the emulator depends on a patched vendored copy of the m68k CPU core, which a crates.io release needs resolved first. Release steps for every channel are in RELEASE.md.

What gets emulated

Subsystem Notes
M68K CPU Via a vendored pure-Rust m68k crate; model selectable through 68040, accurate 68000 cycle counts, 6888x FPU.
Chip RAM mem_map'd; reset starts with ROM overlaid at $0 until CIA-A releases /OVL.
Fast RAM Optional Zorro II autoconfig RAM at $00200000 and Zorro III autoconfig RAM ([memory] z3); runs at the CPU clock.
Slow RAM Optional A500 trapdoor/fake-fast RAM at $00C00000; arbitrated on the chip bus through Agnus like chip RAM.
ROM Kickstart at $F80000 (512 KiB); optional extended ROM for CD32 ($E00000) and CDTV ($F00000).
Battery RTC Read-only MSM6242-compatible register view at $DC0000; guest writes affect only emulated latch/control state.
CIA-A / CIA-B I/O ports, /OVL, timers, TOD, keyboard SDR/ICR, disk control/status lines, and CIA-B FLAG disk index pulses.
Paula serial SERDAT -> stdout through a one-word transmit buffer and timed shift register; SERDATR reports TBE/TSRE/RBF.
Paula audio 4-channel DMA/sample playback, stereo mix, LED filter.
Paula DMACON / INTENA / INTREQ IRQ bits are stored and delivered through manual M68K autovectors with modelled 68000 interrupt-recognition latency; audio and disk DMA raise completion IRQs.
Floppy / ADF / DMS / SCP DF0-DF3 standard DD ADF read/write, read-only ADZ/DMS, UAE extended ADF, initial read-only SCP flux import, track-timed disk DMA, CIA drive lines, index FLAG, DSKLEN/DSKBYTR/DSKSYNC/DSKDAT, per-drive multi-disk playlists with a swap key.
Agnus VPOSR / VHPOSR Beam counters advanced per colour clock; PAL and NTSC timing (including NTSC long/short lines).
Agnus Copper Beam-scheduled OCS Copper with COP1/COP2 jumps, WAIT, SKIP, DMAEN/COPEN gating, and chip-bus grants.
Agnus blitter Scheduled per-slot engine: normal/line/fill modes, hardware per-word channel bus sequences (including the area-fill idle C slot), BBUSY/BZERO, BLTPRI "nasty" vs CPU starvation-yield arbitration, blit-done IRQ.
Denise BPLCON / COLORxx Stored and replayed by beam position.
Bitplane renderer OCS lo-res or hi-res; reads chip RAM via BPLxPT; honours modulos and beam-timed BPLCON1 scroll; EHB, HAM, dual playfield, and CLXDAT collisions. Completed frames render on a worker thread by default; COPPERLINE_THREADED_RENDER=0 forces synchronous rendering.
Display window winit 0.30 + pixels 0.17 surface; 716x285 framebuffer presented at 4:3 (716x537) plus a 44-pixel status bar with power/disk controls.
Keyboard / mouse / gamepad Host keyboard/mouse mapped to Amiga input paths; key down and key up events go through CIA-A SDR/ICR with acknowledge + KDAT handshake backpressure and keyboard-MCU pacing; mouse deltas feed JOY0DAT; Cmd+G on macOS or Alt+G on Linux/Windows toggles host mouse capture; a USB gamepad (gilrs) or keyboard joystick emulation drives the port-2 digital joystick (JOY1DAT directions, /FIR1 fire, POT1Y button 2); Ctrl+Ami+Ami resets.
OCS sprites 8 DMA/manual 16-pixel sprites, attached sprites, composited over bitplanes with playfield priority.
Chip bus arbitration Per-colour-clock OCS slot ownership for refresh, display DMA, sprites, disk, audio, Copper, blitter, and CPU chip/custom accesses, with CPU wait states.
ECS ECS Agnus revisions (8372A/8375) and ECS Denise (8373): up to 2M chip RAM, DIWHIGH, BEAMCON0, SuperHires, ECS blitter (BLTSIZV/BLTSIZH), programmable geometry.
AGA Alice/Lisa: 8 bitplanes, 256-entry 24-bit palette (plus the genlock T bit) with BANK/LOCT, HAM8, FMODE wide bitplane/sprite fetch, BPLCON4, CLXCON2; A1200/CD32 profiles. Remaining gaps (e.g. 35 ns SHRES sprites) recorded in the internals docs.

The detailed architecture (source layout, the bus, the replay renderer) and timing model live in the internals docs.

Tests

cargo test runs the unit suite, which needs no external assets. The integration tests under tests/ are marked #[ignore] because they run the emulator against local Kickstart ROM and disk images that are not part of the repository; they skip cleanly when the assets are absent. See tests/README.md for the asset list and lookup directory, and the headless guide for the vAmigaTS compatibility runs. timing-test/ is a bootable disk that measures CPU and chip-bus timings against the CIA E-clock for cross-emulator comparison.

Known quirks

  • Lo-res content is pixel-doubled horizontally inside the framebuffer; the window presents the field at a TV-like 4:3 aspect plus the status bar.
  • The CPU may halt with an EXCEPTION on an unimplemented feature (an exotic custom register or CIA edge case). This is non-fatal: the window stays alive showing the last framebuffer, and the debugger can inspect the halted state.

Credits

Extension points exported contracts — how you extend this code

AudioSink (Interface)
Note: this trait is intentionally *not* `Send`. CpalSink owns a `cpal::Stream` which is `!Send` on macOS (the CoreAudio [9 …
src/audio.rs
HleHandler (Interface)
Trap handler with CPU and bus access for HLE. This is the recommended trait for high-level emulation: handlers get dire [8 …
crates/m68k/src/core/types.rs
SerialSink (Interface)
(no doc) [6 implementers]
src/serial.rs
ZorroDevice (Interface)
(no doc) [5 implementers]
src/zorro_device.rs
BreakContext (Interface)
Live CPU/memory state a [`BreakCond`] reads. Implemented over the running machine at the breakpoint gate, kept as a trai [2 …
src/debugger.rs
NetBackend (Interface)
A host networking backend an emulated NIC sends and receives frames through. `Send` so it can live in a wasmtime store's [1 …
src/net.rs
AddressBus (Interface)
(no doc) [34 implementers]
crates/m68k/src/core/memory.rs

Core symbols most depended-on inside this repo

write_chip_word
called by 606
src/bus.rs
len
called by 368
src/timetravel.rs
iter
called by 321
src/video/bitplane.rs
empty_bus
called by 274
src/bus.rs
advance_chipset
called by 218
src/bus.rs
push
called by 188
src/timetravel.rs
write_prb
called by 168
src/floppy.rs
write_ocs
called by 133
src/chipset/denise.rs

Shape

Function 2,646
Method 2,421
Class 357
Enum 96
Interface 7

Languages

Rust100%
C1%
Python1%
Ruby1%

Modules by API surface

src/bus.rs761 symbols
src/video/bitplane.rs444 symbols
src/video/window.rs365 symbols
src/floppy.rs327 symbols
src/chipset/paula.rs169 symbols
src/cpu.rs166 symbols
src/config.rs163 symbols
src/chipset/agnus.rs154 symbols
src/video/ui.rs125 symbols
src/emulator.rs116 symbols
src/chipset/blitter.rs111 symbols
src/video/launcher.rs96 symbols

For agents

$ claude mcp add Copperline \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact