🎯 Введение: Зачем понадобились TZX и TAP?​

В эпоху ZX Spectrum (1980-е) основной носитель данных — обычная компакт-кассета. Компьютер записывал на неё данные в виде последовательности импульсов разной длины. Каждая программа, будь то игровой «loader» или текст на BASIC, представляла собой уникальную «песню» из этих импульсов.

С появлением эмуляторов в 1990-х годах возникла проблема: как сохранить эти аудиоданные в цифровом виде? Первым решением стал простой формат TAP (Tape), который фиксировал длину импульсов. Однако он не мог корректно сохранить многие сложные методы защиты от копирования, использующие нестандартные скорости загрузки, паузы или специальные сигналы.

Формат TZX (Tape Image for ZX Spectrum) был создан в 1996-97 годах как универсальный контейнер, способный сохранить любую кассетную запись со 100% точностью, включая все тонкости оригинального «железа». Если TAP — это фотография процесса загрузки, то TZX — это его полная видеозапись со всеми деталями.

📁 Формат TAP: Простота и ограничения​

Формат TAP был разработан Гунарсом Бриедисом (Gunar`s Briedis) для эмулятора ZX32. Это первый широко принятый формат образов кассет.

Структура TAP-файла​

Файл представляет собой простую последовательность блоков данных. Каждый блок имеет следующую структуру:
СмещениеДлина (байт)Описание
0x002Длина этого блока данных (младший байт первый, Little Endian)
0x02NНепосредственно данные блока (как они были на кассете)

Принцип работы​

  1. Компьютер (или эмулятор) читает первые два байта, определяя длину следующего фрагмента.
  2. Считываются N байт данных.
  3. Процесс повторяется до конца файла.
Каждый байт данных в блоке кодируется стандартным способом:
  • Биту 0 соответствуют 2 импульса (высокий/низкий уровень) общей длиной ~855 тактов процессора Z80 (при стандартной скорости).
  • Биту 1 соответствуют 2 импульса общей длиной ~1710 тактов (вдвое дольше).
Главное ограничение TAP: он предполагает, что все данные на ленте используют одинаковую, стандартную скорость загрузки (так называемую «нормальную» скорость, ~1500 бод). Множество игр использовали нестандартные, более быстрые или медленные скорости, а также сложные паузы между блоками для проверки оригинальности кассеты — всё это TAP корректно сохранить не мог.

🧩 Формат TZX: Универсальный контейнер для кассетного наследия​

Формат TZX был создан Томашем Вилладжи (Tomasz Viladys) при участии сообщества энтузиастов. Его философия — не просто хранить данные, а точно воспроизводить временную шкалу и все характеристики оригинального аудиопотока с кассеты.

Структура заголовка TZX​

Каждый TZX-файл начинается со специальной сигнатуры, идентифицирующей его тип и версию.
СмещениеДлинаЗначениеОписание
0x007 байтZXTape!Сигнатура формата (ASCII-строка)
0x071 байт0x1AМаркер конца заголовка (Ctrl+Z)
0x081 байт0x01Мажорный номер версии формата (напр., 1)
0x091 байт0x14Минорный номер версии формата (напр., 20 для версии 1.20)

После заголовка идёт последовательность блоков данных. Ключевая мощь TZX заключается в разнообразии этих блоков. На сегодняшний день спецификация определяет более 20 различных типов блоков.

Основные типы блоков в TZX (выдержка из спецификации)​

Вот некоторые из самых важных и показательных типов блоков, демонстрирующих возможности формата:
ID (Hex)Название блокаКраткое назначениеПочему это важно
0x10Standard Speed Data BlockБлок стандартных данных (аналог TAP)Базовый блок для обычных программ.
0x11Turbo Speed Data BlockБлок данных с настраиваемой скоростьюПозволяет точно сохранить игры с ускоренной или замедленной загрузкой.
0x12Pure ToneГенерирует тон заданной длины и частотыИспользуется для создания лидирующих сигналов (пилотонов) перед данными.
0x13Pulse SequenceПоследовательность импульсов произвольной длиныКритически важен для воспроизведения нестандартных аппаратных защит.
0x14Pure Data BlockБлок данных с точными параметрамиХранит данные, где важна длительность не только импульсов, но и пауз.
0x20Pause (Stop the Tape)Команда паузы/остановки лентыЭмулирует нажатие STOP на магнитофоне между частями записи.
0x21Group StartНачало именованной группы блоковПозволяет логически группировать части многочастейной записи (Игра + Trainer).
0x22Group EndКонец группы блоков
0x30Text DescriptionТекстовое описаниеПозволяет добавить комментарии, информацию о дампе, авторские права.
0x32Archive InfoРасширенная информация об архивеМожет содержать год выпуска, издателя, тип ПО, жанр, системные требования.
0x35Custom Info BlockБлок для произвольных данныхПредоставляет разработчикам инструментов гибкость для своих нужд.

Пример: Анатомия блока стандартных данных (ID 0x10)​

Этот блок наиболее близок к тому, как работает TAP, но в рамках контейнера TZX.
Код:
  +------------------+  Байт 0x10 (ID блока)
  |   Длина паузы    |  2 байта (длительность паузы ПОСЛЕ этого блока, в миллисекундах)
  +------------------+
  |   Длина данных   |  2 байта (N = длина следующего за заголовком фрагмента данных)
  +------------------+
  |                  |
  |   Данные (N)     |  Непосредственно данные программы
  |                  |
  +------------------+

🔧 Детальная структура и контрольная сумма в формате TAP

Пользователь абсолютно прав. Формат .TAP сложнее, чем просто «длина + данные». Он напрямую имитирует структуру данных, как они записывались на кассету ZX Spectrum, включая механизм проверки ошибок.

Согласно спецификации (источник: ZX Spectrum FAQ / Reference), каждый блок данных в .TAP-файле точно соответствует одному кассетному блоку, который компьютер записывал или считывал. Эта структура включает в себя два типа блоков и обязательную контрольную сумму.

1. Структура ПОЛНОГО кассетного блока в TAP-файле

Внутри одного блока .TAP, заданного двухбайтовой длиной, находится следующий набор данных:
| Длина блока (2 байта) | Флаг (1 байт) | Данные (N байт) | Контрольная сумма (1 байт) |
Где:
  • Длина блока (Little Endian): Длина всего последующего содержимого, включая флаг, данные и контрольную сумму. То есть: Длина = 1 + N + 1.
  • Флаг (Flag): Определяет тип данных в блоке.
    • 0x00 (HEADER): Блок содержит заголовок программы (имя, тип, параметры загрузки).
    • 0xFF (DATA): Блок содержит непосредственно байты программы (код) или числового массива.
  • Данные: Полезная нагрузка. Для HEADER — это 17 байт структурированной информации. Для DATA — это байты самой программы.
  • Контрольная сумма (Checksum): Рассчитывается как байт XOR всех байтов в поле Данные. Для HEADER — XOR 17 байт. Для DATA — XOR всех N байт кода.
Алгоритм проверки: Загрузчик Spectrum после считывания данных вычисляет свою контрольную сумму и сравнивает её с последним байтом блока. Если они не совпадают — возникает ошибка "R: Tape loading error".

2. Детальный разбор структуры HEADER-блока (Флаг = 0x00)

Если флаг указывает на заголовок, то поле данных всегда имеет длину 17 байт и следующую структуру:
СмещениеДлинаОписание
01 байтТип файла: 0=Программа, 1=Числовой массив, 2=Символьный массив, 3=Блок кода.
110 байтИмя файла в кодировке ZX Spectrum (обычно заполнено до длины пробелами).
112 байтаДлина поля данных следующего DATA-блока (для типов 1,2,3). Для типа 0 (программа) — длина программы.
132 байтаПараметр 1:
- Для программы (0): Адрес автостарта (обычно 0x8000 для RUN).
- Для блока кода (3): Адрес загрузки.
152 байтаПараметр 2:
- Для программы (0): Длина программы (дублирует поле по смещению 11).
- Для блока кода (3): Обычно 0x8000 (не используется).

Пример: HEADER для простой программы BASIC будет содержать длину программы, её имя и адрес автостарта 0x8000.

3. Практическое значение контрольной суммы

  1. Обнаружение ошибок чтения: Контрольная сумма была основным механизмом защиты от помех на кассете. Современные .TAP-файлы, созданные с правильной контрольной суммой, гарантируют, что эмулятор (или программатор ПЗУ) будет вести себя так же, как оригинальный ROM Spectrum.
  2. Валидация файлов: Утилиты для работы с .TAP (например, tapinfo) проверяют контрольные суммы, чтобы определить целостность архива. Битый .TAP-файл с неверной суммой может не загрузиться даже в эмуляторе.
  3. Отличие от «сырых» данных: Простая последовательность байтов программы без заголовков и контрольных сумм — это не валидный .TAP. Именно наличие этой структуры делает .TAP полноценным форматом образа кассеты, а не просто контейнером.

⚙️ Сравнительная таблица: TAP vs TZX​

КритерийФормат TAPФормат TZX
Основная цельПростое хранение данных кассетыТочное сохранение сигнала кассеты
Поддержка скоростейТолько одна, стандартнаяЛюбые скорости (Turbo, Slow, настраиваемые)
Специальные сигналыНетДа (Pure Tone, Pulse Sequences)
Паузы и управлениеОграниченноПолный контроль (паузы, остановки, группы)
МетаданныеНетБогатые (описание, информация об архиве)
Сложность обработкиОчень простаяСложная, требует полноценного «виртуального магнитофона»
Типичное использованиеПростые программы, файлы BASICИгры с защитой, коммерческий софт, архивные дампы
Структура блокаЖёсткая: Длина + [Флаг + Данные + Контр. сумма]Гибкая: ID блока + Длина + Специфичные данные
Контроль ошибокВстроенная байт-XOR сумма в каждом блокеЗависит от типа блока. Данные копируются «как есть», включая оригинальные ошибки с кассеты.
Типы данныхДва типа: HEADER (0x00) и DATA (0xFF)Более 20 типов (тон, пауза, данные со скоростью и др.)
Проверка целостностиВозможна на уровне логики данных (проверить сумму)Возможна только на уровне контейнера (целостность потока байтов)

🔧 Практическое значение для сообщества​

Создание и поддержка формата TZX решили несколько фундаментальных задач:
  1. Сохранение цифрового наследия: Благодаря TZX удалось сделать и сохранить точные дампы тысяч игр, которые в формате TAP были бы искажены или вообще неработоспособны.
  2. Развитие точной эмуляции: Эмуляторы, поддерживающие TZX (такие как Fuse, SpecEmu, ZXSpin), смогли достичь невиданной ранее точности в воспроизведении процесса загрузки, вплоть до характерных «скрипов» и пауз оригинальных кассет.
  3. Исследование защит: Формат стал инструментом для изучения исторических методов защиты ПО. Анализируя блоки Pulse Sequence или Pure Tone в дампе редкой игры, энтузиасты могут понять, как работала оригинальная защита.
  4. Создание новых «релизов»: Демосцена и ретро-разработчики используют TZX для распространения своих новых игр и демо, точно контролируя, как их творение будет «звучать» при загрузке.

🛠️ Работа с форматами сегодня​

Современный инструментарий для работы с TZX/TAP обширен:
  • Эмуляторы: Практически все современные эмуляторы ZX Spectrum (Fuse, Retro Virtual Machine) поддерживают оба формата, но TZX является предпочтительным для архивов.
  • Конвертеры: Существуют утилиты (like tzx2wav, tap2tzx) для преобразования между TZX, TAP и реальными аудиофайлами (WAV), которые можно записать на кассету и загрузить на реальный Spectrum.
  • Анализаторы: Специализированные программы (например, TzxDupe) позволяют просматривать внутреннюю структуру TZX-файла, изучать типы блоков и их параметры.
Главный архив, World of Spectrum, использует TZX в качестве основного формата для хранения легально распространяемых образов ПО.

💎 Заключение​

Эволюция от TAP к TZX — это путь от простой оцифровки данных к комплексному сохранению цифрового артефакта во всей его сложности. TAP был важным первым шагом, но именно TZX, с его философией абсолютной точности и расширяемой структурой, стал тем стандартом, который позволил сохранить «живой звук» эпохи ZX Spectrum для будущих поколений.

Если вы сегодня загружаете в эмуляторе классическую игру и слышите точь-в-точь тот же скрип, те же паузы и тот же ритм загрузки, что и на настоящем компьютере 40 лет назад, — это заслуга именно формата TZX и сообщества, которое его создало и поддерживает.

Статья составлена на основе анализа официальной спецификации формата TZX (версия 1.20) с сайта World of Spectrum (https://worldofspectrum.net/TZXformat.html).