Expand documentation suite: 30+ articles enriched with diagrams, code examples, and hardware details

Graphics: text_fonts (bitmap layout, styles), sprites (DMA, multiplexing), gfx_base (chipset detection), rastport (draw modes, clipping), ham_ehb (mermaid fixes), display_modes (HAM palettes)

Devices: scsi (per-model interfaces, Gayle limits, CD-ROM, native vs vendor drivers), console (ANSI sequences, CON:/RAW:), parallel (CIA registers, pinout), timer (resource exhaustion), gameport (quadrature, XOR state)

Libraries: workbench (WBStartup, AppWindow/Icon/MenuItem), rexxsyslib (ARexx port hosting, command parsing), diskfont (font directory, colour fonts), keymap (rawkey codes, dead keys), locale (catalogue system, date formatting), layers (ClipRect, refresh types), utility (TagItem chains), icon (DiskObject, ToolTypes), iffparse (IFF structure, ByteRun1), expansion (Zorro AutoConfig)

Networking: tcp_ip_stacks (major rewrite - Amiga vs Unix architecture, SANA-II pipeline, PPP/SLIP dial-up, Ethernet cards, MiSTer), bsdsocket (pure API ref), sana2 (buffer hooks, driver requirements), protocols (all code examples). Deduplicated overlap between the three files.

Toolchain: debugging (Enforcer patterns, SnoopDOS, GDB remote, kprintf checklist), sasc (pragma encoding, __saveds idioms), stormc (NEW - StormC IDE, C++, PowerPC)

References: error_codes (DOS, Exec, trackdisk, Intuition error tables)
Driver development: rtg_driver (Native driver analysis, P96 tuning)

All 22 README indexes updated. Root README synced with stormc.md entry.
This commit is contained in:
Ilia Sharin 2026-04-23 21:37:26 -04:00
parent 0ded078134
commit f61c26b542
38 changed files with 6402 additions and 1065 deletions

View file

@ -2,15 +2,18 @@
# Toolchain — Overview
Development tools for building Amiga software, from native compilers to modern cross-compilation environments.
## Section Index
| File | Description |
|---|---|
| [gcc_amiga.md](gcc_amiga.md) | m68k-amigaos-gcc cross-compiler: bebbo's toolchain, Docker setup, CPU targets, libnix/ixemul startup |
| [sasc.md](sasc.md) | SAS/C 6.x: pragma format with register encoding, compiler/linker flags, __saveds/__asm idioms, SAS/C vs GCC comparison |
| [stormc.md](stormc.md) | StormC native IDE: C/C++ with exceptions, integrated debugger, PowerPC support, version history |
| [vasm_vlink.md](vasm_vlink.md) | vasm assembler and vlink linker |
| [gcc_amiga.md](gcc_amiga.md) | m68k-amigaos-gcc cross-compiler |
| [sasc.md](sasc.md) | SAS/C 6.x compiler |
| [fd_files.md](fd_files.md) | FD/SFD file format and LVO generation |
| [pragmas.md](pragmas.md) | Compiler pragmas and inline stubs |
| [ndk.md](ndk.md) | NDK versions, contents, and where to get them |
| [makefiles.md](makefiles.md) | Makefile patterns for Amiga cross-compilation |
| [debugging.md](debugging.md) | Debugging tools: BareFoot, wack, gdb remote |
| [pragmas.md](pragmas.md) | Compiler pragmas and inline stubs: SAS/C pragmas, GCC inline asm, proto headers, fd2pragma |
| [ndk.md](ndk.md) | NDK versions (3.1/3.9/3.2): contents, downloads, cross-compiler integration |
| [makefiles.md](makefiles.md) | Makefile patterns for GCC cross-compilation, vasm/vlink assembly, mixed C+asm projects |
| [debugging.md](debugging.md) | Debugging tools: Enforcer/MuForce memory watchdog, SnoopDOS tracing, FS-UAE GDB remote, kprintf, debugging checklist |

View file

@ -1,62 +1,191 @@
[← Home](../README.md) · [Toolchain](README.md)
# Debugging Tools — BareFoot, wack, GDB Remote
# Debugging Tools — Enforcer, BareFoot, GDB Remote
## Overview
Debugging Amiga programs ranges from ROM-resident kernel debuggers (wack/SAD) through software monitors to modern cross-debugging via GDB stubs.
Debugging Amiga programs spans from hardware-level ROM debuggers through MMU-based memory watchers to modern cross-debugging via GDB stubs. The unique Amiga challenges — no memory protection, shared address space, custom chip state — require specialised tools.
```mermaid
flowchart TD
subgraph "Development Host (Linux/macOS)"
GDB["m68k-elf-gdb<br/>(source-level)"]
end
subgraph "Amiga / Emulator"
ENF["Enforcer/MuForce<br/>(MMU memory watch)"]
MON["MonAm/Barfly<br/>(software debugger)"]
SERD["BareFoot/SAD<br/>(serial ROM debugger)"]
APP["Application<br/>under test"]
end
GDB -->|"TCP/Serial<br/>GDB Remote Protocol"| APP
ENF -->|"Traps illegal<br/>memory access"| APP
MON -->|"Breakpoints,<br/>disassembly"| APP
style ENF fill:#ffcdd2,stroke:#c62828,color:#333
style GDB fill:#c8e6c9,stroke:#2e7d32,color:#333
```
---
## Tool Comparison
| Tool | Type | Target | Best for |
| Tool | Type | Requires | Best For |
|---|---|---|---|
| BareFoot | Serial debugger | Real hardware / UAE | OS-level, Exec kernel |
| wack/SAD | ROM debugger | Real hardware | Boot-time, crash analysis |
| MonAm | Software monitor | AmigaOS | Breakpoints, disassembly |
| IDA Pro | Static + remote | Cross-platform | Static RE, decompilation |
| GDB (m68k-elf-gdb) | Cross-debugger | FS-UAE / Basilisk | Source-level C debugging |
| Enforcer | Memory watchdog | AmigaOS (68020+) | Illegal memory access detection |
| MuForce | Memory watchdog | AmigaOS (68040+) | Same as Enforcer for 040/060 |
| **Enforcer** | MMU memory watchdog | 68020+ with MMU | Catching NULL ptr, illegal reads/writes |
| **MuForce** | MMU memory watchdog | 68040/060 | Same as Enforcer, optimised for 040/060 |
| **MuGuardianAngel** | Stack overflow detector | 68040/060 | Catching stack overflow crashes |
| **BareFoot** | Serial kernel debugger | Serial cable + terminal | Exec internals, boot crashes, system hangs |
| **wack / SAD** | ROM-resident debugger | Guru Meditation (crash) | Post-crash analysis, ROM debugging |
| **MonAm** | Software monitor/debugger | AmigaOS | Interactive breakpoints, register inspection |
| **SnoopDOS** | DOS call tracer | AmigaOS 2.0+ | Tracing file/library opens, locks |
| **CPR** | Debug output viewer | AmigaOS | Capturing `kprintf` and `RawPutChar` output |
| **m68k-elf-gdb** | Cross-debugger | FS-UAE or vamos | Source-level C debugging from host |
| **IDA Pro** | Static + remote | Cross-platform | Static RE, decompilation |
---
## Enforcer / MuForce
## Enforcer / MuForce — Memory Access Watchdog
Detects invalid memory accesses using MMU:
The most essential Amiga debugging tool. Uses the MMU to trap **all invalid memory accesses** — reading from address 0 (NULL pointer), writing to ROM, accessing non-existent memory, etc.
```
Enforcer Hit! $0000000C read by task "myapp" at $00020456
```
```
; Install:
; Start Enforcer (runs in background):
run >NIL: Enforcer
; or for 040/060:
; For 040/060 systems:
run >NIL: MuForce
; Output goes to the serial port by default.
; Redirect to a file or console:
run >NIL: Enforcer STDOUT
run >NIL: Enforcer FILE RAM:enforcer.log
```
### Reading Enforcer Hits
```
WORD-READ from $00000004 by "myapp" at $00020456
Data: $00000000 USP: $0007FFF0 PC: $00020456
--- Loss of Register Dump ---
D0 00000000 D1 0003A2F0 D2 00000010 D3 00000001
D4 00000000 D5 FFFFFFFF D6 00000000 D7 00000000
A0 00000000 A1 0003A2F0 A2 00070000 A3 00040000
A4 00020000 A5 00000000 A6 0003F000 A7 0007FFF0
```
| Field | Meaning |
|---|---|
| `WORD-READ from $00000004` | Tried to read a WORD from address 4 (low memory = NULL struct deref) |
| `by "myapp"` | Task name that caused the hit |
| `at $00020456` | PC (program counter) where the access occurred |
> [!TIP]
> **Address $00000004 = reading `ExecBase` through NULL pointer.** This is the #1 Enforcer hit — it means code is dereferencing a NULL pointer to a structure and accessing field at offset 4. Find the instruction at the PC address in your disassembly.
### Common Enforcer Hit Patterns
| Address Range | Likely Cause |
|---|---|
| `$00000000$000003FF` | NULL pointer dereference (struct field at offset N) |
| `$00F00000$00FFFFFF` | Reading from ROM area (write-to-ROM bug) |
| `$00C00000$00DFFFFF` | Accessing custom chip area with bad address |
| `$01000000+` | Accessing memory beyond physical RAM |
---
## SnoopDOS — System Call Tracer
Monitors all DOS and library calls system-wide — essential for understanding why programs fail to find files or libraries:
```
; Start SnoopDOS (MUI GUI):
SnoopDos
; Typical output:
Open "myapp" LIBS:mytool.library OK (Lock=$0003A000)
Open "myapp" DEVS:Keymaps/usa FAIL (Object not found)
Lock "myapp" SYS:Prefs/Env-Archive OK (Lock=$00042000)
OpenLibrary "myapp" intuition.library v39 OK (Base=$0003F000)
```
---
## FS-UAE GDB Debugging
## FS-UAE GDB Remote Debugging
Modern source-level debugging from your development host:
```bash
# In fs-uae.conf:
remote_debugger = 1
remote_debugger_port = 6860
# Connect from host:
# Start FS-UAE, then from your development machine:
m68k-elf-gdb myapp
(gdb) target remote localhost:6860
(gdb) symbol-file myapp # load debug symbols
(gdb) break main
(gdb) continue
(gdb) print myVariable
(gdb) info registers
(gdb) x/10i $pc # disassemble at PC
(gdb) backtrace # show call stack
```
### Building with Debug Info
```bash
# GCC — include DWARF debug info in hunk format:
m68k-amigaos-gcc -g -noixemul -o myapp main.c
# SAS/C — include SAS debug info:
lc -d2 main.c
blink main.o TO myapp LIB lib:sc.lib lib:amiga.lib DEBUG
```
---
## kprintf / RawPutChar — Debug Output
For printf-style debugging without a console:
```c
/* kprintf writes directly to the serial port,
bypassing all OS output — works even during interrupts: */
#include <clib/debug_protos.h>
kprintf("Value: %ld at %lx\n", value, address);
/* RawPutChar — single character to serial: */
RawPutChar('X');
```
Capture with a terminal emulator on the serial port, or use **CPR** (Capture Raw Putchar) to redirect to a window or file.
---
## Debugging Checklist
| Symptom | Tool | Action |
|---|---|---|
| Guru Meditation | wack/SAD | Note crash address, check code at that PC |
| Random crashes | Enforcer | Run Enforcer, look for illegal accesses before the crash |
| "Can't open library" | SnoopDOS | See what path the open is trying |
| Memory leak | MungWall | Tracks AllocMem/FreeMem, reports leaks at exit |
| Stack overflow | MuGuardianAngel | Detects stack underflow on 040/060 |
| Performance issue | sprof (SAS/C) | Profile C functions |
| File not found | SnoopDOS | See where the OS is looking for the file |
---
## References
- BareFoot: Aminet `dev/debug/BareFoot.lha`
- Enforcer: Aminet `dev/debug/Enforcer.lha`
- MuForce: Aminet `dev/debug/MuForce.lha`
- SnoopDOS: Aminet `util/monitor/SnoopDos.lha`
- BareFoot: Aminet `dev/debug/BareFoot.lha`
- MungWall: Aminet `dev/debug/MungWall.lha`
- CPR: Aminet `dev/debug/cpr.lha`

View file

@ -4,7 +4,9 @@
## Overview
SAS/C (originally Lattice C) was the dominant commercial C compiler for AmigaOS. Version 6.58 is the final release. It produces optimised 68k code with full AmigaOS integration, including pragma-based system calls and SAS-specific debug formats.
SAS/C (originally Lattice C) was the dominant commercial C compiler for AmigaOS from the mid-1980s through the mid-1990s. Version **6.58** is the final release. It produces highly optimised 68k code with deep AmigaOS integration, including pragma-based system calls, SAS-specific debug formats, and a built-in profiler.
Most existing Amiga source code and documentation assumes SAS/C conventions. Understanding its idioms is essential for working with legacy codebases.
---
@ -12,52 +14,143 @@ SAS/C (originally Lattice C) was the dominant commercial C compiler for AmigaOS.
| Feature | Description |
|---|---|
| Register args | Automatic register parameter passing |
| Pragmas | `#pragma libcall` for direct library LVO calls |
| Small data | A4-relative addressing for globals |
| Profiling | Built-in `sprof` profiler |
| Debug format | SAS stabs (`=APS` tag in HUNK_DEBUG) |
| Optimizer | Global optimizer (`lc -O`) with peephole |
| **Register args** | Automatic register parameter passing for small functions |
| **Pragmas** | `#pragma libcall` for direct library LVO calls — no stub library needed |
| **Small data model** | A4-relative addressing for global variables (faster, smaller code) |
| **Large data model** | Absolute addressing for globals (no 64 KB limit) |
| **Profiler** | Built-in `sprof` function-level profiler |
| **Debug format** | SAS stabs (`=APS` tag in `HUNK_DEBUG`) |
| **Global optimizer** | `lc -O` with peephole, dead code elimination, CSE |
| **Code generation** | 68000 through 68060 + 68881/68882 FPU |
| **Integrated linker** | `blink` — faster than generic linkers, understands Amiga hunks |
---
## Pragma Format
Pragmas tell the compiler how to call AmigaOS library functions directly via JSR through the library base, with arguments in specific registers:
```c
/* dos_pragmas.h — generated from FD files: */
#pragma libcall DOSBase Open 1e 2102
/* ^^ ^^ ^^^^
name LVO reg-encoding
reg-encoding: 2=D2, 1=D1, 0=result in D0, 2 args */
/* ^^ ^^^^
LVO register encoding
LVO $1E = -30 (decimal) = offset in jump table
Register encoding: read RIGHT to LEFT:
2 = D2 (not used here)
0 = D0 (return value)
1 = D1 (first arg)
2 = D2 (second arg)
Last digit = number of arguments */
#pragma libcall DOSBase Close 24 101
/* LVO -$24 (-36), 1 arg in D1, returns in D0 */
#pragma libcall DOSBase Read 2a 32103
/* LVO -$2A (-42), 3 args: D1=fh, D2=buffer, D3=length */
```
Register encoding: digits map to registers (1=D0, 2=D1, ... 9=A0, A=A1, etc.)
### Register Encoding
| Digit | Register | Digit | Register |
|---|---|---|---|
| 0 | D0 | 8 | (unused) |
| 1 | D1 | 9 | A0 |
| 2 | D2 | A | A1 |
| 3 | D3 | B | A2 |
| 4 | D4 | C | A3 |
| 5 | D5 | D | A4 |
| 6 | D6 | E | A5 |
| 7 | D7 | F | (unused) |
The rightmost digit is always the result register, next digit is number of args, then args are listed left-to-right.
---
## Compilation
## Compilation Workflow
```
lc -v -O -b0 -j73 hello.c ; compile
blink hello.o TO hello LIB lib:sc.lib lib:amiga.lib ; link
Source (.c) → lc (compile) → Object (.o) → blink (link) → Executable
```
```bash
# Compile a single file:
lc -v -O -b0 main.c
# Link:
blink main.o util.o TO myapp LIB lib:sc.lib lib:amiga.lib
# Compile + link in one step:
lc -v -O -b0 -j73 main.c util.c LINK TO myapp
```
### Compiler Flags
| Flag | Meaning |
|---|---|
| `-v` | Verbose |
| `-O` | Optimise |
| `-b0` | Small data model (A4-relative) |
| `-b1` | Large data model |
| `-j73` | Generate 68020/68881 code |
| `-v` | Verbose output |
| `-O` | Enable global optimiser |
| `-b0` | Small data model (A4-relative, max 64 KB globals) |
| `-b1` | Large data model (absolute addressing) |
| `-j30` | Generate 68030 code |
| `-j40` | Generate 68040 code |
| `-j73` | Generate 68020 + 68881 FPU code |
| `-d0` | No debug info |
| `-d2` | Full debug info |
| `-d2` | Full debug info (SAS stabs) |
| `-r` | Generate resident/reentrant code |
| `-L` | Disable auto-open of amiga.lib |
| `-w` | Suppress warnings |
| `-E` | Preprocess only |
### Linker Flags (blink)
| Flag | Meaning |
|---|---|
| `TO name` | Output file name |
| `LIB libs` | Link libraries |
| `DEBUG` | Include debug hunks |
| `STRIPDEBUG` | Remove debug hunks |
| `SMALLCODE` | PC-relative addressing |
| `SMALLDATA` | A4-relative data |
| `MAP file` | Generate link map |
| `NODEBUG` | Omit all debug info |
---
## SAS/C-Specific Idioms
```c
/* Register parameters: */
ULONG __asm MyFunc(register __d0 ULONG arg1,
register __a0 APTR arg2);
/* Interrupt-safe function: */
void __interrupt __saveds MyInterrupt(void);
/* Resident code: */
LONG __saveds __asm LibOpen(register __a6 struct Library *base);
/* __saveds: saves/restores A4 (small data base) on entry/exit */
/* __interrupt: preserves all registers */
/* __asm: use register calling convention */
```
### Differences from GCC
| Feature | SAS/C | GCC (m68k-amigaos) |
|---|---|---|
| Register args | `register __d0 ULONG x` | `ULONG x __asm("d0")` |
| Small data base | A4 (automatic with `-b0`) | `-fbaserel` (A4) |
| Library pragmas | `#pragma libcall` | Inline asm stubs in `<inline/lib.h>` |
| Startup | `cres.o` (resident) / `c.o` (standard) | `libnix` or `ixemul` |
| String constants | Pooled by default | `-fmerge-constants` |
---
## References
- SAS/C 6.x User Manual
- SAS/C 6.x User Manual and Reference Manual
- NDK39 pragma files: `NDK_3.9/Include/pragmas/`
- See also: [pragmas.md](pragmas.md) — pragma/inline mechanism in depth
- See also: [gcc_amiga.md](gcc_amiga.md) — GCC cross-compiler (modern alternative)

106
13_toolchain/stormc.md Normal file
View file

@ -0,0 +1,106 @@
[← Home](../README.md) · [Toolchain](README.md)
# StormC — Native IDE and Compiler Suite
## Overview
**StormC** was a native Amiga integrated development environment (IDE) developed by **Haage & Partner**. Unlike SAS/C (command-line focused) or GCC (cross-compilation), StormC provided a modern GUI-based IDE running directly on the Amiga with project management, integrated editor, debugger, and compiler — similar to what Borland C++ and Visual Studio offered on PC.
---
## Version History
| Version | Year | Key Features |
|---|---|---|
| StormC 1.0 | 1996 | Initial release, C compiler, basic IDE |
| StormC 2.0 | 1997 | C++ support, improved optimiser |
| StormC 3.0 | 1998 | Full C++ with exceptions, STL, PowerPC support |
| StormC 4.0 | 1999 | Final version, OS 3.5 integration |
---
## Key Features
| Feature | Description |
|---|---|
| **Native IDE** | GUI editor + project manager running on AmigaOS itself |
| **C and C++** | Full C89/C90, C++ with exceptions and RTTI |
| **PowerPC** | StormC 3+ could target PPC (for CyberStorm PPC, BlizzardPPC) |
| **68k code gen** | 68000 through 68060 target support |
| **Debugger** | Integrated source-level debugger with breakpoints and watch |
| **Linker** | StormLink — Amiga hunk format output |
| **Profiler** | Built-in function-level profiler |
| **AmigaOS integration** | Full NDK headers, pragma support, Amiga library call stubs |
| **MUI support** | Built-in MUI class creation wizards (later versions) |
---
## Project Structure
StormC used `.storm` project files (proprietary format) containing:
- Source file list and compilation order
- Compiler flags per file or project-wide
- Include paths and library search paths
- Debug/Release build configurations
- Target CPU selection
---
## Compilation
```
; From the IDE:
; Project → Build (or press Ctrl+B)
; Command-line compiler also available:
stormc -O2 -m68020 -o myapp main.c util.c
; Typical flags:
; -m68000 Target 68000
; -m68020 Target 68020+
; -m68040 Target 68040
; -m68060 Target 68060
; -O0 to -O3 Optimisation level
; -g Debug info
; -c Compile only (no link)
; -I<path> Include path
; -L<path> Library path
; -l<lib> Link library
```
---
## StormC vs. Other Amiga Compilers
| Feature | SAS/C 6.58 | GCC (bebbo) | StormC 4.0 |
|---|---|---|---|
| **C++ support** | No (C only) | Yes (GCC 6.5) | Yes (with exceptions) |
| **IDE** | No (CLI + editor) | No (CLI + any editor) | **Yes (native GUI)** |
| **Debugger** | External (CodeProbe) | GDB remote | **Integrated** |
| **Cross-compile** | No (native only) | **Yes (Linux/macOS host)** | No (native only) |
| **Optimiser quality** | Excellent | Good | Good |
| **PowerPC** | No | No | Yes (v3+) |
| **Availability** | Abandonware | Free / open source | Abandonware |
| **Legacy code compat** | High (dominant compiler) | Moderate (GCC differences) | Moderate |
| **Pragma support** | Native `#pragma libcall` | Inline asm stubs | Pragma compatible |
---
## Limitations and Legacy
- **Proprietary project format**: `.storm` files can't be converted to Makefiles easily
- **No cross-compilation**: Must run on a real Amiga or emulator
- **C++ ABI**: StormC's C++ name mangling and vtable layout differ from GCC — libraries compiled with StormC can't be linked with GCC C++ code
- **Abandoned**: Haage & Partner ceased operations; no source release
- **PowerPC path abandoned**: The WarpOS/PowerUP split made PPC support fragmented
Despite these issues, StormC was the most productive **native** Amiga development environment, and many late-era Amiga applications (19962000) were developed with it.
---
## References
- Haage & Partner: historical website (archived)
- Aminet: `dev/c/StormC` — various StormC patches and updates
- See also: [sasc.md](sasc.md) — SAS/C (dominant legacy compiler)
- See also: [gcc_amiga.md](gcc_amiga.md) — GCC cross-compiler (modern standard)