I support DMK in my MSX emulator, and bear in mind that it's a bit of a confused file format. It has a bunch of design deficiencies, and was clearly tightly coupled to the program that originally implemented it. But starting with the perfectly sensible stuff:
The first 16 bytes are the header, which you seem to be familiar with — write protection, geometry, track size, etc.
From there on are a bunch of track images. Each track image is the length you got from the header, and they're interleaved by side. So you can find track t
on side s
of a q
-sided disk (i.e. 1-sided or 2-sided) with track lengths of n
at file offset:
(t*q + s)*n + 16
i.e. immediately after the 16-byte header, on a double-sided disk, you'll see the track image for side 0, track 0. Then you'll see side 1, track 0. Then side 0, track 1; side 1, track 1; side 0, track 2, etc, etc.
The first 128 bytes of each track image are a list of IDAM pointers and single/double density flags. So the first 128 bytes of each track image aren't actually on the original floppy disk, they're just part of this file format.
As you note, an IDAM is an ID Address Mark. This relates to how floppy disks work — they're always spinning and a floppy controller just receives an incoming stream of data bits. Having stepped to the track it wants, to read a given sector the controller then has to sit and wait until that particular sector goes past.
How does it tell where the sectors begin? Through the presence of an IDAM. Standard IBM System 34 disk encoding as used by most computers is an ID Address Mark, then an address ending with a CRC, then a gap, then a data (or deleted data) mark, then sector data and another CRC, then another gap to the next IDAM.
This is where DMK starts to go off the rails a little:
Obviously repeating every byte twice for single-density disks is a complete fiction, likely invented so that the one-size-for-all-tracks model worked. When dealing with sectors marked as single-density, just discard every other byte from the original file.
On a real disk, address and data marks are specially-crafted so as to be unambiguous, by dropping a clock bit. This file format doesn't attempt to preserve that. Instead it tells you where the address marks are in a separate table. It doesn't tell you anything about where the data marks are. You have to make an educated guess.
The file format also records FM and MFM marks as looking the same. This is likely a misunderstanding of the author based on the control commands a WD1770 accepts. But:
- where an IDAM is recorded, you should see an
0xfe
in the track image;
- there'll then be a standard address — one byte track address, one byte side number, one byte sector number, one byte length (log 2, minus seven*), then two bytes of CRC;
- some number of gap bytes will follow;
- eventually you'll see either a
0xfb
or 0xf8
. That's your data mark. 0xfb
is regular data, 0xf8
is deleted data. I don't know about the specifics of the TRS-80 but it's very common not to use the deleted data mark as it's not that useful if you have an actual filing system;
- the contents of the sector are then the number of bytes after that corresponding to the sector size, followed by another two bytes for the CRC.
* i.e. if the byte value stored for sector length is m
then the sector is 1 << (m + 7)
bytes long. Or 128 << m
if you prefer — if m
is 0 then the sector is 128 bytes long, if m
is 1
then the sector is 256 bytes long, etc.
So now you've got an algorithm for transcribing a DMK track back into an actual floppy disk:
- skip to track location;
- read IDAM table;
- move to the end of the IDAM table;
- output all bytes from there until the first indicated IDAM;
- discard the byte at the IDAM and write an actual IDAM;
- output the next six bytes, forming the address mark;
- keep outputting whatever you find until you see a
0xfb
or 0xf8
. Remember to throw away every other byte if this is flagged as a single-density sector;
- throw away the
0xfb
or 0xf8
and write a data or deleted data mark;
- output every following byte (or every other re: single density) for the declared length of the sector plus its CRC;
- return to step 4, now with an eye on the next IDAM; or
- if there is no next IDAM, just write out all remaining bytes until the end of the track.
Supposing you're interested in a tool just to extract a particular sector, you can jump to the appropriate track, check out the IDAM table, use it to look up all the address marks, check those addresses for the sector you're looking for and then search forward for the associated data if you find it.
That's why you're seeing stuff like directory contents at different locations in different DMKs. Within a track the sectors can come in any order. Even when they come in the same order, they can be rotated arbitrarily since this file format is not rigorous as to the location of the index hole. E.g. if a real floppy disk had sectors tagged as 1, 2, 3, 9, 5
then it is technically valid to encode that as a DMK as sectors in the order 1, 2, 3, 9, 5
or 2, 3, 9, 5, 1
or 3, 9, 5, 1, 2
or the other two rotations of that.
(Aside: it might be that the author intended the index hole always to be at the start of a track image, but the specification doesn't say that so your mileage may vary.)