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.