mirror of
https://github.com/aaru-dps/docs.git
synced 2025-12-16 19:24:38 +00:00
* FD-Soft.html: Documents Atari FAT variations. * File_Manager.pdf: Documents HFS and Apple Partition Map. * hm2def.h: Documentation for ODS. * td0notes.txt: TeleDisk format information. * tn1150.html: Documents HFS+. * README.md: Information about this folder.
573 lines
22 KiB
Plaintext
573 lines
22 KiB
Plaintext
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Teledisk
|
||
|
||
Image File Format
|
||
|
||
Notes
|
||
|
||
|
||
|
||
|
||
|
||
PRELIMINARY
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Dave Dunfield
|
||
April 2, 2007
|
||
|
||
Last revised: July 28, 2008
|
||
|
||
|
||
|
||
Teledisk .TD0 notes
|
||
|
||
TABLE OF CONTENTS
|
||
|
||
|
||
Page
|
||
|
||
1. Introduction 1
|
||
|
||
1.1 Acknowlegements 1
|
||
|
||
2. Image file Format 2
|
||
|
||
|
||
3. Image Header 2
|
||
|
||
3.1 Signature (2 bytes) 2
|
||
3.2 Sequence (1 byte) 2
|
||
3.3 CheckSequence (1 byte) 3
|
||
3.4 Teledisk version (1 byte) 3
|
||
3.5 Data rate (1 byte) 3
|
||
3.6 Drive type (1 byte) 3
|
||
3.7 Stepping (1 byte) 3
|
||
3.8 DOS allocation flag (1 byte) 4
|
||
3.9 Sides (1 byte) 4
|
||
3.10 Cyclic Redundancy Check (2 bytes) 4
|
||
|
||
4. Comment Header / Data block 4
|
||
|
||
4.1 Cyclic Redundancy Check (2 bytes) 4
|
||
4.2 Data length (2 bytes) 4
|
||
4.3 Year (1 byte) 5
|
||
4.4 Month (1 byte) 5
|
||
4.5 Day (1 byte) 5
|
||
4.6 Hour, Minite, Second (1 byte each) 5
|
||
4.7 Comment data block (variable size) 5
|
||
|
||
5. Track Header 6
|
||
|
||
5.1 Number of sectors (1 byte) 6
|
||
5.2 Cylinder number (1 byte) 6
|
||
5.3 Side/Head number (1 byte) 6
|
||
5.4 Cyclic Redundancy Check (1 byte) 6
|
||
|
||
6. Sector Header 7
|
||
|
||
6.1 Cylinder number (1 byte) 7
|
||
6.2 Side/Head (1 byte) 7
|
||
6.3 Sector number (1 byte) 7
|
||
6.4 Sector size (1 byte) 8
|
||
6.5 Flags 8
|
||
6.6 Cyclic Redundancy Check (1 byte) 8
|
||
|
||
7. Sector Data Header 9
|
||
|
||
Teledisk .TD0 notes Table of Contents
|
||
|
||
Page
|
||
7.1 Data block size (2 bytes) 9
|
||
7.2 Encoding method (1 byte) 9
|
||
Teledisk .TD0 notes Page: 1
|
||
|
||
|
||
1. Introduction
|
||
|
||
Teledisk is a program which reads non-PC format diskettes into image
|
||
files for archival and can later recreate a copy of the original disk
|
||
from the image file. Once popular for archival of classic computer
|
||
software, Teledisk has been withdrawn from the market by it's
|
||
manufacturer and is no longer legally available. This presents a
|
||
problem for those people who have data archived with Teledisk,
|
||
because the file format is proprietary and not documented rendering
|
||
the data useless without the program.
|
||
|
||
In my development of ImageDisk (a replacement for Teledisk), I have
|
||
created a utility to convert Teledisk .TD0 images into ImageDisk .IMD
|
||
format - in doing so, I have researched the Teledisk format, read
|
||
other peoples notes, done some reverse engineering myself, and come
|
||
to what I believe is a somewhat complete understanding of the
|
||
contents of a .TD0 image file.
|
||
|
||
This document presents my notes on the Teledisk .TD0 image file
|
||
format.
|
||
|
||
This document is a work in progress. If you have any information to
|
||
add, corrections etc. Please contact me. I can be reached via the
|
||
contact information on my web site.
|
||
|
||
http://www.classiccmp.org/dunfield
|
||
|
||
1.1 Acknowlegements
|
||
|
||
The following people whom I have never met have saved me tons of
|
||
time by making the results of their related efforts freely
|
||
available.
|
||
|
||
Will Krantz - Wrote a program called wteledisk which converts
|
||
TX50 .TD0 into binary files for an emulator.
|
||
Published a web page with his notes and source.
|
||
|
||
Sergey Erokhin - Provided more details for Wills web page.
|
||
|
||
Simon Owen - Published source code to read some .TD0 files
|
||
for his SimCoupe emulator.
|
||
|
||
Haruhika - Published LZSS-Huffman source code which has
|
||
Okumura become "the reference" for many implementations.
|
||
Teledisk .TD0 notes Page: 2
|
||
|
||
|
||
2. Image file Format
|
||
|
||
The overall disk image file has this format:
|
||
|
||
Image header (12 bytes)
|
||
;If the image was created using "Advanced Compression", everything
|
||
;below this line is compressed with LZSS-Huffman encoding.
|
||
Optional comment header (10 bytes)
|
||
Optional comment data (Variable size)
|
||
;For each track on the disk ...
|
||
Track header (4 bytes)
|
||
;For each sector within the track
|
||
Sector header (6 bytes)
|
||
Optional data header (3 bytes)
|
||
Optional data block (variable size)
|
||
;Image ends with Trackheader beginning with 255 (FF hex)
|
||
|
||
If the Teledisk image was generated with "Advanced Data Compression",
|
||
all parts of the file following "Image Header" are compressed as a
|
||
single block with LZSS-Huffman encoding with the string lookup buffer
|
||
preset to all spaces (ASCII 20). With "normal" compression, the
|
||
remainder of the file is not compressed/encoded (other than the
|
||
sector RLE compression).
|
||
|
||
3. Image Header
|
||
|
||
The image header describes global information about the disk image.
|
||
It is never compressed, and is laid out in the following format:
|
||
|
||
Signature (2 bytes)
|
||
Sequence (1 byte)
|
||
Checksequence (1 byte)
|
||
Teledisk version (1 byte)
|
||
Data rate (1 byte)
|
||
Drive type (1 byte)
|
||
Stepping (1 byte)
|
||
DOS allocation flag (1 byte)
|
||
Sides (1 byte)
|
||
Cyclic Redundancy Check (2 bytes)
|
||
|
||
3.1 Signature (2 bytes)
|
||
|
||
- Contains 'TD' for normal compression
|
||
|
||
- Contains 'td' for advanced compression
|
||
|
||
3.2 Sequence (1 byte)
|
||
|
||
- Early Teledisk document indicates that this begins with 00 and
|
||
increments for each member of a multi-volume set.
|
||
|
||
- TDCHECK reports "bad header" if this value is set to anything
|
||
other than 00.
|
||
Teledisk .TD0 notes Page: 3
|
||
|
||
|
||
3.3 CheckSequence (1 byte)
|
||
|
||
- Early Teledisk document indicates that this must be the same for
|
||
each member of a multi-volume set
|
||
|
||
3.4 Teledisk version (1 byte)
|
||
|
||
- Encodes the version number of the Teledisk program which created
|
||
the image in the form High-nibble.low-nibble. eg: 15 = 1.5
|
||
|
||
3.5 Data rate (1 byte)
|
||
|
||
- Encodes the data rate used for the diskette in lower 2 bits.
|
||
|
||
0 = 250kbps
|
||
1 = 300kbps
|
||
2 = 500kbps
|
||
|
||
- High bit indicates single-density diskette (I believe this is for
|
||
older versions only which did not support mixed density disks).
|
||
|
||
3.6 Drive type (1 byte)
|
||
|
||
- Indicates the type of drive the disk was made on.
|
||
|
||
- Early Teledisk document indicates the encoding is:
|
||
|
||
1 = 360k
|
||
2 = 1.2M
|
||
3 = 720k
|
||
4 = 1.44M
|
||
|
||
- Experimentation with TDCHECK indicates that the text generated
|
||
from the various encoding is:
|
||
|
||
0 = 5.25 96 tpi disk in 48 tpi drive
|
||
1 = 5.25
|
||
2 = 5.25 48-tpi
|
||
3 = 3.5
|
||
4 = 3.5
|
||
5 = 8-inch
|
||
6 = 3.5
|
||
|
||
- Use Data rate to determine appropriate drive density.
|
||
|
||
3.7 Stepping (1 byte)
|
||
|
||
- Encodes step type in lower 2 bits
|
||
|
||
0 = Single-Step
|
||
1 = Double-step
|
||
2 = Even-only step (96 tpi disk in 48 tpi drive)
|
||
|
||
- High bit indicates presence of optional comment block
|
||
Teledisk .TD0 notes Page: 4
|
||
|
||
|
||
3.8 DOS allocation flag (1 byte)
|
||
|
||
- non-zero means the disk was read using the DOS FAT table to skip
|
||
unallocted sectors.
|
||
|
||
3.9 Sides (1 byte)
|
||
|
||
- Encodes the number of sides read from the disk.
|
||
|
||
01 = One
|
||
anything-else = Two
|
||
|
||
3.10 Cyclic Redundancy Check (2 bytes)
|
||
|
||
This field contains the error-checking cyclic redundancy check for
|
||
the header calculated with the polynomial value 41111 (A097 hex)
|
||
using an input preset value of 0. The CRC is calculated over the
|
||
first 10 bytes of the header, and should match the value stored in
|
||
this field.
|
||
|
||
4. Comment Header / Data block
|
||
|
||
The comment block encodes an ASCII comment as well as the creation
|
||
date. It's presence is indicated by the high bit of the "Stepping"
|
||
field in the image header being set.
|
||
|
||
When present, it occurs immediately after the Image header in the
|
||
following format:
|
||
|
||
Cyclic Redundancy Check (2 bytes)
|
||
Data length (2 bytes)
|
||
Year since 1900 (1 byte)
|
||
Month (1 byte)
|
||
Day (1 byte)
|
||
Hour (1 byte)
|
||
Minite (1 byte)
|
||
Second (1 byte)
|
||
|
||
Following the comment header are comment line records, consisting of
|
||
ASCII text terminated by NUL (00) bytes.
|
||
|
||
4.1 Cyclic Redundancy Check (2 bytes)
|
||
|
||
This 16-bit field contains the error-checking cyclic redundancy
|
||
check for the header calculated with the polynomial value 41111
|
||
(A097 hex) using an input preset value of 0. The CRC is calculated
|
||
over the entire header block (beginning at offset 2 - just after
|
||
the CRC) and the data records.
|
||
|
||
4.2 Data length (2 bytes)
|
||
|
||
This is the length of the comment data block which follows the
|
||
comment header. To display the comment data, read and output this
|
||
many bytes following the header, translating NUL (00) bytes into
|
||
newline sequences.
|
||
Teledisk .TD0 notes Page: 5
|
||
|
||
|
||
4.3 Year (1 byte)
|
||
|
||
Gives the year the image was created as an offset from 1900. eg:
|
||
2007 is encoded as 2007 - 1900 = 107 (6B hex).
|
||
|
||
4.4 Month (1 byte)
|
||
|
||
Gives the month the image was created using a zero index. ie:
|
||
0=January, 11=December.
|
||
|
||
4.5 Day (1 byte)
|
||
|
||
Gives the day (of the month) the image was created using a range
|
||
of 1-31.
|
||
|
||
4.6 Hour, Minite, Second (1 byte each)
|
||
|
||
Gives the time of day the image was created using 24-hour time.
|
||
|
||
4.7 Comment data block (variable size)
|
||
|
||
Contains the ASCII text of the comment as NUL (00) terminated
|
||
lines. The size of this block is given by "Data length" in the
|
||
comment header. To display the comment, read and output "Data
|
||
length bytes" from this block, translating NUL (00) bytes into
|
||
newline sequences.
|
||
Teledisk .TD0 notes Page: 6
|
||
|
||
|
||
5. Track Header
|
||
|
||
Every disk track recorded in the image will begin with a track
|
||
header, which has the following format:
|
||
|
||
Number of sectors (1 byte)
|
||
Cylinder number (1 byte)
|
||
Side/Head number (1 byte)
|
||
Cyclic Redundancy Check (1 byte)
|
||
|
||
5.1 Number of sectors (1 byte)
|
||
|
||
This field indicates how many sectors are recorded for this track.
|
||
This also indicates how many sector headers to expect following
|
||
the track header.
|
||
|
||
A number of sectors of 255 (FF hex) indicates the end of the track
|
||
list. No other fields occur in this record, and the CRC is not
|
||
checked.
|
||
|
||
5.2 Cylinder number (1 byte)
|
||
|
||
This field encodes the physical cylinder number (head position)
|
||
for this track, in a range of 0-(#tracks on drive-1).
|
||
|
||
5.3 Side/Head number (1 byte)
|
||
|
||
This field encodes the disk side (0 or 1) that this track occurs
|
||
on in it's lower bit.
|
||
|
||
The high bit of this field is used to indicate the track was
|
||
recorded in single-density. This allows mixed-density disks to be
|
||
represented (FM on some tracks, and MFM on others).
|
||
|
||
FM disks that I recorded had this bit set for every track, and NOT
|
||
the FM indicator in bit 7 of the "Data rate" field of the image
|
||
header. I cannot confirm this, but I suspect that early versions
|
||
of Teledisk did not support mixed density disks, using only the FM
|
||
bit in the image header. If this is the case, then a track should
|
||
be interpreted as single density if either of the two FM indicator
|
||
bits are set.
|
||
|
||
5.4 Cyclic Redundancy Check (1 byte)
|
||
|
||
This 8-bit field contains the lower byte of a 16-bit
|
||
error-checking cyclic redundancy check for the header calculated
|
||
with the polynomial value 41111 (A097 hex) using an input preset
|
||
value of 0. The CRC is calculated over the first three bytes of
|
||
the header and should match the forth byte.
|
||
|
||
Track headers and sector block lists occur until all tracks on the
|
||
disk have been accounted for. When the last track record and sector
|
||
block list has been read, a 255 (FF hex) byte indicates the end of
|
||
the image.
|
||
Teledisk .TD0 notes Page: 7
|
||
|
||
|
||
6. Sector Header
|
||
|
||
Following the Track header will be a number of sector blocks
|
||
consisting of a sector header and optional data header/data block.
|
||
The number of sector blocks is indicated by the "Number of sectors"
|
||
field in the track header.
|
||
|
||
Each sector header has the following format:
|
||
|
||
Cylinder number (1 byte)
|
||
Side/Head (1 byte)
|
||
Sector number (1 byte)
|
||
Sector size (1 byte)
|
||
Flags (1 byte)
|
||
Cyclic Redundancy Check (1 byte)
|
||
|
||
6.1 Cylinder number (1 byte)
|
||
|
||
This field indicates the logical cylinder number which is written
|
||
in the ID field of the disk sector. For most disk formats it
|
||
matches the Cylinder number indicated in the track header, however
|
||
this does NOT have to be the case - some formats encode
|
||
non-physical cylinder numbers.
|
||
|
||
6.2 Side/Head (1 byte)
|
||
|
||
This field indicates the logical Side/Head indicator which is
|
||
written in the ID field of the disk sector. For most disk formats
|
||
it matches the Side/Head number indicated in the track header,
|
||
however this does NOT have to be the case - some formats encode
|
||
non-physical Side/Head numbers.
|
||
|
||
6.3 Sector number (1 byte)
|
||
|
||
This field indicates the logical sector number which is wrtten in
|
||
the ID field of the disk sector. Sector numbers do not have to be
|
||
in any particular order (the ordering of the sectors determines
|
||
the interleave factor of the track), do not necessarily begin at 0
|
||
or 1, and are not necessarily an unbroken series of numbers. Some
|
||
formats encode seemingly arbitrary sector numbers.
|
||
|
||
Teledisk sometimes creates bogus sectors headers to describe data
|
||
that is not in a properly formatted sector. These extra sectors
|
||
appear to be created with sector numbers begining at 100.
|
||
Teledisk .TD0 notes Page: 8
|
||
|
||
|
||
6.4 Sector size (1 byte)
|
||
|
||
Indicates the size of the sector, according to the following
|
||
table:
|
||
|
||
0 = 128 bytes 4 = 2048 bytes
|
||
1 = 256 bytes 5 = 4096 bytes
|
||
2 = 512 bytes 6 = 8192 bytes
|
||
3 = 1024 bytes
|
||
|
||
Note that disk formats exist which have different sector sizes
|
||
within the same track, and Teledisk will encode them this way,
|
||
however the PC 765 floppy disk controller cannot format such
|
||
tracks, and the disk can not be recreated.
|
||
|
||
6.5 Flags
|
||
|
||
This is a bit field indicating characteristics that Teledisk noted
|
||
about the sector when it was recorded. The field contain the
|
||
logical OR of the following byte values:
|
||
|
||
01 = Sector was duplicated within a track
|
||
02 = Sector was read with a CRC error
|
||
04 = Sector has a "deleted-data" address mark
|
||
10 = Sector data was skipped based on DOS allocation [note]
|
||
20 = Sector had an ID field but not data [note]
|
||
40 = Sector had data but no ID field (bogus header)
|
||
|
||
note: Bit values 20 or 10 indicate that NO SECTOR DATA BLOCK
|
||
FOLLOWS.
|
||
|
||
The meaning of some of these bits was taken from early Teledisk
|
||
documentation, and may not be accurate - For example, I've seen
|
||
images where sectors were duplicated within a track and the 01 bit
|
||
was NOT set.
|
||
|
||
6.6 Cyclic Redundancy Check (1 byte)
|
||
|
||
This 8-bit field contains the lower byte of a 16-bit
|
||
error-checking cyclic redundancy check for the sector header, data
|
||
header and sector data calculated with the polynomial value 41111
|
||
(A097 hex) using an input preset value of 0. The CRC is calculated
|
||
over the first five bytes of the sector header, the entire sector
|
||
data header and the sector data block. The calculated CRC should
|
||
match the value stored in the fourth byte of the sector header.
|
||
Teledisk .TD0 notes Page: 9
|
||
|
||
|
||
7. Sector Data Header
|
||
|
||
The sector data header occurs following the sector header only when
|
||
sector data is present. This is indicated by bits 10 and 20 of the
|
||
Flags value NOT being set. When present it has the following format:
|
||
|
||
Data block size (2 bytes)
|
||
Encoding method (1 byte)
|
||
|
||
7.1 Data block size (2 bytes)
|
||
|
||
This indicates the size of the sector data block, including the
|
||
encoding method (ie: data block size + 1).
|
||
|
||
7.2 Encoding method (1 byte)
|
||
|
||
This field describes how the sector data is encoded. It can have
|
||
three possible values:
|
||
|
||
7.2.1 0 - Raw sector data
|
||
|
||
Encoding method == 0 indicates that "sector size" bytes of raw
|
||
sector data follow. This is the actual data content for the
|
||
sector.
|
||
|
||
7.2.2 1 - Repeated 2-byte pattern
|
||
|
||
Encoding method == 1 indicates that a repeated 2-byte pattern
|
||
is used. Note that this may occur multiple times until the
|
||
entire sector has been recreated, as determined by "sector
|
||
size" in the sector header.
|
||
|
||
Each entry consits of two 16-bit values. The first is a count
|
||
value indicating how many times the second (the data value) is
|
||
repeated.
|
||
|
||
7.2.3 2 - Run Length Encoded data
|
||
|
||
Encoding == 2 indicates that an RLE data block occurs. Note
|
||
that this may occur multiple times until the entire sector has
|
||
been recreated, as determined by "sector size" in the sector
|
||
header.
|
||
|
||
Each entry begins with a 1 byte length value or 00.
|
||
|
||
If 00, then this entry is for a literal block. The next byte
|
||
indicates a length 'n', and the following 'n' bytes are copied
|
||
into the sector data as raw bytes (similar to Encoding
|
||
method==0 except for only a portion of the sector).
|
||
|
||
If not 00, then the length 'l' is determined as the value * 2
|
||
(ie: 2-510). The next byte indicates a repeat count 'r'. A
|
||
block of 'l' bytes is then read once from the file, and
|
||
repeated in the sector data 'r' times.
|
||
|
||
Sector headers and data blocks occur until all sectors for the
|
||
track have been accounted for.
|