ZX-State format

From Sinclair Wiki
Jump to navigation Jump to search

ZX-State (SZX) format

ZX-State is the preferred snapshot format for Spectaculator and Fuse. It is usually used with the extension .SZX. Fuse unofficially uses the mimetype x-spectrum-szx for the format (although this could potentially change to x-spectrum-zxstate or x-spectrum-zx-state).

See the official ZX-State documentation and also the draft of the next version.

Support for the format is implemented in libspectrum (used by Fuse), Zero, ZXDS, SpecEmu and Spin.

Early versions of libspectrum (prior to 1.0.0) contained a bug which caused the A and A' registers to be swapped with F and F', respectively, when loading or saving in the SZX format. Current versions of libspectrum detect "libspectrum: 0.5.0" and earlier versions strings and correct for this.

Format extensions

With the official specification being somewhat stalled, some emulators have added unofficial extensions to the format. These include:

ZXSTDIVIDE

The state of the DivIDE IDE hard disk and CompactFlash card interface.

// DivIDE flags
#define ZXSTDIVIDE_EPROM_WRITEPROTECT 1
#define ZXSTDIVIDE_PAGED 2
#define ZXSTDIVIDE_COMPRESSED 4

// DivIDE IDE settings
typedef struct _tagZXSTDIVIDEBLOCK
{
  ZXSTBLOCK blk;
  WORD wFlags;
  BYTE chMemCtrl;
  BYTE chNumRamPages;
  BYTE chData[1];
} ZXSTDIVIDEBLOCK, *LPZXSTDIVIDEBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_DIVIDE ('D', 'I', 'D', 'E').
   wFlags
      Various flags. This can be any combination of:

Flag Meaning
ZXSTDIVIDE_EPROM_WRITEPROTECT The DivIDE's EPROM is write protected.
ZXSTDIVIDE_PAGED The DivIDE is currently paged in.
ZXSTDIVIDE_COMPRESSED If set, the EPROM data (beginning from chData) will be compressed using the Zlib compression library.

   chMemCtrl
      The current value of the DivIDE's memory control register.
   chNumRamPages
      The amount of RAM installed in this DivIDE interface, in units of 8KB. Normally 4, representing a 32KB DivIDE interface.
   chData
      The compressed or uncompressed contents of the DivIDE's EPROM. When uncompressed, this member is exactly 16KB (16,384) bytes in size. When loading Zlib compressed pages, the compressed size can be obtained by:

compressedSize = blk.dwSize - ( sizeof( ZXSTDIVIDEBLOCK ) - sizeof( ZXSTBLOCK ) - 1 );

ZXSTDIVIDERAMPAGE

This block is used to save and restore the contents of the DivIDE's built-in RAM.

A zx-state file will contain a number of these blocks, normally 4 for the 32KB DivIDE. A ZXSTDIVIDE block will proceed the first of these blocks.

// Ram pages are compressed using Zlib
#define ZXSTDRF_COMPRESSED 1

// DivIDE RAM page
typedef struct _tagZXSTDIVIDERAMPAGEBLOCK
{
  ZXSTBLOCK blk;
  WORD wFlags;
  BYTE chPageNo;
  BYTE chData[1];
} ZXSTDIVIDERAMPAGEBLOCK, *LPZXSTDIVIDERAMPAGEBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_DIVIDERAMPAGE ('D', 'I', 'R', 'P').
   wFlags
      Various flags. This can be any combination of:

Flag Meaning
ZXSTDRF_COMPRESSED If set, the RAM page data (beginning from chData) will be compressed using the Zlib compression library.

   chPageNo
      Page number of this 8KB RAM page. For the 32KB version of the DivIDE interface, this is 0 - 3.
   chData
      The compressed or uncompressed contents of the RAM page. When uncompressed, this member is exactly 8KB (8,192) bytes in size. When loading Zlib compressed pages, the compressed size can be obtained by:

compressedSize = blk.dwSize - ( sizeof( ZXSTDIVIDERAMPAGEBLOCK ) - sizeof( ZXSTBLOCK ) - 1 );

ZXSTDIVMMC

The state of the DivMMC interface.

// DivMMC flags
#define ZXSTDIVMMC_EPROM_WRITEPROTECT 1
#define ZXSTDIVMMC_PAGED 2
#define ZXSTDIVMMC_COMPRESSED 4

// DivMMC settings
typedef struct _tagZXSTDIVMMCBLOCK
{
  ZXSTBLOCK blk;
  WORD wFlags;
  BYTE chMemCtrl;
  BYTE chNumRamPages;
  BYTE chData[1];
} ZXSTDIVMMCBLOCK, *LPZXSTDIVMMCBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_DIVMMC ('D', 'M', 'M', 'C').
   wFlags
      Various flags. This can be any combination of:

Flag Meaning
ZXSTDIVMMC_EPROM_WRITEPROTECT The DivMMC's EPROM is write protected.
ZXSTDIVMMC_PAGED The DivMMC is currently paged in.
ZXSTDIVMMC_COMPRESSED If set, the EPROM data (beginning from chData) will be compressed using the Zlib compression library.

   chMemCtrl
      The current value of the DivMMC's memory control register.
   chNumRamPages
      The amount of RAM installed in this DivMMC interface, in units of 8KB. Normally 16, 32 or 64, representing 128KB, 256KB or 512KB DivMMC interfaces.
   chData
      The compressed or uncompressed contents of the DivMMC's EPROM. When uncompressed, this member is exactly 16KB (16,384) bytes in size. When loading Zlib compressed pages, the compressed size can be obtained by:

compressedSize = blk.dwSize - ( sizeof( ZXSTDIVMMCBLOCK ) - sizeof( ZXSTBLOCK ) - 1 );

ZXSTDIVMMCRAMPAGE

This block is used to save and restore the contents of the DivMMC's built-in RAM.

A zx-state file will contain a number of these blocks, normally 16 for the 128KB DivMMC, 32 for the 256KB version or 64 for the 512KB version . A ZXSTDIVMMC block will proceed the first of these blocks.

// Ram pages are compressed using Zlib
#define ZXSTDRF_COMPRESSED 1

// DivMMC RAM page
typedef struct _tagZXSTDIVMMCRAMPAGEBLOCK
{
  ZXSTBLOCK blk;
  WORD wFlags;
  BYTE chPageNo;
  BYTE chData[1];
} ZXSTDIVMMCRAMPAGEBLOCK, *LPZXSTDIVMMCRAMPAGEBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_DIVIDERAMPAGE ('D', 'M', 'R', 'P').
   wFlags
      Various flags. This can be any combination of:

Flag Meaning
ZXSTDRF_COMPRESSED If set, the RAM page data (beginning from chData) will be compressed using the Zlib compression library.

   chPageNo
      Page number of this 8KB RAM page. For the 128KB version of the DivIDE interface, this is 0 - 15, for the 256KB version, it is 0 - 31 and for the 512KB version it is 0 - 63.
   chData
      The compressed or uncompressed contents of the RAM page. When uncompressed, this member is exactly 8KB (8,192) bytes in size. When loading Zlib compressed pages, the compressed size can be obtained by:

compressedSize = blk.dwSize - ( sizeof( ZXSTDIVMMCRAMPAGEBLOCK ) - sizeof( ZXSTBLOCK ) - 1 );

ZXSTLEC

This is documented in the draft of the next version of the SZX format.

ZXSTLECRAMPAGE

This is documented in the draft of the next version of the SZX format.

ZXSTPALETTE

The state of the ULA registers found in the 64 colour replacement ULA. This block may be present for any machine.

// Palette Block flags
#define ZXSTPALETTE_DISABLED 0
#define ZXSTPALETTE_ENABLED 1

// Palette Block. Contains the palette register values
typedef struct _tagZXSTPALETTEBLOCK
{
  ZXSTBLOCK blk;
  BYTE chFlags;
  BYTE chCurrentRegister;
  BYTE chPaletteRegs[64];
} ZXSTPALETTEBLOCK, *LPZXSTPALETTEBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_PALETTE ('P', 'L', 'T', 'T').
   chFlags
      A flags that indicates if the palette is enabled or if the normal display mode is in use. This can be one of:

Flag Meaning
ZXSTPALETTE_DISABLED Normal palette mode with BRIGHT and FLASH
ZXSTPALETTE_ENABLED 64 colour palette mode


    chCurrentRegister
      The currently selected palette register (0-63).
    chPaletteRegs
      The current values of the palette registers.

ZXSTSPECTRANET

NB: Note that the draft of the next version of the SZX format is out of date and does not represent what has been implemented in Fuse.

This block represents Dylan Smith's Spectranet Ethernet interface for the 16K, 48K, 128, +2, +2A and +3 ZX Spectrums.

// Spectranet state
#define ZXSTSNETF_PAGED                      0x0001
#define ZXSTSNETF_PAGED_VIA_IO               0x0002
#define ZXSTSNETF_PROGRAMMABLE_TRAP_ACTIVE   0x0004
#define ZXSTSNETF_PROGRAMMABLE_TRAP_MSB      0x0008
#define ZXSTSNETF_ALL_DISABLED               0x0010
#define ZXSTSNETF_RST8_DISABLED              0x0020
#define ZXSTSNETF_DENY_DOWNSTREAM_A15        0x0040
#define ZXSTSNETF_NMI_FLIPFLOP               0x0080

typedef struct _tagZXSTSPECTRANET
{
  ZXSTBLOCK blk;
  DWORD dwFlags;
  BYTE chPageA;
  BYTE chPageB;
  WORD wTrap;
  BYTE chRegisters[0x30];
} ZXSTSPECTRANET, *LPZXSTSPECTRANET;

Members

   blk
      The block header. The block id is ZXSTBID_SPECTRANET ('S', 'N', 'E', 'T').
   wFlags
      Various flags. This can be any combination of:

Flag Meaning
ZXSTSNETF_PAGED The Spectranet is currently paged.
ZXSTSNETF_PAGED_VIA_IO The Spectranet was paged in via I/O port.
ZXSTSNETF_PROGRAMMABLE_TRAP_ACTIVE The Spectranet's programmable trap is currently active.
ZXSTSNETF_PROGRAMMABLE_TRAP_MSB The next write to the Spectranet's programmable trap port will set the MSB of the programmable trap address.
ZXSTSNETF_ALL_DISABLED All the Spectranet's traps are currently disabled.
ZXSTSNETF_RST8_DISABLED The Spectranet's RST 8 trap is currently disabled.
ZXSTSNETF_DENY_DOWNSTREAM_A15 The Spectranet is forcing the A15 line low for any peripherals connecting via its expansion port.
ZXSTSNETF_NMI_FLIPFLOP The Spectranet's "suppress NMI" flipflop is set

   chPageA
      The page currently paged into the Spectranet's page A (0x1000-0x1fff).
   chPageB
      The page currently paged into the Spectranet's page B (0x2000-0x2fff).
   wTrap
      The current value of the Spectranet's programmable trap.
   chRegisters
      The values of the core W5100 registers.

Remarks

The contents of the W5100's socket registers are not saved - whatever was listening on the other end will have gone away when the snapshot is restored.

ZXSTSPECTRANETFLASHPAGE

This block is used to save and restore the contents of the Spectranet's built-in flash memory.

A zx-state file will contain only one of these blocks. A ZXSTSPECTRANET block will proceed the the blocks.

// Flash memory is compressed using Zlib
#define ZXSTSFF_COMPRESSED 1

// Spectranet flash memory
typedef struct _tagZXSTSPECTRANETFLASHPAGEBLOCK
{
  ZXSTBLOCK blk;
  BYTE chFlags;
  DWORD ???
  DWORD dwCompressedSize;
  BYTE chData[1];
} ZXSTSPECTRANETFLASHPAGEBLOCK, *LPZXSTSPECTRANETFLASHPAGEBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_SPECTRANETFLASHPAGE ('S', 'N', 'E', 'F').
   wFlags
      Various flags. This can be any combination of:

Flag Meaning
ZXSTSFF_COMPRESSED If set, the flash memory page data (beginning from chData) will be compressed using the Zlib compression library.

   dwCompressedSize
      The size of the data at chData.
   chData
      The compressed or uncompressed contents of the Spectranet's flash memory. When uncompressed, this member is exactly 128KB (131,072) bytes in size.

ZXSTSPECTRANETRAMPAGE

This block is used to save and restore the contents of the Spectranet's built-in RAM.

A zx-state file will contain only one of these blocks. A ZXSTSPECTRANET block will proceed the the blocks.

// RAM is compressed using Zlib
#define ZXSTSRF_COMPRESSED 1

// Spectranet RAM
typedef struct _tagZXSTSPECTRANETRAMPAGEBLOCK
{
  ZXSTBLOCK blk;
  BYTE chFlags;
  DWORD ???
  DWORD dwCompressedSize;
  BYTE chData[1];
} ZXSTSPECTRANETRAMPAGEBLOCK, *LPZXSTSPECTRANETRAMPAGEBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_SPECTRANETRAMPAGE ('S', 'N', 'E', 'R').
   wFlags
      Various flags. This can be any combination of:

Flag Meaning
ZXSTSRF_COMPRESSED If set, the RAM data (beginning from chData) will be compressed using the Zlib compression library.

   dwCompressedSize
      The size of the data at chData.
   chData
      The compressed or uncompressed contents of the Spectranet's RAM. When uncompressed, this member is exactly 128KB (131,072) bytes in size.

ZXSTZXMMC

The state of the ZXMMC interface.

// ZXMMC settings
typedef struct _tagZXSTZXMMCBLOCK
{
  ZXSTBLOCK blk;
} ZXSTZXMMCBLOCK, *LPZXSTZXMMCBLOCK;

Members

   blk
      The block header. The block id is ZXSTBID_ZXMMC ('Z', 'M', 'M', 'C').

(It is correct that this block has no members other than the block ID; the presence of this block indicates the presence of the interface).

Emulator / tool support

The earliest version of each emulator or tool which supports each block type.

Block type Fuse[1] libspectrum
ZXSTDIVIDE 0.10.0 0.5.0
ZXSTDIVIDERAMPAGE 0.10.0 0.5.0
ZXSTDIVMMC 1.4.0 1.4.0
ZXSTDIVMMCRAMPAGE 1.4.0 1.4.0
ZXSTLEC None[2] None[2]
ZXSTLECRAMPAGE None[2] None[2]
ZXSTPALETTE None[3] 1.2.0
ZXSTSPECTRANET 1.1.0 1.1.0
ZXSTSPECTRANETFLASHPAGE 1.1.0 1.1.0
ZXSTSPECTRANETRAMPAGE 1.1.0 1.1.0
ZXSTZXMMC 1.4.0 1.4.0

Notes

  1. Fuse's snapshot support is supplied by libspectrum; the version number listed is the first released version of Fuse which uses appropriate version of libspectrum.
  2. 2.0 2.1 2.2 2.3 As of August 2017, no version of Fuse or libspectrum supports the LEC RAM interface. However, version 1.1.0 (of both Fuse and libspectrum) will not produce a warning when loading a zx-state file with a ZXSTLEC or ZXSTLECRAMPAGE block.
  3. As of August 2017, no released version of Fuse supports the ULAplus interface. However, version 1.2.0 will not produce a warning when loading a zx-state file with a ZXSTPALETTE block.