Quill Adventure Guides

Quill Data Formats

This page captures the knowledge that I have so far on the Quill binary data formats (i.e. the structure of the data after it has been compiled into a game). Primarily this is covering the ZX Spectrum format at the moment, although all platforms had fairly similar formats (although with minor differences). I've highlighted the differences where I have the information, although the details on non-ZX Spectrum formats will be expanded over time. The BBC Micro format is quite different in a number of respects, so may require a separate document. This does not yet include details on the expansion dictionary (used for compressed games) or a definition of how the graphics are stored, but this may be added in due course.

The main source of this knowledge is the source code of the UnQuill tool by John Elliot and my own experiences writing a reverse engineering tool based on the knowledge of this format. I have started investigating the Atari AdventureWriter data format, which is very similar (although even closer to the C64 data format) and will expand this page as my investigations progress.

Locating the Quill Lookup Table

All Quill formats start from a base address in memory which allows a lookup table to be located. For Spectrum formats, this can be determined by looking for a series of bytes $10,$11,$12,$13,$14,$15 interspersed with colour values. Determining the base address for other formats may not be as straightforward. There is a possibility that the base address is consistent for all adventures on a given hardware platform, however more investigation is needed before I can be certain of this.

ZX Spectrum Colour table

The colour table is 13 bytes long, each entry taking one byte.

Offset Entry Comments
00 $10 Always $10
01 Ink colour Between $00 and $09
02 $11 Always $11
03 Paper colour Between $00 and $09
04 $12 Always $12
05 Flash state $00 or $01
06 $13 Always $13
07 Bright state $00 or $01
08 $14 Always $14
09 Inverse state $00 or $01
10 $15 Always $15
11 Over state $00 or $01
12 Border colour Between $00 and $07

Following this the lookup table starts at the next memory location.

ZX Spectrum colours

The ZX Spectrum colour codes are as per the following table:

Code Colour
$00 Black
$01 Blue
$02 Red
$03 Magenta
$04 Green
$05 Cyan
$06 Yellow
$07 White
$08 Transparent
$09 Contrast

ZX Spectrum Version A Lookup Table

Offset Entry Size
0 Max number of objects carriable 1 byte
1 Number of objects in game 1 byte
2 Number of locations in game 1 byte
3 Number of messages in game 1 byte
4 Address of response table 2 bytes
6 Address of status table 2 bytes
8 Address of object table 2 bytes
10 Address of location table 2 bytes
12 Address of message table 2 bytes
14 Address of connections table 2 bytes
16 Address of vocabulary table 2 bytes
18 Address of object position table 2 bytes

ZX Spectum Version C lookup table

Version C games differ from Version A in that they are not constrained to 32 system messages and there is also a table of words associated with objects (supporting AutoGet, AutoDrop etc actions)

Offset Entry Size
0 Max number of objects carriable 1 byte
1 Number of objects in game 1 byte
2 Number of locations in game 1 byte
3 Number of messages in game 1 byte
4 Number of system messages in game 1 byte
5 Address of response table 2 bytes
7 Address of status table 2 bytes
9 Address of object table 2 bytes
11 Address of location table 2 bytes
13 Address of message table 2 bytes
15 Address of system message table 2 bytes
17 Address of connections table 2 bytes
19 Address of vocabulary table 2 bytes
21 Address of object position table 2 bytes
23 Address of object words table 2 bytes

For other platforms, the lookup table typically follows the ZX Spectrum Version C structure. (Confirmed for C64, Amstrad and Atari; BBC Micro may be different.)

Object, Location and Message Tables

The address of the object table, location table, message table and system message table (for version C games) and the number of entries in each can be found in the lookup table. Each entry is two bytes long.

Offset Entry
0 Address of Object/Loc/Msg 0 text
2 Address of Object/Loc/Msg 1 text
4 Address of Object/Loc/Msg 2 text
etc...

In ZX Spectrum Version A files, there is a fixed number of system messages (32) and the address of System Message 0 is always found at memory address $5C7B

System messages on this version are all stored contiguously in memory so further system messages can be found by scanning through and counting the number of terminator ($1F) bytes seen.

Object, Location and Message Text Entries

The object, location or message text can be found at the memory address specified in the object, location or message table.

Each text entry is a set of bytes, terminated by $1F. Each byte should be converted to a character by subtracting it from 255 (or doing an Exclusive OR operation with $FF, which is equivalent).

(Other platforms may have different termination characters. For example, Atari games have text terminated by an $FF byte; other platforms are to be confirmed).

On the ZX Spectrum, each character is interpreted as follows:

Value Meaning
$06 A tab of 16 spaces. If beyond column 16, this is interpreted as a newline.
$08 Backspace
$0D Newline
$10 Set ink colour. The byte following should be converted to a Spectrum colour by subtracting it from 255.
$11 Set paper colour. The byte following should be converted to a Spectrum colour by subtracting it from 255.
$12 Set flash state. The byte following is $FF or $FE specifying off or on respectively.
$13 Set bright state. The byte following is $FF or $FE specifying off or on respectively.
$14 Set inverse state. The byte following is $FF or $FE specifying off or on respectively.
$15 Set over state. The byte following is $FF or $FE specifying off or on respectively.
$17 Tab. The byte following specifies the number of spaces.
$20-$7F Standard ASCII characters
$80-$FF Special characters including UDGs (user-defined graphics)

Characters $00-$05,$09-$0C,$0E,$0F and $18-$1F are still to be confirmed. Handling of character codes for other platforms to be confirmed.

Connections Table

The address of the Connections table is found in the lookup table. This table contains an entry for every location in the game. Each entry is two bytes long and give the address of where the Connection Details Block for that location can be found.

Offset Entry
0 Address of Location 0 connection details
2 Address of Location 1 connection details
4 Address of Location 2 connection details
etc...

Connection Details Block

The Connection Details Block for each location allows for movement to take place between locations. The connection details block contains an arbitrary number of connection entries, depending on how many exits there are from the given location and is terminated by a $FF byte. Each connection entry is two bytes, as shown below.

Offset Entry
0 Id of movement word
1 Destination location number

Note that the connections table does not necessarily describe every exit from a location. Some exits may be conditional on other factors, e.g. an object being carried or a flag being set. In this case, those exits are represented by Response table entries.

Vocabulary Table

The address of the Vocabulary table is found in the lookup table. The number of entries is not specified, routines using this table scan the table until reaching a $00 termination byte.

Each entry consists of five bytes - four bytes giving the word and 1 byte giving the id of the word.

Each letter in the word is stored as 255 minus the ASCII value (or by doing an Exclusive OR with $FF). Words with the same id value are considered synonyms.

Offset Entry Size
0 Word 1 4 bytes
4 Id of Word 1 1 byte
5 Word 2 4 bytes
9 Id of Word 2 1 byte
etc...

Object Start Position Table

The address of the object start position table is given in the lookup table. There is one byte per object in game, each byte representing the start location of the object.

Offset Entry
0 Location of Object 0
1 Location of Object 1
2 Location of Object 2
etc...

The following locations are treated as special:

Location Meaning
252 ($FC) Not in game
253 ($FD) Object is worn
254 ($FE) Object is carried

Object Word Table - ZX Spectrum Version C only

The address of the object word table is given in lookup table. There is one byte per object in game

Offset Entry
0 Id of word for Object 0
1 Id of word for Object 1
2 Id of word for Object 2
etc...

Response/Status tables

These tables have the same format; the only difference is that the verb/noun in the status table is ignored - all entries are processed every turn regardless of what the user has entered whereas the response table entries are only processed if they match user input.

Each entry has the following form:

Offset Entry Size
0 Id of vocab entry matching verb 1 byte
1 Id of vocab entry matching noun 1 byte
2 Address of CondActs (conditions/actions) to be applied 2 bytes

This table is terminated by a 0 byte. The size of these tables is not specified, so processing needs to be through each entry in turn until the 0 terminator is reached.

CondActs entry

These are the entries referenced in the Response and Status tables.

Each CondAct entry is comprised of:

Entry Size
A list of conditions 2 or 3 bytes per condition - see Condition definition table below
$FF byte terminating the conditions list 1 byte
A list of actions 1, 2 or 3 bytes per action - see Action definition table below
$FF byte terminating the actions list 1 byte

Condition definitions

These appear to be consistent across all Quill file formats

Code Condition Parameters Size Meaning
$00 AT location 2 bytes Is player at location?
$01 NOTAT location 2 bytes Is player not at location?
$02 ATGT location 2 bytes Is player at location with number greater than the given location?
$03 ATLT location 2 bytes Is player at location with number less than the given location?
$04 PRESENT object 2 bytes Is the given object present (in current location, carried or worn)?
$05 ABSENT object 2 bytes Is the given object absent from the current location?
$06 WORN object 2 bytes Is the given object worn?
$07 NOTWORN object 2 bytes Is the given object not currently worn?
$08 CARRIED object 2 bytes Is the given object being carried?
$09 NOTCARR object 2 bytes Is the given object not currently carried?
$0A CHANCE percent 2 bytes This condition is true a given percentage of the time
$0B ZERO flag 2 bytes Is the given flag equal to zero?
$0C NOTZERO flag 2 bytes Is the given flag not equal to zero?
$0D EQ flag, value 3 bytes Is the given flag equal to the given value?
$0E GT flag, value 3 bytes Is the given flag greater than the given value?
$0F LT flag, value 3 bytes Is the given flag less than the given value?

Action definitions

The mapping of bytes to actions varies between Quill file formats.

ZX Spectrum Version A has the following action definitions:

Code Action Parameters Size Meaning
$00 INVEN none 1 byte Display inventory
$01 DESC none 1 byte Display current location description
$02 QUIT none 1 byte Asks user if they want to Quit
$03 END none 1 byte Displays game over message and gives user option of restarting
$04 DONE none 1 byte Process no more actions
$05 OK none 1 byte Display an OK message
$06 ANYKEY none 1 byte Prompt the user to press a key
$07 SAVE none 1 byte Save the game
$08 LOAD none 1 byte Load a saved game
$09 TURNS none 1 byte Display the number of turns the player has taken
$0A SCORE none 1 byte Display the current score
$0B PAUSE length 2 bytes Pause for (length/50) seconds
$0C GOTO location 2 bytes Set the current player location to that given
$0D MESSAGE message number 2 bytes Display the message with the given number
$0E REMOVE object 2 bytes Attempt to remove (un-wear) the given object
$0F GET object 2 bytes Attempt to get the given object
$10 DROP object 2 bytes Attempt to drop the given object
$11 WEAR object 2 bytes Attempt to wear the given object
$12 DESTROY object 2 bytes Remove the given object from the game (set its location to 252)
$13 CREATE object 2 bytes Place the given object at the current location
$14 SWAP two objects 3 bytes Swap the location of the two given objects
$15 SET flag 2 bytes Set the given flag to 255
$16 CLEAR flag 2 bytes Set the given flag to 0
$17 PLUS flag, value 3 bytes Increment the given flag by the given value
$18 MINUS flag, value 3 bytes Decrement the given flag by the given value
$19 LET flag, value 3 bytes Set the given flag to the given value
$1A BEEP duration, pitch 3 bytes Make a sound at the given pitch for the given duration

ZX Spectrum Version C has additional actions: CLS, DROPALL, AUTOG, AUTOD, AUTOW, AUTOR, PAPER, INK, BORDER and PLACE

ZX Spectrum Version C has the following action definitions:

Code Action Parameters Size Meaning
$00 INVEN none 1 byte Display inventory
$01 DESC none 1 byte Display current location description
$02 QUIT none 1 byte Asks user if they want to Quit
$03 END none 1 byte Displays game over message and gives user option of restarting
$04 DONE none 1 byte Process no more actions
$05 OK none 1 byte Display an OK message
$06 ANYKEY none 1 byte Prompt the user to press a key
$07 SAVE none 1 byte Save the game
$08 LOAD none 1 byte Load a saved game
$09 TURNS none 1 byte Display the number of turns the player has taken
$0A SCORE none 1 byte Display the current score
$0B CLS none 1 byte Clear the screen
$0C DROPALL none 1 byte Moves all objects carried or worn into the current location
$0D AUTOG none 1 byte Attempts to get the object referred to by a given noun
$0E AUTOD none 1 byte Attempts to drop the object referred to by a given noun
$0F AUTOW none 1 byte Attempts to wear the object referred to by a given noun
$10 AUTOR none 1 byte Attempts to remove the object referred to by a given noun
$11 PAUSE length 2 bytes Pause for (length/50) seconds
$12 PAPER colour 2 bytes Set the paper (background) colour to that given
$13 INK colour 2 bytes Set the ink (foreground) colour to that given
$14 BORDER colour 2 bytes Set the ink (foreground) colour to that given
$15 GOTO location 2 bytes Set the current player location to that given
$16 MESSAGE message number 2 bytes Display the message with the given number
$17 REMOVE object 2 bytes Attempt to remove (un-wear) the given object
$18 GET object 2 bytes Attempt to get the given object
$19 DROP object 2 bytes Attempt to drop the given object
$1A WEAR object 2 bytes Attempt to wear the given object
$1B DESTROY object 2 bytes Remove the given object from the game (set its location to 252)
$1C CREATE object 2 bytes Place the given object at the current location
$1D SWAP two objects 3 bytes Swap the location of the two given objects
$1E PLACE object, location 3 bytes Set the location of the given object to the location given
$1F SET flag 2 bytes Set the given flag to 255
$20 CLEAR flag 2 bytes Set the given flag to 0
$21 PLUS flag, value 3 bytes Increment the given flag by the given value
$22 MINUS flag, value 3 bytes Decrement the given flag by the given value
$23 LET flag, value 3 bytes Set the given flag to the given value
$24 BEEP duration, pitch 3 bytes Make a sound at the given pitch for the given duration

Other platforms have their own subsets of action definitions, the majority being the same as for the ZX Spectrum, but with some platform-specific differences. These are to be confirmed.