From a5b49d073f336a7f3bfef454cd478cc582a7538e Mon Sep 17 00:00:00 2001 From: Ilia Sharin Date: Sat, 25 Apr 2026 14:51:45 -0400 Subject: [PATCH] Peripherals and models description improved and expanded --- 01_hardware/README.md | 10 +- 01_hardware/aga_a1200_a4000/README.md | 46 +- 01_hardware/aga_a1200_a4000/akiko_cd32.md | 386 ++++++++++++++ 01_hardware/aga_a1200_a4000/chipset_aga.md | 6 + .../aga_a1200_a4000/gayle_ide_a1200.md | 97 ---- 01_hardware/common/address_space.md | 158 ++++-- 01_hardware/common/cia_chips.md | 66 +++ 01_hardware/common/gayle_ide_pcmcia.md | 220 ++++++++ 01_hardware/common/memory_types.md | 4 + 01_hardware/ecs_a600_a3000/README.md | 3 +- 01_hardware/ecs_a600_a3000/gary_gayle.md | 114 ---- .../ecs_a600_a3000/gary_system_controller.md | 62 +++ 01_hardware/ocs_a500/README.md | 59 +++ 01_hardware/ocs_a500/cdtv_hardware.md | 283 ++++++++++ 08_graphics/README.md | 1 + 08_graphics/blitter_programming.md | 2 +- 08_graphics/pixel_conversion.md | 494 ++++++++++++++++++ 10_devices/scsi.md | 6 +- README.md | 10 +- 19 files changed, 1752 insertions(+), 275 deletions(-) create mode 100644 01_hardware/aga_a1200_a4000/akiko_cd32.md delete mode 100644 01_hardware/aga_a1200_a4000/gayle_ide_a1200.md create mode 100644 01_hardware/common/gayle_ide_pcmcia.md delete mode 100644 01_hardware/ecs_a600_a3000/gary_gayle.md create mode 100644 01_hardware/ecs_a600_a3000/gary_system_controller.md create mode 100644 01_hardware/ocs_a500/cdtv_hardware.md create mode 100644 08_graphics/pixel_conversion.md diff --git a/01_hardware/README.md b/01_hardware/README.md index 9268efa..4ff6379 100644 --- a/01_hardware/README.md +++ b/01_hardware/README.md @@ -15,7 +15,7 @@ | Sprites | 8 × 16px | 8 × 16px | 8 × 64px, 256 colours | | Blitter bus | 16-bit | 16-bit | 64-bit (FMODE) | | Display modes | NTSC/PAL | +Productivity, VGA | +Doublescan, 31kHz | -| Machines | A500/A1000/A2000 | A600/A3000/A500+ | A1200/A4000/CD32 | +| Machines | A500/A1000/A2000/**CDTV** | A600/A3000/A500+ | A1200/A4000/A4000T/**CD32** | --- @@ -43,10 +43,10 @@ See [custom_registers_full.md](../references/custom_registers_full.md) for the c | Subfolder | Content | |---|---| -| [common/](common/) | M68k CPU, address space layout, **memory types (Chip/Fast/Slow)**, CIA chips, Zorro bus | -| [ocs_a500/](ocs_a500/) | OCS chipset — A500, A1000, A2000 | -| [ecs_a600_a3000/](ecs_a600_a3000/) | ECS chipset — A600, A3000, A500+ | -| [aga_a1200_a4000/](aga_a1200_a4000/) | AGA chipset — A1200, A4000, CD32 | +| [common/](common/) | M68k CPU, address space layout, **memory types (Chip/Fast/Slow)**, CIA chips, Zorro bus, **Gayle IDE/PCMCIA** | +| [ocs_a500/](ocs_a500/) | OCS chipset — A500, **A1000 (WCS)**, **A2000 (Zorro II)**, **CDTV (CD-ROM, NVRAM, IR)** | +| [ecs_a600_a3000/](ecs_a600_a3000/) | ECS chipset — A600, A3000 (**Gary** system controller), A500+ | +| [aga_a1200_a4000/](aga_a1200_a4000/) | AGA chipset — A1200, A4000, **A4000T (SCSI)**, **CD32 (Akiko C2P, CD-ROM, NVRAM)** | --- diff --git a/01_hardware/aga_a1200_a4000/README.md b/01_hardware/aga_a1200_a4000/README.md index f995934..3dec225 100644 --- a/01_hardware/aga_a1200_a4000/README.md +++ b/01_hardware/aga_a1200_a4000/README.md @@ -23,8 +23,10 @@ The **Advanced Graphics Architecture** (AGA) is the final custom chipset develop | [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 | +| [aga_copper.md](aga_copper.md) | AGA Copper programming guide | | [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 | +| [akiko_cd32.md](akiko_cd32.md) | CD32 Akiko chip: C2P conversion, CD-ROM, NVRAM | +| [Gayle IDE & PCMCIA](../common/gayle_ide_pcmcia.md) | A1200 Gayle: IDE and PCMCIA (shared with A600) | ## AGA vs ECS — Key Differences @@ -53,17 +55,53 @@ BOOL is_aga = (GfxBase->ChipRevBits0 & (1 << GFXB_AA_ALICE)) != 0; | 4 | `GFXB_AA_ALICE` | AGA Alice present | | 5 | `GFXB_AA_LISA` | AGA Lisa present | -## AGA Machines +--- + +## AGA Machines — Per-Model Details | Model | CPU | Notes | |---|---|---| -| A1200 | 68020 14 MHz | Budget AGA; Gayle IDE; PCMCIA; 2 MB Chip | +| A1200 | 68EC020 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 | +| CD32 | 68EC020 14 MHz | Game console; Akiko C2P; CD-ROM; no keyboard | + +### CD32 (1993) — AGA Game Console + +The CD32 uses the **identical AGA chipset** (Alice + Lisa + Paula) as the A1200, but adds the **Akiko** custom chip — a unique ASIC providing: + +- **Chunky-to-Planar (C2P) hardware conversion** — converts 8-bit linear pixel data to planar bitplane format +- **CD-ROM controller** — drives the internal double-speed CD-ROM via PIO (no SCSI, no IDE) +- **NVRAM interface** — I²C controller for 128-byte onboard EEPROM + +The CD32 has **no Gayle chip** — Akiko replaces all storage functions. It has no keyboard, no floppy, no Zorro slots, and no PCMCIA. The only expansion path is the rear port (SX-1/SX-32 add-on units) or the FMV module slot. + +See the dedicated article: **[Akiko — CD32 Custom Chip](akiko_cd32.md)** + +### A4000T (1994) — Tower Workstation + +The A4000T is the tower variant of the A4000 desktop, adding: + +| Feature | A4000 Desktop | A4000T Tower | +|---|---|---| +| CPU | 68030 @ 25 MHz or 68040 @ 25 MHz | 68040 @ 25 MHz or 68060 @ 50 MHz | +| SCSI | None | **NCR53C710** (Fast SCSI-2, bus-mastering DMA) | +| Drive bays | 1× 3.5" IDE | 3× 5.25" + 1× 3.5" | +| Zorro III | 4 slots | 5 slots | +| CPU slot | Yes | Yes (enhanced pinout) | +| Power supply | Internal 150W | Internal 300W | +| IDE | On-board (Gayle-less) | On-board + SCSI | + +The A4000T's **NCR53C710** SCSI controller is a high-performance bus-mastering DMA controller — significantly faster than the WD33C93 used in the A3000 and CDTV. It supports up to 7 SCSI devices on an internal 50-pin ribbon cable. + +> [!NOTE] +> The A4000T was the last Amiga produced by Commodore before the company's bankruptcy in April 1994. Very few units were manufactured, making it one of the rarest stock Amiga models. + +--- ## References - ADCD 2.1 Hardware Manual — AGA chapters - NDK39: `graphics/gfxbase.h`, `hardware/custom.h` - Commodore A1200/A4000 Technical Reference Manuals (local archive) + diff --git a/01_hardware/aga_a1200_a4000/akiko_cd32.md b/01_hardware/aga_a1200_a4000/akiko_cd32.md new file mode 100644 index 0000000..920f378 --- /dev/null +++ b/01_hardware/aga_a1200_a4000/akiko_cd32.md @@ -0,0 +1,386 @@ +[← Home](../../README.md) · [Hardware](../README.md) · [AGA](README.md) + +# Akiko — CD32 Custom Chip + +## Overview + +The **Akiko** chip is a custom ASIC unique to the Amiga CD32 game console (1993). It sits alongside the standard AGA chipset (Alice + Lisa + Paula) and provides three subsystems that exist in no other Amiga model: + +1. **Chunky-to-Planar (C2P) conversion** — hardware-accelerated pixel format conversion +2. **CD-ROM controller** — drives the internal double-speed CD-ROM +3. **NVRAM interface** — I²C controller for the onboard serial EEPROM + +Akiko is mapped at base address **`$B80000`** and occupies a 32 KB window (`$B80000`–`$B87FFE`). + +## Chip Identification + +Reading a longword from `$B80000` returns the Akiko ID: + +```asm + move.l $B80000, d0 ; d0 = $C0CACAFE if Akiko present + cmp.l #$C0CACAFE, d0 + beq .has_akiko +``` + +> [!NOTE] +> On non-CD32 machines, reading `$B80000` will return bus noise or trigger a bus error. Always wrap Akiko detection in an exception handler or use `graphics.library` v40+ `WriteChunkyPixels()` which auto-detects Akiko internally. + +## Register Map + +| Offset | Name | R/W | Description | +|---|---|---|---| +| `$B80000` | `AKIKO_ID` | R | Chip ID — returns `$C0CACAFE` | +| `$B80002` | `AKIKO_REV` | R | Silicon revision | +| `$B80004` | `AKIKO_INTREQ` | R | Interrupt request (CD subcode, C2P done) | +| `$B80008` | `AKIKO_INTENA` | RW | Interrupt enable mask | +| `$B80010` | `CDROM_PBXSTAT` | RW | CD-ROM PIO buffer/status | +| `$B80014` | `CDROM_FLAGS` | RW | CD-ROM control flags | +| `$B80018` | `CDROM_TXDATA` | W | CD-ROM command transmit | +| `$B8001C` | `CDROM_RXDATA` | R | CD-ROM response receive | +| `$B80020` | `CDROM_SUBCDATA` | R | CD subcode (Q-channel) data | +| `$B80024` | `NVRAM_CTRL` | RW | NVRAM I²C control (SCL/SDA direction) | +| `$B80028` | `NVRAM_DATA` | RW | NVRAM I²C data (SCL/SDA bit-bang) | +| `$B80030` | `C2P_INPUT` | W | Chunky-to-Planar input register (longword) | +| `$B80030` | `C2P_OUTPUT` | R | Chunky-to-Planar output register (longword) | + +> [!IMPORTANT] +> The register map above is reverse-engineered from WinUAE (`akiko.cpp`) and community hardware testing. Commodore never published an official Akiko datasheet. + +--- + +## Chunky-to-Planar (C2P) Conversion + +### The Problem + +The AGA chipset uses **planar** graphics — each bitplane is a separate contiguous block of memory. But most game engines (especially PC ports) render in **chunky** format — one byte per pixel in a linear framebuffer. Converting between these formats is computationally expensive on the 68020. + +### How Akiko C2P Works + +Akiko converts **32 chunky pixels** (8-bit each) into **8 bitplane longwords** in hardware. The CPU must feed data in and read results out — Akiko has **no DMA**; it is a register-based pipeline. + +#### Conversion Protocol + +``` +Input: 8 longwords of chunky data (4 pixels × 8 = 32 pixels) +Output: 8 longwords of planar data (1 longword per bitplane × 8 planes) +``` + +**Step 1 — Write 8 longwords of chunky pixels:** + +```asm +; a0 = source chunky buffer (32 pixels = 32 bytes, read as 8 longwords) +; Each longword contains 4 consecutive 8-bit pixels: [P0|P1|P2|P3] + + lea $B80030, a1 ; C2P input register + move.l (a0)+, (a1) ; pixels 0–3 + move.l (a0)+, (a1) ; pixels 4–7 + move.l (a0)+, (a1) ; pixels 8–11 + move.l (a0)+, (a1) ; pixels 12–15 + move.l (a0)+, (a1) ; pixels 16–19 + move.l (a0)+, (a1) ; pixels 20–23 + move.l (a0)+, (a1) ; pixels 24–27 + move.l (a0)+, (a1) ; pixels 28–31 +``` + +**Step 2 — Read 8 longwords of planar output:** + +```asm +; a2 = destination planar buffer (8 bitplanes × 4 bytes = 32 bytes) + + lea $B80030, a1 ; C2P output register (same address, read mode) + move.l (a1), (a2)+ ; bitplane 0 (32 pixels, 1 bit each) + move.l (a1), (a2)+ ; bitplane 1 + move.l (a1), (a2)+ ; bitplane 2 + move.l (a1), (a2)+ ; bitplane 3 + move.l (a1), (a2)+ ; bitplane 4 + move.l (a1), (a2)+ ; bitplane 5 + move.l (a1), (a2)+ ; bitplane 6 + move.l (a1), (a2)+ ; bitplane 7 +``` + +#### Optimised Loop (MOVEM) + +In practice, the entire 32-pixel conversion is done with two MOVEM instructions: + +```asm +; Convert 32 chunky pixels → 8 planar longwords +; a0 = chunky source, a2 = planar dest +; a1 = $B80030 (Akiko C2P register) + + movem.l (a0)+, d0-d7 ; load 32 chunky pixels (8 longwords) + movem.l d0-d7, (a1) ; write to Akiko C2P input + movem.l (a1), d0-d7 ; read 8 planar longwords from Akiko + movem.l d0-d7, (a2) ; store to bitplane memory + lea 32(a2), a2 ; advance planar pointer +``` + +> [!WARNING] +> MOVEM to a fixed address writes all registers to the **same** address (FIFO-style), which is exactly what Akiko expects. This only works because `$B80030` is a hardware register, not normal RAM. + +#### Full-Screen Conversion Example + +For a 320×256 screen at 8 bitplanes (256 colours): + +```asm +; Total pixels = 320 × 256 = 81,920 +; Each pass converts 32 pixels → 81,920 / 32 = 2,560 passes + + lea chunky_buffer, a0 + lea planar_buffer, a2 + lea $B80030, a1 + move.l #2560-1, d7 ; loop counter + +.c2p_loop: + movem.l (a0)+, d0-d6/a3 ; 8 longwords (use a3 for 8th reg) + movem.l d0-d6/a3, (a1) ; write to Akiko + movem.l (a1), d0-d6/a3 ; read planar output + movem.l d0-d6/a3, (a2) + lea 32(a2), a2 + dbf d7, .c2p_loop +``` + +### Performance Characteristics + +| Metric | Value | +|---|---| +| Pixels per pass | 32 | +| CPU cycles per pass | ~80–100 (68020 @ 14 MHz) | +| Throughput | ~1.5 MB/s (register I/O bound) | +| 320×256×8bpp full screen | ~54 ms (~18 fps standalone) | + +#### When to Use Akiko C2P + +| Scenario | Recommendation | +|---|---| +| Stock CD32 (68020, Chip RAM only) | **Use Akiko** — significantly faster than CPU-only C2P | +| CD32 + SX-32 with 68030 + Fast RAM | Benchmark both — software C2P may match Akiko | +| CD32 + 68040/060 accelerator | **Use software C2P** — CPU is 5–10× faster than Akiko's throughput | + +### AmigaOS Interface + +OS-compliant applications use `WriteChunkyPixels()` from `graphics.library` v40+: + +```c +#include + +/* graphics.library auto-detects Akiko and uses it if present */ +WriteChunkyPixels( + rp, /* RastPort */ + xstart, ystart, /* top-left corner */ + xstop, ystop, /* bottom-right corner */ + chunky_array, /* source chunky pixel data */ + bytes_per_row /* chunky buffer pitch */ +); +``` + +--- + +## CD-ROM Controller + +### Hardware + +The CD32 contains a **Philips/Sony double-speed (2×) CD-ROM** drive. Unlike the CDTV (which uses a SCSI-based controller via DMAC/WD33C93), the CD32's CD-ROM is controlled **directly by Akiko** through a proprietary PIO interface. + +### Drive Capabilities + +| Feature | Specification | +|---|---| +| Speed | 2× (300 KB/s data, 150 KB/s audio) | +| Media | CD-ROM (Mode 1/2), CD-DA, Mixed Mode | +| Seek | ~400 ms average | +| Interface | Akiko PIO (no SCSI, no IDE) | + +### CD-ROM Register Protocol + +Communication with the drive is command/response based through the Akiko registers: + +1. **Write command bytes** to `CDROM_TXDATA` (`$B80018`) +2. **Poll status** via `CDROM_PBXSTAT` (`$B80010`) for response availability +3. **Read response bytes** from `CDROM_RXDATA` (`$B8001C`) +4. **Read subcode** from `CDROM_SUBCDATA` (`$B80020`) for TOC/position data + +### Boot from CD + +The CD32 boots exclusively from CD-ROM (no floppy drive). The boot sequence: + +1. Kickstart 3.1 initialises from ROM (`$F80000`) +2. Extended ROM at `$E00000` provides `cd.device` and the CD filesystem +3. Akiko initialises the CD-ROM drive +4. The system reads the TOC and looks for a boot block (Amiga executable format) +5. If found, the boot executable is loaded and run — this is the game/application entry point + +> [!NOTE] +> CD32 game discs use standard ISO 9660 with Amiga-specific boot blocks. Many titles also include CD-DA audio tracks for music, played via Akiko's CDDA passthrough. + +--- + +## NVRAM (Non-Volatile Storage) + +### Hardware + +The CD32 includes a **1 Kbit (128 bytes) serial EEPROM** (typically a 93C46 or compatible) accessed via I²C bit-banging through Akiko registers. + +| Parameter | Value | +|---|---| +| Type | Serial EEPROM (I²C / Microwire) | +| Capacity | 1 Kbit (128 bytes usable) | +| Interface | Akiko bit-bang (SCL/SDA via `$B80024`/`$B80028`) | +| Persistence | Battery-backed (CR2032) | +| Typical use | Game saves, system preferences, high scores | + +### Access Protocol + +NVRAM access requires bit-banging the I²C clock (SCL) and data (SDA) lines through Akiko registers: + +```asm +; Simplified NVRAM byte read +; d0 = address (0–127) + + ; Set SDA as output, clock high + move.l #$01, $B80024 ; NVRAM_CTRL: configure direction + + ; Send device address + read command via bit-bang + ; (full protocol requires start condition, address bits, ack) + + ; Clock in 8 data bits + moveq #7, d1 +.read_bit: + bset #0, $B80028 ; SCL high + move.l $B80028, d2 ; read SDA + bclr #0, $B80028 ; SCL low + roxl.b #1, d0 ; shift bit into result + dbf d1, .read_bit +``` + +### AmigaOS NVRAM Access + +The OS provides `nonvolatile.library` for structured NVRAM access: + +```c +#include + +/* Store data */ +StoreNV("MyGame", "SaveSlot1", save_data, data_length, TRUE); + +/* Retrieve data */ +APTR data = GetNV("MyGame", "SaveSlot1", TRUE); +``` + +--- + +## CD32 Expansion Options + +The CD32 has **no standard expansion slots** (no Zorro, no CPU slot, no trapdoor, no PCMCIA). Third-party units connect via the rear expansion port: + +### SX-1 (Paravision) + +| Feature | Specification | +|---|---| +| Memory | 1× 72-pin SIMM (1–8 MB Fast RAM) | +| Storage | Internal 44-pin IDE (2.5" HDD) + external DB37 IDE | +| I/O | Parallel (DB25), Serial (9-pin RS232), RGB video (DB23) | +| Keyboard | AT-101 connector | +| Floppy | External DB23 floppy connector | +| Other | RTC (CR2032), FMV pass-through, disable switch | + +### SX-32 / SX-32 Pro (DCE) + +| Feature | Specification | +|---|---| +| Memory | 1× 72-pin SIMM (up to 8 MB) | +| Storage | Internal 44-pin IDE | +| I/O | Parallel (DB25), Serial (DB25), RGB (DB23), VGA (HD15) | +| CPU upgrade | SX-32 Pro includes 68030 socket | +| Other | RTC, external floppy | + +### FMV Module (Commodore) + +| Feature | Specification | +|---|---| +| Function | MPEG-1 video + audio decoder (Video CD playback) | +| Video chip | C-Cube CL450 MPEG decoder | +| Audio chip | LSI Logic audio decoder | +| Limitation | Caps system Fast RAM at 4 MB | +| Compatibility | Works with SX-1 (pass-through); **incompatible** with SX-32 | + +> [!WARNING] +> The FMV module had four hardware revisions. Early revisions (rev 1–2) are prone to overheating. If sourcing one today, look for rev 3 or later. + +--- + +## CD32 vs A1200 — Hardware Comparison + +The CD32 is often described as "an A1200 in a console shell." The chipset is identical, but the system-level hardware differs significantly: + +| Feature | A1200 | CD32 | +|---|---|---| +| CPU | 68EC020 @ 14 MHz | 68EC020 @ 14 MHz | +| Custom chips | Alice + Lisa + Paula | Alice + Lisa + Paula + **Akiko** | +| Chip RAM | 2 MB | 2 MB | +| Chipset | AGA | AGA | +| Storage | IDE (Gayle), Floppy | **CD-ROM (Akiko)**, no floppy | +| Expansion | Trapdoor (150-pin), PCMCIA | Rear port only (SX-1/SX-32) | +| Keyboard | Built-in | None (requires SX-1/SX-32) | +| Controller | Atari-style DB9 joystick | **CD32 gamepad** (7-button protocol) | +| NVRAM | None | **128 bytes EEPROM** (Akiko) | +| Gayle | Yes (IDE, PCMCIA) | **No** — Akiko replaces storage functions | +| C2P hardware | No | **Yes** (Akiko) | +| Boot media | Floppy / HDD | CD-ROM only | + +### CD32 Gamepad Protocol + +The CD32 gamepad uses a serial shift-register protocol through the standard DB9 controller port, providing 7 buttons: + +| Button | Bit | Accent | +|---|---|---| +| Blue (Play) | 0 | Fire 1 / primary action | +| Red (Rewind) | 1 | Fire 2 / secondary | +| Yellow (FF) | 2 | Fire 3 | +| Green (Stop) | 3 | Fire 4 | +| Right shoulder | 4 | Shoulder R | +| Left shoulder | 5 | Shoulder L | +| Pause | 6 | Start/Pause | + +Detection: the CD32 pad responds to a clock signal on pin 5 of the joystick port. Standard Atari-style joysticks ignore this signal and remain compatible. + +--- + +## Detecting CD32 at Runtime + +```c +#include + +/* Method 1: Check Akiko ID register (hardware-level) */ +BOOL has_akiko(void) +{ + volatile ULONG *akiko_id = (ULONG *)0xB80000; + /* Wrap in exception handler — bus error on non-CD32 */ + return (*akiko_id == 0xC0CACAFE); +} + +/* Method 2: Check for CD32 via expansion.library (safer) */ +#include +#include + +BOOL is_cd32(void) +{ + /* Akiko autoconfig: manufacturer 0x0202, product 0x3E */ + struct ConfigDev *cd = FindConfigDev(NULL, 0x0202, 0x3E); + return (cd != NULL); +} +``` + +## References + +- WinUAE source: `akiko.cpp` — reverse-engineered register definitions (Toni Wilen) +- Commodore CD32 Technical Reference (internal, partial — never publicly released) +- NDK39: `graphics/gfx.h` — `WriteChunkyPixels()` prototype +- NDK39: `libraries/nonvolatile.h` — NVRAM access API +- [Big Book of Amiga Hardware — CD32](https://bigbookofamigahardware.com/) +- English Amiga Board (EAB) — CD32 hardware discussions + +## See Also + +- [AGA Chipset Internals](chipset_aga.md) — Alice and Lisa (shared with CD32) +- [Memory Types](../common/memory_types.md) — CD32 memory configuration +- [Address Space](../common/address_space.md) — CD32 address map with Akiko region diff --git a/01_hardware/aga_a1200_a4000/chipset_aga.md b/01_hardware/aga_a1200_a4000/chipset_aga.md index 33712cc..a9c7d1d 100644 --- a/01_hardware/aga_a1200_a4000/chipset_aga.md +++ b/01_hardware/aga_a1200_a4000/chipset_aga.md @@ -118,3 +118,9 @@ move.w #$9411, BPLCON0+custom ; HIRES=1 (if needed), BPU=8 (BPU3=1, BPU2-0=000 - NDK39: `hardware/custom.h` — struct Custom (with AGA extensions) - Commodore A1200 Technical Reference Manual — Alice/Lisa section - AmigaMail Vol. 2 — AGA programming articles + +## See Also + +- [Akiko — CD32 Custom Chip](akiko_cd32.md) — CD32-exclusive ASIC (C2P, CD-ROM, NVRAM) that sits alongside Alice/Lisa/Paula +- [AGA Blitter](aga_blitter.md) — 64-bit FMODE blitter details +- [AGA Palette](aga_palette.md) — 256-register 24-bit colour system diff --git a/01_hardware/aga_a1200_a4000/gayle_ide_a1200.md b/01_hardware/aga_a1200_a4000/gayle_ide_a1200.md deleted file mode 100644 index 3a9248b..0000000 --- a/01_hardware/aga_a1200_a4000/gayle_ide_a1200.md +++ /dev/null @@ -1,97 +0,0 @@ -[← 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 diff --git a/01_hardware/common/address_space.md b/01_hardware/common/address_space.md index aee2f96..ed0bc3c 100644 --- a/01_hardware/common/address_space.md +++ b/01_hardware/common/address_space.md @@ -6,46 +6,102 @@ The Amiga uses a **24-bit physical address bus** on OCS/ECS machines (68000/68020 effective), giving 16 MB of addressable space. AGA machines with 68030/040 and 32-bit-clean software can address the full 4 GB, but Chip RAM and custom registers remain in the lower 16 MB. -## Memory Map — 24-bit (OCS/ECS, A500/A600/A3000) +## Memory Map — 24-bit (OCS/ECS: A1000, A500, A500+, A2000, A600, A3000, CDTV) -``` -$000000–$1FFFFF Chip RAM (max 2 MB on ECS, 512 KB on OCS A500) -$200000–$9FFFFF Fast RAM (expansion via Zorro II autoconfig) -$A00000–$BEFFFF Zorro II I/O space -$BFD000–$BFDFFF CIA-B (8520, keyboard, floppy motor, disk side) -$BFE001–$BFE1FF CIA-A (8520, parallel port, serial flags, timer) -$C00000–$C7FFFF Slow RAM ("Ranger", DMA-visible but not fast) -$C80000–$CFFFFF Zorro II expansion I/O (boards) -$D00000–$D7FFFF Zorro II expansion I/O -$D80000–$DBFFFF Reserved / board-specific -$DC0000–$DCFFFF Real-Time Clock (MSM6242B / RF5C01A) -$DD0000–$DEFFFF Reserved -$DF0000–$DFFFFF Custom chip registers ($DFF000–$DFF1FE) -$E00000–$E7FFFF Kick memory (WCS / Ranger slow RAM mirror) -$E80000–$EFFFFF Autoconfig space (Zorro II probe) -$F00000–$F7FFFF Extended Kickstart ROM (OS 3.1: second 256 KB) -$F80000–$FFFFFF Kickstart ROM (512 KB mirror at top of 16 MB) -``` +| Address Range | Size | Region | +|---|---|---| +| `$000000`–`$1FFFFF` | 2 MB max | Chip RAM (512 KB on OCS A500, 1–2 MB on ECS) | +| `$200000`–`$9FFFFF` | 8 MB | Fast RAM (Zorro II autoconfig expansion) | +| `$A00000`–`$BEFFFF` | ~2 MB | Zorro II I/O space | +| `$BFD000`–`$BFDFFF` | 4 KB | CIA-B (8520 — keyboard, floppy motor, disk side select) | +| `$BFE001`–`$BFE1FF` | 512 B | CIA-A (8520 — parallel port, serial flags, timers) | +| `$C00000`–`$C7FFFF` | 512 KB | Slow RAM ("Ranger" — on Chip bus, not DMA-visible) | +| `$C80000`–`$CFFFFF` | 512 KB | Zorro II expansion I/O (boards) | +| `$D00000`–`$D7FFFF` | 512 KB | Zorro II expansion I/O | +| `$D80000`–`$DBFFFF` | 256 KB | Reserved / board-specific | +| `$DC0000`–`$DCFFFF` | 64 KB | Real-Time Clock (MSM6242B / RF5C01A) | +| `$DD0000`–`$DEFFFF` | 128 KB | Reserved | +| `$DF0000`–`$DFFFFF` | 64 KB | Custom chip registers (`$DFF000`–`$DFF1FE`) | +| `$E00000`–`$E7FFFF` | 512 KB | Kick memory (WCS / Ranger slow RAM mirror) | +| `$E80000`–`$EFFFFF` | 512 KB | Autoconfig space (Zorro II probe) | +| `$F00000`–`$F7FFFF` | 512 KB | Extended Kickstart ROM (OS 3.1: second 256 KB) | +| `$F80000`–`$FFFFFF` | 512 KB | Kickstart ROM (primary, mirrored at top of 16 MB) | -## Memory Map — 32-bit (AGA, A1200/A4000) +## Memory Map — 32-bit (AGA: A1200, A4000, CD32) + +| Address Range | Size | Region | +|---|---|---| +| `$000000`–`$1FFFFF` | 2 MB | Chip RAM | +| `$200000`–`$07FFFFFF` | up to 126 MB | Fast RAM (on-board via Ramsey on A4000; trapdoor/PCMCIA on A1200) | +| `$A00000`–`$BEFFFF` | ~2 MB | Zorro II I/O | +| `$BFD000` | — | CIA-B | +| `$BFE001` | — | CIA-A | +| `$C00000`–`$CFFFFF` | 1 MB | Slow RAM / board I/O | +| `$D80000`–`$D8FFFF` | 64 KB | IDE / Gayle (A1200/A4000) | +| `$DA0000`–`$DA3FFF` | 16 KB | PCMCIA attribute memory (A1200) | +| `$DC0000` | — | Real-Time Clock | +| `$DFF000`–`$DFFFFF` | 64 KB | Custom chip registers | +| `$E00000`–`$E7FFFF` | 512 KB | Kick mirror / WCS | +| `$F00000`–`$F7FFFF` | 512 KB | Extended Kickstart ROM | +| `$F80000`–`$FFFFFF` | 512 KB | Kickstart ROM | +| `$01000000`+ | up to 1.75 GB | Zorro III expansion (32-bit, A3000/A4000 only) | + +## Per-Model Address Space Variations + +The maps above show the common layout. Several models have unique regions: + +### A1000 — Writable Control Store (WCS) + +| Address Range | Size | Region | +|---|---|---| +| `$F80000`–`$FFFFFF` | 512 KB | **WCS RAM** — Kickstart is loaded from floppy into this RAM at boot (A1000 has no ROM-based Kickstart) | +| `$FC0000`–`$FFFFFF` | 256 KB | Bootstrap ROM (256-byte boot loader that loads Kickstart into WCS) | + +The A1000 is the only model where Kickstart lives in **RAM**, not ROM. If power is lost, Kickstart must be reloaded from the Kickstart floppy. The WCS is write-protected after loading via a hardware latch. + +### A2000 — Zorro II Bus and CPU Slot + +| Address Range | Size | Region | +|---|---|---| +| `$200000`–`$9FFFFF` | 8 MB | Zorro II Fast RAM (5 expansion slots, autoconfig) | +| `$E80000`–`$EFFFFF` | 512 KB | Autoconfig space — probed at boot for each Zorro II card | +| CPU slot | — | Directly wired 68000 socket — accepts accelerators (GVP G-Force, A2630) | + +The A2000 is the canonical "big-box" expandable Amiga. Its 5 Zorro II slots provide 8 MB of Fast RAM address space. Some later A2000 revisions (rev 6+) support Super Agnus for 2 MB Chip RAM. + +### CDTV — CD-ROM Controller and NVRAM + +| Address Range | Size | Region | +|---|---|---| +| `$000000`–`$0FFFFF` | 1 MB | Chip RAM (stock, expandable to 2 MB with Super Agnus mod) | +| `$E00000`–`$E3FFFF` | 256 KB | CDTV Extended ROM (CD filesystem, player software, DMAC) | +| `$E40000`–`$E7FFFF` | 256 KB | CDTV Extended ROM (second bank) | +| `$DC0000`–`$DC003F` | 64 B | Real-Time Clock (Oki MSM6242B) | +| `$E90000`–`$E9FFFF` | 64 KB | DMAC (WD33C93 SCSI DMA controller for CD-ROM) | +| `$F00000`–`$F3FFFF` | 256 KB | CDTV **NVRAM** (battery-backed, stores bookmarks and saves) | + +The CDTV is essentially an A500 with a CD-ROM drive, IR remote, and NVRAM in a consumer set-top box form factor. It uses the OCS chipset (original Agnus) with 1 MB Chip RAM. The DMAC at `$E90000` handles DMA transfers between the CD-ROM's SCSI interface and memory. + +### CD32 — Akiko Chip and Flash ROM + +| Address Range | Size | Region | +|---|---|---| +| `$000000`–`$1FFFFF` | 2 MB | Chip RAM (fixed) | +| `$B80000`–`$B8FFFF` | 64 KB | **Akiko** custom chip (chunky-to-planar conversion, CD-ROM controller, NVRAM interface) | +| `$DC0000`–`$DC003F` | 64 B | Real-Time Clock | +| `$DFF000`–`$DFFFFF` | 64 KB | Custom chip registers (AGA — Alice/Lisa) | +| `$E00000`–`$E7FFFF` | 512 KB | CD32 Extended ROM (CD filesystem, boot, CDDA player) | +| `$F00000`–`$F7FFFF` | 512 KB | CD32 flash ROM (firmware, SysInfo) | +| `$F80000`–`$FFFFFF` | 512 KB | Kickstart 3.1 ROM | + +The CD32's unique feature is the **Akiko** chip at `$B80000`, which provides: +- **Chunky-to-Planar (C2P) conversion**: a hardware DMA engine that converts linear 8-bit pixel arrays to planar bitplane format — the single most sought-after feature for game ports +- **CD-ROM controller**: handles the double-speed CD drive directly +- **NVRAM interface**: 1 KB battery-backed storage for game saves + +> [!NOTE] +> The CD32 has no Zorro slots, no CPU slot, no trapdoor connector, and no PCMCIA port. The only expansion path is the (rare) FMV module slot or the SX-1/SX-32 expansion unit that adds a keyboard port, IDE, and PCMCIA. -``` -$000000–$1FFFFF 2 MB Chip RAM -$200000–$07FFFFFF Fast RAM (on-board: 4–16 MB via Ramsey on A4000) - Trapdoor/PCMCIA on A1200 -$A00000–$BEFFFF Zorro II I/O -$BFD000 CIA-B -$BFE001 CIA-A -$C00000–$CFFFFF Slow RAM / board I/O -$D80000–$D8FFFF IDE / Gayle (A1200/A4000) -$DA0000–$DA3FFF PCMCIA attribute memory (A1200) -$DC0000 RTC -$DFF000–$DFFFFF Custom registers -$E00000–$E7FFFF Kick mirror / WCS -$F00000–$F7FFFF Extended ROM -$F80000–$FFFFFF Kickstart ROM (512 KB) -$01000000+ Zorro III expansion (32-bit, A3000/A4000 only) -``` ## Memory Type Classification @@ -77,16 +133,24 @@ Fast RAM is **CPU-only** — generally used for code, non-DMA data structures, a ## Diagram ```mermaid -block-beta - columns 1 - block:chip["Chip RAM\n$000000–$1FFFFF\n(DMA accessible)"] - block:fast["Fast RAM\n$200000–$9FFFFF\n(CPU only, faster)"] - block:zio["Zorro II I/O\n$A00000–$BEFFFF"] - block:cia["CIA-A/B\n$BFD000/$BFE001"] - block:slow["Slow/Ranger RAM\n$C00000–$C7FFFF"] - block:rtc["RTC $DC0000"] - block:custom["Custom Registers\n$DFF000–$DFFFFF"] - block:rom["Kickstart ROM\n$F80000–$FFFFFF"] +flowchart TB + chip["Chip RAM
$000000–$1FFFFF
(DMA accessible)"] + fast["Fast RAM
$200000–$9FFFFF
(CPU only, faster)"] + zio["Zorro II I/O
$A00000–$BEFFFF"] + cia["CIA-A/B
$BFD000 / $BFE001"] + slow["Slow / Ranger RAM
$C00000–$C7FFFF"] + custom["Custom Registers
$DFF000–$DFFFFF"] + rom["Kickstart ROM
$F80000–$FFFFFF"] + + chip --- fast --- zio --- cia --- slow --- custom --- rom + + style chip fill:#2d6a4f,color:#fff + style fast fill:#1b4332,color:#fff + style slow fill:#774936,color:#fff + style custom fill:#e63946,color:#fff + style rom fill:#457b9d,color:#fff + style zio fill:#264653,color:#fff + style cia fill:#264653,color:#fff ``` ## Key Chip RAM Addresses diff --git a/01_hardware/common/cia_chips.md b/01_hardware/common/cia_chips.md index a695b33..df69197 100644 --- a/01_hardware/common/cia_chips.md +++ b/01_hardware/common/cia_chips.md @@ -144,9 +144,75 @@ Direct CIA programming should be done with `ciaa`/`ciab` resource claims via `Op /* ciaa.ciapra, ciaa.ciaprb, ciaa.ciaicr, ciaa.ciacra, ... */ ``` +## Per-Model CIA Wiring Variations + +While CIA-A and CIA-B register layouts are identical across all Amigas, the **physical wiring** of their port pins varies by model: + +### CIA-A Port A Differences + +| Bit | Standard (A500/A2000/A1200/A4000) | A1000 | CDTV | CD32 | +|---|---|---|---|---| +| 7 | `/FIR1` — joystick 1 fire | Same | Same | **CD32 pad button** (via shift register) | +| 6 | `/FIR0` — joystick 0 fire | Same | Same | **CD32 pad button** (via shift register) | +| 5 | `/RDY` — floppy ready | Same | No internal floppy | No floppy | +| 4 | `/TK0` — track 0 sensor | Same | No internal floppy | No floppy | +| 3 | `/WPRO` — write protect | Same | No internal floppy | No floppy | +| 2 | `/CHNG` — disk change | Same | No internal floppy | No floppy | +| 1 | `/LED` — power LED | Same | Front panel LED | Front panel LED | +| 0 | `/OVL` — Chip RAM overlay | Same | Same | Same | + +### CIA-A `/FLG` Pin + +| Model | `/FLG` Source | +|---|---| +| A500/A2000/A3000 | Directly accessible for parallel port `BUSY` or expansion | +| A600/A1200 | **Gayle interrupt routing** — IDE and PCMCIA interrupts arrive here | +| CDTV | **IR remote receiver** — IR data packets trigger `/FLG` | +| CD32 | **Akiko interrupt routing** — CD-ROM and NVRAM events | + +### CIA-B Port A (Floppy Drive Selection) + +| Bit | Standard | CDTV | CD32 | +|---|---|---|---| +| 7 | `/MTR` — motor | N/A (no internal floppy) | N/A | +| 6–3 | `/SEL3`–`/SEL0` — drive select | External floppy only (`/SEL0`) | N/A | +| 2 | `/SIDE` — head side | N/A | N/A | +| 1 | `/DIR` — step direction | N/A | N/A | +| 0 | `/STEP` — step pulse | N/A | N/A | + +> [!NOTE] +> On CDTV and CD32, the CIA-B floppy control bits are electrically disconnected from any drive hardware. Writing to them has no effect. If an external floppy is connected (CDTV with external drive, or CD32 with SX-1), only `/SEL0` and related signals are active. + +### CD32 Gamepad — CIA Shift Register Protocol + +The CD32 gamepad uses CIA-A's **Serial Data Register (SDR)** for button reads. The controller contains a shift register that is clocked via the joystick port pin 5: + +```asm +; Read CD32 gamepad buttons +; Returns 7 button bits in d0 + + move.b #$FF, $BFE301 ; CIA-A DDRA: all outputs (temporarily) + bset #6, $BFE001 ; Pin 5 high (clock start) + bclr #6, $BFE001 ; Pin 5 low → latch button state + + ; Clock in 7 bits via pin toggling + moveq #6, d1 +.read_pad: + bset #6, $BFE001 ; clock pulse high + btst #0, $BFE001 ; read data bit + bclr #6, $BFE001 ; clock pulse low + roxl.b #1, d0 ; shift into result + dbf d1, .read_pad +``` + +Standard 2-button Atari joysticks ignore the clock signal and remain fully compatible. + +--- + ## References - MOS Technology 6526/8520 datasheet - ADCD 2.1 Hardware Manual — CIA chapter: http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/ - NDK39: `hardware/cia.h`, `resources/cia.h` - Autodocs: `cia` resource — http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node00C7.html + diff --git a/01_hardware/common/gayle_ide_pcmcia.md b/01_hardware/common/gayle_ide_pcmcia.md new file mode 100644 index 0000000..1a9186b --- /dev/null +++ b/01_hardware/common/gayle_ide_pcmcia.md @@ -0,0 +1,220 @@ +[← Home](../../README.md) · [Hardware](../README.md) · [Common](../common/) + +# Gayle — IDE & PCMCIA Controller + +## Overview + +**Gayle** is Commodore's custom gate-array chip providing **ATA/IDE** hard drive and **PCMCIA Type II** card slot interfaces. It appears in two models with different silicon revisions: + +| Model | Gayle ID | IDE | PCMCIA | Notes | +|---|---|---|---|---| +| **A600** | `$D0` | Yes (ECS system) | Yes | First Gayle implementation | +| **A1200** | `$D1` | Yes (AGA system) | Yes | Different byte-lane mapping | + +The **CD32** does *not* have Gayle — its storage is handled by [Akiko](../aga_a1200_a4000/akiko_cd32.md). + +The **A4000** uses a different IDE interface (directly on the motherboard, no Gayle chip). + +## Gayle Identification + +The Gayle ID register shifts one bit per read access: + +```asm + move.b $DA8000, d0 ; Read Gayle ID byte + ; d0 = $D0 → A600 Gayle + ; d0 = $D1 → A1200 Gayle +``` + +```c +#define GAYLE_ID_ADDR 0xDA8000 + +volatile UBYTE *gayle_id = (UBYTE *)GAYLE_ID_ADDR; +UBYTE id_byte = *gayle_id; +/* $D0 = A600, $D1 = A1200 */ +``` + +On machines without Gayle (A500, A2000, A3000, A4000, CD32), reading `$DA8000` returns bus noise — always check before assuming Gayle is present. + +--- + +## Gayle Register Map + +| Address | Register | R/W | Description | +|---|---|---|---| +| `$DA8000` | `GAYLE_ID` | R | Chip ID (shifts on each read access) | +| `$DA9000` | `GAYLE_INT_STATUS` | RW | Interrupt status (IDE + PCMCIA) | +| `$DA9004` | `GAYLE_INT_ENABLE` | RW | Interrupt enable mask | +| `$DA9008` | `GAYLE_CONTROL` | RW | Control register (PCMCIA power, wait states) | + +--- + +## IDE Interface + +### Register Maps — A600 vs A1200 + +The IDE registers are at base `$DA0000` on both models. The critical difference is **byte-lane mapping**: the A1200 places 8-bit ATA registers on **odd byte offsets** within each 4-byte window, while the A600 uses even offsets. + +#### A600 IDE Registers + +| Address | ATA Register | R/W | +|---|---|---| +| `$DA0000` | Data (16-bit) | RW | +| `$DA0004` | Error (R) / Features (W) | RW | +| `$DA0008` | Sector Count | RW | +| `$DA000C` | Sector Number (LBA 7:0) | RW | +| `$DA0010` | Cylinder Low (LBA 15:8) | RW | +| `$DA0014` | Cylinder High (LBA 23:16) | RW | +| `$DA0018` | Drive/Head (LBA 27:24) | RW | +| `$DA001C` | Status (R) / Command (W) | RW | +| `$DA101C` | Alternate Status / Device Control | RW | + +#### A1200 IDE Registers + +| Address | ATA Register | R/W | +|---|---|---| +| `$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 (LBA 27:24) | RW | +| `$DA001D` | Status (R) / Command (W) | RW | +| `$DA101D` | Alternate Status / Device Control | RW | + +> [!IMPORTANT] +> The A1200 byte-lane offset (+1 from A600) is because Gayle maps 8-bit ATA registers on the **odd byte lane** of the 16-bit Amiga bus. IDE drivers must account for this — a single driver cannot blindly use the same offsets for both machines. Check the Gayle ID first. + +### PIO Data Transfer + +IDE data transfers use 16-bit word access to the Data register: + +```asm +; Read one sector (512 bytes = 256 words) from IDE +; a0 = destination buffer + + lea $DA0000, a1 ; IDE data register + move.w #255, d0 ; 256 words +.read_loop: + move.w (a1), (a0)+ ; read word from IDE → buffer + dbf d0, .read_loop +``` + +--- + +## PCMCIA Interface + +Both A600 and A1200 support a **Type II PCMCIA** (PC Card) slot: + +| Address Range | Type | Description | +|---|---|---| +| `$600000`–`$9FFFFF` | Attribute memory | Card CIS (Card Information Structure) | +| `$A00000`–`$A3FFFF` | Common memory | Data / I/O window | +| `$A40000`–`$A7FFFF` | Common memory (cont.) | Extended data area | + +### Card Insertion Sequence + +1. Card insertion triggers `GAYLE_IRQ_CD` (card detect interrupt) +2. Software reads CIS from attribute memory at `$600000` to identify card type +3. Parse `CONFIG` tuple for card configuration +4. For **ATA cards** (CompactFlash in PCMCIA adapter): configure as IDE device +5. For **network/modem cards**: use card-specific I/O mapping +6. For **SRAM cards**: map as block device (up to 4 MB) + +--- + +## Interrupt Handling + +### Interrupt Routing + +Gayle routes all its interrupts through **CIA-A** `/FLG` pin → `CIAICRF_FLG` → CPU **IPL 6** (INT6). + +### Interrupt Status Bits + +```c +/* $DA9000 GAYLE_INT_STATUS — read to check, write 0 to clear */ +#define GAYLE_IRQ_IDE (1<<7) /* IDE drive interrupt (A1200) */ + /* bit 6 on A600 */ +#define GAYLE_IRQ_CARD (1<<6) /* PCMCIA card interrupt */ +#define GAYLE_IRQ_BVD1 (1<<5) /* PCMCIA battery voltage detect 1 */ +#define GAYLE_IRQ_BVD2 (1<<4) /* PCMCIA battery voltage detect 2 */ +#define GAYLE_IRQ_WP (1<<3) /* PCMCIA write protect */ +#define GAYLE_IRQ_CD (1<<2) /* PCMCIA card detect */ +``` + +> [!WARNING] +> The IDE interrupt bit position differs between A600 and A1200 Gayle revisions. Always check the Gayle ID register before masking interrupt bits. + +### Interrupt Service Routine + +```asm +; Gayle ISR (INT6 handler) +gayle_isr: + move.b $DA9000, d0 ; read GAYLE_INT_STATUS + btst #7, d0 ; IDE interrupt? (A1200) + beq.s .check_pcmcia + + ; Handle IDE interrupt + move.b $DA001D, d1 ; read ATA status to clear INTRQ + bclr #7, $DA9000 ; clear Gayle IDE IRQ + bra.s .done + +.check_pcmcia: + btst #6, d0 ; PCMCIA interrupt? + beq.s .done + ; Handle PCMCIA... + bclr #6, $DA9000 ; clear PCMCIA IRQ + +.done: + rte +``` + +--- + +## PCMCIA Power Control + +Gayle controls PCMCIA card power (5V standard; 3.3V on A1200 rev 1D+): + +```c +/* $DA9008 GAYLE_CONTROL bits */ +#define GAYLE_POW (1<<7) /* PCMCIA power on/off */ +#define GAYLE_WS (1<<6) /* Wait states for PCMCIA access */ +``` + +--- + +## AmigaOS IDE Access + +AmigaOS accesses Gayle IDE through the standard device driver stack: + +``` +Application → dos.library → File System Handler → scsi.device / ata.device → Gayle IDE +``` + +Applications never access Gayle registers directly: + +```c +/* Standard file access — no direct Gayle interaction */ +BPTR fh = Open("DH0:myfile", MODE_NEWFILE); +Write(fh, data, length); +Close(fh); +``` + +The A600 uses `scsi.device` from Kickstart ROM. The A1200 uses `ata.device` (also called `ide.device` in some OS versions) which includes A1200-specific byte-lane handling. + +--- + +## References + +- Commodore A600 Technical Reference Manual — Gayle chapter +- Commodore A1200 Technical Reference Manual — Gayle chapter +- NDK39: community-documented Gayle registers (no official header) +- ADCD 2.1: `scsi.device` / `ata.device` Autodocs +- [Big Book of Amiga Hardware](https://bigbookofamigahardware.com/) — Gayle pinout and board photos + +## See Also + +- [Akiko — CD32 Custom Chip](../aga_a1200_a4000/akiko_cd32.md) — CD32 uses Akiko instead of Gayle +- [Gary — A3000 System Controller](../ecs_a600_a3000/gary_system_controller.md) — A3000 bus controller (no IDE) +- [CIA Chips](cia_chips.md) — Gayle routes interrupts through CIA-A +- [Memory Types](memory_types.md) — IDE storage as expansion path diff --git a/01_hardware/common/memory_types.md b/01_hardware/common/memory_types.md index 9a61bec..8935c96 100644 --- a/01_hardware/common/memory_types.md +++ b/01_hardware/common/memory_types.md @@ -122,6 +122,8 @@ This is why adding Fast RAM instantly speeds up the system — Workbench, librar | **A3000** | 1990 | 68030 @ 25 MHz | 1–2 MB | 2 MB | 4–16 MB Fast (on-board) | 4× Zorro III + CPU slot | 32-bit bus, first Zorro III | | **A1200** | 1992 | 68EC020 @ 14 MHz | 2 MB | 2 MB | None stock | Trapdoor 150-pin + PCMCIA | AGA chipset | | **A4000** | 1992 | 68030 @ 25 MHz or 68040 @ 25 MHz | 2 MB | 2 MB | 4–16 MB Fast (on-board) | 5× Zorro III + CPU slot | AGA, big-box | +| **CDTV** | 1991 | 68000 @ 7.09 MHz | 1 MB | 2 MB (Super Agnus mod) | None stock | None (A2000-compatible internal) | OCS, CD-ROM, IR remote, NVRAM | +| **CD32** | 1993 | 68EC020 @ 14 MHz | 2 MB | 2 MB | None stock | FMV slot only (SX-1/SX-32 add-on) | AGA, Akiko C2P, 2× CD-ROM | ### Expansion Capabilities @@ -135,6 +137,8 @@ This is why adding Fast RAM instantly speeds up the system — Workbench, librar | **A3000** | Fixed 2 MB | On-board (Ramsey), Zorro III cards | 256 MB (Zorro III) | | **A1200** | Fixed 2 MB | Trapdoor accelerator, PCMCIA (4 MB) | 256 MB (accelerator) | | **A4000** | Fixed 2 MB | On-board (Ramsey), Zorro III, CPU slot | 256 MB+ (accelerator + Zorro III) | +| **CDTV** | To 2 MB (Super Agnus mod) | None standard; internal A2000-compatible bus | ~2 MB (rare 3rd-party via internal expansion) | +| **CD32** | Fixed 2 MB | SX-1/SX-32 add-on provides trapdoor-style slot | 128 MB (SX-32 + accelerator) | --- diff --git a/01_hardware/ecs_a600_a3000/README.md b/01_hardware/ecs_a600_a3000/README.md index 4cde627..f6c4835 100644 --- a/01_hardware/ecs_a600_a3000/README.md +++ b/01_hardware/ecs_a600_a3000/README.md @@ -21,7 +21,8 @@ The **Enhanced Chip Set** (ECS) is a significant revision of OCS, shipping from | [chipset_ecs.md](chipset_ecs.md) | Super Agnus and ECS Denise internals | | [ecs_registers_delta.md](ecs_registers_delta.md) | New/changed registers vs OCS | | [productivity_modes.md](productivity_modes.md) | Multiscan/productivity display modes | -| [gary_gayle.md](gary_gayle.md) | Gary (A3000) and Gayle (A600) chips: IDE, PCMCIA | +| [gary_system_controller.md](gary_system_controller.md) | Gary — A3000 bus controller, DMA arbitration, SCSI glue | +| [Gayle IDE & PCMCIA](../common/gayle_ide_pcmcia.md) | A600 Gayle: IDE and PCMCIA (shared with A1200) | | [chip_ram_expansion.md](chip_ram_expansion.md) | 2 MB Chip RAM with Super Agnus | ## ECS vs OCS — Key Differences diff --git a/01_hardware/ecs_a600_a3000/gary_gayle.md b/01_hardware/ecs_a600_a3000/gary_gayle.md deleted file mode 100644 index 2e4ff30..0000000 --- a/01_hardware/ecs_a600_a3000/gary_gayle.md +++ /dev/null @@ -1,114 +0,0 @@ -[← Home](../../README.md) · [Hardware](../README.md) · [ECS](README.md) - -# Gary & Gayle — System Controller Chips - -## Gary (A3000) - -**Gary** is the custom system controller chip in the A3000, combining functions that are discrete ICs on the A2000: - -- **Bus controller**: Manages the interaction between 68030/68882, chip bus, and Zorro III -- **Auto-config controller**: Runs the Zorro expansion enumeration -- **DMA arbitration**: Between 68030, custom chips, and Zorro III DMA -- **SCSI interface glue**: Works with the A3000's built-in WD33C93 SCSI controller -- **ROM decode**: Maps Kickstart ROM into the address space - -Gary is not directly programmable by user software; its configuration is set by hardware strapping and the ROM initialisation sequence. - -## Gayle (A600 / A1200) - -**Gayle** is the custom chip providing **IDE** and **PCMCIA** interface on the A600 and A1200. The A600 and A1200 use different Gayle revisions with different PCMCIA pinouts. - -### Gayle Identification - -``` -A600 Gayle revision ID: read from $DA8000 -A1200 Gayle revision ID: read from $DA8000 -``` - -```asm -move.b $DA8000, d0 ; Read Gayle ID byte -``` - -| Byte | Machine | -|---|---| -| $D0 | A600 Gayle | -| $D1 | A1200 Gayle (revision 1) | - -### Gayle Register Map (A600/A1200) - -| Address | Register | Description | -|---|---|---| -| $DA8000 | GAYLE_ID | Chip ID (read shifts bits) | -| $DA9000 | GAYLE_INT_STATUS | Interrupt status | -| $DA9004 | GAYLE_INT_ENABLE | Interrupt enable | -| $DA9008 | GAYLE_CONTROL | Control register | - -### IDE Interface - -The IDE interface via Gayle is at `$DA0000` (A1200) or `$DA0000` (A600): - -| Offset | Register | Description | -|---|---|---| -| $DA0000 | DATA | IDE data register (16-bit) | -| $DA0004 | ERROR/FEATURE | Error (read) / Feature (write) | -| $DA0008 | SECTOR_COUNT | Sector count | -| $DA000C | SECTOR_NUMBER | Sector number (LBA 7:0) | -| $DA0010 | CYLINDER_LOW | Cylinder low (LBA 15:8) | -| $DA0014 | CYLINDER_HIGH | Cylinder high (LBA 23:16) | -| $DA0018 | DRIVE_HEAD | Drive/Head/LBA (LBA 27:24) | -| $DA001C | STATUS/COMMAND | Status (read) / Command (write) | -| $DA101C | ALT_STATUS | Alternate status (no interrupt clear) | -| $DA101C | DEVICE_CONTROL | Device control (write) | - -> [!NOTE] -> On the A1200, IDE registers are byte-wide on odd addresses in a 16-bit window. The data register is 16-bit. This differs from standard PC IDE — byte lanes are swapped relative to x86 convention. - -### PCMCIA Interface (A600/A1200) - -The A600 and A1200 support a Type II PCMCIA (PC Card) slot: - -| Address Range | Type | Description | -|---|---|---| -| $600000–$9FFFFF | Attribute memory | Card configuration (CIS access) | -| $A00000–$A3FFFF | Common memory | Modem/network card data | -| $A40000–$A7FFFF | Common memory (cont.) | | -| $600000 (Gayle) | Gayle attribute | Gayle own config space | - -PCMCIA interrupt routing: Card interrupt → Gayle → CIA-A (`/FLG` pin) → CPU IPL 6. - -### Gayle Interrupt Bits - -```c -/* DA9000 GAYLE_INT_STATUS */ -#define GAYLE_IRQ_IDE (1<<6) /* IDE drive interrupt */ -#define GAYLE_IRQ_CARD (1<<5) /* PCMCIA card interrupt */ -#define GAYLE_IRQ_BVD1 (1<<4) /* PCMCIA battery voltage 1 */ -#define GAYLE_IRQ_BVD2 (1<<3) /* PCMCIA battery voltage 2 */ -#define GAYLE_IRQ_WP (1<<2) /* PCMCIA write protect */ -#define GAYLE_IRQ_CD (1<<1) /* PCMCIA card detect */ -``` - -### Gayle Power Control - -Gayle controls PCMCIA card power (5V / 3.3V on A1200 rev 1D+): -```c -/* GAYLE_CONTROL bits */ -#define GAYLE_POW (1<<7) /* PCMCIA power on */ -#define GAYLE_WS (1<<6) /* wait states for PCMCIA */ -``` - -## AmigaOS IDE Access - -AmigaOS accesses the Gayle IDE through the `scsi.device` or dedicated `ata.device` driver provided with OS 3.1+. Direct IDE programming is done in the filesystem handler (`trackdisk.device` replacement). - -The standard path: -``` -Application → dos.library → File System Handler → scsi.device → Gayle IDE -``` - -## References - -- Commodore A600 Technical Reference Manual — Gayle chapter -- Commodore A1200 Technical Reference Manual — Gayle chapter -- ADCD 2.1 — `Devices_Manual_guide/` scsi.device -- NDK39: `hardware/gayle.h` (if present), community-documented Gayle registers diff --git a/01_hardware/ecs_a600_a3000/gary_system_controller.md b/01_hardware/ecs_a600_a3000/gary_system_controller.md new file mode 100644 index 0000000..f63d78b --- /dev/null +++ b/01_hardware/ecs_a600_a3000/gary_system_controller.md @@ -0,0 +1,62 @@ +[← Home](../../README.md) · [Hardware](../README.md) · [ECS](README.md) + +# Gary — A3000 System Controller + +## Overview + +**Gary** is the custom system controller chip in the Amiga 3000. It consolidates functions that are discrete ICs on the A2000 into a single gate array: + +- **Bus controller**: Manages interaction between 68030/68882, chip bus, and Zorro III +- **Auto-config controller**: Runs Zorro expansion enumeration at boot +- **DMA arbitration**: Between 68030, custom chips, and Zorro III DMA masters +- **SCSI interface glue**: Works with the A3000's built-in WD33C93 SCSI controller +- **ROM decode**: Maps Kickstart ROM into the address space + +Gary is not directly programmable by user software; its configuration is set by hardware strapping and the ROM initialisation sequence. + +## Bus Arbitration + +Gary manages three bus masters: + +| Master | Priority | Description | +|---|---|---| +| Custom chips (DMA) | Highest | Agnus DMA for display, audio, disk — must never stall | +| 68030 CPU | Normal | Program execution | +| Zorro III cards | Lowest | Expansion bus-mastering DMA | + +When a custom chip DMA cycle occurs, Gary holds the 68030 off the bus until the cycle completes. This is the fundamental source of "DMA contention" slowdown on all Amiga models. + +## A3000 SCSI Integration + +The A3000 includes a built-in **WD33C93A** SCSI controller. Gary provides the glue logic between the SCSI chip and the system bus: + +| Feature | Details | +|---|---| +| SCSI chip | WD33C93A (SBIC) | +| DMA | SDMAC — dedicated SCSI DMA controller (separate from the CDTV-style DMAC) | +| Interface | A3000 uses a dedicated SDMAC chip, not the A2091-style DMAC | +| AmigaOS driver | `scsi.device` in Kickstart ROM | + +> [!NOTE] +> The A3000's SDMAC is a different chip from the A2091/CDTV DMAC, despite both interfacing with WD33C93 SCSI controllers. The register layouts are incompatible. + +## Machines Using Gary + +| Model | Gary variant | Notes | +|---|---|---| +| A3000 | Original Gary | 68030, Zorro III, WD33C93 SCSI | +| A3000T | Gary (tower variant) | Same chip; tower form factor with more drive bays | + +The A4000 does **not** use Gary — it uses a different system controller chip called **Ramsey** along with **Budgie** and **Buster** for bus management. + +## References + +- Commodore A3000 Technical Reference Manual +- ADCD 2.1 — Hardware Manual, A3000 chapter +- NDK39: hardware headers (community-documented Gary behaviour) + +## See Also + +- [Gayle — IDE & PCMCIA](../common/gayle_ide_pcmcia.md) — A600/A1200 storage controller (different chip, different function) +- [Zorro Bus](../common/zorro_bus.md) — Zorro II/III expansion managed by Gary +- [ECS Chipset](chipset_ecs.md) — Super Agnus + ECS Denise (A3000) diff --git a/01_hardware/ocs_a500/README.md b/01_hardware/ocs_a500/README.md index 0a4d658..a1cf653 100644 --- a/01_hardware/ocs_a500/README.md +++ b/01_hardware/ocs_a500/README.md @@ -25,6 +25,65 @@ The **Original Chip Set** (OCS) ships in the Amiga 1000 (1985), A500 (1987), and | [paula_audio.md](paula_audio.md) | Audio DMA: AUDxLCH/LCL/LEN/PER/VOL, interrupt | | [paula_serial.md](paula_serial.md) | Serial port: SERPER/SERDATR, baud rate | | [sprites.md](sprites.md) | Hardware sprites: SPRxPTH, control words, attach mode | +| [cdtv_hardware.md](cdtv_hardware.md) | CDTV platform: DMAC, CD-ROM, IR remote, NVRAM | + +--- + +## OCS Machines — Per-Model Details + +### A1000 (1985) — Writable Control Store + +The A1000 is the original Amiga. Its most distinctive feature is the **Writable Control Store (WCS)** — Kickstart is loaded from floppy into RAM at every cold boot, rather than residing in ROM. + +| Feature | Details | +|---|---| +| CPU | 68000 @ 7.09 MHz | +| Chip RAM | 256 KB base (daughterboard adds 256 KB = 512 KB total) | +| Kickstart | Loaded from floppy into 256 KB WCS RAM at `$F80000` | +| Bootstrap ROM | 256 bytes at `$FC0000` — just enough to load Kickstart from floppy | +| Expansion | 86-pin sidecar bus (predecessor to Zorro) | + +**WCS boot process:** +1. Power on → bootstrap ROM displays "Insert Kickstart disk" +2. User inserts Kickstart 1.x floppy +3. Bootstrap loads 256 KB Kickstart image into WCS RAM +4. Hardware write-protect latch activates → WCS becomes read-only +5. System resets and boots from the now-protected WCS as if it were ROM + +> [!NOTE] +> The WCS is the reason the A1000 can run different Kickstart versions without swapping ROM chips. Third-party "Kickstart Eliminators" add actual ROM chips, bypassing the floppy-loading step entirely. + +The A1000 daughterboard (256 KB Chip RAM expansion) sits inside the case on top of the motherboard. The 86-pin sidecar connector on the right side accepts external expansion chassis for memory, hard drives, and other peripherals. + +### A2000 (1987) — The Expandable Workhorse + +The A2000 is the first "big-box" Amiga, designed for professional expansion. It shipped in two major variants: + +| Variant | Board Revisions | Chipset | Chip RAM | Notes | +|---|---|---|---|---| +| **A2000-A** (German) | Rev 3.x | OCS (Agnus 8361) | 512 KB | Original design by Commodore Germany | +| **A2000-B** (US) | Rev 4.x | OCS (Fat Agnus 8370/8372) | 512 KB + 512 KB slow | Redesigned for US market | +| **A2000-C** | Rev 6.x | ECS (Super Agnus 8372A) | 1 MB Chip | Late production with ECS chips | + +#### Expansion Architecture + +| Slot Type | Count | Bus Width | Address Space | Description | +|---|---|---|---|---| +| **Zorro II** | 5 | 16-bit | `$200000`–`$9FFFFF` (8 MB) | Autoconfig expansion cards | +| **CPU slot** | 1 | Direct 68000 | — | Directly wired to CPU socket — accepts accelerators (A2630, GVP G-Force) | +| **Video slot** | 1 | 36-pin | — | Internal video signals for genlocks and framebuffers | +| **ISA (PC bridgeboard)** | 2 | 8/16-bit | — | For A2088/A2286 PC compatibility cards | + +The CPU slot is the A2000's most important expansion feature. Accelerator cards plug directly into the 68000 socket, replacing the CPU with 68020/030/040/060 processors. This makes the A2000 the most upgradeable classic Amiga. + +> [!NOTE] +> Late A2000 boards (rev 6+) shipped with ECS chips and are sometimes listed under ECS. Architecturally they remain A2000 boards with the same Zorro II bus and expansion layout. + +### CDTV (1991) — CD-ROM Set-Top Box + +The CDTV is an A500-class OCS computer in a consumer set-top box form factor. See the dedicated article: **[CDTV Platform Hardware](cdtv_hardware.md)** — covers the DMAC/WD33C93 SCSI CD-ROM controller, 512 KB Extended ROM, 64 KB NVRAM, infrared remote, and real-time clock. + +--- ## OCS Limitations vs ECS/AGA diff --git a/01_hardware/ocs_a500/cdtv_hardware.md b/01_hardware/ocs_a500/cdtv_hardware.md new file mode 100644 index 0000000..9b05bfc --- /dev/null +++ b/01_hardware/ocs_a500/cdtv_hardware.md @@ -0,0 +1,283 @@ +[← Home](../../README.md) · [Hardware](../README.md) · [OCS](README.md) + +# CDTV — Platform Hardware + +## Overview + +The **Commodore Dynamic Total Vision** (CDTV, 1991) is an A500-class OCS computer packaged as a consumer CD-ROM set-top box. Internally it uses the same Agnus/Denise/Paula chipset as the A500, but adds several unique subsystems: + +1. **DMAC + WD33C93 SCSI controller** — drives the internal CD-ROM via DMA +2. **Extended ROM** — 512 KB of additional firmware for CD filesystem and player software +3. **NVRAM** — 64 KB battery-backed non-volatile storage +4. **IR remote receiver** — proprietary 40 kHz infrared protocol +5. **Real-Time Clock** — Oki MSM6242B at `$DC0000` + +The CDTV has **no keyboard** (optional external), **no internal floppy** (optional external), and **no expansion slots** visible to the end user. It targets the living room, not the desktop. + +## System Specifications + +| Parameter | Value | +|---|---| +| CPU | 68000 @ 7.09 MHz (PAL) / 7.16 MHz (NTSC) | +| Chipset | OCS (Agnus 8361/8367, Denise 8362, Paula 8364) | +| Chip RAM | 1 MB (expandable to 2 MB with Super Agnus mod) | +| Fast RAM | None stock | +| ROM | 256 KB Kickstart 1.3 + 512 KB Extended ROM | +| CD-ROM | Single-speed (1×), SCSI-based via DMAC/WD33C93 | +| Audio | 4-channel Paula DMA + CD-DA passthrough | +| Video | Composite, S-Video, RF (no RGB without mod) | +| Controller | IR remote, optional external keyboard | +| Storage | CD-ROM, 64 KB NVRAM | + +## Address Map — CDTV-Specific Regions + +The standard OCS 24-bit address map applies. The CDTV adds these regions: + +| Address Range | Size | Region | +|---|---|---| +| `$DC0000`–`$DC003F` | 64 B | Real-Time Clock (Oki MSM6242B) | +| `$E00000`–`$E3FFFF` | 256 KB | Extended ROM bank 1 (CD filesystem, player UI) | +| `$E40000`–`$E7FFFF` | 256 KB | Extended ROM bank 2 (DMAC driver, boot logic) | +| `$E90000`–`$E9FFFF` | 64 KB | DMAC registers (WD33C93 SCSI DMA controller) | +| `$F00000`–`$F3FFFF` | 256 KB | NVRAM (battery-backed, 64 KB actual usable) | + +See also: [Address Space](../common/address_space.md) — full 24-bit map with CDTV-specific entries. + +--- + +## DMAC and WD33C93 SCSI Controller + +### Architecture + +The CDTV's CD-ROM is connected via a **SCSI bus** — the same architecture used in the A2091 and A590 hard drive controllers. The system uses two chips: + +| Chip | Role | +|---|---| +| **DMAC** (Commodore custom) | DMA controller — transfers data between the WD33C93 and Amiga memory | +| **WD33C93** (Western Digital) | SCSI Bus Interface Controller (SBIC) — handles SCSI protocol with the CD-ROM drive | + +This is fundamentally different from the CD32, where Akiko handles CD-ROM control directly via PIO. + +### DMAC Register Map + +The DMAC is mapped at `$E90000`: + +| Offset | Register | R/W | Description | +|---|---|---|---| +| `$E90000` | `DAWR` | W | DMAC address write (DMA destination) | +| `$E90002` | `WTCH` | W | Word Transfer Count High | +| `$E90004` | `CNTR` | RW | Control register (DMA direction, interrupt enable) | +| `$E90040` | `ACR_H` | W | Address Counter Register high word | +| `$E90042` | `ACR_L` | W | Address Counter Register low word | +| `$E90048` | `ST_DMA` | W | Start DMA transfer (write any value) | +| `$E9004A` | `FLUSH` | W | Flush DMA FIFO | +| `$E9004C` | `CINT` | W | Clear DMAC interrupt | +| `$E9004E` | `ISTR` | R | Interrupt Status Register | +| `$E90090` | `SASR` | W | WD33C93 Address/Select Register | +| `$E90091` | `SCMD` | RW | WD33C93 Data Register (read/write SBIC registers) | + +### WD33C93 SBIC Registers + +The WD33C93 is accessed indirectly through the DMAC. Write the target register number to `SASR` (`$E90090`), then read/write data via `SCMD` (`$E90091`): + +| Register | Name | Description | +|---|---|---| +| `$00` | Own ID | SCSI initiator ID (typically 7) | +| `$01` | Control | DMA mode, interrupt enables | +| `$02` | Timeout | Selection timeout period | +| `$03`–`$0B` | CDB | Command Descriptor Block (SCSI command bytes) | +| `$0F` | Command | SCSI command register (initiate bus phases) | +| `$10` | Data | Data transfer register (PIO mode) | +| `$17` | Status | SCSI bus phase and completion status | + +### SCSI Commands for CD-ROM + +The CD-ROM drive responds to standard SCSI-2 commands: + +| Command | Opcode | Use | +|---|---|---| +| `TEST UNIT READY` | `$00` | Check drive presence | +| `READ(6)` | `$08` | Read data sectors (Mode 1) | +| `READ(10)` | `$28` | Read data sectors (extended addressing) | +| `READ TOC` | `$43` | Read Table of Contents | +| `PLAY AUDIO(10)` | `$45` | Play CD-DA audio tracks | +| `PAUSE/RESUME` | `$4B` | Pause/resume audio playback | +| `READ SUB-CHANNEL` | `$42` | Read current position, ISRC, UPC/EAN | + +### AmigaOS Access + +Under AmigaOS, the CD-ROM is accessed through `scsi.device` loaded from Extended ROM: + +``` +Application → dos.library → cdfs (CD filesystem handler) → scsi.device → DMAC → WD33C93 → CD-ROM +``` + +--- + +## Extended ROM + +The CDTV includes **512 KB of additional ROM** mapped at `$E00000`–`$E7FFFF`, split across two 256 KB banks. This ROM contains: + +| Bank | Address Range | Contents | +|---|---|---| +| Bank 1 | `$E00000`–`$E3FFFF` | CD filesystem (CDFS), audio player UI, bookmark manager | +| Bank 2 | `$E40000`–`$E7FFFF` | DMAC/WD33C93 device driver (`scsi.device`), boot sequence, system initialization | + +The Extended ROM is **not present** on standard A500/A2000 machines. Software that detects CDTV typically checks for the presence of `cdtv.device` or reads the Extended ROM base. + +### Boot Sequence + +1. Kickstart 1.3 loads from ROM (`$F80000`) +2. Extended ROM at `$E00000` is detected and initialised +3. `scsi.device` from Extended ROM initialises DMAC + WD33C93 +4. CD-ROM drive is probed for a bootable disc +5. If a valid Amiga boot block is found on the CD → boot from CD +6. If no CD → fall through to standard floppy boot (if external floppy present) + +--- + +## NVRAM (Non-Volatile Storage) + +### Hardware + +The CDTV includes **64 KB of battery-backed SRAM** mapped at `$F00000`–`$F3FFFF`. This is fundamentally different from the CD32's tiny serial EEPROM — the CDTV has substantially more storage. + +| Parameter | Value | +|---|---| +| Type | Battery-backed SRAM | +| Capacity | 64 KB (512 Kbit) | +| Address | `$F00000`–`$F0FFFF` (64 KB usable within 256 KB window) | +| Persistence | Battery-backed (internal lithium cell) | +| Access | Direct memory-mapped (byte-addressable) | +| Typical use | Bookmarks, game saves, user preferences | + +### Access + +Unlike the CD32's I²C EEPROM, CDTV NVRAM is **directly memory-mapped** — the CPU reads and writes it like normal RAM: + +```asm +; Read a byte from NVRAM + move.b $F00000, d0 ; read first byte of NVRAM + +; Write a byte to NVRAM + move.b d0, $F00000 ; write to NVRAM — persists across power cycles +``` + +### AmigaOS Interface + +The CDTV provides `bookmark.device` for structured NVRAM access: + +```c +/* CDTV bookmark access — stores named data blocks in NVRAM */ +struct IOStdReq *io; +/* ... open bookmark.device ... */ +io->io_Command = CMD_WRITE; +io->io_Data = save_data; +io->io_Length = data_length; +DoIO((struct IORequest *)io); +``` + +--- + +## Infrared Remote Controller + +### Hardware + +The CDTV includes a dedicated IR receiver module and ships with a full remote control unit. The remote provides media playback buttons, a numeric keypad, and navigation controls. + +### Protocol + +The CDTV uses a **proprietary IR protocol** (not NEC, not RC-5): + +| Parameter | Value | +|---|---| +| Carrier frequency | 40 kHz | +| Frame size | 12-bit command + 12-bit inverted (24-bit total) | +| Header | 9 ms pulse + 4.5 ms space | +| Bit encoding | 400 µs pulse + variable space (400 µs = 0, 1200 µs = 1) | +| Repeat | 9 ms pulse + 2.1 ms space + 400 µs end (every ~60 ms) | +| Receiver | Dedicated module tuned for 40 kHz (TSOP38240 compatible) | + +### Button Mapping + +| Button | Code | Function | +|---|---|---| +| Play/Pause | `$01` | Media playback toggle | +| Stop | `$02` | Stop playback | +| Forward | `$03` | Next track / fast forward | +| Rewind | `$04` | Previous track / rewind | +| Vol+ | `$05` | Volume up | +| Vol− | `$06` | Volume down | +| 0–9 | `$10`–`$19` | Numeric keypad | +| Enter | `$1A` | Confirm / select | +| Escape | `$1B` | Cancel / back | +| Up/Down/Left/Right | `$1C`–`$1F` | Navigation | +| A / B | `$20` / `$21` | Assignable (game buttons) | + +> [!NOTE] +> The IR receiver connects to the system as a keyboard-like input device. AmigaOS treats remote button presses as `IECLASS_RAWKEY` input events with dedicated qualifier codes. Standard `input.device` handlers receive these events transparently. + +--- + +## Real-Time Clock + +The CDTV includes an **Oki MSM6242B** RTC chip at `$DC0000`: + +| Address | Register | Description | +|---|---|---| +| `$DC0001` | Seconds (units) | BCD 0–9 | +| `$DC0003` | Seconds (tens) | BCD 0–5 | +| `$DC0005` | Minutes (units) | BCD 0–9 | +| `$DC0007` | Minutes (tens) | BCD 0–5 | +| `$DC0009` | Hours (units) | BCD 0–9 | +| `$DC000B` | Hours (tens) | BCD 0–2 | +| `$DC000D` | Day (units) | BCD 0–9 | +| `$DC000F` | Day (tens) | BCD 0–3 | +| `$DC0011` | Month (units) | BCD 0–9 | +| `$DC0013` | Month (tens) | BCD 0–1 | +| `$DC0015` | Year (units) | BCD 0–9 | +| `$DC0017` | Year (tens) | BCD 0–9 | +| `$DC0019` | Day of week | 0–6 | +| `$DC001B` | Control D | AM/PM, 12/24 mode | +| `$DC001D` | Control E | IRQ enable, test | +| `$DC001F` | Control F | Reset, busy flag | + +> [!NOTE] +> The same MSM6242B RTC is used in the A2000 and A3000. The register layout is identical across all models. + +--- + +## CDTV vs A500 — Hardware Comparison + +| Feature | A500 | CDTV | +|---|---|---| +| CPU | 68000 @ 7.09 MHz | 68000 @ 7.09 MHz | +| Chipset | OCS | OCS (identical) | +| Chip RAM | 512 KB–1 MB | 1 MB | +| ROM | 256 KB Kickstart | 256 KB Kickstart + **512 KB Extended ROM** | +| Storage | Internal floppy (880 KB) | **CD-ROM** (1×, 680 MB) + 64 KB NVRAM | +| Input | Keyboard + mouse + joystick | **IR remote** + optional ext. keyboard | +| Audio | Paula 4-channel | Paula + **CD-DA passthrough** | +| Video output | RGB (DB23) | Composite, S-Video, RF | +| Expansion | Trapdoor + side | None visible (internal A2000-compatible) | +| RTC | None stock (add-on) | **Oki MSM6242B** | + +### Software Compatibility + +The CDTV runs standard AmigaOS 1.3 software from CD or external floppy. The Extended ROM adds CD-specific functionality but does not break compatibility. Most A500 games work unmodified when loaded from compatible media. + +## References + +- Commodore CDTV Technical Reference Manual (internal) +- WD33C93 SCSI Bus Interface Controller datasheet (Western Digital) +- Oki MSM6242B Real-Time Clock datasheet +- WinUAE source: CDTV emulation code (Toni Wilen) +- [Big Book of Amiga Hardware — CDTV](https://bigbookofamigahardware.com/) +- ADCD 2.1: `scsi.device` Autodocs + +## See Also + +- [OCS Chipset](chipset_ocs.md) — Agnus/Denise/Paula (shared with CDTV) +- [Memory Types](../common/memory_types.md) — CDTV memory configuration +- [Address Space](../common/address_space.md) — CDTV address map with Extended ROM and NVRAM regions +- [CIA Chips](../common/cia_chips.md) — CIA A/B (shared across all models) diff --git a/08_graphics/README.md b/08_graphics/README.md index 2df202d..4ea919e 100644 --- a/08_graphics/README.md +++ b/08_graphics/README.md @@ -21,3 +21,4 @@ The Amiga graphics system is built on custom DMA-driven hardware (Agnus/Alice + | [views.md](views.md) | View, ViewPort, MakeVPort, display construction | | [text_fonts.md](text_fonts.md) | TextFont bitmap layout, baseline rendering, algorithmic styles, AvailFonts enumeration | | [animation.md](animation.md) | GEL system deep dive: BOBs, VSprites, AnimObs, hardware foundation (Blitter/Copper/Sprite interaction), collision detection, double buffering, performance tuning | +| [pixel_conversion.md](pixel_conversion.md) | Chunky↔Planar conversion: butterfly algorithm, Akiko C2P, Blitter-assisted, RTG bypass; SoA/AoS parallels to GPU/SIMD | diff --git a/08_graphics/blitter_programming.md b/08_graphics/blitter_programming.md index 47d72e5..9f026fd 100644 --- a/08_graphics/blitter_programming.md +++ b/08_graphics/blitter_programming.md @@ -977,4 +977,4 @@ The Blitter is one of the most complex subsystems to reproduce accurately in an - See also: [copper.md](copper.md) — Copper coprocessor (often co-programmed with the Blitter) - See also: [rastport.md](rastport.md) — RastPort drawing context (uses Blitter for all draw operations) - See also: [display_modes.md](display_modes.md) — DMA slot budget (Blitter competes for bus bandwidth) - +- See also: [Akiko — CD32 C2P](../01_hardware/aga_a1200_a4000/akiko_cd32.md) — hardware Chunky-to-Planar conversion (CD32 alternative to CPU/Blitter C2P) diff --git a/08_graphics/pixel_conversion.md b/08_graphics/pixel_conversion.md new file mode 100644 index 0000000..a2526ad --- /dev/null +++ b/08_graphics/pixel_conversion.md @@ -0,0 +1,494 @@ +[← Home](../README.md) · [Graphics](README.md) + +# Pixel Format Conversion — Chunky ↔ Planar and Beyond + +## The Core Problem + +Every Amiga programmer eventually hits the same wall: the custom chipset displays graphics in **planar** format, but nearly every interesting algorithm — 3D rendering, texture mapping, image decompression, PC game ports — produces output in **chunky** format. Converting between these two layouts is the single most CPU-intensive bottleneck in Amiga graphics programming. + +This article covers: +1. **What** planar and chunky formats are, mathematically +2. **Why** the conversion is expensive +3. **How** every known solution works — from naive loops to the Kalms butterfly +4. **Where** this problem appears in broader computing (SoA/AoS, GPU swizzle, SIMD) + +> [!NOTE] +> The Akiko hardware article covers the CD32's dedicated C2P register interface. This article covers the *algorithm theory* that applies to every Amiga model, and the broader data-layout concepts that connect the Amiga to modern computing. +> +> See: [Akiko — CD32 C2P Hardware](../01_hardware/aga_a1200_a4000/akiko_cd32.md) + +--- + +## Planar vs Chunky — The Two Layouts + +### Chunky (Packed Pixel) + +Every pixel's complete colour index is stored contiguously. For 8-bit (256 colour) pixels: + +``` +Address: $0000 $0001 $0002 $0003 $0004 $0005 $0006 $0007 +Data: $0D $05 $1B $0A $FF $03 $42 $7E + pixel0 pixel1 pixel2 pixel3 pixel4 pixel5 pixel6 pixel7 +``` + +Each byte = one pixel. Linear, simple, cache-friendly for rendering. This is how **every modern GPU**, every PC VGA card, every framebuffer since 1990 stores pixels. + +### Planar (Bitplane) + +Each pixel's colour index is **split across N separate memory regions** (bitplanes). For 8-bit pixels (8 bitplanes), each bitplane stores one bit of every pixel: + +``` +Bitplane 0: 1 0 1 1 0 0 1 0 ← bit 0 of pixels 0–7 +Bitplane 1: 0 1 0 1 1 0 0 1 ← bit 1 of pixels 0–7 +Bitplane 2: 1 1 0 0 0 1 1 0 ← bit 2 +Bitplane 3: 0 1 1 0 1 1 0 0 ← bit 3 +Bitplane 4: 1 0 1 0 1 0 0 1 ← bit 4 +Bitplane 5: 1 0 0 0 0 0 1 0 ← bit 5 +Bitplane 6: 0 0 1 0 0 0 0 1 ← bit 6 +Bitplane 7: 0 0 0 0 1 0 1 0 ← bit 7 +``` + +To read pixel 0's colour: collect bit 0 from each of the 8 planes → `10101100` = `$AC`. The 8 planes are **not interleaved** in standard Amiga layout — each is a separate contiguous memory block. + +### Why the Amiga Uses Planar + +The planar format was a brilliant engineering choice in 1985: + +| Advantage | Explanation | +|---|---| +| **Bandwidth efficiency** | A 4-colour screen uses 2 bitplanes = ½ the memory bandwidth of 4bpp chunky. DMA fetches only the planes actually used. | +| **Scalable colour depth** | Adding a bitplane doubles the colour count without redesigning the display engine. OCS: 1–6 planes. AGA: 1–8 planes. | +| **Cheap colour cycling** | Rotating palette indices only requires changing colour registers — zero memory writes. | +| **Blitter efficiency** | Blitting a masked sprite at 4 colours touches only 2 planes (2 blits), not 4× the data. | +| **Copper integration** | The Copper can change palette registers mid-scanline, effectively multiplying colours without more bitplanes. | + +The downside only became critical as rendering algorithms evolved past 2D sprites into 3D, texture mapping, and pixel-level effects that naturally produce chunky output. + +--- + +## The Conversion — Mathematically + +C2P is a **bit matrix transposition**. Given 32 chunky pixels (each 8 bits wide), you have a 32×8 bit matrix (32 rows × 8 columns). C2P transposes this to an 8×32 matrix (8 bitplanes × 32 bits each): + +``` +Input (chunky): Output (planar): + 32 pixels × 8 bits 8 bitplanes × 32 bits + ┌─────────────────┐ ┌──────────────────────────────┐ + │ P0: b7 b6 b5 b4 b3 b2 b1 b0 │ │ Plane 0: p0.b0 p1.b0 p2.b0 ... p31.b0 │ + │ P1: b7 b6 b5 b4 b3 b2 b1 b0 │ │ Plane 1: p0.b1 p1.b1 p2.b1 ... p31.b1 │ + │ ... │ │ ... │ + │ P31: b7 b6 b5 b4 b3 b2 b1 b0 │ │ Plane 7: p0.b7 p1.b7 p2.b7 ... p31.b7 │ + └─────────────────┘ └──────────────────────────────┘ +``` + +This is equivalent to a 90° bit rotation. On a modern CPU with SIMD, this is trivial. On a 68020 with 8 data registers and no bit-parallel instructions, it is an algorithmic challenge that consumed thousands of programmer-hours across the demoscene. + +--- + +## Solution 1 — The Naive Loop + +The simplest approach: iterate over every pixel, extract each bit, and set it in the corresponding bitplane. + +```c +/* Naive C2P — educational only, never use in production */ +void c2p_naive(UBYTE *chunky, UBYTE *planes[8], int width, int height) +{ + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + UBYTE pixel = chunky[y * width + x]; + int byte_offset = y * (width / 8) + (x / 8); + int bit_position = 7 - (x & 7); + + for (int plane = 0; plane < 8; plane++) + { + if (pixel & (1 << plane)) + planes[plane][byte_offset] |= (1 << bit_position); + else + planes[plane][byte_offset] &= ~(1 << bit_position); + } + } + } +} +``` + +**Performance:** ~200+ cycles per pixel on 68020. For 320×256 = 81,920 pixels → **~16 million cycles → ~1.1 seconds at 14 MHz**. This gives roughly **0.9 FPS**. Completely unusable. + +**Why it's terrible:** +- One bit at a time — no parallelism +- Read-modify-write on every bitplane byte (bus-killing) +- No register reuse — constant memory traffic +- Branch on every bit (pipeline flush on 68020) + +--- + +## Solution 2 — The Merge (Butterfly) Algorithm + +This is the standard approach used by virtually all serious Amiga C2P routines. Invented independently by several demoscene coders and formalised by **Mikael Kalms** (Kalmalyzer) and others. + +### The Key Insight + +Instead of processing one pixel at a time, load **32 pixels** (8 longwords = 256 bits) into CPU registers and perform a series of **bit-level swap operations** (called "merges") that progressively rearrange the bits into planar order. Each merge pass swaps bits at a different granularity: 16-bit blocks, then 8-bit, then 4-bit, 2-bit, and 1-bit. + +This is exactly a **butterfly network** — the same structure used in the FFT (Fast Fourier Transform) and Batcher's bitonic sort. + +### The Merge Primitive + +The fundamental building block is a 2-register swap that exchanges bits at a given stride: + +```asm +; merge(d0, d1, mask, shift) +; Exchanges bits between d0 and d1 where mask selects which bits to swap +; and shift determines the stride + + move.l d0, d2 ; temp = a + lsr.l #shift, d2 ; temp >>= stride + eor.l d1, d2 ; temp ^= b + and.l #mask, d2 ; temp &= mask (select bits to swap) + eor.l d2, d1 ; b ^= temp (swap into b) + lsl.l #shift, d2 ; temp <<= stride (restore position) + eor.l d2, d0 ; a ^= temp (swap into a) +``` + +**7 instructions** per merge. Each merge moves half the bits in two registers to their correct positions. + +### Pass Structure for 8 Bitplanes + +A full 8-bitplane C2P conversion on 32 pixels requires **5 passes** of merge operations: + +| Pass | Block Size | Mask | Swap Distance | Effect | +|---|---|---|---|---| +| 1 | 16-bit | `$0000FFFF` | 16 | Swap upper/lower halves of longword pairs | +| 2 | 8-bit | `$00FF00FF` | 8 | Swap bytes within pairs | +| 3 | 4-bit | `$0F0F0F0F` | 4 | Swap nibbles | +| 4 | 2-bit | `$33333333` | 2 | Swap bit-pairs | +| 5 | 1-bit | `$55555555` | 1 | Swap individual bits | + +After all 5 passes, the 8 data registers contain one longword per bitplane. + +### Full 8-Bitplane C2P Inner Loop + +```asm +; Kalms-style C2P inner loop — converts 32 chunky pixels (8 longwords) +; to 8 planar longwords (one per bitplane) +; +; Input: d0-d7 = 8 longwords of chunky data (4 pixels each) +; Output: d0-d7 = 8 longwords of planar data (one per bitplane) + +; ---- Pass 1: 16-bit swap ---- + swap d0 ; exchange upper/lower words of d0 + swap d1 + swap d2 + swap d3 + ; (merge d0,d4), (merge d1,d5), (merge d2,d6), (merge d3,d7) + ; using mask $0000FFFF, shift 16 + + move.l d0, a3 ; temp save + move.l d4, d0 + move.w a3, d0 ; d0 = d4.hi : d0.lo + move.w d4, a3 ; a3 = d0.hi : d4.lo + move.l a3, d4 + + move.l d1, a3 + move.l d5, d1 + move.w a3, d1 + move.w d5, a3 + move.l a3, d5 + + move.l d2, a3 + move.l d6, d2 + move.w a3, d2 + move.w d6, a3 + move.l a3, d6 + + move.l d3, a3 + move.l d7, d3 + move.w a3, d3 + move.w d7, a3 + move.l a3, d7 + +; ---- Pass 2: 8-bit swap ---- +; mask = $00FF00FF, shift = 8 + move.l #$00FF00FF, a3 + ; merge(d0, d2) + move.l d0, a4 + lsr.l #8, a4 + eor.l d2, a4 + and.l a3, a4 + eor.l a4, d2 + lsl.l #8, a4 + eor.l a4, d0 + ; merge(d1, d3) ... merge(d4, d6) ... merge(d5, d7) ... + ; (same pattern repeated for each pair) + +; ---- Pass 3: 4-bit swap ---- +; mask = $0F0F0F0F, shift = 4 + ; merge(d0, d1), merge(d2, d3), merge(d4, d5), merge(d6, d7) + +; ---- Pass 4: 2-bit swap ---- +; mask = $33333333, shift = 2 + +; ---- Pass 5: 1-bit swap ---- +; mask = $55555555, shift = 1 + +; Result: d0 = bitplane 0 (32 bits), d1 = bitplane 1, ... d7 = bitplane 7 +``` + +> [!NOTE] +> The above is a pedagogical skeleton. Production C2P routines are **heavily unrolled** and use every register trick available — address registers as temporary storage, interleaving loads with merges to hide memory latency, and sometimes splitting the conversion across two phases to overlap with Chip RAM writes. + +### Performance + +| Metric | Naive | Merge/Butterfly | Improvement | +|---|---|---|---| +| Instructions per 32 pixels | ~6,400+ | ~160–200 | **32–40×** | +| Cycles per pixel (68020 @ 14 MHz) | ~200 | ~5–7 | **~30×** | +| 320×256 full frame | ~1.1 s | ~35 ms | **~30× (28 FPS)** | +| 320×256 per frame budget | 0.9 FPS | **28 FPS** | Playable | + +--- + +## Solution 3 — Akiko Hardware C2P (CD32 Only) + +The CD32's Akiko chip implements C2P in dedicated silicon. The CPU feeds 8 longwords of chunky data to register `$B80030` and reads back 8 longwords of planar data from the same address. + +| Metric | Software C2P (68020) | Akiko | +|---|---|---| +| Method | CPU merge/butterfly | Hardware register pipeline | +| Throughput | ~1.5 MB/s | ~1.5 MB/s | +| CPU cost | 100% | ~50% (register I/O) | +| Availability | All Amigas | **CD32 only** | + +Akiko's throughput is approximately the same as optimised software C2P on the 68020 because both are limited by the Chip RAM bus bandwidth (~3.5 MB/s shared). On faster CPUs (68040/060), software C2P **outperforms** Akiko because the CPU can process data faster than the register interface can shuttle it. + +Full Akiko protocol: [Akiko — CD32 C2P Hardware](../01_hardware/aga_a1200_a4000/akiko_cd32.md#chunky-to-planar-c2p-conversion) + +--- + +## Solution 4 — Blitter-Assisted C2P + +The Blitter can be used as part of a C2P pipeline, but it cannot perform the transposition itself. Typical usage: + +1. CPU performs the merge/butterfly in registers → outputs planar longwords to a temporary buffer in Chip RAM +2. Blitter copies the planar data from the temporary buffer to the screen's bitplanes with correct modulo + +This approach **overlaps** CPU computation with Blitter DMA — while the Blitter writes frame N's planes to the screen, the CPU computes frame N+1's transposition. + +``` +Time ──────────────────────────────────────────────────────→ +CPU: [merge frame 0] [merge frame 1] [merge frame 2] ... +Blitter: [write frame 0] [write frame 1] ... + ↑ overlap: CPU and Blitter run in parallel +``` + +> [!WARNING] +> On 68040/060 systems, the Blitter is often **slower** than letting the CPU do both the merge and the writes via `MOVE16` (68040) or unrolled `MOVEM.L`. The Blitter's 16-bit bus (even in AGA FMODE×4) adds DMA contention that may actually slow down the CPU's merge passes. + +--- + +## Solution 5 — WriteChunkyPixels (AmigaOS) + +AmigaOS 3.0+ provides `WriteChunkyPixels()` in `graphics.library`, which performs C2P conversion internally using the best available method: + +```c +#include + +WriteChunkyPixels(rp, + xstart, ystart, xstop, ystop, + chunky_buffer, chunky_bytes_per_row); +``` + +On CD32, this function auto-detects Akiko and uses it. On other AGA machines, it uses an internal software C2P. However, the OS implementation is **not** as fast as the best demoscene routines — it prioritises correctness and generality over raw speed. + +--- + +## Solution 6 — RTG: Eliminating C2P Entirely + +The ultimate solution to C2P is to **not do it at all**. Retargetable Graphics (RTG) cards like the Picasso IV, CyberVision 64, and MiSTer's virtual `uaegfx` provide a chunky framebuffer directly. The rendering engine writes chunky pixels to VRAM, and the card's RAMDAC/scaler converts them to video output. + +The irony: RTG cards must perform the **reverse** conversion (P2C — planar-to-chunky) when legacy planar software runs on an RTG screen. The CyberVision 64 included a dedicated **Roxxler** chip for this. Without hardware help, P2C on software is equally expensive. + +See: [RTG — Retargetable Graphics](../16_driver_development/rtg_driver.md#planar-to-chunky-conversion-c2p) + +--- + +## Choosing the Right Approach + +| Platform | Recommended C2P | Why | +|---|---|---| +| A500/A2000 (68000) | Merge algorithm (simplified, fewer planes) | No fast multiply; 68000 can manage 4–5 plane C2P at ~15 FPS | +| A1200 (68020) | Kalms merge, 5-pass | Sweet spot: enough registers, usable I-cache | +| CD32 (68020 + Akiko) | Akiko hardware | Frees ~50% CPU for game logic | +| A4000 (68030/040) | CPU merge (skip Akiko if not CD32) | 68040 `MOVE16` makes CPU writes fast enough | +| 68060 accelerated | CPU merge, no Blitter | 68060 superscalar outperforms everything else | +| MiSTer FPGA | RTG (`uaegfx`) | Chunky framebuffer in DDR — no C2P needed | + +--- + +## The Bigger Picture — Data Layout Transformation + +C2P is not unique to the Amiga. It is an instance of a fundamental problem in computer architecture: **transforming data layout between Structure-of-Arrays (SoA) and Array-of-Structures (AoS)**. + +### SoA vs AoS — The Universal Duality + +``` +AoS (Array of Structures) = Chunky: + struct Pixel { r, g, b, a; }; + Pixel pixels[1024]; + // Memory: r0 g0 b0 a0 r1 g1 b1 a1 r2 g2 b2 a2 ... + // Each element's fields are contiguous + +SoA (Structure of Arrays) = Planar: + struct Pixels { + float r[1024]; + float g[1024]; + float b[1024]; + float a[1024]; + }; + // Memory: r0 r1 r2 ... r1023 g0 g1 g2 ... g1023 ... + // Each field is contiguous across all elements +``` + +The Amiga's planar format is **SoA**: each bitplane is an array of one field (one bit) across all pixels. The chunky format is **AoS**: each pixel's fields (all 8 bits) are packed together. + +### Where This Problem Appears Today + +| Domain | SoA (Planar-Like) | AoS (Chunky-Like) | Conversion | +|---|---|---|---| +| **Amiga graphics** | Bitplanes (Agnus DMA) | Chunky pixel buffer (CPU render) | C2P algorithm | +| **GPU compute shaders** | SoA buffer layouts (SSBO) | Vertex attributes (interleaved VBO) | Shader transpose | +| **SIMD / AVX-512** | Separate float arrays (vectorisable) | Struct arrays (gather/scatter) | `_mm512_transpose` intrinsics | +| **Database engines** | Columnar storage (Parquet, Arrow) | Row-oriented storage (MySQL) | Column↔row materialisation | +| **Image compression** | Colour planes (JPEG YCbCr) | RGB pixels (BMP) | MCU block decomposition | +| **GPU texture memory** | Block-compressed (BC/ASTC) | Linear RGBA | Hardware texture unit decode | +| **Neural network inference** | NCHW tensor layout (channels first) | NHWC (channels last) | Layout transposition kernel | + +### Why Each System Prefers a Different Layout + +| Layout | Optimal For | Reason | +|---|---|---| +| **SoA / Planar** | Streaming one field across many elements | Maximises cache line utilisation, enables SIMD vectorisation | +| **AoS / Chunky** | Random-access to complete elements | All fields of one element in one cache line | + +The Amiga's custom DMA engine streams bitplane data to the display sequentially — plane 0 for the whole line, then plane 1, etc. This is a **SoA access pattern**, perfectly matched by the planar layout. The CPU, which wants to set a single pixel's complete colour, has the opposite need — it wants **AoS**. + +### Modern Hardware Parallels + +| Amiga Component | Modern Equivalent | Function | +|---|---|---| +| **Akiko C2P register** | GPU texture swizzle unit | Hardware layout transposition | +| **Blitter + merge algorithm** | CUDA shared memory transpose kernel | CPU/coprocessor-assisted transpose | +| **RTG (planar bypass)** | Unified chunky framebuffer (since VGA) | Eliminates the problem entirely | +| **Copper palette cycling** | GPU palette shader / LUT texture | Colour manipulation without pixel writes | +| **FMODE (fetch width)** | GPU memory bus width (256/384/512-bit) | Wider bus = more data per DMA cycle | + +### GPU Texture Swizzle — The Modern Akiko + +Modern GPUs store textures in **swizzled** (Morton/Z-order) layouts rather than linear row-major order. This is architecturally identical to what the Amiga does with planar bitmaps: the hardware's memory access pattern doesn't match the CPU's logical layout, so a dedicated hardware unit transparently converts between them. + +``` +Linear (CPU view): Morton/Z-order (GPU internal): + 0 1 2 3 0 1 4 5 + 4 5 6 7 → 2 3 6 7 + 8 9 10 11 8 9 12 13 + 12 13 14 15 10 11 14 15 +``` + +When you call `glTexImage2D()` or `vkCmdCopyBufferToImage()`, the GPU driver performs a layout conversion from linear (CPU-friendly) to swizzled (GPU-cache-friendly). This is the exact same class of operation as Amiga C2P — a hardware-accelerated data layout transformation that is invisible to the application programmer. + +--- + +## Performance Comparison Across Eras + +| System | Data Layout Problem | Throughput | Method | +|---|---|---|---| +| A500 (1987, 7 MHz 68000) | C2P 320×256×4bpp | ~2 MB/s | CPU merge, 4 planes | +| A1200 (1992, 14 MHz 68020) | C2P 320×256×8bpp | ~1.5 MB/s | CPU merge, 8 planes | +| CD32 (1993, 14 MHz + Akiko) | C2P 320×256×8bpp | ~1.5 MB/s | Akiko hardware | +| 486 DX2/66 (1992) | No conversion needed | N/A | VGA Mode 13h = chunky | +| Pentium MMX (1997) | Colour space (YUV→RGB) | ~200 MB/s | MMX SIMD | +| GTX 1080 (2016) | Texture swizzle (linear→tiled) | ~300 GB/s | Hardware TMU | +| Apple M2 (2022) | SoA↔AoS for ML tensors | ~100 GB/s | Hardware AMX | + +The throughput gap tells the story: what consumed 100% of a 68020's capability is handled by a dedicated hardware unit at 200,000× the bandwidth on modern silicon. But the fundamental problem — **data layout mismatch between producer and consumer** — is identical. + +--- + +## Historical Timeline + +| Year | Event | +|---|---| +| 1985 | Amiga launches with planar display. C2P not needed — all software renders directly to bitplanes | +| 1989 | First 3D demos appear (Juggler, etc.). Rendering in chunky buffers starts | +| 1991 | Demoscene coders develop first optimised C2P routines for 68000 | +| 1992 | AGA ships (A1200/A4000). 8 bitplanes = C2P problem gets 2× harder | +| 1993 | CD32 ships with Akiko — first hardware C2P. Mikael Kalms publishes optimised CPU routines | +| 1994 | Kalms C2P library becomes the de facto standard. Multiple variants for 020/030/040/060 | +| 1995 | RTG cards (Picasso II, CyberVision 64) begin to make C2P irrelevant for productivity | +| 1996 | CyberVision 64 ships with Roxxler P2C chip — the reverse problem, solved in hardware | +| 1998 | 68060 accelerators make CPU C2P faster than any hardware solution | +| 2020+ | MiSTer FPGA core implements RTG via `uaegfx` — C2P eliminated for modern setups | + +--- + +## Implementing C2P — Practical Checklist + +For developers writing Amiga software that renders in chunky format: + +1. **Allocate the chunky buffer in Fast RAM** (`MEMF_FAST`) — the CPU reads it during conversion, and Fast RAM has no DMA contention +2. **Allocate the planar screen in Chip RAM** (`MEMF_CHIP | MEMF_DISPLAYABLE`) — this is mandatory for display DMA +3. **Use a proven C2P library** — Kalms C2P (`kalms-c2p` on GitHub/Aminet) is the gold standard +4. **Match the routine to your CPU** — different unrolling for 68020 vs 68040 vs 68060 +5. **Use triple buffering** if possible — render to buffer A, C2P buffer B into Chip RAM, display buffer C +6. **On CD32, detect and use Akiko** — `WriteChunkyPixels()` does this automatically +7. **On RTG systems, skip C2P entirely** — render chunky directly to the RTG card's VRAM +8. **Profile with CIA timers** — the bottleneck shifts between CPU merge and Chip RAM write speed depending on configuration + +### Adaptive Detection + +```c +#include +#include + +extern struct GfxBase *GfxBase; + +/* Determine best C2P strategy for current hardware */ +enum C2P_Strategy determine_c2p_strategy(struct BitMap *screen_bm) +{ + /* Check for RTG screen first — no C2P needed */ + if (GetCyberMapAttr(screen_bm, CYBRMATTR_ISRTG)) + return C2P_NONE_RTG; + + /* Check for Akiko (CD32) */ + if (GfxBase->ChunkyToPlanarPtr != NULL) + return C2P_AKIKO; + + /* Check CPU type for best software routine */ + UWORD attn = SysBase->AttnFlags; + if (attn & AFF_68060) return C2P_KALMS_060; + if (attn & AFF_68040) return C2P_KALMS_040; + if (attn & AFF_68020) return C2P_KALMS_020; + + return C2P_KALMS_000; /* 68000 fallback */ +} +``` + +--- + +## References + +- Mikael Kalms — [kalms-c2p](https://github.com/Kalmalyzer/kalms-c2p) — the definitive C2P library (GitHub) +- Scout/Azure — "Chunky 2 Planar Tutorial" — the seminal demoscene document explaining the transposition theory +- *Amiga Hardware Reference Manual* — bitplane DMA, display pipeline +- NDK39: `graphics/gfx.h` — `WriteChunkyPixels()` prototype +- Intel — [Structure of Arrays vs Array of Structures](https://www.intel.com/content/www/us/en/developer/articles/technical/memory-layout-transformations.html) — modern SoA/AoS guide +- NVIDIA — CUDA Programming Guide, "Shared Memory Matrix Transpose" — GPU equivalent of C2P + +## See Also + +- [Akiko — CD32 C2P Hardware](../01_hardware/aga_a1200_a4000/akiko_cd32.md) — Akiko register protocol +- [BitMap — Planar Layout](bitmap.md) — how Amiga bitmaps are structured in memory +- [Blitter Programming](blitter_programming.md) — Blitter DMA used in Blitter-assisted C2P +- [RTG — Retargetable Graphics](../16_driver_development/rtg_driver.md) — chunky framebuffer cards that eliminate C2P +- [Memory Types](../01_hardware/common/memory_types.md) — Chip vs Fast RAM (critical for C2P buffer placement) diff --git a/10_devices/scsi.md b/10_devices/scsi.md index 1e677c0..a64d5d6 100644 --- a/10_devices/scsi.md +++ b/10_devices/scsi.md @@ -22,7 +22,7 @@ SCSI and IDE hard disks on the Amiga are accessed through `scsi.device` or compa | A4000 | IDE (40-pin) | **A4000 IDE** | `scsi.device` | ~2 MB/s (PIO) | | A4000T | SCSI (50-pin) + IDE | **NCR 53C710** + IDE | `2nd.scsi.device` / `scsi.device` | ~10 MB/s (SCSI DMA) | | CD32 | IDE (internal CD) | **Akiko** | `scsi.device` | ~1.5 MB/s | -| CDTV | SCSI (internal CD) | Custom | `scsi.device` | Slow | +| CDTV | SCSI (internal CD) | **DMAC + WD33C93** | `scsi.device` | ~150 KB/s (1× CD) | ### Why Native Bandwidth Is Limited @@ -281,3 +281,7 @@ DoIO((struct IORequest *)diskReq); - ADCD 2.1: scsi.device autodocs - SCSI-2 standard: ANSI X3.131-1994 - See also: [trackdisk.md](trackdisk.md) — floppy I/O (shares the same API model) +- See also: [CDTV Hardware](../01_hardware/ocs_a500/cdtv_hardware.md) — DMAC/WD33C93 SCSI CD-ROM controller +- See also: [Akiko — CD32](../01_hardware/aga_a1200_a4000/akiko_cd32.md) — CD32 CD-ROM controller (Akiko PIO, not SCSI) +- See also: [Gayle IDE & PCMCIA](../01_hardware/common/gayle_ide_pcmcia.md) — A600/A1200 IDE controller +- See also: [Gary — A3000](../01_hardware/ecs_a600_a3000/gary_system_controller.md) — A3000 SDMAC/WD33C93 SCSI integration diff --git a/README.md b/README.md index fcf0423..882fe11 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The Amiga's documentation was scattered across out-of-print manuals, Usenet post | Layer | Coverage | |---|---| -| **⚙️ Hardware** | Custom chip registers (OCS/ECS/AGA), Copper & Blitter programming with worked examples, memory architecture (Chip/Fast/Slow RAM), CIA, Zorro bus, CPU feature matrix | +| **⚙️ Hardware** | Custom chip registers (OCS/ECS/AGA), Copper & Blitter programming, memory architecture (Chip/Fast/Slow RAM), CIA, Zorro bus, CPU feature matrix, **per-model hardware (A1000 WCS, A2000 Zorro II, CDTV DMAC/CD-ROM, CD32 Akiko C2P)** | | **🔌 Boot & Init** | Cold boot sequence, ROM checksum, resident module scan, Kickstart init, startup-sequence | | **📦 Binary Format** | HUNK executable format (every record type), relocation, debug info, overlays | | **🔗 Linking & ABI** | .fd files, LVO tables, register calling conventions, compiler stubs, SetFunction | @@ -74,10 +74,10 @@ The Amiga's documentation was scattered across out-of-print manuals, Usenet post ### 01 — Hardware (by chipset generation) | Folder | Coverage | |---|---| -| [common/](01_hardware/common/) | M68k CPU, address space, **memory types (Chip/Fast/Slow RAM)**, CIA chips, Zorro bus | -| [ocs_a500/](01_hardware/ocs_a500/) | OCS chipset: custom registers, copper, blitter, sprites, Paula | -| [ecs_a600_a3000/](01_hardware/ecs_a600_a3000/) | ECS chipset: Super Agnus, productivity modes, Gary, Gayle | -| [aga_a1200_a4000/](01_hardware/aga_a1200_a4000/) | AGA chipset: Alice, Lisa, copper, blitter (64-bit), palette, Gayle IDE | +| [common/](01_hardware/common/) | M68k CPU, address space, **memory types (Chip/Fast/Slow RAM)**, CIA chips, Zorro bus, **Gayle IDE/PCMCIA** | +| [ocs_a500/](01_hardware/ocs_a500/) | OCS chipset: custom registers, copper, blitter, sprites, Paula, **A1000 WCS**, **A2000 Zorro II**, **CDTV hardware** | +| [ecs_a600_a3000/](01_hardware/ecs_a600_a3000/) | ECS chipset: Super Agnus, productivity modes, **Gary** system controller | +| [aga_a1200_a4000/](01_hardware/aga_a1200_a4000/) | AGA chipset: Alice, Lisa, copper, blitter (64-bit), palette, **CD32 Akiko**, **A4000T SCSI** | ### 02 — Boot Sequence | File | Topic |