ZZT file format
General Info
All 8-bit (byte) values are unsigned. All 16-bit (short) values are signed. Boolean values (such as a player's keys) are represented with 0 for false and 1 for true.
World Name is used by the game both on the title screen to display the game name as well as determine which file to load after the player quits and restarts the game. Therefore if a world contains a world name that is actually the filename of another world, after the player quits and restarts the game, the world with the matching filename will be loaded.
There are some unused bytes after the world information that are ignored by the game. While it is safe to put any data whatsoever into this unused space, it is not saved back to disk by the ZZT and will be converted to empty padding.
World Header
This header is found at the head of all ZZT files. After this information, storage of the boards starts at byte offset 512 (hex 0x200).
Unused values are preserved. Data not listed here is overwritten with zeroes when saving worlds.
Offset | Hex | Data type | Description |
---|---|---|---|
0 | 0x000 | INT16LE | WorldType Used to identify the world's format. ZZT uses -1 (FF FF). |
2 | 0x002 | INT16LE | NumBoards Number of boards in the world, not including the title screen. Increment by 1 for the real number of stored boards. A value of 0 means only the title screen exists. |
4 | 0x004 | INT16LE | PlayerAmmo Player's ammunition. |
6 | 0x006 | INT16LE | PlayerGems Player's gems. |
8 | 0x008 | char[7] | PlayerKeys Player's keys. A nonzero value means the player has the specified key. The keys are in this order: Blue, Green, Cyan, Red, Purple, Yellow, White. |
15 | 0x00F | INT16LE | PlayerHealth Player's health. |
17 | 0x011 | INT16LE | PlayerBoard In a world file, this will be the starting board for the player (the title screen, board 0, is always shown first). In a saved game, this will be the board that the player is currently on. |
Offset | Hex | Data type | Description |
---|---|---|---|
19 | 0x013 | INT16LE | PlayerTorches Player's torches. |
21 | 0x015 | INT16LE | TorchCycles Game cycles left for a torch to remain lit. |
23 | 0x017 | INT16LE | EnergyCycles Game cycles left for an energizer to be effective. |
25 | 0x019 | INT16LE | (unused) |
27 | 0x01B | INT16LE | PlayerScore Player's score. |
29 | 0x01D | UINT8 | WorldNameLength Length of the internal name of the world. |
30 | 0x01E | char[20] | WorldName Internal name of the world. |
50 | 0x032 | UINT8 | Flag0Length Length of the name of Flag 0. |
51 | 0x033 | char[20] | Flag0 Name of Flag 0. |
71 | 0x047 | UINT8 | Flag1Length Length of the name of Flag 1. |
72 | 0x048 | char[20] | Flag1 Name of Flag 1. |
92 | 0x05C | UINT8 | Flag2Length Length of the name of Flag 2. |
93 | 0x05D | char[20] | Flag2 Name of Flag 2. |
113 | 0x071 | UINT8 | Flag3Length Length of the name of Flag 3. |
114 | 0x072 | char[20] | Flag3 Name of Flag 3. |
134 | 0x086 | UINT8 | Flag4Length Length of the name of Flag 4. |
135 | 0x087 | char[20] | Flag4 Name of Flag 4. |
155 | 0x09B | UINT8 | Flag5Length Length of the name of Flag 5. |
156 | 0x09C | char[20] | Flag5 Name of Flag 5. |
176 | 0x0B0 | UINT8 | Flag6Length Length of the name of Flag 6. |
177 | 0x0B1 | char[20] | Flag6 Name of Flag 6. |
197 | 0x0C5 | UINT8 | Flag7Length Length of the name of Flag 7. |
198 | 0x0C6 | char[20] | Flag7 Name of Flag 7. |
218 | 0x0DA | UINT8 | Flag8Length Length of the name of Flag 8. |
219 | 0x0DB | char[20] | Flag8 Name of Flag 8. |
239 | 0x0EF | UINT8 | Flag9Length Length of the name of Flag 9. |
240 | 0x0F0 | char[20] | Flag9 Name of Flag 9. |
260 | 0x104 | INT16LE | TimePassed Amount of time in seconds that has passed on the current board. Only applicable if the board the player is on has a time limit. |
262 | 0x106 | INT16LE | TimePassedTicks This contains information about sub-seconds on time limited boards. |
264 | 0x108 | UINT8 | Locked A nonzero value indicates the world is actually a saved game. Additionally, worlds with a nonzero Locked byte can't be edited using the built-in editor. |
265 | 0x109 | UINT8[14] | (unused) |
After this follows the boards. Boards consist of 4 parts: Board Header, RLE Tiles, Board Properties, and Status Element Properties. Status Elements are elements on the board that the game actively processes - these include the player, enemies, any animating blocks, and Scrolls and Objects which can contain ZZT-OOP code.
Board header
ZZT boards are 60x25 tiles.
Offset | Hex | Data type | Description |
---|---|---|---|
0 | 0x000 | INT16LE | BoardSize Size of the board, in bytes (excluding the two bytes from this value). Even if the board was corrupted by the built-in editor (which happens sometimes) this value will be correct; the rest of the boards remain intact and in place. |
2 | 0x002 | UINT8 | BoardNameLength Length of the board's name. |
3 | 0x003 | char[50] | BoardName Board's name. |
53 | 0x035 | ZZT_RLE | Tiles Start of the RLE tile data. |
Run-length encoded tile data
Tile data is represented as sets of 3 bytes. These sets are repeated until the board is completely filled. For ZZT, this will be 60*25=1500 tiles. The tiles are unpacked from left to right, top to bottom.
Data type | Description |
---|---|
UINT8 | Count Number of tiles. |
UINT8 | Element Element of the tiles. |
UINT8 | Color Color of the tiles. |
A small quirk of this RLE format is when the number of tiles is set to zero. Due to the way the decoder is set up, a Count of 0 means there are actually 256 tiles encoded. The built-in editor does not encode tiles using this value despite being decoded correctly in the game, and it will probably crash some older external editors.
Board properties
This information follows directly after the tile RLE data.
Offset | Hex | Data type | Description |
---|---|---|---|
0 | 0x000 | UINT8 | MaxPlayerShots Maximum number of player-owned projectiles allowed at once. |
1 | 0x001 | UINT8 | IsDark When set to 1, the board is covered in darkness which can only be revealed by using a torch. |
2 | 0x002 | UINT8 | ExitNorth Board # that is traveled to when moving off the North side of the board. |
3 | 0x003 | UINT8 | ExitSouth Board # that is traveled to when moving off the South side of the board. |
4 | 0x004 | UINT8 | ExitWest Board # that is traveled to when moving off the West side of the board. |
5 | 0x005 | UINT8 | ExitEast Board # that is traveled to when moving off the East side of the board. |
6 | 0x006 | UINT8 | RestartOnZap When set to 1, the player will teleport to the location where they entered the board whenever they are hurt. |
7 | 0x007 | UINT8 | MessageLength Length of the on-screen message. |
8 | 0x008 | char[58] | Message On-screen message. This is used internally and is not loaded by the game. |
66 | 0x042 | UINT8 | PlayerEnterX X-coordinate of the tile where the player entered the board. |
67 | 0x043 | UINT8 | PlayerEnterY Y-coordinate of the tile where the player entered the board. |
68 | 0x044 | INT16LE | TimeLimit Time limit of the board, in seconds. The player is hurt when time runs out. |
70 | 0x046 | UINT8[16] | (unused) |
86 | 0x056 | INT16LE | StatElementCount Number of Status Elements on the board, not including the player. Increment by 1 to get the real stored number of status elements. |
Status Elements
This follows directly after board properties. It is repeated for each Status Element. The first element stored is always the player-controlled element. This element may contain strange values for Step, Leader, Follower, and Parameter information, especially in older worlds / the commercial+shareware worlds.
Offset | Hex | Data type | Description |
---|---|---|---|
0 | 0x000 | UINT8 | LocationX X-coordinate. Location coordinates are 1-based, unlike any other coordinates in the file. |
1 | 0x001 | UINT8 | LocationY Y-coordinate. |
2 | 0x002 | INT16LE | StepX X-step value. This pair of values represents a vector that typically points in one of the four cardinal directions. Its use differs for each type of element. |
4 | 0x004 | INT16LE | StepY Y-step value. |
6 | 0x006 | INT16LE | Cycle Cycle. This represents the frequency, in ticks, at which the game will process this status element. |
8 | 0x008 | UINT8 | P1 Parameter 1. Its use will differ depending on the type of element. |
9 | 0x009 | UINT8 | P2 Parameter 2. Its use will differ depending on the type of element. |
10 | 0x00A | UINT8 | P3 Parameter 3. Its use will differ depending on the type of element. |
11 | 0x00B | INT16LE | Follower Follower status element. Its value determines if another status element is linked behind this one. Used for linking centipedes. |
13 | 0x00D | INT16LE | Leader Leader status element. Its value determines if another status element is linked in front of this one. Used for linking centipedes. |
15 | 0x00F | UINT8 | UnderID Element of the tile under this status element. |
16 | 0x010 | UINT8 | UnderColor Color of the tile under this status element. |
17 | 0x011 | INT32LE | Pointer Stores the location in memory of the code that this status element is using. Status elements typically point to their own code until they #BIND the code of another - in which case this memory location value is replaced with the new one. ZZT does not use this value when loading worlds, and always sets it to 0 when saving worlds. |
21 | 0x015 | INT16LE | CurrentInstruction The offset in bytes of the code block to execute ZZT-OOP from. Only Objects and Scrolls can execute ZZT-OOP. |
23 | 0x017 | INT16LE | Length There are two uses for this value: If this value is positive, it represents the number of bytes that are in the code block. If this value is negative, the absolute value of this value represents the Status Element number to copy code from. This saves space by removing redundant code duplication. Since code is shared in this way, all modifications to code will affect any other Status Elements using it. |
After this follows 8 bytes of padding (2 unused pointers). If "Length" is positive, the code is stored after the padding.
Element properties
These are all possible internal properties for each element. They are initialized on startup and used both in-game and in the editor.
Property | Description |
---|---|
Id | Id number of the element |
Hex | Hexidecimal representation of the Id number |
Name | Known name of the element, which may not be present internally |
Character | ASCII character for the default draw code, which may be ignored if special draw code is enabled |
Color | Default color. If the color is 0xFE, then new tiles will be created with the primary color as the background and a white foreground. If the color is >= 0xF0, any primary color is allowed, but in the editor you can't choose the color unless the default color is 0xFF |
Destructible | Element can be destroyed by bullets and by being crushed by puzzle pieces |
Pushable | Element can be pushed. The NS/EW sliders are a special case in the code, so they will not be marked with this flag |
Editor Floor | When using the editor, actors such as enemies can be placed on top of elements marked with this flag. Has no effect during gameplay. |
Floor | Elements with this flag can freely be moved upon by actors |
Shown | ZZT only. Elements marked with this flag will always be shown, even on dark boards |
Special Draw | If this flag is set, the default draw code is bypassed with different draw code |
Draw Code | Offset of the routine that performs the drawing, if Special Draw is set |
Cycle | Default cycle. If this is -1, the element is not generated as an actor. Creatures will have cycles above zero |
Act Code | Offset of the routine that performs standard behavior. For example: creature movement, bomb countdown |
Interact Code | Offset of the routine that handles when a player touches the element. For example: item pickups, entering a passage |
Menu# | Number of the editor menu where this element can be found |
Key | Key press which is mapped to this element in the editor |
Internal Name | Name of the element used in the editor. It is also used by OOP- the parser will remove all symbols and spaces and compare that |
Category | When it comes time to display this element in the editor, if present, the category will be drawn in yellow first. |
Edit P1 | Text to show when editing the P1 of an actor that uses this element |
Edit P2 | Text to show when editing the P2 of an actor that uses this element |
Edit P3 | Text to show when editing the P3 of an actor that uses this element |
Edit Board | Text to show when selecting the target board |
Edit Step | Text to show when selecting the target direction |
Edit Code | Text to show when editing an actor's code (scroll or object OOP) |
Points | When an actor using this element is killed by the player, it's worth this much score |
ZZT elements
Id | Hex | Name | Character | Color | Destructible | Pushable | Editor Floor | Floor | Shown | Special Draw | Draw Code | Cycle | Act Code | Interact Code | Menu# | Key | Internal Name | Category | Edit P1 | Edit P2 | Edit P3 | Edit Board | Edit Step | Edit Code | Points |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0x00 | Empty | 0x20 | 0x70 | Yes | Yes | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | Empty | 0 | ||||||||||||
1 | 0x01 | Board Edge | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x3973 | 0 | 0 | |||||||||||||||
2 | 0x02 | Messenger | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0039 | 0x0010 | 0 | 0 | |||||||||||||||
3 | 0x03 | Monitor | 0x20 | 0x07 | 0x0020 | 1 | 0x4481 | 0x0010 | 0 | Monitor | 0 | ||||||||||||||
4 | 0x04 | Player | 0x02 | 0x1F | Yes | Yes | Yes | 0x0020 | 1 | 0x3E2F | 0x0010 | 1 | Z | Player | Items: | 0 | |||||||||
5 | 0x05 | Ammo | 0x84 | 0x03 | Yes | 0x0020 | -1 | 0x0000 | 0x3289 | 1 | A | Ammo | 0 | ||||||||||||
6 | 0x06 | Torch | 0x9D | 0x06 | Yes | 0x0020 | -1 | 0x0000 | 0x37B6 | 1 | T | Torch | 0 | ||||||||||||
7 | 0x07 | Gem | 0x04 | Any (0xFF) | Yes | Yes | 0x0020 | -1 | 0x0000 | 0x3306 | 1 | G | Gem | 0 | |||||||||||
8 | 0x08 | Key | 0x0C | Any (0xFF) | Yes | 0x0020 | -1 | 0x0000 | 0x3169 | 1 | K | Key | 0 | ||||||||||||
9 | 0x09 | Door | 0x0A | Any BG (0xFE) | 0x0020 | -1 | 0x0000 | 0x33DA | 1 | D | Door | 0 | |||||||||||||
10 | 0x0A | Scroll | 0xE8 | 0x0F | Yes | 0x0020 | 1 | 0x2F9F | 0x308B | 1 | S | Scroll | Edit text of scroll | 0 | |||||||||||
11 | 0x0B | Passage | 0xF0 | Any BG (0xFE) | Yes | 0x0020 | 0 | 0x0000 | 0x3372 | 1 | P | Passage | Room thru passage? | 0 | |||||||||||
12 | 0x0C | Duplicator | 0xFA | 0x0F | Yes | 0x2A15 | 2 | 0x2BFF | 0x0010 | 1 | U | Duplicator | Duplication rate?;SF | Source direction? | 0 | ||||||||||
13 | 0x0D | Bomb | 0x0B | Any (0xFF) | Yes | Yes | 0x1872 | 6 | 0x18DA | 0x19F3 | 1 | B | Bomb | 0 | |||||||||||
14 | 0x0E | Energizer | 0x7F | 0x05 | 0x0020 | -1 | 0x0000 | 0x2034 | 1 | E | Energizer | 0 | |||||||||||||
15 | 0x0F | Star | 0x53 | 0x0F | Yes | 0x1D5D | 1 | 0x1DE9 | 0x00F5 | 0 | Star | 0 | |||||||||||||
16 | 0x10 | Clockwise | 0x2F | Any (0xFF) | Yes | 0x171C | 3 | 0x176C | 0x0010 | 1 | 1 | Clockwise | Conveyors: | 0 | |||||||||||
17 | 0x11 | Counter | 0x5C | Any (0xFF) | Yes | 0x17C7 | 2 | 0x1817 | 0x0010 | 1 | 2 | Counter | 0 | ||||||||||||
18 | 0x12 | Bullet | 0xF8 | 0x0F | Yes | 0x0020 | 1 | 0x0F65 | 0x00F5 | 0 | Bullet | 0 | |||||||||||||
19 | 0x13 | Water | 0xB0 | 0xF9 | Yes | 0x0020 | -1 | 0x0000 | 0x3B03 | 3 | W | Water | Terrains: | 0 | |||||||||||
20 | 0x14 | Forest | 0xB0 | 0x20 | 0x0020 | -1 | 0x0000 | 0x38D0 | 3 | F | Forest | 0 | |||||||||||||
21 | 0x15 | Solid | 0xDB | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 3 | S | Solid | Walls: | 0 | ||||||||||||
22 | 0x16 | Normal | 0xB2 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 3 | N | Normal | 0 | |||||||||||||
23 | 0x17 | Breakable | 0xB1 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 3 | B | Breakable | 0 | |||||||||||||
24 | 0x18 | Boulder | 0xFE | Any (0xFF) | Yes | 0x0020 | -1 | 0x0000 | 0x34E3 | 3 | O | Boulder | 0 | ||||||||||||
25 | 0x19 | Slider (NS) | 0x12 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x34E3 | 3 | 1 | Slider (NS) | 0 | |||||||||||||
26 | 0x1A | Slider (EW) | 0x1D | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x34E3 | 3 | 2 | Slider (EW) | 0 | |||||||||||||
27 | 0x1B | Fake | 0xB2 | Any (0xFF) | Yes | Yes | 0x0020 | -1 | 0x0000 | 0x3949 | 3 | A | Fake | 0 | |||||||||||
28 | 0x1C | Invisible | 0xB0 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x3848 | 3 | I | Invisible | 0 | |||||||||||||
29 | 0x1D | Blink wall | 0xCE | Any (0xFF) | Yes | 0x242E | 1 | 0x2445 | 0x0010 | 3 | L | Blink wall | Starting time | Period | Wall direction | 0 | |||||||||
30 | 0x1E | Transporter | 0xC5 | Any (0xFF) | Yes | 0x1CC5 | 2 | 0x1C85 | 0x1C41 | 3 | T | Transporter | Direction? | 0 | |||||||||||
31 | 0x1F | Line | 0xCE | Any (0xFF) | Yes | 0x122A | -1 | 0x0000 | 0x0010 | 0 | Line | 0 | |||||||||||||
32 | 0x20 | Ricochet | 0x2A | 0x0A | 0x0020 | -1 | 0x0000 | 0x0010 | 3 | R | Ricochet | 0 | |||||||||||||
33 | 0x21 | Blink Ray (Horizontal) | 0xCD | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
34 | 0x22 | Bear | 0x99 | 0x06 | Yes | Yes | 0x0020 | 3 | 0x054F | 0x00F5 | 2 | B | Bear | Creatures: | Sensitivity? | 1 | |||||||||
35 | 0x23 | Ruffian | 0x05 | 0x0D | Yes | Yes | 0x0020 | 1 | 0x0351 | 0x00F5 | 2 | R | Ruffian | Intelligence? | Resting time? | 2 | |||||||||
36 | 0x24 | Object | 0x02 | Any (0xFF) | Yes | 0x2B85 | 3 | 0x2AA5 | 0x2BB7 | 2 | O | Object | Character? | Edit Program | 0 | ||||||||||
37 | 0x25 | Slime | 0x2A | Any (0xFF) | 0x0020 | 3 | 0x20AE | 0x2295 | 2 | V | Slime | Movement speed?;FS | 0 | ||||||||||||
38 | 0x26 | Shark | 0x5E | 0x07 | 0x0020 | 3 | 0x2321 | 0x0010 | 2 | Y | Shark | Intelligence? | 0 | ||||||||||||
39 | 0x27 | Spinning gun | 0x18 | Any (0xFF) | Yes | 0x11D0 | 2 | 0x12A7 | 0x0010 | 2 | G | Spinning gun | Intelligence? | Firing rate? | Firing type? | 0 | |||||||||
40 | 0x28 | Pusher | 0x10 | Any (0xFF) | Yes | 0x3517 | 4 | 0x358A | 0x0010 | 2 | P | Pusher | Push direction? | 0 | |||||||||||
41 | 0x29 | Lion | 0xEA | 0x0C | Yes | Yes | 0x0020 | 2 | 0x0113 | 0x00F5 | 2 | L | Lion | Beasts: | Intelligence? | 1 | |||||||||
42 | 0x2A | Tiger | 0xE3 | 0x0B | Yes | Yes | 0x0020 | 2 | 0x022D | 0x00F5 | 2 | T | Tiger | Intelligence? | Firing rate? | Firing type? | 2 | ||||||||
43 | 0x2B | Blink Ray (Vertical) | 0xBA | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
44 | 0x2C | Head | 0xE9 | Any (0xFF) | Yes | 0x0020 | 2 | 0x06BF | 0x00F5 | 2 | H | Head | Centipedes | Intelligence? | Deviance? | 1 | |||||||||
45 | 0x2D | Segment | 0x4F | Any (0xFF) | Yes | 0x0020 | 2 | 0x0EED | 0x00F5 | 2 | S | Segment | 3 | ||||||||||||
46 | 0x2E | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | ||||||||||||||||
47 | 0x2F | Text (Blue) | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
48 | 0x30 | Text (Green) | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
49 | 0x31 | Text (Cyan) | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
50 | 0x32 | Text (Red) | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
51 | 0x33 | Text (Purple) | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
52 | 0x34 | Text (Brown) | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 | |||||||||||||||
53 | 0x35 | Text (Black) | 0x20 | Any (0xFF) | 0x0020 | -1 | 0x0000 | 0x0010 | 0 | 0 |
Credits
The ZZT file format was reverse engineered by SaxxonPike, Kev Vance and David Hammond.
This article is based on content written by SaxxonPike as part of a corresponding article on the ModdingWiki. Saxxon has given permission to license their edits to that article under CC BY-SA 4.0.