Skip to content

PZX Tape

PZX is an alternative tape format for the ZX Spectrum with pulse-level encoding. It uses a tagged block structure with four-byte ASCII block identifiers. PZX is designed to be simpler and more compact than TZX while still preserving the full timing information needed for non-standard loaders.

Details about the PZX format can be found at https://github.com/raxoft/pzxtools.

API

Class Description
PzxFormat Singleton format for reading and writing PZX files.
PzxFile Represents a PZX file as a list of blocks.
PzxBlock Base class for all PZX blocks.

Reading and Writing

// Read
using var stream = File.OpenRead("tape.pzx");
PzxFile pzx = PzxFormat.Instance.Read(stream);

// Write
using var output = File.Create("output.pzx");
PzxFormat.Instance.Write(pzx, output);

Blocks

A PzxFile contains a list of PzxBlock objects. The first block is always a PzxHeaderBlock (PZXT tag) carrying version information and optional metadata entries.

Block Type Tag Description
PzxHeaderBlock PZXT File header with version and metadata.
PulseSequenceBlock PULS Sequence of pulse lengths in T-states.
DataBlock DATA Data bits with associated zero/one pulse patterns.
PauseBlock PAUS A pause of a given duration in T-states.
BrowsePointBlock BRWS A named browse point for tape navigation.
StopBlock STOP Stop the tape, optionally only on 48K machines.
if (pzx.Blocks[0] is PzxHeaderBlock header)
{
    Console.WriteLine($"PZX version {header.Header.MajorVersionNumber}.{header.Header.MinorVersionNumber}");
    foreach (var info in header.Info)
        Console.WriteLine($"{info.Type}: {info.Text}");
}

foreach (PzxBlock block in pzx.Blocks.Skip(1))
{
    switch (block)
    {
        case DataBlock data:
            Console.WriteLine($"Data: {data.Header.SizeInBytes} bytes");
            break;
        case PauseBlock pause:
            Console.WriteLine($"Pause: {pause.Header.Duration} T-states");
            break;
    }
}

Conversions

PZX files can be converted to TAP, TZX, and WAV.

When converting to TAP, only DataBlock blocks are converted. All other block types (header, pulse sequences, pauses, browse points, and stop blocks) are skipped.

See Reading, Writing and Converting.