AmigaOS Code Patterns and Idioms¶
This article distills the recurring patterns found across the ~150 example source files on the Developer CD. These are the structural templates an agent should follow when writing AmigaOS C code.
Standard program structure¶
Every AmigaOS C program follows this skeleton:
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/alib_protos.h> /* amiga.lib */
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/intuition_pragmas.h>
extern struct ExecBase *SysBase;
struct Library *DOSBase;
struct Library *IntuitionBase;
struct Library *GfxBase;
int main(int argc, char **argv)
{
/* 1. Open libraries with version checks */
if (!(IntuitionBase = OpenLibrary("intuition.library", 37)))
return RETURN_FAIL;
if (!(GfxBase = OpenLibrary("graphics.library", 37)))
{ CloseLibrary(IntuitionBase); return RETURN_FAIL; }
/* 2. Open screen/window */
struct Screen *scr = OpenScreenTags(NULL, SA_Depth, 4, TAG_DONE);
struct Window *win = OpenWindowTags(NULL,
WA_CustomScreen, (ULONG)scr,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_GADGETUP,
WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET,
TAG_DONE);
/* 3. Event loop */
BOOL running = TRUE;
while (running)
{
struct IntuiMessage *msg;
while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
{
switch (msg->Class)
{
case IDCMP_CLOSEWINDOW: running = FALSE; break;
case IDCMP_VANILLAKEY:
if (msg->Code == 0x1b) running = FALSE; /* ESC */
break;
}
ReplyMsg((struct Message *)msg);
}
Wait(1 << win->UserPort->mp_SigBit);
}
/* 4. Cleanup (reverse order) */
CloseWindow(win);
CloseScreen(scr);
CloseLibrary(GfxBase);
CloseLibrary(IntuitionBase);
return RETURN_OK;
}
Rules: Always check OpenLibrary() return. Always ReplyMsg() every GetMsg(). Always close in reverse order. Always close libraries.
Include file conventions¶
<exec/types.h>— basic types (ULONG, APTR, BOOL, etc.)<clib/*_protos.h>— function prototypes for each library<pragmas/*_pragmas.h>— inline-call pragmas (SAS/C optimization)<alib_protos.h>— amiga.lib utility prototypes (HookEntry,BeginIO, etc.)
Command-line argument parsing with ReadArgs¶
#define TEMPLATE "FILE/A,PORT/K/N,QUIET/S"
LONG opts[3];
struct RDArgs *rdargs = ReadArgs(TEMPLATE, opts, NULL);
if (rdargs)
{
STRPTR file = (STRPTR)opts[0]; /* /A required string */
LONG *port = (LONG *)opts[1]; /* /K/N optional number */
BOOL quiet = opts[2]; /* /S switch */
/* ... use args ... */
FreeArgs(rdargs);
}
Async I/O double-buffering pattern¶
The AsynchIO/asyncio.c example implements high-performance async file reading by double-buffering DOS packets:
SendPacket()fills buffer A while the application processes buffer B.WaitPacket()waits for the packet reply and brings up retry requesters viaErrorReport()on errors.- The two buffers alternate — while one is being filled by the filesystem, the other is being consumed by the application.
Key detail: uses Remove() instead of GetMsg() to retrieve the packet, because only one packet can be in the port at a time. If multiple packets were possible, GetMsg() would be required for correct arbitration.
DataType object creation (sound, picture, text)¶
Object *o = NewDTObject(name,
DTA_SourceType, DTST_FILE,
DTA_GroupID, GID_SOUND,
SDTA_Volume, 64,
SDTA_SignalTask, (ULONG)FindTask(NULL),
SDTA_SignalBit, (ULONG)SIGBREAKB_CTRL_F,
TAG_DONE);
struct dtTrigger dtt = { DTM_TRIGGER, NULL, STM_PLAY, NULL };
DoMethodA(o, (Msg)&dtt);
Wait(SIGBREAKB_CTRL_F); /* async completion */
DisposeDTObject(o);
Pattern: NewDTObject loads any supported format → DoMethodA with DTM_TRIGGER + STM_PLAY plays it → Wait() for the async signal → DisposeDTObject() cleans up. The SDTA_SignalTask/SDTA_SignalBit pair provides async completion notification.
GadTools listview with custom callback rendering¶
struct Hook drawHook;
drawHook.h_Entry = HookEntry;
drawHook.h_SubEntry = drawFunc; /* your custom render function */
gad = CreateGadgetA(LISTVIEW_KIND, gad, &ng,
GTLV_Labels, NULL,
GTLV_CallBack, (ULONG)&drawHook,
GTLV_MaxPen, drawInfo->dri_NumPens,
TAG_DONE);
The draw hook receives the rastport, the entry data, bounds rectangle, and selection state. This enables rendering images, icons, or multi-line text in listview rows instead of plain strings.
BOOPSI custom class as a shared library¶
The boopsi/myclassinit.c example shows the full lifecycle:
myLibInit()— setSysBase, store seglist.myLibOpen()— first open:openAll()(openIntuitionBase,GfxBase,UtilityBase) +MakeClass()to create the class.AddClass()to make it public.myLibClose()— last close: if marked for expunge,RemoveClass()+FreeClass().myLibExpunge()—FreeClass()+CloseLibrary()+FreeMem().- Dispatcher — switch on method ID (
OM_NEW,OM_SET,OM_GET,OM_DISPOSE, custom methods). Always callDoSuperMethodA()first for inherited behavior.
IFF file loading pattern¶
struct IFFHandle *iff = AllocIFF();
iff->iff_Stream = Open(filename, MODE_OLDFILE);
InitIFFasDOS(iff);
OpenIFF(iff, IFFF_READ);
PropChunk(iff, ID_ILBM, ID_BMHD); /* collect header */
PropChunk(iff, ID_ILBM, ID_CMAP); /* collect colormap */
StopChunk(iff, ID_ILBM, ID_BODY); /* stop at body */
/* scan handler reads BODY via ReadChunkBytes */
ParseIFF(iff, IFFPARSE_SCAN);
CloseIFF(iff);
Close(iff->iff_Stream);
FreeIFF(iff);
Commodities application structure¶
CxBroker()creates the broker with name, description, flags.AttachCxObj(broker, filter)builds the input-processing object tree.ActivateCxObj(broker, TRUE)starts processing.- Wait for broker signal + window signal.
DeleteCxObjAll(broker)recursively deletes the entire tree on cleanup.
Where to find examples by topic¶
| Topic | Location |
|---|---|
| Intuition V39 demos | NDK_3.1/Examples1/intuition/ |
| GadTools (listview callback) | NDK_3.1/Examples1/gadtools/ListView.c |
| ASL requesters + hooks | NDK_3.1/Examples1/asl/ |
| Color wheel + gradient slider | NDK_3.1/Examples1/colorwheel/WheelGrad.c |
| Async IO (double-buffered) | NDK_3.1/Examples1/AsynchIO/asyncio.c |
| Locale + self-loading catalogs | NDK_3.1/Examples1/locale/ |
| AmigaGuide embedding | NDK_3.1/Examples2/AmigaGuide/ |
| DataTypes (sound, picture, ClipView) | NDK_3.1/Examples2/DataTypes/ |
| IFF ILBM loading/saving | NDK_3.1/Examples2/IFF/ |
| BOOPSI custom classes | Extras/Development/Example_Code_v37/Libraries/Intuition/boopsi/ |
| Commodities | Extras/Development/Example_Code_v37/Libraries/Commodities/ |
| BOOPSI image/gadget classes | Extras/BOOPSI/ |
See Also¶
Sources: ESCOM AG / Commodore-Amiga / David N. Junod, example code (1985-1996).
Raw: raw/examples/code-idioms.md
Updated: 2026-08-04