If you are building an application that uses Zorb to compile Z-machine stories, follow these rules and conventions.
Core Mandates for Consumers
- Z-Machine Versions: Zorb supports Versions 1-5 and 7-8. Version 6 is not supported. Ensure your story files match these versions.
- WASM Interface: Zorb generates WASM Game Capsules that follow the
ziohost interface. You must provide a host environment (in Elixir, JavaScript, or another WASM-capable language) to execute these capsules. - Compilation Method: Zorb uses a WASM patcher by default for ~1ms compilation. Use
method: :traditionaloption for debugging if needed.
Elixir Integration
Compiling a Story
Use Zorb.compile/2 to generate a WebAssembly binary.
# Fast patcher-based compilation (~1ms)
wasm_bytes = Zorb.compile("path/to/zork1.z3", cache: true)
# Traditional compilation for debugging (~4s)
wasm_bytes = Zorb.compile("path/to/zork1.z3", method: :traditional)Analyzing Story Metadata
Use Zorb.metadata/1 to extract semantic metadata (e.g., for Orbit Radio) from a story file.
meta = Zorb.metadata("path/to/story.z5")
# => %{command_prefix: 47, chat_prefix: "ORB", channel_prefix: "SOULS", ...}Cache Management
To clear all compiled capsules and temporary artifacts:
Zorb.clear_cache()To prune the cache based on usage (LRU):
Zorb.prune_cache(max_files: 50)
Zorb.prune_cache(max_size: 1024 * 1024 * 100) # 100MB
Zorb.prune_cache(older_than: 3600 * 24 * 7) # 1 weekCache files are "touched" on every cache hit, ensuring that active story files are retained during pruning.
Configuration
You can configure Zorb in your config/config.exs:
config :zorb,
working_dir: "/tmp/zorb_artifacts",
cache_dir: "/tmp/zorb_cache"Host Interface (Advanced)
Zorb produces Game Capsules that export a set of zio_ prefixed functions. These can be used to drive the interpreter from a custom Host environment.
Exported WASM Interface
All capsules export the following functions:
zio_save() -> i32: Triggers a save.zio_restore() -> i32: Triggers a restore.zio_save_undo() -> i32: Triggers an undo save.zio_restore_undo() -> i32: Triggers an undo restore.zio_print_char(char: i32): Outputs a character.zio_print_num(num: i32): Outputs a number.zio_read_char() -> i32: Reads a character.zio_set_window(id: i32): Selects a window.zio_split_window(lines: i32): Splits the screen.zio_set_cursor(line: i32, col: i32): Moves the cursor.zio_erase_window(id: i32): Clears a window.zio_erase_line(val: i32): Erases a line.zio_set_text_style(style: i32): Sets text style.zio_set_colour(fg: i32, bg: i32): Sets colors.zio_sound_effect(id: i32): Plays sound.zio_get_screen_size() -> i32: Returns packed size.zio_get_capabilities() -> i32: Returns feature bitmask.zio_get_version() -> i32: Returns Z-machine version.zio_get_serial() -> i64: Returns 6-byte serial string packed in i64.zio_get_command_prefix() -> i32: Returns command prefix character.zio_get_chat_prefix() -> i64: Returns null-terminated chat tag packed in i64.zio_get_channel_prefix() -> i64: Returns null-terminated user label packed in i64.zio_halt(reason: i32): Terminates the VM.
Required Imports (The Host Interface)
The Host must provide the zio namespace with the following functions:
print_char(char: i32): Outputs a single ZSCII/Unicode character.print_num(num: i32): Outputs a signed 32-bit integer.read_char() -> i32: Waits for a single character input and returns its ZSCII value.get_random(max: i32) -> i32: Returns a random integer between 1 andmax.get_random_seed() -> i32: Returns a 32-bit integer to seed the PRNG.halt(reason: i32, pc: i32, opcode: i32): Called on fatal error orquit.sound_effect(number: i32): Plays a sound effect (1=High beep, 2=Low beep).check_interrupt() -> i32: (New) Polled by WASM to check for Host-triggered save/restore.0: No request.1: Save.2: Restore.3: Save Undo.4: Restore Undo.
Triggering External Operations (Custom Host)
If you are implementing a custom host and wish to trigger a save/restore from outside the Z-machine loop:
- When an external trigger occurs, return the corresponding code (1-4) from the next
check_interrupt()call. - The Game Capsule will then invoke the appropriate ZIO function (
save,restore, etc.). - If the Z-machine is currently waiting for input in
read_char(), you can return a special character code (0x101-0x104) fromread_char()to wake it up and trigger the interrupt immediately.
Optional Interface (Capabilities)
The Host can signal support for optional features via get_capabilities() -> i32 (bitmask):
0x01: Status line.0x02: Screen splitting.0x04: Variable-width font.0x08: Font 3 (Graphics).0x10: Color.0x20: Timed input.