Z-machine
The Z-machine is a virtual machine developed by Joel Berez and Marc Blank in autumn 1979 for Infocom, Inc., designed to interpret bytecode (known as Z-code) compiled from the Zork Implementation Language (ZIL) and enable portable execution of interactive fiction games across diverse computer platforms without requiring recompilation.[1] Its core purpose was to adapt the mainframe-based adventure game Zork for early personal computers, such as the TRS-80 and Apple II, by abstracting hardware differences into a unified interpretive environment.[1] Over its active development period from 1979 to 1989, the Z-machine evolved through six primary versions, each enhancing capabilities like memory management, text compression, object handling, and input/output operations to support increasingly complex games.[1] Versions 1 through 3 focused on basic text adventures with features such as a stack-based instruction set, a dictionary for parsing commands, and an object tree for game world modeling, while later iterations (4 through 6) introduced support for graphics, sound effects, mouse input, and larger file sizes to accommodate titles like Zork Zero.[1] This progression allowed Infocom to release over 30 commercial games, including classics such as The Hitchhiker's Guide to the Galaxy and Trinity, all encoded in Z-code files that could be run via platform-specific interpreters like ZIP for early versions or YZIP for graphical ones.[1] Following Infocom's closure in 1989, the Z-machine's legacy was preserved and expanded through community efforts, notably the reverse-engineering and formal standardization led by Graham Nelson and Mark Howell between 1994 and 1995.[2] Nelson's Z-machine Standards Document (first released in 1995 and updated through version 1.1 in 2006) meticulously defined the machine's opcodes, memory layout, and behaviors across all eight versions (including non-Infocom extensions 7 and 8 for larger programs), ensuring full interpreter compatibility and portability.[2] This built upon Nelson's earlier creation of the Inform authoring system in 1993, which had initiated reverse-engineering of the Z-machine and compiles modern interactive fiction to Z-code, resulting in thousands of additional games and sustaining the format's use in freeware interpreters today.[2]Overview
Definition and purpose
The Z-machine is a stack-based virtual machine developed by Joel Berez and Marc Blank for Infocom in 1979 to execute interactive fiction games, particularly text-based adventures like Zork.[1][3] It interprets bytecode compiled from game source code, allowing programs to operate as if on a dedicated hardware platform regardless of the host system.[4] The primary purpose of the Z-machine was to enable portability of Infocom's games across diverse hardware environments without requiring recompilation for each platform, such as the Apple II, TRS-80, and CP/M systems.[5][3] By abstracting hardware differences through interpretation, it addressed the challenges of limited memory (often 32K or less) and incompatible architectures prevalent in the late 1970s personal computing landscape, ensuring games could reach a broad audience efficiently.[6] In the context of interactive fiction, the Z-machine supports parser-driven narrative experiences where players input natural language commands to interact with a simulated world, managing input/output operations, story logic, object interactions, and resource allocation within constrained environments.[6] This design facilitated immersive, text-only adventures that emphasized exploration and puzzle-solving, with the machine handling the underlying simulation to maintain consistency across play sessions.[1] The Z-machine's initial development was tied to the porting of Zork, originally created as a mainframe game between 1977 and 1979, with Infocom formalizing the system for commercial release by 1980 and stabilizing its core design around 1981.[3][5]Key features
The Z-machine employs a stack-based architecture to manage game state, object manipulation, and routine calls, enabling efficient handling of recursive operations and local variables within constrained memory environments.[7] This design includes packed addressing schemes, such as 2-byte packing in early versions, which optimize memory usage by compressing routine and string addresses into fewer bytes.[7] Text output in the Z-machine is facilitated through ZSCII encoding, a 10-bit character system that supports ASCII-like values alongside extensions for international characters and control codes, allowing for compact storage of game narratives.[7] Dynamic vocabulary tables enable flexible parsing of player input by storing word dictionaries in memory, while built-in save and restore mechanisms in all versions, with undo added from version 5, preserve the execution state—including the stack, program counter, and dynamic memory—for seamless game resumption.[7] Portability is a core strength of the Z-machine, achieved through its bytecode format (Z-code), which remains independent of the host operating system, with interpreters responsible for platform-specific input/output operations like screen display and keyboard handling.[7] This abstraction layer allowed games to run across diverse hardware without recompilation.[7] The system incorporates multimedia features starting from Version 3, including sound effects via dedicated opcodes that support volume control and repetition; Version 6 adds graphics capabilities for displaying images and menu systems for user navigation.[7] Early versions impose a 64KB limit on low memory (dynamic and static), supporting story files up to 128KB overall, though later iterations expand this up to 512KB.[7][8] Error handling is integrated into the Z-machine's design, with mechanisms to detect and halt on invalid operations like division by zero or illegal opcodes, alongside debugging hooks such as verification routines for integrity checks during execution.[7] These features ensure robust performance in interactive fiction, a design later adopted and extended by tools like Inform for broader development.[7]Development history
Origins at Infocom
Infocom was founded on June 22, 1979, by a group of MIT graduates including Tim Anderson, Joel Berez, Marc Blank, Mike Broos, Scott Cutler, Stu Galley, and Dave Lebling, primarily to commercialize interactive adventure games stemming from their work on Zork at MIT's Dynamic Modeling Group.[9][10][11] The company emerged from the need to adapt mainframe-based software for emerging personal computers, with Zork serving as the foundational project.[12] In the pre-Z-machine era, Zork I, II, and III were developed between 1977 and 1979 in the MDL (MUDDLE) programming language for the DEC PDP-10 mainframe, resulting in a sprawling game exceeding 1 MB that was distributed via ARPANET.[5][9][10] Porting this code to microcomputers like the Apple II and TRS-80 proved challenging, as the games far exceeded the typical 16-32 KB memory limits of these systems, necessitating extensive manual rewriting and truncation that consumed months of effort per platform and introduced inconsistencies across versions.[5][11] These portability issues highlighted the limitations of direct code translation from a mainframe environment to diverse, resource-constrained hardware.[12] To address these challenges, Infocom decided around 1979-1981 to develop the Z-machine, a virtual machine architecture designed to generate a single, platform-agnostic story file that could be interpreted by lightweight, machine-specific executables, thereby automating and streamlining the porting process.[5][11] The Z-machine debuted with the 1980 release of Zork I for personal computers, but its full implementation appeared in 1982 titles such as Deadline, a detective adventure by Marc Blank, and Starcross, a science fiction game by Dave Lebling, marking the first productions fully leveraging the system for efficient cross-platform deployment.[5][9] Infocom's business model centered on releasing high-quality text adventures simultaneously across dozens of platforms—over 30 by the mid-1980s—including the Apple II, Atari 8-bit, Commodore 64, and IBM PC, which drove strong sales, with Zork I exceeding 400,000 copies.[9][12][13] The Z-machine drastically reduced porting times from months of manual labor to mere days, as developers compiled once into a universal format while interpreters handled hardware variations, enabling rapid market expansion and cost efficiencies that sustained Infocom's growth through the early 1980s.[5][11] A key milestone was the maturation of Z-machine Version 3 by the mid-1980s, which became the standard for most of Infocom's classic titles, supporting up to 255 rooms and 255 objects to accommodate more complex narratives and interactions within memory constraints.[5][14] This version powered iconic games like The Hitchhiker's Guide to the Galaxy and Trinity, solidifying the Z-machine's role in enabling sophisticated interactive fiction without platform-specific rework.[12]ZIL and compilation tools
The Zork Implementation Language (ZIL) was a high-level programming language developed by Infocom for authoring interactive fiction games targeted at the Z-machine virtual machine. Derived from MDL, a dialect of Lisp used in early Zork development on the PDP-10 mainframe, ZIL adopted a prefix notation and parenthetical syntax to define game elements such as rooms, objects, actions, and parser behaviors. It supported routines for procedural logic, properties for object attributes, and global variables for state management, enabling developers to model complex worlds with interconnected elements like inventories, locations, and verb-object interactions. Prior to ZIL, Infocom prototyped games in MDL, but ZIL streamlined the process by stripping unnecessary features for more efficient code generation.[15][5] ZIL's syntax emphasized declarative structures; for instance, objects were defined using the<OBJECT> form with properties like LOC for location, DESC for descriptions, FLAGS for attributes (e.g., TAKEBIT for portable items), and ACTION for custom routines triggered by player input. Routines followed the form <ROUTINE NAME (ARG1 ARG2) <body>>, where the body could include conditionals via COND, output with TELL, and returns with RTRUE or RFALSE. Global states were managed through variables prefixed with commas (e.g., ,HERE for the current room), and the parser tokenized input into semantic units like PRSA (action verb), PRSO (direct object), and PRSI (indirect object) for processing commands. Technical conventions in ZIL included Easter eggs like "zorkmid" as a unit of currency in object properties, reflecting Infocom's playful nomenclature while maintaining consistent property numbering across objects within a game.[15][16]
A representative example of ZIL code for handling a basic movement command like "go north" involves room properties and a generic walk routine. A room might be defined as <ROOM LIVING-ROOM (DESC "You are in the living room.") (NORTH TO [KITCHEN](/page/Kitchen)) (FLAGS LIGHTBIT)>, where the parser sets PRSA to V?WALK and PRSO to P?NORTH. The movement routine then checks: <ROUTINE GO? (DIRECTION) <COND (<GETP ,HERE ,DIRECTION> <GOTO .?>) (T <TELL "You can't go that way." CR> <RFALSE>)>>, executing the transition if the directional property (e.g., NORTH) exists. This structure allowed for conditional exits, such as (NORTH TO [KITCHEN](/page/Kitchen) IF UNLOCKED ELSE "The door is locked.").[15]
The compilation pipeline for ZIL began with source files written in the language, which were processed by ZILCH, the primary compiler, to generate Z Assembly Language code (often in .ZAP files). ZILCH handled macro expansion, optimization, and intermediate representation, producing assembly that could be manually edited for fine-tuning. The Z Assembly Language was then assembled by ZAP (Zork Assembler Program) into the final Z-code story file, a compact, machine-independent binary executable for the Z-machine. ZILCH also included utilities for generating headers and managing build configurations, though it was tightly integrated with the PDP-10 environment initially. This toolchain formed a closed ecosystem at Infocom, requiring developers to optimize memory usage manually due to ZIL's verbose syntax and the constraints of early Z-machine versions, such as limited object counts and string storage.[17][16][18]
ZIL and its tools remained proprietary to Infocom throughout the company's operation, used exclusively by in-house authors for all 32 major releases from 1979 to 1989. The language's reliance on Lisp-like evaluation and manual interventions for packing objects into memory slots made it powerful for narrative depth but demanding for efficiency, often necessitating iterative compilation to fit within Z-machine limits like 64 KB for version 3 games. Infocom's shutdown in 1989 marked the end of active ZIL development, leaving the tools inaccessible until source code leaks and reverse-engineering efforts in the 2010s.[5][19]
Expansion via Inform
Following Infocom's acquisition by Activision in 1986 and the subsequent closure of its operations in 1989, the Z-machine entered a period of dormancy, with no new official developments or tools emerging from the company.[20][21] This changed in 1993 when Graham Nelson created Inform as a modern authoring system specifically targeting the Z-machine, enabling hobbyists and independent developers to produce interactive fiction in the established format.[22][23] Inform 6, released in 1996, further standardized Z-machine Versions 1 through 8 by incorporating extensions for larger story files in Versions 7 and 8 while maintaining compatibility with earlier versions.[24][25] Key features of Inform included a simplified, higher-level syntax that was more intuitive and accessible than Infocom's proprietary ZIL, reducing the need for low-level programming through an extensive library of predefined objects, actions, and parsing rules; support for modular extensions to customize game mechanics; and the Z-machine as the primary output format.[26][27] The Z-machine remained Inform's default target until 2006, when support for the Glulx virtual machine—designated informally as Version 10—was added in Inform 7 to accommodate larger games and modern features beyond Z-machine limits.[28] Nelson's standardization efforts culminated in the Z-machine Standards Document (version 1.0 released in 1996 and updated to version 1.1 in 2006), which formally documented opcodes, memory organization, the ZSCII character encoding, and other technical details, providing a comprehensive reference that facilitated community-driven implementations and ensured long-term portability.[25][29] This specification, building on earlier drafts from 1995, helped establish de facto standards within the emerging interactive fiction community, enabling consistent interpreter development and game creation without proprietary restrictions.[25] The adoption of Inform revitalized the Z-machine in the 1990s and 2000s, leading to the creation of thousands of free interactive fiction games, such as Curses! (1993) by Nelson himself and later works like Anchorhead (1998) by Michael Gentry, which leveraged the format's portability and the tools' ease of use to foster a vibrant, non-commercial scene. As of 2025, Inform remains actively maintained, with the latest Inform 7 release (version 10.1.2) in September 2024 supporting Z-machine output alongside Glulx.[30][31][32][33]Technical architecture
Versions and standards
The Z-machine evolved through eight versions developed primarily by Infocom between 1979 and 1988, with versions 7 and 8 added later by Graham Nelson to support larger games created using the Inform system. Version 1, introduced in autumn 1979 by Joel Berez and Marc Blank, provided basic text handling capabilities, including a header, divided memory layout, variables and stack, object tree, dictionary, and instruction format, along with "shift lock" characters for text compression.[1] Version 2 followed as a minor update, introducing a 32-word abbreviation bank and a six-digit serial number in the header.[1] Version 3, established by March 1982 and used until November 1987, became the most common format for Infocom games such as Deadline and Zork I, dropping shift lock compression in favor of 96 abbreviation entries, adding the "verify" opcode for checksums, and supporting status line reprinting; it limited story files to 128 KB total, with approximately 64 KB allocated to dynamic memory.[1][8] Version 4, released in August 1985 with A Mind Forever Voyaging, enhanced dictionary handling to address size restrictions of prior versions, while expanding the maximum story file size to 256 KB.[1][8] Version 5, introduced in September 1987 for titles like Beyond Zork and Border Zone, incorporated calculated addresses, character graphics, real-time keyboard input, additional opcodes, and support for 9-letter words in the dictionary, maintaining the 256 KB file limit.[1][8] Version 6, deployed in 1988 for games including Zork Zero and Shogun, added graphics support via opcodes such as @picture, mouse input, menus, sound, and a computationally advanced parser, doubling the story file size to 512 KB.[1][34] Versions 7 and 8, devised by Nelson in 1995, extended the 512 KB limit of version 6 but were otherwise similar to version 5, with version 7 rarely used and version 8 applied nichely to large Inform-generated games requiring packed address scaling (e.g., byte address B = 8P for version 8).[35][8] These versions introduced compatibility levels where interpreters must handle earlier formats, with dynamic and static memory combined not exceeding 64 KB across all versions, though total file sizes varied.[8] Infocom maintained informal specifications for the Z-machine internally, without public documentation, until Nelson formalized them in The Z-Machine Standards Document, first released in draft form (version 0.2) in November 1995 and updated to version 1.0 around 1996, and version 1.1 in May 2006 (revised February 2014).[2] This document standardized elements across versions 1 through 8, including header formats (e.g., release number and serial code in YYMMDD format like 970619), opcode behaviors, memory organization, and expansion provisions for features like graphics.[2][8] Community extensions, such as the Quetzal save-file format (version 1.4, November 1997), further standardized portable save states across interpreters by defining Interchange File Format (IFF) chunks for memory and stack data, addressing Infocom's proprietary save incompatibilities.[36]Memory organization
The Z-machine employs a contiguous block of memory divided into distinct regions to support the execution of interactive fiction games, with the entire story file typically loaded into memory at startup. The layout begins with a fixed 64-byte header at address 0, which contains essential metadata including the machine version, memory configuration pointers, and a checksum for integrity verification. Following the header is dynamic memory, a writable region starting immediately after byte 63 and extending to the address specified in header word $0E (multiplied by 2 for byte addressing), used for mutable game state such as the object table and global variables. Static memory, which is read-only, occupies the subsequent region up to the start of high memory (indicated by header word $04 multiplied by 2), housing permanent data structures like the vocabulary dictionary and grammar tables. High memory, accessed indirectly, holds read-only code and resources including routines, Z-strings, and the call stack, extending to the end of the allocated memory block.[7][37] Addressing in the Z-machine distinguishes between direct byte or word addresses in the lower memory regions and packed addresses for high memory to optimize space in the compact story files. Byte addresses are straightforward unsigned values for accessing dynamic and static memory, while word addresses represent even byte locations (multiplied by 2). Packed addresses, encoded in 1 to 4 bytes depending on the version, are unpacked via version-specific multipliers—such as multiplying by 2 for versions 1–3 or by 4 for versions 4–5—to compute locations in high memory, with versions 6–7 adding header-based offsets and version 8 using multiplication by 8. This scheme enables efficient referencing of routines and strings while limiting total memory; for example, version 3 supports up to 128 KB overall, with dynamic memory configurable but often around half that size in practice.[7][37] Key data structures are allocated within these regions to manage game elements efficiently. The object table resides in dynamic memory (starting at the address in header word $0A), forming a hierarchical tree where each object entry includes attributes (bit flags for state, up to 48 in later versions), links to parent, sibling, and child objects, and pointers to property lists containing numerical or textual data; versions 1–3 limit objects to 255 with 9-byte entries, while versions 4+ expand to 65,535 objects using 14-byte entries. The dictionary, located in static memory (at header word $08), stores hashed vocabulary words as Z-character encoded strings for input parsing, typically supporting hundreds of entries sorted alphabetically, with entry sizes of 4 bytes in early versions increasing to 6 in later ones. Routine frames are pushed onto the call stack in high memory during execution, each comprising the return program counter, 0–15 local variables, and an evaluation stack for temporary values; the evaluation stack supports up to 256 entries across frames, though the overall call stack depth is limited only by available memory.[7][37] Resource management in the Z-machine relies on manual allocation by game authors, as no automatic garbage collection is provided, requiring careful packing of data to minimize fragmentation and fit within memory constraints. Dynamic memory serves as a heap for runtime modifications, such as updating object attributes or allocating temporary storage, but authors must pre-arrange layouts to avoid exhaustion during play. File I/O is handled by loading the complete story file into memory upon initialization, with save states preserving the dynamic region; interpreters manage high memory access transparently, but fragmentation from stack growth or property additions can necessitate compression techniques in game design. Version-specific memory sizes influence these limits, such as 128 KB total for version 3 compared to 256 KB for version 5.[7][37] To illustrate the conceptual memory map:- Header (0–63 bytes): Configuration and pointers.
- Dynamic Memory (~64 bytes to ~32–64 KB): Writable heap (objects, globals); grows/shrinks via game logic.
- Static Memory (~32–64 KB to ~64–128 KB): Read-only data (dictionary, grammar); fixed at compile time.
- High Memory (~64–128 KB to end): Code and stack (routines, strings); indirect access via packing.
Instruction set and execution
The Z-machine employs an opcode-based instruction set where each instruction is encoded as a variable-length sequence ranging from 1 to 9 bytes, with opcodes numbered from 0 to 255.[38] These opcodes are divided into forms based on the number and types of operands: zero-operand (0OP), one-operand (1OP), two-operand (2OP), variable number of operands (VAR), and extended opcodes (EXT, introduced via a special prefix in Version 5 and later).[39] Common categories include stack operations such as @add (adds two values and stores the result) and @sub (subtracts one value from another), branching instructions like @je (jumps if the first operand equals any subsequent operand) and @jl (jumps if the first operand is less than the second), object manipulation opcodes including @get_prop (retrieves a property value from an object), and input/output commands such as @print (outputs a literal string) and @call (invokes a routine with arguments).[38][39] The execution model follows a classic fetch-decode-execute cycle within an interpreter loop, where the program counter (PC) points to the current instruction in the high memory region containing the game's code.[40] The interpreter fetches the opcode and operands from memory at the PC location, decodes them to determine the operation and data types (such as small constants of 0-255, large constants of 0-65535, or variables), executes the instruction, and then advances the PC to the next byte position unless branching occurs.[38] Branching uses a 1- or 2-byte offset after the operands; the high bit of the first byte (bit 7) is 0 to branch if the condition is false or 1 to branch if true. If the branch is taken, for a 1-byte offset O (0 to 63): if O=0, execute rfalse; if O=1, execute rtrue; otherwise, set PC to the position immediately after the branch data plus (O - 2). For 2-byte offsets, the offset is a signed 14-bit value with analogous special cases and adjustment by -2.[38] Stack operations form a core part of the instruction set, supporting zero-operand instructions that implicitly use the evaluation stack (a last-in, first-out structure for temporary values), one-operand forms that take a single operand and often push or pop from the stack, two-operand instructions that operate on two explicit values, and variable forms that specify the number of operands in a following byte.[38] For instance, @store (opcode 13 in 2OP form) takes a variable and a value, storing the latter into the former to update game state such as player location or inventory flags, while implicitly managing stack pushes for intermediate results in expressions.[39] Operand types are encoded efficiently: variables are referenced by a 1-byte index (0 for the stack top, 1-255 for local or global variables), allowing compact representation without direct memory access.[38] Flow control is managed through dedicated opcodes for subroutine calls, unconditional jumps, and exception handling. Routine calls like @call (VAR form, opcode 224) push the return address and up to three arguments (or more in extended versions) onto the stack before transferring control to the routine's address, with results optionally stored upon return.[39] Loops and unconditional branches use @jump (1OP, opcode 140), which sets the PC to the current position plus a signed offset for arbitrary control flow.[39] In Versions 5 and later, error handling is supported by @catch (0OP, opcode 185 in V5/6), which pushes the current stack frame pointer for later use, and @throw (2OP, opcode 28), which unwinds the stack to a specified frame and returns a value.[39] Unique to the Z-machine is its lack of interrupts, ensuring uninterrupted execution except for explicit operations like sound completion callbacks in later versions, which promotes predictable behavior.[40] This deterministic model facilitates save and restore functionality: saves capture the full memory state and stack, while restores resume from the saved PC with an empty stack, guaranteeing identical execution paths across interpreters.[40] The following table summarizes the standard opcodes by form and category, with decimal numbers, hexadecimal equivalents, store/branch capabilities (St for result storage, Br for conditional branching), and representative Inform assembly syntax for clarity. Illegal opcodes in a given version cause interpreter errors. The extended opcodes (EXT, prefixed by 190) are listed separately for versions 5+, including only defined standard ones.[39]| Form | Decimal Range | Hex Range | St/Br | Category Examples (Opcode: Name - Syntax) |
|---|---|---|---|---|
| 2OP (Long form, small/variable operands) | 0-31 (small const, small const) 32-63 (small const, variable) 64-95 (variable, small const) 96-127 (variable, variable) | 0x00-0x1F 0x20-0x3F 0x40-0x5F 0x60-0x7F | Varies | Branch: 1: je a b ?L; 2: jl a b ?L; 3: jg a b ?L; 6: jin obj1 obj2 ?L; 7: test bitmap flags ?L; 10: test_attr obj attr ?L Object: 11: set_attr obj attr; 12: clear_attr obj attr; 14: insert_obj obj dest; 17: get_prop obj prop -> r; 18: get_prop_addr obj prop -> r; 19: get_next_prop obj prop -> r Stack/Math: 8: or a b -> r; 9: and a b -> r; 13: store var val; 15: loadw arr idx -> r; 16: loadb arr idx -> r; 20: add a b -> r; 21: sub a b -> r; 22: mul a b -> r; 23: div a b -> r; 24: mod a b -> r Flow: 25: call_2s rout arg -> r; 26: call_2n rout arg; 27: set_colour fg bg (V5+); 28: throw val frame (V5+) Check: 4: dec_chk var val ?L; 5: inc_chk var val ?L |
| 1OP (Short form, large/small/variable operands) | 128-143 (large const) 144-159 (small const) 160-175 (variable) | 0x80-0x8F 0x90-0x9F 0xA0-0xAF | Varies | Branch/Object: 128: jz a ?L; 129: get_sibling obj -> r ?L; 130: get_child obj -> r ?L Object: 131: get_parent obj -> r; 132: get_prop_len addr -> r Stack: 133: inc var; 134: dec var; 142: load var -> r; 143: not val -> r (V3/4; VAR in V5+) I/O: 135: print_addr addr; 141: print_paddr paddr Flow/Object: 136: call_1s rout -> r; 137: remove_obj obj; 138: print_obj obj; 139: ret val; 140: jump ?L |
| 0OP (No operands) | 176-191 (except 190=EXT) | 0xB0-0xBF | None (except Br on some) | Flow/I/O: 176: rtrue; 177: rfalse; 178: print "str"; 179: print_ret "str"; 180: nop; 183: restart; 184: ret_popped; 186: quit; 187: new_line; 188: show_status (V3+); 191: piracy ?L (V5+) Stack: 185: pop (V1-4; catch in V5/6) Save: 181: save ?L (V1-4); 182: restore ?L (V1-4); 189: verify ?L (V5; unused in V1-4) |
| VAR (Variable operands, types in next 1-2 bytes) | 192-223 (2OP) 224-255 (VAR/EXT prefix) | 0xC0-0xDF (2OP) 0xE0-0xFF (VAR) | Varies | Branch: 193: call_1n rout ?L (V4+; illegal V1-3); 194: remove_obj obj ?L (V4+); 195: print_obj obj ?L (V4+); 196: ret val ?L (V4+); 197: jump ?L (V4+); 198: print_paddr paddr ?L (V4+) Store: 199: load var -> r ?L (V4+); 200: not val -> r ?L (V5/6) I/O: 201: call rout -> r ?L (V4+); 202: store var val ?L (V4+); 203: insert_obj obj dest ?L (V4+); 204: loadw arr idx -> r ?L (V4+); 205: loadb arr idx -> r ?L (V4+); 206: get_prop obj prop -> r ?L (V4+); 207: get_prop_addr obj prop -> r ?L (V4+); 208: get_next_prop obj prop -> r ?L (V4+); 209: add a b -> r ?L (V4+); 210: sub a b -> r ?L (V4+); 211: mul a b -> r ?L (V4+); 212: div a b -> r ?L (V4+); 213: mod a b -> r ?L (V4+) Flow: 214: call_vs rout -> r (V4+); 215: store var val (V5+); 216: insert_obj obj dest (V5+); 217: loadw arr idx -> r (V5+); 218: loadb arr idx -> r (V5+); 219: get_prop obj prop -> r (V5+); 220: get_prop_addr obj prop -> r (V5+); 221: get_next_prop obj prop -> r (V5+); 222: set_attr obj attr ?L (V5+); 223: clear_attr obj attr ?L (V5+); 224: call_vs rout -> r (V5+); 225: store var val (V6+); 226: insert_obj obj dest (V6+); 227: loadw arr idx -> r (V6+); 228: read table parse (V5+; aread in Inform); 229: print_char ch (V5+); 230: print_num val (V5+); 231: random num -> r (V5+); 232: split_window lines (V4+); 233: set_window win (V4+); 234: output_stream num table (V5+; - in V4); 235: input_stream num (V5+); 236: call_vs2 rout -> r (V6+); 237: erase_window win (V6+); 238: erase_line value (V6+); 239: set_cursor_line row (V6+); 240: set_cursor_column col (V6+); 241: set_cursor_position row col (V6+); 242: buffer_mode on/off (V6+); 243: output_stream num table (V6+); 244: input_stream num (V6+); 245: set_font font -> r (V5+); 246: draw_picture pic y x (V6+); 247: picture_data table pic (V6+); 248: not val -> r (V6+); 249: call_vn rout (V6+); 250: call_vn2 rout (V7/8); 251: tokenise dict text parse (V5+); 252: encode_text dest src len (V5+); 253: copy_table dest src size (V5+); 254: print_table addr size table (V7+); 255: check_arg_count num ?L (V7+) |
| EXT (Byte 190 prefix + 0-255 number; V5+) | N/A (second byte 0-255) | N/A | Varies | 0: save table bytes name prompt -> (result) (V5); 1: restore table bytes name prompt -> (result) (V5); 2: log_shift number places -> (result) (V5); 3: art_shift number places -> (result) (V5+); 4: set_font font -> (result) (V5+); 5: draw_picture picture-number y x (V6); 6: picture_data picture-number array ?(label) (V6); 7: erase_picture picture-number y x (V6); 8: set_margins left right window (V6); 9: save_undo -> (result) (V5); 10: restore_undo -> (result) (V5); 11: print_unicode char-number (V5+); 12: check_unicode char-number -> (result) (V5+); 13: set_true_colour foreground background (V5+); 16: move_window window y x (V6); 17: window_size window y x (V6); 18: window_style window flags operation (V6); 19: get_wind_prop window property-number -> (result) (V6); 20: scroll_window window pixels (V6); 21: pop_stack items stack (V6); 22: read_mouse array (V6); 23: mouse_window window (V6); 24: push_stack value stack ?(label) (V6); 25: put_wind_prop window property-number value (V6); 26: print_form formatted-table (V6); 27: make_menu number table ?(label) (V6); 28: picture_table table (V6); 29: buffer_screen mode -> (result) (V6+). Opcodes 14-15, 30-255 are reserved or undefined in the standard (50-127 reserved, 128-255 user-defined). |