Numbers are little-endian. Facts on this page are from World of Spectrum's description of the format
(z80format, read through a summarising fetch tool) and
checked against the source of libspectrum's z80.c, and against 15 real files.
The 30-byte header
Every version starts with this. Version 1 stops here; the memory follows at offset 30.
| Offset | Size | Field |
|---|---|---|
0 | 1 | A |
1 | 1 | F |
2 | 2 | BC (C first) |
4 | 2 | HL |
6 | 2 | Program counter; zero in version 2 and 3 (the real value is in the extra header) |
8 | 2 | Stack pointer |
10 | 1 | I |
11 | 1 | R (bits 0-6; bit 7 is in byte 12) |
12 | 1 | Flags, below; a value of 255 is read as 1 |
13 | 2 | DE |
15 | 2 | BC' |
17 | 2 | DE' |
19 | 2 | HL' |
21 | 1 | A' |
22 | 1 | F' |
23 | 2 | IY |
25 | 2 | IX |
27 | 1 | Interrupt flip-flop: 0 is DI, anything else EI |
28 | 1 | IFF2 |
29 | 1 | Interrupt mode and hardware flags, below |
Telling the versions apart
If the program counter at offset 6 is not zero the file is version 1. If it is zero, the 16-bit number at offset 30 is the length of the
extra header: 23 is version 2, and 54 or 55 is version 3 (libspectrum accepts exactly these three values and refuses any other). The memory
blocks start at offset 32 + length.
The extra header (versions 2 and 3)
| Offset | Size | Field |
|---|---|---|
30 | 2 | Length of the rest: 23, 54 or 55 |
32 | 2 | Program counter (the real one) |
34 | 1 | Hardware mode, below |
35 | 1 | SamRam: the state of the 74LS259 bits. 128K: the last value written to port $7FFD. Timex: the last value written to port $F4 |
36 | 1 | $FF if the Interface I ROM is paged in. Timex: the last value written to port $FF |
37 | 1 | Emulation flags, below |
38 | 1 | The last value written to port $FFFD: the sound chip register selected |
39 | 16 | The contents of the 16 sound chip (AY-3-8912) registers |
| Version 3 continues: | ||
55 | 2 | Low T-state counter |
57 | 1 | High T-state counter |
58 | 1 | Spectator flag byte (ignored when loading, zero when saving) |
59 | 1 | $FF if the M.G.T. ROM is paged in |
60 | 1 | $FF if the Multiface ROM is paged in (should always be 0) |
61 | 1 | $FF if addresses 0-8191 are ROM, 0 if RAM |
62 | 1 | $FF if addresses 8192-16383 are ROM, 0 if RAM |
63 | 10 | Five keyboard mappings for a user-defined joystick, two bytes each: the row in the low byte and a mask of columns in the high byte (Enter is $0106, G is $1001) |
73 | 10 | Five ASCII words naming those keys (left, right, down, up, fire), high byte 0; Shift, Symbol Shift, Enter and Space are written [ ] / \ |
83 | 1 | M.G.T. type: 0 Disciple + Epson, 1 Disciple + HP, 16 Plus D |
84 | 1 | Disciple inhibit button: 0 out, $FF in |
85 | 1 | Disciple inhibit flag: 0 ROM pageable, $FF not |
86 | 1 | Last value written to port $1FFD (only when the length at 30 is 55) |
The T-state counters give the position inside the frame at which the snapshot was taken. The format description says the high counter counts modulo 4
(the quarter of the frame) and the low counter counts down from 17471 (17726 on 128K machines) to 0 within a quarter, a frame being 69888 T-states
(70908 on 128K machines). libspectrum computes the T-state of the snapshot from them as ((high + 1) mod 4 + 1) × quarter − (low + 1).
Flag bytes
Byte 12
- Bit 0: bit 7 of the R register
- Bits 1-3: border colour (0 black, 1 blue, 2 red, 3 magenta, 4 green, 5 cyan, 6 yellow, 7 white)
- Bit 4: 1 if the SamRam BASIC ROM is switched in
- Bit 5: 1 if the data is compressed (version 1 only; bits 4 and 5 have no meaning in versions 2 and 3)
Byte 29
- Bits 0-1: interrupt mode (0, 1 or 2; a few files hold 255 here, so the value is read as bits 0-1 and a mode of 3 is not defined)
- Bit 2: Issue 2 emulation
- Bit 3: double interrupt frequency
- Bits 4-5: video synchronisation (1 high, 3 low, 0 or 2 normal)
- Bits 6-7: joystick type: 0 Cursor/Protek/AGF, 1 Kempston, 2 Sinclair 2 left (user defined in version 3), 3 Sinclair 2 right
Byte 37 (versions 2 and 3)
- Bit 0: R register emulation on
- Bit 1: LDIR emulation on
- Bit 2: AY sound in use, even on a 48K machine
- Bit 6: Fuller Audio Box emulation (valid only if bit 2 is set)
- Bit 7: modify hardware: a 48K mode means a 16K machine, a 128K mode means a +2, a +3 mode means a +2A
Hardware mode (byte 34)
The numbers 0 to 6 mean different machines in version 2 and in version 3. Versions 3.00 to 3.02 of Z80 documented the SamRam and 48K + M.G.T. labels swapped; files written by those versions follow the table below.
| Value | Version 2 | Version 3 |
|---|---|---|
| 0 | 48K | 48K |
| 1 | 48K + Interface I | 48K + Interface I |
| 2 | SamRam | SamRam |
| 3 | 128K | 48K + M.G.T. |
| 4 | 128K + Interface I | 128K |
| 5 | not used | 128K + Interface I |
| 6 | not used | 128K + M.G.T. |
Values used by other emulators, valid in version 2 and 3:
| Value | Machine |
|---|---|
| 7 | Spectrum +3 |
| 8 | Spectrum +3 (written by mistake by some versions of XZX-Pro) |
| 9 | Pentagon (128K) |
| 10 | Scorpion (256K) |
| 11 | Didaktik-Kompakt |
| 12 | Spectrum +2 |
| 13 | Spectrum +2A |
| 14 | TC2048 |
| 15 | TC2068 |
| 128 | TS2068 |
libspectrum does not know value 11 and refuses such a file; the explorer names it and shows the memory as it does for other machines it does not model.
Sources
- Z80 format – World of Spectrum (read through a summarising tool)
- libspectrum's
z80.c– the reading code, read in place on the machine used to build the explorer
Not described
The behaviour of the machines the extra bytes belong to (what port $F4 or $FF does on a Timex, the SamRam latch), and any
field of a file written by a tool that stores something the description does not list.