Просмотр полной версии : Формат файла tap zx spectrum
san010101
13.09.2017, 12:10
Всем добра!
Прошу не ругать за повтор и т.д.
Не нашел ответов на вопросы вот и решил создать тему.
Format Description
The .TAP files contain blocks of tape-saved data. All blocks start with two bytes specifying how many bytes will follow (not counting the two length bytes). Then raw tape data follows, including the flag and checksum bytes. The checksum is the bitwise XOR of all bytes including the flag byte. For example, when you execute the line SAVE "ROM" CODE 0,2 this will result:
|------ Spectrum-generated data -------| |---------|
13 00 00 03 52 4f 4d 7x20 02 00 00 00 00 80 f1 04 00 ff f3 af a3
^^^^^...... first block is 19 bytes (17 bytes+flag+checksum)
^^... flag byte (A reg, 00 for headers, ff for data blocks)
^^ first byte of header, indicating a code block
file name ..^^^^^^^^^^^^^
header info ..............^^^^^^^^^^^^^^^^^
checksum of header .........................^^
length of second block ........................^^^^^
flag byte ...........................................^^
first two bytes of rom .................................^^^^^
checksum (checkbittoggle would be a better name!).............^^
Note that it is possible to join .TAP files by simply stringing them together; for example, in DOS / Windows: COPY /B FILE1.TAP + FILE2.TAP ALL.TAP ; or in Unix/Linux: cp file1.tap all.tap && cat file2.tap >> all.tap
For completeness, I'll include the structure of a tape header. A header always consists of 17 bytes:
Byte Length Description
0 1 Type (0,1,2 or 3)
1 10 Filename (padded with blanks)
11 2 Length of data block
13 2 Parameter 1
15 2 Parameter 2
The type is 0,1,2 or 3 for a Program, Number array, Character array or Code file. A SCREEN$ file is regarded as a Code file with start address 16384 and length 6912 decimal. If the file is a Program file, parameter 1 holds the autostart line number (or a number >=32768 if no LINE parameter was given) and parameter 2 holds the start of the variable area relative to the start of the program. If it's a Code file, parameter 1 holds the start of the code block when saved, and parameter 2 holds 32768. For data files finally, the byte at position 14 decimal holds the variable name.
Вопрос по блокам
length of second block ........................^^^^^
flag byte ...........................................^^
first two bytes of rom .................................^^^^^
checksum (checkbittoggle would be a better name!).............^^
что это за блок и откуда берутся first two bytes of rom (в каждом файле они разные)
Нужно ли этот блок считывать.
Spectramine
13.09.2017, 13:21
На самом деле, формат файла .TAP очень простой. Формат предназначен для хранения данных, записанных на кассете магнитофона на стандартной скорости записи, без информации о паузах и т.п.
Каждый блок данных предваряется двумя байтами его длины, и дальше идут собственно данные. Это всё.
2 байта длины (младший вначале), затем данные блока последовательно, начиная с первого флагового байта, заканчивая последним байтом контрольной суммы.
Собственно, формат о них ничего не знает, и первый и последний байт могут быть произвольными, но для корректной загрузки стандартными загрузчиками обычно первый байт - флаговый, последний - байт контрольной суммы (XOR всех предыдущих байтов блока).
Формат стандартного заголовочного блока Бейсика такой:
1 байт - флаговый, для блока заголовка всегда равен 0 (для блока данных за ним равен 255)
1 байт - тип Бейсик блока, 0 - бейсик программа, 1 - числовой массив, 2 - символьный массив, 3 - кодовый блок
10 байт - имя блока
2 байта - длина блока данных, следующего за заголовком (без флагового байта и байта контрольной суммы)
2 байта - Параметр 1, для Бейсик-программы - номер стартовой строки Бейсик-программы, заданный параметром LINE (или число >=32768, если стартовая строка не была задана. Для кодового блока - начальный адрес блока в памяти. Для массивов данных - 14й-байт хранит односимвольное имя массива
2 байта - Параметр 2. Для Бейсик-программы - хранит размер собственно Бейсик-програмы, без инициализированных переменных, хранящихся в памяти на момент записи Бейсик-программы. Для остальных блоков содержимое этого параметра не значимо, и я почти уверен, что это не два байта ПЗУ. Скорее всего, они просто не инициализируются при записи.
1 байт - контрольная сумма заголовочного блока.
Считывать блок заголовка нужно, если программа не знает точных параметров блока данных за ним. Если знает, его можно пропустить.
- - - Добавлено - - -
Понял, откуда 2 байта ПЗУ. В примере описано содержимое файла .TAP, для сохраненного из Бейсика командой <SAVE "ROM" CODE 0,2>
блока кодов ПЗУ длиной 2 байта. Это актуально только для данного примера:
13 00 - длина TAP-блока заголовка (19 байт - #13 в шестнадцатеричной системе)
00 - флаговый байт заголовка
03 - байт типа данных (3 - кодовый блок)
52 4f 4d - имя блока ("ROM")
7x20 - ещё семь пробелов имени блока
02 00 - длина блока кодов без флагового байта и байта контрольной суммы
00 00 - начальный адрес блока кодов
00 80 - параметр, не имеющий смысла для блока кодов
f1 - контрольная сумма заголовка
04 00 - длина TAP-блока данных за заголовком (2 байта данных, плюс флаговый байт и байт контрольной суммы)
ff - флаговый байт блока данных (255)
f3 af - два первых байта ПЗУ
a3 - байт контрольной суммы блока данных
ZART-TCH.DOC
ZART
File Transfer Utility for ZX Spectrum / IBM PC Computers
(C) Rick Murray, 1994, Chelyabinsk
Структуры всяких штук.
┌─────────────── ──────────────── ──┐
│ Стандартный заголовок файла, │
│ записанного на пленке. │
└─────────────── ──────────────── ──┘
typedef struct {
unsigned char type; тип файла
char name[10]; имя файла
unsigned int length; длина файла
unsigned int start; стартовый адрес
unsigned int blen; длина бейсика
} tHEADER;
┌─────────────── ──────────────── ──┐
│ Стандартный элемент каталога │
│ TR-DOS │
└─────────────── ──────────────── ──┘
typedef struct {
char name[8]; имя файла
char type; тип ('C','B', итд)
unsigned int start; стартовый адрес
unsigned int length; длина
unsigned char sex; количество секторов
unsigned char sector; стартовый сектор
unsigned char track; стартовая дорожка
} trHEADER;
Если это бейсиковский текст, то как правило start == length, а номер
стартовой строки вычисляется следующим способом:
- Берется буфер, куда считаны сектора, к-во которых берется из sex,
- От вершины буфера отсчитывается start байт,
- Следующими после этого должны идти 2 байта AA80h,
- Сразу за этими байтами - число int, обозначающее стартовую строчку.
┌─────────────── ───────────────┐
│ Заголовок файла, который │
│ понимает HOBETA. │
└─────────────── ───────────────┘
typedef struct {
char name[8]; имя для TR-DOS
char type; тип ('C','B',...)
unsigned int start; стартовый адрес
unsigned int length; длина
unsigned char temp; всегда 0
unsigned char sex; количество секторов
unsigned int checksum; контрольная сумма заголовка
} dHEADER;
Сразу вслед за этим заголовком следуют данные собственно файла, имеющие
размер sex * 256 байт.
Контрольная сумма рассчитывается следующим образом:
int dhcheck()
{
unsigned int i,j,k;
for(j=i=0; i<0x0F; ++i){
k = *((char *)&Dhead+i); k &= 0xFF;
j += (k * 0x0101 + i);
}
return j;
}
Здесь Dhead - переменная типа dHEADER содержащая сформированный
заголовок.
┌─────────────── ──────────────┐
│ Формат файла TAPE_ZX.SPC │
└─────────────── ──────────────┘
Файл состоит из циклически повторяющихся блоков:
Pазмер Тип Hазначение
──────────────── ──────────────── ───────
2 unsigned int Pазмер блока данных
1 unsigned char Тип блока (0-заголовок, FF-данные)
?? ... Блок данных
1 unsigned char Контрольная сумма блока данных
Поле размера блока включает только размер самого блока данных.
Контрольная сумма считается как xor всех байт блока данных.
┌─────────────── ──────────┐
│ Формат TAP файла │
└─────────────── ──────────┘
Аналогично файл состоит из повторяющихся кусков:
Pазмер Тип Hазначение
──────────────── ──────────────── ───────
2 unsigned int Pазмер всего, что надо считать относящегося к файлу.
(иными словами - размер блока данных + 2, т.е. плюс
байт типа и байт crc)
1 unsigned char Тип блока (аналогично SPC)
?? ... Блок данных
1 unsigned char Контрольная сумма блока данных вместе с байтом типа.
Поле размера включает размер блока данных + 2.
Контрольная сумма считается как xor фсех байт блока данных и байта типа.
TAP файл является точным отображением структуры записи на кассете за
исключением первых двух байт, вместо которых на пленке записан
лидер-сигнал и синхроимпульс.
┌─────────────── ──────────────── ───┐
│ Стандартный элемент какталога │
│ MS-DOS │
└─────────────── ──────────────── ───┘
Стандартный элемент какталога MS-DOS располагается в области таблицы
партиций и занимает по крайней мере первую половину диска MS-DOS. Для
того чтобы прочитать этот элемент необходимо по меньшей мере 12 минут,
для того чтобы направляющий ролик смог обнаружить межсекторное
пространство, а для того чтобы гарантировать правильное чтение данного
сектора, вы должны быть уверены, что сам какталог находится на диске, а
не под ним.
san010101
13.09.2017, 13:52
Спасибо за помощь.
Начал вникать, т.е. в приведенном примере
13 00 00 03 52 4f 4d 7x20 02 00 00 00 00 80 f1 04 00 ff f3 af a3
байты f3 af - два первых байта ПЗУ
и есть то что было записано командой
SAVE "ROM" CODE 0,2
в конце идет контр.сумма
согласно примеру заполню структуру
typedef struct {
unsigned char type; тип файла тут ставим 0 (программа)
char name[10]; имя файла ROM
unsigned int length; длина файла 0x02
unsigned int start; стартовый адрес 0x00
unsigned int blen; длина бейсика ????? что тут???
} tHEADER;
Spectramine
13.09.2017, 14:19
Что угодно, для блока кодов это неважно. И тип файла для блока кодов должен быть 3, а не 0.
san010101
13.09.2017, 14:36
unsigned int blen; длина бейсика
если это бейсик или массив?
- - - Добавлено - - -
Контрольную сумму считает сам загрузчик и сравнивает ее потом с последним байтом, т.е. размер контрольной суммы это байт?
сорри, смотрю в стандартном заголовке ленты вообще нет упоминание о контрольной сумме.
Spectramine
13.09.2017, 14:56
Третий после имени файла параметр (blen в сишной структуре) имеет смысл только для блоков с Бейсик-программами, для кодовых и массивов данных он не имеет смысла, и может быть любым. Для Бейсик-программы, как я уже сказал, он хранит длину собственно Бейсик-программы, без хранящихся совместно с ней инициализированных переменных Бейсика. Если инициализации переменных ещё не было, длина Бейсик-программы равна длине блока в первом параметре (length).
Контрольную сумму считает загрузчик, да, размер КС- байт. Формат заголовка ленты относится к более высокому уровню абстракции, поэтому контрольной суммы не содержит.
san010101
13.09.2017, 15:13
Вот теперь все встало на свои места, благодарю за развернутый ответ.
Bedazzle
16.09.2017, 17:00
Тут (http://www.zx-modules.de/fileformats/fileformats.html) дофига можно чего найти, клик на расширении файла - даёт более подробную инфу.
san010101
16.09.2017, 17:39
Спасибо за ресурс!
Отправлено с моего A0001 через Tapatalk
Oleg N. Cher
16.09.2017, 19:25
Вот я писал модуль для работы с форматом tap, в нём реализован базис, включая подсчёт контрольной суммы.
https://github.com/Oleg-N-Cher/MakeZX/blob/master/Mod/TapeTAP.Mod
Интерфейс:
https://s8.hostingkartinok.com/uploads/images/2017/09/086a88ad152ef7f6eb603a2c149754f6.png (https://hostingkartinok.com/show-image.php?id=086a88ad152ef7f6eb603a2c149754f6)
P.S. Сорри за Оберон. Любителей его поругать просьба идти...
san010101
17.09.2017, 06:17
Благодарю за поддержку, буду реализовывать для STM32 в среде ARM Keil. Там язык C.
- - - Добавлено - - -
Пока разбираюсь с таймерами и прерываниями.
- - - Добавлено - - -
Нужно реализовать пилот тон и синхо.
- - - Добавлено - - -
http://zx-info.ru/images/articles/articles/zx_and_tape.1.gif
- - - Добавлено - - -
http://www.zx-info.ru/?rc=12&id=9
можно тут посмотреть https://github.com/raydac/zxtap-to-wav
san010101
30.09.2017, 04:03
Всем добра.
Подскажите правильно я делаю или нет.
Алгоритм чтения tap файла
1. Сначала пилот для заголовка длительность 5 сек. частота 807 Гц
2. Синхроимпульс ~ 171,4 мксек
3. Синхроимпульс 200 мксек
4. Читаем 17 байт заголовка
где
00...01 это длина заголовка (обычно 0х13)
02 флаг 00 для заголовка FF для блока данных
04...0D имя файла
15..16 длина блока данных
17 флаг FF
5. Пилот тон данных 2 сек. 807Гц
6. Синхроимпульс ~ 171,4 мксек
7. Синхроимпульс 200 мксек
8. Чтение блока данных
- - - Добавлено - - -
Ссылка на код обработчика прерываний, где происходит чтение файла
http://zx-pk.ru/threads/28153-proigryvatel-tap-fajlov-zx-spectrum-na-demonstratsionnoj-plate-stm32f407g-disc1.html?p=929795&viewfull=1#post929795
Spectramine
30.09.2017, 04:11
Нет, не правильно. Заголовок это флаговый байт 00 + 17 байт заголовка + байт контрольной суммы, итого 19 байт. (Но при загрузке заголовка мы задаем загрузчику длину 17, потому что флаговый байт и байт контрольной суммы служебные, и не учитываются.)
Длина заголовка в заголовке не хранится, потому что она фиксирована. Она хранится только в TAP файле, потому что он ничего не знает о содержимом блоков, он хранит только их длины+содержимое.
Так что:
пилот
синхро1
синхро2
флаговый байт 00
байт типа даннных (03 - для кодового блока)
10 байт имени
2 байта длины блока кодов
2 байта ещё один параметр (стартовый адрес для кодового блока)
2 байта ещё один параметр (незначим для кодового блока)
1 байт контрольной суммы
пауза
пилот
синхро1
синхро2
флаговый байт FF
содержимое блока кодов длиной, указанной в заголовке
байт контрольной суммы
пауза
san010101
30.09.2017, 04:20
длина паузы?
san010101
30.09.2017, 10:26
Так как я делаю плеер на STM32 файлов tap то сколько байт мне нужно считать????
с
00..0х12
или
00..0х17
- - - Добавлено - - -
Если я считаю до 0х12 байта то следующая очередь пойдет чтение блока данных
это 0х13 и далее...
но блок данных начнется с 0х18 байта/
- - - Добавлено - - -
что бы не было путаницы можно написать какие байты мне после первого пилот тона прочитать и какие после второго пилота
san010101
30.09.2017, 12:43
Все нашел. Пауза 1 секунда.
Читаем заголовок до 0х14 байта
с 0х18 идет блок кода
где 0х17 флаг
и последний байт контрольная сумма
Получается:
Пилот заголовок
синхро 1,2
Данные заголовоек
0х00...0х14
пауза 1 сек
Пилот блок кода
синхро 1,2
Блок кода с 0х15......
где
0х15, 0х16 длина кода с флагом + контр сумма
0х17 флаг
0х18...........контр сумма
пауза 1 сек
san010101, Не нужно тебе различать заголовки и данные. Просто нужно пропищать все блоки из TAP по порядку. В них уже есть и тип блока и контрольная сумма.
- - - Добавлено - - -
Двух секунд по началу хватит на все пилоты.
Потом, для аутентичности, можно сделать длинный пилот для блоков-заголовков, для работы это не важно, это-же не лента, у которой самое начало наивероятно поджована/загрязнена/осыпана.
Алгоритм примерно такой:
1. Открываем нужный TAP и ставим позицию чтения на нулевой байт.
2. Если файл уже кончился, то передача завершена.
3. Читаем двухбайтовую длину блока.
4. Пищим пилот, синхро.
5. Читаем нужное число байт и пищим их.
6. Завершаем с паузой.
7. Идём выполнять пункт 2.
san010101
29.11.2017, 19:16
Всем спасибо за помощь в разборе формата tap.
Мне удалось воплотить эту информацию в устройстве проигрыватель tap файлов на STM32. Информация на форуме в соседей ветке.
Сейчас для дальнейшего творчества интересен формат tzx.
Прежде всего описание формата и его программная реализация чтения файлов.
Отправлено с моего A0001 через Tapatalk
san010101
29.11.2017, 19:18
https://r.tapatalk.com/shareLink?url=http%3A%2F%2Fzx-pk%2Eru%2Fshowthread%2Ephp%3Ft%3D28153&share_tid=28153&share_fid=35919&share_type=t
Проигрыватель tap файлов ZX-Spectrum на демонстрационной плате STM32F407G-DISC1
Вот ссылка на моё устройство.
Отправлено с моего A0001 через Tapatalk
san010101
30.11.2017, 17:30
Кто разбирался с tzx. Начал читать мануал, очень интересный формат.
Spectramine
30.11.2017, 17:57
Я разбирался, пришлось для эмулятора. Если будут вопросы, задавайте, что вспомню, подскажу. Для него лучше наверно отдельную тему завести. Это один из самых распространённых и самый сложный из форматов ленточных образов. Многие эмуляторы даже не поддерживают его полностью, только часть его блоков. А часть блоков вообще проблематично поддержать вне эмулятора - блоки взаимодействия с пользователем.
объясните глупому в чём преимущество этой платы для реала перед загрузкой wav/mp3 с чего угодно ?
(зачем тратить 2000руб, ради меньшего размера файлов ?)
goodboy, это прикольно. :)
san010101
30.11.2017, 18:55
объясните глупому в чём преимущество этой платы для реала перед загрузкой wav/mp3 с чего угодно ?
(зачем тратить 2000руб, ради меньшего размера файлов ?)У меня просто нет комментариев.
Отправлено с моего A0001 через Tapatalk
san010101
30.11.2017, 18:58
http://s.aliexpress.com/RRziI3Ir
(from AliExpress Android)
Вот достойная плата и стоит около 800 руб
Отправлено с моего A0001 через Tapatalk
Spectramine
30.11.2017, 19:10
Вообще есть и проигрыватели TAP/TZX с андроид-телефонов:
https://play.google.com/store/apps/details?id=dk.rift.tzxdroid&hl=ru
https://play.google.com/store/apps/details?id=com.baltazarstudios.playzxtapes&hl=ru
san010101
30.11.2017, 19:12
Если такими категориями оперировать то и пиво Балтика 0 пиво и резиновая женщина тоже женщина.
Прошу прощения за аналогии, это шутка.
Отправлено с моего A0001 через Tapatalk
Spectramine
30.11.2017, 19:19
Ну, в любом случае имитатор кассеты - не кассета :)
объясните глупому в чём преимущество этой платы для реала перед загрузкой wav/mp3 с чего угодно ?
(зачем тратить 2000руб, ради меньшего размера файлов ?)
Преимущество в том, что такой штукой можно не только читать, но и писать файлы. Чего не умеют плееры и всякие там ведроидные симуляторы.
Но использовать для этого навороченный 32-битный МК с кучей ресурсов, это тоже, имхо, перебор - копеечной AVR-ки для всего этого вполне достаточно.
Хотя, для целей обучения STM32 эта тема подходит идеально.
Ну, в любом случае имитатор кассеты - не кассета
И это хорошо, т.к. у имитатора нет тех проблем, что есть у кассеты. А "тёплый ламповый звук" и атмосферу погружения они дают достаточную :)
Преимущество в том, что такой штукой можно не только читать, но и писать файлы. Чего не умеют плееры и всякие там ведроидные симуляторы.
запись я не увидел поэтому и спросил
(про самообразование мне и так понятно)
Spectramine
30.11.2017, 19:51
Преимущество в том, что такой штукой можно не только читать, но и писать файлы. Чего не умеют плееры и всякие там ведроидные симуляторы.
Что имеется ввиду под "писать"? Захватывать с реального спека звук записи и получать на выходе TAP-файл? Насколько я понял, в данном случае это не реализовано.
Что имеется ввиду под "писать"? Захватывать с реального спека звук записи и получать на выходе TAP-файл? Насколько я понял, в данном случае это не реализовано.
Ага, писать TAP-файл (и другие форматы тоже). Если это пока не реализовано, то наверняка будет сделано в будущем - задача для такой мощной железки тривиальная.
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot