Copyright & Licensing --------------------- Copyright (C) 2024 Jason Self You can redistribute and/or modify this file under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file. If not, see . Chapter 1.1: Overview of ZAP and its Purpose -------------------------------------------- ZAP (Z-language Assembly Program) is a software tool used to translate assembly language code written for the Z-machine into a binary format that can be directly executed by a compatible Z-language Interpreter Program (ZIP). The Z-machine is a virtual machine specifically designed for running interactive fiction games, also known as text adventures. Infocom originally developed the Z-machine and its associated programming language, ZIL (Zork Implementation Language) but now these belong to the community. ZAP is the last stage of the toolchain, after the source code has been compiled into a a human-readable assembly language format. This assembly language is then processed by ZAP, which converts it into the binary format understood by the Z-machine. ZAP is a two-pass assembler, meaning it processes the input file twice. In the first pass, it analyzes the code, builds symbol tables, and calculates addresses. In the second pass, it generates the binary code and resolves any forward references to symbols. This specification document provides a detailed explanation of ZAP's functionality, including the supported assembly language syntax, data structures, algorithms, and error handling mechanisms. It serves as a guide for understanding and implementing ZAP. ZAP is an integral component of the development system for interactive fiction games. It bridges the gap between the high-level ZIL (Zork Implementation Language) and the low-level Z-code that runs on the Z-machine. Here's how ZAP fits into the overall development process: 1. **Game Design and Implementation:** Game designers and programmers use a high-level language (the Zork Implementation Language, or ZIL) to define the game's world, objects, characters, and interactions. ZIL provides a more abstract and convenient way to express the game's logic compared to directly writing Z-code instructions. 2. **ZIL Compilation:** The ZIL code is compiled into Z-code assembly language. This assembly language represents the Z-code instructions and data in a human-readable format. 3. **ZAP Assembly:** ZAP takes the Z-code assembly language as input and translates it into the binary format understood by the Z-machine. This binary code is what ultimately gets executed by the ZIP interpreter. Chapter 1.2: Goals and Design Principles of ZAP ----------------------------------------------- ZAP was designed with several key goals and principles in mind: **Goals:** - **Provide a convenient and efficient way to write Z-code programs:** ZAP's assembly language allows programmers to express Z-code instructions and data in a more readable and structured format compared to directly writing binary code. - **Generate optimized and efficient Z-code:** ZAP optimizes the generated code for efficient execution on the Z-machine, ensuring smooth gameplay and minimizing memory usage. - **Support debugging and troubleshooting:** ZAP can generate optional listing files that provide insights into the generated code, aiding in debugging and identifying issues. - **Maintain portability across different platforms:** ZAP itself is designed to be portable and run on various machines, allowing for cross-platform development. **Design Principles:** - **Simplicity and clarity:** ZAP's assembly language syntax is designed to be straightforward and easy to understand, minimizing the learning curve for programmers. - **Efficiency:** ZAP optimizes the generated code for efficient execution on the Z-machine, taking advantage of the architecture's features. - **Flexibility:** ZAP provides various directives and options to give programmers control over the assembly process and allow for customization. - **Error detection and reporting:** ZAP incorporates robust error detection mechanisms and provides informative error messages to help programmers identify and fix issues. - **Modularity:** ZAP is organized into well-defined modules, each responsible for specific tasks, promoting code maintainability and extensibility. These goals and design principles have guided the development of ZAP and continue to be relevant in understanding its functionality and behavior. By adhering to these principles, ZAP provides a powerful and efficient tool for assembling Z-code programs for interactive fiction games. Chapter 1.3: Target Audience for the Specification -------------------------------------------------- This specification document is primarily intended for the following audiences: - **Z-machine enthusiasts and researchers:** The specification offers detailed insights into the Z-code assembly language, ZAP's internal workings, and the overall structure of Z-machine programs. This information can be valuable for individuals interested in understanding the Z-machine architecture and its associated tools. - **Interactive fiction developers:** Understanding ZAP's functionality and the Z-code it generates can be beneficial for game designers and programmers. The document assumes a basic understanding of assembly language concepts and the Z-machine architecture. However, it provides sufficient detail and explanations to be accessible to individuals with a general interest in interactive fiction and the technical aspects of the Z-machine. By catering to these different audiences, the specification aims to contribute to the understanding of the Z-machine, and support the continued development of interactive fiction games. Chapter 2.1: Character Set and Lexical Elements ----------------------------------------------- The Z-code assembly language used by ZAP consists of a defined character set and specific lexical elements that form the building blocks of instructions and directives. **Character Set:** The following characters are allowed in a ZAP program: - **Letters:** A-Z (case-insensitive) - **Digits:** 0-9 - **Special characters:** , ? \# . - \_ ' \" /  : ( ) - **Whitespace:** Space and tab characters are ignored except as operand prefixes. - **Line endings:** Carriage return (`\r`), line feed (``), and form feed (`\f`) characters are ignored. **Lexical Elements:** ZAP recognizes the following lexical elements: - **Symbols:** Used to represent values and labels. They consist of letters, digits, and some special characters. By convention, pseudo-ops (assembler directives) begin with a period (`.`). - **Numbers:** Represent integer values. - **Strings:** Enclosed in double quotes (`"`). Double quotes within strings are escaped by using two consecutive double quotes. - **Operators:** Predefined symbols representing Z-machine instructions. - **Pseudo-ops (directives):** Instructions to the assembler, such as `.word`, `.str`, and `.funct`. - **Operand prefixes:** Special characters used to indicate the type of operand following them (e.g., `,` for general operand, `>` for return value). - **Comments:** Begin with a semicolon (`;`) and extend to the end of the line. These lexical elements are combined to form valid assembly language statements that are processed by ZAP. **Note:** This chapter provides a basic overview of the character set and lexical elements. More detailed information about specific elements and their usage will be presented in subsequent chapters. Chapter 2.2: Symbol Definition and Types (Global, Local, Constants) ------------------------------------------------------------------- Symbols in ZAP are used to represent various types of values and labels within the program. They play a crucial role in code organization, readability, and address resolution. **Symbol Definition:** A symbol is defined by assigning it a value using either: - **Equate statement:** `symbol = value` - **Pseudo-op:** `.equal symbol, value` - **Label definition:** `symbol::` or `symbol:` **Symbol Types:** ZAP distinguishes between three main types of symbols: - **Global symbols:** Defined outside of any function and accessible throughout the entire program. They can represent global variables, function names, table names, and string names. - **Local symbols:** Defined within a function using the `.funct` directive and accessible only within that function. They represent local variables and labels used for branching within the function. - **Constants:** Represent fixed values that cannot be changed. They are defined using equate statements or specific pseudo-ops like `.seq`. **Naming Conventions:** The following naming conventions exist: - **Pseudo-ops:** Begin with a period (`.`). - **Global labels:** End with two colons (`::`). - **Local labels:** End with one colon (`:`) **Symbol Redefinition:** - **Global and local symbols:** Cannot be redefined within their scope. Attempting to do so will result in an error. - **Constants:** Can be redefined at any point in the program. **Predefined Symbols:** ZAP includes several predefined global symbols: - **Operators:** Represent Z-machine instructions (e.g., `ADD`, `SUB`, `PRINT`). - **Pseudo-ops:** Represent assembler directives (e.g., `.word`, `.str`, `.funct`). - **Special symbols:** Represent specific data structures or locations within the program (e.g., `VOCAB`, `OBJECT`, `STACK`). Understanding symbol definition and types is essential for writing well-structured and organized Z-code assembly programs. By following the conventions and understanding the scope of different symbol types, programmers can ensure proper address resolution and code functionality. Chapter 2.3: Statement Syntax and Structure ------------------------------------------- ZAP assembly language statements are line-oriented, meaning each statement occupies a single line in the source file. Each statement consists of four optional fields: **Statement Structure:** [label] [operator] [operands] [comment] **Field Descriptions:** - **Label:** A symbol followed by one or two colons, depending on whether it's a local or global label. - **Operator:** A predefined symbol representing either an operator (Z-machine instruction) or a pseudo-op (assembler directive). - **Operands:** A space or tab-separated list of operands, each optionally preceded by an operand prefix character. - **Comment:** Begins with a semicolon (`;`) and extends to the end of the line. **Examples:** ``` {.assembly} START:: .funct main ; Define the main function add 1, 2 ; Add two constants print "Hello" ; Print a string jump END ; Jump to the END label END: ``` **Operand Prefixes:** Operand prefixes are special characters used to indicate the type of operand following them and provide additional information: - **`,` (comma):** General operand. - **`>` (greater than):** Return value operand. Specifies where the return value of an instruction should be stored - **`\` (backslash):** Branch on failure operand. Indicates the branch target if the predicate fails - **`/` (forward slash):** Branch on success operand. Indicates the branch target if the predicate succeeds. - **`=` (equal sign):** Value operand for assignments. Used for assigning values to symbols - **`+` (plus sign):** Addend operand for constant addition. **Line Continuation:** Operands can be continued to the next line by placing the operand prefix character on one line and the corresponding operand on the next line. **Note:** This chapter provides a general overview of statement syntax and structure. More detailed information about specific operators, pseudo-ops, and operands will be presented in subsequent chapters. Chapter 2.4: Operands and Addressing Modes ------------------------------------------ Operands in ZAP assembly language specify the data or values that instructions operate on. ZAP supports three main types of operands: **Operand Types:** - **Immediate:** A constant value directly encoded within the instruction. It can be either a short (one-byte) or long (two-byte) constant. - **Variable:** A reference to a variable stored in memory. The operand specifies the variable number, which is interpreted differently depending on the context. - **Other:** Represents special values like labels, function pointers, or string pointers. **Addressing Modes:** ZAP uses different addressing modes to access and interpret operands: - **Direct addressing:** The operand directly specifies the value or memory address of the data. This is used for immediate operands and some other types. - **Indirect addressing:** The operand specifies the number of a variable, which is then used to access the actual data in memory. This is used for variable operands. **Variable Addressing:** Variable operands are interpreted as follows: - **0:** Refers to the top of the game stack. - **1-15:** Refer to local variables within the current function. - **16-255:** Refer to global variables. **Examples:** ``` {.assembly} add 1, 2 ; Add two immediate operands set var1, 5 ; Set the variable var1 to 5 jump START ; Jump to the label START get table, 3 ; Get the 3rd element from the table ``` Understanding operand types and addressing modes is crucial for writing correct and efficient Z-code assembly programs. By using the appropriate operand prefixes and addressing modes, programmers can ensure that instructions operate on the intended data and achieve the desired results. Chapter 2.5: Instruction Formats (2OP, 1OP, 0OP, EXT) ----------------------------------------------------- ZAP instructions are encoded in different formats depending on the number and type of operands they require. This allows for efficient use of memory while providing flexibility in instruction design. **Instruction Formats:** - **2OP (Two-operand):** This format is used for instructions with two operands, typically immediate values or variables. It is the most compact format but has limitations on the types of operands it can handle. - **1OP (One-operand):** This format is used for instructions with a single operand, which can be an immediate value, variable, or other type. - **0OP (Zero-operand):** This format is used for instructions that do not require any explicit operands. - **EXT (Extended):** This format is used for instructions that cannot be represented in the other formats due to: - Having more than two operands. - Requiring long immediate operands. - Being rarely used instructions. **Encoding Details:** The specific encoding of each format varies, but generally: - **2OP:** The opcode byte contains both the operator and mode bits, specifying the instruction and the types of its two operands. - **1OP:** The opcode byte contains the operator and mode bits for the single operand. - **0OP:** The opcode byte solely represents the instruction, as there are no operands. - **EXT:** The opcode byte identifies the instruction, and a separate byte (or two bytes for some instructions) follows the opcode to specify the operand types and modes. **Extended Opcode Prefix (EXTOP):** ZAP provides an additional 256 extended opcodes through the `EXTOP` instruction. When `EXTOP` is encountered, the next byte is interpreted as an opcode with its value increased by 256. This allows for a larger instruction set while maintaining backward compatibility with older ZIP interpreters. **Choosing the Right Format:** The assembler automatically chooses the most efficient format for each instruction based on the number and types of operands. Programmers do not need to explicitly specify the format. The assembler determines the most efficient instruction format by following a set of rules based on the number and types of operands involved. Here's a simplified explanation of the process: 1. **Count the number of operands:** - If there are **zero operands**, the **0OP format** is used. - If there is **one operand**, the **1OP format** is used, unless the operand is a long immediate value, in which case the **EXT format** is necessary. - If there are **two operands**: - If both operands are either immediate values or variables, and neither is a long immediate, the **2OP format** is used. - Otherwise, the **EXT format** is used. 2. **Check for special cases:** - Some instructions, like `EQUAL?`, can take a variable number of operands. In such cases, the **EXT format** is used regardless of the actual number of operands provided. - Certain rarely used instructions might also be encoded in the **EXT format** even if they could fit in other formats. This is done to optimize the overall instruction set usage. By following these rules, the assembler ensures that each instruction is encoded in the most compact and efficient format possible, reducing the overall size of the Z-code program and improving its execution speed. **Example:** - The instruction `add 1, 2` has two immediate operands, so it can be encoded in the **2OP format**. - The instruction `set var1, 5` has one variable operand and one immediate operand, so it can also be encoded in the **2OP format**. - The instruction `print "Hello"` has one string operand, which is considered an "other" type. Therefore, it needs the **EXT format**. - The instruction `jump START` has one label operand, also requiring the **EXT format**. Understanding instruction formats is helpful for comprehending the structure of Z-code programs and how instructions are encoded in memory. However, for most programming tasks, it is sufficient to focus on the instruction names and operands, as ZAP handles the format selection automatically. Chapter 2.6: Instruction Values and Predicates ---------------------------------------------- Some ZAP instructions return values or act as predicates, influencing the flow of control in the program. **Instruction Values:** Certain instructions, such as arithmetic and logical operations, produce a value as a result of their execution. This value can be: - **Pushed onto the game stack:** This is the default behavior if no explicit destination is specified. - **Stored in a variable:** The instruction can be followed by an operand prefix `>` and a variable number to indicate where the value should be stored. **Example:** ``` {.assembly} add 1, 2 ; Value is pushed onto the stack add 1, 2 > var1 ; Value is stored in the variable var1 ``` **Predicates:** Predicate instructions evaluate a condition and implicitly perform a conditional branch based on the result. They are typically used for decision-making and control flow within the program. **Branch Polarity and Offset:** Predicate instructions are followed by one or two bytes that specify: - **Branch polarity:** Whether the branch occurs on success (predicate evaluates to true) or failure (predicate evaluates to false). This is indicated by the high-order bit of the first byte. - **Branch offset:** The distance to jump if the branch condition is met. This can be either a short (6-bit) or long (14-bit) offset. **Branch Targets:** The branch offset determines the target of the conditional jump: - **Offset 0:** Executes an `RFALSE` instruction, returning false from the current function. - **Offset 1:** Executes an `RTRUE` instruction, returning true from the current function. - **Other offsets:** Jumps to the instruction located at the current address plus the offset minus two. **Example:** ``` {.assembly} less? var1, 5 / label1 ; Branch to label1 if var1 is less than 5 ``` Understanding instruction values and predicates is essential for controlling the flow of execution in Z-code programs. By using predicates and specifying appropriate branch targets, programmers can implement conditional logic and decision-making within their games. Chapter 3.1: Detailed Description of Each Opcode and Directive -------------------------------------------------------------- This chapter provides a comprehensive description of each opcode and directive supported by ZAP. For each element, the following information is provided: - **Name:** The name of the opcode or directive. - **Syntax:** The format of the instruction or directive, including operand types and prefixes. - **Functionality:** A detailed explanation of what the opcode or directive does. - **Special cases:** Any special conditions or behaviors to be aware of. - **Error conditions:** Potential errors that might occur during assembly or execution. - **Examples:** Illustrative examples of how the opcode or directive can be used. This chapter serves as a reference for understanding the functionality and usage of each opcode and directive available in ZAP. By consulting this information, programmers can write accurate and efficient Z-code assembly programs. ### .ALIGN **.ALIGN** is a directive that instructs the assembler to align the next generated code or data to a specified byte boundary. This can be useful for ensuring proper memory access and improving performance on certain architectures. **Syntax:** ``` {.assembly} .align value ``` **Functionality:** The `.align` directive pads the object file with zero bytes until the current address is a multiple of the specified `value`. This effectively aligns the next instruction or data element to the specified boundary. **Special Cases:** - If `value` is 1, the directive has no effect, as all data is already aligned to a byte boundary. - If `value` is not a power of two, the assembler may align to the next higher power of two. **Error Conditions:** An error occurs if `value` is zero or negative. **Examples:** ``` {.assembly} .align 4 .word data1 ; data1 will be aligned to a 4-byte boundary .align 8 .funct func1 ; func1 will be aligned to an 8-byte boundary ``` **Use Cases:** - Aligning data structures to their natural word or longword boundaries can improve memory access efficiency. - Some Z-machine instructions might have specific alignment requirements for optimal performance. - Aligning functions can be helpful for debugging and code analysis. **Note:** While `.align` can be used to enforce specific alignment, it is generally recommended to let the assembler choose the appropriate alignment for optimal code generation. ### .BYTE The `.BYTE` directive instructs the assembler to generate one or more byte values in the object file. It is used to define raw byte data or initialize specific memory locations with byte values. **Syntax:** ``` {.assembly} .byte value1 [, value2 ...] ``` **Functionality:** The `.byte` directive generates the specified byte values sequentially in the object file. Each value must be a constant expression that evaluates to a number within the range of 0 to 255. **Special Cases:** None. **Error Conditions:** An error occurs if a value exceeds the byte range (0-255). **Examples:** ``` {.assembly} .byte 10, 20, 30 ; Generates three bytes with values 10, 20, and 30 .byte 'A' ; Generates a byte with the ASCII value of 'A' (65) ``` **Use Cases:** - Defining raw byte data for specific purposes, such as flags or status codes. - Initializing memory locations with specific byte values. - Embedding special characters or control codes within the object file. **Note:** While `.byte` allows for precise control over byte values, it is generally recommended to use higher-level directives like `.word` or `.str` whenever possible, as they provide better readability and maintainability. ### .CHRSET The `.CHRSET` directive allows the programmer to redefine the character sets used for encoding strings in the Z-machine. This can be useful for optimizing string storage and handling characters specific to certain languages or display systems. **Syntax:** ``` {.assembly} .chrset id, char1, char2, ..., charN ``` **Functionality:** The `.chrset` directive redefines one of the three character sets used for string encoding: - **`id`:** Specifies the character set to modify (0, 1, or 2). - **`char1, char2, ..., charN`:** A list of characters (specified as their ASCII values) that will be assigned to the character set. The number of characters provided depends on the `id`: - **Set 0 and 1:** 26 characters are expected. - **Set 2:** 24 characters are expected (excluding ASCII escape and newline characters). **Special Cases:** - Character set 2 has two special characters that cannot be redefined: - **6:** Represents the ASCII escape sequence. - **7:** Represents the newline character. **Error Conditions:** - An error occurs if `id` is not 0, 1, or 2. - An error occurs if the number of characters provided does not match the expected count for the specified `id`. **Examples:** ``` {.assembly} .chrset 0, 'a', 'b', ..., 'z' ; Redefines character set 0 with lowercase letters .chrset 1, 'A', 'B', ..., 'Z' ; Redefines character set 1 with uppercase letters ``` **Use Cases:** - Optimizing string storage by assigning frequently used characters to the compact character sets. - Handling characters specific to certain languages or display systems that are not included in the default character sets. **Note:** Redefining character sets can have significant implications for string encoding and decoding. It is generally recommended to use the default character sets unless there is a specific need for optimization or handling special characters. ### .DEFSEG The `.DEFSEG` directive is used to define a segment and specify its relationships with other segments. Segments are logical divisions of the Z-code program that can be used to optimize disk usage and loading times in multi-disk games. **Syntax:** ``` {.assembly} .defseg name, seg1, seg2, seg3 ``` **Functionality:** The `.DEFSEG` directive performs the following: - **Defines a segment:** Creates a new segment with the specified `name`. - **Specifies adjacent segments:** Declares that the segment is adjacent to the segments `seg1`, `seg2`, and `seg3`. This information is used by the `zsplit` tool to determine how to distribute segments across multiple disks. **Special Cases:** - If the segment `name` is "0", it refers to the default segment that contains all preloaded data and code. - If a segment name is not defined with `.DEFSEG`, it is implicitly considered adjacent to segment 0. **Error Conditions:** An error occurs if a segment name is not a valid symbol. **Examples:** ``` {.assembly} .defseg "ROOM", "HALL", "GARDEN" ; Defines the "ROOM" segment and declares it adjacent to "HALL" and "GARDEN" segments .defseg "STARTUP", "MAIN" ; Defines the "STARTUP" segment and declares it adjacent to the "MAIN" segment ``` **Use Cases:** - Organizing the game's code and data into logical segments for efficient disk usage and loading. - Informing the `zsplit` tool about segment relationships to optimize the distribution of segments across multiple disks. **Note:** Segment definitions and adjacency information are primarily used by the `zsplit` tool and do not directly affect the execution of the Z-code program. ### .END The `.END` directive marks the end of the assembly language program. It instructs the assembler to stop processing input and perform final operations. **Syntax:** ``` {.assembly} .end ``` **Functionality:** When the `.END` directive is encountered, the assembler performs the following: - **Stops processing input:** Any code or directives following `.END` are ignored. - **Resolves forward references:** Performs fixup operations to resolve any outstanding forward references to symbols. - **Generates final output:** Writes the assembled Z-code program to the object file and generates any optional listing or error files. **Special Cases:** None. **Error Conditions:** An error might occur during fixup if undefined symbols are encountered. **Examples:** ``` {.assembly} ; ... game code ... .end ``` **Use Cases:** The `.END` directive is mandatory and must be placed at the end of every Z-code assembly program to signal the completion of the assembly process. **Note:** It is essential to ensure that all necessary code and data have been defined before the `.END` directive, as anything following it will not be processed by the assembler. ### .ENDI The `.ENDI` directive marks the end of an `.INSERT` file. It instructs the assembler to return to the previous input source and continue processing. **Syntax:** ``` {.assembly} .endi ``` **Functionality:** The `.ENDI` directive is used in conjunction with the `.INSERT` directive, which allows the contents of another file to be inserted and assembled at a specific point in the main source file. When `.ENDI` is encountered, the assembler: - **Stops processing the inserted file:** Any code or directives following `.ENDI` in the inserted file are ignored. - **Returns to the previous input source:** The assembler resumes processing the main source file from the point where the `.INSERT` directive was encountered. **Special Cases:** - A `.ENDI` directive without a preceding `.INSERT` directive is an error. **Error Conditions:** An error occurs if `.ENDI` is found outside of an inserted file. **Examples:** ``` {.assembly} ; ... main source file ... .insert "header.zap" ; ... contents of header.zap ... .endi ; ... main source file continues ... ``` **Use Cases:** - Modularizing code by separating commonly used routines or data into separate files that can be inserted into multiple programs. - Including header files that define constants, macros, or other elements. **Note:** The `.INSERT` and `.ENDI` directives provide a mechanism for code inclusion and modularity, but their usage should be carefully considered to avoid potential complexity and maintainability issues. ### .ENDSEG The `.ENDSEG` directive closes all currently open segments. Segments are logical divisions of the Z-code program used to optimize disk usage and loading times in multi-disk games. **Syntax:** ``` {.assembly} .endseg ``` **Functionality:** The `.ENDSEG` directive closes any segments that were previously opened with the `.SEGMENT` directive. This indicates to the assembler that the code and data belonging to those segments have been defined. **Special Cases:** - If no segments are currently open, the `.ENDSEG` directive has no effect. **Error Conditions:** None. **Examples:** ``` {.assembly} .segment "ROOM" ; ... code and data for the ROOM segment ... .endseg ``` **Use Cases:** - Ensuring that all segments are properly closed before the end of the assembly process. - Organizing code and data into logical segments for efficient disk usage and loading. **Note:** Segment definitions and closures are primarily used by the `zsplit` tool and do not directly affect the execution of the Z-code program. ### .ENDT The `.ENDT` directive marks the end of a table definition. Tables are logical structures used to organize data in Z-code programs. **Syntax:** ``` {.assembly} .endt ``` **Functionality:** The `.ENDT` directive must be used to terminate a table that was previously declared with the `.TABLE` directive. It performs the following: - **Checks table size:** If a size was specified in the `.TABLE` directive, the assembler verifies that the actual table size does not exceed the declared size. - **Finalizes table data:** The assembler performs any necessary operations to finalize the table data, such as padding or alignment. **Special Cases:** - A `.ENDT` directive without a preceding `.TABLE` directive is an error. **Error Conditions:** - An error occurs if the actual table size exceeds the declared size (if specified in `.TABLE`). **Examples:** ``` {.assembly} .table 10 .word data1, data2, data3 .endt ``` **Use Cases:** - Defining tables of data with a specific size and ensuring that the size is not exceeded. - Organizing data into logical structures for easier access and manipulation. **Note:** The `.TABLE` and `.ENDT` directives provide a way to define and manage tables in Z-code programs, but their usage should be consistent and well-structured to avoid potential errors and maintainability issues. ### .FALSE The `.FALSE` directive generates a word (two-byte) value of 0 in the object file. It is used to represent the boolean value `false` or to initialize memory locations with a zero value. **Syntax:** ``` {.assembly} .false ``` **Functionality:** The `.false` directive simply generates a word with the value 0 at the current address in the object file. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} .false ; Generates a word with value 0 set flag1, .false ; Sets the flag variable `flag1` to false ``` **Use Cases:** - Representing the boolean value `false` in conditional statements or data structures. - Initializing variables or memory locations with a zero value. **Note:** The `.false` directive is equivalent to using `.word 0`. However, `.false` provides better readability and clarity when representing boolean values. ### .FSTR The `.FSTR` directive defines a string as a "frequent string" and adds it to the frequent words table. Frequent strings are short, commonly used substrings that can be referenced efficiently within other strings, reducing overall memory usage. **Syntax:** ``` {.assembly} .fstr name, string ``` **Functionality:** The `.fstr` directive performs the following: - **Defines a symbol:** Creates a global symbol with the specified `name`. The value of the symbol is the address of the string divided by 2 (since strings are stored as words). - **Outputs the string:** Generates the string in the object file, aligning it to a word boundary. - **Adds to frequent words table:** Adds the string to the frequent words table, which is used by the Z-machine to efficiently reference frequently used substrings within other strings. **Special Cases:** - Frequent strings cannot contain other frequent strings within them. - The frequent words table has a limited size (96 entries). If this limit is exceeded, the assembler will issue an error. **Error Conditions:** - An error occurs if `name` is not a valid symbol. - An error occurs if the frequent words table is full. **Examples:** ``` {.assembly} .fstr "the", "the " ; Defines the frequent string "the" .fstr "and", "and " ; Defines the frequent string "and" ``` **Use Cases:** - Optimizing string storage by defining frequently used words or phrases as frequent strings. - Reducing the overall size of the Z-code program by efficiently referencing common substrings. **Note:** The use of frequent strings can improve memory efficiency, but it is important to choose appropriate strings and avoid exceeding the table size limit. ### .FUNCT The `.FUNCT` directive defines a function and begins a new local symbol block. Functions are subroutines that can be called and return values, allowing for modular and reusable code. **Syntax:** ``` {.assembly} .funct name [, arg1 [: type] [, arg2 [: type] ...]] ``` **Functionality:** The `.funct` directive performs the following: - **Defines a function:** Creates a new function with the specified `name`. The function name becomes a global symbol. - **Starts a new local symbol block:** Any symbols defined after `.funct` are considered local to the function and are not accessible outside of it. - **Defines local variables:** The optional `arg1`, `arg2`, etc., specify local variables for the function. Each variable can optionally have a type specified after a colon (`:`) to indicate its data type. - **Aligns function:** Aligns the function to a quad-byte boundary for efficient execution. **Special Cases:** - If no arguments are provided, the function has no local variables. - If a type is not specified for a local variable, it is assumed to be of type `ANY`. **Error Conditions:** - An error occurs if `name` is not a valid symbol. - An error occurs if the function is defined within another function (nested functions are not supported). **Examples:** ``` {.assembly} .funct main ; ... code for the main function ... .funct add, num1: int, num2: int > result: int ; ... code for the add function ... ``` **Use Cases:** - Defining functions to modularize code and promote reusability. - Creating subroutines to perform specific tasks within the program. - Utilizing local variables to manage data within functions. **Note:** The `.funct` directive is essential for defining functions in Z-code assembly programs. Proper function definition and usage are crucial for code organization and maintainability. ### .GSTR The `.GSTR` directive defines a global string and stores it in the string area of the Z-code program. Global strings are accessible from anywhere in the program and are typically used for longer text passages or messages. **Syntax:** ``` {.assembly} .gstr name, string ``` **Functionality:** The `.gstr` directive performs the following: - **Defines a symbol:** Creates a global symbol with the specified `name`. The value of the symbol is the address of the string in the string area, adjusted for the string offset (`SOFF`). - **Outputs the string:** Generates the string in the object file, aligning it to a quad-byte boundary. - **Updates string offset:** If necessary, updates the `SOFF` value to reflect the new string's location. **Special Cases:** - The string area is located in a separate section of the Z-code program and is accessed using the `SOFF` value. - Strings are encoded in a special 5-bit byte format for efficient storage. **Error Conditions:** - An error occurs if `name` is not a valid symbol. **Examples:** ``` {.assembly} .gstr "intro", "Welcome to the game!" print intro ; Prints the "intro" string ``` **Use Cases:** - Defining long text passages or messages that need to be accessed from various parts of the program. - Storing strings that are too large to be defined as immediate operands within instructions. **Note:** The `.gstr` directive is used to define global strings, while the `.str` directive is used for defining strings within tables or as immediate operands. ### .GVAR The `.GVAR` directive defines a global variable and assigns it a default value. Global variables are accessible from anywhere in the program and are typically used to store persistent data or game state. **Syntax:** ``` {.assembly} .gvar name [= value] ``` **Functionality:** The `.gvar` directive performs the following: - **Defines a symbol:** Creates a global symbol with the specified `name`. The value of the symbol is the variable number, which is used to access the variable in the global table. - **Assigns a default value:** If `value` is provided, it is assigned as the initial value of the global variable. Otherwise, the default value is 0. - **Outputs the value:** Generates the default value in the object file, placing it in the global table. **Special Cases:** - Global variables are stored in a dedicated table pointed to by the `GLOBALS` word in the program header. - The first global variable has a variable number of 16, and subsequent variables are assigned incrementing numbers. **Error Conditions:** - An error occurs if `name` is not a valid symbol. - An error occurs if the maximum number of global variables is exceeded. **Examples:** ``` {.assembly} .gvar score = 0 ; Defines a global variable "score" with initial value 0 .gvar health ; Defines a global variable "health" with default value 0 ``` **Use Cases:** - Storing persistent data that needs to be accessed from different parts of the program. - Managing game state and tracking variables like score, health, or inventory items. **Note:** The `.gvar` directive is used to define global variables, while local variables are defined within functions using the `.funct` directive. ### .INSERT The `.INSERT` directive instructs the assembler to insert the contents of another file at the current point in the assembly process. This allows for code modularity and reuse. **Syntax:** ``` {.assembly} .insert "filename" ``` **Functionality:** The `.insert` directive opens the specified `filename` and inserts its contents into the assembly stream as if they were part of the main source file. The assembler processes the inserted file's code and directives, including any symbols or definitions it contains. **Special Cases:** - The inserted file must be a valid Z-code assembly language file. - The `.insert` directive can be nested, meaning inserted files can themselves contain `.insert` directives. - The `.ENDI` directive is used to mark the end of an inserted file and return to the previous input source. **Error Conditions:** - An error occurs if the specified `filename` cannot be opened. - An error occurs if the inserted file contains syntax errors or invalid directives. **Examples:** ``` {.assembly} ; ... main source file ... .insert "header.zap" ; Inserts the contents of header.zap ; ... main source file continues ... ``` **Use Cases:** - Including header files that define constants, macros, or other commonly used elements. - Modularizing code by separating routines or data into separate files that can be inserted into multiple programs. **Note:** While `.insert` provides a mechanism for code inclusion and modularity, its usage should be carefully considered to avoid potential complexity and maintainability issues. Excessive nesting of `.insert` directives can make code harder to understand and debug. ### .LANG The `.LANG` directive specifies the language and escape character used for string encoding. This allows ZAP to generate Z-code programs that support different languages and character sets. **Syntax:** ``` {.assembly} .lang id, escape ``` **Functionality:** The `.lang` directive sets the following parameters for string encoding: - **`id`:** Specifies the language ID. Currently, only two languages are supported: - **0:** English (default) - **1:** German - **`escape`:** Specifies the escape character used to represent special characters or switch character sets within strings. **Special Cases:** - The default language is English with the `%` character as the escape character. - The German language setting modifies the character set used for compact encoding to include German-specific characters. **Error Conditions:** - An error occurs if `id` is not 0 or 1. **Examples:** ``` {.assembly} .lang 1, '%' ; Sets the language to German with '%' as the escape character ``` **Use Cases:** - Creating Z-code programs that support languages other than English. - Optimizing string storage for languages with specific character sets. **Note:** The `.lang` directive is typically used at the beginning of the assembly program to set the language and escape character for all subsequent string definitions. ### .LEN The `.LEN` directive calculates the length of a string in words and generates a byte containing that length in the object file. This is typically used in conjunction with the `.STR` directive to create self-contained string definitions. **Syntax:** ``` {.assembly} .len string ``` **Functionality:** The `.len` directive performs the following: - **Calculates string length:** Determines the length of the specified string in words, taking into account the Z-machine's 5-bit byte encoding for strings. - **Generates length byte:** Outputs a single byte containing the calculated length to the object file. **Special Cases:** - The string must be a short string, meaning it can be represented in 255 words or less. **Error Conditions:** An error occurs if the string length exceeds 255 words. **Examples:** ``` {.assembly} .len "Hello" .str "Hello" ; This string will be preceded by a byte indicating its length ``` **Use Cases:** - Creating self-contained string definitions where the length is explicitly stored alongside the string data. - Facilitating string manipulation routines that require knowledge of the string length. **Note:** The `.len` directive is often used together with the `.strl` directive, which combines the functionality of `.len` and `.str` into a single operation. ### .NEW The `.NEW` directive sets the release level of the Z-code program being assembled. This information is used to ensure compatibility with different versions of the ZIP interpreter. **Syntax:** ``` {.assembly} .new level ``` **Functionality:** The `.new` directive sets the `Version` variable in ZAP, which determines the version of the Z-machine that the generated program is compatible with. The `level` argument must be a constant expression that evaluates to one of the supported Z-machine versions: - **3:** ZIP - **4:** EZIP - **5:** XZIP - **6:** YZIP **Special Cases:** - The default release level is 5 (XZIP). - Some features and opcodes might not be available in older versions of ZIP. **Error Conditions:** An error occurs if `level` is not a supported Z-machine version. **Examples:** ``` {.assembly} .new 6 ; Sets the release level to YZIP ``` **Use Cases:** - Ensuring compatibility with specific versions of the ZIP interpreter. - Taking advantage of features and opcodes introduced in newer Z-machine versions. **Note:** The `.new` directive should be used at the beginning of the assembly program to set the release level before any other code or directives. ### .OBJECT The `.OBJECT` directive defines an object and assigns it a unique object number. Objects are complex data structures used to represent entities and items within the game world. **Syntax:** ``` {.assembly} .object name, flag1, flag2, ..., flag7 ``` **Functionality:** The `.object` directive performs the following: - **Defines a symbol:** Creates a global symbol with the specified `name`. The value of the symbol is the object number. - **Assigns object number:** Assigns a unique, incrementing object number to the object. - **Outputs object data:** Generates the object data in the object file, including flag words and property table pointer. **Special Cases:** - Objects are stored in a dedicated table pointed to by the `OBJECT` word in the program header. - The first object has an object number of 1, and subsequent objects are assigned incrementing numbers. - The `flag1` to `flag7` arguments represent the initial values of the object's 48 one-bit flags, divided into seven words. **Error Conditions:** - An error occurs if `name` is not a valid symbol. - An error occurs if the maximum number of objects is exceeded. **Examples:** ``` {.assembly} .object "player", 0, 0, 0, 0, 0, 0 ; Defines the "player" object .object "sword", 1, 0, 0, 0, 0, 0 ; Defines the "sword" object ``` **Use Cases:** - Defining objects to represent entities and items in the game world. - Assigning properties and flags to objects to track their state and characteristics. **Note:** The `.object` directive is used to define objects, while properties are defined within the object's property table using the `.PROP` directive. ### .OPTIONS The `.OPTIONS` directive is used to set options that control the behavior of the ZIP interpreter. These options affect features such as scripting and user input. **Syntax:** ``` {.assembly} .options script, ask ``` **Functionality:** The `.options` directive sets the following options: - **`script`:** A boolean value (0 or 1) indicating whether scripting is enabled. When scripting is enabled, the interpreter can read commands from a script file instead of from the user. - **`ask`:** A boolean value (0 or 1) indicating whether the interpreter should ask the user for confirmation before executing certain actions, such as restarting or restoring the game. **Special Cases:** - If either `script` or `ask` is omitted, the corresponding option is not modified. **Error Conditions:** An error occurs if `script` or `ask` is not a valid boolean value (0 or 1). **Examples:** ``` {.assembly} .options 1, 0 ; Enables scripting and disables confirmation prompts ``` **Use Cases:** - Enabling scripting for automated testing or gameplay recording. - Disabling confirmation prompts for a more streamlined user experience. **Note:** The `.options` directive is typically used at the beginning of the assembly program to set the desired interpreter options. ### .PCSET The `.PCSET` directive sets the program counter (PC) to a specific value. This directive is used to jump to a specific address within the program or to align code and data to specific memory locations. **Syntax:** ``` {.assembly} .pcset value ``` **Functionality:** The `.pcset` directive sets the program counter to the specified `value`. The assembler then continues generating code and data from that address onwards. **Special Cases:** - If `value` is less than the current program counter, the assembler will issue a warning but will still set the PC to the specified value. **Error Conditions:** An error occurs if `value` is negative. **Examples:** ``` {.assembly} .pcset 1000 ; Sets the program counter to 1000 ``` **Use Cases:** - Jumping to a specific address within the program, typically for implementing subroutines or handling error conditions. - Aligning code or data to specific memory locations for optimization or compatibility purposes. **Note:** The `.PCSET` directive should be used with caution, as it can lead to unexpected behavior if not used correctly. It is generally recommended to use labels and jump instructions for control flow whenever possible. ### .PDEF The `.PDEF` directive aligns the next generated code or data to the next word boundary. This directive is used to ensure proper alignment for word-sized data elements. **Syntax:** ``` {.assembly} .pdef ``` **Functionality:** The `.pdef` directive pads the object file with a zero byte if the current address is not already a multiple of two. This ensures that the next word (two-byte) value will be aligned to a word boundary. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} .pdef .word data1 ; data1 will be aligned to a word boundary ``` **Use Cases:** - Ensuring proper alignment for word-sized data elements, such as numbers and pointers. - Improving memory access efficiency on architectures that require word alignment. **Note:** The `.PDEF` directive is typically used before defining word-sized data elements to guarantee their alignment. However, the assembler generally handles alignment automatically, so explicit use of `.PDEF` is often unnecessary. ### .PICFILE The `.PICFILE` directive defines a picture file and specifies its properties. Picture files contain images and associated data used by the `DISPLAY` and `DCLEAR` instructions. **Syntax:** ``` {.assembly} .picfile filename, machine, ideal-x, ideal-y, base-x, base-y ``` **Functionality:** The `.picfile` directive defines a picture file with the following properties: - **`filename`:** The name of the picture file. - **`machine`:** The target machine for which the picture file is intended (e.g., "apple", "ega", "mac"). - **`ideal-x` and `ideal-y`:** The ideal dimensions of the picture in pixels. - **`base-x` and `base-y`:** The base coordinates of the picture in pixels. This information is used by the interpreter to properly display and manage pictures from the specified file. **Special Cases:** - The picture file format and encoding are specific to the Z-machine and may vary depending on the target machine. - The `zsplit` tool uses the picture file information to distribute pictures across multiple disks in multi-disk games. **Error Conditions:** - An error occurs if `filename` is not a valid string. - An error occurs if `machine` is not a recognized target machine. **Examples:** ``` {.assembly} .picfile "pictures.p", "mac", 320, 200, 0, 0 ``` **Use Cases:** - Defining picture files for use with the `DISPLAY` and `DCLEAR` instructions. - Providing information to the interpreter and `zsplit` tool for picture management. **Note:** The `.PICFILE` directive is used in conjunction with the `DISPLAY` and `DCLEAR` instructions to display and manage pictures within Z-code programs. ### .PROP The `.PROP` directive defines a property within an object's property table. Properties are used to associate additional data and attributes with objects. **Syntax:** ``` {.assembly} .prop length, number ``` **Functionality:** The `.prop` directive defines a property with the following characteristics: - **`length`:** The length of the property value in bytes. - **`number`:** The property number. The assembler generates the property data in the object file, including the length, number, and value. **Special Cases:** - Properties are stored in a sorted order within the object's property table. - The length of a property value can be 1, 2, or more bytes. The encoding of the length depends on the size: - 1 byte: The high-order bit of the length byte is 0. - 2 bytes: The high-order bit is 1, and the second-highest bit is 0. - More than 2 bytes: The high-order two bits are both 1, and the remaining 6 bits specify the length. **Error Conditions:** - An error occurs if `length` is zero or negative. - An error occurs if `number` is not within the valid range (1-63). **Examples:** ``` {.assembly} .object "player", ... .prop 1, 1 ; Defines a one-byte property with number 1 .prop 2, 10 ; Defines a two-byte property with number 10 ``` **Use Cases:** - Associating additional data with objects, such as descriptions, attributes, or inventory items. - Extending the functionality of objects beyond their basic flags and attributes. **Note:** The `.PROP` directive is used within an object definition to define its properties. The object itself is defined using the `.OBJECT` directive. ### .SEGMENT The `.SEGMENT` directive opens a new segment for code and data definition. Segments are logical divisions of the Z-code program used to optimize disk usage and loading times in multi-disk games. **Syntax:** ``` {.assembly} .segment "name" ``` **Functionality:** The `.segment` directive opens a new segment with the specified `name`. All subsequent code and data definitions are considered to belong to this segment until a `.ENDSEG` directive is encountered or another `.SEGMENT` directive opens a different segment. **Special Cases:** - If the segment "0" is opened, it refers to the default segment that contains all preloaded data and code. - If a segment name is not defined with `.DEFSEG`, it is implicitly considered adjacent to segment 0. **Error Conditions:** An error occurs if `name` is not a valid string. **Examples:** ``` {.assembly} .segment "ROOM" ; ... code and data for the ROOM segment ... .endseg ``` **Use Cases:** - Organizing the game's code and data into logical segments for efficient disk usage and loading. - Informing the `zsplit` tool about segment boundaries to optimize the distribution of segments across multiple disks. **Note:** Segment definitions and closures are primarily used by the `zsplit` tool and do not directly affect the execution of the Z-code program. ### .SEQ The `.SEQ` directive assigns sequential values to a list of symbols, starting from 0. This is a convenient way to define a series of constants or variables with incrementing values. **Syntax:** ``` {.assembly} .seq symbol1 [, symbol2 ...] ``` **Functionality:** The `.seq` directive assigns values to the specified symbols in the following manner: - `symbol1` is assigned the value 0. - `symbol2` is assigned the value 1. - ... and so on. The symbols become global constants with their respective values. **Special Cases:** None. **Error Conditions:** An error occurs if any of the symbols are already defined. **Examples:** ``` {.assembly} .seq color_red, color_green, color_blue ; Defines three constants with values 0, 1, and 2 ``` **Use Cases:** - Defining a series of constants with incrementing values, such as color codes or status flags. - Creating a sequence of variables with unique identifiers. **Note:** The `.seq` directive provides a concise way to define multiple constants or variables with sequential values. ### .SEQ The `.SEQ` directive assigns sequential values to a list of symbols, starting from 0. This is a convenient way to define a series of constants or variables with incrementing values. **Syntax:** ``` {.assembly} .seq symbol1 [, symbol2 ...] ``` **Functionality:** The `.seq` directive assigns values to the specified symbols in the following manner: - `symbol1` is assigned the value 0. - `symbol2` is assigned the value 1. - ... and so on. The symbols become global constants with their respective values. **Special Cases:** None. **Error Conditions:** An error occurs if any of the symbols are already defined. **Examples:** ``` {.assembly} .seq color_red, color_green, color_blue ; Defines three constants with values 0, 1, and 2 ``` **Use Cases:** - Defining a series of constants with incrementing values, such as color codes or status flags. - Creating a sequence of variables with unique identifiers. **Note:** The `.seq` directive provides a concise way to define multiple constants or variables with sequential values. ### .STR The `.STR` directive generates a string in the object file, encoding it in the Z-machine's 5-bit byte format. It is used to define strings that can be referenced and printed by instructions like `PRINT` and `PRINTB`. **Syntax:** ``` {.assembly} .str string ``` **Functionality:** The `.str` directive performs the following: - **Encodes the string:** Converts the ASCII string into the Z-machine's 5-bit byte format, using frequent words and character set shifting as needed. - **Outputs the string:** Generates the encoded string data in the object file. - **Sets the end-of-string bit:** Marks the last word of the string with the end-of-string bit to indicate its termination. **Special Cases:** - If a string is provided without an explicit directive, it is implicitly treated as a `.str` directive. - Strings are aligned to word boundaries in the object file. **Error Conditions:** None. **Examples:** ``` {.assembly} .str "Hello, world!" ; Defines a string print message ; Prints the string defined above ``` **Use Cases:** - Defining strings that can be printed or manipulated by the Z-code program. - Storing text data efficiently using the Z-machine's string encoding format. **Note:** The `.str` directive is used to define strings within tables or as immediate operands. For defining global strings in the string area, the `.GSTR` directive is used. ### .STRL The `.STRL` directive combines the functionality of the `.LEN` and `.STR` directives. It calculates the length of a string in words, generates a byte containing that length, and then generates the encoded string data in the object file. **Syntax:** ``` {.assembly} .strl string ``` **Functionality:** The `.strl` directive performs the following: - **Calculates string length:** Determines the length of the specified string in words, taking into account the Z-machine's 5-bit byte encoding for strings. - **Generates length byte:** Outputs a single byte containing the calculated length to the object file. - **Encodes the string:** Converts the ASCII string into the Z-machine's 5-bit byte format, using frequent words and character set shifting as needed. - **Outputs the string:** Generates the encoded string data in the object file, following the length byte. **Special Cases:** - The string must be a short string, meaning it can be represented in 255 words or less. **Error Conditions:** An error occurs if the string length exceeds 255 words. **Examples:** ``` {.assembly} .strl "Hello, world!" ; Defines a string with its length ``` **Use Cases:** - Creating self-contained string definitions where the length is explicitly stored alongside the string data. - Simplifying string definition by combining the functionality of `.LEN` and `.STR` into a single directive. **Note:** The `.strl` directive is a convenient way to define strings with their lengths, but it is equivalent to using `.len` followed by `.str`. ### .TABLE The `.TABLE` directive declares the beginning of a table definition. Tables are logical structures used to organize data in Z-code programs. **Syntax:** ``` {.assembly} .table [size] ``` **Functionality:** The `.table` directive marks the start of a table definition. It can optionally take a `size` argument, which specifies the maximum size of the table in bytes. The assembler uses this information to: - **Check for size violations:** If a size is specified, the assembler ensures that the actual table data generated does not exceed the declared size. - **Perform alignment:** The assembler may align the table data to a specific boundary depending on the target architecture or data type. **Special Cases:** - If the `size` argument is omitted, the table size is not checked by the assembler. However, debugging versions of the ZIP interpreter may perform bounds checking at runtime. **Error Conditions:** An error occurs if the actual table size exceeds the declared size (if specified). **Examples:** ``` {.assembly} .table 100 ; Declares a table with a maximum size of 100 bytes .word data1, data2, data3 .endt ``` **Use Cases:** - Defining tables of data with a specific size and ensuring that the size is not exceeded. - Organizing data into logical structures for easier access and manipulation. **Note:** The `.TABLE` directive must be paired with a `.ENDT` directive to mark the end of the table definition. ### .TRUE The `.TRUE` directive generates a word (two-byte) value of 1 in the object file. It is used to represent the boolean value `true` or to initialize memory locations with a non-zero value. **Syntax:** ``` {.assembly} .true ``` **Functionality:** The `.true` directive simply generates a word with the value 1 at the current address in the object file. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} .true ; Generates a word with value 1 set flag1, .true ; Sets the flag variable `flag1` to true ``` **Use Cases:** - Representing the boolean value `true` in conditional statements or data structures. - Initializing variables or memory locations with a non-zero value. **Note:** The `.true` directive is equivalent to using `.word 1`. However, `.true` provides better readability and clarity when representing boolean values. ### .VOCBEG The `.VOCBEG` directive declares the beginning of the vocabulary area. The vocabulary area contains words and associated information used by the `READ` and `LEX` instructions for parsing player input. **Syntax:** ``` {.assembly} .vocbeg record-length, key-length ``` **Functionality:** The `.vocbeg` directive defines the following parameters for the vocabulary area: - **`record-length`:** Specifies the length of each vocabulary entry in bytes. This includes the word itself and any additional associated data. - **`key-length`:** Specifies the length of the key used for sorting vocabulary entries. The key is typically the word itself, but it can be a shorter substring. The assembler uses this information to: - **Allocate space for vocabulary entries:** Ensures that enough space is allocated in the object file for the vocabulary data. - **Sort vocabulary entries (optional):** If the number of entries in the vocabulary table is specified as negative, the vocabulary is considered unsorted. Otherwise, the assembler sorts the entries based on their keys for efficient searching during input parsing. **Special Cases:** - The vocabulary area is located in a separate section of the Z-code program and is accessed using the `VOCAB` word in the program header. - The first byte of the vocabulary area specifies the number of self-inserting break characters used by the `READ` instruction. - The format of the vocabulary entries depends on the `record-length` and `key-length` values specified in `.VOCBEG`. **Error Conditions:** - An error occurs if `record-length` or `key-length` is zero or negative. - An error occurs if the vocabulary area has an invalid length or structure. **Examples:** ``` {.assembly} .vocbeg 6, 3 ; Define vocabulary with 6-byte entries and 3-byte keys ; ... vocabulary words and data ... .vocend ``` **Use Cases:** - Defining the vocabulary of words that the game understands and can parse from player input. - Optimizing input parsing by sorting the vocabulary for efficient searching. **Note:** The `.VOCBEG` directive must be paired with a `.VOCEND` directive to mark the end of the vocabulary area. ### .VOCEND The `.VOCEND` directive marks the end of the vocabulary area. The vocabulary area contains words and associated information used by the `READ` and `LEX` instructions for parsing player input. **Syntax:** ``` {.assembly} .vocend ``` **Functionality:** The `.VOCEND` directive must be used to terminate a vocabulary area that was previously declared with the `.VOCBEG` directive. It performs the following: - **Sorts vocabulary entries:** If the vocabulary is defined as sorted, the assembler sorts the entries based on their keys. - **Outputs vocabulary data:** The assembler writes the vocabulary data to the object file in the appropriate format. - **Finalizes vocabulary table:** The assembler performs any necessary operations to finalize the vocabulary table, such as calculating the total number of words. **Special Cases:** - A `.VOCEND` directive without a preceding `.VOCBEG` directive is an error. **Error Conditions:** - An error occurs if the vocabulary area has an invalid length or structure. **Examples:** ``` {.assembly} .vocbeg 6, 3 ; Define vocabulary with 6-byte entries and 3-byte keys ; ... vocabulary words and data ... .vocend ``` **Use Cases:** - Defining the vocabulary of words that the game understands and can parse from player input. - Optimizing input parsing by sorting the vocabulary for efficient searching. **Note:** The `.VOCBEG` and `.VOCEND` directives are essential for defining and managing the vocabulary used by the `READ` and `LEX` instructions. Proper structure and usage of the vocabulary area are crucial for correct input parsing. ### .WORD The `.WORD` directive instructs the assembler to generate one or more word (two-byte) values in the object file. It is used to define word-sized data or initialize specific memory locations with word values. **Syntax:** ``` {.assembly} .word value1 [, value2 ...] ``` **Functionality:** The `.word` directive generates the specified word values sequentially in the object file. Each value can be: - **A constant expression:** Evaluates to a number within the range of -32768 to 65535. - **A symbol:** Refers to a previously defined symbol representing a word value. **Special Cases:** - If a single value is provided without the `.word` directive, it is implicitly treated as a `.word` directive. **Error Conditions:** An error occurs if a value exceeds the 16-bit word range. **Examples:** ``` {.assembly} .word 1000, 2000, 3000 ; Generates three words with values 1000, 2000, and 3000 .word counter ; Generates a word with the value of the symbol `counter` ``` **Use Cases:** - Defining word-sized data, such as numbers, pointers, or flags. - Initializing memory locations with specific word values. **Note:** The `.word` directive is a fundamental data definition directive used to generate word-sized data in Z-code programs. ### .ZWORD The `.ZWORD` directive generates a Z-word string in the object file. Z-word strings are similar to regular Z-strings but are limited to a maximum of two words (four bytes). They are used to store short text snippets or identifiers efficiently. **Syntax:** ``` {.assembly} .zword string ``` **Functionality:** The `.zword` directive performs the following: - **Encodes the string:** Converts the ASCII string into the Z-machine's 5-bit byte format, similar to the `.STR` directive but limited to two words. - **Outputs the string:** Generates the encoded string data in the object file. - **Pads the string:** If the string is less than two words, it is padded with the standard pad character (5) to fill the remaining space. **Special Cases:** - Z-word strings are always four bytes long, regardless of the actual string length. **Error Conditions:** An error occurs if the string length exceeds two words. **Examples:** ``` {.assembly} .zword "OK" ; Defines a Z-word string ``` **Use Cases:** - Storing short text snippets or identifiers efficiently. - Defining data structures that require fixed-length strings. **Note:** The `.ZWORD` directive is used for defining short strings that need to be stored efficiently. For longer strings, the `.STR` or `.GSTR` directives are more appropriate. ### ADD **ADD** is an opcode that performs addition on two 16-bit word values. It adds the first operand to the second operand and returns the result. **Syntax:** ``` {.assembly} add arg1:int, arg2:int > val ``` **Functionality:** The `add` opcode performs the following: - **Adds `arg1` and `arg2`:** Performs integer addition. - **Stores the result:** The sum is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If the result of the addition overflows the 16-bit word size, an error occurs. **Error Conditions:** An error occurs if the addition result overflows the 16-bit word range. **Examples:** ``` {.assembly} add 5, 10 > result ; Adds 5 and 10, stores the sum (15) in `result` ``` **Use Cases:** - Performing integer addition calculations. - Increasing values or accumulating totals. **Note:** The `add` opcode performs signed integer addition. If the operands are unsigned, the programmer needs to handle potential overflow conditions. ### ASHIFT **ASHIFT** is an opcode that performs an arithmetic shift on a 16-bit integer value. It shifts the bits of the operand to the left or right, depending on the specified shift amount. **Syntax:** ``` {.assembly} ashift int, n > val ``` **Functionality:** The `ashift` opcode performs the following: - **Shifts the bits of `int`:** - If `n` is positive, `int` is shifted left by `n` bits. - If `n` is negative, `int` is shifted right by the absolute value of `n` bits. - **Preserves the sign bit:** In an arithmetic shift, the sign bit of the operand is replicated to fill in the vacated bits during a right shift. This ensures that the sign of the number is preserved. - **Stores the result:** The shifted value is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If `n` is zero, the value of `int` remains unchanged. - If the shift amount exceeds the word size (16 bits), the result is undefined. **Error Conditions:** None. **Examples:** ``` {.assembly} ashift num, 2 > shifted ; Shifts the value in `num` left by 2 bits ashift num, -1 > shifted ; Shifts the value in `num` right by 1 bit ``` **Use Cases:** - Multiplying or dividing numbers by powers of two efficiently. - Manipulating individual bits within a word. - Implementing bitwise operations and algorithms. **Note:** The `ashift` opcode performs an arithmetic shift, which preserves the sign of the operand. For a logical shift, where the sign bit is not replicated, use the `shift` opcode. ### ASSIGNED? **ASSIGNED?** is an opcode that checks whether an optional argument was provided when calling the current function. It is used to implement conditional logic based on the presence or absence of optional arguments. **Syntax:** ``` {.assembly} assigned? opt:var /pred ``` **Functionality:** The `assigned?` opcode evaluates to true if an optional argument was supplied for the variable `opt`. Otherwise, it evaluates to false. The result is used to determine whether to take a conditional branch, as specified by the predicate (`/pred`) syntax. **Special Cases:** - The `assigned?` opcode can only be used within a function to check for optional arguments passed to that function. - The variable `opt` must be a local variable of the function. **Error Conditions:** An error occurs if `assigned?` is used outside of a function or if `opt` is not a local variable. **Examples:** ``` {.assembly} .funct my_function, optional_arg assigned? optional_arg / handle_optional ; ... code if optional_arg is not assigned ... handle_optional: ; ... code to handle optional_arg ... ``` **Use Cases:** - Implementing functions with optional arguments. - Performing different actions depending on whether optional arguments are provided. **Note:** The `assigned?` opcode is specific to the Z-machine and does not have a direct equivalent in most other assembly languages. It is a useful feature for implementing functions with flexible argument lists. ### BAND **BAND** is an opcode that performs a bitwise AND operation on two 16-bit word values. It combines the corresponding bits of the operands, setting each bit in the result to 1 only if both corresponding bits in the operands are also 1. **Syntax:** ``` {.assembly} band word1, word2 > val ``` **Functionality:** The `band` opcode performs the following: - **Performs bitwise AND:** Combines the corresponding bits of `word1` and `word2` using the logical AND operation. - **Stores the result:** The resulting word is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} band flags, mask > result ; Performs bitwise AND between `flags` and `mask` ``` **Use Cases:** - Masking out specific bits in a word. - Checking the state of individual bits or groups of bits. - Implementing bitwise algorithms and operations. **Note:** The `band` opcode is a fundamental bitwise operation used in various programming tasks, including data manipulation, flag handling, and low-level control. ### BCOM **BCOM** is an opcode that performs a bitwise complement (NOT) operation on a 16-bit word value. It inverts each bit in the operand, setting 1s to 0s and vice versa. **Syntax:** ``` {.assembly} bcom word > val ``` **Functionality:** The `bcom` opcode performs the following: - **Inverts the bits of `word`:** Flips each bit in the operand, changing 1s to 0s and 0s to 1s. - **Stores the result:** The resulting word is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} bcom flags > inverted ; Inverts the bits in the `flags` word ``` **Use Cases:** - Inverting the state of individual bits or groups of bits. - Implementing bitwise algorithms and operations. - Toggling the values of flags or status bits. **Note:** The `bcom` opcode is a fundamental bitwise operation used in various programming tasks, including data manipulation, flag handling, and low-level control. ### BOR **BOR** is an opcode that performs a bitwise OR operation on two 16-bit word values. It combines the corresponding bits of the operands, setting each bit in the result to 1 if either or both of the corresponding bits in the operands are 1. **Syntax:** ``` {.assembly} bor word1, word2 > val ``` **Functionality:** The `bor` opcode performs the following: - **Performs bitwise OR:** Combines the corresponding bits of `word1` and `word2` using the logical OR operation. - **Stores the result:** The resulting word is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} bor flags, mask > result ; Performs bitwise OR between `flags` and `mask` ``` **Use Cases:** - Setting specific bits in a word. - Combining flags or status bits. - Implementing bitwise algorithms and operations. **Note:** The `bor` opcode is a fundamental bitwise operation used in various programming tasks, including data manipulation, flag handling, and low-level control. ### BTST **BTST** is an opcode that tests whether specific bits are set in a 16-bit word value. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} btst word1, word2 /pred ``` **Functionality:** The `btst` opcode performs the following: - **Checks bit states:** Compares the corresponding bits of `word1` and `word2`. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if every bit that is set (1) in `word2` is also set in `word1`. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - If all bits in `word2` are 0, the predicate always succeeds. **Error Conditions:** None. **Examples:** ``` {.assembly} btst flags, mask / handle_flags ; Branch to `handle_flags` if all bits set in `mask` are also set in `flags` ``` **Use Cases:** - Checking the state of individual bits or groups of bits within a word. - Implementing conditional logic based on bit states. - Handling flags or status bits efficiently. **Note:** The `btst` opcode is a useful tool for working with bitwise data and implementing conditional behavior based on specific bit patterns. ### BUFOUT **BUFOUT** is an opcode that controls whether output to the screen is buffered or unbuffered. Buffering allows the interpreter to optimize line breaks and handle text wrapping more effectively. **Syntax:** ``` {.assembly} bufout int ``` **Functionality:** The `bufout` opcode sets the output buffering mode based on the value of `int`: - **`int` = 1:** Enables output buffering (default). Output is accumulated in a buffer and printed to the screen when a newline character is encountered or the buffer is full. - **`int` = 0:** Disables output buffering. All currently buffered output is immediately sent to the screen, and subsequent output is printed as it is generated. **Special Cases:** - Output redirected to a table using `DIROUT 3` is never buffered, regardless of the `bufout` setting. **Error Conditions:** An error occurs if `int` is not 0 or 1. **Examples:** ``` {.assembly} bufout 0 ; Disables output buffering print "Immediate output" bufout 1 ; Re-enables output buffering ``` **Use Cases:** - Disabling output buffering can be useful for displaying text immediately without waiting for a newline or buffer to fill. This might be used for real-time updates or interactive prompts. - In most cases, output buffering should be enabled to allow the interpreter to handle line breaks and text wrapping efficiently. **Note:** The `bufout` opcode is rarely needed in typical Z-code programs, as most output operations implicitly handle buffering as necessary. ### CALL **CALL** is an opcode that calls a function with three arguments and returns a value. It is the most general form of the function call instruction, allowing for a flexible number of arguments and return values. **Syntax:** ``` {.assembly} call fcn, arg1:any, arg2:any, arg3:any > val ``` **Functionality:** The `call` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the three arguments (`arg1`, `arg2`, and `arg3`) onto the game stack. - **Calls the function:** Transfers control to the function specified by `fcn`. The function address is calculated by shifting `fcn` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Retrieves return value:** When the function returns, its return value is retrieved and stored in the specified destination (`val`). If no destination is provided, the value is pushed onto the game stack. **Special Cases:** - If `fcn` is zero, the `call` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `fcn` is not a valid function pointer. **Examples:** ``` {.assembly} call process_input, input_buffer, parse_buffer, options > result ; Calls the `process_input` function with three arguments ``` **Use Cases:** - Calling functions with three arguments. - Implementing subroutines and modular code structures. **Note:** The `CALL` opcode is the most general form of the function call instruction. For functions with fewer arguments, the `CALL1` and `CALL2` opcodes can be used for more efficient encoding. The compiler automatically chooses the appropriate opcode based on the number of arguments and their types. ### CALL1 **CALL1** is an opcode that calls a function with one argument and returns a value. It is a more compact version of the `CALL` opcode, optimized for functions with a single argument. **Syntax:** ``` {.assembly} call1 fcn > val ``` **Functionality:** The `call1` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the single argument onto the game stack. - **Calls the function:** Transfers control to the function specified by `fcn`. The function address is calculated by shifting `fcn` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Retrieves return value:** When the function returns, its return value is retrieved and stored in the specified destination (`val`). If no destination is provided, the value is pushed onto the game stack. **Special Cases:** - If `fcn` is zero, the `call1` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `fcn` is not a valid function pointer. **Examples:** ``` {.assembly} call1 get_input > input_char ; Calls the `get_input` function and stores the returned character in `input_char` ``` **Use Cases:** - Calling functions with a single argument efficiently. - Implementing subroutines and modular code structures. **Note:** The `call1` opcode is generated by the compiler when it detects a function call with one argument. It is not typically used directly by programmers. ### CALL2 **CALL2** is an opcode that calls a function with two arguments and returns a value. It is a more compact version of the `CALL` opcode, optimized for functions with two arguments. **Syntax:** ``` {.assembly} call2 fcn, arg > val ``` **Functionality:** The `call2` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the two arguments (`fcn` and `arg`) onto the game stack. - **Calls the function:** Transfers control to the function specified by `fcn`. The function address is calculated by shifting `fcn` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Retrieves return value:** When the function returns, its return value is retrieved and stored in the specified destination (`val`). If no destination is provided, the value is pushed onto the game stack. **Special Cases:** - If `fcn` is zero, the `call2` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `fcn` is not a valid function pointer. **Examples:** ``` {.assembly} call2 add, num1, num2 > sum ; Calls the `add` function with `num1` and `num2` as arguments, stores the sum in `sum` ``` **Use Cases:** - Calling functions with two arguments efficiently. - Implementing subroutines and modular code structures. **Note:** The `call2` opcode is generated by the compiler when it detects a function call with two arguments. It is not typically used directly by programmers. ### CATCH **CATCH** is an opcode that captures an exception thrown by the `THROW` opcode and provides a way to handle it. It is used in conjunction with `THROW` to implement exception handling and non-local control flow. **Syntax:** ``` {.assembly} catch > frame ``` **Functionality:** The `catch` opcode performs the following: - **Captures exception:** If an exception has been thrown using the `THROW` opcode, the `catch` opcode captures it and prevents the program from terminating. - **Stores frame pointer:** The opcode stores a pointer to the current call frame in the specified destination (`frame`). This frame pointer identifies the point in the call stack where the exception was caught. - **Continues execution:** The program continues execution from the instruction following the `catch` opcode. **Special Cases:** - If no exception has been thrown, the `catch` opcode stores 0 in the `frame` variable and continues execution. - The `CATCH` and `THROW` opcodes do not work within "internal" calls, such as timeout handling routines called by `READ` or `INPUT`. **Error Conditions:** None. **Examples:** ``` {.assembly} catch > frame ; ... some code that might throw an exception ... if frame != 0 ; ... handle the exception ... ``` **Use Cases:** - Implementing exception handling to deal with errors or unexpected conditions. - Performing non-local control flow, such as exiting multiple nested functions at once. **Note:** The `CATCH` and `THROW` opcodes provide a mechanism for exception handling and non-local control flow in Z-code programs. They should be used with caution to avoid complex control flow and potential errors. ### CLEAR **CLEAR** is an opcode that clears a window or the entire screen, filling it with the current background color. **Syntax:** ``` {.assembly} clear window:int ``` **Functionality:** The `clear` opcode clears the specified window or the entire screen: - **`window` = 0 to 7:** Clears the corresponding window. - **`window` = -1:** Unsplits the screen (if it was previously split) and clears the entire screen. - **`window` = -2:** Clears the entire screen without affecting window attributes or cursor position. When a window is cleared, the cursor is moved to the top-left corner of that window. **Special Cases:** - If the `window` argument is omitted, the current window is cleared. **Error Conditions:** An error occurs if `window` is not within the valid range (-2 to 7). **Examples:** ``` {.assembly} clear 0 ; Clears the main window (window 0) clear -2 ; Clears the entire screen ``` **Use Cases:** - Clearing the screen or a window to prepare for new output. - Erasing previous content and resetting the display. **Note:** The `clear` opcode is a convenient way to clear the screen or a window. It is important to remember that clearing a window moves the cursor to its top-left corner. ### COLOR **COLOR** is an opcode that sets the foreground and background colors for subsequent text output. **Syntax:** ``` {.assembly} color fore:int, back:int ``` **Functionality:** The `color` opcode sets the colors for text output as follows: - **`fore`:** Specifies the foreground color (text color). - **`back`:** Specifies the background color. The colors are interpreted according to the following values: - **-1:** Use the color of the pixel at the current cursor position. - **0:** No change. - **1:** System default color. - **2:** Black. - **3:** Red. - **4:** Green. - **5:** Yellow. - **6:** Blue. - **7:** Magenta. - **8:** Cyan. - **9:** White. - **10:** Light gray - **11:** Gray - **12:** Dark gray **Special Cases:** - The availability of colors and their specific shades may vary depending on the target machine and display capabilities. - On some machines, like the Amiga, the colors set for the main window (window 0) are used for all windows. **Error Conditions:** An error occurs if `fore` or `back` is not within the valid range (-1 to 12). **Examples:** ``` {.assembly} color 3, 2 ; Sets foreground color to red and background color to black color 0, 1 ; Sets background color to the system default ``` **Use Cases:** - Changing the colors of text output for visual distinction or emphasis. - Enhancing the game's appearance and atmosphere. **Note:** Games should be designed to handle machines that do not support color selection. The `MODE` byte in the program header indicates whether the `COLOR` operation is available. ### COPYT **COPYT** is an opcode that copies a specified number of bytes from one table to another. It can also be used to zero out a section of memory or duplicate data within a table. **Syntax:** ``` {.assembly} copyt source:tbl, dest:tbl, length:int ``` **Functionality:** The `copyt` opcode copies bytes from the source table (`source`) to the destination table (`dest`) according to the specified `length`: - **Positive `length`:** Copies `length` bytes from `source` to `dest`. If the source and destination regions overlap, the opcode performs a "backwards" copy to avoid overwriting data before it is copied. - **Negative `length`:** Copies `length` bytes from `source` to `dest` without checking for overlap. This allows for data duplication within the source table. - **Zero `dest`:** If `dest` is zero, the opcode zeroes out `length` bytes in the source table. **Special Cases:** - The `copyt` opcode can be used to copy data to itself, allowing for shifting or duplication of data within a table. **Error Conditions:** An error occurs if: - `source` or `dest` is not a valid table pointer. - The copy operation would exceed the bounds of the tables. **Examples:** ``` {.assembly} copyt buffer1, buffer2, 100 ; Copies 100 bytes from buffer1 to buffer2 copyt table, 0, 50 ; Zeroes out the first 50 bytes of table copyt table, table + 10, 20 ; Duplicates 20 bytes within table, shifting them by 10 bytes ``` **Use Cases:** - Copying data between tables. - Zeroing out sections of memory. - Duplicating data within a table. - Implementing memory management or data manipulation routines. **Note:** The `copyt` opcode provides a flexible way to copy and manipulate data within tables. It is important to be aware of the overlap behavior when using positive lengths to avoid unintended data overwrites. ### CRLF **CRLF** is an opcode that prints an end-of-line sequence to the screen. This typically results in a carriage return and line feed, moving the cursor to the beginning of the next line. **Syntax:** ``` {.assembly} crlf ``` **Functionality:** The `crlf` opcode outputs an end-of-line sequence to the current window. The specific behavior depends on the window's attributes: - **Scrolling window:** The window contents scroll up by one line, and the cursor is moved to the beginning of the newly created empty line. - **Non-scrolling window:** The cursor is moved to the beginning of the next line within the window. If the window is full, the output may be clipped or overwritten. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} print "This is a line." crlf print "This is on the next line." ``` **Use Cases:** - Starting a new line of output. - Separating paragraphs or sections of text. - Formatting text display within windows. **Note:** The `crlf` opcode is a basic output operation used to control the vertical positioning of text on the screen. ### CURGET **CURGET** is an opcode that retrieves the current cursor position within a window and stores it in a table. **Syntax:** ``` {.assembly} curget output:tbl ``` **Functionality:** The `curget` opcode retrieves the current cursor position in the specified window and writes the coordinates into the `output` table: - **Word 0 of `output`:** Contains the Y coordinate of the cursor (row number, 1-based). - **Word 1 of `output`:** Contains the X coordinate of the cursor (column number, 1-based). **Special Cases:** - If the `window` argument is omitted, the current window is used. **Error Conditions:** An error occurs if: - `output` is not a valid table pointer. - The `output` table does not have enough space to store the coordinates (at least two words). **Examples:** ``` {.assembly} curget cursor_pos ; Retrieves the cursor position in the current window ``` **Use Cases:** - Determining the current cursor position for display or interaction purposes. - Implementing custom cursor movement or text editing routines. **Note:** While `CURGET` can be used to retrieve the cursor position, it is generally recommended to use the `WINGET` opcode with the appropriate offset values, as it provides more flexibility and can access other window properties as well. ### CURSET **CURSET** is an opcode that sets the cursor position within a window to specified coordinates. **Syntax:** ``` {.assembly} curset y:int, x:int [, window:int] ``` **Functionality:** The `curset` opcode sets the cursor position in the specified window to the coordinates (`y`, `x`): - **`y`:** The Y coordinate (row number, 1-based). - **`x`:** The X coordinate (column number, 1-based). If the coordinates are outside the window's boundaries, they are adjusted to the closest valid position within the window. **Special Cases:** - If the `window` argument is omitted, the current window is used. - If `y` is -1, the cursor is turned off. - If `y` is -2, the cursor is turned on. In this case, the `x` argument is ignored. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `y` or `x` is negative (except for the special cases mentioned above). **Examples:** ``` {.assembly} curset 5, 10 ; Sets the cursor to row 5, column 10 in the current window curset 1, 1, 2 ; Sets the cursor to the top-left corner of window 2 curset -1 ; Turns off the cursor ``` **Use Cases:** - Positioning the cursor for text output or user interaction. - Implementing custom cursor movement or text editing routines. **Note:** The `curset` opcode provides a direct way to set the cursor position. However, for more complex window manipulations, consider using the `WINPOS` and `WINSIZE` opcodes. ### DCLEAR **DCLEAR** is an opcode that clears the area occupied by a previously displayed picture, restoring the window's background color. **Syntax:** ``` {.assembly} dclear picture:int [, y:int, x:int] ``` **Functionality:** The `dclear` opcode clears the area of the specified picture: - **`picture`:** The ID number of the picture to clear. - **`y` and `x` (optional):** The coordinates where the picture was displayed (in pixels). If omitted, the opcode uses the coordinates where the picture was last displayed. The opcode restores the window's background color in the area previously occupied by the picture. **Special Cases:** None. **Error Conditions:** An error occurs if: - `picture` is not a valid picture ID. - The coordinates (`y`, `x`) are outside the window's boundaries. **Examples:** ``` {.assembly} display 10, 10, 10 ; Displays picture 10 at coordinates (10, 10) dclear 10 ; Clears the area occupied by picture 10 ``` **Use Cases:** - Removing pictures from the screen. - Restoring the window's background color after displaying a picture. **Note:** The `DCLEAR` opcode is used in conjunction with the `DISPLAY` opcode to manage the display of pictures within Z-code programs. ### DEC **DEC** is an opcode that decrements the value of a variable by 1. **Syntax:** ``` {.assembly} dec var ``` **Functionality:** The `dec` opcode subtracts 1 from the value of the specified variable (`var`). **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} dec counter ; Decrements the value of the variable `counter` ``` **Use Cases:** - Decrementing counters or loop variables. - Reducing the value of a variable by a fixed amount. **Note:** The `dec` opcode is a convenient way to decrement a variable by 1. For more complex arithmetic operations, use the `SUB` opcode. ### DIRIN **DIRIN** is an opcode that redirects input from a specified device. It allows the Z-code program to receive input from sources other than the keyboard, such as command files or scripts. **Syntax:** ``` {.assembly} dirin device:int [, any1, any2, any3] ``` **Functionality:** The `dirin` opcode redirects input based on the value of `device`: - **`device` = 0:** Keyboard input (default). - **`device` = 1:** Command file input. The interpreter reads input from a previously created command file, typically generated using `DIROUT 4`. The additional arguments (`any1`, `any2`, `any3`) are currently unused and should be ignored by the interpreter. **Special Cases:** - Not all interpreters implement command file input. If the interpreter does not support it, the `dirin 1` instruction should be ignored. **Error Conditions:** An error occurs if `device` is not 0 or 1. **Examples:** ``` {.assembly} dirin 1 ; Redirects input to the command file ``` **Use Cases:** - Reading commands from a script file for automated testing or gameplay recording. - Implementing custom input methods or interactive sequences. **Note:** The `dirin` opcode is used in conjunction with `DIROUT` to manage input and output redirection. ### DIROUT **DIROUT** is an opcode that redirects output to a specified device. It allows the Z-code program to send output to destinations other than the screen, such as the transcript or a table. **Syntax:** ``` {.assembly} dirout device:int [, any1, any2, any3] ``` **Functionality:** The `dirout` opcode redirects output based on the value of `device`: - **`device` = 1:** Screen output (default). - **`device` = -1:** Disables screen output. - **`device` = 2:** Transcript output. Sends all subsequent output to the transcript device, which can be a file, printer, or other suitable destination. - **`device` = -2:** Disables transcript output. - **`device` = 3:** Table output. Sends output to the table specified by `any1`. The `any2` argument can optionally specify justification for formatted tables. - **`device` = -3:** Disables table output. - **`device` = 4:** Command recording. Creates a command file and writes all subsequent input commands to it. - **`device` = -4:** Disables command recording. **Special Cases:** - If the screen device is disabled and the transcript device is enabled, output is still sent to the transcript. - Table output using `dirout 3` is not buffered, regardless of the `BUFOUT` setting. - Not all interpreters implement command recording (device 4). **Error Conditions:** An error occurs if `device` is not within the valid range (-4 to 4). **Examples:** ``` {.assembly} dirout 2 ; Enables transcript output dirout -1 ; Disables screen output dirout 3, table, 80 ; Redirects output to `table` with right justification at 80 pixels ``` **Use Cases:** - Sending output to the transcript for debugging or recording purposes. - Creating formatted tables for display using `PRINTF`. - Recording player input commands for testing or analysis. **Note:** The `dirout` opcode is used in conjunction with `DIRIN` to manage input and output redirection. ### DISPLAY **DISPLAY** is an opcode that displays a picture at a specified location on the screen. Pictures are images stored in a separate picture file and referenced by their ID numbers. **Syntax:** ``` {.assembly} display picture:int [, y:int, x:int] ``` **Functionality:** The `display` opcode displays the picture with the specified ID number (`picture`) at the given coordinates (`y`, `x`) in pixels: - **`picture`:** The ID number of the picture to display. - **`y` and `x` (optional):** The coordinates where the picture should be displayed, relative to the top-left corner of the current window. If omitted, the opcode uses the current cursor position. **Special Cases:** - If the picture ID is 0, the opcode does nothing. - If the coordinates are outside the window's boundaries, the picture may be clipped or partially displayed. **Error Conditions:** An error occurs if: - `picture` is not a valid picture ID. - The coordinates (`y`, `x`) are outside the window's boundaries. **Examples:** ``` {.assembly} display 10, 10, 10 ; Displays picture 10 at coordinates (10, 10) in the current window display 5 ; Displays picture 5 at the current cursor position ``` **Use Cases:** - Displaying images and graphics on the screen. - Creating visual elements for the game world or user interface. **Note:** The `DISPLAY` opcode requires the interpreter to support picture display. The `MODE` byte in the program header indicates whether the `DISPLAY` operation is available. ### DIV **DIV** is an opcode that performs integer division on two 16-bit word values. It divides the first operand by the second operand and returns the truncated quotient. **Syntax:** ``` {.assembly} div arg1:int, arg2:int > val ``` **Functionality:** The `div` opcode performs the following: - **Divides `arg1` by `arg2`:** Performs integer division, discarding any remainder. - **Stores the result:** The quotient is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - Division by zero results in an error. **Error Conditions:** An error occurs if `arg2` is zero. **Examples:** ``` {.assembly} div 10, 2 > result ; Divides 10 by 2, stores the quotient (5) in `result` ``` **Use Cases:** - Performing integer division calculations. - Scaling values or calculating ratios. **Note:** The `div` opcode performs integer division, meaning it discards any remainder. For operations that require the remainder, use the `MOD` opcode. ### DLESS? **DLESS?** is an opcode that decrements a variable and then checks if the new value is less than a specified integer. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} dless? var, int /pred ``` **Functionality:** The `dless?` opcode performs the following: - **Decrements `var`:** Subtracts 1 from the value of the variable `var`. - **Compares with `int`:** Checks if the new value of `var` is less than `int`. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if the new value of `var` is indeed less than `int`. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} dless? counter, 0 / end_loop ; Branch to `end_loop` if `counter` is decremented to a value less than 0 ``` **Use Cases:** - Implementing loops or conditional statements that depend on decrementing a variable and comparing it to a threshold. - Optimizing code by combining decrement and comparison operations into a single instruction. **Note:** The `dless?` opcode is a useful tool for writing efficient and concise code when dealing with decrementing variables and comparisons. ### EQUAL? **EQUAL?** is an opcode that checks whether its first operand is equal to any of the subsequent operands. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} equal? arg1:any, arg2:any [, arg3:any ...] /pred ``` **Functionality:** The `equal?` opcode performs the following: - **Compares `arg1` with other arguments:** Checks if `arg1` is equal to any of the `arg2`, `arg3`, etc., operands. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if `arg1` is equal to at least one of the other arguments. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - The `equal?` opcode can take a variable number of operands in the extended (`EXT`) format. The 2OP format is limited to two operands. **Error Conditions:** None. **Examples:** ``` {.assembly} equal? object, "sword", "axe" / handle_weapon ; Branch to `handle_weapon` if `object` is equal to either "sword" or "axe" ``` **Use Cases:** - Implementing conditional logic based on equality comparisons. - Checking if a variable or object matches one of several possible values. **Note:** The `equal?` opcode is a versatile tool for performing equality checks and implementing conditional behavior based on the results. ### ERASE **ERASE** is an opcode that erases a portion of the current window, filling it with the current background color. **Syntax:** ``` {.assembly} erase int ``` **Functionality:** The `erase` opcode erases a section of the current window based on the value of `int`: - **`int` = 1:** Erases from the current cursor position to the end of the line. - **`int` \> 1:** Erases a rectangular area starting at the current cursor position, with a width of `int` pixels and a height equal to the current font height. The erased area does not extend past the right edge of the window. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} erase 1 ; Erases from the cursor to the end of the line erase 20 ; Erases a 20-pixel wide rectangle starting at the cursor ``` **Use Cases:** - Erasing text or graphics from the screen. - Clearing portions of the window for new output. **Note:** The `ERASE` opcode is used to selectively erase parts of the window. For clearing the entire window, use the `CLEAR` opcode. ### EXTOP **EXTOP** is an opcode that signals to the interpreter that the next byte is an extended opcode. Extended opcodes are part of an additional set of 256 instructions beyond the standard opcode set. **Syntax:** ``` {.assembly} extop opcode:int ``` **Functionality:** The `extop` opcode itself does not perform any operation. Instead, it indicates that the following byte (`opcode`) should be interpreted as an extended opcode. The interpreter adds 256 to the value of `opcode` to obtain the actual extended opcode number. **Special Cases:** - The `extop` opcode is never explicitly used by programmers. It is generated by the assembler when encoding instructions that require the extended format. **Error Conditions:** An error occurs if `opcode` is not a valid extended opcode number. **Examples:** The `extop` opcode is not used directly in assembly code. It is handled internally by the assembler and interpreter. **Use Cases:** The `extop` opcode allows ZAP to generate a wider range of instructions while maintaining backward compatibility with older ZIP interpreters that only recognize the standard opcode set. **Note:** The `extop` opcode is a low-level mechanism used by the assembler and interpreter to handle extended opcodes. Programmers do not need to be concerned with its usage directly. ### FCLEAR **FCLEAR** is an opcode that clears a specific flag within an object's flag list. Objects have 48 one-bit flags that can be used to track their state or attributes. **Syntax:** ``` {.assembly} fclear obj, flag ``` **Functionality:** The `fclear` opcode sets the specified flag (`flag`) in the object (`obj`) to 0. **Special Cases:** None. **Error Conditions:** An error occurs if: - `obj` is not a valid object number. - `flag` is not within the valid range (0-47). **Examples:** ``` {.assembly} fclear player, 10 ; Clears flag number 10 in the "player" object ``` **Use Cases:** - Resetting flags or attributes associated with objects. - Changing the state of objects based on game logic or player actions. **Note:** The `FCLEAR` opcode is used to clear individual flags within an object. To set a flag, use the `FSET` opcode. ### FIRST? **FIRST?** is an opcode that retrieves the "first" property of an object and checks if it is non-zero. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} first? obj > val /pred ``` **Functionality:** The `first?` opcode performs the following: - **Retrieves "first" property:** Gets the value of the "first" slot within the object (`obj`). This slot typically contains the object number of the first object contained within `obj`. - **Checks for non-zero value:** Evaluates to true if the retrieved value is not zero (meaning there is a "first" object). Otherwise, it evaluates to false. - **Stores the value (optional):** If the `> val` operand is provided, the retrieved value is also stored in the specified variable. - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - If the object `obj` does not have any contained objects, the "first" slot will be zero, and the predicate will fail. **Error Conditions:** An error occurs if `obj` is not a valid object number. **Examples:** ``` {.assembly} first? container > first_item / process_item ; Branch to `process_item` if `container` has a "first" object ``` **Use Cases:** - Checking if an object contains other objects. - Iterating through a chain of objects linked by their "next" properties. - Implementing inventory management or object interaction logic. **Note:** The `FIRST?` opcode is used to access and check the "first" property of an object. To retrieve the "next" property in a chain, use the `NEXT?` opcode. ### FONT **FONT** is an opcode that selects a font for text output in a specified window. Fonts determine the style and appearance of the displayed text. **Syntax:** ``` {.assembly} font font:int, window:int > val ``` **Functionality:** The `font` opcode sets the font for the specified window (`window`) to the font identified by `font`: - **`font`:** The ID number of the font to select. - **`window`:** The window number where the font should be applied. The opcode returns the ID number of the previously selected font for the window. **Special Cases:** - If the `window` argument is omitted, the current window is used. - Font 1 is typically the "normal" font for the machine and is selected by default for all windows. - Some interpreters may not support all font IDs or may have different fonts available. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `font` is not a valid font ID. **Examples:** ``` {.assembly} font 4, 0 ; Selects the monospace font for the main window (window 0) font 2, 3 ; Selects font 2 for window 3 ``` **Use Cases:** - Changing the appearance of text for visual distinction or emphasis. - Displaying text in different styles, such as bold, italic, or monospace. - Enhancing the game's visual presentation and atmosphere. **Note:** The `FONT` opcode requires the interpreter to support font selection. The `MODE` byte in the program header indicates whether the `FONT` operation is available. ### FSET **FSET** is an opcode that sets a specific flag within an object's flag list to 1. Objects have 48 one-bit flags that can be used to track their state or attributes. **Syntax:** ``` {.assembly} fset obj, flag ``` **Functionality:** The `fset` opcode sets the specified flag (`flag`) in the object (`obj`) to 1. **Special Cases:** None. **Error Conditions:** An error occurs if: - `obj` is not a valid object number. - `flag` is not within the valid range (0-47). **Examples:** ``` {.assembly} fset player, 5 ; Sets flag number 5 in the "player" object to 1 ``` **Use Cases:** - Setting flags or attributes associated with objects. - Changing the state of objects based on game logic or player actions. **Note:** The `FSET` opcode is used to set individual flags within an object. To clear a flag, use the `FCLEAR` opcode. ### FSET? **FSET?** is an opcode that checks whether a specific flag is set within an object's flag list. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} fset? obj, flag /pred ``` **Functionality:** The `fset?` opcode performs the following: - **Checks flag state:** Determines whether the specified flag (`flag`) in the object (`obj`) is set (1) or cleared (0). - **Evaluates predicate:** The predicate succeeds (evaluates to true) if the flag is set. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** None. **Error Conditions:** An error occurs if: - `obj` is not a valid object number. - `flag` is not within the valid range (0-47). **Examples:** ``` {.assembly} fset? player, 15 / handle_flag ; Branch to `handle_flag` if flag number 15 in the "player" object is set ``` **Use Cases:** - Implementing conditional logic based on the state of object flags. - Checking for specific object attributes or conditions. **Note:** The `FSET?` opcode is used to test the state of individual flags within an object. To set or clear a flag, use the `FSET` or `FCLEAR` opcodes, respectively. ### FSTACK **FSTACK** is an opcode that flushes (removes) a specified number of elements from a stack. It can be used to clear the game stack or a user-defined stack. **Syntax:** ``` {.assembly} fstack n [, stack:tbl] ``` **Functionality:** The `fstack` opcode removes elements from a stack as follows: - **`n`:** The number of elements to flush from the stack. - **`stack` (optional):** A pointer to a table representing a user-defined stack. If omitted, the opcode flushes elements from the game stack. The opcode does not return any value. **Special Cases:** - Flushing more elements than are present on the stack is an error. **Error Conditions:** An error occurs if: - `n` is negative. - `stack` is not a valid table pointer (if provided). - Attempting to flush more elements than are present on the stack. **Examples:** ``` {.assembly} fstack 3 ; Flushes 3 elements from the game stack fstack 2, user_stack ; Flushes 2 elements from the `user_stack` table ``` **Use Cases:** - Clearing the game stack before calling a function or performing a specific operation. - Resetting user-defined stacks to a known state. **Note:** The `FSTACK` opcode is used to remove elements from stacks. To add elements, use the `PUSH` or `XPUSH` opcodes. ### GET **GET** is an opcode that retrieves the value of an element from a word-oriented table. It is used to access data stored in tables based on their index or offset. **Syntax:** ``` {.assembly} get table, item > val ``` **Functionality:** The `get` opcode performs the following: - **Calculates element address:** Multiplies the `item` (index or offset) by 2 and adds it to the base address of the `table`. This gives the address of the desired element in memory. - **Retrieves the value:** Reads the word value at the calculated address. - **Stores the result:** The retrieved value is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - Table offsets are zero-based, meaning the first element has an index of 0. - The interpreter does not perform bounds checking on table accesses. It is the programmer's responsibility to ensure that `item` is within the valid range of the table. **Error Conditions:** An error may occur if: - `table` is not a valid table pointer. - `item` is outside the bounds of the table. **Examples:** ``` {.assembly} get inventory, 3 > item ; Retrieves the 4th element from the `inventory` table and stores it in `item` ``` **Use Cases:** - Accessing data stored in tables based on their index or offset. - Implementing data structures and algorithms that rely on table lookups. **Note:** The `GET` opcode is used for accessing word-sized elements in tables. For byte-sized elements, use the `GETB` opcode. ### GETB **GETB** is an opcode that retrieves the value of an element from a byte-oriented table. It is used to access data stored in tables based on their index or offset. **Syntax:** ``` {.assembly} getb table, item > val ``` **Functionality:** The `getb` opcode performs the following: - **Calculates element address:** Adds the `item` (index or offset) to the base address of the `table`. This gives the address of the desired element in memory. - **Retrieves the value:** Reads the byte value at the calculated address. - **Converts to word:** The retrieved byte value is converted to a word (two bytes). - **Stores the result:** The word value is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - Table offsets are zero-based, meaning the first element has an index of 0. - The interpreter does not perform bounds checking on table accesses. It is the programmer's responsibility to ensure that `item` is within the valid range of the table. **Error Conditions:** An error may occur if: - `table` is not a valid table pointer. - `item` is outside the bounds of the table. **Examples:** ``` {.assembly} getb text_buffer, 5 > char ; Retrieves the 6th byte from the `text_buffer` table and stores it as a word in `char` ``` **Use Cases:** - Accessing data stored in byte-oriented tables. - Reading individual characters from text buffers. - Implementing data structures and algorithms that rely on byte-level table access. **Note:** The `GETB` opcode is used for accessing byte-sized elements in tables. For word-sized elements, use the `GET` opcode. ### GETP **GETP** is an opcode that retrieves the value of a property from an object. Properties are used to associate additional data and attributes with objects. **Syntax:** ``` {.assembly} getp obj, prop > val ``` **Functionality:** The `getp` opcode performs the following: - **Locates property table:** Finds the property table associated with the object (`obj`). - **Searches for property:** Searches the property table for the property with the specified number (`prop`). - **Retrieves the value:** If the property is found, its value is retrieved. - **Handles default properties:** If the property is not found in the object's property table, the opcode retrieves the default value from the default property table. - **Stores the result:** The retrieved value is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - Properties are stored in a sorted order within the object's property table. - The `GETP` opcode can only be used to retrieve properties with a length of 1 or 2 bytes. For properties of arbitrary length, use the `GETPT` opcode. **Error Conditions:** An error occurs if: - `obj` is not a valid object number. - `prop` is not within the valid range (1-63). **Examples:** ``` {.assembly} getp player, 1 > strength ; Retrieves the value of property 1 ("strength") from the "player" object ``` **Use Cases:** - Accessing data associated with objects through properties. - Retrieving object attributes or characteristics. **Note:** The `GETP` opcode is used to retrieve properties with a length of 1 or 2 bytes. For properties of arbitrary length, use the `GETPT` opcode. ### GETPT **GETPT** is an opcode that retrieves a pointer to a property within an object's property table. Unlike `GETP`, which can only retrieve properties of 1 or 2 bytes, `GETPT` can access properties of any length. **Syntax:** ``` {.assembly} getpt obj, prop > val ``` **Functionality:** The `getpt` opcode performs the following: - **Locates property table:** Finds the property table associated with the object (`obj`). - **Searches for property:** Searches the property table for the property with the specified number (`prop`). - **Retrieves the pointer:** If the property is found, a pointer to its value is retrieved. - **Handles default properties:** If the property is not found in the object's property table, the opcode retrieves a pointer to the default value from the default property table. - **Stores the result:** The retrieved pointer is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - Properties are stored in a sorted order within the object's property table. - The retrieved pointer can be used as a table pointer in other table operations like `GET`, `GETB`, `PUT`, and `PUTB`. **Error Conditions:** An error occurs if: - `obj` is not a valid object number. - `prop` is not within the valid range (1-63). **Examples:** ``` {.assembly} getpt object, 10 > prop_ptr ; Retrieves a pointer to property 10 of `object` getb prop_ptr, 0 > first_byte ; Retrieves the first byte of the property value ``` **Use Cases:** - Accessing properties of arbitrary length. - Implementing data structures or algorithms that require accessing variable-length properties. **Note:** The `GETPT` opcode is used to retrieve pointers to properties, while `GETP` is used to directly retrieve property values of 1 or 2 bytes. ### GRTR? **GRTR?** is an opcode that compares two integer values and checks if the first operand is greater than the second operand. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} grtr? arg1:int, arg2:int /pred ``` **Functionality:** The `grtr?` opcode performs the following: - **Compares `arg1` and `arg2`:** Checks if the integer value `arg1` is greater than `arg2`. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if `arg1` is indeed greater than `arg2`. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} grtr? health, 0 / game_over ; Branch to `game_over` if `health` is greater than 0 ``` **Use Cases:** - Implementing conditional logic based on greater-than comparisons. - Making decisions based on numerical values, such as health, score, or inventory counts. **Note:** The `grtr?` opcode is a basic comparison operator used for implementing conditional behavior in Z-code programs. ### HLIGHT **HLIGHT** is an opcode that sets the highlighting mode for subsequent text output. Highlighting can be used to emphasize text, change its appearance, or create special visual effects. **Syntax:** ``` {.assembly} hlight int ``` **Functionality:** The `hlight` opcode sets the highlighting mode based on the value of `int`: - **`int` = 0:** No highlighting (normal text). - **`int` = 1:** Inverse video (text and background colors are swapped). - **`int` = 2:** Bold text. - **`int` = 4:** Underline or italic text (implementation-dependent). - **`int` = 8:** Monospaced font. **Special Cases:** - The availability of highlighting modes depends on the capabilities of the interpreter and the target machine. - The `MODE` byte in the program header specifies which highlighting modes are supported. - The monospace font mode may either select an actual monospaced font or modify the display of a variable-width font to appear monospaced. **Error Conditions:** An error occurs if `int` specifies an unsupported highlighting mode. **Examples:** ``` {.assembly} hlight 2 ; Sets bold text highlighting print "Important message!" hlight 0 ; Resets to normal text ``` **Use Cases:** - Emphasizing important text or messages. - Creating visual distinctions between different types of text. - Implementing special visual effects or text-based graphics. **Note:** Games should be designed to handle machines that do not support all highlighting modes. The `MODE` byte can be used to check which modes are available. ### ICALL **ICALL** is an opcode that calls a function with three arguments but does not return a value. It is similar to the `CALL` opcode but optimized for situations where the function's return value is not needed. **Syntax:** ``` {.assembly} icall routine:fcn, arg1:any, arg2:any, arg3:any ``` **Functionality:** The `icall` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the three arguments (`arg1`, `arg2`, and `arg3`) onto the game stack. - **Calls the function:** Transfers control to the function specified by `routine`. The function address is calculated by shifting `routine` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Does not retrieve return value:** When the function returns, its return value is discarded. **Special Cases:** - If `routine` is zero, the `icall` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `routine` is not a valid function pointer. **Examples:** ``` {.assembly} icall update_score, player, points, bonus ; Calls the `update_score` function without using its return value ``` **Use Cases:** - Calling functions where the return value is not needed, reducing stack usage and potential stack overflows. - Implementing subroutines or actions that do not produce a result. **Note:** The `icall` opcode is generated by the compiler when it detects a function call where the return value is not used. It is not typically used directly by programmers. ### ICALL1 **ICALL1** is an opcode that calls a function with one argument but does not return a value. It is similar to the `CALL1` opcode but optimized for situations where the function's return value is not needed. **Syntax:** ``` {.assembly} icall1 routine:fcn ``` **Functionality:** The `icall1` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the single argument onto the game stack. - **Calls the function:** Transfers control to the function specified by `routine`. The function address is calculated by shifting `routine` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Does not retrieve return value:** When the function returns, its return value is discarded. **Special Cases:** - If `routine` is zero, the `icall1` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `routine` is not a valid function pointer. **Examples:** ``` {.assembly} icall1 play_sound, sound_id ; Calls the `play_sound` function without using its return value ``` **Use Cases:** - Calling functions with a single argument where the return value is not needed, reducing stack usage and potential stack overflows. - Implementing subroutines or actions that do not produce a result. **Note:** The `icall1` opcode is generated by the compiler when it detects a function call with one argument where the return value is not used. It is not typically used directly by programmers. ### ICALL2 **ICALL2** is an opcode that calls a function with two arguments but does not return a value. It is similar to the `CALL2` opcode but optimized for situations where the function's return value is not needed. **Syntax:** ``` {.assembly} icall2 routine:fcn, arg:any ``` **Functionality:** The `icall2` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the two arguments (`routine` and `arg`) onto the game stack. - **Calls the function:** Transfers control to the function specified by `routine`. The function address is calculated by shifting `routine` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Does not retrieve return value:** When the function returns, its return value is discarded. **Special Cases:** - If `routine` is zero, the `icall2` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `routine` is not a valid function pointer. **Examples:** ``` {.assembly} icall2 set_color, foreground, background ; Calls the `set_color` function without using its return value ``` **Use Cases:** - Calling functions with two arguments where the return value is not needed, reducing stack usage and potential stack overflows. - Implementing subroutines or actions that do not produce a result. **Note:** The `icall2` opcode is generated by the compiler when it detects a function call with two arguments where the return value is not used. It is not typically used directly by programmers. ### IGRTR? **IGRTR?** is an opcode that increments a variable and then checks if the new value is greater than a specified integer. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} igrtr? var, int /pred ``` **Functionality:** The `igrtr?` opcode performs the following: - **Increments `var`:** Adds 1 to the value of the variable `var`. - **Compares with `int`:** Checks if the new value of `var` is greater than `int`. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if the new value of `var` is indeed greater than `int`. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} igrtr? counter, limit / overflow ; Branch to `overflow` if `counter` is incremented to a value greater than `limit` ``` **Use Cases:** - Implementing loops or conditional statements that depend on incrementing a variable and comparing it to a threshold. - Optimizing code by combining increment and comparison operations into a single instruction. **Note:** The `igrtr?` opcode is a useful tool for writing efficient and concise code when dealing with incrementing variables and comparisons. ### IN? **IN?** is an opcode that checks whether one object is contained within another object. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} in? child:obj, parent:obj /pred ``` **Functionality:** The `in?` opcode performs the following: - **Checks containment:** Compares the `LOC` property of the `child` object with the object number of the `parent` object. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if the `LOC` of `child` is equal to `parent`, meaning `child` is contained within `parent`. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - An object is considered to be contained within itself. **Error Conditions:** An error occurs if `child` or `parent` is not a valid object number. **Examples:** ``` {.assembly} in? item, player / take_item ; Branch to `take_item` if `item` is contained within the "player" object ``` **Use Cases:** - Implementing inventory management and object interaction logic. - Checking the location of objects within the game world. - Determining containment relationships between objects. **Note:** The `IN?` opcode is a fundamental operation for working with object hierarchies and containment in Z-code programs. ### INC **INC** is an opcode that increments the value of a variable by 1. **Syntax:** ``` {.assembly} inc var ``` **Functionality:** The `inc` opcode adds 1 to the value of the specified variable (`var`). **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} inc counter ; Increments the value of the variable `counter` ``` **Use Cases:** - Incrementing counters or loop variables. - Increasing the value of a variable by a fixed amount. **Note:** The `inc` opcode is a convenient way to increment a variable by 1. For more complex arithmetic operations, use the `ADD` opcode. ### INPUT **INPUT** is an opcode that reads a single byte of input from a specified device, typically the keyboard. It allows the Z-code program to receive input from the user or other input sources. **Syntax:** ``` {.assembly} input dev:int [, time:int, routine:fcn] > val ``` **Functionality:** The `input` opcode reads input based on the value of `dev`: - **`dev` = 1:** Keyboard input (default). The opcode reads the next key pressed by the user and returns its ASCII value. - **Other values of `dev`:** May be used for other input devices, but their behavior is implementation-dependent. **Optional Arguments:** - **`time`:** Specifies a timeout value in tenths of a second. If no input is received within the specified time, the interpreter calls the `routine` function. - **`routine`:** A function to call when a timeout occurs. The function should return true (1) to abort the input operation or false (0) to continue waiting for input. **Return Value:** The `input` opcode returns the value of the input byte, which is stored in the specified destination (`val`). If no destination is provided, the value is pushed onto the game stack. **Special Cases:** - Function keys and other special keys may return values greater than 127, with the high bit of the byte set. - The interpreter may handle timeout behavior differently depending on the target machine and implementation. **Error Conditions:** An error occurs if: - `dev` is not a valid device code. - `time` is negative (if provided). - `routine` is not a valid function pointer (if provided). **Examples:** ``` {.assembly} input 1 > key ; Reads a key from the keyboard and stores its ASCII value in `key` input 1, 50, handle_timeout > key ; Reads a key with a 5-second timeout ``` **Use Cases:** - Getting input from the user, such as commands, responses, or key presses. - Implementing timed input or interactive sequences. **Note:** The `INPUT` opcode is a fundamental operation for receiving input in Z-code programs. The specific behavior and available devices may vary depending on the interpreter and target machine. ### INTBL? **INTBL?** is an opcode that searches for a specific item within a table and returns a pointer to its location if found. It acts as both an opcode and a predicate, meaning it can return a value and also influence control flow based on the search result. **Syntax:** ``` {.assembly} intbl? item, table, length:int [, record-spec:int] > val /pred ``` **Functionality:** The `intbl?` opcode performs the following: - **Searches for `item`:** Looks for the specified `item` within the `table`. - **Table length:** The `length` argument specifies the number of elements to search within the table. - **Record specification (optional):** The `record-spec` argument, if provided, defines the format of each element in the table. It is a byte value where: - The high-order bit indicates whether the table elements are words (1) or bytes (0). - The low-order seven bits specify the length of each element in bytes. - **Returns a pointer:** If `item` is found, the opcode returns a pointer to its location within the table. Otherwise, it returns 0. - **Stores the result (optional):** If the `> val` operand is provided, the returned pointer is also stored in the specified variable. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if `item` is found in the table. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - If `record-spec` is omitted or 0, it defaults to 130 (word-oriented elements with a length of 2 bytes). **Error Conditions:** An error occurs if: - `table` is not a valid table pointer. - `length` is negative. **Examples:** ``` {.assembly} intbl? "north", directions, 4 > direction_ptr / handle_direction ; Searches for "north" in the `directions` table intbl? char, buffer, buffer_length, 1 > char_ptr / process_char ; Searches for `char` in a byte-oriented buffer ``` **Use Cases:** - Searching for specific elements within tables. - Implementing data structures and algorithms that require table lookups. - Performing conditional logic based on search results. **Note:** The `INTBL?` opcode is a versatile tool for searching tables and implementing conditional behavior based on the results. The optional `record-spec` argument allows for searching tables with different element formats. ### IRESTORE **IRESTORE** is an opcode that restores the game state from a previously saved copy in memory. It is used to implement a single-level undo functionality. **Syntax:** ``` {.assembly} irestore > val ``` **Functionality:** The `irestore` opcode restores the game state from a copy of the impure area that was previously saved using the `ISAVE` opcode. The impure area contains all modifiable data in the Z-code program, including global variables, object flags, and table contents. **Return Value:** The `irestore` opcode returns 0 if it fails or if the instruction is not implemented on the target machine. Otherwise, it returns -1. **Special Cases:** - The `IRESTORE` opcode only works if a previous `ISAVE` operation was successful. - The interpreter may not implement the `ISAVE` and `IRESTORE` opcodes on all machines. **Error Conditions:** None. **Examples:** ``` {.assembly} isave ; Saves the current game state ; ... some actions that modify the game state ... irestore ; Restores the previously saved game state ``` **Use Cases:** - Implementing an undo feature in the game. - Restoring the game state to a previous point after an error or unexpected event. **Note:** The `ISAVE` and `IRESTORE` opcodes provide a simple mechanism for implementing undo functionality. However, they are not supported on all interpreters and may require additional memory resources. ### ISAVE **ISAVE** is an opcode that saves a copy of the current game state in memory. It is used in conjunction with the `IRESTORE` opcode to implement a single-level undo functionality. **Syntax:** ``` {.assembly} isave > val ``` **Functionality:** The `isave` opcode copies the impure area of the Z-code program to a reserved section of memory. The impure area contains all modifiable data, including global variables, object flags, and table contents. **Return Value:** The `isave` opcode returns 0 if it fails or if the instruction is not implemented on the target machine. Otherwise, it returns -1. **Special Cases:** - The interpreter may not implement the `ISAVE` and `IRESTORE` opcodes on all machines. - The reserved memory area for storing the saved game state may have limited size. **Error Conditions:** None. **Examples:** ``` {.assembly} isave ; Saves the current game state ; ... some actions that modify the game state ... irestore ; Restores the previously saved game state ``` **Use Cases:** - Implementing an undo feature in the game. - Saving the game state before performing an action that might have unintended consequences. **Note:** The `ISAVE` and `IRESTORE` opcodes provide a simple mechanism for implementing undo functionality. However, they are not supported on all interpreters and may require additional memory resources. ### IXCALL **IXCALL** is an opcode that calls a function with a variable number of arguments but does not return a value. It is similar to the `XCALL` opcode but optimized for situations where the function's return value is not needed. **Syntax:** ``` {.assembly} ixcall routine:fcn, arg1:any [, arg2:any ...] ``` **Functionality:** The `ixcall` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the variable number of arguments (`arg1`, `arg2`, etc.) onto the game stack. The number of arguments is determined by the operand types specified in the instruction. - **Calls the function:** Transfers control to the function specified by `routine`. The function address is calculated by shifting `routine` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Does not retrieve return value:** When the function returns, its return value is discarded. **Special Cases:** - If `routine` is zero, the `ixcall` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `routine` is not a valid function pointer. **Examples:** ``` {.assembly} ixcall print_list, item1, item2, item3 ; Calls the `print_list` function with three arguments ``` **Use Cases:** - Calling functions with a variable number of arguments where the return value is not needed, reducing stack usage and potential stack overflows. - Implementing functions that take a flexible number of arguments. **Note:** The `ixcall` opcode is generated by the compiler when it detects a function call with a variable number of arguments where the return value is not used. It is not typically used directly by programmers. ### JUMP **JUMP** is an opcode that performs an unconditional relative jump to a specified location within the program. It is used to control the flow of execution and implement loops or conditional branching. **Syntax:** ``` {.assembly} jump offset:loc ``` **Functionality:** The `jump` opcode performs the following: - **Calculates target address:** Adds the `offset` value to the address of the next instruction. This gives the target address of the jump. - **Jumps to target:** Transfers control to the calculated target address. **Special Cases:** - The `offset` value is a signed 16-bit integer, allowing for both forward and backward jumps within the program. **Error Conditions:** None. **Examples:** ``` {.assembly} jump start_loop ; Jumps to the label `start_loop` jump -5 ; Jumps back 5 instructions ``` **Use Cases:** - Implementing loops by jumping back to the beginning of the loop code. - Performing conditional branching by jumping to different sections of code based on the results of predicates. - Creating subroutines or functions by jumping to their starting addresses. **Note:** The `JUMP` opcode is a fundamental control flow instruction used to direct the execution of Z-code programs. ### LESS? **LESS?** is an opcode that compares two integer values and checks if the first operand is less than the second operand. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} less? arg1:int, arg2:int /pred ``` **Functionality:** The `less?` opcode performs the following: - **Compares `arg1` and `arg2`:** Checks if the integer value `arg1` is less than `arg2`. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if `arg1` is indeed less than `arg2`. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} less? count, 10 / continue_loop ; Branch to `continue_loop` if `count` is less than 10 ``` **Use Cases:** - Implementing conditional logic based on less-than comparisons. - Making decisions based on numerical values, such as health, score, or inventory counts. **Note:** The `less?` opcode is a basic comparison operator used for implementing conditional behavior in Z-code programs. ### LEX **LEX** is an opcode that parses the contents of an input buffer and looks up the words in a vocabulary table. It is similar to the parsing phase of the `READ` opcode but offers more flexibility in choosing the vocabulary. **Syntax:** ``` {.assembly} lex inbuf:tbl, lexv:tbl [, lexicon:tbl, preserve:bool] ``` **Functionality:** The `lex` opcode performs the following: - **Parses input buffer:** Reads the contents of the `inbuf` table, which is assumed to contain a string of text. - **Tokenizes words:** Breaks the text into individual words based on whitespace and self-inserting break characters defined in the vocabulary. - **Looks up words:** Searches for each word in the specified `lexicon` table. If `lexicon` is omitted, the default vocabulary table (pointed to by the `VOCAB` word in the program header) is used. - **Stores results:** For each word, the opcode stores the following information in the `lexv` table: - A pointer to the word entry in the vocabulary table (or 0 if not found). - The length of the word in bytes. - The byte offset of the word within the input buffer. - **Preserves existing entries (optional):** If the `preserve` argument is provided and non-zero, the opcode does not modify entries in `lexv` for words that are not found in the vocabulary. **Special Cases:** - The `lexv` table must have enough space to store the parsing results. - The format of the `lexv` table is specific to the Z-machine and is used by other opcodes like `PRINTC` to reprint words from the input buffer. **Error Conditions:** An error occurs if: - `inbuf` or `lexv` is not a valid table pointer. - `lexicon` is not a valid table pointer (if provided). - The `lexv` table does not have enough space to store the parsing results. **Examples:** ``` {.assembly} lex input_buffer, parsed_words ; Parses `input_buffer` using the default vocabulary lex input_buffer, parsed_words, special_vocab, 1 ; Parses using `special_vocab` and preserves existing entries ``` **Use Cases:** - Parsing player input and looking up words in a vocabulary. - Implementing custom parsers or natural language processing routines. - Using multiple vocabularies for different contexts or situations. **Note:** The `LEX` opcode provides more flexibility than the parsing phase of the `READ` opcode by allowing the programmer to specify the vocabulary table. ### LOC **LOC** is an opcode that retrieves the "parent" object of a given object. Objects in Z-code programs are organized in a hierarchical structure, where each object can be contained within another object. **Syntax:** ``` {.assembly} loc obj > val ``` **Functionality:** The `loc` opcode retrieves the object number of the object that contains the specified object (`obj`). This is done by reading the value of the `LOC` property of `obj`. - **Stores the result:** The retrieved object number is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If the object `obj` is not contained within any other object (i.e., it is a top-level object), the `LOC` property will be 0, and the opcode will return 0. **Error Conditions:** An error occurs if `obj` is not a valid object number. **Examples:** ``` {.assembly} loc item > container ; Retrieves the object number of the container that holds `item` ``` **Use Cases:** - Determining the location of objects within the game world. - Implementing inventory management and object interaction logic. - Traversing the object hierarchy to find related objects. **Note:** The `LOC` opcode is used to navigate the object hierarchy and determine containment relationships between objects. ### MARGIN **MARGIN** is an opcode that sets the left and right margins for text output in a window. Margins control the horizontal spacing of text within the window. **Syntax:** ``` {.assembly} margin left:int, right:int [, window:int] ``` **Functionality:** The `margin` opcode sets the margins for the specified window (`window`) as follows: - **`left`:** The width of the left margin in pixels. - **`right`:** The width of the right margin in pixels. The opcode stores the margin values in the `LMRG` and `RMRG` words associated with the window. **Special Cases:** - If the `window` argument is omitted, the current window is used. - Margins only affect windows that have text wrapping enabled. - The opcode must be executed before any text is buffered for the current line. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `left` or `right` is negative. **Examples:** ``` {.assembly} margin 10, 20 ; Sets a 10-pixel left margin and a 20-pixel right margin in the current window ``` **Use Cases:** - Indenting text within a window. - Creating visual distinctions between different sections of text. - Implementing custom text formatting or layout. **Note:** The `MARGIN` opcode is used to control the horizontal spacing of text within windows. It is important to consider the window's wrapping attribute and the timing of the opcode execution. ### MENU **MENU** is an opcode that adds or removes a menu from the menu bar. This feature is currently only supported on the Macintosh platform. **Syntax:** ``` {.assembly} menu id, table /pred ``` **Functionality:** The `menu` opcode performs the following: - **Adds a menu (table is non-zero):** - **`id`:** Specifies the slot in the menu bar where the menu should be added. Slots 0, 1, and 2 are reserved for the Apple menu, File menu, and Edit menu, respectively. - **`table`:** A pointer to an LTABLE containing the menu data. The first element of the table is the menu name, and subsequent elements are the menu items. - **Removes a menu (table is zero):** - **`id`:** Specifies the slot of the menu to remove. **Predicate Behavior:** The `menu` opcode also acts as a predicate: - **Success:** The predicate succeeds if the menu was successfully added or removed. - **Failure:** The predicate fails if there is no room in the menu bar for the new menu or if the specified menu ID is invalid. **Special Cases:** - The `MENU` opcode is only supported on the Macintosh platform. - The interpreter must have the `%FMENU` flag set in the `FLAGS` word to indicate support for menus. **Error Conditions:** An error occurs if: - The interpreter does not support menus. - `id` is not a valid menu slot number. - `table` is not a valid table pointer (when adding a menu). **Examples:** ``` {.assembly} menu 3, my_menu / check_menu ; Adds `my_menu` to the menu bar in slot 3 menu 3, 0 ; Removes the menu from slot 3 ``` **Use Cases:** - Creating custom menus for user interaction. - Providing additional options or commands within the game interface. **Note:** The `MENU` opcode is platform-specific and requires interpreter support. It is important to check the `FLAGS` word before using this opcode. ### MOD **MOD** is an opcode that performs modulo operation on two 16-bit word values. It divides the first operand by the second operand and returns the remainder. **Syntax:** ``` {.assembly} mod arg1:int, arg2:int > val ``` **Functionality:** The `mod` opcode performs the following: - **Divides `arg1` by `arg2`:** Performs integer division. - **Calculates the remainder:** Determines the remainder of the division. - **Stores the result:** The remainder is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - Modulo by zero results in an error. **Error Conditions:** An error occurs if `arg2` is zero. **Examples:** ``` {.assembly} mod 10, 3 > result ; Divides 10 by 3, stores the remainder (1) in `result` ``` **Use Cases:** - Calculating the remainder of a division. - Implementing cyclic behavior or patterns. - Performing operations based on the position within a cycle. **Note:** The `mod` opcode is used to obtain the remainder of an integer division. For operations that require the quotient, use the `DIV` opcode. ### MOUSE-INFO **MOUSE-INFO** is an opcode that retrieves information about the current state of the mouse and stores it in a table. This information includes the mouse cursor position, button status, and any selected menu items. **Syntax:** ``` {.assembly} mouse-info table ``` **Functionality:** The `mouse-info` opcode fills the specified `table` with the following information: - **Word 0:** Y coordinate of the mouse cursor (row number, in screen units). - **Word 1:** X coordinate of the mouse cursor (column number, in screen units). - **Word 2:** Button status. Each bit represents a mouse button, with bit 1 corresponding to the rightmost button. A set bit indicates that the button is currently pressed. - **Word 3:** Menu/item selection. The high byte contains the menu number (1 for the default menu), and the low byte contains the selected item number within that menu. **Special Cases:** - The `table` argument must be a table with at least four words of available space. - The interpretation of button status and menu/item selection may vary depending on the target machine and the number of buttons or menus available. **Error Conditions:** An error occurs if: - `table` is not a valid table pointer. - The `table` does not have enough space to store the mouse information (at least four words). **Examples:** ``` {.assembly} mouse-info mouse_data ; Retrieves the current mouse state ``` **Use Cases:** - Implementing mouse-based interaction and controls. - Tracking the mouse cursor position for display or game logic purposes. - Handling mouse button clicks and menu selections. **Note:** The `MOUSE-INFO` opcode requires the interpreter to support mouse input. The `%FMOUS` flag in the `FLAGS` word indicates whether mouse operations are available. ### MOUSE-LIMIT **MOUSE-LIMIT** is an opcode that restricts the movement of the mouse cursor to a specific window. This can be used to confine mouse interactions to a particular area of the screen. **Syntax:** ``` {.assembly} mouse-limit window:int ``` **Functionality:** The `mouse-limit` opcode restricts the mouse cursor movement to the specified window (`window`). The interpreter, if possible, will prevent the cursor from moving outside the boundaries of that window. Mouse events, such as button clicks or movements, will only be reported if the cursor is within the limited window. **Special Cases:** - **`window` = -1:** Removes any mouse cursor restrictions, allowing it to move freely across the entire screen. - Initially, the mouse cursor is assumed to be limited to window 1. **Error Conditions:** An error occurs if `window` is not within the valid range (-1 to 7). **Examples:** ``` {.assembly} mouse-limit 0 ; Limits the mouse cursor to the main window (window 0) mouse-limit -1 ; Removes mouse cursor restrictions ``` **Use Cases:** - Confining mouse interactions to a specific area of the screen, such as a menu or game window. - Preventing accidental clicks or movements outside the intended interaction area. **Note:** The ability to limit the mouse cursor may vary depending on the capabilities of the interpreter and the target machine. ### MOVE **MOVE** is an opcode that moves an object from one location to another within the object hierarchy. Objects in Z-code programs are organized in a tree structure, where each object can be contained within another object. **Syntax:** ``` {.assembly} move thing:obj, dest:obj ``` **Functionality:** The `move` opcode moves the object `thing` into the object `dest`: - **Checks for existing containment:** If `thing` is already contained within `dest`, the opcode does nothing. - **Removes from previous location:** If `thing` is contained within another object, it is removed from that object's containment chain. - **Adds to new location:** The `LOC` property of `thing` is set to the object number of `dest`, and `thing` is added as the first object in `dest`'s containment chain. This means the `FIRST` property of `dest` will now point to `thing`. **Special Cases:** - If `dest` is 0, the `thing` object is effectively removed from the object hierarchy, as its `LOC` property is set to 0. **Error Conditions:** An error occurs if: - `thing` or `dest` is not a valid object number. **Examples:** ``` {.assembly} move sword, player ; Moves the "sword" object into the "player" object's inventory move box, room ; Moves the "box" object into the "room" object ``` **Use Cases:** - Implementing inventory management and object interaction. - Changing the location of objects within the game world. - Updating the object hierarchy based on game logic or player actions. **Note:** The `MOVE` opcode is a fundamental operation for manipulating the object hierarchy and managing object containment in Z-code programs. ### MUL **MUL** is an opcode that performs multiplication on two 16-bit word values. It multiplies the first operand by the second operand and returns the result. **Syntax:** ``` {.assembly} mul arg1:int, arg2:int > val ``` **Functionality:** The `mul` opcode performs the following: - **Multiplies `arg1` by `arg2`:** Performs integer multiplication. - **Stores the result:** The product is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If the result of the multiplication overflows the 16-bit word size, an error occurs. **Error Conditions:** An error occurs if the multiplication result overflows the 16-bit word range. **Examples:** ``` {.assembly} mul 5, 10 > result ; Multiplies 5 by 10, stores the product (50) in `result` ``` **Use Cases:** - Performing integer multiplication calculations. - Scaling values or calculating areas and volumes. **Note:** The `mul` opcode performs signed integer multiplication. If the operands are unsigned, the programmer needs to handle potential overflow conditions. ### NEXT? **NEXT?** is an opcode that retrieves the "next" property of an object and checks if it is non-zero. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} next? obj > val /pred ``` **Functionality:** The `next?` opcode performs the following: - **Retrieves "next" property:** Gets the value of the "next" slot within the object (`obj`). This slot typically contains the object number of the next object in a linked chain. - **Checks for non-zero value:** Evaluates to true if the retrieved value is not zero (meaning there is a "next" object). Otherwise, it evaluates to false. - **Stores the value (optional):** If the `> val` operand is provided, the retrieved value is also stored in the specified variable. - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - If the object `obj` is the last object in a chain, the "next" slot will be zero, and the predicate will fail. **Error Conditions:** An error occurs if `obj` is not a valid object number. **Examples:** ``` {.assembly} next? item > next_item / process_item ; Branch to `process_item` if `item` has a "next" object in the chain ``` **Use Cases:** - Iterating through a chain of objects linked by their "next" properties. - Implementing inventory management or object interaction logic. **Note:** The `NEXT?` opcode is used to access and check the "next" property of an object. To retrieve the "first" property in a chain, use the `FIRST?` opcode. ### NEXTP **NEXTP** is an opcode that retrieves the number of the property following a specified property within an object's property table. It is used to iterate through the properties of an object. **Syntax:** ``` {.assembly} nextp obj, prop > val ``` **Functionality:** The `nextp` opcode performs the following: - **Locates property table:** Finds the property table associated with the object (`obj`). - **Searches for property:** Searches the property table for the property with the specified number (`prop`). - **Finds next property:** If the property is found, the opcode determines the number of the next property in the table. - **Handles circularity:** If `prop` is the last property in the table, the opcode returns the number of the first property, creating a circular iteration. - **Stores the result:** The retrieved property number is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If `prop` is 0, the opcode returns the number of the first property in the table. - Properties are stored in a sorted order within the object's property table. **Error Conditions:** An error occurs if: - `obj` is not a valid object number. - `prop` is not a valid property number within the object's property table. **Examples:** ``` {.assembly} nextp object, 5 > next_prop ; Retrieves the number of the property following property 5 in `object` ``` **Use Cases:** - Iterating through the properties of an object. - Implementing generic routines that need to access all properties of an object. **Note:** The `NEXTP` opcode provides a way to navigate through the properties of an object in a circular manner. It is important to handle the case where the last property is reached and the opcode returns the first property number. ### ORIGINAL? **ORIGINAL?** is an opcode that checks whether the game is running from the original distribution disk. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} original? /pred ``` **Functionality:** The `original?` opcode checks if the game is running from the original distribution disk. The specific method for determining originality is implementation-dependent and may vary between interpreters. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if the game is determined to be running from the original disk. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** The implementation of originality checking is left to the interpreter. - Checking for specific files or data on the disk. - Comparing checksums or other validation data. - Using copy protection mechanisms. **Error Conditions:** None. **Examples:** ``` {.assembly} original? / display_warning ; Branch to `display_warning` if the game is not running from the original disk ``` ### NOOP **NOOP** is an opcode that performs no operation. It is essentially a placeholder instruction that does nothing and simply advances the program counter to the next instruction. **Syntax:** ``` {.assembly} noop ``` **Functionality:** The `noop` opcode has no effect on the program state or data. It simply increments the program counter, causing the interpreter to move on to the next instruction in the sequence. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} noop ; Does nothing ``` **Use Cases:** - Aligning code or data to specific memory locations. - Providing a placeholder for future instructions or as a debugging aid. - Implementing timing delays or loops with empty bodies. **Note:** The `NOOP` opcode is rarely used in typical Z-code programs but can be helpful in specific situations where a placeholder or delay is needed. ### PICINF **PICINF** is an opcode that retrieves information about a picture, such as its dimensions. Pictures are images stored in a separate picture file and referenced by their ID numbers. **Syntax:** ``` {.assembly} picinf picture:int, data:tbl /pred ``` **Functionality:** The `picinf` opcode retrieves information about the specified picture (`picture`) and stores it in the `data` table: - **Word 0 of `data`:** The width of the picture in pixels. - **Word 1 of `data`:** The height of the picture in pixels. **Predicate Behavior:** The `picinf` opcode also acts as a predicate: - **Success:** The predicate succeeds if the picture ID is valid and the information is successfully retrieved. - **Failure:** The predicate fails if the picture ID is invalid. **Special Cases:** - If the picture ID is 0, the opcode stores the highest picture ID in the picture library (the number of pictures) in word 0 of the `data` table. **Error Conditions:** None. **Examples:** ``` {.assembly} picinf 10, pic_data / handle_picture ; Retrieves information about picture 10 picinf 0, pic_data > num_pictures ; Retrieves the number of pictures in the library ``` **Use Cases:** - Determining the dimensions of a picture before displaying it. - Implementing custom picture handling or display routines. - Checking the validity of a picture ID. **Note:** The `PICINF` opcode is used in conjunction with the `DISPLAY` and `DCLEAR` opcodes to manage the display of pictures within Z-code programs. ### PICSET **PICSET** is an opcode that defines a group of pictures that should be loaded together from the picture file. This can be used to optimize picture loading and reduce disk access times. **Syntax:** ``` {.assembly} picset picture:int, count:int ``` **Functionality:** The `picset` opcode defines a group of pictures starting from the specified picture ID (`picture`) and including the next `count` pictures. The interpreter should attempt to load all pictures in the group from the picture file simultaneously, reducing the need for multiple disk accesses. **Special Cases:** - All pictures within a group must be located in the same picture file. - If the interpreter does not support picture grouping, the opcode should be ignored. **Error Conditions:** An error occurs if: - `picture` is not a valid picture ID. - `count` is negative. **Examples:** ``` {.assembly} picset 10, 5 ; Defines a group of 5 pictures starting from picture ID 10 ``` **Use Cases:** - Optimizing picture loading by grouping related pictures together. - Reducing disk access times in multi-disk games. **Note:** The `PICSET` opcode is an optimization feature that may not be supported by all interpreters. It is important to check the interpreter's capabilities before using this opcode. ### POP **POP** is an opcode that removes the top element from a stack and returns its value. It can be used to retrieve values from the game stack or a user-defined stack. **Syntax:** ``` {.assembly} pop [, stack:tbl] > val ``` **Functionality:** The `pop` opcode removes the top element from the specified stack and returns its value: - **Game stack (default):** If the `stack` argument is omitted, the opcode pops the top element from the game stack. - **User-defined stack:** If the `stack` argument is provided, the opcode pops the top element from the table pointed to by `stack`. **Return Value:** The popped value is stored in the specified destination (`val`). If no destination is provided, the value is pushed onto the game stack. **Special Cases:** - Attempting to pop from an empty stack is an error. **Error Conditions:** An error occurs if: - `stack` is not a valid table pointer (if provided). - The stack is empty. **Examples:** ``` {.assembly} pop > value ; Pops the top element from the game stack and stores it in `value` pop user_stack > value ; Pops the top element from `user_stack` ``` **Use Cases:** - Retrieving values from the game stack or user-defined stacks. - Implementing stack-based data structures and algorithms. **Note:** The `POP` opcode is used to remove and retrieve elements from stacks. To add elements, use the `PUSH` or `XPUSH` opcodes. ### PRINT **PRINT** is an opcode that prints a string to the screen. It is used to display text output in the current window. **Syntax:** ``` {.assembly} print str ``` **Functionality:** The `print` opcode prints the string pointed to by `str`. The string address is calculated by shifting `str` left by two bits and adding the string offset (`SOFF`) shifted left by three bits. **Special Cases:** - The `str` argument is a quad-pointer, meaning it points to a string that is aligned to a quad-byte boundary in the string area. - The string area is located in a separate section of the Z-code program and is accessed using the `SOFF` value. - Strings are encoded in a special 5-bit byte format for efficient storage. **Error Conditions:** An error occurs if `str` is not a valid string pointer. **Examples:** ``` {.assembly} .gstr "message", "Hello, world!" print message ; Prints the "message" string ``` **Use Cases:** - Displaying text output to the user. - Printing messages, prompts, or descriptions. **Note:** The `PRINT` opcode is used to print strings from the string area. For printing strings within tables or as immediate operands, use the `PRINTB` opcode. ### PRINTB **PRINTB** is an opcode that prints a string from a table or an immediate string operand. It is used to display text output that is not stored in the string area. **Syntax:** ``` {.assembly} printb str ``` **Functionality:** The `printb` opcode prints the string pointed to by `str`. The string can be: - **A string within a table:** The `str` argument is a byte pointer to the beginning of the string within a table. - **An immediate string operand:** The string is directly encoded within the instruction as a sequence of bytes. **Special Cases:** - The `printb` opcode is typically used for printing shorter strings or strings that are dynamically generated. - Strings printed with `printb` are not subject to the string offset (`SOFF`) adjustment. **Error Conditions:** An error occurs if `str` is not a valid string pointer or if the immediate string operand is malformed. **Examples:** ``` {.assembly} printb vocabulary[word_index] ; Prints the word from the vocabulary table at the specified index printb "This is an immediate string." ; Prints the immediate string ``` **Use Cases:** - Printing strings from tables, such as vocabulary entries or text buffers. - Displaying short messages or prompts that do not need to be stored in the string area. **Note:** The `PRINTB` opcode is used for printing strings that are not located in the string area. For printing strings from the string area, use the `PRINT` opcode. ### PRINTC **PRINTC** is an opcode that prints a word from the game's vocabulary table. It is typically used to reprint words that were previously parsed from player input. **Syntax:** ``` {.assembly} printc text-char ``` **Functionality:** The `printc` opcode performs the following: - **Looks up word:** Uses the value of `text-char` as an index into the vocabulary table (pointed to by the `VOCAB` word in the program header). - **Retrieves word data:** If the index is valid, the opcode retrieves the word data from the vocabulary table. This data includes the encoded Z-string representation of the word and its length. - **Prints the word:** Decodes the Z-string and prints the corresponding characters to the screen. **Special Cases:** - The `text-char` argument is typically obtained from the `lexv` table, which is filled by the `READ` or `LEX` opcodes during input parsing. - The format of the vocabulary table entries is specific to the Z-machine and is defined by the `.VOCBEG` directive. **Error Conditions:** An error occurs if: - `text-char` is not a valid index into the vocabulary table. **Examples:** ``` {.assembly} read input_buffer, lexv printc lexv[1] ; Prints the second word from the parsed input ``` **Use Cases:** - Reprinting words that were previously entered by the player. - Implementing text-based menus or displays that use words from the game's vocabulary. **Note:** The `PRINTC` opcode is used to print words from the vocabulary table. For printing arbitrary strings, use the `PRINT` or `PRINTB` opcodes. ### PRINTD **PRINTD** is an opcode that prints the short description of an object. Objects in Z-code programs can have a short description associated with them, which is typically used for providing a brief textual representation of the object. **Syntax:** ``` {.assembly} printd obj ``` **Functionality:** The `printd` opcode performs the following: - **Locates object:** Finds the object with the specified object number (`obj`). - **Retrieves short description:** Accesses the object's property table and retrieves the value of the `DESC` property, which contains the short description. - **Prints the description:** Decodes the Z-string representation of the short description and prints the corresponding characters to the screen. **Special Cases:** - If the object does not have a `DESC` property, the opcode does nothing. - The short description is typically a short string encoded in the Z-machine's 5-bit byte format. **Error Conditions:** An error occurs if `obj` is not a valid object number. **Examples:** ``` {.assembly} printd player ; Prints the short description of the "player" object ``` **Use Cases:** - Displaying a brief description of an object to the player. - Providing context or information about objects in the game world. **Note:** The `PRINTD` opcode is a convenient way to print the short description associated with an object. For printing other properties or arbitrary strings, use the `GETP`, `GETPT`, `PRINT`, or `PRINTB` opcodes. ### PRINTF **PRINTF** is an opcode that prints a formatted table to the screen. Formatted tables allow for more flexible text layout and can include variable-length lines, different fonts, and highlighting. **Syntax:** ``` {.assembly} printf table ``` **Functionality:** The `printf` opcode prints the contents of the specified `table` as a formatted block of text. The table format is as follows: - **Line length indicators:** Each line of text is preceded by a word (two bytes) that specifies the number of characters in that line. - **Character data:** The characters of each line are stored as consecutive bytes. - **End of table marker:** A word with the value 0 marks the end of the table. The opcode interprets the line length indicators and character data to print the text with the appropriate formatting, including line breaks and potential justification. **Special Cases:** - Formatted tables are typically generated using the `DIROUT 3` opcode with the `just` argument to specify justification. - The `printf` opcode can handle tables with variable-length lines, different fonts, and highlighting. **Error Conditions:** An error occurs if: - `table` is not a valid table pointer. - The table format is invalid. **Examples:** ``` {.assembly} dirout 3, formatted_text, 80 ; Redirects output to `formatted_text` with right justification at 80 pixels ; ... generate formatted text ... dirout -3 printf formatted_text ; Prints the formatted table ``` **Use Cases:** - Displaying text with custom formatting and layout. - Creating menus or dialog boxes with variable-length lines and different styles. - Implementing text-based graphics or visual effects. **Note:** The `PRINTF` opcode provides a more flexible way to display text compared to the `PRINT` or `PRINTB` opcodes. It is particularly useful for situations where precise control over text layout and formatting is required. ### PRINTI **PRINTI** is an opcode that prints an immediate string directly encoded within the instruction. It is used to display short, fixed messages or prompts without the need to define them as separate strings in the string area. **Syntax:** ``` {.assembly} printi "string" ``` **Functionality:** The `printi` opcode decodes and prints the string literal `"string"` that is included directly within the instruction. **Special Cases:** - The string literal must be enclosed in double quotes (`"`). - Double quotes within the string are escaped by using two consecutive double quotes. **Error Conditions:** An error occurs if the string literal is malformed or not properly terminated. **Examples:** ``` {.assembly} printi "Hello, world!" ; Prints the string "Hello, world!" printi "He said, ""Hello!""" ; Prints the string "He said, "Hello!"" ``` **Use Cases:** - Printing short, fixed messages or prompts. - Displaying error messages or debugging information. **Note:** The `PRINTI` opcode is a convenient way to print short strings without the overhead of defining them as separate entities in the string area. However, for longer or more complex strings, using the `PRINT` or `PRINTB` opcodes with strings defined using `.STR` or `.GSTR` is more efficient. ### PRINTN **PRINTN** is an opcode that prints a signed integer value as a decimal number. It is used to display numerical values on the screen. **Syntax:** ``` {.assembly} printn number:int ``` **Functionality:** The `printn` opcode converts the signed integer value `number` into a decimal string representation and prints it to the current window. **Special Cases:** - Negative numbers are printed with a leading minus sign (`-`). - The number is printed using the current font and highlighting settings. **Error Conditions:** None. **Examples:** ``` {.assembly} printn score ; Prints the value of the variable `score` as a decimal number printn -10 ; Prints the number -10 ``` **Use Cases:** - Displaying numerical values, such as scores, health points, or inventory counts. - Printing the results of calculations or comparisons. **Note:** The `PRINTN` opcode is used to print signed integer values. For printing unsigned values or values in other formats, use the `PRINT` or `PRINTB` opcodes with appropriate string formatting. ### PRINTR **PRINTR** is an opcode that prints an immediate string and then performs a carriage return and line feed (CRLF), effectively moving the cursor to the beginning of the next line. It also implicitly returns true from the current function. **Syntax:** ``` {.assembly} printr "string" ``` **Functionality:** The `printr` opcode performs the following: 1. **Prints the string:** Decodes and prints the string literal `"string"` that is included directly within the instruction. 2. **Outputs CRLF:** Prints a carriage return and line feed sequence, moving the cursor to the beginning of the next line. 3. **Returns true:** Implicitly returns the value 1 (true) from the current function. **Special Cases:** - The string literal must be enclosed in double quotes (`"`). - Double quotes within the string are escaped by using two consecutive double quotes. **Error Conditions:** An error occurs if the string literal is malformed or not properly terminated. **Examples:** ``` {.assembly} printr "Game over!" ; Prints "Game over!" and then returns true, ending the current function ``` **Use Cases:** - Printing a final message or prompt before ending the current function. - Displaying error messages or debugging information and then returning from the function. **Note:** The `PRINTR` opcode combines string printing, line termination, and function return into a single operation. It is a convenient way to print a message and then exit the current function. ### PRINTT **PRINTT** is an opcode that prints a rectangular block of text from a byte-oriented table. It allows for flexible formatting and display of text data. **Syntax:** ``` {.assembly} printt bytes:tbl, width:int, height:int [, skip:int] ``` **Functionality:** The `printt` opcode prints a block of text from the specified table (`bytes`) according to the given dimensions and skip value: - **`bytes`:** A pointer to a byte-oriented table containing the text data. - **`width`:** The width of the text block in columns (number of characters per line). - **`height`:** The height of the text block in lines. - **`skip` (optional):** The number of bytes to skip at the end of each line. This allows for printing rectangular blocks from within larger tables. If omitted, the default skip value is 0. The opcode prints the text line by line, wrapping to the next line when the `width` is reached. After each line, it skips `skip` bytes in the table before starting the next line. **Special Cases:** - If the `skip` argument is 0, the opcode prints a continuous block of text without skipping any bytes. - The `printt` opcode does not perform any character set decoding or string interpretation. It simply prints the raw bytes from the table. **Error Conditions:** An error occurs if: - `bytes` is not a valid table pointer. - `width` or `height` is zero or negative. - `skip` is negative. **Examples:** ``` {.assembly} printt text_buffer, 80, 24 ; Prints a 24-line block of text from `text_buffer`, 80 characters per line printt table, 10, 5, 20 ; Prints a 5-line block from `table`, 10 characters per line, skipping 20 bytes after each line ``` **Use Cases:** - Displaying formatted text from tables. - Printing text-based graphics or user interface elements. - Implementing custom text layout and formatting. **Note:** The `PRINTT` opcode provides a flexible way to print text from tables. It is important to ensure that the table format and dimensions are correct to avoid unexpected output. ### PTSIZE **PTSIZE** is an opcode that returns the size of a property table in bytes. Property tables are associated with objects and contain additional data and attributes. **Syntax:** ``` {.assembly} ptsize table > val ``` **Functionality:** The `ptsize` opcode calculates the size of the property table pointed to by `table` and stores the result in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - The `ptsize` opcode is typically used with property tables obtained using the `GETPT` opcode. - The opcode assumes that the property table has the correct format, with properties stored in a sorted order and appropriate length indicators. **Error Conditions:** An error may occur if `table` is not a valid property table pointer or if the table format is invalid. **Examples:** ``` {.assembly} getpt object, 10 > prop_ptr ; Retrieves a pointer to property 10 of `object` ptsize prop_ptr > prop_size ; Calculates the size of the property value ``` **Use Cases:** - Determining the size of a property value before accessing or manipulating it. - Implementing routines that need to handle properties of varying lengths. **Note:** The `PTSIZE` opcode is used to determine the size of property tables. It is important to ensure that the table pointer is valid and the table format is correct. ### PUSH **PUSH** is an opcode that pushes a value onto the game stack. The game stack is a LIFO (Last-In-First-Out) data structure used to store temporary values and function arguments. **Syntax:** ``` {.assembly} push value ``` **Functionality:** The `push` opcode pushes the specified `value` onto the top of the game stack. **Special Cases:** - Pushing a value onto a full stack results in a stack overflow error. **Error Conditions:** An error occurs if the game stack is full. **Examples:** ``` {.assembly} push 5 ; Pushes the value 5 onto the stack push var1 ; Pushes the value of the variable `var1` onto the stack ``` **Use Cases:** - Storing temporary values during calculations or operations. - Passing arguments to functions. - Implementing stack-based data structures and algorithms. **Note:** The `PUSH` opcode is used to add elements to the game stack. To remove elements, use the `POP` or `FSTACK` opcodes. ### PUT **PUT** is an opcode that stores a word value into a specified element of a word-oriented table. It is used to modify data stored in tables based on their index or offset. **Syntax:** ``` {.assembly} put table, item, value ``` **Functionality:** The `put` opcode performs the following: - **Calculates element address:** Multiplies the `item` (index or offset) by 2 and adds it to the base address of the `table`. This gives the address of the desired element in memory. - **Stores the value:** Writes the word value `value` to the calculated address. **Special Cases:** - Table offsets are zero-based, meaning the first element has an index of 0. - The interpreter does not perform bounds checking on table accesses. It is the programmer's responsibility to ensure that `item` is within the valid range of the table. **Error Conditions:** An error may occur if: - `table` is not a valid table pointer. - `item` is outside the bounds of the table. **Examples:** ``` {.assembly} put inventory, 3, "sword" ; Stores the word "sword" in the 4th element of the `inventory` table ``` **Use Cases:** - Modifying data stored in tables based on their index or offset. - Implementing data structures and algorithms that require updating table values. **Note:** The `PUT` opcode is used for storing word-sized elements in tables. For byte-sized elements, use the `PUTB` opcode. ### PUTB **PUTB** is an opcode that stores a byte value into a specified element of a byte-oriented table. It is used to modify data stored in tables based on their index or offset. **Syntax:** ``` {.assembly} putb table, item, value ``` **Functionality:** The `putb` opcode performs the following: - **Calculates element address:** Adds the `item` (index or offset) to the base address of the `table`. This gives the address of the desired element in memory. - **Extracts byte value:** Takes the low-order byte of `value` as the byte to be stored. - **Stores the byte:** Writes the extracted byte value to the calculated address. **Special Cases:** - Table offsets are zero-based, meaning the first element has an index of 0. - The interpreter does not perform bounds checking on table accesses. It is the programmer's responsibility to ensure that `item` is within the valid range of the table. - The high-order byte of `value` is ignored. **Error Conditions:** An error may occur if: - `table` is not a valid table pointer. - `item` is outside the bounds of the table. **Examples:** ``` {.assembly} putb text_buffer, 5, 'A' ; Stores the ASCII value of 'A' in the 6th byte of the `text_buffer` table ``` **Use Cases:** - Modifying data stored in byte-oriented tables. - Writing individual characters to text buffers. - Implementing data structures and algorithms that require updating byte-level table values. **Note:** The `PUTB` opcode is used for storing byte-sized elements in tables. For word-sized elements, use the `PUT` opcode. ### PUTP **PUTP** is an opcode that sets the value of a property within an object's property table. Properties are used to associate additional data and attributes with objects. **Syntax:** ``` {.assembly} putp obj, prop, value ``` **Functionality:** The `putp` opcode modifies a property within an object's property table: - **Locates property table:** Finds the property table associated with the object (`obj`). - **Searches for property:** Searches the property table for the property with the specified number (`prop`). - **Updates property value:** If the property is found, its value is updated to `value`. - **Error if property not found:** If the property is not found in the object's property table, an error occurs. **Special Cases:** - The `PUTP` opcode can only be used to modify properties with a length of 1 or 2 bytes. For properties of arbitrary length, use a combination of `GETPT` and table manipulation opcodes. **Error Conditions:** An error occurs if: - `obj` is not a valid object number. - `prop` is not a valid property number within the object's property table. - The property does not exist in the object's property table. **Examples:** ``` {.assembly} putp player, 1, 15 ; Sets the value of property 1 ("strength") in the "player" object to 15 ``` **Use Cases:** - Modifying data associated with objects through properties. - Updating object attributes or characteristics based on game logic or player actions. **Note:** The `PUTP` opcode is used to modify properties with a length of 1 or 2 bytes. For properties of arbitrary length, use a combination of `GETPT` and table manipulation opcodes. ### QUIT **QUIT** is an opcode that terminates the execution of the Z-code program. It is used to end the game or exit the interpreter. **Syntax:** ``` {.assembly} quit ``` **Functionality:** The `quit` opcode signals to the interpreter that the program should terminate. The interpreter performs any necessary cleanup operations and then exits. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} quit ; Terminates the program ``` **Use Cases:** - Ending the game when the player reaches a specific condition or completes all objectives. - Exiting the interpreter in response to a user command or error condition. **Note:** The `QUIT` opcode is a terminal instruction that stops the execution of the Z-code program. It is important to ensure that all necessary cleanup or saving operations are performed before using this opcode. ### RANDOM **RANDOM** is an opcode that generates a random number within a specified range. It is used to introduce randomness and unpredictability into the game. **Syntax:** ``` {.assembly} random range:int > val ``` **Functionality:** The `random` opcode generates a random integer value between 1 and `range` (inclusive) and stores it in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - **Negative `range`:** If `range` is negative, the opcode enters a "predictable" mode. The absolute value of `range` is saved, and subsequent calls to `random` with a positive range will generate numbers in a sequence from 1 to the saved absolute value. - **`range` = 0:** Resets the random number generator to its normal (unpredictable) mode. **Error Conditions:** None. **Examples:** ``` {.assembly} random 6 > dice_roll ; Generates a random number between 1 and 6 random -10 ; Enters predictable mode with a sequence of 1 to 10 random 4 > next_num ; Generates the next number in the predictable sequence (e.g., 1, 2, 3, 4, 1, ...) random 0 ; Resets to unpredictable mode ``` **Use Cases:** - Generating random events or outcomes in the game. - Simulating dice rolls or other random processes. - Introducing variability and replayability into the game experience. **Note:** The implementation of the random number generator may vary between interpreters. The predictable mode allows for testing and debugging scenarios where consistent random values are desired. ### READ **READ** is an opcode that reads a line of input from the user, parses it into words, and looks up the words in the vocabulary table. It is a fundamental operation for receiving player input and interpreting commands. **Syntax:** ``` {.assembly} read text-buffer:tbl, parse-buffer:tbl [, time:int, routine:fcn] > val ``` **Functionality:** The `read` opcode performs the following: 1. **Clears output buffer:** Prints and empties the current output buffer, ensuring that any pending output is displayed before reading input. 2. **Reads input:** Reads a line of text from the user, storing the characters in the `text-buffer` table. The first byte of `text-buffer` specifies the maximum length of the buffer, and the second byte is used by the opcode to store the number of characters read. 3. **Converts to lowercase:** Converts all uppercase letters in the input to lowercase. 4. **Parses input (optional):** If `parse-buffer` is non-zero, the opcode parses the input text into words and stores information about each word in the `parse-buffer` table. The format of the `parse-buffer` is specific to the Z-machine and is used by other opcodes like `PRINTC` to reprint words from the input. 5. **Returns terminator:** The opcode returns the character that terminated the input (e.g., newline, space, or a character from the `TCHARS` table). This value is stored in the specified destination (`val`). If no destination is provided, the value is pushed onto the game stack. **Optional Arguments:** - **`time`:** Specifies a timeout value in tenths of a second. If no input is received within the specified time, the interpreter calls the `routine` function. - **`routine`:** A function to call when a timeout occurs. The function should return true (1) to abort the input operation or false (0) to continue waiting for input. **Special Cases:** - The `TCHARS` table in the program header specifies which characters can terminate input. - The vocabulary table (pointed to by the `VOCAB` word) is used to look up words during parsing. - The interpreter may handle timeout behavior differently depending on the target machine and implementation. **Error Conditions:** An error occurs if: - `text-buffer` or `parse-buffer` is not a valid table pointer. - The `text-buffer` is not large enough to hold the input line. - `time` is negative (if provided). - `routine` is not a valid function pointer (if provided). **Examples:** ``` {.assembly} read input_buffer, parse_buffer > terminator ; Reads input and parses it into words read input_buffer, 0 > terminator ; Reads input without parsing ``` **Use Cases:** - Getting input from the user, such as commands, responses, or text entry. - Implementing a text parser to interpret player commands. - Handling timed input or interactive sequences. **Note:** The `READ` opcode is a fundamental operation for receiving and processing player input in Z-code programs. ### REMOVE **REMOVE** is an opcode that removes an object from the object hierarchy. Objects in Z-code programs are organized in a tree structure, where each object can be contained within another object. **Syntax:** ``` {.assembly} remove obj ``` **Functionality:** The `remove` opcode removes the specified object (`obj`) from the object hierarchy: 1. **Finds the containing object:** Determines the object that currently contains `obj` by examining its `LOC` property. 2. **Updates containment chain:** Removes `obj` from the containment chain of the containing object. This involves updating the `FIRST` and `NEXT` properties of the objects in the chain. 3. **Clears object properties:** Sets the `LOC`, `FIRST`, and `NEXT` properties of `obj` to 0, effectively removing it from the object hierarchy. **Special Cases:** - If `obj` is not contained within any other object (i.e., it is a top-level object), the opcode only clears its `LOC`, `FIRST`, and `NEXT` properties. **Error Conditions:** An error occurs if `obj` is not a valid object number. **Examples:** ``` {.assembly} remove item ; Removes the `item` object from its container ``` **Use Cases:** - Implementing inventory management and object interaction. - Removing objects from the game world when they are no longer needed. - Updating the object hierarchy based on game logic or player actions. **Note:** The `REMOVE` opcode is used to remove objects from the object hierarchy. It is important to ensure that the object is properly removed from any containment chains to avoid dangling references or memory leaks. ### RESTART **RESTART** is an opcode that reinitializes the Z-code program and restarts the game from the beginning. It is used to reset the game state and start a new playthrough. **Syntax:** ``` {.assembly} restart ``` **Functionality:** The `restart` opcode performs the following: 1. **Reloads the preloaded area:** The interpreter reloads the portion of the game file that is below the `ENDLOD` address, which includes all modifiable data and essential tables. 2. **Resets the game state:** All global variables, object flags, and other modifiable data are reset to their initial values. 3. **Jumps to the start address:** The program counter is set to the address specified by the `START` word in the program header, which is typically the beginning of the main game function. **Special Cases:** - The `RESTART` opcode does not affect the state of the interpreter itself, such as window configurations or display settings. - The random number generator may or may not be reseeded, depending on the interpreter implementation. **Error Conditions:** None. **Examples:** ``` {.assembly} restart ; Restarts the game ``` **Use Cases:** - Starting a new game from the beginning. - Resetting the game state after an error or unexpected event. - Implementing a "restart game" command for the player. **Note:** The `RESTART` opcode provides a way to reset the game state and start a new playthrough. It is important to ensure that all necessary data is properly reinitialized during the restart process. ### RESTORE **RESTORE** is an opcode that restores a previously saved game state from disk. It allows players to resume a game from a saved point. **Syntax:** ``` {.assembly} restore [, start:int, length:int, name:tbl] > val ``` **Functionality:** The `restore` opcode has two modes of operation: **1. Full Restore (no arguments):** - **Prompts for filename:** The interpreter typically prompts the user to provide a filename or select a saved game file. - **Reads saved data:** The interpreter reads the saved game data from the specified file. - **Restores game state:** The impure area of the Z-code program, which includes global variables, object flags, and table contents, is restored to the state it was in when the game was saved. - **Continues execution:** The program resumes execution from the point where it was saved. **2. Partial Restore (with arguments):** - **`start`:** The starting address of the memory region to restore. - **`length`:** The length of the memory region to restore in bytes. - **`name`:** A string specifying the name of the saved data. This mode allows for restoring specific sections of the impure area, such as individual tables or groups of variables. **Return Value:** - **Full restore:** The opcode does not return a value. - **Partial restore:** The opcode returns the number of bytes successfully read from the saved data. **Special Cases:** - The format of the saved game data is specific to the Z-machine and may vary depending on the interpreter implementation. - The `RESTORE` opcode does not restore the state of the interpreter itself, such as window configurations or display settings. - The random number generator may or may not be reseeded, depending on the interpreter implementation. **Error Conditions:** An error occurs if: - The specified saved game file cannot be found or opened. - The saved game data is corrupted or invalid. - The `start` or `length` arguments are invalid (in partial restore mode). **Examples:** ``` {.assembly} restore ; Restores a saved game from a file restore table_address, table_size, "my_table" ; Restores a specific table from saved data ``` **Use Cases:** - Allowing players to save and resume their progress in the game. - Implementing checkpoint or save-game functionality. - Restoring specific data structures or variables from saved data. **Note:** The `RESTORE` opcode is essential for providing save and restore functionality in Z-code games. The specific implementation and user interface for saving and loading games may vary depending on the interpreter. ### RETURN **RETURN** is an opcode that returns from the current function and resumes execution in the calling function. It also allows for specifying a return value. **Syntax:** ``` {.assembly} return value ``` **Functionality:** The `return` opcode performs the following: 1. **Sets return value:** The specified `value` is set as the return value of the function. 2. **Restores stack frame:** The interpreter restores the stack frame of the calling function, including local variables, stack pointer, and argument count. 3. **Resumes execution:** Control is transferred back to the instruction following the `CALL` instruction that invoked the current function. **Special Cases:** - If the current function was called using an `ICALL` variant (which does not expect a return value), the `value` argument is ignored. **Error Conditions:** None. **Examples:** ``` {.assembly} return 5 ; Returns the value 5 from the function return result ; Returns the value of the variable `result` ``` **Use Cases:** - Returning from functions and providing a result to the calling function. - Implementing subroutines and modular code structures. **Note:** The `RETURN` opcode is essential for controlling the flow of execution between functions in Z-code programs. ### RFALSE **RFALSE** is an opcode that returns the value 0 (false) from the current function. It is typically used as a branch target for predicate instructions that evaluate to false. **Syntax:** ``` {.assembly} rfalse ``` **Functionality:** The `rfalse` opcode sets the return value of the current function to 0 and then returns control to the calling function. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} equal? object, "sword" / handle_sword rfalse ; Returns false if the object is not a sword ``` **Use Cases:** - Returning false from a function when a condition is not met. - Implementing conditional logic and branching based on predicate results. **Note:** The `RFALSE` opcode is often used as a branch target for predicate instructions that evaluate to false. It provides a convenient way to return a false value and exit the current function. ### RSTACK **RSTACK** is an opcode that returns from the current function and uses the value on top of the stack as the return value. This allows for a more flexible way to return values from functions without explicitly specifying them in the `RETURN` instruction. **Syntax:** ``` {.assembly} rstack ``` **Functionality:** The `rstack` opcode performs the following: 1. **Pops return value:** Removes the top element from the game stack and uses it as the return value of the function. 2. **Restores stack frame:** The interpreter restores the stack frame of the calling function, including local variables, stack pointer, and argument count. 3. **Resumes execution:** Control is transferred back to the instruction following the `CALL` instruction that invoked the current function. **Special Cases:** - If the game stack is empty, a stack underflow error occurs. **Error Conditions:** An error occurs if the game stack is empty when the `RSTACK` opcode is executed. **Examples:** ``` {.assembly} ; ... function code that pushes a value onto the stack ... rstack ; Returns the value from the top of the stack ``` **Use Cases:** - Returning values from functions without explicitly specifying them in the `RETURN` instruction. - Implementing functions that can return different types of values depending on the context. **Note:** The `RSTACK` opcode provides a more flexible way to return values from functions, but it is important to ensure that the stack contains the correct value before using this opcode. ### RTRUE **RTRUE** is an opcode that returns the value 1 (true) from the current function. It is typically used as a branch target for predicate instructions that evaluate to true. **Syntax:** ``` {.assembly} rtrue ``` **Functionality:** The `rtrue` opcode sets the return value of the current function to 1 and then returns control to the calling function. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} equal? object, "sword" / handle_sword rtrue ; Returns true if the object is a sword ``` **Use Cases:** - Returning true from a function when a condition is met. - Implementing conditional logic and branching based on predicate results. **Note:** The `RTRUE` opcode is often used as a branch target for predicate instructions that evaluate to true. It provides a convenient way to return a true value and exit the current function. ### SAVE **SAVE** is an opcode that saves the current game state to disk, allowing players to resume their progress later. **Syntax:** ``` {.assembly} save [, start:int, length:int, name:tbl] > val ``` **Functionality:** The `save` opcode has two modes of operation: **1. Full Save (no arguments):** - **Prompts for filename:** The interpreter typically prompts the user to provide a filename or select a save game slot. - **Writes game data:** The interpreter writes the current game state to the specified file. This includes the contents of the impure area, which contains all modifiable data such as global variables, object flags, and table contents. - **Returns status:** The opcode returns 0 if the save operation fails and 1 if it succeeds. **2. Partial Save (with arguments):** - **`start`:** The starting address of the memory region to save. - **`length`:** The length of the memory region to save in bytes. - **`name`:** A string specifying a unique name for the saved data. This mode allows for saving specific sections of the impure area, such as individual tables or groups of variables. **Return Value:** - **Full save:** Returns 0 if the save operation fails and 1 if it succeeds. - **Partial save:** Returns 2 to indicate successful completion. **Special Cases:** - The format of the saved game data is specific to the Z-machine and may vary depending on the interpreter implementation. - The `SAVE` opcode does not save the state of the interpreter itself, such as window configurations or display settings. - The random number generator seed is typically not saved to ensure that restoring a saved game does not result in the same sequence of random events. **Error Conditions:** An error occurs if: - The specified save game file cannot be created or written to. - The `start` or `length` arguments are invalid (in partial save mode). **Examples:** ``` {.assembly} save ; Saves the entire game state to a file save table_address, table_size, "my_table" ; Saves a specific table to a file ``` **Use Cases:** - Allowing players to save their progress in the game. - Implementing checkpoint or save-game functionality. - Saving specific data structures or variables for later retrieval. **Note:** The `SAVE` opcode is essential for providing save and restore functionality in Z-code games. The specific implementation and user interface for saving and loading games may vary depending on the interpreter. ### SCREEN **SCREEN** is an opcode that selects the active window for subsequent text output. Z-code programs can have multiple windows, each with its own properties and display area. **Syntax:** ``` {.assembly} screen window:int ``` **Functionality:** The `screen` opcode sets the current window to the window specified by `window`. All subsequent text output, including printing strings and characters, will be directed to this window. **Special Cases:** - If the `window` argument is omitted, the current window remains unchanged. - Each window maintains its own cursor position and other attributes. When switching between windows, the cursor position and attributes of the previously active window are preserved. **Error Conditions:** An error occurs if `window` is not within the valid range (0 to 7). **Examples:** ``` {.assembly} screen 1 ; Switches to window 1 for output print "This text will appear in window 1." screen 0 ; Switches back to the main window (window 0) ``` **Use Cases:** - Managing multiple windows for displaying different types of information or creating a more complex user interface. - Implementing split-screen displays or separate areas for text output. **Note:** The `SCREEN` opcode is used to control which window receives text output. It is important to keep track of the current window and switch between windows as needed to ensure that text is displayed in the correct location. ### SCROLL **SCROLL** is an opcode that scrolls the contents of a window up or down by a specified number of lines. This can be used to create scrolling text displays or to shift the contents of a window. **Syntax:** ``` {.assembly} scroll window:int, lines:int ``` **Functionality:** The `scroll` opcode scrolls the contents of the specified window (`window`) by the number of lines indicated by `lines`: - **Positive `lines`:** Scrolls the window contents up by `lines` lines. Blank lines are inserted at the bottom of the window, filled with the current background color. - **Negative `lines`:** Scrolls the window contents down by the absolute value of `lines` lines. Lines at the top of the window are removed. - **`lines` = 0:** Has no effect. **Special Cases:** - The `scroll` opcode works on both scrolling and non-scrolling windows. - The cursor position is not affected by scrolling. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). **Examples:** ``` {.assembly} scroll 0, 1 ; Scrolls the main window (window 0) up by one line scroll 2, -3 ; Scrolls window 2 down by three lines ``` **Use Cases:** - Creating scrolling text displays, such as status messages or dialogue boxes. - Shifting the contents of a window to make room for new output. - Implementing custom scrolling behavior or animations. **Note:** The `SCROLL` opcode provides a way to manipulate the contents of a window by scrolling it up or down. It is important to consider the window's scrolling attribute and the desired visual effect when using this opcode. ### SET **SET** is an opcode that assigns a value to a variable. It is used to modify the contents of variables and update the program state. **Syntax:** ``` {.assembly} set var, value ``` **Functionality:** The `set` opcode assigns the specified `value` to the variable `var`. The type of `value` can be: - **Immediate value:** A constant value directly encoded within the instruction. - **Variable:** A reference to another variable. - **Other:** A value obtained from another instruction or expression. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} set counter, 0 ; Initializes the variable `counter` to 0 set player_health, health_potion ; Assigns the value of `health_potion` to `player_health` ``` **Use Cases:** - Initializing variables with specific values. - Updating variables based on game logic or player actions. - Assigning the results of calculations or expressions to variables. **Note:** The `SET` opcode is a fundamental operation for modifying variables and managing the program state in Z-code programs. ### SHIFT **SHIFT** is an opcode that performs a logical shift on a 16-bit integer value. It shifts the bits of the operand to the left or right, depending on the specified shift amount. **Syntax:** ``` {.assembly} shift int, n > val ``` **Functionality:** The `shift` opcode performs the following: - **Shifts the bits of `int`:** - If `n` is positive, `int` is shifted left by `n` bits. Zeros are shifted into the least significant bits. - If `n` is negative, `int` is shifted right by the absolute value of `n` bits. Zeros are shifted into the most significant bits. - **Does not preserve the sign bit:** In a logical shift, the sign bit is not replicated during a right shift. This means that the sign of the number may change after the shift. - **Stores the result:** The shifted value is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If `n` is zero, the value of `int` remains unchanged. - If the shift amount exceeds the word size (16 bits), the result is undefined. **Error Conditions:** None. **Examples:** ``` {.assembly} shift num, 2 > shifted ; Shifts the value in `num` left by 2 bits, filling with zeros shift num, -1 > shifted ; Shifts the value in `num` right by 1 bit, filling with zeros ``` **Use Cases:** - Multiplying or dividing numbers by powers of two efficiently. - Manipulating individual bits within a word. - Implementing bitwise operations and algorithms. **Note:** The `shift` opcode performs a logical shift, which does not preserve the sign of the operand. For an arithmetic shift, where the sign bit is replicated, use the `ashift` opcode. ### SOUND **SOUND** is an opcode that plays a sound effect. It allows Z-code programs to incorporate audio feedback and enhance the game experience. **Syntax:** ``` {.assembly} sound id:int, op:int [, volume:int, repeat:int] ``` **Functionality:** The `sound` opcode performs sound operations based on the specified arguments: - **`id`:** The ID number of the sound effect to play. - **`op`:** The sound operation to perform: - **1:** Initialize the specified sound. - **2:** Start playing the specified sound (default if `op` is omitted). - **3:** Stop playing the specified sound. - **4:** Clean up buffers associated with the specified sound. - **`volume` (optional):** The volume level at which to play the sound. -1 indicates the default volume. - **`repeat` (optional):** The number of times to repeat the sound. -1 indicates that the sound should repeat indefinitely until explicitly stopped. **Special Cases:** - **`id` = 0:** Uses the last sound ID specified. - **`id` = 1 or 2:** Plays a simple beep or boop sound, ignoring the `op` argument. - The availability of sound effects and the range of volume levels depend on the interpreter and target machine capabilities. **Error Conditions:** An error occurs if: - The interpreter does not support sound effects. - `id` is not a valid sound ID. - `op` is not within the valid range (1-4). - `volume` or `repeat` is invalid (if provided). **Examples:** ``` {.assembly} sound 10, 2 ; Starts playing sound effect with ID 10 sound 0, 3 ; Stops playing the last sound effect sound 5, 2, 50, 3 ; Plays sound effect 5 three times at 50% volume ``` **Use Cases:** - Playing sound effects to provide feedback or enhance the game atmosphere. - Creating audio cues for events or actions. - Implementing music or background sounds. **Note:** The `SOUND` opcode requires the interpreter to support sound effects. The `%FSOUN` flag in the `FLAGS` word and the `%XSOUN` bit in the `MODE` byte indicate whether sound operations are available. ### SPLIT **SPLIT** is an opcode that divides the screen vertically between windows 0 and 1. It is used to create a split-screen display, with each window showing different content. **Syntax:** ``` {.assembly} split height:int ``` **Functionality:** The `split` opcode adjusts the vertical dimensions and positions of windows 0 and 1 as follows: - **Sets window 1 height:** The height of window 1 is set to the value of `height` in lines. - **Sets window 1 position:** The top of window 1 is placed at the top of the screen (line 1). - **Adjusts window 0 position:** The top of window 0 is moved down to the line following the bottom of window 1. - **Adjusts window 0 height:** The height of window 0 is adjusted to fill the remaining space on the screen. - **Selects window 0:** After splitting the screen, window 0 becomes the active window for output. **Special Cases:** - **`height` = 0:** This effectively unsplits the screen, setting the height of window 1 to 0 and making window 0 occupy the entire screen. **Error Conditions:** None. **Examples:** ``` {.assembly} split 10 ; Splits the screen, giving window 1 a height of 10 lines split 0 ; Unsplits the screen ``` **Use Cases:** - Creating a split-screen display to show different information or perspectives simultaneously. - Implementing status displays or separate areas for text output and input. **Note:** The `SPLIT` opcode is a convenient way to create a split-screen display, but it only affects windows 0 and 1. For more flexible window management, consider using the `WINPOS` and `WINSIZE` opcodes. ### SUB **SUB** is an opcode that performs subtraction on two 16-bit word values. It subtracts the second operand from the first operand and returns the result. **Syntax:** ``` {.assembly} sub arg1:int, arg2:int > val ``` **Functionality:** The `sub` opcode performs the following: - **Subtracts `arg2` from `arg1`:** Performs integer subtraction. - **Stores the result:** The difference is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If the result of the subtraction overflows the 16-bit word size, an error occurs. **Error Conditions:** An error occurs if the subtraction result overflows the 16-bit word range. **Examples:** ``` {.assembly} sub 10, 5 > result ; Subtracts 5 from 10, stores the difference (5) in `result` ``` **Use Cases:** - Performing integer subtraction calculations. - Decreasing values or calculating differences between numbers. **Note:** The `sub` opcode performs signed integer subtraction. If the operands are unsigned, the programmer needs to handle potential overflow conditions. ### THROW **THROW** is an opcode that throws an exception and returns from a previously called function with a specified value. It is used in conjunction with the `CATCH` opcode to implement exception handling and non-local control flow. **Syntax:** ``` {.assembly} throw value, frame ``` **Functionality:** The `throw` opcode performs the following: - **Sets return value:** The specified `value` is set as the return value of the function identified by the `frame` pointer. - **Unwinds stack:** The interpreter unwinds the call stack, returning from all functions called since the function where the corresponding `CATCH` opcode was executed. - **Resumes execution:** Control is transferred back to the instruction following the `CATCH` opcode in the function that caught the exception. **Special Cases:** - The `frame` pointer must be a valid frame pointer obtained from a previous `CATCH` opcode. - Throwing an exception to a frame that is no longer on the call stack results in an error. **Error Conditions:** An error occurs if: - `frame` is not a valid frame pointer. - The frame pointed to by `frame` is no longer on the call stack. **Examples:** ``` {.assembly} catch > frame ; ... some code that might throw an exception ... throw "Error!", frame ; Throws an exception and returns to the `catch` instruction ``` **Use Cases:** - Implementing exception handling to deal with errors or unexpected conditions. - Performing non-local control flow, such as exiting multiple nested functions at once. **Note:** The `THROW` and `CATCH` opcodes provide a mechanism for exception handling and non-local control flow in Z-code programs. They should be used with caution to avoid complex control flow and potential errors. ### VALUE **VALUE** is an opcode that retrieves the value of a variable and stores it in a specified destination. It is used to access the current value of a variable and use it in calculations or other operations. **Syntax:** ``` {.assembly} value var > val ``` **Functionality:** The `value` opcode performs the following: - **Retrieves variable value:** Reads the value of the specified variable (`var`). - **Stores the result:** The retrieved value is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} value score > current_score ; Retrieves the value of `score` and stores it in `current_score` ``` **Use Cases:** - Accessing the current value of a variable for calculations or comparisons. - Passing variable values as arguments to functions. - Storing variable values in other variables or data structures. **Note:** The `VALUE` opcode is a simple way to retrieve the value of a variable. It is equivalent to using the variable directly as an operand in most instructions. ### VERIFY **VERIFY** is an opcode that checks the integrity of the game file by comparing a calculated checksum with a stored checksum value. It is used to detect potential corruption or modifications of the game data. **Syntax:** ``` {.assembly} verify /pred ``` **Functionality:** The `verify` opcode performs the following: - **Calculates checksum:** Computes a 16-bit checksum of the game file data from byte 64 to the end of the file (excluding the header). - **Compares with stored checksum:** Compares the calculated checksum with the value stored in the `PCHKSM` word of the program header. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if the calculated checksum matches the stored checksum. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - The checksum calculation excludes the first 64 bytes of the game file, which contain the program header. - The `PLENTH` word in the program header specifies the length of the game file in units of 8 bytes. **Error Conditions:** None. **Examples:** ``` {.assembly} verify / handle_corruption ; Branch to `handle_corruption` if the game file is corrupted ``` **Use Cases:** - Detecting unauthorized modifications or corruption of the game file. - Implementing copy protection mechanisms. - Ensuring data integrity before loading or saving games. **Note:** The effectiveness of the `VERIFY` opcode depends on the strength of the checksum algorithm and the implementation of copy protection measures. ### WINATTR **WINATTR** is an opcode that modifies the attributes of a window. Window attributes control various aspects of the window's behavior, such as text wrapping, scrolling, and transcripting. **Syntax:** ``` {.assembly} winattr window:int, bits:int, operation:int ``` **Functionality:** The `winattr` opcode modifies the attributes of the specified window (`window`) based on the `bits` and `operation` arguments: - **`bits`:** A bitmask where each bit represents a specific window attribute: - Bit 0: Text wrapping (1 = enabled, 0 = disabled). - Bit 1: Scrolling (1 = enabled, 0 = disabled). - Bit 2: Transcripting (1 = enabled, 0 = disabled). - Bit 3: Buffering (1 = enabled, 0 = disabled). - **`operation`:** Specifies how to modify the attributes: - **0 (MOVE):** Sets the window attributes to the values specified by `bits`. - **1 (SET):** Sets the attributes corresponding to the bits that are set (1) in `bits`. - **2 (CLEAR):** Clears the attributes corresponding to the bits that are set (1) in `bits`. - **3 (COMP):** Toggles the attributes corresponding to the bits that are set (1) in `bits`. **Special Cases:** - If the `operation` argument is omitted, it defaults to 0 (MOVE). **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `operation` is not within the valid range (0-3). **Examples:** ``` {.assembly} winattr 1, 1, 1 ; Enables text wrapping for window 1 winattr 2, 6, 2 ; Disables scrolling and transcripting for window 2 ``` **Use Cases:** - Changing the behavior of windows based on game logic or player actions. - Enabling or disabling text wrapping, scrolling, or transcripting for specific windows. - Customizing the appearance and functionality of the game interface. **Note:** The `WINATTR` opcode provides a flexible way to modify window attributes. It is important to understand the meaning of each bit in the `bits` argument and the effect of the different operations. ### WINGET **WINGET** is an opcode that retrieves the value of a specific property from a window's property table. Window properties store information about the window's position, size, attributes, and other characteristics. **Syntax:** ``` {.assembly} winget window:int, property:int > val ``` **Functionality:** The `winget` opcode retrieves the value of the property specified by `property` from the property table of the window identified by `window`: - **`window`:** The number of the window to access. - **`property`:** The number of the property to retrieve. Valid property numbers and their corresponding meanings are: - 0: `WTOP` - Y position of the window (top edge, in screen units). - 1: `WLEFT` - X position of the window (left edge, in screen units). - 2: `WHIGH` - Height of the window in screen units. - 3: `WWIDE` - Width of the window in screen units. - 4: `WYPOS` - Y coordinate of the cursor within the window (row number, 1-based). - 5: `WXPOS` - X coordinate of the cursor within the window (column number, 1-based). - 6: `WLMARG` - Left margin of the window in pixels. - 7: `WRMARG` - Right margin of the window in pixels. - 8: `WCRFCN` - Function to call for carriage return interrupts. - 9: `WCRCNT` - Counter for carriage return interrupts. - 10: `WHLIGHT` - Highlighting mode of the window. - 11: `WCOLOR` - Color word of the window (background and foreground colors). - 12: `WFONT` - Font ID used in the window. - 13: `WFSIZE` - Font size (height and width) used in the window. - 14: `WATTRS` - Window attributes (wrapping, scrolling, transcripting, buffering). - 15: `WLCNT` - Line counter for the window. - **Stores the result:** The retrieved property value is stored in the specified destination (`val`). If no destination is provided, the result is pushed onto the game stack. **Special Cases:** - If the `window` argument is omitted, the current window is used. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `property` is not a valid property number. **Examples:** ``` {.assembly} winget 0, 2 > window_height ; Retrieves the height of the main window (window 0) winget 1, 14 > window_attrs ; Retrieves the attributes of window 1 ``` **Use Cases:** - Accessing information about window properties, such as position, size, or attributes. - Implementing custom window management or display routines. - Checking the state of specific window features. **Note:** The `WINGET` opcode provides a flexible way to access various window properties. It is important to use the correct property numbers to retrieve the desired information. ### WINPOS **WINPOS** is an opcode that sets the position of a window on the screen. It allows for precise control over the location of windows within the display area. **Syntax:** ``` {.assembly} winpos window:int, y:int, x:int ``` **Functionality:** The `winpos` opcode sets the position of the specified window (`window`) to the coordinates (`y`, `x`): - **`window`:** The number of the window to reposition. - **`y`:** The Y coordinate of the top-left corner of the window (row number, 1-based). - **`x`:** The X coordinate of the top-left corner of the window (column number, 1-based). The coordinates are specified in screen units, with the top-left corner of the screen being (1, 1). **Special Cases:** - If the `window` argument is omitted, the current window is repositioned. - The opcode does not check if the new window position would place the window partially or completely off-screen. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `y` or `x` is negative. **Examples:** ``` {.assembly} winpos 1, 5, 10 ; Positions window 1 at row 5, column 10 winpos 2, 1, 1 ; Positions window 2 at the top-left corner of the screen ``` **Use Cases:** - Positioning windows for optimal layout and user interface design. - Creating overlapping windows or dynamic window arrangements. - Implementing custom window management or animation routines. **Note:** The `WINPOS` opcode provides direct control over window positioning. It is important to consider the window's size and the overall screen layout when using this opcode. ### WINPUT **WINPUT** is an opcode that sets the value of a specific property within a window's property table. It allows for modifying various aspects of a window's behavior and appearance. **Syntax:** ``` {.assembly} winput window:int, property:int, value ``` **Functionality:** The `winput` opcode sets the value of the property specified by `property` in the property table of the window identified by `window`: - **`window`:** The number of the window to modify. - **`property`:** The number of the property to set. See the description of `WINGET` for a list of valid property numbers and their meanings. - **`value`:** The new value to assign to the property. **Special Cases:** - Not all window properties are writable using `WINPUT`. Some properties, such as window size and position, require specific opcodes like `WINSIZE` and `WINPOS` for modification. - If the `window` argument is omitted, the current window is used. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `property` is not a valid property number or is not writable. **Examples:** ``` {.assembly} winput 1, 10, 2 ; Sets the highlighting mode of window 1 to bold winput 2, 6, 15 ; Sets the left margin of window 2 to 15 pixels ``` **Use Cases:** - Modifying window properties to change their behavior or appearance. - Setting the highlighting mode, color, or font of a window. - Adjusting margins or other window settings. **Note:** The `WINPUT` opcode provides a way to modify window properties, but it is important to check which properties are writable and use the appropriate opcodes for those that are not. ### WINSIZE **WINSIZE** is an opcode that sets the size of a window on the screen. It allows for controlling the dimensions of windows and adjusting the display area they occupy. **Syntax:** ``` {.assembly} winsize window:int, height:int, width:int ``` **Functionality:** The `winsize` opcode sets the size of the specified window (`window`) to the given dimensions: - **`window`:** The number of the window to resize. - **`height`:** The new height of the window in screen units (number of lines). - **`width`:** The new width of the window in screen units (number of characters). If the new size would cause the window to extend beyond the screen boundaries, the dimensions are adjusted to fit within the available space. **Special Cases:** - If the `window` argument is omitted, the current window is resized. - If the new size is smaller than the current cursor position, the cursor is moved to the bottom-right corner of the resized window. **Error Conditions:** An error occurs if: - `window` is not within the valid range (-3 to 7). - `height` or `width` is zero or negative. **Examples:** ``` {.assembly} winsize 1, 10, 40 ; Sets the size of window 1 to 10 lines by 40 characters winsize 2, 25, 80 ; Sets the size of window 2 to 25 lines by 80 characters (full screen width) ``` **Use Cases:** - Adjusting the size of windows to fit content or accommodate different display requirements. - Creating windows with specific dimensions for menus, dialog boxes, or other UI elements. - Implementing dynamic window resizing or animations. **Note:** The `WINSIZE` opcode provides direct control over window size. It is important to consider the window's position and the overall screen layout when using this opcode. ### XCALL **XCALL** is an opcode that calls a function with a variable number of arguments and returns a value. It is the most general form of the `CALL` instruction, allowing for up to seven arguments to be passed to the function. **Syntax:** ``` {.assembly} xcall fcn, arg1:any [, arg2:any ...] > val ``` **Functionality:** The `xcall` opcode performs the following: - **Pushes arguments onto the stack:** Pushes the variable number of arguments (`arg1`, `arg2`, etc.) onto the game stack. The number of arguments is determined by the operand types specified in the instruction. - **Calls the function:** Transfers control to the function specified by `fcn`. The function address is calculated by shifting `fcn` left by two bits and adding the function offset (`FOFF`) shifted left by three bits. - **Retrieves return value:** When the function returns, its return value is retrieved and stored in the specified destination (`val`). If no destination is provided, the value is pushed onto the game stack. **Special Cases:** - If `fcn` is zero, the `xcall` opcode acts as if it called a function that immediately returned false. **Error Conditions:** An error occurs if `fcn` is not a valid function pointer. **Examples:** ``` {.assembly} xcall format_string, buffer, arg1, arg2, arg3 > formatted_text ; Calls the `format_string` function with four arguments ``` **Use Cases:** - Calling functions with a variable number of arguments. - Implementing functions that take a flexible number of parameters. **Note:** The `XCALL` opcode is generated by the compiler when it detects a function call with more than two arguments or when the argument types require the extended format. It is not typically used directly by programmers. ### XPUSH **XPUSH** is an opcode that attempts to push a value onto a stack and acts as a predicate based on the success of the operation. It can be used with both the game stack and user-defined stacks. **Syntax:** ``` {.assembly} xpush value, stack:tbl /pred ``` **Functionality:** The `xpush` opcode performs the following: - **Checks stack space:** Determines if there is enough space available on the specified stack (`stack`) to push the value. - **Pushes value (if space available):** If there is sufficient space, the opcode pushes the `value` onto the top of the stack. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if the value was successfully pushed onto the stack. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** - If the `stack` argument is omitted, the opcode operates on the game stack. **Error Conditions:** An error occurs if `stack` is not a valid table pointer (if provided). **Examples:** ``` {.assembly} xpush item, inventory / inventory_full ; Attempts to push `item` onto the `inventory` stack ; ... code to handle full inventory ... inventory_full: ``` **Use Cases:** - Pushing values onto stacks while checking for potential stack overflow conditions. - Implementing stack-based data structures with overflow handling. **Note:** The `XPUSH` opcode provides a way to push values onto stacks while simultaneously checking for available space. This can be useful for preventing stack overflow errors and implementing robust stack management. ### ZERO? **ZERO?** is an opcode that checks whether a value is equal to zero. It acts as a predicate, meaning it evaluates a condition and implicitly performs a conditional branch based on the result. **Syntax:** ``` {.assembly} zero? arg:any /pred ``` **Functionality:** The `zero?` opcode performs the following: - **Checks for zero:** Determines if the value of `arg` is equal to zero. - **Evaluates predicate:** The predicate succeeds (evaluates to true) if `arg` is indeed zero. Otherwise, the predicate fails (evaluates to false). - **Conditional branch:** Based on the predicate result and the specified branch polarity (`/pred`), the interpreter may perform a conditional jump to a specified target. **Special Cases:** None. **Error Conditions:** None. **Examples:** ``` {.assembly} zero? counter / end_loop ; Branch to `end_loop` if `counter` is zero ``` **Use Cases:** - Implementing conditional logic based on zero checks. - Determining if a variable or expression has a value of zero. - Loop termination conditions. **Note:** The `ZERO?` opcode is a simple but useful predicate for checking for zero values and implementing conditional behavior in Z-code programs. ### ZWSTR **ZWSTR** is an opcode that converts a word from an input buffer into a Z-string and stores it in a specified location. Z-strings are the standard format for representing text in Z-code programs. **Syntax:** ``` {.assembly} zwstr inbuf:tbl, inlen:int, inbeg:int, zword:tbl ``` **Functionality:** The `zwstr` opcode performs the following: - **Reads input word:** Extracts the word starting at the byte offset `inbeg` within the input buffer `inbuf`. The `inlen` argument specifies the length of the word in bytes, but it is not strictly necessary as the opcode assumes the word is terminated by a break character (whitespace or a self-inserting break character). - **Converts to Z-string:** Encodes the extracted word into a Z-string using the current character set and frequent words table. - **Stores the result:** The encoded Z-string is stored in the first three words of the `zword` table. **Special Cases:** - The `inbuf` argument is typically a pointer to the text buffer used by the `READ` or `LEX` opcodes. - The `zword` table must have at least three words of available space to store the Z-string. **Error Conditions:** An error occurs if: - `inbuf` or `zword` is not a valid table pointer. - `inbeg` is outside the bounds of the `inbuf` table. - The `zword` table does not have enough space to store the Z-string. **Examples:** ``` {.assembly} read input_buffer, lexv zwstr input_buffer, 0, lexv[1].offset, word_buffer ; Converts the second word from the parsed input into a Z-string ``` **Use Cases:** - Converting words from input buffers into Z-strings for further processing or comparison. - Implementing custom parsing or text manipulation routines. **Note:** The `ZWSTR` opcode is used to convert words from input buffers into the Z-string format used by the Z-machine. It is typically used in conjunction with the `READ` or `LEX` opcodes for processing player input. Chapter 3.2: Opcode Summary Table --------------------------------- -------------------------------------------------------------------------------------- Opcode Name Operands Type Description -------- ------------- --------------- ------ ---------------------------------------- 1 EQUAL? arg1:any, 2OP Is arg1 equal to any one of arg2, arg3, arg2:any or arg4? Note that in the extended form, EQUAL? can take more than two operands. 2 LESS? arg1:int, 2OP Is arg1 less than arg2? arg2:int 3 GRTR? arg1:int, 2OP Is arg1 greater than arg2? arg2:int 4 DLESS? var, int 2OP Decrements var and succeeds if new value is less than int. 5 IGRTR? var, int 2OP Increments var and succeeds if new value is greater than int. 6 IN? child:obj, 2OP Is child contained in parent? parent:obj 7 BTST arg1:word, 2OP Are bits on in arg2 also on in arg1? arg2:word 8 BOR arg1:word, 2OP Bitwise logical OR. arg2:word 9 BAND arg1:word, 2OP Bitwise logical AND. arg2:word 10 FSET? obj, flag 2OP Is flag number set in obj? 11 FSET obj, flag 2OP Sets flag in obj. 12 FCLEAR obj, flag 2OP Clears flag in obj. 13 SET var, any 2OP Sets variable to any. 14 MOVE thing:obj, 2OP Puts thing into dest as the first dest:obj object. 15 GET table, item 2OP Returns item'th element of table (word-oriented). 16 GETB table, item 2OP Returns item'th element of table (byte-oriented). 17 GETP obj, prop 2OP Returns prop property of obj. 18 GETPT obj, prop 2OP Returns pointer to property table prop from obj. 19 NEXTP obj, prop 2OP Returns number of the property following prop in obj. 20 ADD arg1:int, 2OP Adds the integers. arg2:int 21 SUB arg1:int, 2OP Subtracts arg2 from arg1. arg2:int 22 MUL arg1:int, 2OP Multiplies the integers. arg2:int 23 DIV arg1:int, 2OP Divides arg1 by arg2, returning the arg2:int truncated quotient. 24 MOD arg1:int, 2OP Divides arg1 by arg2, returning the arg2:int remainder. 25 CALL2 fcn, any 2OP Calls the function pointed to by fcn. 26 ICALL2 routine:fcn, 2OP Calls the function pointed to by fcn (no arg1:any return value). 27 COLOR fore:int, 2OP Sets foreground and background color. back:int 28 THROW any, frame 2OP Returns any from a frame (see CATCH). 128 ZERO? arg:any 1OP Is arg equal to zero? 129 NEXT? obj 1OP Returns the "next" slot of obj (fails if none). 130 FIRST? obj 1OP Returns the "first" slot of obj (fails if none). 131 LOC obj 1OP Returns the "parent" of obj (zero if none). 132 PTSIZE table 1OP Returns length of property table in bytes. 133 INC var 1OP Increments the value of var by one. 134 DEC var 1OP Decrements the value of var by one. 135 PRINTB str 1OP Prints the string pointed to by str (byte pointer). 136 CALL1 fcn 1OP Calls the function pointed to by fcn. 137 REMOVE obj 1OP Removes obj from the object tree. 138 PRINTD obj 1OP Prints the short description of obj. 139 RETURN any 1OP Returns from the most recently executed call. 140 JUMP loc 1OP Unconditional relative branch. 141 PRINT str 1OP Prints the string pointed to by str (quad pointer). 142 VALUE var 1OP Returns the value of var. 143 ICALL1 routine:fcn 1OP Calls the function pointed to by fcn (no return value). 176 RTRUE 0OP Returns 1 (true). 177 RFALSE 0OP Returns 0 (false). 178 PRINTI (in-line 0OP Prints an immediate string. string) 179 PRINTR (in-line 0OP Prints an immediate string and executes string) CRLF + RTRUE. 180 NOOP 0OP No operation. 183 RESTART 0OP Reinitializes the game. 184 RSTACK 0OP Returns from a call and takes value from stack. 185 CATCH 0OP Returns a pointer to the current call frame. 186 QUIT 0OP Terminates the game. 187 CRLF 0OP Prints an end-of-line sequence. 188 (Unused) 189 VERIFY 0OP Verifies the game program on disk. 190 EXTOP opcode:int 0OP Signals the next opcode is an extended opcode. 191 ORIGINAL? 0OP Returns non-false if the game disk is the original. 193 EQUAL? arg1:any, EXT Is arg1 equal to any of the other arg2:any, ... arguments? 224 CALL fcn, any1, EXT Calls the function pointed to by fcn. any2, any3 225 PUT table, item, EXT Sets the word pointed to in table to any any. 226 PUTB table, item, EXT Sets the byte pointed to in table to the any low byte of any. 227 PUTP obj, prop, any EXT Changes the value of obj's property prop to any. 228 READ inbuf:tbl, EXT Reads a line of input and parses it. lexv:tbl, time:int, handler:fcn 229 PRINTC int EXT Prints the character whose ASCII value is int. 230 PRINTN int EXT Prints int as a signed number. 231 RANDOM arg:int EXT Returns a random value between 1 and arg. 232 PUSH value EXT Pushes value onto the game stack. 233 POP stack EXT Pops a value from the stack. 234 SPLIT height:int EXT Splits the screen vertically between windows 0 and 1. 235 SCREEN window:int EXT Selects the specified window for output. 236 XCALL fcn, any1, ..., EXT Calls the function pointed to by fcn (up any7 to 7 args). 237 CLEAR window:int EXT Clears the specified window. 238 ERASE int EXT Erases a portion of the current line. 239 CURSET y:int, x:int, EXT Sets the cursor position in the window specified window. 240 CURGET output:tbl EXT Returns information about the current cursor position. 241 HLIGHT int EXT Sets the display highlighting mode. 242 BUFOUT int EXT Controls output buffering. 243 DIROUT device:int, EXT Selects or deselects a virtual output any1, any2, device. any3 244 DIRIN device:int, EXT Selects or deselects a virtual input any1, any2, device. any3 245 SOUND id:int, op:int, EXT Produces a sound. volume:int, repeat:int 246 INPUT dev:int, EXT Returns a single byte from the specified time:int, device. handler:fcn 247 INTBL? item, tbl, EXT Searches for a record in a table. len:int, recspec:int 248 BCOM arg:word 1OP Performs a bitwise logical NOT (complement) on the word. 249 ICALL routine:fcn, EXT Calls the function pointed to by fcn (no arg1:any, return value). arg2:any, arg3:any 250 IXCALL routine:fcn, EXT Calls the function pointed to by fcn arg1,... (variable args, no return value). 251 LEX inbuf:tbl, EXT Tokenizes and looks up an input buffer's lexv:tbl, contents. lexicon:tbl, preserve:bool 252 ZWSTR inbuf:tbl, EXT Converts a word to a Z-string. inlen:int, inbeg:int, zword:tbl 253 COPYT source:tbl, EXT Copies bytes from source to dest. dest:tbl, length:int 254 PRINTT bytes:tbl, EXT Prints a block of text from a table. width:int, height:int, skip:int 255 ASSIGNED? opt:var EXT Checks if an optional argument was supplied. 256 SAVE start:tbl, EXT Saves a section of the game state. length:int, name:tbl 257 RESTORE start:tbl, EXT Restores a section of the game state. length:int, name:tbl 258 SHIFT int, n EXT Performs a logical shift on int. 259 ASHIFT int, n EXT Performs an arithmetic shift on int. 260 FONT font:int, EXT Selects a font for the specified window. window 261 DISPLAY picture:int, EXT Displays a picture at the specified y:int, x:int location. 262 PICINF picture:int, EXT Returns information about a picture. data:tbl 263 DCLEAR picture:int, EXT Clears the area occupied by a picture. y:int, x:int 264 MARGIN left:int, EXT Sets the left and right margins for a right:int, window. window 265 ISAVE EXT Saves the game state to a reserved area in RAM. 266 IRESTORE EXT Restores the game state from the reserved area in RAM. 272 WINPOS window:int, y, EXT Sets the location of the top left corner x of a window. 273 WINSIZE window, y, x EXT Sets the size of a window. 274 WINATTR window, bits, EXT Sets characteristics of a window. operation 275 WINGET window, offset EXT Returns the value of a window property. 276 SCROLL window, lines EXT Scrolls the specified window up or down. 277 FSTACK n, stack EXT Flushes n elements from the specified stack. 278 MOUSE-INFO table EXT Returns information about the mouse status. 279 MOUSE-LIMIT window EXT Restricts the mouse to a specific window. 280 XPUSH value, stack EXT Pushes value onto the specified stack. 281 WINPUT window, offset, EXT Sets the value of a window property. value 282 PRINTF tbl EXT Prints a formatted table. 283 MENU id, tbl EXT Adds a menu to the menu bar. 284 PICSET tbl EXT A table of picture numbers to pre-load or cache for faster display. Pictures not included in the most recent PICSET call are no longer considered "hot" and can be safely removed from the cache. --------------------------------------------------------------------------------------