QXL.WIN 

What does a sector dump actually look like and how exactly is the data stored on a microdrive cartridge?

<< - Back to homepage (opens in this tab/window).

The Basics

Computers only understand highs and lows (1's and 0's), AKA binary. Microdrive cartridges contain magnetic representations of highs (1) or lows (0) and these highs and lows (plus carefully positioned gaps) whizz past the microdrive's stereo read/write head and are interpreted into data that can be understood by the QL.

Eight binary highs/lows make up an eight bit byte, e.g. 01110110, which is 118 in decimal. To make things a bit easier for humans, bytes are usually converted to and written in hexadecimal, as that form of counting can represent every eight bit byte with just two characters in the hexadecimal range of 00 to FF (00000000 to 11111111 in binary, or 0 to 255 in normal decimal 'every day' counting). Written hex numbers are often prefixed by a dollar sign, a 0x or sometimes suffixed by a lower-case h, e.g. $0E, 0x0E or 0Eh.

The continuous loop of tape within a microdrive cartridge is divided into sectors when the cartridge is formatted - this lays out the template that any data saved to the cartridge should follow.

When you format a microdrive cartridge you'll see afterwards that the QL reports the number of good sectors that were achieved. This number of sectors is always a little different, as it depends on the precise length of tape within the cartridge and on the number of sectors that were found to be bad (i.e. not reliable). Formatting is deemed unacceptable and will fail if the cartridge formats with less than 200 good sectors, so you'll never see lower than 200. In my experience, with my equipment, cartridges with around 215 good sectors and less than 8 bad sectors seem to be the most reliable.

Format complete message

There are always two special areas of each cartridge, one is the first sector, numbered $00, which contains the sector map (more on that later) and the other special area is the directory, which is always file number $00 and can take up multiple data blocks (if the directory contains a lot of file names). All other files saved onto the cartridge are numbered from $01 onwards and the files are numbered in the order in which they are saved onto the cartridge.

The Structure of a Cartridge Dump

All of the normal sectors on the cartridge contain a 512 byte data block, plus a sector number, a random number (which is the same for every sector on the cartridge), a file number or flag, a block number, the cartridge name (which is also the same for every sector) and a checksum, which should always add up to the total of the bytes within the data block.

In total each sector represented in an mdump .mdv file is 530 bytes in length (18b in total for the name, flags, numbers and checksum etc, plus the 512b data block), so what I do when examining an mdump_task file is, using a hex editor like HxD, set the bytes per row to 530, that way everything is organised in easier to read columns.

HxD screenshot showing organised columns

Note that there are other mdv cartridge file formats, all have an .mdv extension but are internally different. As I primarily deal with dumps of original cartridges, the info on this page relates to .mdv files created with the mdump_task program on a QL using the JS ROM. Note also that the actual data on the tape is not exactly the same as how it is represented in an mdump .mdv file.

The mdump_task program adds its own 46 byte header (bytes $00 to $2D) to the raw .mdv dump data. After that follows sector $00 (which contains the sector map). Sectors then follow in descending order, from the highest that the tape length allows (e.g. $D9 for 217 sectors) all the way down to $01 at the bottom. After sector $01 mdump_task does sometimes save alternate copies of bad sectors.

So, after the 46 byte mdump header there are rows of similar 530 byte patterns. Here's an example of one such sector row, this one has no data in its data block:

Byte No. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... ... 29 30
  FF D9 62 6C 61 6E 6B 20 20 20 20 20 3E 70 FD 00 AA 55 AA 55 AA 55 AA 55     0E 0F

Byte 1 is always an $FF.
Byte 2 is the sector number, in this case $D9 or 217 in decimal.
Bytes 3 to 12 are the cartridge name assigned to it when it was formatted - in the example above the name $62 $6C $61 $6E $6B is the word 'blank', which is then padded out with 5 spaces (5x $20 in hex).
Bytes 13 and 14 ($3E $70) are randomly assigned to the cartridge when it is formatted and these 13th and 14th bytes are always identical for every sector of a given cartridge.
Byte 15 is the number of the file that is contained (or partly contained) within the data block of the sector, or it's a flag. When the sector contains no data, this is always the flag $FD.
Byte 16 is the number of the block of data of the file contained within the sectors' data block, or if there is no data contained within the block (as with the example above) then this byte is $00.
Bytes 17 all the way to byte 528 are the data block, which for empty sectors which always alternates $AA and $55.
Then right at the end, the last 2 bytes of a sector are always the checksum.

Here's another example of a sector which does contain data:

Byte No. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... ... 29 30
  FF BC 4E 45 4D 45 53 49 53 5F 32 20 1C 92 03 1B 6E 2E 22 3A 66 25 28 31     58 FF

It starts with $FF, as usual. It is sector number $BC, which is 188 in decimal. There is a 9 character name, followed by a padding space ($20). All of the sectors on the cartridge have the random number $1C $92. Byte 15 shows that its data block contains (part of) file $03 - in fact in byte 16 you can see that it contains part $1B, or part 27 in decimal (actually the 28th part, because 0 counts!) of file $03. Then follows the actual data and right at the end is the 2 byte checksum.

How are files actually saved?

Files are not saved within data blocks of consecutive sectors, instead, they are spread out evenly across the tape. The sector map contains the info that tells the QL where the various parts of a file can be found. Small files that are less than 512b in size will only take up one data block of one sector and the data is always padded out at the end to use the full 512b data block space.

Larger files that take up multiple data blocks obviously have to be spread over 2 or more (non consecutive) sectors, so for example, a file that is the first file saved onto a cartridge (and is therefore file $01 - remember file $00 is always the directory) that is 1,400 bytes in size will live in a total of 3 sectors. These sectors will have the following pairs of 15th and 16th bytes: $01 $00, $01 $01 and $01 $02 - that's $01 for file number 1 and then its three blocks $00, $01 and $02. As the file is smaller than 3x 512b, the last part of the data block that contains part $02 of the file will be padded out.

The sector map

The sector map tells the QL where to find the parts of each file. As mentioned above, the sector map is always sector $00. Here is an example of the beginning of a sector map:

Byte No. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
  FF 00 71 75 65 73 74 69 6F 6E 73 20 08 31 80 00 F8 00 05 07 04 04 03 01 FD 00 FD 00 FD 00 12 08 0B 03

Byte 1, as usual, is $FF.
Byte 2 is the sector number, $00 for the sector map.
Bytes 3 to 12 are the cartridge name with, in this example, one padding space ($20) at the end.
Bytes 13 and 14 are the random number.
Byte 15 is $80, which I believe is a flag to indicate the sector map.
Byte 16 is $00, the block number - the sector map is always $00 and always only one block long.
Sector mapping starts at byte 17. First, the sector map gives its own position, thus
Byte 17 is the designated file number for the sector map. It is always $F8.
Byte 18 is the block number for the sector map, always $00.

From byte 20 all the way to the end of the sector (where there are 2 checksum bytes as usual) there are pairs of file and block numbers, in total 255 pairs. Their position in the sector map represents their position on the tape, so the first pair represents sector $01, and being $05 $07 in the example above, it tells the QL that part $07 of file $05 is held within the data block of sector $01. Remember that sector $01 is at bottom of the file, as mdump_task dumps start with sector $00 (the sector map) and then descend from the highest sector number to the lowest.

The next (2nd relevant) pair of numbers in the example above tells the QL that its sector - $02 - contains part $04 of file $04. The next pair represents sector $03 and within that sector is the $01 part of file $03.

A file number with the flag $FD and block number $00 indicates that the block is empty, and you can see three empty sectors on the example above. These empty sectors correspond to sectors $04, $05 and $06. Another flag used in the sector map is $FF (and block $00) - where this appears indicates that the corresponding sector has been marked as bad by the formatting process and it will not be used to store data.

A note on file headers

At the beginning of each file, i.e. at the start of its first ($00) block, is always a 64 byte header before the actual data begins. This header contains information such as the file length, type and its name. It also contains space for the file save date, but this extra info was not implemented within the original QL ROMs.

Checksums

The checksums at the end of each data block are made up of the total of each byte in the block, plus $0F0F. For blank data blocks, that is always $0E0F. Actual cartridges also have two other checksums - one after the sector header and one after the block header, but these are not saved as part of the mdump_task dump file.
 

<< - Back to homepage (opens in this tab/window).