Tape File Formats:
Files stored in one of the following formats can be used to reproduce exact (or near-perfect) duplicates of the original source tape. For this reason,
they are generally preferred to 'snapshot' files, although they are slightly less well supported. Additional information regarding the intended
hardware type (for example) can often be encoded with files of this type, and custom loading systems are both reliably and accurately preserved.
- TAP Format
The .tap files contain blocks of tape-saved data. All blocks start with two bytes specifying how many bytes will follow (not counting the two length bytes).
Then raw tape data follows, including the flag and checksum bytes. The checksum is the bitwise XOR of all bytes including the flag byte. For example, when
you execute the line SAVE "ROM" CODE 0,2 this will result:
-
|------ Spectrum-generated data -------| |------|
13 00 00 03 52 4f 4d 7x20 02 00 00 00 00 80 f1 04 00 ff f3 af a3
^^^^^...... first block is 19 bytes (17 bytes+flag+checksum)
^^... flag byte (A reg, 0x00 for headers, 0xff for data blocks)
^^ first byte of header, indicating a code block
file name ..^^^^^^^^^^^^^
header info ..............^^^^^^^^^^^^^^^^^
checksum of header .........................^^
length of second block ........................^^^^^
flag byte ...........................................^^
first two bytes of rom .................................^^^^^
checksum .....................................................^^
Note that it is possible to join .tap files by simply stringing them together, for example COPY /B FILE1.TAP + FILE2.TAP ALL.TAP
Here is the structure of a tape header, which always consists of 17 bytes:
The type is 0,1,2 or 3 for a PROGRAM, Number array, Character array or CODE file. A SCREEN$ file is regarded as a
CODE file with start address 16384 and length 6912 decimal. If the file is a PROGRAM file, parameter 1 holds the autostart
line number (or a number >=32768 if no LINE parameter was given) and parameter 2 holds the start of the variable
area relative to the start of the program. If it's a CODE file, parameter 1 holds the start of the code block when
saved, and parameter 2 holds 32768. For data files finally, the byte at position 14 decimal holds the variable name.
- TZX Format v1.13
TZX is the 'preferred' format for emulation since it can be used to replicate the original tape
content exactly. Tapes can be reproduced using a variety of utilities.
The .tzx format was originally developed by Tomaz Kac (now maintained by Martijn van der Heide) to allow the storage of games with
non-standard loaders in a format much smaller than .voc files. Although originally designed for use with Spectrum compatible computers
only, it can also be used to reproduce tapes for the Amstrad CPC, Commodore 64, Enterprise, Jupiter ACE and SAM Coupe. It is also
possible, in theory only since no utilities exist that allow it, save cassette images as .tzx files for use with a ZX81. An extremely
detailed specification for the .tzx format is available in .txt and HTML formats is available
here.
See the TZX Vault entry for a large number of files in .tzx format
(also accessible via FTP)
Snapshot File Formats:
Snapshot files represent the contents of the system memory at a particular moment in time. As a result of this, they can be loaded
into an emulator almost instantaneously, but cannot normally be used to recreate the original tape. Please note that the
.z80 format is now located on a different page.
- SLT Format
The level loader trap has one annoying disadvantage; lots of extra files lying around for each game.
The super level loader was developed by Damien Burke to replace this multi-file format with a single snapshot file
containing all the level data files. It has been designed in co-operation with James McKay (x128), Gerton Lunter (Z80),
Rui Ribeiro (WSpecEm) and Darren Salt (helping with Z80Em), and is quite widely supported. The format was designed
with future expansion in mind;
Size Description
------------------------------------------------------------------------
varies bytes Z80 snapshot (version 2+)
3 bytes Three null bytes (compatibility; see below)
3 bytes "SLT" (signature)
---- the following blocks make up a table to access the data files -----
2 word data type (0 = end of table, 1 = level data)
2 word data identifier (for type 1 this is level number)
4 long data length
2 word data type (0 = end of table, 1 = level data)
2 word data identifier (for type 1 this is level number)
4 long data length
... and so on
---- the following blocks are the data files themselves ----------------
varies bytes data
varies bytes data
... and so on
------------------------------------------------------------------------
The three null bytes after the end of the snapshot are for compatibility reasons; older versions of Z80 would crash if the
extra data was just appended to the snapshot. With these three null bytes, they just complain about an error in the snapshot
file instead (this presumes you have renamed the .slt file to .z80 and attempted to load it into an older emulator)
After the "SLT" signature, there is a table of data types and sizes. Currently, only data types 0 (end of table) and 1 (level data) are
supported; if other values are encountered, that data block should be ignored by the emulator.
To read a level data file using .slt, the emulator should find the correct entry in the table (type = 1, identifier matching the
A register when the ED/FB instruction was encountered), get its size from the table and calculate its position from the total
of sizes of data blocks previous to the required one, added to the position of the end of the table. For example, to load level 2 from
a .slt snapshot with this table:
Position Size Value Description
------------------------------------------------------------------------
40000 2 1 data type = level data
40002 2 1 data identifier = level 1
40004 4 256 data length = 256 bytes
40008 2 1 data type = level data
40010 2 2 data identifier = level 2
40012 4 128 data length = 128 bytes
40016 2 0 data type = end of table
40018 2 * data identifier = unused (may as well be zero)
40020 4 * data length = unused (may as well be zero)
40024 256 * data block for level 1
40280 128 * data block for level 2
------------------------------------------------------------------------
(* = could be anything)
So, the size of level 2 is 128 bytes, and its located at the end of the table (40024) + the length of all previous blocks
(just 256 here) = 40280.
Level data is packed in the same way as z80 snapshot memory banks are.
The trainspotter award seekers of you may wonder why a whole word is used for the data identifier;
after all, this is the level number and is held in the A register, so could be just a byte. For level data, correct.
But future expansion is better served by a word. For the same reasons, the data length is held as a long word
instead of just a word; level data will never exceed 64Kb (indeed, could not even be as much as 48Kb), but future
data types may do so. One example; embedding a scan of a game's inlay card in the file is possible, and that file
could easily exceed 64Kb.
- SNA Format
This format is one of the most well-supported of all snapshot formats, but has a drawback:
As the program counter is pushed onto the stack so that a RETN instruction can restart the program, 2 bytes of memory
are overwritten. This will usually not matter; the game (or whatever) will have stack space that can be used for this.
However, if this space is all in use when the snap is made, memory below the stack space will be corrupted. According
to Rui Ribeiro, the effects of this can sometimes be avoided by replacing the corrupted bytes with zeros; e.g. take the PC
from the, stack pointer, replace that word with 0000 and then increment SP. This worked with snapshots of Batman,
Bounder and others which had been saved at critical points. Theoretically, this problem could cause a complete crash on a
real Spectrum if the stack pointer happened to be at address 16384; the push would try and write to the ROM.
When the registers have been loaded, a RETN command is required to start the program. IFF2 is short for interrupt flip-flop 2,
and for all practical purposes is the interrupt-enabled flag. Set means enabled.
Offset Size Description
------------------------------------------------------------------------
0 1 byte I
1 8 word HL',DE',BC',AF'
9 10 word HL,DE,BC,IY,IX
19 1 byte Interrupt (bit 2 contains IFF2, 1=EI/0=DI)
20 1 byte R
21 4 words AF,SP
25 1 byte IntMode (0=IM0/1=IM1/2=IM2)
26 1 byte BorderColor (0..7, not used by Spectrum 1.7)
27 49152 bytes RAM dump 16384..65535
------------------------------------------------------------------------
Total: 49179 bytes
The 128K version of the .sna format is the same as above, with extensions to include the extra memory banks of the
128K/+2 machines, and fixes the problem with the PC being pushed onto the stack - now it is located in an extra variable
in the file (and is not pushed onto the stack at all). The first 49179 bytes of the snapshot are otherwise exactly as described
above, so the full description is:
Offset Size Description
------------------------------------------------------------------------
0 27 bytes SNA header (see above)
27 16Kb bytes RAM bank 5 \
16411 16Kb bytes RAM bank 2 } - as standard 48Kb SNA file
32795 16Kb bytes RAM bank n / (currently paged bank)
49179 2 word PC
49181 1 byte port 0x7ffd setting
49182 1 byte TR-DOS rom paged (1) or not (0)
49183 16Kb bytes remaining RAM banks in ascending order
...
------------------------------------------------------------------------
Total: 131103 or 147487 bytes
The third RAM bank saved is always the one currently paged, even if this is page 5 or 2 - in this case, the bank is actually
included twice. The remaining RAM banks are saved in ascending order - e.g. if RAM bank 4 is paged in, the snapshot is made up
of banks 5, 2 and 4 to start with, and banks 0, 1, 3, 6 and 7 afterwards. If RAM bank 5 is paged in, the snapshot is made up of
banks 5, 2 and 5 again, followed by banks 0, 1, 3, 4, 6 and 7.
- Z80
The .z80 Format is now documented on a different page.
Disk File Formats:
There are relatively few disk formats in common use by modern emulators, with .dsk and .trd being the most popular. Virtually all
modern emulators support one (often both) or more of the following:
- DSK / Extended DSK Format
The extended DSK image is a file designed to describe copy-protected floppy disk software. The format was defined by Marco Vieth, Ulrich
Doewich and Kevin Thacker with the full specification available from the
Unofficial Amstrad WWW Resource.
- FDI Format
Supported by various emulators, including
SPIN. Note that this entry was translated from UKV Spectrum Debugger's documentation by
Mac Buster.
Offset Field size Description
0x00 0x03 Text "FDI"
0x03 0x01 Write protection (0: write enabled; 1: disabled)
0x04 0x02 Number of cylinders
0x06 0x02 Number of heads
0x08 0x02 Offset of disk description
0x0A 0x02 Data offset
0x0C 0x02 Length of additional information in header. (UKV
uses 00)
0x0E (x) Additional information; length is specified in the
previous field.
0x0E+(x) Track headers area. This section contains all
information on the disk format. This area must
contain at least "Number of cylinders"*"Number of
heads" headers. The headers are stored in the
sequence Cyl 0 Head 0; Cyl 0 Head 1; Cyl 1 Head 0
etc.
(Description offset) A description of the disk terminated with 0x00 can
be placed here; the MAKEFDI utility (supplied by
UKV) allows for up to 64 characters, including
the terminating null.
(Data offset) The actual disk data. The size and sequence depends
on the disk format.
Track Header Format:
Offset Field size Description
0x00 0x04 Track offset: the offset of the track data, relative
to the data offset defined above.
0x04 0x02 (Always 0x0000)
0x06 0x01 Number of sectors on this track.
0x07 (Sectors*7) Sector infomation:
Bytes 00-03 give the cylinder number, head number,
sector size (00: 128 bytes; 01: 256; 02: 512; 03:
1024; 04: 4096) and sector number respectively.
Byte 04 contains the flags:
Bits 0-5 are CRC marks: if the CRC was correct for
a sector size 128,256,512,1024 or 4096, then the
respective bit will be set. If all bits are 0 then
there was a CRC error when this sector was
written.
Bit 6 is always 0.
Bit 7 is 0 for normal data, or 1 for deleted data.
Bytes 05-06 give the sector offset, relative to
(data offset+track offset)
7*(Sectors+1) Track header length
Note that UKV 1.2 does not use the flag byte.
- TRD Format
See the TR-DOS page on the World of
Spectrum site for several TR-DOS conversion utilities.
- IMG Format
This is just a simple dump of a Disciple/+D disk, in the order:
- Side: 0 Track: 0
- ...
- Side: 0 Track: 79
- Side: 1 Track: 0
- ...
- Side: 1 Track: 79
- MGT Format
Again, this is just a simple dump of a Disciple/+D disk, in the order:
- Side: 0 Track: 0
- Side: 1 Track: 0
- Side: 0 Track: 1
- ...
- Side: 0 Track: 79
- Side: 1 Track: 79
Emulator-specific Formats:
The following formats are (currently) tied to individual emulators, and provide specific features or make special allowances for the
emulator in question. Few of these formats are well documented by their authors, so providing accurate specifications
can be difficult; Warajevo DCK and Spectaculator SZX are noteworthy exceptions.
SZX Format v1.1
The SZX Format is used by Spectaculator to save the entire state of the machine at a particular time, including the hardware
configuration, including the state of the virtual cassette recorder. This format was developed by Jonathan Needle, and is
fully documented on the Spectaculator web site.
DCK Format
Used by Warajevo, and now supported by others, .dck files keep information about memory content of various Timex memory
expansions, and information which chunks of extra memory are RAM chunks and which chunks are ROM chunks. The full specification can be found as part of the Warajevo home page.
Other/Miscellaneous Formats:
The formats used to store Microdrive cartridge images, loading screens/titles and to capture emulator input for later playback are
documented below, with links to more detailed specifications where available. Of the formats listed, only .scr and .pok are very widely
supported across multiple platforms, although .rzx is becoming increasingly popular. The .mdr format is supported by
Spectaculator v4.0 and above,
RealSpec and
XZX-Pro, plus others.
AIR Format
An input-recording format used by the RealSpec emulator. Developed by
Aley Keprt, the specification for the .air format is closed,
so no technical details are available. Predecessor to .rzx.
HDF Format
An image of an IDE hard disk, used by RealSpec and Fuse. The full specification is available from the RamSoft website.
MDR Format
ZX Microdrive cartridge file format. The following information is adapted from documentation supplied with Carlo Delhez' Spectrum emulator
(Spectator - this emulator is no longer maintained by the author) for the Sinclair QL. It can also be found in the 'Spectrum Microdrive Book'
by Dr. Ian Logan (co-author of the 'Complete Spectrum ROM Disassembly', and author of the Microdrive software.)
A cartridge file contains 254 'sectors' of 543 bytes each, and a final byte flag which is non-zero is the cartridge is write protected,
so the total length is 137923 bytes. On the cartridge tape, after a GAP of some time the
ZX Interface I writes 10 zeros and 2 FF bytes (the preamble), and then a fifteen byte
header-block-with-checksum. After another GAP, it writes a preamble again, with a 15-byte record-descriptor-with-checksum
(which has a structure very much like the header block), immediately followed by the data block of 512 bytes, and a final checksum
of those 512 bytes. The preamble is used by the ZX Interface I hardware to
synchronise, and is not explicitly used by the software. The preamble is not saved to the microdrive file:
Offset Length Name Contents
------------------------------
0 1 HDFLAG Value 1, to indicate header block *See note.
1 1 HDNUMB sector number (values 254 down to 1)
2 2 not used (and of undetermined value)
4 10 HDNAME microdrive cartridge name (blank padded)
14 1 HDCHK header checksum (of first 14 bytes)
15 1 RECFLG - bit 0: always 0 to indicate record block
- bit 1: set for the EOF block
- bit 2: reset for a PRINT file
- bits 3-7: not used (value 0)
16 1 RECNUM data block sequence number (value starts at 0)
17 2 RECLEN data block length (<=512, LSB first)
19 10 RECNAM filename (blank padded)
29 1 DESCHK record descriptor checksum (of previous 14 bytes)
30 512 data block
542 1 DCHK data block checksum (of all 512 bytes of data
block, even when not all bytes are used)
---------
254 times
(Actually, this information is 'transparent' to the emulator. All it does is store 2 times 254 blocks in the .mdr file as it is OUTed, alternatingly of length
15 and 528 bytes. The emulator does check checksums, see below; the other fields are dealt with by the emulated Interface I software.)
A used record block is either an EOF block (bit 1 of RECFLG is 1) or contains 512 bytes of data (RECLEN=512, i.e. bit 1 of MSB is 1). An empty record
block has a zero in bit 1 of RECFLG and also RECLEN=0. An unusable block (as determined by the FORMAT command) is an EOF block with RECLEN=0.
The three checksums are calculated by adding all the bytes together modulo 255; this will never produce a checksum of 255. Possibly, this is the value
that is read by the ZX Interface I if there's no or bad data on the tape.
In normal operation, all first-fifteen-byte blocks of each header or record block will have the right checksum. If the checksum is incorrect, the block will
be treated as a GAP. For instance, if you type OUT 239,0 on a normal Spectrum with ZX Interface I,
the microdrive motor starts running and the cartridge will be erased completely in 7 seconds. CAT 1 will respond with 'microdrive not ready'.
Warajevo uses basically the same format, but ignores the 'read-only' final byte (it obtains this information from the file attributes), and also the files do
not have to contain all 254 sectors.
Note: This is not strictly correct; it is not set to 1 - only bit 0 is set which would give the value 1 if the location previously held 0 or 1. Also,
please be aware that if you format if you FORMAT cartridges after the NEW command, then the channel is created in an area where the bytes have been
set to zero. If you FORMAT cartridges with a BASIC program in memory then the channel is created where the BASIC was and so these bits and bytes
show through.
POK Format v1.20
The .pok file format is a proprietary format designed for use with SGD (from version 1.20)
and was originally used to POKE snapshots prior to launching an emulator to play the specific game. This mechanism works on snapshots only.
Each trainer contains one or more POKEs (sometimes a game check needs more than one poke to acquire a result). All trainers for a game are written
after each other. The first character in a line of the file determines the content of the line;
- 'N' means: this is the Next trainer,
- 'Y' means: this is the last line of the file (the rest of the file is ignored).
After the 'N' follows the name/description of this specific trainer. This string may be up to 30 characters. There is no space between the 'N' and the string.
The following lines, up to the next 'N' or 'Z' hold the POKEs to be applied for this specific trainer. Again, the first character determines the content;
- 'M' means: this is not the last POKE (More)
- 'Z' means: this is the last POKE
The POKE line has the format:
Where l determines the content, bbb is the bank, aaaaa is the address to be poked with value vvv and ooo is the original value of aaaaa. All values are decimal,
and separated by one or more spaces, apart from between l and bbb; however, the bank value is never larger than 8, so you will always see 2 spaces in front of
the bank. The field bank field is built from;
- bit 0-2 : bank value
- bit 3 : ignore bank (1=yes, always set for 48K games)
If the field [value] is in range 0-255, this is the value to be POKEd. If it is 256, a requester should pop up where the user can enter a value.
The 'original' field holds the original value at the address. It is used to remove a POKE. Normally, when applying a POKE, the original value can be read
from the address. Sometimes however, games as found on the internet are already POKEd, so the original value can not be read. If this field is filled
in (non-0) you still have the possibility to remove the trainer. (This format cannot handle the possibility that the original value was 0).
RZX Format
An input-recording format. The RZX Archive contains an increasing number of .rzx files
which can be downloaded and replayed using any emulator that supports
this format. The full .rzx format specification is available from Ramsoft.
SCR Format
These files are Spectrum screen dumps, and are simply the 6912 bytes of pixel and attribute data found at address 16384,
stored on disk in exactly the same way as they are stored in memory.
The Spectrum screen is split into four areas; top third, mid third, bottom third and attributes (colours). The thirds each
consist of 2048 bytes and the attribute area is 768 bytes (32 characters wide x 24 lines). So the first 6144 bytes are the actual
pixel data and the remainder decides what two colours are used in each8x8 square.
Each third of the screen is laid out unusually; the first 32 bytes are the pixels for the top row of the first character line, then the
next 32 bytes are the pixels for the top row of the second character line and so on until you reach the ninth load of 32 bytes, which is
the second row of the first character line. Next 32 bytes is the second row of the second character line, and so on. It's hard to
explain, so the best thing to do is see for yourself; write a program to POKE data to 16384 up and see how the bytes fill in on the screen.
In addition to the above, vbSpec, BMP2SCR Pro, and
Fuse extend the .scr specification in the following ways:
- A 12288 byte .SCR file contains a Timex hi-colour screen.
The first 6144 bytes are a dump from address 16384, and the second 6144 bytes are a dump from 22528.
- A 12289 byte .SCR file contains a Timex hi-res screen.
The first 6144 bytes are a dump from address 16384, and the second 6144 bytes are a dump from 22528,
the last byte contains the hi-res colour information that was dumped from port 255.
| special thanks to Fredrick Meunier for providing updated information for this section |
|