QDOS Internals

Anything you never knew you wanted to know about the Sinclair QL.

User Tools

Site Tools


QL ED Floppy Discs

This section gives some information on QL ED floppy discs

This section only covers the 3.2 Mb DS/ED floppy discs known as QL5A and QL5B There is a page dedicated to the DS/DD and DS/HD floppies elsewhere.

There will be a section added, at some point, describing these enhanced discs.

The Disc Map

The very first sector of an ED disc holds the first map sector. A sector is 2,048 bytes in length, unlike the other floppy formats which have 512 byte sectors.

Sector 1 of the map contains 96 bytes of disc information as follows :

ByteSizeDescription (Byte & size are in HEX)
0004Header flag QL5B. (Same as DS/HD)
040AMedium name space padded.
0E02Format random number.
1004Update counter for this disc.
1402Free sector count.
1602Good sector count. Normally 1,600
1802Total sector count. Normally 1,600
1A02Number of sectors per track, 10.
1C02Number of sectors per cylinder, 10 (Single sided) or 20 (Double sided).
1E02Number of tracks per disc, 80.
2002Number of sectors per block, 1.
2202Block number of the directory end of file. Zero on a freshly formatted floppy.
2402Byte in block of directory end of file. 64 on a freshly formatted floppy.
2602Sector offset per track, 2 (Same as DS/HD).
2814Logical → physical translation table.
3C24Spare bytes, currently unused.

The format random number is used to detect when the disc has been swapped.

The update counter is used to detect when the disc has been removed, put into another drive, updated & then returned to the original drive.

The sector offset is used to allow for some sectors passing under the heads when the drive has to step from the current track to the next one.

The remaining 1,952 bytes make up the first part of the map for this disc. The map consists of three full allocation blocks (aka 3 sectors of 2,048 bytes each as an allocation block is one sector in the DS/ED format) and can hold up to 1,600 entries although there is enough room for 2,016 potential entries in the map - these are the allocation units.

Each allocation unit is 24 bits in length, the first 12 bits hold the file number on the disc, the last 12 bits hold the block number within the file (starting at 0) as follows :

The allocation unit details are stored sequentially in the map. Allocation unit 0 is the first one and 1,599 is the last one. Allocation units 0, 1 and 2 refer to the map itself, which has file number $F80.

Allocation unit 4 is the root directory, which has file number zero.

There are other values used by the QL for its own internal workings, these are held in the first 12 bits only and the last 12 bits are ignored.

  • Blocks pending a deletion are held as file number $FCx.
  • Free blocks are held as file number $FDx.
  • Bad blocks are held as file number $FEx.
  • Blocks that do not exist are held as file number $FFx.

Note: the lower 4 bits of the file number are not used for the last 3 of these and may be undefined. My own experience shows that they are probably $F.

An allocation block which has a file number between $001 and $F7F will belong to a user file, although a DS/ED disc can only have 1,600 files on it as an absolute maximum, so you are highly unlikely to see file numbers above $640.

The sectors making up the map are as follows:

QL5B (DS/ED) Map Sectors

|0       95|96            2047|2048                      4095|4096                     6143|
| Header   | Map (1600 entries)                                               | Unused     |
| 96 Bytes | 1952 bytes       | 2,048 bytes                  | 800 bytes      | 1248 bytes |
| Sector 0                    | Sectors 1                    | Sector 2                    |

A DS/ED disc has 1,600 map entries (three bytes each) plus a 96 byte header making three 2,048 byte sectors in all but with the final 1,248 bytes of the last sector unused. The map is therefore 96 bytes for the header plus 1,600 * 3 = 4,800 bytes for map entries giving a total of 5,076 bytes used out of 6,144. The final 1,248 bytes are unused.

It should hopefully be obvious that 'number of sides' * 'sectors per track' * 'number of tracks' should be the total number of allocation units on the disc.

Converting A Map Allocation Unit To A Disc Address

The allocation unit number must be in range 0 to 1,599.

The TRACK number is the UNIT DIV 'sectors per cylinder'.
The LOGICAL BLOCK number is the UNIT MOD 'sectors per cylinder'.

This gives TRACK from 0 to 'number of tracks' -1, and LOGICAL BLOCK within TRACK as 0 to 'sectors per cylinder' -1.

The offset into the Logical → Physical table for this logical block is:

(logical block * 'sectors per block') + 1

assuming you are in SuperBASIC and count from 1 otherwise lose the 1.

The sector number for this logical block is the byte at offset 0 from the calculated offset into the Logical → Physical table.

Now for each sector number, if it is greater or equal to 128, then the side is 1 and the adjusted sector = sector - 128, otherwise the side is 0.

This is fine if we are still on track 0, however, as mentioned above, there is a track offset to be taken into account as follows :

(adjusted sector + (TRACK * 'track offset')) MOD 'sectors per track'

this gives a 0 to 'sectors per track' -1 result, in SuperBASIC you would need to add 1 to get a true sector number of 1 to 9. In Assembly or C code, this is not required.

Now you have a SIDE, TRACK and the sectors for this allocation unit. Easy.


Allocation unit 423:

TRACK     = 423 DIV 20 ===> 21.
BLOCK     = 423 MOD 20 ===>  3.
LP_OFFSET = (BLOCK * 1) + 1 ===> 4.

Assume that the LP table has byte $06 at LP_OFFSET:

LP_OFFSET byte = $06
SIDE = 0

As above, the sector offset is 2 (normally)

So the actual sector on track 21 of side 0 is:

(6 + (21 * 2)) MOD 10) ====> 8

Therefore, the sector of the disc that are used by the file are located at


The file in question is of course unknown, but if you take the 24 bits held in the 3 characters of the map that relate to this allocation unit and convert them into hex, you will get something like $007002 which means that the actual file number is 7 and the block within the file is 2.

Finding The File In The Directory

If the file number is not a 'special' as listed above, then the file name is found as follows :

DIR_OFFSET = (File number - 1) * 64

it appears that there is no way to access the directories own information from the directory, hence the minus 1.

The next 64 bytes of the directory hold all the information for that file, including its name, dataspace, type etc etc.

The first 64 bytes of each files very first sector contain a copy of the file header, this is never ever ever updated by the QL, so is of no use at all. All it does is waste 64 bytes per file and eventually, as the disc gets used and files deleted with others saved, these 64 bytes seem to contain what ever data was on the disc when the file was written to the sector.

Deleted Files In The Map

When a file gets deleted, its map entries have the first byte set to $FD, the other information in the map does not seem to be affected. This is slightly unfortunate as it means that an UNDELETE program could not be entirely successful as there could be more than one file in the map which had been deleted from the disc.

qdosmsq/fs/dsed.txt · Last modified: 2018/11/05 12:25 by norman