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.
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.
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()`.