Since version 1 of ZIP, the story header is a fixed 64 bytes at the start of every Infocom game that provides information regarding the location of specific data and code. The header for ZIP 1 games used the first 9 words/18 bytes. Subsequent ZIP versions would add more values into the header. XZIP (Version 5) would use all 32 words (64 bytes).
The original story header information about the game and addresses to specific types of data. Details are in Appendix A. The first word, ZVERSION, ensures that the ZIP is compatible with the given story file and emulates the proper Z-machine version. The version number is located in the first byte. The second byte has the mode flags which are set by the ZAP assembler (for bits 0 and 1) and the ZIP at startup for the remaining bits. START address will be the first operation to be executed by the ZIP. It points to the first instruction and not the start of the routine. The next three addresses are used by the various instructions. All the object-related operators use the address in OBJECT to manipulate the object data. The READ instruction uses the Vocabulary data at VOCAB to match and tokenize the characters in the input buffer. GLOBALS points to the table holding the global variables data.
ZIP 1 Story Header:
Word
|
Name
|
Function
|
00
|
ZVERSION
|
Byte 0: Z-machine version
Byte 1: Z-machine mode
|
01
|
ZORKID
|
Release number
|
02
|
ENDLOD
|
End address of pre-loaded memory, start of variable (or exchangeable memory)
|
03
|
START
|
Address of first instruction (not routine), Program Counter
|
04
|
VOCAB
|
Address to Vocabulary table
|
05
|
OBJECT
|
Address to Object data
|
06
|
GLOBALS
|
Address to Global Variable table
|
07
|
PURBOT
|
Start address of read-only (static) memory
|
2.2 The Memory Layout of Infocom Games
The layout of data in the Infocom game files is fairly consistent between games. An example using Zork 1 is shown below. The “memory” of the emulated Z-machine is first loaded with the header information starting at $0000. Memory from $0000 up to PURBOT encompasses the writeable memory such as variables, objects, tables, and buffers. Data after PURBOT is read-only data such as syntax data, routines, preposition data, and strings. The exact locations of the syntax data, action routines, and preposition table are stored in global variables, not the header. The ZIP will continue to load data into memory. All data up to the address in ENDLOD must be loaded. The ZIP may decide to load data past ENDLOD at its discretion. All data after ENDLOD can be swapped out with other disk-based data as needed. Usually routines and strings are the data that is swapped. All important and quickly accessible data remains resident in memory below the ENDLOD address.
Base End Size
0000 3F 40 Story file header
0040 7D 3D Objects - Property Defaults (Address at OBJECTS, word 5)
007E 974 935 Objects - Entries
0975 203A 16C6 Objects - Property data
203B 221A 1E0 Global Variables (Address at GLOBALS, word 6)
221B 2C28 A0E Misc Data (such as tables and buffers)
2C29 2CFE D6 Syntax - Pointer table (Address at PURBOT)
2CFF 33d4 6D6 Syntax - Entries (referred by the Pointer Table)
33D5 34b6 E2 Action routine table (Address in global variables)
34B7 3598 E2 Pre-action routine table (Address in global variables)
3599 35DE 46 Preposition table (Address in global variables)
35DF 46CA 10EC Vocabulary (Address at VOCAB, word 4)
46CC EDC5 A6FA Routines (Load up to ENDLOD, $5DEC here)
EDC6 14328 5563 Strings
14329 143FF D7 Empty (fill up to the end of memory page)
2.3 The Massive Object Table
Objects are the heart of the Infocom games and are the first data after the story header. Storing them in a logical and efficient manner for the game to access is important. Each object contains information such as the name, properties and attributes. It will also have a parent and possibly siblings. The object’s parent is usually a room or container that contains the object. Siblings are objects that are in the same room or container. Rooms are also considered objects and have a generic ROOMS object as the parent for all rooms. Attributes are true/false bits that set various characteristics of an object such as is it takable (TAKEBIT) or a source of fire (FLAMEBIT). They are numbered 0 to 31. Each object will define all the attributes. Properties are like attributes but hold groups of bytes instead of a bit. The maximum size for a property is 8 bytes. If no property is given for an object, the default property value (a word) is used. Properties are numbered 1 to 31. Objects are numbered from 1 to 255.
- Default Property Table:
- 31 words that are the default property values if it is not explicit set for a specific object
- Object Entries - repeated for all objects
- 4 bytes representing the 32 attribute bits (#0=top bit of byte 0, #31=bottom bit of byte 3)
- 1 byte each for object number of the parent, sibling, and child of the object
- 1 word address to that object’s property table
- Property Table - repeated for all objects with their own property table
- 1 byte for size of the object name in words
- Z-string of the object name
- 1 byte for property info (LLLNNNNN)
- bits 5-7 = length of property-1 (length 1-8 bytes is represented as 0-7)
- bits 0-4 = property number
- 1-8 bytes of property data
- The 1 byte property info and 1-8 property data are repeated for each property, listed in descending order
Example object property table:
The meaning of an attribute or property number is consistent in all objects in that game but not consistent between games. For example. the attribute bit and properties used in Zork 1 are listed in Appendices B and C. The number of objects is not specifically stored here but calculated based upon the number of object entries. It can also be calculated by the difference between the addresses of the first object entry and first property table entry divided by 9 bytes for each entry.
2.4 Global VariablesThe section following the objects is a 480 byte block corresponding to 240 global variables with each holding a word. By default in Infocom version 1-3 games, variable 0 contains the object number of the player’s current location. Variable 1 is the score while variable 2 is the number of turns or game time. A game does not need to use all 240 global variables and can use part of this memory block for other variable data such as tables and buffers. The addresses to these other data structures as well as addresses to specialized grammar structures like syntax entries, preposition table, and action routine table are typically stored in global variables.
2.5 Tables and Buffers
Between the last global variable and the start of the static data (at PURBOT), there is usually extra memory that is used to store custom data structures. These are typical tables and buffers. Tables are a fixed set of words where the first word (element 0) contains the number of elements in the table. Examples include tables to hold the direct or indirect object numbers. A buffer is just a fixed set of bytes used to hold any type of data. The most common buffers used in Infocom games are the input buffer (INBUF) or token buffer (LEXV). These data structures are not standard to ZIL and are specific to Infocom games. For ZIP 1-3 games, these tables are located in the preloaded memory of the computer. For EZIP and XZIP games, tables can also be located amongst the game routines. The addresses to these buffers and tables are usually stored in specific global variables but can sometimes be hardcoded into the routines that use them. If a game does not need all 240 global variables, the space for those unused variables can be used for buffers and tables. Infocom games have their own custom ZIL routines for reading and writing to these structures.
Between the last global variable and the start of the static data (at PURBOT), there is usually extra memory that is used to store custom data structures. These are typical tables and buffers. Tables are a fixed set of words where the first word (element 0) contains the number of elements in the table. Examples include tables to hold the direct or indirect object numbers. A buffer is just a fixed set of bytes used to hold any type of data. The most common buffers used in Infocom games are the input buffer (INBUF) or token buffer (LEXV). These data structures are not standard to ZIL and are specific to Infocom games. For ZIP 1-3 games, these tables are located in the preloaded memory of the computer. For EZIP and XZIP games, tables can also be located amongst the game routines. The addresses to these buffers and tables are usually stored in specific global variables but can sometimes be hardcoded into the routines that use them. If a game does not need all 240 global variables, the space for those unused variables can be used for buffers and tables. Infocom games have their own custom ZIL routines for reading and writing to these structures.
Looks like an image is missing here: the object property table.
ReplyDeleteWhich document you reference, when you mention Appendices A, B and C?
ReplyDelete