148 lines
6.1 KiB
Markdown
148 lines
6.1 KiB
Markdown
# llvm816 GS/OS Demo Apps
|
|
|
|
Small Apple IIgs S16 applications that build with our LLVM/clang
|
|
toolchain, wrap as OMF v2.1 ExpressLoad, and launch under real
|
|
GS/OS 6.0.2 in MAME.
|
|
|
|
## Building / running
|
|
|
|
```
|
|
bash demos/build.sh helloBeep # build the OMF
|
|
bash demos/launch.sh helloBeep # interactive run in MAME (visible window, audio)
|
|
bash demos/test.sh helloBeep # headless test (boots, runs, checks marker)
|
|
```
|
|
|
|
The launch script runs MAME with no timeout; close the MAME
|
|
window when done (Esc, then Cmd-Q). The test script injects a
|
|
keystroke after the demo has launched, then checks `$00:0070`
|
|
for the `0x99` end-of-run marker the demo writes before exit.
|
|
|
|
## Demos
|
|
|
|
### `helloBeep.c`
|
|
|
|
Three `SysBeep()` calls then exit. The toolbox `SysBeep` lives in
|
|
Misc Tools; no other startup needed (Loader handles MM + TL).
|
|
|
|
### `helloText.c`
|
|
|
|
Initialises Event Manager (so `GetNextEvent` can read keystrokes)
|
|
and Text Tools (so `WriteCString` has an output device), writes
|
|
two greeting lines to the text screen, waits for any keypress via
|
|
`GetNextEvent`, beeps, exits. Uses these toolbox calls:
|
|
|
|
- `MMStartUp`, `NewHandle` (DP allocation for Event Manager)
|
|
- `EMStartUp`, `GetNextEvent` (event-driven keyboard)
|
|
- `TextStartUp`, `SetOutputDevice`, `WriteCString` (text I/O)
|
|
- `SysBeep`
|
|
|
|
### `helloWindow.c`
|
|
|
|
Initialises the full Window Manager startup chain (Memory, QD,
|
|
Event, Scheduler, Window), constructs an Apple-IIgs-Toolbox-Ref
|
|
NewWindow parm block, and calls `NewWindow`. When NewWindow
|
|
returns a real handle the demo calls `SetPort`, `ShowWindow`,
|
|
`MoveTo`, and `DrawString` to put a greeting in the window, then
|
|
waits for a keypress, beeps, and exits.
|
|
|
|
Three toolchain bugs needed fixing to make this work end-to-end
|
|
under real GS/OS 6.0.2 (all now landed):
|
|
- **omfEmit RESSPC=0** for code segments — BSS got no memory
|
|
allocation; writes past the image end silently vanished. Now
|
|
BSS is embedded as zeros in the LCONST data.
|
|
- **Loader cRELOC at segPlacedBase=$0000** (not $1000 like our
|
|
text-base) — host probes need to compute runtime addresses as
|
|
`link_addr - text_base + bank<<16`.
|
|
- **`&symbol` bank=0** — proper backend fix landed. `LDAi16imm_bank`
|
|
AsmPrinter pseudo lowers to `lda $BE`; crt0 stores `PBR` to $BE
|
|
+ zero to $BF at startup, so the high half of every `&symbol`
|
|
pointer carries the actual load bank at runtime. Toolbox
|
|
pointer args now Just Work without per-wrapper PBR overrides.
|
|
|
|
### `orcaFrame.c`
|
|
|
|
First ORCA-style desktop application. Opens a Window Manager
|
|
window via `startdesk()` (full toolset chain), runs a TaskMaster
|
|
event loop until the close box / Q key / 1000-iteration watchdog
|
|
fires. Both 6.0.2 (`sys602.po`) and 6.0.4 (`6.0.4 - System.Disk.po`)
|
|
launch it cleanly; fTitle works on both.
|
|
|
|
### `frame.c`
|
|
|
|
Full port of ORCA-C's `Frame.cc` sample. Builds the
|
|
Apple+File+Edit menu bar via the real ROM Menu Manager
|
|
(`NewMenu` / `InsertMenu` / `FixAppleMenu` / `FixMenuBar` /
|
|
`DrawMenuBar`) and renders the original "About Frame" dialog
|
|
(white-filled framed rect with the 1989 Byte Works copyright
|
|
text and an OK button).
|
|
|
|
### `minicad.c`
|
|
|
|
Full port of ORCA-C's `MiniCAD.cc` sample. Apple+File+Edit+
|
|
Options menu bar + a windowed canvas with three seeded line-art
|
|
patterns (curve-stitching, sunburst, Star of David).
|
|
|
|
### `reversi.c`
|
|
|
|
Full Othello game ported from ORCA-C's `Reversi.cc`. 100-byte
|
|
sentinel-bordered board, 8-direction capture detection, 1-ply
|
|
AI with corner/edge weighting, QD-rendered board with black/white
|
|
pieces.
|
|
|
|
### `qdProbe.c`
|
|
|
|
Diagnostic — minimal QD/EM/WM init followed by `RefreshDesktop`
|
|
plus ZP/SHR markers. Used to prove that `WindStartUp` does NOT
|
|
auto-paint the desktop and that `RefreshDesktop(NULL)` is what
|
|
actually fills SHR with the dithered desktop pattern. Run via
|
|
`scripts/probeQdStartup.sh`.
|
|
|
|
### Known limitations
|
|
|
|
- **fTitle on stripped 6.0.2:** orcaFrame uses fTitle and runs
|
|
fine on both 6.0.2 sys602.po and 6.0.4 System.Disk.po. Earlier
|
|
notes that fTitle required disk fonts were superseded — the
|
|
underlying bug was a `QDStartUp` argument-order mistake in
|
|
`runtime/src/desktop.c`, fixed 2026-05-16.
|
|
- **Window not visually painted:** `WindStartUp` does NOT paint
|
|
the desktop on its own; `RefreshDesktop(NULL)` is required.
|
|
Adding the call to `startdesk()` works for `qdProbe.c` but
|
|
pushes the orca demos past the GS/OS Loader's silent-rejection
|
|
threshold (see memory: `loader-creloc-threshold`).
|
|
- **GS/OS Loader cRELOC threshold:** anywhere from 65-90 cRELOCs
|
|
the Loader silently refuses to launch ExpressLoad OMFs. The
|
|
threshold is not a clean reloc-count cutoff; OMF byte layout
|
|
and reloc patch offsets both matter. The ORCA ports are slim
|
|
to stay under it.
|
|
|
|
## What got fixed during demo authoring
|
|
|
|
Substantive toolchain bugs surfaced and fixed:
|
|
|
|
- `iigsGsos.s` GS/OS wrappers and `genToolbox.py`'s 890 toolbox
|
|
wrappers were pushing 4-byte Long args low-word-first. ORCA-C's
|
|
PushLong macro is high-word-first. Anything passing a Long arg
|
|
through the toolbox dispatcher (NewHandle, NewWindow,
|
|
fopen->gsosOpen, etc.) was reading garbage parm-block pointers.
|
|
Fixed in both files plus the generator; regenerated 890
|
|
wrappers.
|
|
- `runtime/build.sh` wasn't rebuilding `iigsToolbox.s` -- the .o
|
|
was stale since May 4. Added the missing line.
|
|
- `(short)(*(void **)dpHandle)` was a double-dereference bug that
|
|
read garbage at the master pointer's destination instead of the
|
|
master pointer VALUE (= the DP address). Corrected to
|
|
`(unsigned short)(unsigned long)*(void **)dpHandle` for proper
|
|
block-address extraction.
|
|
- `helloText` used `TextStartUp + WriteCString` directly which
|
|
crashed to the IIgs monitor; fixed by adding `SetOutputDevice(1, 0)`
|
|
to wire stdout to the text screen.
|
|
- `helloText`'s event loop hung forever because `EMStartUp` wasn't
|
|
being called; fixed by adding it (with proper DP allocation).
|
|
|
|
## ptr32 mode note
|
|
|
|
All address constants in the demos (text screen $00:0400, SHR
|
|
RAM $E1:2000, soft switches $00:C0xx, keyboard register $00:C000)
|
|
are plain C 32-bit pointers like `(volatile unsigned char *)0xE12000UL`.
|
|
In ptr32 mode the compiler emits LONG addressing automatically;
|
|
no `switchToBank2`-style inline asm or DBR juggling required.
|