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
07_dos/README.md Normal file
View file

@ -0,0 +1,18 @@
[← Home](../README.md)
# dos.library — AmigaDOS Overview
## Section Index
| File | Description |
|---|---|
| [dos_base.md](dos_base.md) | DosLibrary structure and global state |
| [file_io.md](file_io.md) | Open, Close, Read, Write, Seek |
| [locks_examine.md](locks_examine.md) | Lock, UnLock, Examine, ExNext, ExAll |
| [pattern_matching.md](pattern_matching.md) | ParsePattern, MatchPattern, wildcards |
| [process_management.md](process_management.md) | CreateNewProc, SystemTagList, Execute |
| [packet_system.md](packet_system.md) | DosPacket, ACTION_* codes, handler protocol |
| [filesystem.md](filesystem.md) | FFS/OFS layout, block structure |
| [environment.md](environment.md) | GetVar/SetVar, local/global env variables |
| [error_handling.md](error_handling.md) | IoErr, Fault, PrintFault, error codes |
| [cli_shell.md](cli_shell.md) | CLI/Shell: pipes, redirection, scripts, ReadArgs |

176
07_dos/cli_shell.md Normal file
View file

@ -0,0 +1,176 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# CLI and Shell — Command Interpreter
## Overview
The AmigaDOS **Shell** (called CLI in OS 1.x) is the command-line interface. It processes scripts, handles I/O redirection, pipes, and environment variable expansion. Understanding Shell internals is essential for writing scripts and understanding process creation.
---
## Shell vs CLI
| Feature | CLI (OS 1.x) | Shell (OS 2.0+) |
|---|---|---|
| Command history | No | Yes |
| Line editing | Minimal | Full (cursor keys, delete) |
| Pipes | No | Yes (`|` and `|&`) |
| Wildcards | Manual `#?` | Automatic in `Dir`, `List`, etc. |
| Resident commands | No | Yes (`Resident` command) |
| Background execution | `Run` only | `Run` + `&` suffix |
---
## I/O Redirection
```
; Redirect output to file:
Dir >RAM:listing.txt SYS:
; Redirect input from file:
Type <RAM:data.txt
; Append output:
Echo "log entry" >>RAM:log.txt
; Discard output:
Copy >NIL: file1 file2
; Redirect stderr (error output) — OS 2.0+:
command *>RAM:errors.txt
```
---
## Pipes
```
; Pipe output of one command to input of another:
List SYS:C | Sort | More
; Pipe both stdout and stderr:
command |& Filter
```
Pipes create temporary files in `T:` (assigned to `RAM:T`). Not true Unix-style byte streams.
---
## Script Execution
Scripts are text files executed line by line. Use `.` or `Execute`:
```
; Run a script:
Execute S:MyScript
; Or make executable and run directly (with Execute bit set):
Protect S:MyScript +s
S:MyScript
```
### Script Control Structures
```
; Conditional:
IF EXISTS SYS:Libs/68040.library
Echo "68040 detected"
ELSE
Echo "No 68040"
ENDIF
; Loop:
LAB loop
Echo "iteration"
SKIP loop
; Fail handling:
FailAt 21
Copy SYS:Missing RAM:
IF WARN
Echo "Copy had warnings"
ENDIF
```
---
## ReadArgs — Argument Parsing
AmigaDOS provides `ReadArgs()` for standardised argument parsing:
```c
/* Template syntax: KEYWORD/A = required, /S = switch, /K = keyword,
/N = numeric, /M = multi, /F = rest-of-line */
LONG args[4] = {0};
struct RDArgs *rd = ReadArgs("FROM/A,TO/A,ALL/S,BUFFER/K/N", args, NULL);
if (rd) {
char *from = (char *)args[0];
char *to = (char *)args[1];
BOOL all = (BOOL)args[2];
LONG *bufsize = (LONG *)args[3];
FreeArgs(rd);
}
```
### Template Format
| Qualifier | Meaning | Example |
|---|---|---|
| `/A` | Required argument | `FROM/A` |
| `/K` | Keyword (must use keyword=value) | `PUBSCREEN/K` |
| `/S` | Switch (boolean flag) | `ALL/S` |
| `/N` | Numeric value | `BUF/N` |
| `/M` | Multiple values (array) | `FILES/M` |
| `/F` | Rest of line (to end) | `CMD/F` |
| `=` | Alias | `FILE=FROM/A` |
---
## Resident Commands
Frequently used commands can be made **resident** (kept in RAM):
```
; Make a command resident:
Resident C:Dir PURE
Resident C:List PURE
Resident C:Copy PURE
; List resident commands:
Resident
; Remove:
Resident C:Dir REMOVE
```
Requires the binary to be compiled as `PURE` (position-independent, no writeable globals in code section).
---
## Built-in Shell Commands
| Command | Description |
|---|---|
| `CD` | Change directory |
| `Echo` | Print text |
| `If/Else/EndIf` | Conditional |
| `Skip/Lab` | Loop |
| `FailAt` | Set error threshold |
| `Set/Unset` | Local variables |
| `SetEnv/GetEnv` | Global (ENV:) variables |
| `Alias` | Command aliases |
| `Path` | Manage command search path |
| `Prompt` | Set shell prompt |
| `Protect` | Set file protection bits |
| `Run` | Execute command in background |
| `Execute` | Run script file |
| `EndCLI` | Close this shell |
| `NewCLI`/`NewShell` | Open new shell |
---
## References
- NDK39: `dos/rdargs.h`
- RKRM: Shell chapter
- ADCD 2.1: AmigaDOS Guide

77
07_dos/dos_base.md Normal file
View file

@ -0,0 +1,77 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# DosLibrary — Structure and Global State
## Overview
`dos.library` is opened by nearly every Amiga program. The library base `DOSBase` is a `struct DosLibrary` that extends `struct Library` with process-level state, the root node, and handler management.
---
## struct DosLibrary
```c
/* dos/dosextens.h — NDK39 */
struct DosLibrary {
struct Library dl_lib; /* standard Library header */
struct RootNode *dl_Root; /* pointer to the system root node */
APTR dl_GV; /* BCPL global vector */
LONG dl_A2; /* BCPL scratch */
LONG dl_A5; /* BCPL scratch */
LONG dl_A6; /* BCPL scratch */
struct ErrorString *dl_Errors; /* error string table */
struct timerequest *dl_TimeReq; /* timer.device request */
struct Library *dl_UtilityBase; /* cached UtilityBase */
struct Library *dl_IntuitionBase;/* cached IntuitionBase */
};
```
---
## struct RootNode
```c
struct RootNode {
BPTR rn_TaskArray; /* BPTR to CLI task array */
BPTR rn_ConsoleSegment; /* console handler segment */
struct DateStamp rn_Time; /* current system time */
LONG rn_RestartSeg; /* restart segment */
BPTR rn_Info; /* BPTR to DosInfo */
BPTR rn_FileHandlerSegment;
struct MinList rn_CliList; /* list of CLI processes */
/* ... OS 3.x additions ... */
ULONG rn_BootFlags;
APTR rn_BootProc;
};
```
---
## Opening dos.library
```c
struct DosLibrary *DOSBase;
DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 40);
if (!DOSBase) { /* OS 3.1 or later required */ }
```
---
## BCPL Heritage
AmigaDOS was originally written in BCPL. Artifacts remain:
- **BPTR** — pointers right-shifted by 2 (`real = bptr << 2`)
- `dl_GV` — BCPL global vector (used internally by filesystem handlers)
- File handles and locks are BPTRs, not real pointers
```c
/* Convert BPTR to C pointer: */
#define BADDR(bptr) ((APTR)((ULONG)(bptr) << 2))
```
---
## References
- NDK39: `dos/dosextens.h`, `dos/dos.h`
- ADCD 2.1: dos.library autodocs

67
07_dos/environment.md Normal file
View file

@ -0,0 +1,67 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# Environment Variables — GetVar, SetVar
## Overview
AmigaDOS supports both **local** (per-process) and **global** (system-wide) environment variables. Local variables are stored in the process's `pr_LocalVars` MinList; global variables are stored as files in `ENV:` (RAM-backed) and `ENVARC:` (persistent on disk).
---
## API
| LVO | Function | Description |
|---|---|---|
| 900 | `GetVar(name, buf, size, flags)` | Read a variable |
| 906 | `SetVar(name, buf, size, flags)` | Set or create a variable |
| 912 | `DeleteVar(name, flags)` | Remove a variable |
| 918 | `FindVar(name, type)` | Find a LocalVar node |
### Flags
```c
/* dos/var.h — NDK39 */
#define GVF_GLOBAL_ONLY 0x100 /* search only ENV: */
#define GVF_LOCAL_ONLY 0x200 /* search only pr_LocalVars */
#define GVF_BINARY_VAR 0x10 /* treat value as binary data */
#define GVF_DONT_NULL_TERM 0x20 /* don't null-terminate result */
#define LV_VAR 0 /* standard variable */
#define LV_ALIAS 1 /* shell alias */
```
---
## Usage
```c
/* Set a global variable: */
SetVar("EDITOR", "ed", -1, GVF_GLOBAL_ONLY);
/* Read it back: */
char buf[256];
if (GetVar("EDITOR", buf, sizeof(buf), 0) >= 0) {
Printf("EDITOR = %s\n", buf);
}
/* Delete: */
DeleteVar("EDITOR", GVF_GLOBAL_ONLY);
```
---
## Storage Locations
| Scope | Storage | Persistent? |
|---|---|---|
| Local | `pr_LocalVars` MinList (in-memory) | No — dies with process |
| Global (volatile) | `ENV:` — assign to `RAM:Env/` | No — lost on reboot |
| Global (persistent) | `ENVARC:` — assign to `SYS:Prefs/Env-Archive/` | Yes — survives reboot |
The startup-sequence copies `ENVARC:` to `ENV:` at boot.
---
## References
- NDK39: `dos/var.h`
- ADCD 2.1: `GetVar`, `SetVar`, `DeleteVar`

89
07_dos/error_handling.md Normal file
View file

@ -0,0 +1,89 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# Error Handling — IoErr, Fault, PrintFault, Error Codes
## Overview
Every DOS function that can fail sets an error code retrievable via `IoErr()`. The error code is stored in `pr_Result2` of the calling process.
---
## API
| LVO | Function | Description |
|---|---|---|
| 132 | `IoErr()` | Return last error code |
| 138 | `SetIoErr(code)` | Set error code manually |
| 468 | `Fault(code, header, buf, len)` | Format error message into buffer |
| 474 | `PrintFault(code, header)` | Print error message to stderr |
---
## Complete Error Code Table
| Code | Constant | Meaning |
|---|---|---|
| 103 | `ERROR_NO_FREE_STORE` | Out of memory |
| 104 | `ERROR_TASK_TABLE_FULL` | Process table full |
| 114 | `ERROR_BAD_TEMPLATE` | Bad template for ReadArgs |
| 115 | `ERROR_BAD_NUMBER` | Bad number in argument |
| 116 | `ERROR_REQUIRED_ARG_MISSING` | Required argument missing |
| 117 | `ERROR_KEY_NEEDS_ARG` | Keyword requires an argument |
| 118 | `ERROR_TOO_MANY_ARGS` | Too many arguments |
| 119 | `ERROR_UNMATCHED_QUOTES` | Unmatched quotes |
| 120 | `ERROR_LINE_TOO_LONG` | Argument line too long |
| 121 | `ERROR_FILE_NOT_OBJECT` | Not a valid executable |
| 122 | `ERROR_INVALID_RESIDENT_LIBRARY` | Invalid resident library |
| 202 | `ERROR_OBJECT_IN_USE` | Object is in use |
| 203 | `ERROR_OBJECT_EXISTS` | Object already exists |
| 204 | `ERROR_DIR_NOT_FOUND` | Directory not found |
| 205 | `ERROR_OBJECT_NOT_FOUND` | Object not found |
| 206 | `ERROR_BAD_STREAM_NAME` | Invalid stream name |
| 207 | `ERROR_OBJECT_TOO_LARGE` | Object too large |
| 209 | `ERROR_ACTION_NOT_KNOWN` | Action not known (by handler) |
| 210 | `ERROR_INVALID_COMPONENT_NAME` | Invalid filename component |
| 211 | `ERROR_INVALID_LOCK` | Invalid lock |
| 212 | `ERROR_OBJECT_WRONG_TYPE` | Object wrong type |
| 213 | `ERROR_DISK_NOT_VALIDATED` | Disk not validated |
| 214 | `ERROR_DISK_WRITE_PROTECTED` | Disk is write-protected |
| 215 | `ERROR_RENAME_ACROSS_DEVICES` | Rename across devices |
| 216 | `ERROR_DIRECTORY_NOT_EMPTY` | Directory not empty |
| 217 | `ERROR_TOO_MANY_LEVELS` | Too many directory levels |
| 218 | `ERROR_DEVICE_NOT_MOUNTED` | Device not mounted |
| 219 | `ERROR_SEEK_ERROR` | Seek error |
| 220 | `ERROR_COMMENT_TOO_BIG` | Comment too big |
| 221 | `ERROR_DISK_FULL` | Disk full |
| 222 | `ERROR_DELETE_PROTECTED` | Delete protected |
| 223 | `ERROR_WRITE_PROTECTED` | Write protected |
| 224 | `ERROR_READ_PROTECTED` | Read protected |
| 225 | `ERROR_NOT_A_DOS_DISK` | Not a DOS disk |
| 226 | `ERROR_NO_DISK` | No disk in drive |
| 232 | `ERROR_NO_MORE_ENTRIES` | No more directory entries |
| 233 | `ERROR_IS_SOFT_LINK` | Object is a soft link |
| 234 | `ERROR_OBJECT_LINKED` | Object is hard-linked |
| 235 | `ERROR_BAD_HUNK` | Bad hunk in executable |
| 236 | `ERROR_NOT_IMPLEMENTED` | Function not implemented |
| 240 | `ERROR_RECORD_NOT_LOCKED` | Record not locked |
| 241 | `ERROR_LOCK_COLLISION` | Record lock collision |
| 242 | `ERROR_LOCK_TIMEOUT` | Record lock timeout |
| 243 | `ERROR_UNLOCK_ERROR` | Unlock error |
---
## Usage Pattern
```c
BPTR fh = Open("nonexistent", MODE_OLDFILE);
if (!fh) {
LONG err = IoErr();
PrintFault(err, "myapp");
/* prints: "myapp: Object not found" */
}
```
---
## References
- NDK39: `dos/dos.h`, `dos/dosasl.h`
- ADCD 2.1: `IoErr`, `Fault`, `PrintFault`

107
07_dos/file_io.md Normal file
View file

@ -0,0 +1,107 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# File I/O — Open, Close, Read, Write, Seek
## Overview
AmigaDOS file I/O is synchronous from the caller's perspective. All functions use `BPTR` file handles and communicate errors via `IoErr()`.
---
## Core Functions
| LVO | Function | Registers | Returns |
|---|---|---|---|
| 30 | `Open(name, mode)` | D1=name, D2=mode | D0=BPTR handle (0=fail) |
| 36 | `Close(fh)` | D1=handle | D0=BOOL |
| 42 | `Read(fh, buf, len)` | D1=handle, D2=buf, D3=len | D0=actual bytes (1=error) |
| 48 | `Write(fh, buf, len)` | D1=handle, D2=buf, D3=len | D0=actual bytes (1=error) |
| 66 | `Seek(fh, pos, mode)` | D1=handle, D2=pos, D3=mode | D0=old position (1=error) |
---
## Access Modes
```c
/* dos/dos.h — NDK39 */
#define MODE_READWRITE 1004 /* open existing, read+write */
#define MODE_OLDFILE 1005 /* open existing, read only */
#define MODE_NEWFILE 1006 /* create new (truncate if exists) */
```
---
## Seek Modes
```c
#define OFFSET_BEGINNING -1 /* from start of file */
#define OFFSET_CURRENT 0 /* from current position */
#define OFFSET_END 1 /* from end of file */
```
---
## File Handle (BPTR)
The returned handle is a BPTR to a `struct FileHandle`:
```c
struct FileHandle {
struct Message *fh_Link;
struct MsgPort *fh_Interactive; /* non-NULL if console */
struct MsgPort *fh_Type; /* handler process port */
BPTR fh_Buf; /* I/O buffer (BPTR) */
LONG fh_Pos; /* current position in buffer */
LONG fh_End; /* end of valid data in buffer */
LONG fh_Funcs; /* unused */
LONG fh_Func2; /* unused */
LONG fh_Func3; /* unused */
LONG fh_Args; /* packet args */
BPTR fh_Arg2;
};
```
To access as a C pointer: `struct FileHandle *fh = BADDR(handle);`
---
## Usage Example
```c
BPTR fh = Open("RAM:test.txt", MODE_NEWFILE);
if (fh) {
Write(fh, "Hello Amiga\n", 12);
Close(fh);
}
fh = Open("RAM:test.txt", MODE_OLDFILE);
if (fh) {
UBYTE buf[64];
LONG n = Read(fh, buf, sizeof(buf));
if (n > 0) Write(Output(), buf, n); /* echo to stdout */
Close(fh);
} else {
PrintFault(IoErr(), "Open failed");
}
```
---
## Error Checking
```c
LONG err = IoErr(); /* LVO 66 — returns last DOS error code */
/* Common codes: */
#define ERROR_OBJECT_NOT_FOUND 205
#define ERROR_OBJECT_EXISTS 203
#define ERROR_DISK_FULL 221
#define ERROR_SEEK_ERROR 219
```
---
## References
- NDK39: `dos/dos.h`, `dos/dosextens.h`
- `07_dos/error_handling.md` — full error code list
- ADCD 2.1: `Open`, `Close`, `Read`, `Write`, `Seek`

90
07_dos/filesystem.md Normal file
View file

@ -0,0 +1,90 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# Filesystem — FFS/OFS Block Structure
## Overview
AmigaOS supports two native filesystem types: **OFS** (Old File System, OS 1.x) and **FFS** (Fast File System, OS 2.0+). Both use a block-based layout with 512-byte blocks. FFS differs by storing data blocks without headers, improving throughput.
---
## Block Types
| Block | Type ID | Description |
|---|---|---|
| Boot block | `"DOS\0"` / `"DOS\1"` | Blocks 01; OFS=`DOS\0`, FFS=`DOS\1` |
| Root block | `T_HEADER` (2) | Always at middle of partition; directory root |
| File header | `T_HEADER` (2) | Metadata for one file |
| Directory header | `T_HEADER` (2) | Metadata for one directory |
| Data block | `T_DATA` (8) | OFS: header + data; FFS: pure data |
| File extension | `T_LIST` (16) | Overflow pointer table for large files |
| Hash chain | — | Root/dir blocks have a 72-entry hash table |
---
## Root Block Layout (Simplified)
| Offset | Field | Description |
|---|---|---|
| 0 | `type` | Always 2 (`T_HEADER`) |
| 4 | `header_key` | Own block number |
| 8 | `high_seq` | Number of data blocks in hash table |
| 12 | `ht_size` | Hash table size (usually 72) |
| 16 | `first_data` | Unused |
| 20 | `checksum` | Block checksum |
| 24312 | `ht[72]` | Hash table: block pointers for directory entries |
| 420 | `bm_flag` | Bitmap valid flag (`-1` = valid) |
| 424472 | `bm_pages[25]` | Pointers to bitmap blocks |
| 484 | `last_altered_days` | Modification date |
| 504 | `disk_name` | BSTR: volume name |
---
## Hash Function
File/directory names are hashed into the 72-slot table:
```c
ULONG hash_name(const char *name, int table_size) {
ULONG hash = strlen(name);
for (int i = 0; name[i]; i++) {
hash = hash * 13 + toupper(name[i]);
hash &= 0x7FF;
}
return hash % table_size;
}
```
Collisions are resolved by chaining: each file/dir header has a `hash_chain` pointer to the next entry in the same slot.
---
## OFS vs FFS
| Feature | OFS (`DOS\0`) | FFS (`DOS\1`) |
|---|---|---|
| Data blocks | 24-byte header + 488 bytes data | Pure 512 bytes data |
| Max filename | 30 chars | 30 chars |
| International | No | `DOS\2` (INTL OFS), `DOS\3` (INTL FFS) |
| Dir cache | No | `DOS\4` (FFS + dir cache) |
| Throughput | ~488/512 = 95% efficiency | 100% efficiency |
---
## Checksum Algorithm
```c
LONG compute_checksum(ULONG *block, int longs) {
LONG sum = 0;
for (int i = 0; i < longs; i++) sum += block[i];
return -sum; /* stored in the checksum field to make total = 0 */
}
```
---
## References
- NDK39: `dos/filehandler.h`
- Ralph Babel: *The AmigaDOS Manual* (3rd edition) — definitive FFS reference
- Laurent Clevy: *The Amiga Filesystem* — http://lclevy.free.fr/adflib/

126
07_dos/locks_examine.md Normal file
View file

@ -0,0 +1,126 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# Locks and Examine — Lock, UnLock, Examine, ExNext, ExAll
## Overview
AmigaDOS uses **locks** to reference files and directories. A lock is a BPTR to a `FileLock` structure. Locks provide exclusive or shared access and are used for directory scanning, attribute reading, and path resolution.
---
## Lock Types
```c
/* dos/dos.h */
#define SHARED_LOCK -2 /* read-only; multiple readers allowed */
#define ACCESS_READ SHARED_LOCK
#define EXCLUSIVE_LOCK -1 /* read/write; only one holder */
#define ACCESS_WRITE EXCLUSIVE_LOCK
```
---
## Core Functions
| LVO | Function | Registers | Returns |
|---|---|---|---|
| 84 | `Lock(name, mode)` | D1=name, D2=mode | D0=lock BPTR (0=fail) |
| 90 | `UnLock(lock)` | D1=lock | — |
| 96 | `DupLock(lock)` | D1=lock | D0=new lock |
| 102 | `Examine(lock, fib)` | D1=lock, D2=fib | D0=BOOL |
| 108 | `ExNext(lock, fib)` | D1=lock, D2=fib | D0=BOOL |
| 78 | `CurrentDir(lock)` | D1=lock | D0=old lock |
| 654 | `ExAll(lock, buf, size, type, ctrl)` | D1D5 | D0=BOOL |
---
## struct FileInfoBlock
```c
/* dos/dos.h — NDK39 */
struct FileInfoBlock {
LONG fib_DiskKey; /* handler-private key */
LONG fib_DirEntryType; /* >0 = directory, <0 = file */
char fib_FileName[108]; /* null-terminated name */
LONG fib_Protection; /* rwed bits */
LONG fib_EntryType; /* same as DirEntryType */
LONG fib_Size; /* file size in bytes */
LONG fib_NumBlocks; /* blocks used */
struct DateStamp fib_Date; /* modification date */
char fib_Comment[80]; /* file comment string */
UWORD fib_OwnerUID;
UWORD fib_OwnerGID;
char fib_Reserved[32];
};
```
> [!IMPORTANT]
> `FileInfoBlock` must be longword-aligned. Use `AllocDosObject(DOS_FIB, NULL)` on OS 2.0+ or `AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC)`.
---
## Protection Bits
```c
/* dos/dos.h */
#define FIBF_SCRIPT (1<<6) /* s script (executable script) */
#define FIBF_PURE (1<<5) /* p pure (re-entrant) */
#define FIBF_ARCHIVE (1<<4) /* a archived */
#define FIBF_READ (1<<3) /* r readable (0=allowed, 1=denied!) */
#define FIBF_WRITE (1<<2) /* w writable */
#define FIBF_EXECUTE (1<<1) /* e executable */
#define FIBF_DELETE (1<<0) /* d deletable */
```
> [!WARNING]
> Amiga protection bits are **inverted** from Unix: bit SET means access is **denied**.
---
## Directory Scanning
```c
BPTR lock = Lock("SYS:", SHARED_LOCK);
struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, NULL);
if (Examine(lock, fib)) { /* read dir's own info */
while (ExNext(lock, fib)) { /* iterate entries */
Printf("%-30s %8ld %s\n",
fib->fib_FileName,
fib->fib_Size,
fib->fib_DirEntryType > 0 ? "(dir)" : "");
}
/* ExNext returns FALSE when done; IoErr() == ERROR_NO_MORE_ENTRIES */
}
FreeDosObject(DOS_FIB, fib);
UnLock(lock);
```
---
## ExAll (OS 2.0+) — Bulk Scan
```c
struct ExAllControl *eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
UBYTE buf[4096];
BOOL more;
eac->eac_LastKey = 0;
do {
more = ExAll(lock, buf, sizeof(buf), ED_NAME, eac);
struct ExAllData *ead = (struct ExAllData *)buf;
while (ead) {
Printf("%s\n", ead->ed_Name);
ead = ead->ed_Next;
}
} while (more);
FreeDosObject(DOS_EXALLCONTROL, eac);
```
---
## References
- NDK39: `dos/dos.h`, `dos/dosextens.h`, `dos/exall.h`
- ADCD 2.1: `Lock`, `UnLock`, `Examine`, `ExNext`, `ExAll`

93
07_dos/packet_system.md Normal file
View file

@ -0,0 +1,93 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# Packet System — DosPacket, ACTION_* Codes
## Overview
AmigaDOS filesystem handlers communicate via **DosPackets** — messages sent to the handler's `MsgPort`. Every file operation (`Open`, `Read`, `Lock`, etc.) is internally translated into an `ACTION_*` packet. Understanding packets is essential for writing custom handlers or intercepting filesystem calls.
---
## struct DosPacket
```c
/* dos/dosextens.h — NDK39 */
struct DosPacket {
struct Message *dp_Link; /* exec message (backlink) */
struct MsgPort *dp_Port; /* reply port */
LONG dp_Type; /* ACTION_* code */
LONG dp_Res1; /* primary result */
LONG dp_Res2; /* secondary result (error code) */
LONG dp_Arg1; /* argument 1 — type depends on dp_Type */
LONG dp_Arg2;
LONG dp_Arg3;
LONG dp_Arg4;
LONG dp_Arg5;
LONG dp_Arg6;
LONG dp_Arg7;
};
```
---
## Common ACTION_* Codes
| Code | Dec | Action | Args |
|---|---|---|---|
| `ACTION_FINDINPUT` | 1005 | Open for reading | Arg1=FileHandle, Arg2=Lock, Arg3=name(BSTR) |
| `ACTION_FINDOUTPUT` | 1006 | Open for writing (create) | same |
| `ACTION_FINDUPDATE` | 1004 | Open for r/w | same |
| `ACTION_READ` | 82 | Read bytes | Arg1=FH_Arg1, Arg2=buf, Arg3=len |
| `ACTION_WRITE` | 87 | Write bytes | Arg1=FH_Arg1, Arg2=buf, Arg3=len |
| `ACTION_SEEK` | 1008 | Seek | Arg1=FH_Arg1, Arg2=pos, Arg3=mode |
| `ACTION_END` | 1007 | Close file | Arg1=FH_Arg1 |
| `ACTION_LOCATE_OBJECT` | 8 | Lock (obtain) | Arg1=dirLock, Arg2=name(BSTR), Arg3=mode |
| `ACTION_FREE_LOCK` | 15 | UnLock | Arg1=lock |
| `ACTION_EXAMINE_OBJECT` | 23 | Examine (stat) | Arg1=lock, Arg2=FIB(BPTR) |
| `ACTION_EXAMINE_NEXT` | 24 | ExNext | Arg1=lock, Arg2=FIB(BPTR) |
| `ACTION_PARENT` | 29 | ParentDir | Arg1=lock |
| `ACTION_DELETE_OBJECT` | 16 | Delete | Arg1=lock, Arg2=name(BSTR) |
| `ACTION_RENAME_OBJECT` | 17 | Rename | Arg1=fromLock, Arg2=fromName, Arg3=toLock, Arg4=toName |
| `ACTION_CREATE_DIR` | 22 | CreateDir | Arg1=lock, Arg2=name(BSTR) |
| `ACTION_SET_PROTECT` | 21 | SetProtection | Arg1=0, Arg2=lock, Arg3=name(BSTR), Arg4=bits |
| `ACTION_DISK_INFO` | 25 | Info | Arg1=InfoData(BPTR) |
| `ACTION_IS_FILESYSTEM` | 1027 | Query | (none) → Res1=DOSTRUE if filesystem |
---
## Sending a Packet Manually
```c
struct MsgPort *handler = ((struct FileLock *)BADDR(lock))->fl_Task;
struct StandardPacket sp;
sp.sp_Msg.mn_Node.ln_Name = (char *)&sp.sp_Pkt;
sp.sp_Pkt.dp_Link = &sp.sp_Msg;
sp.sp_Pkt.dp_Port = CreateMsgPort();
sp.sp_Pkt.dp_Type = ACTION_DISK_INFO;
sp.sp_Pkt.dp_Arg1 = MKBADDR(infodata);
PutMsg(handler, &sp.sp_Msg);
WaitPort(sp.sp_Pkt.dp_Port);
GetMsg(sp.sp_Pkt.dp_Port);
/* sp.sp_Pkt.dp_Res1 = result */
DeleteMsgPort(sp.sp_Pkt.dp_Port);
```
---
## BSTR — BCPL Strings
Handler packets use **BSTR** for filenames: a BPTR to a length-prefixed string:
```
[len_byte][char_0][char_1]...[char_n]
```
- `len_byte` = string length (max 255)
- No null terminator
- Convert: `UBYTE *bstr = (UBYTE *)BADDR(bstr_bptr); int len = bstr[0]; char *name = &bstr[1];`
---
## References
- NDK39: `dos/dosextens.h`, `dos/dos.h`
- ADCD 2.1: `DoPkt`, packet system
- *Amiga ROM Kernel Reference Manual: Devices* — filesystem handler chapter

View file

@ -0,0 +1,77 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# Pattern Matching — ParsePattern, MatchPattern
## Overview
AmigaDOS provides built-in wildcard/pattern matching for file operations. Patterns are compiled into token streams via `ParsePattern` and matched via `MatchPattern`.
---
## Wildcard Syntax
| Pattern | Meaning | Example |
|---|---|---|
| `?` | Match exactly one character | `file?.txt` matches `file1.txt` |
| `#` | Match zero or more of the following | `#?.info` matches anything ending in `.info` |
| `#?` | Match any string (equivalent to `*`) | `#?` matches everything |
| `(a\|b)` | Alternation — match a or b | `(read\|write)` |
| `~` | Negation — match if NOT | `~(#?.info)` matches non-info files |
| `[abc]` | Character class | `[abc]` matches a, b, or c |
| `[a-z]` | Character range | `[0-9]` matches digits |
| `'` | Quote next character literally | `'#` matches literal `#` |
---
## API
```c
/* dos/dos.h — NDK39 */
/* Compile a pattern into tokenised form: */
LONG ParsePattern(STRPTR pat, STRPTR buf, LONG buflen);
/* Returns: 1 = pattern has wildcards, 0 = plain string, -1 = error */
/* Test a name against a compiled pattern: */
BOOL MatchPattern(STRPTR pat_compiled, STRPTR name);
/* Case-insensitive variants: */
LONG ParsePatternNoCase(STRPTR pat, STRPTR buf, LONG buflen);
BOOL MatchPatternNoCase(STRPTR pat_compiled, STRPTR name);
```
---
## Usage Example
```c
char pat[256], buf[256];
LONG is_wild;
is_wild = ParsePatternNoCase("#?.txt", pat, sizeof(pat));
if (is_wild >= 0) {
if (MatchPatternNoCase(pat, "readme.txt"))
Printf("Match!\n");
if (!MatchPatternNoCase(pat, "readme.doc"))
Printf("No match\n");
}
```
---
## Common Patterns
| Pattern | Matches |
|---|---|
| `#?` | Everything (wildcard all) |
| `#?.info` | All `.info` icon files |
| `~(#?.info)` | Everything except `.info` files |
| `(#?.c\|#?.h)` | All C source and header files |
| `file[0-9]` | `file0` through `file9` |
---
## References
- NDK39: `dos/dos.h`
- ADCD 2.1: `ParsePattern`, `MatchPattern`

View file

@ -0,0 +1,89 @@
[← Home](../README.md) · [AmigaDOS](README.md)
# Process Management — CreateNewProc, SystemTagList, Execute
## Overview
AmigaDOS provides several ways to launch child processes, ranging from the low-level `CreateNewProc` to the shell-level `Execute` and `SystemTagList`.
---
## CreateNewProcTags (OS 2.0+)
```c
/* dos/dostags.h — NDK39 */
struct Process *proc = CreateNewProcTags(
NP_Entry, myFunction, /* function pointer */
NP_Name, "Worker", /* task name */
NP_StackSize, 8192, /* stack size in bytes */
NP_Priority, 0, /* scheduling priority */
NP_Input, Open("NIL:", MODE_OLDFILE),
NP_Output, Open("NIL:", MODE_NEWFILE),
NP_CloseInput, TRUE, /* close input on exit */
NP_CloseOutput, TRUE,
NP_CurrentDir, DupLock(currentDir),
TAG_DONE);
```
### Tag Constants
| Tag | Value | Meaning |
|---|---|---|
| `NP_Entry` | — | Function to run as the new process |
| `NP_Seglist` | — | Alternative: run from a loaded segment list |
| `NP_Name` | — | Process name (appears in task list) |
| `NP_StackSize` | — | Stack size in bytes (default 4096) |
| `NP_Priority` | — | Task priority (128 to +127) |
| `NP_Input` | — | BPTR stdin handle |
| `NP_Output` | — | BPTR stdout handle |
| `NP_Error` | — | BPTR stderr handle (OS 3.0+) |
| `NP_CurrentDir` | — | Lock for current directory |
| `NP_HomeDir` | — | Lock for PROGDIR: |
| `NP_CopyVars` | — | Copy parent's local vars to child |
---
## SystemTagList — Run a Shell Command
```c
/* Execute a command string as if typed in a shell: */
LONG rc = SystemTagList("dir SYS: ALL", NULL);
/* rc = return code from the command */
/* With custom I/O: */
LONG rc = SystemTagList("list RAM:", (struct TagItem[]){
{ SYS_Input, Open("NIL:", MODE_OLDFILE) },
{ SYS_Output, Open("RAM:output.txt", MODE_NEWFILE) },
{ TAG_DONE, 0 }
});
```
---
## Execute — Legacy Command Execution
```c
/* dos.library LVO 132 */
BOOL Execute(STRPTR command, BPTR input, BPTR output);
```
- `command` — shell command string
- `input` — BPTR to additional input (0 = none)
- `output` — BPTR to output handle (0 = current)
---
## WaitForChild / Process Exit
Child processes are independent tasks. To synchronize:
1. Use a shared `MsgPort` — child sends a death message
2. Check `pr_Result2` after the child task exits
3. Use `SYS_Asynch` tag with `SystemTagList` for fire-and-forget
---
## References
- NDK39: `dos/dostags.h`, `dos/dosextens.h`
- ADCD 2.1: `CreateNewProc`, `SystemTagList`, `Execute`
- `06_exec_os/tasks_processes.md` — Task/Process structures