zmachine5 — a Z-machine v5 interpreter for the 128K Apple //e
A complete Infocom Z-machine version 5 interpreter written in 6502
assembly (NMOS-only opcodes), targeting the Apple //e with 128K, conforming
to the Z-Machine Standards Document 1.1.
It boots from a ProDOS disk and plays real v5 games — including Beyond
Zork, reassembled from the original two-sided Apple II release.
|
|
 |
 |
| 9:05 by Adam Cadre on the //e |
Beyond Zork — “[UNDO completed.]” |
- czech.z5: 406/406 conformance tests passed — both under the PC-side
harness and on the emulated //e itself.
- praxix.z5: all tests passed (multi-level undo excepted, an optional
capability the suite itself notes is not required).
- Playable games: 9:05, Adventure (two-disk build), and Beyond Zork
(from an 800K hard-disk volume), all played interactively under MAME's
apple2e/apple2ee drivers and AppleWin.
- Full v5 opcode set: objects/properties, text with abbreviations and custom
alphabets, dictionary parsing (binary search on sorted dictionaries),
output stream 3 with 16-deep nesting, catch/throw (frame-index cookies),
scan/copy/print_table, terminating-characters tables, and the EXT set.
- 80-column two-window screen driver writing the text pages directly:
split windows, inverse video, word-wrap buffering, [MORE] paging, and a
line editor with delete/arrow handling.
- Demand paging: dynamic memory stays resident in main RAM; static/high
memory is served from a 512-byte-page LRU cache in auxiliary RAM, faulted
in from the story file through ProDOS MLI. 256K stories work on floppies
or hard-disk volumes.
- UNDO: single-slot state snapshot kept in aux RAM (carved from the page
cache), with the XZIP return conventions Beyond Zork actually probes for.
- Quetzal 1.4 saves (IFhd + UMem + Stks), interoperable with Frotz
in both directions — the reader also decodes CMem in place.
- Font 3 character graphics rendered with MouseText on the enhanced
//e / IIc (interpreter number 9, so Beyond Zork engages its on-screen map
and bar-chart UI).
- The interpreter reports itself as Standard 1.0, interpreter 9 'A'.
src/ 6502 source (ca65). main.s includes everything; plat_harness.s
and plat_apple.s are the two platform back-ends.
cfg/ ld65 linker configs (harness @ $0800; Apple SYS + LC bank 2).
harness/ PC-side test harness: a C 6502 emulator (Klaus-validated) with
trap-based I/O — the fast development loop.
games/ Freely-available test suites and story files.
tools/ Build scripts, disk builders, story extractor, header dumper.
docs/ DESIGN.md, implementation-focused spec notes, screenshots.
ref/ Z-Machine Standard 1.1 (HTML) and InterL3 (Infocom Apple disk
format reference).
main $0800-$3Fxx interpreter + buffers + Z-stack aux $0200-$07FF (80-col text)
main $41xx-$BEFF dynamic memory (up to ~32.5K) aux $0800-$BFFF story page cache
LC bank 2 $D000 screen driver + object/table ops + undo snapshot (top)
LC bank 1 ProDOS 8 (entered only via mli_go)
Bank 2 of the language card — the 4K ProDOS leaves free — is the machine's
resident state; every ProDOS call funnels through a single bank-switching
choke point. That reclaimed enough main RAM for Beyond Zork's 32,085 bytes
of dynamic memory.
Building (Windows; adjust paths for your setup)
Prereqs: cc65 (ca65/ld65), MSVC (for the
harness), Python 3, AppleCommander
(ac CLI in tools/), and a ProDOS 8 image to donate boot blocks + the
PRODOS file (see tools/mkdisk.sh).
sh tools/build_core.sh # harness build -> build/core.bin
harness/build.cmd # C harness -> build/harness.exe
build/harness.exe build/core.bin games/czech.z5 # run the suite
sh tools/build_apple.sh # Apple build -> build/interp.sys
sh tools/mkdisk.sh games/905.z5 build/zm905.po # 140K, one disk
sh tools/mkdisk2.sh games/Advent.z5 boot.po data.po # story on drive 2
sh tools/mkdisk800.sh games/beyondzork.z5 build/zmbz.po # 800K + .hdv
- AppleWin: AppleWin.exe -d1 build\zm905.po, or attach build\zmbz.hdv
as the hard disk and boot from it.
- MAME: mame apple2e -flop1 zm905.po, or for hard-disk volumes
mame apple2ee -sl6 cffa202 -hard1 zmbz.hdv (the unenhanced //e ROM only
boots slot 6, and cffa202 is the 6502-firmware CFFA — the 65C02 variant
won't boot an unenhanced machine). MouseText (Beyond Zork's map borders
and bar charts) needs the enhanced apple2ee.
The interpreter opens STORY on the boot volume, falling back to
/ZM2/STORY (a data disk in drive 2). Saves go to a SAVE file on the
boot volume in Quetzal format.
- Spec: Z-Machine Standards Document 1.1 (Graham Nelson et al.),
mirrored under ref/spec/.
- ref/interl3.c — InterL 3.0 by S. V. Nickolas, the definitive reference
for Infocom's Apple II disk formats (and the source of the side-B
long-track decoding used by tools/extract_bz.py).
- Test suites: CZECH (Amir Karger / Evin Robertson) and Praxix (Andrew
Plotkin / Dannii Willis), from the IF Archive.
- Story files: 9:05 © Adam Cadre (freeware); Adventure (Crowther &
Woods, Inform port); Beyond Zork © 1987 Infocom — included for
historical preservation, as widely mirrored online.
- Written almost entirely by Claude (Anthropic's Claude Code), pair-flown
by @hasseily, in one long session:
spec digestion → C harness → core → platform layer → emulator
verification, with an adversarial multi-agent review pass that caught
18 latent bugs the conformance suites couldn't see.