Acorn Disk File System
Categories:
Physical format
Acorn DFS is a single sided, single density 40 or 80 track format. A double sided disc can hold two DFS volumes. Each track carries ten 256 byte sectors numbered from 0 to 9.
Sector ID's
Each sector is given an ID at format time; the parameters of the ID, listed below, are used by the DFS and the floppy disc controller to address sectors.
- C, the cylinder number ranges from 0 on the outermost track to 39 or 79 on the innermost track.
-
H, the head number = 0.
Acorn DFS ignores this after formatting.
Some DFS formatters set it to 1 on the upper surface of the disc (corresponding to drives 2 or 3.) -
R, the record number runs sequentially from 0 to 9 within each track.
There is a standard track skew of 3; that is, the sectors having R = 0 are the first sector of the first track, the fourth sector of the second track, the seventh of the third, the tenth of the fourth, and so on. - N, the record length = 1, showing that the sector length is 27 + 1, or 256 bytes.
All these parameters can potentially take any value between 0 and 255, and so confuse Acorn DFS and some non-standard controllers. Some copy protection schemes make use of this feature.
Catalog
The catalog is located in sectors 0 & 1 on Track 0. It is capable of holding just 31 entries.
Formatting a disk on the real hardware only needs to write to these two sectors (via `*FORM40` or `*FORM80`) but a blank catalogue simply needs these two sectors blanked and the disk size field initialised.
Catalog format
This is the structure of the catalogue header:
Byte | Track 0 Sector 0 | Track 0 Sector 1 | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
0 | First 8 characters of volume title padded with NULs or spaces | Last 4 characters of volume title padded with NULs or spaces | |||||||||||||||
1 | |||||||||||||||||
2 | |||||||||||||||||
3 | |||||||||||||||||
4 | BCD catalogue cycle number | ||||||||||||||||
5 | Number of files | ||||||||||||||||
6 | Boot Opts | Disk Type | 98 | ||||||||||||||
7 | 7 | Sectors in volume | 0 | ||||||||||||||
8 | File name padded with spaces | 7 | Load address | 0 | Last file | ||||||||||||
9 | 15 | 8 | |||||||||||||||
10 | 7 | Execution address | 0 | ||||||||||||||
11 | 15 | 8 | |||||||||||||||
12 | 7 | File length | 0 | ||||||||||||||
13 | 15 | 8 | |||||||||||||||
14 | 17 16 Exec | 17 16 | 17 16 Load | 9 8 | |||||||||||||
15 | Lk. | Directory | 7 | Start sector | 0 | ||||||||||||
16 | File name padded with spaces | 7 | Load address | 0 | Second to last file | ||||||||||||
17 | 15 | 8 | |||||||||||||||
18 | 7 | Execution address | 0 | ||||||||||||||
19 | 15 | 8 | |||||||||||||||
20 | 7 | File length | 0 | ||||||||||||||
21 | 15 | 8 | |||||||||||||||
22 | 17 16 Exec | 17 16 | 17 16 Load | 9 8 | |||||||||||||
23 | Lk. | Directory | 7 | Start sector | 0 | ||||||||||||
All unused bits must be kept clear.
Disc title
Up to 12 printable ASCII characters, padded with NULs (&00) or spaces. The first eight characters are placed in sector 0 bytes 0 to 7, the last four characters in sector 1 bytes 0 to 3.
Cycle number
A binary-coded decimal (BCD) value where each hex nibble takes a value from 0 to 9. This starts at &00 and is incremented each time the catalogue is rewritten.
It provides a simple version control system and allows applications to confirm that their internal copies of the catalogue are up-to-date.
Number of files
The number of files counter is stored in sector 1 byte 5 as bits 3…7.
Bits 0…2 are 0 making the entire byte the offset to the last valid entry in the catalog.
There may be up to 31 files on the disc.
Boot option
Selects the action to be taken when the disc is booted. The field uses two bits of byte 6 in sector 1:
Bit 5 | Bit 4 | Action |
---|---|---|
0 | 0 | No action |
0 | 1 | *LOAD $.!BOOT |
1 | 0 | *RUN $.!BOOT |
1 | 1 | *EXEC $.!BOOT |
Disk Type
Unused in standard DFS, these two bits in byte 6 of sector 1 can be used to detect third party versions of DFS:
Bit 3 | Bit 2 | File System |
---|---|---|
0 | 0 | Acorn DFS or Watford DFS up to 256K |
0 | 1 | Watford DFS larger than 256K |
1 | 0 | Duggan HDFS, single sided disk |
1 | 1 | Duggan HDFS, double sided disk |
Disc size
The total number of sectors on this side of the disc. This is a 10-bit field with the low 8 bits in sector 1 byte 7, and the others in the low two bits of sector 1 byte 6.
File descriptor fields
There is room for 31 file entries in the catalogue. Each entry takes up eight bytes in each of the two catalogue sectors.
Files must be listed in descending order of start sector with no gaps in the catalogue. Empty files should be given a start sector of 2. Files cannot be fragmented but there may be free sectors between files.
The rest of each sector represents the files. Each file is represented by a block of 8 bytes in each sector offset by 8. So the last file starts at offset 8, second to last at 16 & so on.
File name
One to seven valid file name characters stored in sector 0 bytes 8 to 14.
Valid characters are the printable ASCII characters between &20 and &7E inclusive, except . : " # * and space.
The field is padded with spaces.
Bit 7 should always be clear but are used for other file systems as extra storage, either adding a bit to another field such as WDFS or file permissions as in HDFS.
When opening a file the DFS searches for it by name.
Directory
One valid file name character stored in the low 7 bits of sector 0 byte 15 Identifies the directory (namespace) to which the file belongs.
DFS directories are like those in ADFS, DOS or Linux except they cannot nest (they are all root directories) and they share the volume catalogue.
The combination of file name and directory must be unique in the volume.
Locked Attribute
If the top bit of the directory is set, then the file is locked and may not be altered or deleted.
Load address
An 18 bit address in memory where the file should be *LOADed by default. The low 8 bits are in sector 1 byte 8; the next 8 bits in sector 1 byte 9; the top two bits are in bits 2 and 3 of sector 1 byte 14.
If the file is not meant for *LOADing (e.g. a sequential file or text) all 18 bits should be set.
Execution address
An 18 bit address in memory to be jumped to when the file is *RUN. This need not be within the bounds of the loaded file. The low 8 bits are in sector 1 byte 10; the next 8 bits in sector 1 byte 11; the top two bits are in bits 6 and 7 of sector 1 byte 14.
If the file is a sequential file or text then all 18 bits should be set.
File length
An 18 bit value giving the number of bytes in the file.
The low 8 bits are in sector 1 byte 12; the next 8 bits in sector 1 byte 13; the top two bits are in bits 4 and 5 of sector 1 byte 14.
Start sector
The 10 bit logical block address of the first sector that contains the file. The low 8 bits are in sector 1 byte 15; the top two bits are in bits 0 and 1 of sector 1 byte 14. The cylinder and record numbers are the result and remainder, respectively, when the LBA is divided by 10.
A start sector of 0 or 1 is invalid as the file would overlap the catalogue.
Note on load and execution addresses
If bits 16 and 17 of the address are both set, the address refers to I/O processor memory and OSFILE will return the address ORed with &FFFF0000 in its parameter block.
Otherwise it is an address in second processor memory and OSFILE will return the address as is.
In practice the bits are sometimes found clear when they should be set.
Identifying and validating a DFS disc image
Unlike its successor ADFS, the DFS format contains no self-identification strings or checksums, so recognising a disc or disc image as Acorn DFS is a complex and unreliable process.
If one has a floppy disc in hand it is often enough to confirm that the physical format is the same (see above) as Acorn DFS is the majority producer. On the other hand DFS disc image files are normally given the extension .ssd or .dsd, indicating a single or double sided disc image respectively.
Often the task is to identify which format variant a disc or image contains. This is more a matter of finding valid catalogues in the appropriate locations.
To check that a pair of sectors contains a valid standard DFS catalogue
- Firstly confirm that all bits marked white or cream in the above diagram are zeroes; if not, the catalogue can be rejected immediately.
- Check also that the file offset is a multiple of 8.
- The disc size must be between 2 and 800 sectors inclusive, although the format allows up to 1023 sectors, and disk images may contain up to this many.
- The disc title consists of printable ASCII characters, padded with NULs or spaces.
- For each file entry in use:
- The file name field must contain one to seven valid characters and be padded with spaces. Valid characters are the printable ASCII characters between &20 and &7E inclusive, except . : " # * and space.
- The directory character (without the attribute bit) must be a valid file name character.
- The file name (taking the directory character into account) must be unique.
- The start sector must be more than 1 and less than the disc size.
- Skipping over zero-length files:
- The start sectors must run in strictly descending order.
- No file may overlap the one before it in the catalogue. That is, start_sector_2 + ((length_2 + 255) DIV 256) ≤ start_sector_1.
- No file may overshoot the end of the disc. That is, start_sector + ((length + 255) DIV 256) ≤ disc_size. Equivalently, the first file in the catalogue must not overlap the imaginary file whose start sector field is the disc size field.
Further heuristics
Any catalogue complying with the above is a valid DFS catalogue; however, only a tiny subset of these look like catalogues seen in real life. As an informal test a pair of sectors that match many of the following is more likely to be a catalogue:
- The disc size is 400 sectors (40 tracks) or 800 sectors (80 tracks.)
- There is a file named !BOOT in directory $.
- The 16th and 17th bits of the load and execution (exec) addresses are all clear or all set in each file entry.
- There are few directories, or a few unique names in several directories.
- Most directory characters are $ (the default.)
- Some files have load addresses of the form &3nn00 (nn=0E, 11, 19, 1B, 1D, 1F or 21) and exec addresses of &3801F or &38023. (BASIC programs.)
- Some files have load and exec addresses the same, usually &xx00 or &3xx00, and often have length &yy00. (Screen dumps and machine code images.)
- Some files have load and exec addresses of 0, &30000 or &3FFFF (Text and sequential data.)
- Many files are less than 2K; few files more than 20K; no files more than 64K except text and sequential data.
- The file names have very few lowercase letters.
- The file names contain commonly-occurring pairs of letters.
Sources
This section is based loosely on the following:
- Acorn DFS disk format - beebwiki.mdfs.net
- Acorn, Watford, Solidisk and Duggan DFS Filesystem Structure mdfs.net