Here I list a bunch of things that can be done with Z-machine, not specific to any programming language (although some may only be possible in some programming languages). Examples may sometimes be given in the Frolg assembler language, if necessary.
- 1 Alphabet table
- 2 Dynamic fwords
- 3 Global variables overlapping the extension table
- 4 Global variables overlapping the object table
- 5 Level data in high memory
- 6 Memory layout in version 6 and 7 story files
- 7 Overlapping text strings
- 8 Shared property tables
- 9 Shared text
- 10 Truncated default property table
- 11 Very long object names
The alphabet table can be modified so that common characters are on row 0. If there are uncommon characters but they often go together in long strings (for output only, though), you might put them on row 2; a permanent shift into row 2 can more efficiently select a single character from row 1 than the other way around. (Note: The Z-Machine Standard only allows shift locks in V1 and V2; Infocom's interpreters allowed them for later versions, but this functionality was never used. Frolg is the only compiler that will encode them in later versions, and only if it is not in COMPLIANT mode.)
See also: Fun With ZCharacter
Reserve part of the fwords table for dynamic entries. This can be used to allow descriptions to be changed depending on circumstances. An example might be a user option to switch between British or American spelling, or if a lot of descriptions will include the player's name.
Global variables overlapping the extension table
The global variable table can overlap the extension table, so that the mouse and joystick state can be accessed directly as variables.
Global variables overlapping the object table
If the object table is placed right after the global variables table, the first object header might fit in the global variables table. If the first object is the player, then you can read their location easily as a global variable.
Level data in high memory
If the level data doesn't fit in core memory, you can store it in high memory, as a text string loaded into output stream 3.
A two-stage compression can be used, one of which is the Z-machine text packing (which can use the fwords table and other things), and then use a secondary decompression implemented in your program, which might involve run-length encoding, Huffman coding, and whatever else is necessary.
Remember that you will want to represent the most common tiles, as well as other things like run-length, in row 0 (lowercase letters).
Memory layout in version 6 and 7 story files
Version 6 uses offsets in the header which are added to the routine number and string number to calculate their address. This can be used to make overlong story files.
An example of a memory layout might look like this:
- $00000-$0FFFF: Core
- $10000-$1FFFF: Strings for fwords table
- $20000-$5FFFF: Routines
- $60000-$9FFFF: Strings
The VERIFY command won't work if you do this, so if you want to verify it, the interpreter will need to have some other way of doing so.
Overlapping text strings
Text strings can overlap, if one of them doesn't have the high bit set when it ends when it will continue with the next one. Therefore you can have one string which is short and then another one which ends with the same text as that one.
You might also need padding. How this is done depends on the current state and on the Z-machine version. You will need to change it from its current state to row 0.
Here are the possible paddings (after any one, you can place any sequence of state 0 paddings, to fill up the extra padding if required):
- Version 1, state 0: empty, 45, 444.
- Version 1, state 1: 5, 44.
- Version 1, state 2: 4, 55.
- Version 3, state 0: empty, 45, 445.
- Version 3, state 1: 5, 45.
- Version 3, state 2: 4, 54.
You can make multiple objects sharing property tables if it would help. Such objects will then share their name and property values, although they will still have their individual locations and attributes.
It might help if the properties are read-only for those class of objects. An example might be if many rooms contain an identical magical portal all leading to the same location.
If you have a long string with only lowercase letters and spaces (no fwords references) and you want the uppercase variant, it can be the previous text string which encodes a permanent shift into uppercase letters. The coding is:
- Version 1: 454.
- Version 3: 444.
- Version 5: 444444.
It can also be used to make two addresses point to the same text string, regardless of what they contain, in the same shift state too, in case for whatever reason you need two different numbers for the same string. The coding is:
- Version 1: 444.
- Version 3: 445.
- Version 5: 444445.
Truncated default property table
If you don't need 63 default properties, you can truncate the default property table to only the default properties you need. Number the properties that need defaults with the highest numbers, 63 and down. The header to specify where the object table is, it is then deducted the unused default properties so that the address of the default properties will be correct. (Frolg automatically does this.)
Very long object names
Object names have to be in core (which is limited to 64K) and are limited to 765 Z-characters. If you have very long names, you can make them fit by storing them in the fwords table. (The Z-machine port of Wry Humor does this.)