File Control Block Structure
The File Control Block (FCB) is used by the DOS to control the transfer of
data between the computer’s RAM and the disk. It consists of 25 control bytes and a
256-byte data buffer. The 25 control bytes may have different functions if the file
is a random/direct, sequential input or sequential output file. The data buffer is
used to collect data so that the disk I/O will only be required when there is a
full sector (256 bytes) of data to be input or output to the disk. The use of this
buffer speeds up the overall disk I/O by cutting down on the number of times that
actual disk accesses are required.
The number of FCBs allowed is set by the FILES command, which initializes the
direct page variable FCBACT (the maximum number of FCBs allowed). The DOS always
sets up a system FCB directly above the last allocated FCB, which is reserved for
the exclusive use of the DOS and is not accessible to the user through BASIC. The
system FCB is used when the system requires an FCB for disk I/O during the
execution of such commands as MERGE, COPY, SAVE, LOAD, etc. This FCB may be
accessed by the user under machine language but care must be exercised to insure
that none of the BASIC commands which utilize the system FCB are used when doing
so.
The OPEN command is used to initialize the FCB for disk I/O. It keeps track
of which byte, sector, track and granule is currently being accessed by the DOS for
the file controlled by the FCB. When disk I/O has been completed, the FCB is
deactivated with the CLOSE command. When an FCB is closed, it is available for use
by another file and once the FCB is used by another file, all of the information
used by the previous file is lost. Some of the information must be saved since the
user may want to reopen the same file for use later on. Only six bytes from the FCB
must be saved in order to be able to reinitialize an FCB. These six bytes are the
file type (1), ASCII flag (1), first granule in file (2) and the number of bytes
used in the last sector (2) and they are stored in the directory. A two-byte
quantity is used to store number of bytes used in the last sector since the number
of bytes may be any number from 0 to 256 ($100).
Listed below are those FCB control bytes, which are common to all types of
files and their relative offset from the start of the FCB.
0 |
FCBTYP |
Single byte code representing the file type under which
the file was opened. It may not have any relationship to the
actual type of data stored in the file; a sequential file may be
opened as a random file and vice versa. The allowed codes are:
$10 = Sequential input, $20 = Sequential output, $40 = random, 0
= killed file.
|
1 |
FCBDRV |
Single byte quantity defining the drive number where the file is located (0 - 3).
|
2 |
FCBFGR |
Single byte quantity defining the first granule used by the file.
|
3 |
FCBCGR |
Single byte quantity defining the current granule being accessed by the FCB.
|
4 |
FCBSEC |
Single byte quantity defining the current sector being accessed
by the FCB (1 - 9).
|
18 |
FCBDIR |
Single byte quantity defining the directory entry number for this
file (0 - 71).
|
19 |
FCBLST |
Double byte quantity containing the number of bytes used by this
file in the last sector of the file.
|
Listed below are the definitions of the non-common FCB control bytes as
used by random files.
5 |
FCBCPT |
Unused |
6 |
FCBPOS |
Print position - always zero |
7 |
FCBREC |
Double byte quantity containing the current record number being used by the FCB. |
8 |
FCBRLN |
Double byte quantity containing the length of a record |
11 |
FCBBUF |
Double byte quantity containing a pointer to the absolute address
of the start of random file buffer, which is exactly one record
length long.
|
13 |
FCBSOF |
Double byte quantity containing the sector offset to the current
position in the record. These bytes are used to keep track of how
many sectors from the beginning of a random file the current data
being processed is located. These bytes are used to determine if
the data in the FCB data buffer are valid for the current record
number being processed. The high order byte is often set to $FF
to cause new data to be read into the FCB data buffer.
|
15 |
FCBFLG |
Single byte ‘GET’/‘PUT’ flag: 0=GET, 1=PUT. |
16 |
|
Two unused bytes
|
21 |
FCBGET |
Double byte quantity containing the number of characters, which
have been pulled out of the current record. These bytes are set
to zero every time a record is stored in (PUT) or retrieved from
(GET) a file.
|
23 |
FCBPUT |
Double byte quantity containing the number of characters, which
have been ‘PUT’ into the current record. These bytes are set to
zero every time a record is stored in (PUT) or retrieved from
(GET) a file.
|
Listed below are the definitions of the non—common FCB control bytes as used
by sequential files.
5 |
FCBCPT |
Single byte quantity pointing to the next character to be
processed for input files. When this byte is incremented to zero
it indicates that the data buffer needs to be refilled. For
output files this byte is used to indicate that 256 bytes of the
last sector in the file have been used in case a ‘DISK FULL’
error occurs while searching for an unused granule6 FCBPOS
Single byte quantity containing the current print position
in the file for output files, unused for input files. A carriage
return in the output data stream will reset this value to zero.
|
7 |
FCBREC |
Double byte quantity containing the number of whole sectors which
have been input or output to a file.
|
9-15 |
| Seven unused bytes. |
16 |
FCBCFL |
Single byte cache flag: 00=cache empty, $FF=cache full when
inputting data, the DOS treats a CR, LF sequence as a CR.
Therefore the DOS must look for a LF after a CR and if it does
not find a LF, it must save that character for the next time an
input character is needed. The cache flag indicates whether or
not an extra character, which needs to be saved (cached), has
been pulled out of an input file.
|
17 |
FCBCDT |
Single byte cache data byte. If the cache flag is set
the cache data byte is stored here.
|
23 |
FCBDFL |
Single byte data left flag for input files: 00=data
still left in file, $FF=no data left in file.
|
24 |
FCBLFT |
Single byte quantity containing the number of characters left in
the data buffer of an input file or the number of characters
stored in the data buffer of an output file.
|
File Allocation Table
The file allocation table (FAT) is used to keep track of whether or not a
granule has been allocated to a file or if it is free. The FAT is composed of six
control bytes followed by 68 data bytes — one byte for each granule. The FAT is
stored on sector two of the directory track (17). A RAM image of the FAT is kept in
the disk RAM for each of the four possible drives. Keeping an image of the FAT in
RAM helps speed up the overall operation of the DOS by eliminating the need for
disk I/O every time the DOS modifies the FAT. Saving the FAT to disk is done
approximately every 19 times that a new granule is pulled from the free granule
reserve. It is written to disk whenever a file is closed and there are some DOS
operations, which force the FAT to be written to disk when that DOS operation
allocates a free granule.
Only the DOS uses two of the six control bytes. The first FAT control byte
keeps track of how many FCBs are active on the drive for a particular FAT. This
byte is used to preclude the loading in of the FAT from disk when there is any
active file currently using the FAT. You can imagine the disaster, which would
occur if you were creating a file and had allocated some granules to your new file
but had not saved the new FAT to disk when the old FAT was loaded into RAM on top
of the new FAT. Your new file would be hopelessly gone. For that reason the DOS
must not allow the FAT to be loaded into RAM from disk while an FCB is active for
that FAT.
The second FAT control byte is used to govern the need to write data from the
FAT RAM image to the disk. If the value of this byte is zero it means that the FAT
RAM image is an exact copy of what is currently stored on the disk. If the value is
non—zero, it indicates that the data in the FAT RAM image has been changed since
the last time that the FAT was written to disk. The number stored in this byte is
an indicator of how many granules have been removed from the FAT since the last FAT
to disk write. Some BASIC commands, such as KILL, cause an immediate FAT RAM image
to disk write when granules are either freed or allocated. Other commands, which
allocate granules, increment the second FAT control byte. This byte is then
compared to the disk variable WFATVL and when the second control byte is >= WFATVL,
the FAT is written to disk.
The FAT data bytes are used to determine whether or not a granule is free and
if it has been allocated they are used to determine to which file the granule
belongs. If a data byte is $FF, it means that the granule is free and may be
allocated to any file. If a granule has been allocated, it is part of a sector
chain, which defines which granules belong to a certain file. The only information
required to be able to trace the granule chain is the number of the first granule
in the chain. If the first granule of the chain is not known, the chain cannot be
traced down backwards.
A granule data byte, which has been allocated, will contain a value, which is
the number of the next granule in the granule chain for that file. If the two most
significant bits (6,7) of a granule data byte are set, then that granule is the
last granule in a file’s granule chain. The low order four bits will contain the
number of sectors in the last granule, which the file uses. Even though a file may
not use all of the sectors in the last granule in the chain, no other file may use
the sectors. Disk space is not allocated on a sector basis, it is allocated on a
granule basis and the granule may not be broken down. The smallest one-byte file
will still require a full granule to be allocated in order to store the file.
Granules are allocated in such a manner that will cause them to be relatively
uniformly spread around the disk. This will lessen wear on the disk by not always
allocating certain granules so that the disk drive head will not pass over certain
sections of the disk too often. This is a common method used by a DOS in order to
increase the life of a disk by spreading out the wear over as large a surface as
possible, which could not be done if the granules were allocated on a strictly next
in line numerical basis.
The Directory
The directory is used by the DOS to keep track of how many files are stored
on a disk. Track 17 is reserved for the directory and the file allocation table
(FAT). The FAT resides on sector 2 and the directory occupies sectors 3-11. The
remaining sectors are not used by the DOS in the current or past revisions to the
BASIC ROMs. Each directory entry requires 32 bytes; so eight directory entries will
fit in one sector for a total of 72 maximum directory entries. However, one full
granule is required for each directory entry and there are only 68 granules on a
disk so that only 68 directory entries (files) may exist on a disk at any time.
The format of the 32-byte directory entry is as follows:
0 - 7 |
Filename, which is left justified and blank, filled. If byte 0 is 0,
then the file has been ‘KILL’ed and the directory entry is available
for use. If byte 0 is $FF, then the entry and all following entries
have never been used.
|
8 - 10 |
Filename extension |
11 |
File type:
0 = BASIC
1 = BASIC data
2 = Binary/Machine language
3 = Text
|
12 |
ASCII flag:
0=binary or crunched BASIC
$FF=ASCII
|
13 |
Number of the first granule in the file |
14 - 15 |
Number of bytes used in the last sector of the file |
16 - 31 |
Unused (future use) |
|