TZX tape format

Format name: TZX tape format; format creator: Tomaz Kac, Martijn van der Heide and Ramsoft.

Link to the specification homepage

The TZX file format is a generic file format that can store either standard tape loading blocks as well as custom- and turbo loading blocks. The format has been enhanced several times. The last revision 1.20 declared some datablocks as 'deprecated' and introduced some new block types. The format has been structured so that it would be easy to implement new block types. TZX files are supported by nearly all newer ZX-Spectrum emulators.

TZX file format:

Offset:

Field type: Length: Description: Additional information:

0

10

header identification & version
Data blocks:
10 #1 ??? first data block list of data blocks (may be empty)
??? #2 ??? second data block
??? #N ??? last (Nth) data block

TZX files use the following sub-formats:

(10 bytes):

Offset:

Field type: Length: Description: Additional information:

0

7

signature = value "ZXTape!"
7

1

end of file marker = value 26 (eof)
8

1

major version number = value 1
9

1

minor version number = e.g. 13 or 20 (for version 1.13 or 1.20)

 

:

Offset:

Field type: Length: Description: Additional information:

0

1

[ID] selector for the type of following data block
1 ???

if [ID]= 10h

Standard speed data block
1 ???

if [ID]=11h

Turbo speed data block
1 4

if [ID]=12h

Pure tone
1 ???

if [ID]=13h

Pulse sequence
1 ???

if [ID]=14h

Pure data block
1 ???

if [ID]=15h

Direct recording block
1 ???

if [ID]=16h

C64 ROM block (deprecated)
1 ???

if [ID]=17h

C64 turbo block (deprecated)
1 ???

if [ID]=18h

CSW recording block v1.20
1 ???

if [ID]=19h

Generalized data block v1.20
1 2

if [ID]=20h

Pause or Stop the tape
1 ???

if [ID]=21h

Group start
1 0

if [ID]=22h

Group end
1 2

if [ID]=23h

Jump to block
1 2

if [ID]=24h

Loop start
1 0

if [ID]=25h

Loop end
1 ???

if [ID]=26h

Call sequence
1 0

if [ID]=27h

Return from sequence
1 ???

if [ID]=28h

Select block
1 4

if [ID]=2Ah

Stop tape in 48k mode
1 5

if [ID]=2Bh

Set signal level v1.20
1 ???

if [ID]=30h

Text description
1 ???

if [ID]=31h

Message
1 ???

if [ID]=32h

Archive info
1 ???

if [ID]=33h

Hardware type
1 8

if [ID]=34h

Emulation info (deprecated)
1 ???

if [ID]=35h

Custom info
1 ???

if [ID]=40h

SCREEN$ block (deprecated)
1 9

if [ID]=5Ah

Skip (glue) block

Here follows the list of all possible block types which are used by the above
sub-structure:

Standard speed data block (4+[DataLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 2 pause in ms

pause after this block 
(default value = 1000 ms)

2 2 [DataLen]

length of the following data block

4 [DataLen] data block

refer to the TAP file format description

The standard speed data block has to be played by the ZX-Spectrum ROM routines using standardized timing values (refer to default values of ID 11h). Depending on the flag byte, the pilot tone performs 8063 pulses (flag < 128) or 3223 pulses (flag >= 128).


  Turbo speed data block (18+[DataLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 2 pilot tone pulse length

(default value = 2168)

2 2 1st sync pulse length

(default value = 667)

4 2 2nd sync pulse length

(default value = 735)

6 2 0-bit pulse length (default value = 855)
8 2 1-bit pulse length (default value = 1710)
10 2 pilot tone pulse count

(default values = 8063 for headers,
3223 for data blocks)

12 1 used bits of 
the last byte

1..8
Used bits, where the most significant bit is the leftmost bit; e.g. 6 means ++++++00 (+ means a used bit, 0 means unused; default value = 8)

13 2 pause in ms

pause after this block 
(default value = 1000)

15 3 [DataLen]

length of the following data block

18 [DataLen] data block

refer to the TAP file format description

The turbo speed data block allows different timings for special loaders. If the default values are used, the result is a standard speed data block. Some loaders change some of the values to build protections or speed-ups.


  Pure tone (4 bytes):
Offset: Field type: Length: Description: Additional information:
0 2 T-State length

length of one pulse in 1 / 3,500,000 s.

2 2 pulse count

number of pulses for the tone

This block will produce one tone - pretty much like the Spectrum's pilot tone


 Pulse sequence (2*[pulse count]+1 bytes):
Offset: Field type: Length: Description: Additional information:
0 1 [pulse count]

Number of pulses (1..255)

1 2 1st pulse length

List of pulse lengths. Must have at least one entry.

3 2 2nd pulse length
[pulse 
count]
*2-1
2 last pulse length

This block will produce a sequence of tones with individual pulse lengths and is also used by some protections.


Pure data block (10+[DataLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 2 0-bit pulse length (default value = 855)
2 2 1-bit pulse length (default value = 1710)
4 1 used bits of 
the last byte

1..8
Used bits, where the most significant bit is the leftmost bit; e.g. 6 means ++++++00
(+ means a used bit, 0 means unused;
default value = 8).

5 2 pause in ms

pause after this block 
(default value = 1000)

7 3 [DataLen]

length of the following data block

10 [DataLen] data block

refer to the TAP file format description

Identical to the turbo speed data block, but without pilot or sync pulses.


Direct recording block (8+[DataLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 2 T-States per sample Number of T-States per sample. One T-State is 1 / 3,500,000 s.
158 means 22050 Hz
79 means 44100 Hz
other values are not recommended!
2 2 pause in ms Pause after this block
4 1 used bits of 
the last byte
1..8
Used bits (samples), of the last data byte. E.g.  6 means that only the first 6 samples of the last byte are played.
5 3 [DataLen] length of the following data block
8 [DataLen] bit stream The bits that represent the samples to be played. 0 means low, 1 means high signal of the EAR port. The most significant bit is played first.

Stores sample recordings in a binary coded format.


CSW Recording (14+[DataLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 4 block length block length of the following data of this block
4 2 pause in ms pause after this block
6 3 sampling rate the sampling rate, the data bytes
are based; e.g. 44100
9 1 compression type 1: run length encoding
2: zero-based run length encoding
10 4 number of pulses only for validation - pulses after uncompression
14 [DataLen] CSW data CSW data

Contains a sequence of a CSW format (version 2).


Generalized datablock:
Offset: Field type: Length: Description: Additional information:
0 4 block length block length of the following data of this block
4 2 pause pause after this block, in milliseconds
6 4 [TOTP] total number of symbols in pilot/sync part; may be =0
10 1 [NPP] max. number of pulses per pilot/sync symbol
11 1 [ASP] number of pilot/sync symbols in alphabet table;
0 meaning 256!
12 4 [TOTD] Total number of symbols in data stream; may be =0
16 1 [NPD] max. number of pulses per data symbol
17 1 [ASD] number of data symbols in alphabet table;
0 meaning 256!
Symbol definitions for pilot/sync, only present if [TOTP]>0:
18 #1 2*[NPP]+1 first symbol symbol alphabet definitions for pilot/sync;
total size [SYMPLEN] =
(2*[NPP]+1) *[ASP]

if [TOTP]=0, [SYMPLEN] =0
#2 2*[NPP]+1 2nd symbol
#[ASP] 2*[NPP]+1 last symbol
Pilot/sync data stream, only present if [TOTP]>0:
18+
[SYMPLEN]
#1 3 first symbol pilot/sync data stream
#2 3 2nd symbol

#[TOTP] 3 last symbol
Symbol definitions for data stream, only present if [TOTD]>0:
18+
[SYMPLEN]
+3*[TOTP]
#1 2*[NPD]+1 first symbol symbol alphabet definitions for data stream;
total size [SYMDLEN] =
(2*[NPD]+1) *[ASD]

if [TOTD]=0, [SYMDLEN] =0

#2 2*[NPD]+1 2nd symbol
#[ASD] 2*[NPD]+1 last symbol
Data bit stream, only present if [TOTD]>0:
18+
[SYMPLEN]
+3*[TOTP]
+
[SYMDLEN]
#1 1 first data byte data stream, bit-coded;
[BITS] = ceil(log2([ASD]));
[DSIZE] = ceil([BITS]*[TOTD]/8)
bit groups are coded in 
most significant bits first
#2 1 2nd data byte

#[DSIZE] 1 last data byte

The generalized datablock can either be a pilot/sync sequence, or a data sequence, or both together. It can store a wide range of different block types, as it is very flexible with its symbol alphabets.

The generalized data block uses the following sub-formats:

symbol definition (2*[MAXP]+1 bytes):
Offset: Field type: Length: Description: Additional information:
0 1 symbol flags only bits 0 and 1 are used:
00 opposite to current level
01 same as current level
10 force low level
11 force high level
1 #1 2 1st pulse len Array of pulse lengths;
[MAXP] = [NPP] or [NPD] 
(depending on the usage)
3 #2 2 2nd pulse len
??? #[MAXP] 2 last pulse len

The symbol flags in the SYMDEF structure describe the initial pulse level before the pulses of the symbol are played. All symbols in the symbol alphabet tables always have the same number of pulses; only the maximum count of pulses per symbol is defined as [MAXP]. Unused pulses are filled with 0-words. These 0-pulses have to be ignored while playing the waves.

symbol repeater (3 bytes):
Offset: Field type: Length: Description: Additional information:
0 1 symbol index symbol to be represented
1 2 repeater number of repetitions

The PRLE represents 1..65535 of one of the defined symbols


  pause or stop the tape (2 bytes):
Offset: Field type: Length: Description: Additional information:
0 2 milliseconds

length of the pause (silence) or
=0 for "stop the tape"


group start (1+[StringLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 1 [StringLen] length of group name
1 [StringLen] group name the group name itself; should be max. 30 characters long

The group start and group end include a group of sub-blocks that belong together, for instance Speedlock or Bleepload blocks. They have only documentary function.


jump to block (2 bytes):
Offset: Field type: Length: Description: Additional information:
0 2 jump distance relative jump value;
0 = endless loop;
1 = jump to next block (=nop)
2 = skip next block
-1 = jump to previous block

loop start (2 bytes):
Offset: Field type: Length: Description: Additional information:
0 2 repeat count must be greater than 1

A loop start and loop end block include a group of blocks that have to be repeated. Nested loops are not allowed!


call sequence (2*[CallCount]+2 bytes):
Offset: Field type: Length: Description: Additional information:
0 2 [CallCount] number of calls
2 #1 2 first call relative block position (analog to jump block); the destination routine must be terminated by a 'return from sequence'
4 #2 2 2nd call
??? #[CallCount] 2 last call

Defines a list of calls to subroutines. Nested subroutines are not allowed!


select sequence ([BlockLen]+2 bytes):
Offset: Field type: Length: Description: Additional information:
0 2 [BlockLen] length of the following data block
2 1 [Count] number of selections
3 #1 ??? first selection List of selections
??? #2 ??? 2nd selection
??? #[Count] ??? last selection

A SELECT sequence is something like a list of contents; it's used for tapes that have several sections. The block numbers are the starting positions for each section. 
The SELECT sequence uses the following sub-block:

select block ([TextLen]+3 bytes):
Offset: Field type: Length: Description: Additional information:
0 2 relative position relative block position (refer to jump block)
2 1 [TextLen] length of description
3 [TextLen] description description string (should not have more than
30 characters and no line-feeds)

stop tape at 48k (4 bytes):
Offset: Field type: Length: Description: Additional information:
0 4 block length always =0

Lets the emulator stop when it's in 48k mode.


set signal (5 bytes):
Offset: Field type: Length: Description: Additional information:
0 4 block length always =1
4 1 signal level 0 = low
1 = high

Useful for loaders that take care about the signal level.


text description (1+[TextLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 1 [TextLen] length of text description
1 [TextLen] any text ASCII text; should have max. 30 characters and one line

Should be used as a text marker in the tape (for browsing through the tape blocks etc.)


message (2+[MsgLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 1 duration time duration (in seconds), the message should be displayed; 0 means waiting for a key
1 1 [MsgLen] length of message
2 [MsgLen] any text ASCII text; should have max. 30 characters per line and max. 8 lines. Lline should be separated with CHR$(13) character.

Displays a message for a given time. 


archive info (2+[BlockLen] bytes):

Offset: Field type: Length: Description: Additional information:
0 2 [BlockLen] length of the following data
2 1 [Count] number of archive texts
3 #1 ??? 1st item list of archive info items
??? #2 ??? 2nd item
??? #[Count] ??? last item

Use the archive info at the beginning of the tape to identify the game/program. E.g. you can define the game name, publisher, year etc. Some fields can appear more than 1 times (e.g. comments). You don't need to add all items; you may skip Language, if the tape language is English, for example.

The archive info stores the information of the tape, like game name, publisher, etc.

(2+[TextLen] bytes):
Offset: Field type: Length: Description: Additional information:
0 1 Text type 00h - Full title
01h - Software house/publisher
02h - Author(s)
03h - Year
04h - Language
05h - Game/program type
06h - Price
07h - Protection scheme/loader
08h - Origin
FFh - Comment(s)
1 1 [TextLen] length of archive text
2 [TextLen] any text ASCII text that describes the archive item

hardware info (3*[Count]+1 bytes):

Offset: Field type: Length: Description: Additional information:
0 1 [Count] number of hardware items
1 #1 3 1st item list of hardware info items
??? #2 3 2nd item
??? #[Count] 3 last item

The hardware info uses the following sub-format:

(3 bytes):

Offset: Field type: Length: Description: Additional information:
0 1 hardware type hardware type (refer to hardware table)
1 1 hardware ID hardware ID (refer to hardware table)
1 1 run ability 0: The hardware can be fully used 
on the emulated machine
1: The hardware is used on the emulated 
machine
2: The hardware works, but is not 
used on the emulated machine
3: The hardware is not working with 
the emulated machine

custom info ([DataLen]+20 bytes):

Offset: Field type: Length: Description: Additional information:
0 16 identification ASCII identification string
16 4 [DataLen] length of custom info
20 [DataLen] custom info Any data

Custom info blocks store any data; please notice that there are some deprecated standard custom info blocks!


skip block (9 bytes):

Offset: Field type: Length: Description: Additional information:

0

6

signature = value "XTape!"
7

1

end of file marker = value 26 (eof)
8

1

major version number = value 1
9

1

minor version number = e.g. 13 or 20 (for version 1.13 or 1.20)

This block appears if two or more TZX files are concatenated together. 5a is the "Z" character. So, the Z is missing in the signature above. This block has to be skipped.


Deprecated blocks:

There are some deprecated blocks that were used until TZX version 1.13. These should not be used in TZX files with version 1.20 and later. 

C64 block ([BlockLen] bytes):

Offset: Field type: Length: Description: Additional information:

0

4

[BlockLen] length of the whole data (incl.
these 4 bytes)
4 2 pilot tone length default value =616
6 2 pilot tone wave count  
8 2 sync 1st pulse length default value = 1176
10 2 sync 2nd pulse length default value = 896
12 2 0-bit 1st pulse length default value = 616
14 2 0-bit 2nd pulse length default value = 896
16 2 1-bit 1st pulse length default value = 896
18 2 1-bit 2nd pulse length default value = 616
20 1 xor checksum bit
for each data byte
0: start xor checksum with 0
1: start xor checksum with 1
255: no checksum bit
21 2 finish byte 1st pulse length default value = 1176
23 2 finish byte 2nd pulse length default value = 896
25 2 finish data 1st pulse length default value = 1176
27 2 finish data 2nd pulse length default value = 616
29 2 trailing tone pulse length default value = 616
31 2 trailing tone wave count  
33 1 last used bits used bits of the last byte; 1..8;
e.g. if the value is 6, then
the upper 6 bits xxxxxx00 are
used. Other bits = 0.
34 1 data endianess bit 0=0: less significant bit first
bit 0=1: most significant bit first
35 2 pause after this block in milliseconds
37 3 [DataLen] length of following data
40 [DataLen] data block refer to the TAP file format description

This block is used for storing a ROM standard C64 tape loading block.


C64 turbo block ([BlockLen] bytes):

Offset: Field type: Length: Description: Additional information:

0

4

[BlockLen] length of the whole data (incl.
these 4 bytes)
4 2 0-bit pulse  
6 2 1-bit pulse  
8 1 additional bits bit 0-1: number of bits
bit 2: play before (0) or 
after (1) the byte
bit 3: value of add. bits
9 2 lead-in bytes number of lead-in bytes
11 1 lead-in byte value of lead-in byte
12 1 last used bits used bits of the last byte; 1..8;
e.g. if the value is 6, then
the upper 6 bits xxxxxx00 are
used. Other bits = 0.
13 1 data endianess bit 0=0: less significant bit first
bit 0=1: most significant bit first
14 2 trailing bytes number of trailing bytes
16 1 trailing byte value of trailing byte
17 2 pause after this block in milliseconds
19 3 [DataLen] length of following data
22 [DataLen] data block refer to the TAP file format description

Emulation info (8 bytes):

Offset: Field type: Length: Description: Additional information:

0

2

flags bit 0: R-register emulation (default = 1)
bit 1: ldir emulation (default = 1)
bit 2: hi-res colour emulation (default = 1)
bit 3-4: 00: normal video-synchronisation 
(default)
01: high video-synchronisation
10: normal video-synchronisation
11: low video-synchronisation
bit 5: fast ROM loading (default = 1)
bit 6: border emulation (default = 1)
bit 7: screen refresh mode (default = 1)
bit 8: start playing the tape immediately (1)
(default = 0)
bit 9: auto LOAD"" (default = 1)
2 1 screen refresh
delay
interrupts between screen refreshes 1..255
(default = 1); only used when screen refresh 
mode is enabled.
3 2 int. freq. interrupt frequency 0..999 in Hz
5 3 reserved should be zero

SCREEN$ block ([SnapLen]+4 bytes):

Offset: Field type: Length: Description: Additional information:

0

1

snapshot type 0: Z80 format
1: SNA format
1 3 [SnapLen] snapshot length

if snapshot type is Z80 format:

4 [SnapLen] snapshot itself  

if snapshot type is SNA format:

4 [SnapLen] snapshot itself  

A snapshot block should always be the first active block of a TZX file.