[← Home](../../README.md) · [Hardware](../README.md) · [OCS](README.md) # Copper Coprocessor ## Overview The **Copper** (co-processor) is built into Agnus. It executes a simple instruction list (the **copperlist**) in sync with the video beam, allowing precise per-scanline changes to any writable custom register — without CPU intervention. The Copper can only write to custom registers (it cannot access Chip RAM directly), but it can change bitplane pointers, colors, BPLCON0, sprite pointers, and any other `$DFF0xx` register on a cycle-accurate basis. ## Copper Instruction Set The Copper has exactly **three instructions**, each exactly **32 bits** (two 16-bit words): ### 1. MOVE — Write a Register ``` Word 1: [RRR RRRR RRR0] Destination register address (must be even, bit 0 = 0) Word 2: [DDDD DDDD DDDD] Data to write ``` Example — set COLOR00 to red at scanline 100: ``` DC.W $0180, $0F00 ; MOVE COLOR00, $0F00 (red) ``` ### 2. WAIT — Wait for Beam Position ``` Word 1: [VVVV VVVH HHHH HH1] Vertical pos[8:1], Horizontal pos[8:3], bit0=1 Word 2: [EVVV VVVH HHHH HHx0] Enable, VP mask, HP mask, bit0=0 ``` The Copper stalls until the beam reaches `(V,H) AND (Vmask,Hmask)`. Standard full-precision WAIT: ``` DC.W $6401, $FF00 ; WAIT for line $64 (100), any H — full V mask ``` WAIT for end of frame (copper stop): ``` DC.W $FFFF, $FFFE ; WAIT $FF,$FF — impossible position → stop copper ``` ### 3. SKIP — Conditional Skip ``` Word 1: [VVVV VVVH HHHH HH1] Same format as WAIT Word 2: [EVVV VVVH HHHH HHx1] Same as WAIT but bit 0 = 1 (SKIP flag) ``` If beam has passed the position, skip the next instruction. Used for double-buffered copper switching. ## Copperlist Format A copperlist is an array of 32-bit instruction pairs in **Chip RAM**, terminated by: ``` DC.W $FFFF, $FFFE ``` Example — color cycle on vertical blank: ```asm Copperlist: DC.W $0180, $0000 ; COLOR00 = black DC.W $4401, $FF00 ; WAIT line 68 (display area start) DC.W $0180, $0F00 ; COLOR00 = red DC.W $6401, $FF00 ; WAIT line 100 DC.W $0180, $00F0 ; COLOR00 = green DC.W $FFFF, $FFFE ; END ``` ## Copper Pointers and Control | Register | Offset | Description | |---|---|---| | COP1LCH | $080 | Copper list 1 pointer high word | | COP1LCL | $082 | Copper list 1 pointer low word | | COP2LCH | $084 | Copper list 2 pointer high word | | COP2LCL | $086 | Copper list 2 pointer low word | | COPJMP1 | $088 | Strobe: restart copper from list 1 (any write) | | COPJMP2 | $08A | Strobe: restart copper from list 2 | | COPCON | $02E | Copper danger bit (CDANG) | **COPCON** bit 1 (`CDANG`): When set, Copper is allowed to write to registers `$40`–`$7F` (blitter registers). Should be 0 in normal use to prevent runaway copperlists from corrupting the blitter. ## Activating the Copper ```asm ; Load copperlist address into copper list 1 move.l #Copperlist, d0 move.w d0, COP1LCL+custom ; low word swap d0 move.w d0, COP1LCH+custom ; high word ; Restart copper (triggers on next VBlank) move.w d0, COPJMP1+custom ; value irrelevant, strobe only ; Enable copper DMA move.w #$8280, DMACON+custom ; SET + MASTER + COPEN ``` ## Dual-Playfield and HAM via Copper Common copper techniques: **Split-screen different palettes:** Change `COLOR00`–`COLOR31` registers mid-screen via a WAIT at the split scanline. **Mid-screen bitplane pointer change:** Redirect `BPL1PTH/BPL1PTL` to a different bitmap half-way through the display — used for large vertical scrolling without double-buffering the full screen. **BPLCON0 mid-screen:** Switch between `HIRES` and `LORES`, or between 6-plane and 4-plane modes, on different lines. **Raster bars:** Write a different color to COLOR00 on every scanline using sequential WAIT+MOVE pairs. ## Graphics Library vs Direct Copper AmigaOS's `graphics.library` manages the Copper list internally: - `MrgCop()` merges system and user copper lists - `LoadView()` installs a View structure's copper list - `WaitTOF()` waits for the top-of-frame (VBlank) before the copper restarts Direct copper access should be done via `GetColorMap()`, `SetRGB4()` and official graphics calls, or through a custom `View`/`ViewPort`/`ColorMap` structure passed to `LoadView()`. ## References - ADCD 2.1 Hardware Manual — Copper chapter - NDK39: `hardware/custom.h`, `graphics/copper.h` - *Amiga Hardware Reference Manual* 3rd ed., Chapter 6