The following describes the logical structure of DFS and ADFS disks. (Note that some of the detail in the published literature is incomplete or wrong.) The special DOS disk formats available to the Master 512 are detailed elsewhere. No attempt is made here to describe any of the alternative or enhanced disk formats produced by other people to replace or extend the standard DFS or ADFS.
This page is divided into:
|Common Features and Comparison|
|DFS Disk Structure|
|ADFS Disk Structure|
|Notes about Disk Images and Emulators|
DFS (Disk Filing System) was the first disk-based filing system produced for the BBC Computer. It was, however, somewhat limited, and Acorn later released ADFS (the Advanced Disk Filing System) which was supplied as standard with the Master 128. (Since the two systems are incompatible, the Master also included DFS. ADFS could also be used with the earlier Model B and B+ computers, except that it would not work with the original 8271 disk contoller chip.) Both filing systems were supplied in plug-in ROMs.
Both 40-track and 80-track 5¼"-disk drives were produced for the BBC Computer in single- and double-sided versions, and both filing systems were designed to cope with all variations of these (with one exception). DFS is a floppy-only system, but ADFS can also be used with the hard disks that became available for the machine, and indeed was designed with them in mind.
Both systems use disk sectors of 256 bytes. Physically the sectors are numbered sequentially from 0 upwards on each track.
DFS stores data on disks using single-density (FM) encoding. There are ten (256-byte) sectors on each track, giving a total of 100kb on a single side of a 40-track disk, and 200kb on one side of an 80-track one. DFS can use double-sided disks, though only by treating each side as essentially a separate disk.
ADFS uses double-density (MFM) encoding. It has 16 sectors on each floppy-disk track. There are three sizes of floppy disk: Small (single-sided 40-track – 160kb), Medium (single-sided 80-track – 320kb) and Large (double-sided 80-track – 640kb). ADFS does not allow for double-sided 40-track disks. ADFS can also handle hard disks up to a maximum of 512Mb, though in practice the largest hard disks ever produced for the BBC Computer were about 40Mb. (BBC hard disks actually have 33 sectors per track, a number fixed by the Adaptec interface board which forms part of the disk unit.)
No standard BBC filing system can cope with high-density encoding (such as is used for 1.2Mb or 1.44Mb DOS disks).
In both DFS and ADFS files are stored as contiguous blocks of data. A file is never split into sections on different parts of the disk. (So with either filing system this can sometimes lead to problems if an existing file needs to be extended but there is another file immediately following it on the disk.)
Every file on a BBC filing system has associated with a Load address and an Execution address, in addition to the actual file data. Each of these is a 32-bit number, and they are the locations to which a file will be loaded and where execution will start if it is called as a machine-code program. (Machine-code programs for the BBC Computer are not normally relocatable. 32 bits are used for these addresses in case a second processor is attached, though see the note below regarding limitations in DFS.) Even though a file may not be intended to be run as a program, it will still have a load address and an execution address.
In addition to these addresses and its data, a file may have certain status attributes which can be used to restrict access.
Files in DFS have file names of up to 7 characters long. There is no hierarchical directory system, but files can be allocated to "directory" groups, which all have single-character names. The default directory is called "$".
There is only one status attribute available. A file may be "Locked" or not, meaning more-or-less read-only.
A (single side of) a DFS disk can hold up to 31 files in total.
ADFS allows for a hierarchical directory system. A directory may contain both files and sub-directories. A file or directory name may be up to 10 characters in length. (The root is always called "$".)
Four status attributes are available for ADFS files and directories. They may be marked by any combination of L (locked), W (writeable), R (readable) and E (execute only.) (Some combinations of these attributes are logically meaningless. The most commonly used are LR and WR.)
A directory may contain up to 47 entries, either files or sub-directories. There is no limit to the total number of files on the disk (other than the disk size).
In addition to the file and directory data, each disk carries a small amount of extra information:
The disk (in DFS) or each directory (in ADFS) has a Title and a "cycle number". (The title of an ADFS directory is distinct from its name.) ADFS files and subdirectories also have their own individual cycle numbers. The DFS disk title is up to 12 characters long, an ADFS directory title up to 19 characters long. The cycle numbers are incremented (up to 99, then round again) when changes are made. Titles and cycle numbers can be read, and are displayed by *CAT, but are otherwise non-functional.
Finally, the disk has a boot option number – a number between 0 and 3 indicating the action to be taken if the disk is auto-started using Shift-Break.
Although DFS can be used with floppy disks which are physically double-sided, the two sides of such a disk are treated by the system as quite separate. Side 0 of the disk in physical drive 0 is known as Drive :0, side 1 of the same disk is known as Drive :2, and the two sides of a disk in physical drive 1 will be correspondingly Drive :1 and Drive :3. From a structural point of view it thus make sense to say that all DFS disks are single-sided.
All the sectors of a DFS disk should be considered as a single logical sequence (starting at logical sector 0 which will, of course, be physical sector 0 of track 0, and then increasing in the natural order of sector then track). So on a 40-track disk the sectors run logically from 0 to &18F, on an 80-track disk from 0 to &31F.
The first two sectors contain the disk catalogue. The actual file data occupies the remaining sectors. Each file begins at a sector boundary and, as noted above, files are not divided into parts but each one is a contiguous piece of data.
The first two sectors hold the catalogue data and are laid out as follows:
|0 - 7||
First 8 characters of the disk title (padded with zeros if the title is less than 8 characters in length.)
|8 ‑ &FF||
The names of the files on disk.
There are 8 bytes for each file, taking the form:
There is room here for a maximum of 31 files. The files appear in the catalogue in the reverse order to that in which their data is stored on the disk. (Whether this matters is uncertain.) There are no gaps between the file entries. The sector beyond the last file in the catalogue is filled with zeros.
|0 - 3||
Characters 8 to 11 of the disk title (padded with zeros if the title less than 12 characters long)
|4||Disk cycle number (stored in "binary-coded decimal" format)|
|5||Number of files on the disk multiplied by 8|
|7||Bottom 8 bits of the total number of sectors on the disk|
|8 ‑ &FF||
Catalogue details of the files.
As in Sector 0, there are 8 bytes for each file, naturally corresponding to the files with names as listed there. Each block of 8 bytes encodes 4 numbers, namely the file length, the load address, the execution address, and the sector number of the start of the file data. The first three of these are 18-bit numbers, the start sector number is 10 bits. This makes a total of 64 bits ((3*18)+10), and these are divided between the 8 bytes as follows:
It is perhaps worth noting that, under DFS, each of the load address and execution address is stored as an 18-bit number – two full bytes plus a partial top byte which can only take the value 0, 1, 2 or 3. In theory these should be 32-bit numbers. In practice, if the top byte of such a number has the value 3, then the address is reported to the system as &FFFFxxxx (or may be displayed as &FFxxxx); if the top byte is 0, 1 or 2, then the address is reported as between 0 and &2FFFF.
All the sectors on an ADFS disk should be considered as a single logical sequence, starting at logical sector 0.
It is worth noting that for Large (double-sided) ADFS floppy disks, the logical sector numbers increase in the order sector - track - side; in other words first come all the sectors on side 0, followed by all the sectors on side 1. This is different from disks on many other systems such as PCs. On DOS disks, for instance, the sectors on track 0:side 0 are followed by track 0:side 1, then track 1:side 0 and so on – alternating sides between tracks. This difference doesn't arise with single-sided disks, of course, and the issue is not relevant for hard disks since all translation between physical and logical sectors is performed by the interface board in the hard disk unit.
The disk is divided into three areas. All are made of whole numbers of sectors, and they occur in the following order:
1. The Free Space Map – 2 sectors (Sectors 0 and 1)
2. Root Directory – 5 sectors (Sectors 2 to 6)
3. Data area: Files and sub-directories.
There are no gaps between the sections, so the data area starts at sector number 7.
The system needs to keep track of which sectors are in use as file and directory data, and consequently which sectors are available for data storage. This is done by means of the "Free Space Map" (or "FS Map"), which provides a list of those sectors which are not currently in use. The free sectors are listed as blocks with, in each case, the starting sector and the size of the free block.
There are a few other items stored in this area as well. In detail the first two sectors on the disk are laid out as follows:
|0 - &F5||
Start sector of each free-space block. Three bytes per entry, so bytes 0-2 for the first block, 3-5 for the second, etc. This allows a maximum of 82 blocks of free space. (This maximum is independent of the size of the disk. Disk compaction may be necessary from time to time to prevent this limit being exceeded, especially on a hard disk.)
|&F6 - &FB||0|
|&FC - &FE||Total number of sectors on disk (For floppies this works out as: Small - &280; Medium - &500; Large - &A00)|
|&FF||Sector checksum (= [sum-with-carry of bytes &FE to 0] MOD &100. Ie the bytes are added together, starting at the top of the sector, each time using an ADC instruction with no CLC between, so the carry bits (except for the last one) are included. The result is stored in this byte.)|
|0 - &F5||Size of each free-space block in number of sectors. As with Sector 0, three bytes per entry, so bytes 0-2 for the first block, 3-5 for the second, etc.|
|&F6 - &FA||0|
|&FB,&FC||Disk identifier. These bytes are apparently random and written afresh to the disk every time a change is made. The result is that they are always different for any two disks, even when one has been copied track-by-track from the other. This enables the system to recongnise when the disk has been changed.|
|&FD||Boot option number|
|&FE||Pointer to end of free space list. This points to the byte offset (in both these sectors) beyond the end of the free space list. It is thus 3 times the number of free space blocks in the FS Map.|
|&FF||Sector checksum (as in the previous sector)|
Each directory is stored as a block of 5 sectors, ie &500 bytes. The root directory takes up sectors 2 to 6, others are elsewhere on the disk. A block of data is a sub-directory (rather than a file) if the top bit is set in byte 3 of its own entry in its parent directory. There are also identifiers within the structure, in particular the directory identifier string stored twice at location offsets 1 and &4FB
The overall layout is as follows:
|0||Cycle number for directory (stored in "Binary coded decimal" (BCD) format)|
|1 - 4||Directory identifier string. This always reads "Hugo", ie the 4 bytes &48,&75,&67,&6F, and is a way of identifying the block of data as a directory.|
|5 - &4CA||Directory entries. Each entry takes up 26 (&1A) bytes, and there is room here for 47 entries. Note that for some varieties of ADFS (at least) the entries must be in aphabetical order. (See below for details of each entry)|
|&4CC - &4D5||Directory name. For the root directory this is the single character "$", and the remaining bytes are zeros. For other directories it is the name in ASCII, terminated with &D if it is less than 10 bytes long. (There is no &D terminator for the root directory nor for names taking up the full 10 bytes.)|
|&4D6 - &4D8||Start sector of parent directory (Note: For the root directory this is set to 2, so it points to itself – an attempt to move up the tree from the root directory stays at the root.)|
|&4D9 - &4EB||
Directory title. The string is terminated with &D if it does not fill the whole 19-byte block, except for the original value for the root directory when it is just "$" followed by zeros.
|&4EC - &4F9||0|
|&4FA||Cycle number for directory (stored in BCD format) – same as byte 0|
|&4FB - &4FE||Directory identifier string. Again the string "Hugo", the same as bytes 1 - 4.|
|0 - 9||Name and attributes (see below)|
|&A - &D||Load address|
|&E - &11||Execution address|
|&12 - &15||File length (in bytes)|
|&16 - &18||Start sector|
Note that sub-directory entries have load and execution addresses both set to 0, and file length set to &500.
Note also that directories (other than the root) have two different cycle numbers associated wth them. First there is the cycle number stored with the entry in the parent directory. This is exactly the same as the cycle number for files in that parent directory. It is written when the directory is first created, and appears against the directory name in the *CAT listing of the parent directory. Secondly there is the ycle number stored (twice) in the directory entry itself. This is incremented on all directory-related activities, such as a file being written to the directory. This number appears at the top of the *CAT listing of the directory itself, along with the directory title.
Characters in file and directory names must be standard ASCII (values between &21 and &7E – "top bit set" characters are not allowed, and various other characters (such as ".") will confuse the system so should not be used). The names are terminated with &D or a zero byte, unless they fill the whole space allocated to them.
The top bits of the first five bytes of the name (extending beyond the end of the name if it is shorter than 5 characters) are used for attributes as follows. In each case the attribute is set if the bit is 1, clear if it is 0.
|Byte||Meaning if top bit is set|
|0||R – Can be read|
|1||W – Can be written to|
|2||L – File locked|
|3||Item is a subdirectory|
|4||E – Execute only|
A sub-directory is a data item like a file, the only difference being that the "directory" bit (top bit of byte 3) is set in its own directory entry (ie in its parent directory).
The structure of a sub-directory is exactly the same as that of the root directory.
Floppy and hard disk images can be used in an emulator, such as BeebEm.
Images of DFS single-sided disks are normally given the extension .ssd, and double-sided disks .dsd. ADFS floppy disk images usually are given the extension .adf (for small or medium (single-sided) images) or .adl (for large (double-sided) ones).
One thing to notice about this is that *.dsd and *.adl files store sectors in the increment order sector - track - side. So track 0:side 0 is followed by track 0:side 1 then track 1:side 0 etc. This is like the disk images normally used for PCs, but it means that tracks are not stored on the disk in logical sequence order. Instead, for *.adl files, sectors 0 to &F are followed by sectors &500 to &50F, then sectors &10 to &1F, sectors &510 to &51F, etc, with the (10 sector per track) equivalent for *.dsd files. (More recently .ssd has been redesignated as standing for "sequentially stored disk", permitting it to be used for images of double-sided disks which start with all the data on side 0 followed by the data on side 1.)
A hard disk image is stored as two files, if they are to run under under BeebEm for instance. These files are named scsin.dat and scsin.dsc, where n is 0 to 3 and represents the disk drive number. The file scsin.dat is the actual disk image, with all data stored in the natural sequence order. The file scsin.dsc is a file of 22 bytes, containing the equivalent of the hard disk metrics for a physical disk, in the form of the parameter block that would be passed to the interface board. The meanings of the bytes in this file are as follows (Note that multiple-byte numbers are stored here high-byte first):
|0 - 2||0||Reserved|
|3||&80||Block length descriptor (This goes with bytes 9 to 11 – see below)|
|4||0||Density code – 0 means MFM|
|5 - 8||0||Reserved|
|9 - 11||&100||Sector size (also known as Block size). All BBC disks use a sector size of 0x100 (=256) bytes, making these three bytes to have values: 0, 1, 0|
|12||1||The value of 1 means soft sectors|
|13, 14||Number of cylinders (high byte first)|
|15||Number of heads|
|16, 17||&80||Reduced Write Current Cylinder start (RWCC) (Two bytes – high byte first). The beginning of the part of the physical disk which needs a reduced write current. For emulated disks this can be of no significance, but most physical disks for the BBC seem to need a value of &80.|
|18, 19||&80||Write Pre-compensation Cylinder start (WPCC). Write pre-compensation is another feature of physical disks which can have no significance for emulated disks. For physical BBC disks it always seems to have the same value as RWCC. (The "Superform" program always sets them the same.)|
|21||1||Seek time code – This can be 0 (=3ms), 1 (=28μs) or 2 (=12μs)|
For emulated disks the only numbers that will ever need altering within this are bytes 13, 14 and 15. As noted above, all BBC hard disks have 33 sectors per track. In physical disks this gives a total number of sectors as 33 * (number of cylinders) * (number of tracks). This is a little bigger than the number of usable sectors to allow the hardware to substitute some of them when bad sectors are found.