Snapshot Files ============== Those handled by SPConv v1.10 are in italics: .ACH or .archimedes or Snapshots used by !Speccy and Speculator. .SSN .ACH is the extension SPConv uses for these files, so that filename-challenged operating systems like DOS can handle such files for conversion purposes. .PRG Snapshots used by SpecEm. .RAW Raw memory dump from a real Spectrum; just the 48K of RAM and a CODE header on the front. .SEM Snapshots used by ZX Spectrum-Emulator. .SIT Snapshots used by Sinclair. .SLT Super level loader snapshot. Used by many emulators these days; basically a v2/3 .Z80 snapshot with level data appended. .SNA or .snap or Mirage Microdrive snapshot format, used by most .snapshot emulators. .SNA 128K version of SNA. Distinguished by file size of 131103 bytes instead of 49179 bytes for 48K version. .SNX Extended version of .SNA, used by Speccy on the Atari ST. .SP Snapshots used by Spectrum and it's earlier version, VgaSpec. .Z80 Snapshots used by Z80 and many other emulators. Three versions in existence, the latest of which (v3/SLT) is not supported by all emulators. Very flexible; support for SamRam, 128K snapshots, etc. .ZX Snapshots used by KGB. .ZXS Snapshot format used by zx32; .ZXS 'snapshots' can also contain tape and disk images, but are unrelated to the .ZXS tape format. .ZX82 Snapshots used by Speculator '97. For the purposes of these descriptions, the following definitions apply: byte = byte-sized variable word = two bytes long = four bytes All stored in little-endian (Intel) format unless otherwise stated. .SLT (Super Level loader Trap used by x128, WSpecEm, Z80 & others) ------------------------------------------------------------------ The level loader trap has one annoying disadvantage; lots of extra files lying around for each game. The super level loader was thought up (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), so is well-supported already. The format was designed with future expansion in mind, as you will see. 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, of course, 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. Only data types 0 (end of table) and 1 (level data) are supported at the moment, so if other values are encountered an emulator should ignore that data block. 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. E.g., 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 64K (indeed, could not even be as much as 48K), 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 exceed 64K easily. See this page for Damien Burke's proposals for future data types for inclusion in .SLT snapshots. .SNA, .snap or .snapshot (Mirage Microdrive format used by many emulators) -------------------------------------------------------------------------- This format is the most well-supported of all snapshot formats (though Z80 is close on its heels) 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. How different emulators handle this is not something I know... 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 .SNA (128K version) (SP_EMU) ----------------------------- This is simply the SNA format extended 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 16K bytes RAM bank 5 \ 16411 16K bytes RAM bank 2 } - as standard 48K SNA file 32795 16K bytes RAM bank n / (currently paged bank) 49179 2 word PC 49181 1 byte port 7FFD setting 49182 1 byte (unknown - padding for above byte?) 49183 16K 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. .SP (Spectrum) -------------- Offset Size Description ------------------------------------------------------------------------ 0 2 byte "SP" (signature) 2 2 word Program length in bytes (normally 49152 for 48K snaps, or 16384 for 16K snaps) 4 2 word Program location (normally 16384) 6 8 word BC,DE,HL,AF 14 4 word IX,IY 18 8 word BC',DE',HL',AF' 26 2 byte R,I 28 4 word SP,PC 32 2 word 0 (reserved for future use) 34 1 byte Border color 35 1 byte 0 (reserved for future use) 36 2 word Status word ------------------------------------------------------------------------ Status word: Bit Description ------------------------------------------------------------------------ 15-8 Reserved for future use 7-6 Reserved for internal use (0) 5 Flash: 0=INK/1=PAPER 4 Interrupt pending for execution 3 If 1, IM 0; if 0, bit 1 determines interrupt mode (Spectrum v 0.99e had this behaviour reversed, and this bit was not used in versions previous to v 0.99e) 2 IFF2 (internal use) 1 Interrupt Mode (if bit 3 reset): 0=>IM1, 1=>IM2 0 IFF1: 0=DI/1=EI [UPDATED] .Z80 (Z80) [from Z80 documentation] --------------------------------------------- The old .Z80 snapshot format (for version 1.45 and below) looks like this: Offset Length Description --------------------------- 0 1 A register 1 1 F register 2 2 BC register pair (LSB, i.e. C, first) 4 2 HL register pair 6 2 Program counter 8 2 Stack pointer 10 1 Interrupt register 11 1 Refresh register (Bit 7 is not significant!) 12 1 Bit 0 : Bit 7 of the R-register Bit 1-3: Border colour Bit 4 : 1=Basic SamRom switched in Bit 5 : 1=Block of data is compressed Bit 6-7: No meaning 13 2 DE register pair 15 2 BC' register pair 17 2 DE' register pair 19 2 HL' register pair 21 1 A' register 22 1 F' register 23 2 IY register (Again LSB first) 25 2 IX register 27 1 Interrupt flipflop, 0=DI, otherwise EI 28 1 IFF2 (not particularly important...) 29 1 Bit 0-1: Interrupt mode (0, 1 or 2) Bit 2 : 1=Issue 2 emulation Bit 3 : 1=Double interrupt frequency Bit 4-5: 1=High video synchronisation 3=Low video synchronisation 0,2=Normal Bit 6-7: 0=Cursor/Protek/AGF joystick 1=Kempston joystick 2=Sinclair 2 Left joystick (or user defined, for version 3 .Z80 files) 3=Sinclair 2 Right joystick Because of compatibility, if byte 12 is 255, it has to be regarded as being 1. After this header block of 30 bytes the 48K bytes of Spectrum memory follows in a compressed format (if bit 5 of byte 12 is one). The compression method is very simple: it replaces repetitions of at least five equal bytes by a four-byte code ED ED xx yy, which stands for "byte yy repeated xx times". Only sequences of length at least 5 are coded. The exception is sequences consisting of EDs; if they are encountered, even two EDs are encoded into ED ED 02 ED. Finally, every byte directly following a single ED is not taken into a block, for example ED 6*00 is not encoded into ED ED ED 06 00 but into ED 00 ED ED 05 00. The block is terminated by an end marker, 00 ED ED 00. That's the format of .Z80 files as used by versions up to 1.45. Starting from version 2.0, a different format is used, since from then on also 128K snapshots had to be supported. This new format is used for all snapshots, either 48K or 128K. Version 2.01 and 3.0 .Z80 files start with the same 30 byte header as old .Z80 files used. Bit 4 and 5 of the flag byte have no meaning any more, and the program counter (byte 6 and 7) are zero to signal a version 2.01 or version 3.0 snapshot file. After the first 30 bytes, the additional header follows: Offset Length Description --------------------------- * 30 2 Length of additional header block (see below) * 32 2 Program counter * 34 1 Hardware mode (see below) * 35 1 If in SamRam mode, bitwise state of 74ls259. For example, bit 6=1 after an OUT 31,13 (=2*6+1) If in 128 mode, contains last OUT to 7ffd * 36 1 Contains 0FF if Interface I rom paged * 37 1 Bit 0: 1 if R register emulation on Bit 1: 1 if LDIR emulation on * 38 1 Last OUT to fffd (soundchip register number) * 39 16 Contents of the sound chip registers 55 2 Low T state counter 57 1 Hi T state counter 58 1 Flag byte used by Spectator (QL spec. emulator) Ignored by Z80 when loading, zero when saving 59 1 0FF if MGT Rom paged 60 1 0FF if Multiface Rom paged. Should always be 0. 61 1 0FF if 0-8191 is ROM, 0 if RAM 62 1 0FF if 8192-16383 is ROM, 0 if RAM 63 10 5x keyboard mappings for user defined joystick 73 10 5x ascii word: keys corresponding to mappings above 83 1 MGT type: 0=Disciple+Epson,1=Disciple+HP,16=Plus D 84 1 Disciple inhibit button status: 0=out, 0ff=in 85 1 Disciple inhibit flag: 0=rom pageable, 0ff=not The value of the word at position 30 is 23 for version 2.01 files, and 54 for version 3.0 files. The starred fields are the ones that constitute the version 2.01 header, and their interpretation has remained unchanged except for byte 34: Value: Meaning in v2.01 Meaning in v3.0x -------------------------------------------------------- 0 48k 48k 1 48k + If.1 48k + If.1 2 SamRam SamRam 3 128k 48k + M.G.T. 4 128k + If.1 128k 5 - 128k + If.1 6 - 128k + M.G.T. Warajevo writes v2 .Z80 files, but with some extensions to deal with its Timex 2068 emulation: * Byte 34: 128 signifies Timex 2068 emulation is active. * Byte 35: If Timex 2068 is active, last OUT to port 244. * Byte 36: If Timex 2068 is active, last OUT to port 255. xzx always saves the AY registers to .Z80 snapshots, independent of the emulated machine. Bit 2 of byte 37 being set signifies that this feature is in use. Also, xzx has extended the format by adding a 55th byte to the header, which stores the last byte output to #1FFD, and using values of 7 and 8 in the hardware field to signify a +3 without and with Interface 1 respectively. The documenation for versions 3.00 to 3.02 of Z80 had the entries for 'SamRam' and '48k + M.G.T.' in the second column of the above table reversed; also bytes 61 and 62 of the format were wrong up to version 3.04. (The snaps produced by the older versions of Z80 still follow what is above; the documentation for the older versions is wrong). The hi T state counter counts up modulo 4. Just after the ULA generates its once-in-every-20-ms interrupt, it is 3, and is increased by one every 5 emulated milliseconds. In these 1/200s intervals, the low T state counter counts down from 17471 to 0 (17726 in 128K modes), which make a total of 69888 (70908) T states per frame. The 5 ASCII words (high byte always 0) at 73-82 are the keys corresponding to the joystick directions left, right, down (!), up (!), fire respectively. Shift, Symbol Shift, Enter and Space are denoted by [,],/,\ respectively. The ascii values are used only to display the joystick keys; the information in the 5 keyboard mapping words determine which key is actually pressed (and should correspond to the ascii values). The low byte is in the range 0-7 and determines the keyboard row. The high byte is a mask byte and determines the column. Enter for example is stored as 0x0106 (row 6 and column 1) and 'g' as 0x1001 (row 1 and column 4). Byte 60 must be zero, because the contents of the Multiface RAM is not saved in the snapshot file. If the Multiface was paged when the snapshot was saved, the emulated program will most probably crash when loaded back. Bytes 61 and 62 are a function of the other flags, such as byte 34, 59, 60 and 83. Hereafter a number of memory blocks follow, each containing the compressed data of a 16K block. The compression is according to the old scheme, except for the end-marker, which is now absent. The structure of a memory block is: Byte Length Description --------------------------- 0 2 Length of compressed data (without this 3-byte header) If length=0xffff, data is 16384 bytes long and not compressed 2 1 Page number of block 3 [0] Data The pages are numbered, depending on the hardware mode, in the following way: Page In '48 mode In '128 mode In SamRam mode ------------------------------------------------------ 0 48K rom rom (basic) 48K rom 1 Interface I, Disciple or Plus D rom, according to setting 2 - rom (reset) samram rom (basic) 3 - page 0 samram rom (monitor,..) 4 8000-bfff page 1 Normal 8000-bfff 5 c000-ffff page 2 Normal c000-ffff 6 - page 3 Shadow 8000-bfff 7 - page 4 Shadow c000-ffff 8 4000-7fff page 5 4000-7fff 9 - page 6 - 10 - page 7 - 11 Multiface rom Multiface rom - In 48K mode, pages 4,5 and 8 are saved. In SamRam mode, pages 4 to 8 are saved. In '128 mode, all pages from 3 to 10 are saved. There is no end marker. .ZX (KGB) [Contributed by Troels Norgaard] ------------------------------------------ All values stored in big-endian format; on 680x0 the most significant byte goes first. Offset Size Description ------------------------------------------------------------------------ 0 49284 bytes RAM dump 16252..65535 49284 132 bytes unused, make 0 49416 10 word 10,10,4,1,1 (different settings) 49426 1 byte InterruptStatus (0=DI/1=EI) 49427 2 byte 0,3 49429 1 byte ColorMode (0=BW/1=Color) 49430 4 long 0 49434 16 word BC,BC',DE,DE',HL,HL',IX,IY 49450 2 byte I,R 49452 2 word 0 49454 8 byte 0,A',0,A,0,F',0,F 49462 8 word 0,PC,0,SP 49470 2 word SoundMode (0=Simple/1=Pitch/2=RomOnly) 49472 2 word HaltMode (0=NoHalt/1=Halt) 49474 2 word IntMode (-1=IM0/0=IM1/1=IM2) 49476 10 bytes unused, make 0 ------------------------------------------------------------------------ Total: 49486 bytes .ZX82 (Speculator '97) [Taken from the Speculator documentation] ---------------------------------------------------------------- Amiga Speculator has its own file format which I have called ZX82 format because it contains a file identifier in the first four bytes consisting of the ASCII characters "ZX82". The format has a 12 byte header which contains the normal Spectrum type file information like length, type, start etc. as well as a compression flag which is set if the file is byte run compressed. Snapshot files have a further 32 bytes of register values and border colour information. Listed below are the offset definitions taken from the Speculator source code in case you need to write a conversion utility. All registers and other values are in Motorola format (High, Low). I have defined everything in bytes to avoid any possible confusion. * The Standard ZX82 Header ZX_ID rs.l 1 Identifier for a Speculator file "ZX82" ZX_Type rs.b 1 0:BASIC 1:Numeric 2:String 3:Code 4:Snapshot ZX_Comp rs.b 1 Is data block byte run compressed ? $00=No $FF=Yes ZX_Length_H rs.b 1 File length up to 64k (ELINE-PROG for BASIC) ZX_Length_L rs.b 1 ZX_Start_H rs.b 1 Start address for code (AUTOSTART for BASIC) ZX_Start_L rs.b 1 ZX_ProgLen_H rs.b 1 Array name (VARS-PROG for BASIC) ZX_ProgLen_L rs.b 1 ZX_ZXHdrLen rs.b 0 Length of ZX file header ZX_ZXData rs.b 0 Start of Data block for standard ZX file * The extended Snapshot ZX82 Header ZX_Border rs.b 1 Border colour ZX_IntMode rs.b 1 IntMode over-ride (0=use i_reg, 1=im1 and 2=im2) ZX_Registers rs.b 0 Z80 register values for Snapshot Files ZX_iy_H_reg rs.b 1 (High then Low i.e. Motorola format) ZX_iy_L_reg rs.b 1 ZX_ix_H_reg rs.b 1 ZX_ix_L_reg rs.b 1 ZX_de_H_reg rs.b 1 ZX_de_L_reg rs.b 1 ZX_bc_H_reg rs.b 1 ZX_bc_L_reg rs.b 1 ZX_hl_H_reg rs.b 1 ZX_hl_L_reg rs.b 1 ZX_af_H_reg rs.b 1 ZX_af_L_reg rs.b 1 ZX_de_H_alt rs.b 1 ZX_de_L_alt rs.b 1 ZX_bc_H_alt rs.b 1 ZX_bc_L_alt rs.b 1 ZX_hl_H_alt rs.b 1 ZX_hl_L_alt rs.b 1 ZX_af_H_alt rs.b 1 ZX_af_L_alt rs.b 1 ZX_sp_H_reg rs.b 1 ZX_sp_L_reg rs.b 1 ZX_if_H_reg rs.b 1 ZX_if_L_reg rs.b 1 ZX_rf_H_reg rs.b 1 ZX_rf_L_reg rs.b 1 ZX_pc_H_reg rs.b 1 ZX_pc_L_reg rs.b 1 ZX_SnpHdrLen rs.b 0 Length of Snapshot file header ZX_SnpData rs.b 65496 Start of data block for Snapshot type file The ZX_Type field is derived from the MGT disciple directory MGT_Type-1, so further file types may be supported in this way in the future. The compression used is the standard byte run compression as used by ILBM IFF files. The whole 48k data block is compressed as if it were one long row. See Amiga ROM Kernel Reference Manual: Devices Third Edition, Appendix A - IFF Specification (P347), Appendix C - Example Packer C code (P538). .ZXS (zx32) ----------- The latest specification for .ZXS files can be found on the zx32 Home Page. Note that there is also a .ZXS tape format (see below), but this is completely unrelated to this format. .SSN (Speculator) [Documented by JGH] ------------------------------------- A Speculator snapshot is filetyped &702 on RISC OS. It consists of 256 bytes of workspace data containing the register contents, followed by the 64K memory contents. It is loaded with *SpecLoad and saved with *SpecSave. Offset Size Description ------------------------------------------------------------------------ &0000 4 A register &0004 4 F register &0008 4 B register &000C 4 C register &0010 4 D register &0014 4 E register &0018 4 H register &001C 4 L register &0020 4 PC register &0024 4 * ARM address of the Spectrum memory of this shapshot &0028 4 SP register &002C 4 ? &0030 92 unused? &008C 1 ? &008D 1 ? &008E 1 Sound flag - &00=off, <>&00=on &008F 1 Saved escape flag, to restore on exit &0090 4 * SWI intercept vector &0094 4 pseudo-R register - initialised with TIME at startup &0098 4 ? &009C 4 Border colour set by last OUT 254 value &00A0 1 * toggled on interupts &00A1 3 ? &00A4 4 IM 0, 1 or 2 &00A8 4 * Scandir index for scanning tapefile directory &00AC 4 * Currently open file PTR &00B0 4 * Currently open tapefile handle &00B4 4 * Filetype of currently open tapefile &00B8 4 * Saved ARM SP to restore on exit &00BC 1 ? &00BD 1 ? &00BE 1 I register &00BF 1 IFF - &00=INTs disabled, <>&00=INTs enabled &00C0 32 unused? &00E0 8 * Keyboard matrix keypressed bitmap &00E8 4 * Address of (z80mem-&4C) = workspace &00B4 &00EC 1 A' register &00ED 1 F' register &00EE 2 zero &00F0 1 B' register &00F1 1 C' register &00F2 2 zero &00F4 1 D' register &00F5 1 E' register &00F6 1 H' register &00F7 1 L' register &00F8 4 IX register &00FC 4 IY register &0100 64k Start of 64k memory dump &100FF : End of snapshot, total length=&10100 bytes * Ignored on loading Where a register occupies more space than the register size, the unused high bytes must be zero. For example, offset &00 holds the A register and &01, &02 and &03 must hold zero. Loading a snapshot with a register holding an oversized value can have unexpected effects. A valid snapshot can be created with all bytes of the header set to zero, and the register contents set to something sensible. Byte &8E should be set to &FF to enable sound. SpecSnap (Speccy, Carsten Witt) ------------------------------- Byte Register 0 A 1 F 2 B 3 C 4 D 5 E 6 H 7 L 8 PC low 9 PC high 10 SP low 11 SP high 12 F' (only bits 3 and 5 are relevant and correspond to the Z80's inofficial flags) 13 A' 14 F' (Bits SZCVHxNx, ie. in a non-Z80-specific order, where S stands for sign, Z for zero flag etc.; x=no meaning) 15 B' 16 C' 17 D' 18 E' 19 H' 20 L' 21 IX low 22 IX high 23 IY low 24 IY high 25 I 26 R 27 Bits 0-2: Border colour Bits 3-4: Interrupt mode (0, 1 or 2) Bit 5: Interrupt flipflop (1=enabled) Bits 6-7: reserved (must be zero!) The seemingly senseless format of the stored F' register is due to the emulator's internal routines that keep the flags partly in ARM format. You may have detected that the arrangement of the uppest four bits of byte 14 is equivalent to that of the ARM flags in R15. After the header, the 48K of Spectrum memory is stored in a compressed format. The emulator replaces repetitions of at least five equal bytes by incorporating the code ED DD XX YY, which means that the byte YY is repeated XX times. If even more than 255 equal bytes are encountered, the code is ED DE XX YY ZZ, meaning XX+256*YY equal bytes ZZ. Of course an originally existing byte pattern of ED DE or ED DD has to be encoded as well, even if it is not repeated.