mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-13 00:26:28 +00:00
docs(amiga): complete AmigaOS 3.1/3.2 developer reference — 172 files across 17 sections
Comprehensive technical documentation covering: - Hardware: OCS/ECS/AGA custom chip registers, Copper & Blitter deep dives - Boot sequence: cold boot through startup-sequence - Binary format: HUNK executable spec, relocation, debug info - Linking & ABI: .fd files, LVO tables, register calling conventions - Exec kernel: tasks, interrupts, memory, signals, semaphores - AmigaDOS: file I/O, FFS/OFS layout, CLI/Shell scripting - Graphics: planar bitmaps, Copper programming, HAM/EHB modes - Intuition: screens, windows, IDCMP, BOOPSI - Devices: trackdisk, SCSI, serial, timer, audio, keyboard - Libraries: utility, expansion, IFFParse, locale, ARexx - Networking: bsdsocket API, SANA-II, TCP/IP stack comparison - Toolchain: GCC, vasm/vlink, SAS/C, NDK, debugging - Reverse engineering: IDA/Ghidra setup, compiler fingerprints, case studies - CPU & MMU: 68040/060 emulation libs, PMMU, cache management - Driver development: SANA-II, Picasso96/RTG, AHI audio All files include breadcrumb navigation. No local paths or proprietary content.
This commit is contained in:
parent
f07a368bf1
commit
21751c0025
172 changed files with 19701 additions and 0 deletions
69
01_hardware/aga_a1200_a4000/README.md
Normal file
69
01_hardware/aga_a1200_a4000/README.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md)
|
||||
|
||||
# AGA Chipset — A1200 / A4000 / CD32
|
||||
|
||||
## Overview
|
||||
|
||||
The **Advanced Graphics Architecture** (AGA) is the final custom chipset developed by Commodore, shipping from 1992. It dramatically expands colour depth, palette size, sprite capabilities, and blitter bandwidth while retaining full OCS/ECS backward compatibility.
|
||||
|
||||
## Chip Summary
|
||||
|
||||
| Chip | Name | Changes from ECS |
|
||||
|---|---|---|
|
||||
| **Alice** | MOS 8374 | Super Agnus successor: 64-bit bus, FMODE register |
|
||||
| **Lisa** | (unnamed MOS) | ECS Denise successor: 8-bit palette, 256 colours |
|
||||
| **Paula** | MOS 8364 | Unchanged from OCS/ECS |
|
||||
|
||||
## Contents
|
||||
|
||||
| File | Topic |
|
||||
|---|---|
|
||||
| [chipset_aga.md](chipset_aga.md) | Alice and Lisa internals, AGA architecture |
|
||||
| [aga_registers_delta.md](aga_registers_delta.md) | New/changed registers vs ECS |
|
||||
| [aga_palette.md](aga_palette.md) | 24-bit colour system, 256 registers |
|
||||
| [aga_display_modes.md](aga_display_modes.md) | HAM8, 256-colour, doublescan, VGA |
|
||||
| [aga_blitter.md](aga_blitter.md) | 64-bit blitter bus, FMODE |
|
||||
| [cpu_030_040.md](cpu_030_040.md) | 68030/040 on A3000/A4000: cache, MMU, FPU |
|
||||
| [gayle_ide_a1200.md](gayle_ide_a1200.md) | A1200 Gayle: IDE and PCMCIA specifics |
|
||||
|
||||
## AGA vs ECS — Key Differences
|
||||
|
||||
| Feature | ECS | AGA |
|
||||
|---|---|---|
|
||||
| Colour registers | 32 (12-bit) | **256 (24-bit)** |
|
||||
| Max simultaneous colours | 64 EHB / HAM | **256** (or HAM8: 262,144) |
|
||||
| Blitter bus | 16-bit | **64-bit** (FMODE) |
|
||||
| Sprite width | 16 px | **64 px** |
|
||||
| Sprite colours | 3+transparent | **15+transparent** (64-colour attached) |
|
||||
| Bitplane depth | 6 planes max | **8 planes** |
|
||||
| Palette select | 1 bank | **4 bitplane banks, 4 sprite banks** |
|
||||
|
||||
## Identifying AGA at Runtime
|
||||
|
||||
```c
|
||||
#include <graphics/gfxbase.h>
|
||||
|
||||
extern struct GfxBase *GfxBase;
|
||||
|
||||
BOOL is_aga = (GfxBase->ChipRevBits0 & (1 << GFXB_AA_ALICE)) != 0;
|
||||
```
|
||||
|
||||
| ChipRevBits0 bit | Flag | Meaning |
|
||||
|---|---|---|
|
||||
| 4 | `GFXB_AA_ALICE` | AGA Alice present |
|
||||
| 5 | `GFXB_AA_LISA` | AGA Lisa present |
|
||||
|
||||
## AGA Machines
|
||||
|
||||
| Model | CPU | Notes |
|
||||
|---|---|---|
|
||||
| A1200 | 68020 14 MHz | Budget AGA; Gayle IDE; PCMCIA; 2 MB Chip |
|
||||
| A4000 | 68030/040 25 MHz | High-end; Zorro III; IDE; 2 MB Chip + Fast |
|
||||
| A4000T | 68040/060 | Tower variant; SCSI |
|
||||
| CD32 | 68020 14 MHz | Game console; CD-ROM; SX-1 expansion |
|
||||
|
||||
## References
|
||||
|
||||
- ADCD 2.1 Hardware Manual — AGA chapters
|
||||
- NDK39: `graphics/gfxbase.h`, `hardware/custom.h`
|
||||
- Commodore A1200/A4000 Technical Reference Manuals (local archive)
|
||||
167
01_hardware/aga_a1200_a4000/aga_blitter.md
Normal file
167
01_hardware/aga_a1200_a4000/aga_blitter.md
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# AGA Blitter — What It Is, What It Does, and 64-bit Bus Mode
|
||||
|
||||
## What Is the Blitter?
|
||||
|
||||
The **Blitter** (Block Image Transfer) is a dedicated DMA hardware engine inside every Amiga, designed to move and transform rectangular blocks of bitmap data **without CPU intervention**. While the CPU handles game logic, AI, physics, and sound setup, the Blitter does the heavy graphical lifting in the background.
|
||||
|
||||
Think of it as a **hardware GPU for 2D raster operations** — years before PC graphics cards existed.
|
||||
|
||||
### What the Blitter Can Do
|
||||
|
||||
| Capability | Description | Typical Use |
|
||||
|---|---|---|
|
||||
| **Block copy** | Move rectangular bitmap regions | Scrolling backgrounds, restoring screen areas |
|
||||
| **Cookie-cut blit** | Stamp a shape onto a background using a mask | Drawing game sprites (BOBs) with transparency |
|
||||
| **Area fill** | Fill arbitrary shapes | Flood-filling polygons, UI element backgrounds |
|
||||
| **Line drawing** | Draw lines using hardware Bresenham | Vector graphics, wireframe 3D |
|
||||
| **Clear/set memory** | Zero or fill large memory blocks | Screen clearing between frames |
|
||||
| **Logic operations** | Combine 3 inputs with any Boolean function | XOR cursors, shadow effects, masking |
|
||||
| **Shifting** | Shift source data 0–15 pixels | Sub-word-aligned sprite positioning |
|
||||
|
||||
### What the Blitter Cannot Do
|
||||
|
||||
| Limitation | Detail |
|
||||
|---|---|
|
||||
| No scaling | Cannot resize images — fixed 1:1 pixel mapping |
|
||||
| No rotation | Cannot rotate — must be pre-rendered in software |
|
||||
| No 3D | No perspective, texture mapping, or Z-buffer |
|
||||
| No chunky pixels | Operates on **planar** bitplanes only (1 plane at a time) |
|
||||
| No colour blending | Pure Boolean logic — no alpha, no transparency gradients |
|
||||
| Word-aligned width | Minimum operation width is 16 pixels (1 word) |
|
||||
|
||||
### How Software Uses It
|
||||
|
||||
**Games** — The blitter draws BOBs (Blitter Objects = software sprites) by cookie-cutting character graphics onto the playfield. A typical game frame:
|
||||
1. Blitter restores background behind old sprite positions
|
||||
2. Game logic updates positions
|
||||
3. Blitter draws sprites at new positions using cookie-cut
|
||||
4. Copper switches display to the newly drawn buffer (double-buffering)
|
||||
|
||||
**Demos** — Demoscene coders exploit every blitter trick: interleaved bitplane blits, fill-mode for filled vector polygons, line-mode for wireframes, and careful DMA scheduling to run blitter and CPU in parallel.
|
||||
|
||||
**Applications** — Workbench uses `BltBitMap()` for window dragging, scrolling text, and refreshing damaged screen areas. The `layers.library` damage repair system depends entirely on blitter operations.
|
||||
|
||||
---
|
||||
|
||||
## AGA Enhancements
|
||||
|
||||
AGA's Alice chip extends the blitter with a **64-bit data bus mode** controlled by the `FMODE` register. This allows the blitter to fetch 2 or 4 words per DMA cycle, dramatically increasing fill and copy throughput for large bitmap operations.
|
||||
|
||||
## FMODE Configuration
|
||||
|
||||
`FMODE` ($DFF1FC) controls blitter, bitplane, and sprite DMA fetch widths independently:
|
||||
|
||||
```
|
||||
bits 9-8: BLT_FMODE — blitter fetch mode
|
||||
00 = 16-bit (OCS compatible)
|
||||
01 = 32-bit
|
||||
10 = 64-bit
|
||||
11 = reserved
|
||||
|
||||
bits 13-12: BPL_FMODE — bitplane fetch mode (same encoding)
|
||||
bits 15-14: SPR_FMODE — sprite fetch mode (same encoding)
|
||||
```
|
||||
|
||||
Setting 64-bit blitter mode:
|
||||
```asm
|
||||
move.w #$0300, $DFF1FC ; BLT_FMODE = 10 (64-bit)
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> FMODE must be set **before** loading blitter registers and starting the blit. Changing FMODE mid-blit causes undefined behaviour.
|
||||
|
||||
## Width Calculation with FMODE
|
||||
|
||||
When using wider fetch modes, **BLTSIZE widths must be adjusted**:
|
||||
|
||||
| FMODE | Width unit | Width formula |
|
||||
|---|---|---|
|
||||
| 1× (16-bit) | 1 word = 16 bits | `width_in_words` |
|
||||
| 2× (32-bit) | 2 words = 32 bits | `(width_in_words + 1) / 2` |
|
||||
| 4× (64-bit) | 4 words = 64 bits | `(width_in_words + 3) / 4` |
|
||||
|
||||
Example: blitting 320 pixels wide (20 words):
|
||||
- 1× mode: BLTSIZE width = 20
|
||||
- 2× mode: BLTSIZE width = 10
|
||||
- 4× mode: BLTSIZE width = 5
|
||||
|
||||
**Modulo values are still in bytes** regardless of FMODE.
|
||||
|
||||
## Performance Comparison
|
||||
|
||||
For a typical 320×200 blit (simple copy, 1 bitplane):
|
||||
|
||||
| Mode | FMODE | Approx time (7 MHz) |
|
||||
|---|---|---|
|
||||
| OCS/ECS | 1× | ~1.8 ms |
|
||||
| AGA 2× | 2× | ~0.9 ms |
|
||||
| AGA 4× | 4× | ~0.45 ms |
|
||||
|
||||
## Alignment Requirements
|
||||
|
||||
Wider fetch modes impose alignment constraints on source/destination pointers:
|
||||
|
||||
| FMODE | Required alignment |
|
||||
|---|---|
|
||||
| 1× | 2 bytes (word) |
|
||||
| 2× | 4 bytes (long) |
|
||||
| 4× | 8 bytes (quadword) |
|
||||
|
||||
Misaligned pointers with 2× or 4× FMODE produce incorrect blit results.
|
||||
|
||||
## Using graphics.library
|
||||
|
||||
The OS `BltBitMap()` / `BltBitMapRastPort()` calls are FMODE-aware in OS 3.1+ on AGA hardware:
|
||||
|
||||
```c
|
||||
BltBitMap(src_bm, srcx, srcy, dst_bm, dstx, dsty, width, height,
|
||||
0xC0, 0xFF, NULL); /* minterm $C0 = copy, all planes */
|
||||
```
|
||||
|
||||
`graphics.library` automatically selects the optimal FMODE for the current hardware.
|
||||
|
||||
## BLTCON0 / BLTCON1 — Unchanged in AGA
|
||||
|
||||
The minterm logic (`BLTCON0`) and fill/line mode (`BLTCON1`) registers are functionally identical to OCS/ECS. AGA only adds bandwidth, not new logical capabilities.
|
||||
|
||||
## Direct AGA Blitter Example (64-bit clear)
|
||||
|
||||
```asm
|
||||
; Clear 320×256 bitmap at address $100000 (20 words wide, 256 lines)
|
||||
; Using AGA 4× FMODE (5 quads wide)
|
||||
|
||||
move.w #$0300, $DFF1FC ; FMODE: BLT_FMODE = 4×
|
||||
|
||||
move.w #$0100, BLTCON0+custom ; USE D only, minterm $00 (fill with zero)
|
||||
move.w #$0000, BLTCON1+custom
|
||||
|
||||
move.w #$FFFF, BLTAFWM+custom ; first word mask
|
||||
move.w #$FFFF, BLTALWM+custom ; last word mask
|
||||
|
||||
move.l #$00100000, BLTDPTH+custom+$00 ; dest high word
|
||||
; (split into high/low)
|
||||
move.w #$0010, BLTDPTH+custom
|
||||
move.w #$0000, BLTDPTL+custom
|
||||
|
||||
move.w #0, BLTDMOD+custom ; modulo = 0 (contiguous)
|
||||
|
||||
; BLTSIZE = (256 lines << 6) | 5 quads width = (256*64)|5 = $4005
|
||||
move.w #((256<<6)|5), BLTSIZE+custom ; start blit
|
||||
|
||||
; wait for completion
|
||||
WaitBlit:
|
||||
btst #6, DMACONR+custom+1
|
||||
bne.s WaitBlit
|
||||
|
||||
; Restore FMODE to 1× for safety
|
||||
move.w #$0000, $DFF1FC
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- ADCD 2.1 Hardware Manual — AGA blitter section
|
||||
- NDK39: `hardware/blit.h`, `hardware/custom.h`
|
||||
- Commodore A1200/A4000 Technical Reference Manuals — Alice section
|
||||
- graphics.library Autodocs: BltBitMap, BltClear
|
||||
371
01_hardware/aga_a1200_a4000/aga_copper.md
Normal file
371
01_hardware/aga_a1200_a4000/aga_copper.md
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# AGA Copper — What It Is, How It Works, and Programming Guide
|
||||
|
||||
## What Is the Copper?
|
||||
|
||||
The **Copper** (Co-Processor) is one of the most distinctive pieces of hardware in any computer ever built. It is a tiny, ultra-simple programmable DMA engine that executes a program — called a **copper list** — in perfect synchronisation with the video beam as it sweeps across the screen.
|
||||
|
||||
The Copper watches the beam position and can **write any value to any custom chip register at any specific screen position**. This single capability enables an astonishing range of visual effects.
|
||||
|
||||
### Why Does It Matter?
|
||||
|
||||
On a conventional computer, changing display parameters (colours, scroll positions, resolutions) requires the CPU to execute code at precisely the right moment. This is fragile, wastes CPU time, and is limited by interrupt latency.
|
||||
|
||||
The Copper does this **automatically, for free, with perfect timing** — every single frame, without any CPU involvement at all.
|
||||
|
||||
---
|
||||
|
||||
## Copper in the System Architecture
|
||||
|
||||
### Block Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ CHIP RAM (up to 2MB) │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────────────────┐ │
|
||||
│ │ Copper List │ │ Bitplane Data│ │ Sprite Data │ │
|
||||
│ │ (MOVE/WAIT/ │ │ (screen │ │ (hardware sprite │ │
|
||||
│ │ SKIP words) │ │ pixels) │ │ images) │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────────┬────────────────┘ │
|
||||
└─────────┼──────────────────┼─────────────────────┼──────────────────┘
|
||||
│ DMA read │ DMA read │ DMA read
|
||||
▼ ▼ ▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ AGNUS / ALICE (DMA Controller) │
|
||||
│ │
|
||||
│ ┌────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
|
||||
│ │ COPPER │ │ Bitplane │ │ Sprite DMA │ │
|
||||
│ │ Engine │ │ DMA Engine │ │ Engine │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ • Fetches │ │ Fetches 1-8 │ │ Fetches sprite │ │
|
||||
│ │ copper │ │ planes per │ │ data for 8 sprites │ │
|
||||
│ │ list via │ │ line from │ │ per line │ │
|
||||
│ │ DMA │ │ BPLxPT │ │ │ │
|
||||
│ │ • Compares │ │ pointers │ │ │ │
|
||||
│ │ beam pos │ │ │ │ │ │
|
||||
│ │ • Writes │ │ │ │ │ │
|
||||
│ │ to regs │ │ │ │ │ │
|
||||
│ └─────┬──────┘ └──────┬───────┘ └───────────┬───────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌─────┴──────────────────┴────────────────────────┴─────────┐ │
|
||||
│ │ BEAM COUNTER (V count, H count) │ │
|
||||
│ │ Increments every colour clock, resets each frame │ │
|
||||
│ │ PAL: 312 lines × 227 clocks NTSC: 262 × 227 │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
└──────────┬─────────────────────────────────────────────────────────┘
|
||||
│ register writes ($DFF000–$DFF1FE)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ DENISE / LISA (Video Encoder) │
|
||||
│ │
|
||||
│ Receives bitplane data + sprite data + colour register values │
|
||||
│ Composites them into a final pixel stream: │
|
||||
│ │
|
||||
│ ┌────────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ Bitplane │ │ Sprite │ │ Colour │ │ Playfield │ │
|
||||
│ │ Decode │→ │ Priority │→ │ Palette │→ │ Priority & │ │
|
||||
│ │ (planar→ │ │ Merge │ │ Lookup │ │ Genlock Control │ │
|
||||
│ │ index) │ │ │ │ (32/256) │ │ │ │
|
||||
│ └────────────┘ └──────────┘ └──────────┘ └────────┬─────────┘ │
|
||||
└───────────────────────────────────────────────────────┬─────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────┐
|
||||
│ RGB / DAC │
|
||||
│ → Monitor │
|
||||
└────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ M68K CPU │
|
||||
│ │
|
||||
│ • Can read/write the SAME custom registers as the Copper │
|
||||
│ • Can modify the copper list in Chip RAM at any time │
|
||||
│ • Shares the DMA bus with Copper (Agnus arbitrates) │
|
||||
│ • CPU is STALLED when DMA bus is busy (Chip RAM access only) │
|
||||
│ • Fast RAM access is NOT affected by DMA contention │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Component Interactions
|
||||
|
||||
**Copper ↔ Chip RAM:**
|
||||
The Copper fetches its program (the copper list) from Chip RAM via DMA. It reads one instruction (2 words = 4 bytes) every 4 colour clocks. The copper list **must** reside in Chip RAM — it cannot be in Fast RAM because only Chip RAM is DMA-accessible.
|
||||
|
||||
**Copper ↔ Custom Registers:**
|
||||
When the Copper executes a MOVE instruction, it writes directly to a custom chip register (`$DFF000`–`$DFF1FE`). This is the exact same register space the CPU writes to. The Copper can set colours, bitplane pointers, sprite pointers, display window, scroll offsets, DMA control, and audio parameters.
|
||||
|
||||
**Copper ↔ Beam Counter:**
|
||||
The Copper continuously compares the current beam position (V count, H count) against WAIT instructions. When the beam reaches or passes the specified position, execution continues. This is a hardware comparator — no polling loop, no interrupt latency.
|
||||
|
||||
**Copper ↔ CPU:**
|
||||
- They share the DMA bus. Agnus arbitrates: DMA engines get priority, CPU gets remaining cycles
|
||||
- The CPU can modify copper list words in Chip RAM; changes take effect on the next frame (or immediately if the Copper hasn't read that instruction yet)
|
||||
- The CPU can set `COP1LC`/`COP2LC` to change which copper list runs
|
||||
- The CPU can strobe `COPJMP1`/`COPJMP2` to restart the Copper mid-frame
|
||||
- The CPU is **not interrupted** by Copper activity — they are fully independent
|
||||
|
||||
**Copper ↔ Video Output:**
|
||||
The Copper doesn't produce video directly. It modifies the registers that Denise/Lisa uses to produce video. By changing registers at specific beam positions, the Copper indirectly controls what appears on every scanline.
|
||||
|
||||
**Copper ↔ Blitter:**
|
||||
A WAIT instruction with bit 15 of the mask word cleared becomes a "blitter-finished WAIT" — the Copper pauses until both the beam position is reached AND the blitter is idle. This coordinates copper list execution with blitter operations.
|
||||
|
||||
---
|
||||
|
||||
## What the Copper Can Do
|
||||
|
||||
| Effect | How | Used In |
|
||||
|---|---|---|
|
||||
| **Per-line colour changes** | WAIT for line, MOVE colour register | Gradient skies, rainbow bars |
|
||||
| **Split screens** | Change bitplane pointers mid-frame | Status bar + scrolling playfield |
|
||||
| **Parallax scrolling** | Change BPLCON1 (scroll offset) at different lines | Multi-layer side-scrollers |
|
||||
| **Resolution changes** | Change BPLCON0 mid-frame | HiRes menu + LoRes game area |
|
||||
| **Sprite multiplexing** | Repoint sprite DMA pointers after sprite finishes | More than 8 sprites per frame |
|
||||
| **Palette animation** | Modify colour registers each frame | Cycling colours, water shimmer |
|
||||
| **Display window tricks** | Change DIWSTRT/DIWSTOP | Overscan, letterbox |
|
||||
| **Interlace tricks** | Toggle LOF bit | Custom interlace effects |
|
||||
|
||||
### What the Copper Cannot Do
|
||||
|
||||
| Limitation | Detail |
|
||||
|---|---|
|
||||
| No computation | Cannot add, subtract, compare, branch, or loop |
|
||||
| No memory read | Can only WRITE to registers, never read |
|
||||
| Write-only to custom regs | Cannot write to CPU memory, CIA, or Fast RAM |
|
||||
| Limited register set | Protected registers ($000–$03E) need `COPCON` unlock |
|
||||
| No sub-pixel timing | Horizontal resolution is 4 colour clocks (~8 low-res pixels) |
|
||||
| Vertical wrapping | V counter wraps at 255; PAL lines 256+ need two WAITs |
|
||||
|
||||
---
|
||||
|
||||
## Instruction Set
|
||||
|
||||
The Copper has exactly **3 instructions**. Each is 32 bits (two 16-bit words):
|
||||
|
||||
### MOVE — Write Value to Register
|
||||
|
||||
```
|
||||
Word 1: 0RRRRRRR RR000000 R = register offset ($040–$1FE, even)
|
||||
Word 2: DDDDDDDD DDDDDDDD D = 16-bit data to write
|
||||
|
||||
Example: Set COLOR00 ($180) to bright red ($0F00):
|
||||
dc.w $0180, $0F00
|
||||
```
|
||||
|
||||
The register address in word 1 is the offset from `$DFF000`. Bit 0 of word 1 is always 0 (this distinguishes MOVE from WAIT/SKIP).
|
||||
|
||||
### WAIT — Wait for Beam Position
|
||||
|
||||
```
|
||||
Word 1: VVVVVVVV HHHHHHHH V = vertical beam (8 bits), H = horizontal
|
||||
Bit 0 = 1 (marks this as WAIT, not MOVE)
|
||||
Word 2: vvvvvvvv hhhhhhhm v,h = mask bits, m = 0 for WAIT
|
||||
(bit 0 of word 2 = 0 distinguishes from SKIP)
|
||||
|
||||
Example: Wait for line 100 ($64), any horizontal position:
|
||||
dc.w $6401, $FFFE
|
||||
```
|
||||
|
||||
The mask controls which beam position bits are compared. `$FFFE` means "match all bits" (standard). You can mask horizontal bits to wait for a specific column.
|
||||
|
||||
### SKIP — Conditional Skip
|
||||
|
||||
```
|
||||
Same format as WAIT, but bit 0 of word 2 = 1.
|
||||
If beam ≥ specified position, skip the next instruction.
|
||||
|
||||
Example: Skip next if beam is past line 200:
|
||||
dc.w $C801, $FFFF ; SKIP if V ≥ $C8
|
||||
dc.w $0180, $0F00 ; this MOVE is skipped if condition met
|
||||
```
|
||||
|
||||
### End of List
|
||||
|
||||
```
|
||||
dc.w $FFFF, $FFFE ; WAIT for impossible position (V=$FF, H=$FF)
|
||||
; Copper halts until next frame
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Your First Copper List
|
||||
|
||||
Here's the simplest possible copper list — it changes the background colour at line 128:
|
||||
|
||||
```asm
|
||||
SECTION copperlist,DATA_C ; *** MUST be in Chip RAM! ***
|
||||
|
||||
MyCopperList:
|
||||
; Top half: blue background
|
||||
dc.w $0180, $005F ; MOVE COLOR00 = blue
|
||||
|
||||
; Wait for middle of screen
|
||||
dc.w $8001, $FFFE ; WAIT line 128
|
||||
|
||||
; Bottom half: red background
|
||||
dc.w $0180, $0F00 ; MOVE COLOR00 = red
|
||||
|
||||
; End of list
|
||||
dc.w $FFFF, $FFFE ; WAIT forever
|
||||
```
|
||||
|
||||
To activate it:
|
||||
```asm
|
||||
lea $DFF000,a5
|
||||
move.l #MyCopperList,$080(a5) ; COP1LCH = pointer to our list
|
||||
move.w d0,$088(a5) ; COPJMP1 strobe = restart copper
|
||||
move.w #$8280,$096(a5) ; DMACON: enable Copper + Master DMA
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rainbow Gradient (Colour Per Scanline)
|
||||
|
||||
```asm
|
||||
RainbowCopper:
|
||||
dc.w $2C01,$FFFE ; WAIT line 44 (first visible PAL line)
|
||||
dc.w $0180,$0F00 ; red
|
||||
dc.w $2D01,$FFFE ; line 45
|
||||
dc.w $0180,$0E10
|
||||
dc.w $2E01,$FFFE ; line 46
|
||||
dc.w $0180,$0D20
|
||||
dc.w $2F01,$FFFE ; line 47
|
||||
dc.w $0180,$0C30
|
||||
dc.w $3001,$FFFE ; line 48
|
||||
dc.w $0180,$0B40
|
||||
dc.w $3101,$FFFE ; line 49
|
||||
dc.w $0180,$0A50
|
||||
dc.w $3201,$FFFE ; line 50
|
||||
dc.w $0180,$0960
|
||||
; ... continue for each line ...
|
||||
dc.w $FFFF,$FFFE
|
||||
```
|
||||
|
||||
This produces a smooth colour gradient down the screen — **zero CPU cost**.
|
||||
|
||||
---
|
||||
|
||||
## Parallax Scrolling (Per-Layer Scroll Speed)
|
||||
|
||||
```asm
|
||||
ParallaxCopper:
|
||||
; Sky layer (no scroll)
|
||||
dc.w $0102,$0000 ; BPLCON1 = 0 (no shift)
|
||||
|
||||
; Wait for horizon
|
||||
dc.w $6001,$FFFE ; WAIT line 96
|
||||
|
||||
; Hills layer (scroll slow)
|
||||
dc.w $0102,$0022 ; BPLCON1 = shift 2 pixels
|
||||
|
||||
; Wait for ground
|
||||
dc.w $A001,$FFFE ; WAIT line 160
|
||||
|
||||
; Ground layer (scroll fast)
|
||||
dc.w $0102,$0066 ; BPLCON1 = shift 6 pixels
|
||||
|
||||
dc.w $FFFF,$FFFE
|
||||
```
|
||||
|
||||
Each frame, a VBlank interrupt updates the scroll values in the copper list. The CPU just modifies 3 words — the Copper handles all the per-line register changes.
|
||||
|
||||
---
|
||||
|
||||
## Sprite Multiplexing
|
||||
|
||||
The Amiga has 8 hardware sprites, but the Copper can repoint them mid-frame for more:
|
||||
|
||||
```asm
|
||||
; Sprite 0 shows character A at Y=50
|
||||
dc.w $3001,$FFFE ; WAIT before sprite starts
|
||||
dc.w $0120,SprDataA>>16 ; SPR0PTH
|
||||
dc.w $0122,SprDataA ; SPR0PTL
|
||||
|
||||
; After sprite A finishes (Y=66), reuse for character B at Y=120
|
||||
dc.w $7801,$FFFE ; WAIT line 120
|
||||
dc.w $0120,SprDataB>>16 ; SPR0PTH = new sprite data
|
||||
dc.w $0122,SprDataB ; SPR0PTL
|
||||
|
||||
; After character B finishes, reuse for character C...
|
||||
dc.w $A001,$FFFE
|
||||
dc.w $0120,SprDataC>>16
|
||||
dc.w $0122,SprDataC
|
||||
```
|
||||
|
||||
This gives you **24+ sprites** on screen (8 physical × 3+ reuses per frame).
|
||||
|
||||
---
|
||||
|
||||
## System-Friendly Copper (OS API)
|
||||
|
||||
If your program coexists with Workbench, use `graphics.library`:
|
||||
|
||||
```c
|
||||
struct UCopList *ucl = AllocMem(sizeof(struct UCopList), MEMF_CLEAR);
|
||||
|
||||
CINIT(ucl, 50); /* init, max 50 instructions */
|
||||
CWAIT(ucl, 0, 0); /* wait top of screen */
|
||||
CMOVE(ucl, custom.color[0], 0x005F); /* COLOR00 = blue */
|
||||
CWAIT(ucl, 128, 0); /* wait line 128 */
|
||||
CMOVE(ucl, custom.color[0], 0x0F00); /* COLOR00 = red */
|
||||
CEND(ucl); /* end */
|
||||
|
||||
viewport->UCopIns = ucl;
|
||||
RethinkDisplay(); /* merge into system copper list */
|
||||
```
|
||||
|
||||
The OS inserts your instructions into its own copper list, interleaved with its own display management.
|
||||
|
||||
---
|
||||
|
||||
## AGA Copper Enhancements
|
||||
|
||||
AGA (Alice chip) keeps the same 3-instruction Copper but gains access to the **extended AGA registers**:
|
||||
|
||||
| AGA Feature | Copper Can Set |
|
||||
|---|---|
|
||||
| 256-colour palette | `COLOR00–COLOR255` via BPLCON3 bank select |
|
||||
| Extended sprites | 64-colour sprites via palette banks |
|
||||
| FMODE | DMA fetch width (but careful — affects in-progress DMA) |
|
||||
| BPLCON3/BPLCON4 | AGA-specific bitplane/sprite control |
|
||||
|
||||
### AGA Palette via Copper
|
||||
|
||||
AGA has 256 colours but still only 32 colour registers visible at a time. To load all 256 colours, the Copper uses BPLCON3 to select palette banks:
|
||||
|
||||
```asm
|
||||
; Load colours 0–31 (bank 0)
|
||||
dc.w $0106,$0000 ; BPLCON3: bank 0
|
||||
dc.w $0180,$0000 ; COLOR00
|
||||
dc.w $0182,$0111 ; COLOR01
|
||||
; ... all 32 colours ...
|
||||
|
||||
; Switch to bank 1 (colours 32–63)
|
||||
dc.w $0106,$2000 ; BPLCON3: bank 1
|
||||
dc.w $0180,$0222 ; COLOR32
|
||||
dc.w $0182,$0333 ; COLOR33
|
||||
; ... etc for all 8 banks ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Copper Timing
|
||||
|
||||
| Parameter | Value |
|
||||
|---|---|
|
||||
| Instruction time | 4 colour clocks (= 8 lo-res pixels = ~1.12 µs) |
|
||||
| Max instructions per line | ~112 (NTSC) / ~114 (PAL) |
|
||||
| Horizontal resolution | 4 colour clocks (~8 lo-res pixels) |
|
||||
| Vertical range | 0–255 (wraps; use double-WAIT for PAL lines 256+) |
|
||||
| PAL visible lines | 44–300 (256 visible) |
|
||||
| NTSC visible lines | 44–244 (200 visible) |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- HRM: *Copper* chapter — authoritative register descriptions
|
||||
- `08_graphics/copper.md` — graphics.library UCopList API
|
||||
- `08_graphics/copper_programming.md` — additional examples
|
||||
- `01_hardware/ocs_a500/copper.md` — OCS-level register reference
|
||||
122
01_hardware/aga_a1200_a4000/aga_display_modes.md
Normal file
122
01_hardware/aga_a1200_a4000/aga_display_modes.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# AGA Display Modes
|
||||
|
||||
## Overview
|
||||
|
||||
AGA introduces several new display modes and extends existing ones, enabled via the OS **screenmode** system (`graphics/modeid.h`) and `OpenScreenTags()`.
|
||||
|
||||
## Mode ID System
|
||||
|
||||
AmigaOS uses 32-bit **ModeIDs** to identify display modes. The format is:
|
||||
```
|
||||
[Monitor ID (16 bits)] | [Mode flags (16 bits)]
|
||||
```
|
||||
|
||||
Key AGA monitor IDs:
|
||||
```c
|
||||
#define PAL_MONITOR_ID 0x00000000
|
||||
#define NTSC_MONITOR_ID 0x00010000
|
||||
#define A2024_MONITOR_ID 0x00020000
|
||||
#define VGA_MONITOR_ID 0x00031000 /* ECS productivity */
|
||||
#define A2024_10HZ_ID 0x00040000
|
||||
#define DBLPAL_MONITOR_ID 0x00420000 /* AGA double PAL */
|
||||
#define DBLNTSC_MONITOR_ID 0x00400000 /* AGA double NTSC */
|
||||
#define SUPER72_MONITOR_ID 0x00080000
|
||||
```
|
||||
|
||||
Mode flags (lower 16 bits):
|
||||
```c
|
||||
#define LORES_KEY 0x0000 /* 320 wide (PAL) */
|
||||
#define HIRES_KEY 0x8000 /* 640 wide */
|
||||
#define HAM_KEY 0x0800 /* HAM mode */
|
||||
#define EXTRAHALFBRITE_KEY 0x0080 /* EHB */
|
||||
#define LACE_KEY 0x0004 /* interlace */
|
||||
```
|
||||
|
||||
## Standard AGA Modes
|
||||
|
||||
| Mode ID | Resolution | Colours | H rate |
|
||||
|---|---|---|---|
|
||||
| `PAL_MONITOR_ID \| LORES_KEY` | 320×256 | 256 | 15.6 kHz |
|
||||
| `PAL_MONITOR_ID \| HIRES_KEY` | 640×256 | 256 | 15.6 kHz |
|
||||
| `PAL_MONITOR_ID \| HIRES_KEY \| LACE_KEY` | 640×512 | 256 | 15.6 kHz (interlace) |
|
||||
| `DBLPAL_MONITOR_ID \| LORES_KEY` | 320×512 | 256 | 31.25 kHz |
|
||||
| `DBLPAL_MONITOR_ID \| HIRES_KEY` | 640×512 | 256 | 31.25 kHz |
|
||||
| `PAL_MONITOR_ID \| LORES_KEY \| HAM_KEY` | 320×256 | 262,144 (HAM8) | 15.6 kHz |
|
||||
| `SUPER72_MONITOR_ID \| HIRES_KEY` | 800×600 (approx) | 256 | 28+ kHz |
|
||||
|
||||
## Opening an AGA Screen (OS 3.1)
|
||||
|
||||
```c
|
||||
#include <intuition/screens.h>
|
||||
#include <graphics/modeid.h>
|
||||
#include <proto/intuition.h>
|
||||
|
||||
struct Screen *scr;
|
||||
|
||||
/* 256-colour AGA screen, PAL, 320×256 */
|
||||
scr = OpenScreenTags(NULL,
|
||||
SA_DisplayID, PAL_MONITOR_ID | LORES_KEY,
|
||||
SA_Width, 320,
|
||||
SA_Height, 256,
|
||||
SA_Depth, 8, /* 8 bitplanes = 256 colours */
|
||||
SA_Colors32, (ULONG)colour_table, /* LoadRGB32 format */
|
||||
SA_Title, (ULONG)"My AGA Screen",
|
||||
SA_Quiet, TRUE,
|
||||
TAG_DONE);
|
||||
```
|
||||
|
||||
## HAM8 Screen
|
||||
|
||||
```c
|
||||
scr = OpenScreenTags(NULL,
|
||||
SA_DisplayID, PAL_MONITOR_ID | LORES_KEY | HAM_KEY,
|
||||
SA_Width, 320,
|
||||
SA_Height, 256,
|
||||
SA_Depth, 8,
|
||||
TAG_DONE);
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> HAM8 screens require 8 bitplanes. The display system automatically programmes BPLCON0 with HAM=1. The first 64 colour registers are used as the HAM8 index palette.
|
||||
|
||||
## BestModeID() — Querying Available Modes
|
||||
|
||||
```c
|
||||
#include <proto/graphics.h>
|
||||
|
||||
ULONG modeid = BestModeID(
|
||||
BIDTAG_NominalWidth, 640,
|
||||
BIDTAG_NominalHeight, 512,
|
||||
BIDTAG_Depth, 8,
|
||||
BIDTAG_MonitorID, DBLPAL_MONITOR_ID,
|
||||
TAG_DONE);
|
||||
|
||||
if (modeid == INVALID_ID) {
|
||||
/* Requested mode not available */
|
||||
}
|
||||
```
|
||||
|
||||
## Double Scan Modes (DblPAL / DblNTSC)
|
||||
|
||||
`DBLPAL` and `DBLNTSC` modes use AGA's scan doubler to produce non-interlaced 31 kHz output from PAL/NTSC timing:
|
||||
|
||||
- DblPAL: 320×512 or 640×512, 31.25 kHz — compatible with VGA monitors
|
||||
- DblNTSC: 320×400 or 640×400, 31.47 kHz
|
||||
|
||||
These require a multisync monitor and AGA chipset. The A1200 can drive a 1084S in scan-doubled mode.
|
||||
|
||||
## Super72 Mode
|
||||
|
||||
Super72 provides approximately 800×600 resolution at ~28 kHz horizontal:
|
||||
- Used by some Workbench productivity configurations
|
||||
- Requires multisync monitor
|
||||
- Available via `SUPER72_MONITOR_ID`
|
||||
|
||||
## References
|
||||
|
||||
- NDK39: `graphics/modeid.h` — all monitor and mode ID definitions
|
||||
- ADCD 2.1: `Libraries_Manual_guide/` — graphics.library OpenScreen
|
||||
- Autodocs: `BestModeID`, `OpenScreenTags`
|
||||
- AmigaMail Vol. 2 — AGA display mode programming
|
||||
134
01_hardware/aga_a1200_a4000/aga_palette.md
Normal file
134
01_hardware/aga_a1200_a4000/aga_palette.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# AGA Palette & Colour System
|
||||
|
||||
## Overview
|
||||
|
||||
AGA provides **256 colour registers** (COLOR00–COLOR255), each **24-bit RGB** (8 bits per channel). This replaces OCS/ECS's 32 registers with 12-bit colour.
|
||||
|
||||
## Colour Register Layout
|
||||
|
||||
```
|
||||
ADDRESS: $DFF180 + (n × 2) for register n (0–255)
|
||||
```
|
||||
|
||||
AGA extends the register space:
|
||||
```
|
||||
$DFF180–$DFF1BE COLOR00–COLOR31 (same addresses as OCS/ECS)
|
||||
$DFF180–$DFF3BE COLOR00–COLOR255 (full AGA range — needs BPLCON4 bank select)
|
||||
```
|
||||
|
||||
The 256 colour registers are accessed in 64-register **banks** selected by `BPLCON4`.
|
||||
|
||||
## Writing 24-bit Colours
|
||||
|
||||
Each colour register holds 12 bits directly (OCS/ECS compatible). The upper 12 bits (the "low nibble") are written via a second access with `LOCT` set in BPLCON3.
|
||||
|
||||
### Manual 24-bit write sequence:
|
||||
|
||||
```asm
|
||||
; Write color $FF8040 (R=$FF, G=$80, B=$40) to COLOR00
|
||||
|
||||
; Step 1: Write high nibble ($F84 = top 4 bits of R,G,B)
|
||||
move.w #$0F84, COLOR00+custom ; $0RGB high nibble
|
||||
|
||||
; Step 2: Set LOCT bit in BPLCON3 to enable low nibble write
|
||||
bset #9, BPLCON3+custom+1 ; bit 9
|
||||
|
||||
; Step 3: Write low nibble ($F04 = low 4 bits of R,G,B → $0F, $08, $04 → $F84 again!)
|
||||
; Actually: low nibble of FF = F, low nibble of 80 = 0, low nibble of 40 = 0
|
||||
move.w #$0F00, COLOR00+custom ; low nibble
|
||||
|
||||
; Step 4: Clear LOCT
|
||||
bclr #9, BPLCON3+custom+1
|
||||
```
|
||||
|
||||
### Using LoadRGB32()
|
||||
|
||||
The preferred OS call:
|
||||
```c
|
||||
#include <graphics/view.h>
|
||||
#include <proto/graphics.h>
|
||||
|
||||
/* Table: count, index, then 0x00RRGGBB values, terminated by ~0 */
|
||||
ULONG table[] = {
|
||||
4, 0, /* 4 colours starting at index 0 */
|
||||
0x00FF0000, /* COLOR00: red */
|
||||
0x0000FF00, /* COLOR01: green */
|
||||
0x000000FF, /* COLOR02: blue */
|
||||
0x00FFFFFF, /* COLOR03: white */
|
||||
~0UL /* terminator */
|
||||
};
|
||||
LoadRGB32(viewport, table);
|
||||
```
|
||||
|
||||
`LoadRGB32()` (graphics.library LVO -$192) is the AGA-correct way to set colours. It handles the two-write LOCT protocol internally and is available from OS 3.0+.
|
||||
|
||||
### Using LoadRGB4() — OCS/ECS compatible (12-bit)
|
||||
|
||||
```c
|
||||
UWORD colours[32] = { 0x000, 0xF00, 0x0F0, ... };
|
||||
LoadRGB4(viewport, colours, 32); /* sets 32 colours from 12-bit table */
|
||||
```
|
||||
|
||||
`LoadRGB4()` is safe on all chipsets but only provides 12-bit precision on AGA.
|
||||
|
||||
## HAM8 Mode (Hold-And-Modify, 8-bit)
|
||||
|
||||
HAM8 is the AGA extension of OCS's HAM6. It uses 8 bitplanes:
|
||||
|
||||
- **Bits 7-6** of each pixel: mode select
|
||||
- `00` = index mode (look up COLOR00–COLOR63)
|
||||
- `01` = modify blue channel
|
||||
- `10` = modify red channel
|
||||
- `11` = modify green channel
|
||||
- **Bits 5-0**: 6-bit value for the selected channel (or 6-bit colour index)
|
||||
|
||||
Result: 2^18 = **262,144 simultaneous colours** from adjacent-pixel modification.
|
||||
|
||||
Enabling HAM8:
|
||||
```asm
|
||||
; BPLCON0: 8 planes (BPU=8, BPU3=1, BPU2-0=000), HAM=1, ECSENA=1
|
||||
move.w #$9811, BPLCON0+custom
|
||||
```
|
||||
|
||||
## Colour Modes Summary
|
||||
|
||||
| Mode | Planes | Colours | Method |
|
||||
|---|---|---|---|
|
||||
| Standard | 1–8 | 2–256 | Direct palette lookup |
|
||||
| EHB | 6 | 64 | Extra Half-Brite (OCS/ECS compat) |
|
||||
| HAM6 | 6 | 4096 | Hold-and-modify 4-bit channels |
|
||||
| HAM8 | 8 | 262,144 | Hold-and-modify 6-bit channels |
|
||||
| Dual Playfield | 3+3 | 8+8 | Two independent 8-colour layers |
|
||||
|
||||
## Colour Bank Selection (BPLCON4)
|
||||
|
||||
The 256 colour registers are split into 4 banks of 64:
|
||||
|
||||
| BPLAM | Bank | Registers |
|
||||
|---|---|---|
|
||||
| $00 | 0 | COLOR00–COLOR63 |
|
||||
| $40 | 1 | COLOR64–COLOR127 |
|
||||
| $80 | 2 | COLOR128–COLOR191 |
|
||||
| $C0 | 3 | COLOR192–COLOR255 |
|
||||
|
||||
Dual playfield can use BPLCON4 to give each playfield a different 64-colour bank.
|
||||
|
||||
## OS Colour Management
|
||||
|
||||
`graphics.library` manages palette via the `ColorMap` structure attached to a `ViewPort`:
|
||||
|
||||
```c
|
||||
struct ColorMap *cm = GetColorMap(256); /* allocate 256-entry AGA map */
|
||||
SetRGB32(vp, n, r, g, b); /* set one colour (24-bit each) */
|
||||
LoadRGB32(vp, table); /* bulk load */
|
||||
FreeColorMap(cm);
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- NDK39: `graphics/view.h` — ColorMap, LoadRGB32
|
||||
- ADCD 2.1 Autodocs: graphics — LoadRGB32, SetRGB32
|
||||
- http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node02B4.html
|
||||
- AmigaMail Vol. 2 — AGA colour system articles
|
||||
97
01_hardware/aga_a1200_a4000/aga_registers_delta.md
Normal file
97
01_hardware/aga_a1200_a4000/aga_registers_delta.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# AGA Register Deltas vs ECS
|
||||
|
||||
## New Registers
|
||||
|
||||
### FMODE — $DFF1FC (AGA only)
|
||||
|
||||
DMA fetch mode — see `chipset_aga.md` for full description.
|
||||
|
||||
### BPLCON4 — $DFF10C (AGA only)
|
||||
|
||||
Bitplane and sprite colour bank selection:
|
||||
|
||||
```
|
||||
bits 15-8: BPLAM7-0 — Bitplane XOR pattern (AGA colour bank XOR)
|
||||
bits 7-4: ESPRM7-4 — Even sprite colour bank (bits 7:4 of colour reg index)
|
||||
bits 3-0: OSPRM7-4 — Odd sprite colour bank
|
||||
```
|
||||
|
||||
**Bitplane bank select via BPLAM:**
|
||||
- BPLAM provides an XOR mask applied to the 8-bit colour index before palette lookup
|
||||
- BPLAM = $00 → use COLOR00–COLOR63 (bank 0)
|
||||
- BPLAM = $40 → use COLOR64–COLOR127 (bank 1)
|
||||
- BPLAM = $80 → use COLOR128–COLOR191 (bank 2)
|
||||
- BPLAM = $C0 → use COLOR192–COLOR255 (bank 3)
|
||||
|
||||
### COLOR00–COLOR255 — $DFF180–$DFF3BE (AGA)
|
||||
|
||||
AGA extends the colour table from 32 registers (OCS/ECS) to **256 registers**.
|
||||
|
||||
Each AGA colour register is 32 bits (accessed as two word writes via BPLCON3 latch):
|
||||
|
||||
```asm
|
||||
; Write 24-bit colour to COLOR00:
|
||||
; First write sets high nibble, second sets low nibble
|
||||
move.w #$0000, BPLCON3+custom ; set LACE=0, select low colour word
|
||||
move.w #$0FFF, COLOR00+custom ; write $RGB (high 12 bits)
|
||||
bset #9, BPLCON3_shadow ; set LOCT (low nibble enable)
|
||||
move.w #$0FFF, COLOR00+custom ; write low nibble of each channel
|
||||
```
|
||||
|
||||
The standard `LoadRGB32()` and `LoadRGB4()` graphics library calls manage this transparently.
|
||||
|
||||
## Changed Registers
|
||||
|
||||
### BPLCON2 — $DFF104 (AGA extended)
|
||||
|
||||
```
|
||||
bits 14-9: KILLEHB — kill EHB mode (AGA replaces EHB with 256 colour)
|
||||
bit 6: RDRAM — read bitplane data from RAM (not registered in Lisa)
|
||||
bits 5-3: PF2PRI — playfield 2 priority
|
||||
bits 2-0: PF1PRI — playfield 1 priority + sprite priority
|
||||
```
|
||||
|
||||
### BPLCON3 — $DFF106 (AGA extended from ECS)
|
||||
|
||||
Additional AGA bits:
|
||||
```
|
||||
bit 9: LOCT — low colour write enable (for 24-bit colour access)
|
||||
bit 3: BRDSPRT — sprites visible in border
|
||||
```
|
||||
|
||||
## AGA-Specific BPLCON0 Bits
|
||||
|
||||
See `chipset_aga.md` — bit 4 is the MSB of the bitplane count for 7/8-plane modes.
|
||||
|
||||
## Colour Register Access — Low Nibble Protocol
|
||||
|
||||
Writing 24-bit colour to AGA registers requires two steps per colour:
|
||||
|
||||
1. **Write high nibble** (standard): `COLOR00 = $0RGB` (bits [11:0] = R[3:0], G[3:0], B[3:0])
|
||||
2. **Set LOCT** in BPLCON3 (bit 9)
|
||||
3. **Write low nibble**: `COLOR00 = $0rgb` (bits [11:0] = R[3:0], G[3:0], B[3:0], these are the low 4 bits)
|
||||
|
||||
This two-write sequence gives 8 bits per channel (R[7:0], G[7:0], B[7:0]) = 24-bit colour.
|
||||
|
||||
`LoadRGB32()` does this automatically:
|
||||
```c
|
||||
/* AGA 32-bit colour table format:
|
||||
Count, then pairs: [colour_index, 0x00RRGGBB] */
|
||||
ULONG colour_table[] = {
|
||||
32, 0, /* 32 colours starting at index 0 */
|
||||
0x00FF0000, /* COLOR00 = red */
|
||||
0x0000FF00, /* COLOR01 = green */
|
||||
/* ... */
|
||||
~0UL /* terminator */
|
||||
};
|
||||
LoadRGB32(vp, colour_table);
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- ADCD 2.1 Hardware Manual — AGA register appendix
|
||||
- NDK39: `hardware/custom.h`, `graphics/view.h`
|
||||
- Commodore A1200/A4000 Technical Reference Manuals
|
||||
- AmigaMail Vol. 2 — AGA colour programming
|
||||
120
01_hardware/aga_a1200_a4000/chipset_aga.md
Normal file
120
01_hardware/aga_a1200_a4000/chipset_aga.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# AGA Chipset Internals — Alice & Lisa
|
||||
|
||||
## Alice (MOS 8374) — AGA Agnus
|
||||
|
||||
Alice is the successor to Super Agnus and is the DMA controller and Copper/Blitter engine for AGA machines.
|
||||
|
||||
### Key Enhancements over Super Agnus
|
||||
|
||||
**64-bit DMA fetch bus (FMODE):**
|
||||
Alice can fetch 2 or 4 words per DMA cycle via the `FMODE` register ($DFF1FC). This dramatically increases the bandwidth available to the blitter and bitplane DMA.
|
||||
|
||||
**Extended bitplane depth:**
|
||||
Alice supports up to **8 bitplanes** (256 colours), compared to OCS/ECS's 6-plane limit.
|
||||
|
||||
**BPLCON4:**
|
||||
Alice adds `BPLCON4` to control bitplane bank selection — which 64-entry block of the 256-entry colour table is used by the bitplanes.
|
||||
|
||||
### ALICE_ID
|
||||
|
||||
Alice can be identified via `VPOSR`:
|
||||
```asm
|
||||
move.w $DFF004, d0 ; VPOSR
|
||||
lsr.w #8, d0
|
||||
```
|
||||
|
||||
| VPOSR[15:8] | Chip |
|
||||
|---|---|
|
||||
| $22 | Alice AGA (standard) |
|
||||
| $23 | Alice AGA (some A4000 revisions) |
|
||||
|
||||
---
|
||||
|
||||
## Lisa (AGA Denise)
|
||||
|
||||
Lisa is the display chip successor to ECS Denise, providing 8-bit colour output (256 colour registers) and extended sprite capabilities.
|
||||
|
||||
### Key Enhancements over ECS Denise
|
||||
|
||||
**256 colour registers:**
|
||||
Lisa provides COLOR00–COLOR255, each 24-bit (32-bit register with low byte unused).
|
||||
|
||||
**4 colour banks for bitplanes:**
|
||||
`BPLCON4` selects which 64-register bank (0–3) the bitplanes use for lookup. This allows dual-playfield each using a different 64-colour palette.
|
||||
|
||||
**Sprite bank selection:**
|
||||
`BPLCON3` bits select which colour bank sprite pairs use.
|
||||
|
||||
**Extended sprite width:**
|
||||
Sprites can be 16 or 64 pixels wide in AGA mode.
|
||||
|
||||
**Lisa ID:**
|
||||
Readable from `$DFF07C` (DENISEID):
|
||||
```asm
|
||||
move.w $DFF07C, d0 ; DENISEID = $00F8 for AGA Lisa
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FMODE — DMA Fetch Width Register ($DFF1FC)
|
||||
|
||||
The most critical AGA-specific register. Controls the data bus width for blitter and bitplane DMA:
|
||||
|
||||
```
|
||||
bits 15-14: SPR_FMODE — sprite fetch mode
|
||||
bits 13-12: BPL_FMODE — bitplane fetch mode
|
||||
bits 9-8: BLT_FMODE — blitter fetch mode
|
||||
|
||||
00 = 1× (16-bit, OCS/ECS compatible)
|
||||
01 = 2× (32-bit)
|
||||
10 = 4× (64-bit)
|
||||
11 = reserved
|
||||
```
|
||||
|
||||
**Setting full 64-bit blitter mode:**
|
||||
```asm
|
||||
move.w #$00C0, $DFF1FC ; FMODE: BLT_FMODE=11 (64-bit)
|
||||
; Also set BPL and SPR modes as needed
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Writing FMODE on OCS/ECS machines writes to the `LISAID` location (read-only) — no hardware damage, but the read-back value is incorrect. Always verify AGA presence before writing FMODE.
|
||||
|
||||
---
|
||||
|
||||
## DMA Bandwidth with FMODE
|
||||
|
||||
| FMODE | Bus width | Blitter speed | Bitplane DMA |
|
||||
|---|---|---|---|
|
||||
| 1× (OCS compat) | 16-bit | 1× | 1× |
|
||||
| 2× | 32-bit | 2× | 2× |
|
||||
| 4× | 64-bit | 4× | 4× |
|
||||
|
||||
At 4× mode, the AGA blitter can fill/copy at ~70 MB/s theoretical on a 7 MHz bus.
|
||||
|
||||
---
|
||||
|
||||
## BPLCON0 Extended Bits (AGA)
|
||||
|
||||
In AGA mode, `BPLCON0` bit 4 (`ECSENA`) must be **1** to enable AGA features. Additional BPU bit (bit 4 of the count) allows 7 and 8 planes:
|
||||
|
||||
```
|
||||
bits 14-12: BPU2-0 — lower 3 bits of bitplane count
|
||||
bit 4: BPU3 — MSB of bitplane count (AGA: allows 7, 8 planes)
|
||||
```
|
||||
|
||||
To use 8 bitplanes (256 colours):
|
||||
```asm
|
||||
move.w #$9411, BPLCON0+custom ; HIRES=1 (if needed), BPU=8 (BPU3=1, BPU2-0=000), ECSENA=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- ADCD 2.1 Hardware Manual — AGA chapter
|
||||
- NDK39: `hardware/custom.h` — struct Custom (with AGA extensions)
|
||||
- Commodore A1200 Technical Reference Manual — Alice/Lisa section
|
||||
- AmigaMail Vol. 2 — AGA programming articles
|
||||
139
01_hardware/aga_a1200_a4000/cpu_030_040.md
Normal file
139
01_hardware/aga_a1200_a4000/cpu_030_040.md
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# 68030/040 on the Amiga (A3000/A4000)
|
||||
|
||||
## Overview
|
||||
|
||||
The A3000 ships with a **Motorola 68030** at 16 or 25 MHz. The A4000 ships with either a 68030 or **68040** at 25 MHz. Later accelerator cards bring the 68060. This document covers CPU-specific concerns for AmigaOS 3.1/3.2 on these platforms.
|
||||
|
||||
## 68030 (A3000)
|
||||
|
||||
### On-Chip Caches
|
||||
- **Instruction cache**: 256 bytes, direct-mapped
|
||||
- **Data cache**: 256 bytes, direct-mapped
|
||||
- Both enabled by default on AmigaOS 3.1 (`CacheControl()` call)
|
||||
|
||||
### On-Chip PMMU
|
||||
- Full 68030 PMMU: ATC (Address Translation Cache), TT registers
|
||||
- AmigaOS does **not** use the MMU by default on A3000
|
||||
- Third-party tools (e.g., VMM, mmu.library) use it for virtual memory
|
||||
|
||||
### Cache Control (exec)
|
||||
```c
|
||||
#include <proto/exec.h>
|
||||
|
||||
/* Enable instruction and data caches */
|
||||
CacheControl(CACRF_EnableI | CACRF_EnableD, CACRF_EnableI | CACRF_EnableD);
|
||||
|
||||
/* Flush caches (required before self-modifying code) */
|
||||
CacheClearU(); /* clear all caches */
|
||||
CacheClearE(addr, len, CACRF_ClearI | CACRF_ClearD); /* targeted flush */
|
||||
```
|
||||
|
||||
### Cache Coherency with DMA
|
||||
The 68030 data cache is **not snooped** by the Amiga chip bus. If the CPU writes to a buffer that the DMA engine (Blitter, audio, custom chips) will read, the cache must be flushed first:
|
||||
|
||||
```c
|
||||
/* Before handing a buffer to DMA: */
|
||||
CacheClearE(buf, size, CACRF_ClearD);
|
||||
```
|
||||
|
||||
Similarly, after DMA writes to a buffer that the CPU will read:
|
||||
```c
|
||||
CacheClearE(buf, size, CACRF_ClearD);
|
||||
```
|
||||
|
||||
This is a common source of bugs in audio/video programming on 68030+ Amigas.
|
||||
|
||||
---
|
||||
|
||||
## 68040 (A4000 / Accelerators)
|
||||
|
||||
### On-Chip FPU — Partial Implementation
|
||||
The 68040 has an on-chip FPU but omits many instructions present in the 68881/68882:
|
||||
|
||||
**Missing from 68040 FPU:**
|
||||
- `FSIN`, `FCOS`, `FTAN`, `FASIN`, `FACOS`, `FATAN`
|
||||
- `FETOX`, `FETOXM1`, `FLOGN`, `FLOG10`
|
||||
- `FSINH`, `FCOSH`, `FTANH`
|
||||
- `FATANH`, `FASINH`, `FACOSH`
|
||||
- `FSCALE`, `FREMX`, `FREMX`, `FINTRZ`
|
||||
|
||||
AmigaOS provides `68040.library` which installs Line-F exception handlers to emulate the missing instructions in software.
|
||||
|
||||
```c
|
||||
/* 68040.library is opened automatically by exec at boot */
|
||||
/* Software should check that it is open before using FP */
|
||||
struct Library *MathLib = OpenLibrary("68040.library", 0);
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> If `68040.library` is not installed and software uses a missing 68040 FPU instruction, the system will crash with a Line-F exception. Always ensure `68040.library` is present on A4000.
|
||||
|
||||
### 4 KB Instruction + Data Caches
|
||||
- 68040 has **4 KB instruction cache** and **4 KB data cache**, both 4-way set-associative
|
||||
- Cache coherency is more complex: DMA writes may not be visible to the CPU without invalidation
|
||||
- `CacheClearE()` / `CacheClearU()` remain the correct API
|
||||
|
||||
### 68040 Memory Model
|
||||
```
|
||||
CACR (Cache Control Register) accessed via MOVEC:
|
||||
bit 15: EDC — enable data cache
|
||||
bit 14: NAD — no allocate data (streaming mode)
|
||||
bit 13: ESB — enable store buffer
|
||||
bit 10: DPI — disable push-inhibit
|
||||
bit 7: EIC — enable instruction cache
|
||||
bit 3: CINV — cache invalidate
|
||||
```
|
||||
|
||||
### Bus Error Stack Frame (68040)
|
||||
The 68040 generates a **different bus error stack frame** from the 68000:
|
||||
- 68000: 14-byte frame
|
||||
- 68040: 104-byte frame with pipeline state
|
||||
|
||||
This matters for exception handlers and debuggers targeting both platforms.
|
||||
|
||||
---
|
||||
|
||||
## 68060 (Accelerator Cards)
|
||||
|
||||
Available via Blizzard 060, CyberStorm 060, etc. Key differences:
|
||||
|
||||
- **Superscalar**: two integer pipelines (in-order, no OOO)
|
||||
- **Branch prediction**: static and dynamic
|
||||
- **No MOVE16 snooping** on some Amiga implementations
|
||||
- On-chip FPU: missing same transcendentals as 68040 → needs `68060.library`
|
||||
- Separate `68060.library` for the additional missing instructions vs 68040
|
||||
|
||||
```c
|
||||
struct Library *Lib060 = OpenLibrary("68060.library", 0);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AmigaOS exec CacheControl() API
|
||||
|
||||
```c
|
||||
#include <exec/execbase.h>
|
||||
#include <proto/exec.h>
|
||||
|
||||
/* SysBase->CacheFlags reflect current cache state */
|
||||
ULONG flags = CacheControl(0, 0); /* query without changing */
|
||||
|
||||
/* Flag bits: */
|
||||
#define CACRF_EnableD (1L<<3) /* data cache enable */
|
||||
#define CACRF_FreezeD (1L<<4) /* data cache freeze */
|
||||
#define CACRF_ClearD (1L<<5) /* clear data cache */
|
||||
#define CACRF_EnableI (1L<<8) /* instruction cache enable */
|
||||
#define CACRF_FreezeI (1L<<9) /* instruction cache freeze */
|
||||
#define CACRF_ClearI (1L<<10) /* clear instruction cache */
|
||||
#define CACRF_CopyBack (1L<<31) /* data cache write-back mode */
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- Motorola 68030 User's Manual (M68030UM/AD)
|
||||
- Motorola 68040 User's Manual (M68040UM/AD)
|
||||
- NDK39: `exec/execbase.h`, `proto/exec.h` — CacheControl, CacheClearE
|
||||
- ADCD 2.1: `Libraries_Manual_guide/` — exec CacheControl autodoc
|
||||
- Commodore A3000/A4000 Technical Reference Manuals
|
||||
97
01_hardware/aga_a1200_a4000/gayle_ide_a1200.md
Normal file
97
01_hardware/aga_a1200_a4000/gayle_ide_a1200.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md)
|
||||
|
||||
# Gayle — A1200 IDE & PCMCIA
|
||||
|
||||
## Overview
|
||||
|
||||
The A1200 uses a different revision of **Gayle** than the A600. The A1200 Gayle integrates:
|
||||
- **ATA/IDE interface** (for one hard drive + optional CD-ROM)
|
||||
- **PCMCIA Type II** slot (for modems, network cards, RAM cards)
|
||||
- **Interrupt routing** for both IDE and PCMCIA events
|
||||
|
||||
The A1200 Gayle is at a different base address layout than the A600 Gayle, and the byte-lane mapping differs from the A4000 IDE interface.
|
||||
|
||||
## Gayle ID
|
||||
|
||||
Read the Gayle ID by toggling read access to the ID register:
|
||||
```c
|
||||
#define GAYLE_ID_A1200 0xDA8000 /* read 8 bits, shifts on each access */
|
||||
|
||||
volatile UBYTE *gayle_id = (UBYTE *)0xDA8000;
|
||||
UBYTE id_byte = *gayle_id; /* returns $D0 (A600) or $D1 (A1200) */
|
||||
```
|
||||
|
||||
## IDE Register Map (A1200)
|
||||
|
||||
The A1200 IDE registers are at `$DA0000`, but the byte lanes are **swapped** relative to standard AT/ATA convention — the 8-bit registers appear at odd byte offsets within each 4-byte window:
|
||||
|
||||
| A1200 Address | ATA Register | RW |
|
||||
|---|---|---|
|
||||
| $DA0000 | Data (16-bit) | RW |
|
||||
| $DA0005 | Error (R) / Features (W) | RW |
|
||||
| $DA0009 | Sector Count | RW |
|
||||
| $DA000D | Sector Number (LBA 7:0) | RW |
|
||||
| $DA0011 | Cylinder Low (LBA 15:8) | RW |
|
||||
| $DA0015 | Cylinder High (LBA 23:16) | RW |
|
||||
| $DA0019 | Drive/Head select (LBA 27:24) | RW |
|
||||
| $DA001D | Status (R) / Command (W) | RW |
|
||||
| $DA101D | Alternate Status (R) / Device Control (W) | RW |
|
||||
|
||||
> [!NOTE]
|
||||
> The odd byte offset is because Gayle maps ATA registers on the **odd byte lane** of the 16-bit Amiga bus. Accessing `$DA0000+1` is the first register, not `$DA0000`. Many IDE drivers compensate with an offset of +1 or use a byte-swapped struct.
|
||||
|
||||
## Gayle Interrupt Register
|
||||
|
||||
```
|
||||
$DA9000 GAYLE_INT_STATUS (read/write)
|
||||
$DA9004 GAYLE_INT_ENABLE
|
||||
```
|
||||
|
||||
```c
|
||||
#define GAYLE_IRQ_IDE (1<<7) /* IDE interrupt pending */
|
||||
#define GAYLE_IRQ_CARD (1<<6) /* PCMCIA interrupt */
|
||||
#define GAYLE_IRQ_BVD1 (1<<5)
|
||||
#define GAYLE_IRQ_BVD2 (1<<4)
|
||||
#define GAYLE_IRQ_WP (1<<3) /* PCMCIA write protect */
|
||||
#define GAYLE_IRQ_CD (1<<2) /* PCMCIA card detect */
|
||||
```
|
||||
|
||||
Gayle routes its interrupt to **CIA-A /FLG** pin → CIAA ICR `CIAICRF_FLG` → CPU IPL 6.
|
||||
|
||||
Interrupt service routine must:
|
||||
1. Check `GAYLE_INT_STATUS` to identify source (IDE or PCMCIA)
|
||||
2. Clear the relevant bit by writing 0 to it
|
||||
3. If IDE: read the ATA status register to clear the IDE INTRQ
|
||||
|
||||
## PCMCIA Interface (A1200)
|
||||
|
||||
The A1200 PCMCIA slot is at:
|
||||
|
||||
| Address | Content |
|
||||
|---|---|
|
||||
| $600000–$9FFFFF | PCMCIA attribute memory (card CIS) |
|
||||
| $A00000–$A3FFFF | PCMCIA common memory (data) |
|
||||
|
||||
**Card detect sequence:**
|
||||
1. A card insertion triggers `GAYLE_IRQ_CD` (bit 2)
|
||||
2. Software reads CIS from attribute memory at $600000 to identify card type
|
||||
3. For ATA cards: configure card mode via PCMCIA CIS `CONFIG` tuple
|
||||
4. For network/modem cards: use the card's documented I/O mapping
|
||||
|
||||
## AmigaOS IDE Access
|
||||
|
||||
AmigaOS 3.1 includes `ata.device` (sometimes called `ide.device`) which drives the A1200 Gayle IDE internally. Applications never access Gayle registers directly — they go through dos.library → filesystem handler → ata.device.
|
||||
|
||||
```c
|
||||
/* Standard path — no direct Gayle access needed: */
|
||||
BPTR fh = Open("DH0:myfile", MODE_NEWFILE);
|
||||
Write(fh, data, length);
|
||||
Close(fh);
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- Commodore A1200 Technical Reference Manual — Gayle chapter (local archive)
|
||||
- NDK39: (no official Gayle header — community documented)
|
||||
- Amiga Hardware Reference (community supplement) — Gayle register map
|
||||
- `scsi.device` / `ata.device` Autodocs on ADCD 2.1
|
||||
Loading…
Add table
Add a link
Reference in a new issue