# A/UX Hybrid Applications HOWTO

Native graphical applications for Apple A/UX 3.x — UNIX binaries that draw with the
Macintosh Toolbox (no X11), and Macintosh binaries that make UNIX system calls.

Compiled from the manuals in this directory, primarily
*A/UX Toolbox: Macintosh ROM Interface*, Release 3.0
(`Apple_A-UX_30_Toolbox_Mac_ROM_Interface.pdf`, same book as `aux3_mac_rom_interface.pdf`).
Section references like "§2-8" are printed page numbers in that manual unless noted.
Code marked **[manual]** is transcribed from the book; code marked **[adapted]** is a
reconstruction following the book's rules — compare against `/mac/src/examples` on a
live system before trusting the exact flags.

---

## 1. The application taxonomy

A/UX 3.x runs four kinds of programs:

| Type | Format | UI | Runs on Mac OS? | Runs on other UNIX? |
|---|---|---|---|---|
| Pure UNIX | COFF | tty / X11 | no | source-portable |
| Pure Macintosh | Mac binary (resource fork `'CODE'`) | Mac Toolbox | yes | no |
| **UNIX hybrid** | COFF | **Mac Toolbox** | **no** | **no** |
| Macintosh hybrid | Mac binary | Mac Toolbox | yes* | no |

§1-7 **[manual]**: *"Hybrid applications are programs that employ facilities from both
the UNIX and Macintosh application models. There are two basic types… The first type is
a UNIX application that uses the A/UX Toolbox to provide an interface that has the
Macintosh look and feel — called **UNIX hybrid applications**. The A/UX CommandShell
application is an example. The second type is a Macintosh application that makes UNIX
system calls — called **Macintosh hybrid applications**."*

\* A Macintosh hybrid launches under Mac OS only if it guards its UNIX calls behind a
Gestalt check (see §7); the UNIX-dependent paths work only under A/UX.

The **UNIX hybrid** is the "native A/UX graphical app": a COFF executable, exec'd by the
A/UX kernel, whose windows are real System 7 windows inside the A/UX Finder session.
Mac OS cannot load it (COFF + UNIX syscalls); other UNIXes have no Mac ROM to trap into.
Shipped examples: `CommandShell`, `cmdo` (Commando), `/mac/bin/TextEditor`.

Requirement (App. C-2): **the A/UX Finder session must be running** — Toolbox
applications cannot be launched from a plain getty/console login, and X11/MacX sessions
substitute their own display. This is the Mac windowing environment (`startmac`), not X.

---

## 2. How it works under the hood (Appendix C)

- The kernel contains a user-interface device driver, **`/dev/uinter0`**, which maps the
  screen buffer and ROM into the process, keeps the event queue (mouse/keyboard),
  tracks the cursor on vertical-retrace interrupts, and installs the A-line trap handler
  (§C-2..C-3).
- A Toolbox app links a special startup file, **`/usr/lib/maccrt0.o`** *instead of*
  `/lib/crt0.o`. It calls `set42sig(3)`, attaches the shared data segment, opens
  `/dev/uinter0`, builds the trap-dispatch tables and Mac low-memory globals, then calls
  your `main()` (§C-3).
- Toolbox calls compile to **A-line traps** (opcodes `0xA000–0xAFFF`), exactly as on a
  real Mac. The kernel catches the exception, bounces it back to a user-mode
  trap-dispatch routine, which routes each trap either to the **ROM** or to an **A/UX
  replacement routine in user RAM** via per-process dispatch tables (§C-4..C-5).
  A-line traps cannot be issued from UNIX device drivers.
- To leave room for the Mac low-memory globals, A/UX Toolbox binaries are **linked at
  virtual address `0x10000000`** (§C-6). Only a subset of low-memory globals exists —
  hardware-related ones don't (Appendix D has the list).
- "Not in ROM" glue lives in **`/usr/lib/libmac.a`** (static) and **`libmac_s.a`**
  (shared stub → `/shlib/libmac_s`); functionally equivalent, pick either (§C-6).

---

## 3. Development environments

Figure 2-1 (§2-2): source can be developed and built on either side.

- **Build under A/UX**: standard `cc`/`ld`/`make`, headers in `/usr/include/mac`,
  ResEdit or `rez` for resources. Typical for giving an existing UNIX program a Finder
  face.
- **Build under Mac OS with MPW**: write common source, compile separately for each
  environment. MPW 3.2 runs under A/UX (3.1 does not — FAQ M.09). The optional *A/UX
  Developer's Tools* (APDA) adds an ANSI `c89` and MPW-format A/UX syscall libraries
  (§1-6, §3-7).
- Any Macintosh application that is 32-bit clean, System 7-compatible, avoids
  unsupported traps and never touches hardware directly will run under the A/UX Finder
  unmodified (§1-6) — that's the "aux can run mac apps" case.

---

## 4. Building a UNIX hybrid (A/UX Toolbox application)

### 4.1 Toolchain map

| Piece | Path | Notes |
|---|---|---|
| C headers | `/usr/include/mac/*.h` | one per manager; see table in §10 |
| Toolbox glue | `/usr/lib/libmac.a`, `/usr/lib/libmac_s.a` | static / shared (§C-6) |
| Startup | `/usr/lib/maccrt0.o` | replaces `crt0.o` |
| Link script | `/usr/lib/low.ld` | reserves low memory for Mac globals |
| Globals symbols | `/usr/lib/low.o` | Mac low-memory global symbols |
| Resource compiler | `/mac/bin/rez`, `derez` | MPW ports; type defs in `/mac/lib/rincludes` |
| Utilities | `/mac/bin/{setfile,fcnvt,changesize,launch,startmac,startmac24}` | §3-2..3-3 |
| Samples | `/mac/src/examples` (`sample.c/.r`, `qdsamp.c/.r`, makefile), `/mac/src/sndDemo` | §2-10..2-11 |
| Resource lib | `/usr/lib/libmr.a` + `asd.h`, `aux_rsrc.h` | read Mac resources from UNIX code (App. B) |

### 4.2 Build pipeline (Figure 2-2, §2-8)

```
appname.c ──cc──> appname.o ──ld──> appname        (COFF executable)
                    headers: /usr/include/mac/*
                    link with: /usr/lib/maccrt0.o   (init, talks to kernel)
                               /usr/lib/low.ld      (script: space for globals)
                               /usr/lib/low.o       (global symbols)
                               libmac_s.a | libmac.a

appname.r ──rez──> %appname                        (resource file)
                    includes: /mac/lib/rincludes/*  (types.r, systypes.r)
```

Build both explicitly; the shipped makefile builds them as two targets (§2-10):

```sh
cd /mac/src/examples          # or your copy of it
make sample %sample
```

Run it by typing `sample` in CommandShell or double-clicking its icon. The Toolbox
automatically pairs the executable with its `%file` resource file **as long as both sit
in the same directory** (§2-10).

A representative makefile **[adapted** — exact flags: see the shipped sample makefile;
the manual cites its home as both `/mac/src/examples` and `/mac/lib/examples` in
different sections (§2-6, §2-10, App. B)**]**:

```makefile
CFLAGS = -I/usr/include/mac
LIBS   = -lmac_s -lc_s

hello: hello.o
	ld -o hello /usr/lib/maccrt0.o hello.o \
	    /usr/lib/low.ld /usr/lib/low.o $(LIBS)

%hello: hello.r
	rez -o %hello hello.r

all: hello %hello
```

The two non-negotiable deviations from a normal UNIX build (§2-7): add the Mac include
path, and link `maccrt0.o` + globals + Toolbox library instead of the default startup.

### 4.3 Minimal source skeleton **[adapted]**

Same shape as a System 7 application; only the includes and string conventions are
A/UX-specific. Compare with `/mac/src/examples/sample.c`.

```c
#include <types.h>          /* /usr/include/mac via -I           */
#include <quickdraw.h>
#include <fonts.h>
#include <events.h>
#include <windows.h>
#include <menus.h>
#include <textedit.h>
#include <dialogs.h>

int noCD = 1;               /* keep cwd of invoking shell, sec 4.4 */

main()
{
    WindowPtr w;
    EventRecord ev;
    Rect r;

    InitGraf(&qd.thePort);  /* standard manager init sequence */
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(0L);
    InitCursor();

    SetRect(&r, 50, 50, 400, 200);
    /* lowercase variant takes a C string -- A/UX cc has no "\p" literals */
    w = newwindow(0L, &r, "hello from UNIX", 1, documentProc,
                  (WindowPtr)-1L, 1, 0L);
    SetPort(w);
    MoveTo(20, 40);
    drawstring("A COFF binary drawing with QuickDraw");

    for (;;) {
        if (!WaitNextEvent(everyEvent, &ev, 60L, 0L))
            continue;
        if (ev.what == mouseDown && FindWindow(ev.where, &w) == inGoAway)
            break;              /* click close box to quit */
    }
    exit(0);
}
```

Notes:
- **Use `WaitNextEvent`, never `GetNextEvent`** — `GetNextEvent` busy-polls and is
  "very unfriendly to the A/UX kernel scheduler"; `WaitNextEvent` lets the process
  sleep (§2-4).
- Every routine that takes/returns strings or QuickDraw points exists twice:
  the *Inside Macintosh* mixed-case spelling (Pascal `Str255`/point conventions) and an
  all-**lowercase** variant using C strings and pointers (§4-11, §C-7). `c2pstr`/
  `p2cstr` (`strings.h`) convert in place. A/UX `cc` lacks MPW's `\p` Pascal-string
  literals, so lowercase variants are the natural choice in UNIX-side code.
- This is normal UNIX code otherwise: it may `fork`, `open`, `read`, `ioctl`, use the
  whole C library, and mix that freely with Toolbox calls — that's the entire point.

### 4.4 Link-time behavior variables (§3-3)

Define these as globals in the program (they live in `libmac.a`):

```c
int dontForeground = 1;   /* run only in the background            */
int noCD = 1;             /* cwd = directory user ran it from;     */
                          /* default: cwd = directory of the binary */
```

### 4.5 Blending UNIX I/O into the Mac event loop

Two documented mechanisms:

**`ui_setselect`** (§2-5) — makes `WaitNextEvent` return a null event whenever a
`select(2)`-style descriptor mask becomes ready. Bracket the call:

```c
ui_setselect(nfds, readmask, writemask, exceptmask);  /* int masks, not ptrs */
WaitNextEvent(...);
ui_setselect(0, 0, 0, 0);                             /* always clear again  */
select(nfds, &readfds, &writefds, &exceptfds, &zero_tv); /* find out why     */
```

`WaitNextEvent` cannot tell you *why* it woke, so poll `select` with a zero timeout
afterward. Clear the masks before entering any other event loop (`ModalDialog`), or
pending descriptor activity starves update events. Limits: first 32 descriptors only,
no timeout argument, no ready-count returned. (The A/UX 1.1 trick of calling `select`
then `GetNextEvent` no longer works in 3.0.)

**`select` on `/dev/uinter0`** (§3-6) — the reverse direction, for programs built
around a UNIX `select` loop: open the user-interface device (`udevfd`), include it in
your masks, and `select` wakes on Macintosh events too; then call `GetNextEvent` to
fetch them. `AUXDispatch(AUX_SET_SELRECT, &rect)` additionally makes bare mouse motion
outside a rectangle count as activity.

**`AUXDispatch` trap** (§3-4..3-5, `aux.h`) — grab-bag of A/UX-only services. Call it
only after Gestalt confirms A/UX. Selectors:

| Selector | Function |
|---|---|
| `AUX_HIGHEST` | highest supported selector |
| `AUX_GET_ERRNO` | address of `errno` |
| `AUX_GET_PRINTF` | address of `printf` (for Mac-side code linked without libc) |
| `AUX_GET_SIGNAL` | address of `signal` |
| `AUX_GET_TIMEOUT` | ticks until a Mac device driver next needs CPU |
| `AUX_SET_SELRECT` | mouse-motion rectangle for `select` |
| `AUX_CHECK_KIDS` | does this pid have live children? |
| `AUX_POST_MODIFIED` | post event with modifiers (the A/UX `PPostEvent`) |
| `AUX_FIND_EVENT` | search the event queue |

### 4.6 Runtime environment variables (§3-6..3-7, FAQ A.11)

| Variable | Effect |
|---|---|
| `TBCORE` | nonzero: dump core on fatal Toolbox error instead of message+exit |
| `TBRAM` | nonzero: copy ROM into RAM so you can set breakpoints in "ROM" |
| `TBSYSTEM` | path to Mac system files (default `/mac/lib/SystemFiles`) |
| `TBTRAP` | nonzero: log every A-line trap to stderr |
| `TBWARN` | nonzero: warn on unusual-but-nonfatal conditions (set it in `.profile`) |
| `TBMEMORY` | Toolbox memory size for the session, e.g. `TBMEMORY=10m` (FAQ A.11) |

---

## 5. Packaging: resources, type/creator, icons (Chapter 6, App. C-6)

A UNIX file has one fork; a Mac file has data + resource forks + Finder info. A/UX
bridges with two Apple formats (§6-9):

- **AppleSingle** — everything in one file. Magic `0x00051600`. What File Manager and
  `rez` create under A/UX.
- **AppleDouble** — data fork in `file`, resources + Finder info in header file
  **`%file`** (magic `0x00051607`). Best when UNIX tools must read the data fork.
  Move both files together.

Your compiled COFF binary is treated as an AppleDouble *data* file with implicit type
`'COFF'`/creator `'A/UX'` — **no `%` header file is created for it** unless you change
type/creator (§6-10, §6-13). Automatic conversion when files cross environments
(Table 6-2): types `'COFF'`, `'SHEL'`, `'XAPP'`, `'BIN'` with creator `'A/UX'` stay
Plain; `'APPL'` (with the No-INITs flag, bit 7 of `fdFlags`), `'TEXT'`, and `'A/UX'`
types go AppleDouble; everything else goes AppleSingle. Setting type `'APPL'` is how a
program like CommandShell gets **its own icon** (§6-15). Untyped A/UX files entering
the Finder get creator `'A/UX'`; text becomes `'TEXT'` (creator `'tefi'`), shell
scripts `'SHEL'` (§C-6, §6-7).

Tools (§3-2..3-3, §6-14):

```sh
setfile ...        # set type/creator on AppleSingle or %header
changesize ...     # adjust the 'SIZE' resource (memory partition)
fcnvt ...          # convert among AppleSingle/AppleDouble + 4 formats,
                   #   incl. kermit-style file + file.res pairs
rez / derez        # compile/decompile resources (AppleSingle output)
launch ...         # start a Macintosh binary from CommandShell (32-bit env only)
```

Set the `'SIZE'` partition a bit **larger** than you would for System 7 — Mac memory
management under A/UX has extra overhead (§2-4). Line endings: Mac text is CR
(`0x0D`), UNIX text is LF (`0x0A`); conversion is automatic for recognized text files
only, and Toolbox managers expect CR in strings you hand them (§4-7..4-8).

---

## 6. Compatibility rules for the Toolbox side (Ch. 1, 4, 5)

Must (§1-6):
- **32-bit clean** (the 24-bit `startmac24` login exists for testing legacy code).
- **System 7 / MultiFinder-compatible** — apps that can't multitask won't run.
- **No unsupported traps** (below), **no direct hardware access** (video memory is the
  one exception).

Environment realities (§4-2..4-9):
- Process runs in 680x0 **user mode**; common privileged instructions (status-register
  ops, etc.) are emulated by the kernel, slowly (Table 4-1). Priority >0 in the virtual
  SR blocks all A/UX signals.
- No SCC serial-register access, no disk-controller copy protection, no CPU exception
  vectors, hardware-related low-memory globals absent.
- Time Manager / Vertical Retrace Manager are built on A/UX signals
  (`setitimer(2)`): timing is coarser and tasks may be arbitrarily delayed. While using
  them, don't call `alarm`, `setitimer`, `sleep`, or touch `SIGALRM`. Precise timing ⇒
  write an A/UX device driver instead.
- `GetDateTime` returns program start time (global `Time` is never updated); use
  `ReadDateTime`. `SetDateTime` fails (`clkWrEr`) — only root sets the clock.
- Managers not present: **ADB, SCSI Manager, Power Manager** (Table 5-1); Serial Driver
  partially (no 3600/7200/57600 baud, no event posting). Unsupported calls include
  `DoVBLTask`, `PPostEvent`, `Chain`, `SerialPower`, ADB calls (Table 5-3); ~80 calls
  are patched (Table 5-2). `Restart` is unsupported — use the Shutdown Manager.
- MPW C vs A/UX `cc` differences (§4-10): newline character value, enum sizes, pointer
  returns in A0+D0 vs D0, no `extern pascal` — glue in `libmac[_s].a` covers ROM calls;
  writing your own defprocs/filter procs needs hand-written assembly glue (Pascal
  calling conventions, §C-7..C-10).

---

## 7. Macintosh hybrids: UNIX syscalls from a Mac binary (§3-7..3-11)

For Mac applications (built in MPW) that want UNIX services when running under A/UX.
The *A/UX Developer's Tools* product ships ready-made MPW-format syscall libraries;
otherwise roll your own glue:

1. **Capture the syscall sequence**: write a trivial A/UX C program using the call,
   compile, disassemble with `adb(1)`. `open(2)` becomes **[manual, §3-8]**:

   ```
   open:   mov.l  &0x5,%d0     ; syscall number
           trap   &0x0
           bcc.b  noerror
           jmp    cerror%
   noerror: rts
   cerror%: mov.l %d0,errno
           mov.l  &-1,%d0
           mov.l  %d0,%a0
           rts
   ```

2. **Recreate it as an MPW assembly routine** under a distinct name (e.g. `auxopen`).

3. **Call it conditionally** after detecting A/UX via `Gestalt(gestaltAUXVersion, …)`;
   on pre-System 7 systems fall back to low-memory flag `HWCfgFlags` (`0xB22`), bit 9
   set ⇒ running under A/UX. The manual's detector **[manual, §3-9..3-11, abridged]**:

   ```c
   #define HWCfgFlags 0xB22
   short getAUXVersion()
   {
       long  auxversion = 0;
       short err = Gestalt(gestaltAUXVersion, &auxversion);
       if (err == gestaltUnknownErr || err == gestaltUndefSelectorErr) {
           short *flagptr = (short *)HWCfgFlags;
           if (*flagptr & (1 << 9))
               auxversion = 0x100;        /* A/UX present, assume 1.x */
       }
       return (short)(auxversion >> 8);   /* 0 = not A/UX, else major */
   }
   ```

CommandShell-class integration (seeing both file systems, launching UNIX commands) is
exactly this technique plus the Toolbox — FAQ A.10.

---

## 8. Debugging (§1-6, §3-11..3-13)

- **MacsBug 6.2+** (APDA): drop into `/mac/sys/System Folder`; installs at next login.
  Enters on exceptions or Cmd-Ctrl-I. It does *not* underlie the whole system as on Mac
  OS — the programmer's switch enters the UNIX kernel debugger instead. Cmd-Ctrl-E =
  tidy logout escape from a hung Finder session. Useful: `g`, `es` (exit app —
  dirty), `dm curapname`, `il`, `sc`, `help`.
- **`dbx`** (also `adb`, `sdb`): source-level debugging of the COFF side — from a
  second terminal over serial or network. `trace`, `stop`, `cont`, `step`, `next`.
  Combine with MacsBug for apps mixing syscalls and traps.
- `TBTRAP=1` for an A-line trace, `TBCORE=1` for core dumps, `TBRAM=1` to breakpoint
  inside ROM code.

---

## 9. Version fragility (FAQ M.13)

Hybrids bind to the A/UX-modified System file (System 7.0.1 basis in A/UX 3.x). Forcing
System 7.1 into the A/UX System Folder makes Mac binaries mostly still work but **all
hybrids — CommandShell, Commando — die**. Don't replace A/UX's System, AppleTalk, or
MacTCP pieces with stock Mac OS versions.

---

## 10. Reference

### Header files, `/usr/include/mac` (Table F-1)

| Header | Library |
|---|---|
| `types.h` | common type definitions |
| `quickdraw.h` | 32-Bit QuickDraw w/ Color QuickDraw |
| `windows.h` / `menus.h` / `controls.h` / `dialogs.h` | Window / Menu / Control / Dialog Managers |
| `events.h` / `osevents.h` | Toolbox / OS Event Managers |
| `files.h` | File Manager |
| `memory.h` / `vmcalls.h` | Memory Manager (+VM) |
| `resources.h`, `asd.h`, `aux_rsrc.h` | Resource Manager; UNIX-side resource reading (`libmr.a`) |
| `fonts.h` / `textedit.h` / `lists.h` / `scrap.h` / `script.h` | Fonts / TextEdit / List / Scrap / Script |
| `packages.h` | Std File, Intl Utilities, Disk Init, BCD packages |
| `sm.h`, `soundinput.h` | Sound Manager |
| `printing.h`, `printtraps.h` | Printing Manager |
| `processes.h` / `segload.h` / `shutdown.h` / `slots.h` | Process / Segment Loader / Shutdown / Slot |
| `serial.h` / `disks.h` / `diskinit.h` / `devices.h` / `video.h` | drivers |
| `osutils.h` / `toolutils.h` / `dtask.h` / `timer.h` / `retrace.h` / `notify.h` | utilities, deferred tasks, timing, notification |
| `gestalt.h` / `errors.h` / `traps.h` / `sysequ.h` / `romdefs.h` | Gestalt, errors, trap numbers, low-mem equates, ROM defs |
| `aux.h` | `AUXDispatch` |
| `strings.h` | `c2pstr` / `p2cstr` |
| `picker.h` / `palettes.h` | Color Picker / Palette Manager |

### Where to read more (this directory)

| Topic | Document |
|---|---|
| Everything above, in full | `Apple_A-UX_30_Toolbox_Mac_ROM_Interface.pdf` — ch. 1 concepts, ch. 2 building, ch. 3 utilities/extensions, ch. 4 compatibility, ch. 5 per-manager status + patched/unsupported calls, ch. 6 file formats, App. B file map, App. C internals, App. D low-mem globals, App. E rez/derez language, App. F C interfaces |
| `cc`, `ld`, `make`, shared libraries, `dbx` | `aux3_programming_languages_and_tools_1.pdf` / `_2.pdf` |
| `startmac`, `setfile`, `fcnvt`, `rez` man pages | `aux3_command_reference_*.pdf` |
| `launch(1M)`, `select(2)`, `environ(5)` | `aux1_programmers_reference.pdf` (A/UX Programmer's Reference) |
| 24-bit login, Finder environment, personal System Folders | `Apple_A-UX_30_Essentials.pdf` |
| MPW/ETO tooling | `aux3_eto_essentials_tools_objects.pdf` |
| Practical Q&A (TBMEMORY, hybrids vs 7.1, MPW 3.1 hang) | `FAQ.aux.311.txt` §A.10, A.11, M.09, M.13 |
| X11 alternative (what hybrids are *not*) | `Apple_A-UX_30_X11_Users_Guide_for_A-UX.pdf`, `Apple_A-UX_30_MacX_User_Guide.pdf` |
