docs(amiga): complete AmigaOS 3.1/3.2 developer reference — 172 files across 17 sections

Comprehensive technical documentation covering:
- Hardware: OCS/ECS/AGA custom chip registers, Copper & Blitter deep dives
- Boot sequence: cold boot through startup-sequence
- Binary format: HUNK executable spec, relocation, debug info
- Linking & ABI: .fd files, LVO tables, register calling conventions
- Exec kernel: tasks, interrupts, memory, signals, semaphores
- AmigaDOS: file I/O, FFS/OFS layout, CLI/Shell scripting
- Graphics: planar bitmaps, Copper programming, HAM/EHB modes
- Intuition: screens, windows, IDCMP, BOOPSI
- Devices: trackdisk, SCSI, serial, timer, audio, keyboard
- Libraries: utility, expansion, IFFParse, locale, ARexx
- Networking: bsdsocket API, SANA-II, TCP/IP stack comparison
- Toolchain: GCC, vasm/vlink, SAS/C, NDK, debugging
- Reverse engineering: IDA/Ghidra setup, compiler fingerprints, case studies
- CPU & MMU: 68040/060 emulation libs, PMMU, cache management
- Driver development: SANA-II, Picasso96/RTG, AHI audio

All files include breadcrumb navigation. No local paths or proprietary content.
This commit is contained in:
Ilia Sharin 2026-04-23 12:16:52 -04:00
parent f07a368bf1
commit 21751c0025
172 changed files with 19701 additions and 0 deletions

18
10_devices/README.md Normal file
View file

@ -0,0 +1,18 @@
[← Home](../README.md)
# Devices — Overview
## Section Index
| File | Description |
|---|---|
| [trackdisk.md](trackdisk.md) | trackdisk.device — floppy I/O |
| [scsi.md](scsi.md) | scsi.device / 2nd.scsi.device — hard disk I/O |
| [serial.md](serial.md) | serial.device — RS-232 |
| [parallel.md](parallel.md) | parallel.device — Centronics |
| [timer.md](timer.md) | timer.device — timing and delays |
| [audio.md](audio.md) | audio.device — DMA audio channels |
| [keyboard.md](keyboard.md) | keyboard.device — keyboard events |
| [gameport.md](gameport.md) | gameport.device — joystick/mouse |
| [input.md](input.md) | input.device — event merging |
| [console.md](console.md) | console.device — text terminal I/O |

72
10_devices/audio.md Normal file
View file

@ -0,0 +1,72 @@
[← Home](../README.md) · [Devices](README.md)
# audio.device — DMA Audio Channels
## Overview
`audio.device` provides access to the Amiga's 4 DMA audio channels. Each channel plays 8-bit PCM samples from Chip RAM at programmable rates.
---
## Channel Allocation
```c
UBYTE allocationMap[] = { 1, 2, 4, 8 }; /* channel masks */
struct IOAudio *aio = (struct IOAudio *)
CreateIORequest(port, sizeof(struct IOAudio));
aio->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
aio->ioa_Data = allocationMap;
aio->ioa_Length = sizeof(allocationMap);
OpenDevice("audio.device", 0, (struct IORequest *)aio, 0);
/* aio->ioa_AllocKey = allocation key for this channel */
```
---
## Playing a Sample
```c
aio->ioa_Request.io_Command = CMD_WRITE;
aio->ioa_Request.io_Flags = ADIOF_PERVOL;
aio->ioa_Data = sampleData; /* MUST be in Chip RAM */
aio->ioa_Length = sampleLength; /* in bytes */
aio->ioa_Period = 428; /* ~8287 Hz (PAL) */
aio->ioa_Volume = 64; /* 064 */
aio->ioa_Cycles = 1; /* 0 = loop forever */
BeginIO((struct IORequest *)aio);
```
### Period Calculation
```
Period = clock_constant / desired_frequency
PAL: clock = 3546895 Hz → Period = 3546895 / freq
NTSC: clock = 3579545 Hz → Period = 3579545 / freq
```
| Frequency | Period (PAL) |
|---|---|
| 8287 Hz | 428 |
| 11025 Hz | 322 |
| 22050 Hz | 161 |
| 28867 Hz | 124 (minimum safe) |
---
## Channel Registers
| Channel | Address | Description |
|---|---|---|
| 0 | `$DFF0A0` | AUD0 (left) |
| 1 | `$DFF0B0` | AUD1 (right) |
| 2 | `$DFF0C0` | AUD2 (right) |
| 3 | `$DFF0D0` | AUD3 (left) |
Each channel: pointer (PTH/PTL), length (LEN), period (PER), volume (VOL).
---
## References
- NDK39: `devices/audio.h`
- HRM: audio DMA chapter

47
10_devices/console.md Normal file
View file

@ -0,0 +1,47 @@
[← Home](../README.md) · [Devices](README.md)
# console.device — Text Terminal I/O
## Overview
`console.device` provides ANSI-compatible text rendering into Intuition windows. It translates raw keycodes to ASCII and supports a rich set of escape sequences for cursor positioning, colour, and text formatting.
---
## Opening
```c
struct IOStdReq *con = CreateStdIO(port);
con->io_Data = (APTR)win; /* the Intuition Window */
con->io_Length = sizeof(struct Window);
OpenDevice("console.device", 0, (struct IORequest *)con, 0);
```
---
## Common Escape Sequences
| Sequence | Description |
|---|---|
| `\033[H` | Home cursor |
| `\033[nA` | Cursor up n lines |
| `\033[nB` | Cursor down n lines |
| `\033[nC` | Cursor right n columns |
| `\033[nD` | Cursor left n columns |
| `\033[y;xH` | Move to row y, column x |
| `\033[J` | Clear to end of screen |
| `\033[K` | Clear to end of line |
| `\033[nm` | Set graphics rendition (colour/style) |
| `\033[0m` | Reset attributes |
| `\033[1m` | Bold |
| `\033[3m` | Italic |
| `\033[4m` | Underline |
| `\033[3037m` | Foreground colour |
| `\033[4047m` | Background colour |
---
## References
- NDK39: `devices/conunit.h`
- ADCD 2.1: console.device autodocs

64
10_devices/gameport.md Normal file
View file

@ -0,0 +1,64 @@
[← Home](../README.md) · [Devices](README.md)
# gameport.device — Joystick and Mouse
## Overview
`gameport.device` reads joystick and mouse ports (active on port 1 for joystick, port 0 for mouse). Uses CIA and custom chip registers.
---
## Controller Types
```c
/* devices/gameport.h */
#define GPCT_ALLOCATED -1 /* port is allocated */
#define GPCT_NOCONTROLLER 0 /* nothing connected */
#define GPCT_MOUSE 1 /* mouse */
#define GPCT_RELJOYSTICK 2 /* relative joystick (proportional) */
#define GPCT_ABSJOYSTICK 3 /* absolute joystick */
```
---
## Reading a Joystick
```c
struct IOStdReq *gp = CreateStdIO(port);
OpenDevice("gameport.device", 1, (struct IORequest *)gp, 0);
/* Set controller type: */
UBYTE type = GPCT_ABSJOYSTICK;
gp->io_Command = GPD_SETCTYPE;
gp->io_Data = &type;
gp->io_Length = 1;
DoIO((struct IORequest *)gp);
/* Set trigger conditions: */
struct GamePortTrigger trigger = {
GPTF_UPKEYS | GPTF_DOWNKEYS, /* report buttons */
10000, /* X delta timeout */
10000, /* Y delta timeout */
1, 1 /* X/Y delta threshold */
};
gp->io_Command = GPD_SETTRIGGER;
gp->io_Data = &trigger;
gp->io_Length = sizeof(trigger);
DoIO((struct IORequest *)gp);
/* Read events: */
struct InputEvent ie;
gp->io_Command = GPD_READEVENT;
gp->io_Data = &ie;
gp->io_Length = sizeof(ie);
DoIO((struct IORequest *)gp);
/* ie.ie_Code, ie.ie_position.ie_xy give button/direction */
CloseDevice((struct IORequest *)gp);
```
---
## References
- NDK39: `devices/gameport.h`

41
10_devices/input.md Normal file
View file

@ -0,0 +1,41 @@
[← Home](../README.md) · [Devices](README.md)
# input.device — Event Stream Merging
## Overview
`input.device` merges events from keyboard, mouse, gameport, and timer into a single input stream that feeds Intuition. Input handlers can be installed at various priorities to filter, modify, or consume events.
---
## Handler Priority Levels
| Priority | Consumer |
|---|---|
| 100 | System reserved |
| 51+ | Custom high-priority handlers |
| 50 | Intuition |
| 20 | Console.device |
| 0 | Default |
---
## Commands
| Code | Constant | Description |
|---|---|---|
| 9 | `IND_ADDHANDLER` | Add input handler |
| 10 | `IND_REMHANDLER` | Remove input handler |
| 11 | `IND_WRITEEVENT` | Inject an InputEvent into the stream |
| 12 | `IND_SETTHRESH` | Set double-click threshold |
| 13 | `IND_SETPERIOD` | Set key repeat period |
| 14 | `IND_SETMPORT` | Set mouse port type |
| 15 | `IND_SETMTRIG` | Set mouse trigger |
| 16 | `IND_SETMTYPE` | Set mouse type |
---
## References
- NDK39: `devices/input.h`
- `09_intuition/input_events.md` — handler installation example

48
10_devices/keyboard.md Normal file
View file

@ -0,0 +1,48 @@
[← Home](../README.md) · [Devices](README.md)
# keyboard.device — Keyboard Input
## Overview
`keyboard.device` provides raw keycode events from the keyboard controller (8520 CIA-A). Normally used indirectly via `input.device`, but can be accessed directly for keymap-independent scanning.
---
## Keycodes
Amiga keycodes are 7-bit values (0127). Bit 7 indicates key-up:
| Code | Key | Code | Key |
|---|---|---|---|
| `$00` | \` (backtick) | `$40` | Space |
| `$01``$0A` | 10 | `$41` | Backspace |
| `$10``$19` | QP | `$42` | Tab |
| `$20``$28` | AL | `$43` | Enter (keypad) |
| `$31``$39` | Z/ | `$44` | Return |
| `$45` | Escape | `$46` | Delete |
| `$4C` | Cursor Up | `$4D` | Cursor Down |
| `$4E` | Cursor Right | `$4F` | Cursor Left |
| `$50``$59` | F1F10 | `$5F` | Help |
| `$60` | Left Shift | `$61` | Right Shift |
| `$62` | Caps Lock | `$63` | Control |
| `$64` | Left Alt | `$65` | Right Alt |
| `$66` | Left Amiga | `$67` | Right Amiga |
---
## Commands
| Code | Constant | Description |
|---|---|---|
| 2 | `CMD_READ` | Read raw keycodes |
| 5 | `CMD_CLEAR` | Clear keyboard buffer |
| 9 | `KBD_READMATRIX` | Read full key matrix state |
| 10 | `KBD_ADDRESETHANDLER` | Add Ctrl-Amiga-Amiga handler |
| 11 | `KBD_REMRESETHANDLER` | Remove reset handler |
| 12 | `KBD_RESETHANDLERDONE` | Acknowledge reset handler completion |
---
## References
- NDK39: `devices/keyboard.h`

36
10_devices/parallel.md Normal file
View file

@ -0,0 +1,36 @@
[← Home](../README.md) · [Devices](README.md)
# parallel.device — Centronics Parallel Port
## Overview
`parallel.device` provides I/O for the Amiga's Centronics-compatible parallel port, used primarily for printers.
---
## Opening
```c
struct IOExtPar *par = (struct IOExtPar *)
CreateIORequest(port, sizeof(struct IOExtPar));
OpenDevice("parallel.device", 0, (struct IORequest *)par, 0);
```
---
## Commands
| Code | Constant | Description |
|---|---|---|
| 2 | `CMD_READ` | Read bytes (if bidirectional) |
| 3 | `CMD_WRITE` | Write bytes |
| 5 | `CMD_CLEAR` | Clear buffers |
| 8 | `CMD_FLUSH` | Abort pending |
| 9 | `PDCMD_QUERY` | Get status |
| 10 | `PDCMD_SETPARAMS` | Set parameters |
---
## References
- NDK39: `devices/parallel.h`

66
10_devices/scsi.md Normal file
View file

@ -0,0 +1,66 @@
[← Home](../README.md) · [Devices](README.md)
# scsi.device — Hard Disk I/O
## Overview
SCSI and IDE hard disks are accessed via `scsi.device` (A3000/A4000 built-in) or `2nd.scsi.device` / `ide.device` (A1200/A600). The API is the same as trackdisk for basic read/write, with additional SCSI direct commands.
---
## Opening
```c
struct IOStdReq *scsi = CreateStdIO(port);
OpenDevice("scsi.device", 0, (struct IORequest *)scsi, 0);
/* unit 0 = first SCSI/IDE device */
```
---
## Standard Commands
Same as trackdisk: `CMD_READ`, `CMD_WRITE`, `CMD_UPDATE`, `TD_CHANGENUM`, etc.
---
## Direct SCSI Commands (HD_SCSICMD)
```c
struct SCSICmd scsicmd;
UBYTE cdb[10]; /* SCSI CDB */
UBYTE sense[20]; /* sense data buffer */
UBYTE data[512]; /* data buffer */
/* Read 1 sector at LBA 0: */
cdb[0] = 0x28; /* READ(10) */
cdb[1] = 0;
cdb[2] = 0; cdb[3] = 0; cdb[4] = 0; cdb[5] = 0; /* LBA = 0 */
cdb[6] = 0;
cdb[7] = 0; cdb[8] = 1; /* transfer length = 1 sector */
cdb[9] = 0;
scsicmd.scsi_Data = (UWORD *)data;
scsicmd.scsi_Length = 512;
scsicmd.scsi_Command = cdb;
scsicmd.scsi_CmdLength = 10;
scsicmd.scsi_Flags = SCSIF_READ;
scsicmd.scsi_SenseData = sense;
scsicmd.scsi_SenseLength = sizeof(sense);
scsi->io_Command = HD_SCSICMD;
scsi->io_Data = &scsicmd;
scsi->io_Length = sizeof(scsicmd);
DoIO((struct IORequest *)scsi);
if (scsicmd.scsi_Status != 0) {
/* SCSI error — check sense data */
}
```
---
## References
- NDK39: `devices/scsidisk.h`
- ADCD 2.1: scsi.device autodocs

54
10_devices/serial.md Normal file
View file

@ -0,0 +1,54 @@
[← Home](../README.md) · [Devices](README.md)
# serial.device — RS-232 Communication
## Overview
`serial.device` provides buffered RS-232 serial I/O through the Amiga's built-in 8520 CIA UART (active-high active sense).
---
## Opening
```c
struct IOExtSer *ser = (struct IOExtSer *)
CreateIORequest(port, sizeof(struct IOExtSer));
OpenDevice("serial.device", 0, (struct IORequest *)ser, 0);
```
---
## Setting Parameters
```c
ser->io_CtlChar = SER_DEFAULT_CTLCHAR;
ser->io_RBufLen = 4096; /* read buffer size */
ser->io_Baud = 9600;
ser->io_ReadLen = 8; /* data bits */
ser->io_WriteLen = 8;
ser->io_StopBits = 1;
ser->io_SerFlags = SERF_XDISABLED; /* no XON/XOFF */
ser->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO((struct IORequest *)ser);
```
---
## Commands
| Code | Constant | Description |
|---|---|---|
| 2 | `CMD_READ` | Read bytes |
| 3 | `CMD_WRITE` | Write bytes |
| 5 | `CMD_CLEAR` | Clear buffers |
| 8 | `CMD_FLUSH` | Abort pending requests |
| 9 | `SDCMD_QUERY` | Get status (bytes in buffer, errors) |
| 10 | `SDCMD_BREAK` | Send break signal |
| 11 | `SDCMD_SETPARAMS` | Set baud/bits/parity/stop |
---
## References
- NDK39: `devices/serial.h`
- ADCD 2.1: serial.device autodocs

79
10_devices/timer.md Normal file
View file

@ -0,0 +1,79 @@
[← Home](../README.md) · [Devices](README.md)
# timer.device — Timing and Delays
## Overview
`timer.device` provides precise timing services: delays, time-of-day, and high-resolution timestamps. It has two units:
| Unit | Constant | Resolution | Use |
|---|---|---|---|
| 0 | `UNIT_MICROHZ` | ~2µs (E-clock) | Short, precise delays |
| 1 | `UNIT_VBLANK` | ~20ms (VBlank) | Long delays, lower overhead |
| 2 | `UNIT_ECLOCK` | CIA E-clock ticks | Highest resolution timing (OS 2.0+) |
| 3 | `UNIT_WAITUNTIL` | absolute time | Wait until specific time (OS 2.0+) |
| 4 | `UNIT_WAITECLOCK` | E-clock absolute | (OS 2.0+) |
---
## struct timeval / timerequest
```c
/* devices/timer.h — NDK39 */
struct timeval {
ULONG tv_secs; /* seconds */
ULONG tv_micro; /* microseconds */
};
struct timerequest {
struct IORequest tr_node;
struct timeval tr_time;
};
```
---
## Simple Delay
```c
struct timerequest *tr = (struct timerequest *)
CreateIORequest(port, sizeof(struct timerequest));
OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)tr, 0);
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time.tv_secs = 2;
tr->tr_time.tv_micro = 0;
DoIO((struct IORequest *)tr); /* blocks for 2 seconds */
CloseDevice((struct IORequest *)tr);
DeleteIORequest((struct IORequest *)tr);
```
---
## Getting Current Time
```c
tr->tr_node.io_Command = TR_GETSYSTIME;
DoIO((struct IORequest *)tr);
Printf("Time: %lu.%06lu\n", tr->tr_time.tv_secs, tr->tr_time.tv_micro);
```
---
## High-Resolution Timing
```c
/* Read E-clock (OS 2.0+): */
struct EClockVal eclock;
ULONG freq = ReadEClock(&eclock); /* returns ticks/second */
/* eclock.ev_hi, eclock.ev_lo = 64-bit tick count */
/* Typical freq: 709379 Hz (PAL) or 715909 Hz (NTSC) */
```
---
## References
- NDK39: `devices/timer.h`
- ADCD 2.1: timer.device autodocs

74
10_devices/trackdisk.md Normal file
View file

@ -0,0 +1,74 @@
[← Home](../README.md) · [Devices](README.md)
# trackdisk.device — Floppy Disk I/O
## Overview
`trackdisk.device` provides raw sector I/O for Amiga floppy drives. Each drive is a unit (03). The device operates on 512-byte sectors, 11 sectors per track (880 KB DD disks) or 22 per track (1760 KB HD).
---
## Opening
```c
struct IOExtTD *tdreq = (struct IOExtTD *)
CreateIORequest(port, sizeof(struct IOExtTD));
OpenDevice("trackdisk.device", 0, (struct IORequest *)tdreq, 0);
```
---
## Commands
| Code | Constant | Description |
|---|---|---|
| 2 | `CMD_READ` | Read sectors |
| 3 | `CMD_WRITE` | Write sectors |
| 4 | `CMD_UPDATE` | Flush write buffer to disk |
| 9 | `TD_MOTOR` | Turn motor on/off |
| 10 | `TD_FORMAT` | Low-level format track |
| 11 | `TD_SEEK` | Move head to track |
| 12 | `TD_REMOVE` | Notify on disk change |
| 13 | `TD_CHANGENUM` | Get disk change count |
| 14 | `TD_CHANGESTATE` | Check if disk present |
| 15 | `TD_PROTSTATUS` | Check write-protect |
| 16 | `TD_RAWREAD` | Read raw MFM data |
| 17 | `TD_RAWWRITE` | Write raw MFM data |
| 18 | `TD_GETDRIVETYPE` | Get drive type |
| 19 | `TD_GETNUMTRACKS` | Get total tracks |
| 20 | `TD_ADDCHANGEINT` | Add disk change interrupt |
| 21 | `TD_REMCHANGEINT` | Remove disk change interrupt |
---
## Reading a Sector
```c
UBYTE buf[512];
tdreq->iotd_Req.io_Command = CMD_READ;
tdreq->iotd_Req.io_Data = buf;
tdreq->iotd_Req.io_Length = 512;
tdreq->iotd_Req.io_Offset = 0; /* byte offset = sector * 512 */
DoIO((struct IORequest *)tdreq);
```
---
## Disk Geometry
| Parameter | DD (880 KB) | HD (1760 KB) |
|---|---|---|
| Heads | 2 | 2 |
| Cylinders | 80 | 80 |
| Sectors/track | 11 | 22 |
| Bytes/sector | 512 | 512 |
| Total sectors | 1760 | 3520 |
Byte offset = `(cylinder * 2 + head) * sectors_per_track * 512 + sector * 512`
---
## References
- NDK39: `devices/trackdisk.h`
- ADCD 2.1: trackdisk.device autodocs