Teledisk: различия между версиями
Panther (обсуждение | вклад) мНет описания правки |
Xolod (обсуждение | вклад) |
||
(не показаны 3 промежуточные версии 1 участника) | |||
Строка 160: | Строка 160: | ||
Чтение 1 байта «Тип блока» | Чтение 1 байта «Тип блока» | ||
Если «Тип блока» == 0 то | Если «Тип блока» == 0 то | ||
Читаем «Длина данных» в качестве данных сектора | Читаем «Длина данных»-1 в качестве данных сектора | ||
Иначе | Иначе | ||
Если «Тип блока» == 1 то | Если «Тип блока» == 1 то | ||
Строка 177: | Строка 177: | ||
== Источники и ссылки == | == Источники и ссылки == | ||
* {{www}} [ | * {{www}} [https://hwiegman.home.xs4all.nl/fileformats/teledisk/wteledsk.htm Teledisk File Format by Willy] | ||
* {{www}} [http://www.classiccmp.org/dunfield/ | * {{www}} [http://www.classiccmp.org/dunfield/img54306/td0notes.txt Teledisk File Format by Dave Dunfield] | ||
== Программы == | == Программы == | ||
* {{zip | * {{zip||Библиотека для работы с форматом Teledisk|software/dsklib/teledisk.0.1.1.zip}} (Pascal/Delphi, исходные коды, пример использования) | ||
* {{zip | * {{zip||Программа Teledisk разных версий|software/dsklib/teledisk-all.zip}} (MS-DOS/Win 9x/Me, в NT/XP/Vista не работает) | ||
[[Категория:Форматы файлов]] | [[Категория:Форматы файлов]] |
Текущая версия от 11:49, 21 сентября 2023
Этот документ создан для Emuverse и распространяется на условиях лицензии CC-BY-SA-3.0. |
Teledisk — формат файлов, содержащий посекторную копию дискеты. Создавался с помощью одноименной утилиты. Внутри файла находятся данные, упакованные по принципу RLE (RLE+LZSS в режиме «Advanced compression»).
Описание формата
Формат файла следующий:
Заголовок Данные
Формат заголовка:
type TTDHeader = packed record sig: array [0..1] of Char; //Сигнатура "TD" или "td" vol: Byte; //Номер тома. 0 для TD0 chk: Byte; //Сигнатура, одинаковая для всех томов ver: Byte; //Для версий 2.11-2.16 равно 15H dens: Byte; //Плотность записи. Обычно 0. typ: Byte; //Тип устройства. 1=360K, 2=1.2M, //3=720K, 4=1.44M. flag: Byte; //Старший бит - наличие комментария dos: Byte; //DOS mode? Обычно 00H sides: Byte; //Кол-во сторон crc: Word; //CRC первых 10 байт записи end;
Если сигнатура равна «TD», за заголовком следуют данные без упаковки LZSS, иначе они упакованы, и требуется распаковка. Далее распакованные данные обрабатываются аналогично формату без компрессии.
Формат данных (отступы сделаны для удобства):
Комментарий (если TTDHeader.flag > 80H) Заголовок дорожки 0 Заголовок сектора 1 Данные сектора 1 Заголовок сектора 2 Данные сектора 2 .......... Заголовок сектора N Данные сектора N Заголовок дорожки 1 .......... Заголовок дорожки M ..........
Общее количество секторов и дорожек может быть получено только после обработки всего файла, в общем заголовке этих данных нет.
Формат комментария:
Заголовок комментария Данные комментария (текст)
Формат заголовка комментария:
TTDComment = packed record crc: Word; //Контрольная сумма комментария len: Word; //Длина комментария в байтах yr, mon, day, //Дата. Год отсчитывается от 1990. hr, min, sec: Byte; end;
Данные комментария представляют собой строки, оканчивающиеся #0. Строк может быть несколько.
Формат заголовка дорожки:
TTDTrack = packed record nsec: Byte; //Кол-во последующих записей секторов. //Часть записей должна игнорироваться trk: Byte; //Номер дорожки head: Byte; //Номер стороны crc: Byte; //Контрольная сумма заголовка end;
Количество секторов может не совпадать с реальным, так как назначение части записей пока не установлено, они должны игнорироваться.
Заголовок сектора:
TTDSector = packed record trk: Byte; //Номер дорожки; head: Byte; //Номер стороны; sec: Byte; //Номер сектора; secz: Byte; //Код размера сектора; cntrl: Byte; //Тип данных; crc: Byte; //Контрольная сумма распакованных данных end;
TDSector.sec=$65 обозначает, что достигнут конец файла, остаток данных нужно пропустить.
Если TDSector.sec > TDTrack.nsec, последующие данные сектора должны быть проигнорированы.
Вычисление размера сектора в байтах: SectSize := 1 shl (TDSector.secz+7);
Данные относятся к реальному сектору, если выполняется следующее условие: ((TDSector.cntrl and $30) = 0) and ((TDSector.secz and $F8) = 0), иначе данные нужно игнорировать.
Если TDSector.cntrl=$10, то сектор содержит пустые данные (возможно, не был прочитан корректно), нужно переходить к чтению заголовка следующего сектора.
Формат блока данных сектора (если сектор непустой):
Длина блока (2 байта) Тип блока (1 байт) Данные блока
Если Тип блока=0, то «данные блока» представляют собой содержание сектора в неупакованном формате, при этом «длина блока» должна совпадать с размером сектора плюс один байт для поля "Тип блока".
Если Тип блока=1, то «данные блока» представляют собой следующую запись:
TTDRepeat = packed record count: Word; //Количество повторений pat: array [0..1] of Byte; //Данные для повторения (2 байта) end;
«Количество повторений» должно быть в два раза меньше размера сектора.
Если Тип блока=2, то «данные блока» представляют собой последовательность записей:
Заголовок записи Данные записи
Формат заголовка записи:
TTDPattern = packed record flag: Byte; count: Byte; end;
Если TDPattern.flag=0, то за заголовком следуют данные длиной TDPattern.count. Иначе, TDPattern.flag обозначает размер блока для повторения, следующий за заголовком, TDPattern.count — количество повторений. Размер блока в байтах вычисляется как PatSize := 1 shl TDPattern.flag;.
Обобщенный алгоритм
--------- основная процедура --------- Чтение заголовка файла TDHeader Если TDHeader.sig == ”td” то распаковка данных Если TDHeader.sig != ”TD” то выход с ошибкой «неправильный формат» Если TDHeader.flag & 80H > 0 то Чтение заголовка комментария Чтение блока данных комментария Пока не конец данных Чтение заголовка дорожки TDTrack Если TDTrack.nsec == 0FFH то окончание работы Для секторов от 1 до TDTrack.nsec Чтение заголовка сектора TDSector Если TDSector.sec == 65H то окончание работы SectSize := 1 shl (TDSector.secz+7); Если ((TDSector.cntrl & 30H) == 0) && ((TDSector.secz & 0F8H) == 0) то Если TDSector.cntrl == 10H то сектор пустой, переход к следующему Иначе Чтение 2-х байт «Длина данных» Если TDSector.sec <= TDTrack.nsec то Распаковка_данных(Длина данных) Иначе Пропускаем «Длина данных» из входного потока --------- подпрограмма --------- Процедура Распаковка_данных(Длина данных) Чтение 1 байта «Тип блока» Если «Тип блока» == 0 то Читаем «Длина данных»-1 в качестве данных сектора Иначе Если «Тип блока» == 1 то Читаем запись TDRepeat Помещаем в буфер сектора TDRepeat.count повторений TDRepeat.pat Иначе Если «Тип блока» == 2 то Пока не достигнута «Длина данных»-1 Читаем запись TDPattern Если TDPattern.flag == 0 то Читаем TDPattern.count байт и помещаем их в буфер сектора Иначе PatSize := 1 shl TDPattern.flag; Читаем «PatSize» данных из входного потока Пишем эти данные TDPattern.count раз в буфер сектора
Источники и ссылки
Программы
- Библиотека для работы с форматом Teledisk (Pascal/Delphi, исходные коды, пример использования)
- Программа Teledisk разных версий (MS-DOS/Win 9x/Me, в NT/XP/Vista не работает)