This document describes the new filesystem layout to be used with IDE64 and other systems. The expected behaviour for attributes, etc. is also explained.
This document is written in HTML 4.01 Transitional with CSS1. Use browser version 5 or above in 1024x768, or text based browser with table rendering.
Most recent version available at http://singularcrew.hu/cfs/.
The disk starts with a "boot sector". This contains the identification string ("C64 CFS V 0.11B "
),
the global disklabel, a pointer to @Partition directory and it's backup, and the last sectors address.
The default partition number (DP) is used to select which partition
will be automatically selected after power on. Values of 0-15 are valid. The global disklabel is shown in
partition listing. The @Last disk sector points to the last accessible sector on
disk. If this pointer has the LBA bit set, this disk uses LBA addressing.
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Unused | DP | @Last disk sector | |||||
$0008 | $43 | $36 | $34 | $20 | $43 | $46 | $53 | $20 |
$0010 | $56 | $20 | $30 | $2E | $31 | $31 | $42 | $20 |
$0018 | @Partition directory | @Partition directory backup | ||||||
$0020 | Global disklabel padded with $20 if shorter | |||||||
$0028 |
If there's a PC BIOS style partition table in the rest of the sector, then one of the partitions must
cover all the C64 partitions. In this case use $CF
as partition type.
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | 0 | LBA | 0 | 0 | HEAD / LBA HIGHEST | |||
Byte 1 | CYLINDER HIGH / LBA HIGH | |||||||
Byte 2 | CYLINDER LOW / LBA LOW | |||||||
Byte 3 | SECTOR / LBA LOWEST |
If LBA=1 then this pointer is in LBA format.
The partition directory is 1 sector long, and holds 16 entrys from the following 32 bytes long structure:
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Partition's name padded with $00 if shorter. | |||||||
$0008 | ||||||||
$0010 | @Start of partition | @End of partition | ||||||
$0018 | Additional info (filesystem specific, see below) |
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | VALID | LBA | HIDDEN | WRITEABLE | HEAD / LBAHIGHEST |
If VALID=1 then this partition is valid.
If HIDDEN=1 then this partition won't show up in partition listing.
If WRITEABLE=0 then this partition is readonly.
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | TYPE | LBA | TYPE | HEAD / LBAHIGHEST |
%0000
then partition is unformatted.%0001
then filesystem is CFS.OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0018 | @Deleted directory | @Root directory |
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | BITMAP | LBA | reserved | HEAD / LBAHIGHEST |
If BITMAP=0 then this CFS partition uses the #1 usage bitmap, otherwise the #2.
%0010
then disk space is used by GEOS.%0011
-%1011
are reserved.1st usage bitmap sector #1 | 4 0 9 6 |
1st usage bitmap sector #2 | |
4094 data sectors | |
2nd usage bitmap sector #1 | 4 0 9 6 |
2nd usage bitmap sector #2 | |
4094 data sectors | |
...etc... | . |
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | 0 | 0 | 1st-6th data sectors useage | |||||
Byte 1 | 7th-14th data sectors useage | |||||||
... | ...etc... | |||||||
Byte 511 | 4087th-4094th data sectors useage |
Each bit represents a free data sector (1) or used data sector (0).
If there aren't 4094 data sectors at the end of partition, all sectors not part of this partition must be marked as used.
A directory sector holds 16 file entrys and a pointer to @Next directory
sector.
Filesize range is from 0 to 4294967295 bytes, for relative files max. 16711425 bytes.
All entrys have an 1 byte attribute field (AT) at the same position, which specifies flags and filetype.
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | CLOSED | DELETEABLE | READABLE | WRITEABLE | EXECUTEABLE | FILETYPE |
Behaviour of flags:
If CLOSED=0 then this file cannot be accessed, because it wasn't closed (yet).
If DELETEABLE=0 then this file cannot be deleted.
If READABLE=0 then this file cannot be opened for reading. (might be still loadable)
If WRITEABLE=0 then this file is readonly.
If EXECUTEABLE=0 then this file cannot be loaded. (file is skipped for load)
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Filename padded with $00 if shorter. | |||||||
$0008 | ||||||||
$0010 | $00 | $00 | $00 | $00 | @unknown | |||
$0018 | AT | $44 | $45 | $4C | Creation time |
If CLOSED=0 then this is a free entry, can be reused next time. It's skipped in directory list.
If CLOSED=1 then this is a directory separator entry in this case:
The READABLE, WRITEABLE, EXECUTEABLE, bits must be always 0, these flags are not changeable!
A directory separator cannot hold real data, it's only a directory entry.
Should appear with filetype "DEL"
in directory listing.
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Filename padded with $00 if shorter. | |||||||
$0008 | ||||||||
$0010 | Filesize | @Data tree | ||||||
$0018 | AT | Filetype padded with $00 | Modification time |
Filetype "D"
/"DEL"
is not valid, because it's an alias of "DEL"
, and it's handled elsewere.
Filetype "S"
is not valid, because it's an alias of "SEQ"
.
Filetype "P"
is not valid, because it's an alias of "PRG"
.
Filetype "U"
is not valid, because it's an alias of "USR"
.
Filetype "L"
/"R"
/"REL"
is not valid, because it's an alias of "REL"
, and it's handled elsewere.
Filetype "C"
/"CBM"
is not valid, because it's an alias of "CBM"
, and it's reserved.
Filetype "B"
/"DIR"
is not valid, because it's an alias of "DIR"
, and it's handled elsewere.
Filetype "J"
/"LNK"
is not valid, because it's an alias of "LNK"
, and it's handled elsewere.
Normal file type includes "SEQ"
, "PRG"
, "USR"
, and user defined filetypes.
Behaviour of flags:
If EXECUTEABLE=1, it's possible to load this file, otherwise it's skipped when searching (might be still openable!).
If READABLE=1, it's possible to open this file, otherwise error happens (might be still loadable!).
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Filename padded with $00 if shorter. | |||||||
$0008 | ||||||||
$0010 | Filesize | RS | @Data tree | |||||
$0018 | AT | $52 | $45 | $4C | Modification time |
Traditionally used for random access files in CBM DOS.
RS is the record size, from 1 to 255. 0 is invalid.
Should appear with filetype "REL"
in directory listing.
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Dirname padded with $00 if shorter. | |||||||
$0008 | ||||||||
$0010 | $00 | $00 | $00 | $00 | @Sub directory | |||
$0018 | AT | $44 | $49 | $52 | Creation time |
If CLOSED=1 this entry is a regular subdirectory.
If CLOSED=0 this is a directory label.
The directory label must be always the first entry in the directory. It holds the @Parent directory and @This directory pointer. The name field will show up in directory listing as directory label.
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Dirlabel padded with $20 if shorter. | |||||||
$0008 | ||||||||
$0010 | @This directory | @Parent directory | ||||||
$0018 | AT | $44 | $49 | $52 | Creation time |
The DELETEABLE, EXECUTEABLE, WRITEABLE, READABLE, HIDDEN flags must be the
same as for the directory entry for this dir in the parent directory.
Name is changeable by user, defaults to it's "DIR"
entry's name.
Behaviour of flags (for both):
If READABLE=0 if's not possible to list this dir.
If WRITEABLE=0 if's not possible to create/delete/rename file in dir.
If EXECUTEABLE=0 it's not possible to change to this dir.
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | Filename padded with $00 if shorter. | |||||||
$0008 | ||||||||
$0010 | Pathlength | $00 | $00 | @Link sector | ||||
$0018 | AT | $4C | $4E | $4B | Modification time |
The Pathlength represents the size of the string in the link sector.
The link sector holds a string ending with $00. It is a relative path to a file from the current dir.
File cannot be longer than 1 sector.
%101
,%110
,%111
are reserved for future use.Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | Month HIGH | Second (0-59) | ||||||
Byte 1 | Month LOW | Minute (0-59) | ||||||
Byte 2 | Hour HIGH | Year (0-63) | ||||||
Byte 3 | Hour LOW | Day (1-31) |
Month (1-12), Hour (0-23). Year begins from 1980, so 2001 is 21.
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | HIDDEN | LBA | NEXTS | HEAD / LBAHIGHEST |
If HIDDEN=1 this file is hidden, so it won't show up in directory listing. The @Next directory sector pointer is sliced in 16 parts, and the parts are in the NEXTS fields. Structure:
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | in 13rd entry | in 14th entry | in 15th entry | in 16th entry | ||||
Byte 1 | in 9th entry | in 10th entry | in 11th entry | in 12th entry | ||||
Byte 2 | in 5th entry | in 6th entry | in 7th entry | in 8th entry | ||||
Byte 3 | in 1st entry | in 2nd entry | in 3rd entry | in 4th entry |
If all 4 bytes of @Next directory sector pointer are 0s. we reachd end of directory.
It holds the last 15 deleted files, and is usually placed in first data sector of partition.
It has the same structure as a normal directory, but is only 1 sector long, so the
NEXTS field is now called AGE, and it contain the age of entrys instead of
next directory sector pointer's slices. Same filenames with same type are eliminated by replacing
the first character of an older file's name with a character from "A"
to "N"
.
It's directory label is "%DELETED FILES%"
, directory label flags: CLOSED=0, DELETEABLE=0, EXECUTEABLE=1,
WRITEABLE=0, READABLE=1, HIDDEN=1,
It's like any other normal directory, but this is the starting point of directory stucture. It's
usually begins in the second data sector (after the deleted directory sector).
The root directory label is usually the same as
the partition's name, but is changeable. Directory label flags: CLOSED=0, DELETEABLE=0, EXECUTEABLE=1,
WRITEABLE=1, READABLE=1, HIDDEN=0,
After the label there's usually a "%DELETED FILES%"
directory entry with flags CLOSED=1, DELETEABLE=0, EXECUTEABLE=1,
WRITEABLE=0, READABLE=1, HIDDEN=1, it's pointer points to deleted directory
sector.
Data sector pointers are organised in balanced tree for fast seeking. Here's a table about amount of sectors to read to search to a position in file:
Tree depth | Position | Sector(s) to read |
---|---|---|
1 | 0 b - 64 Kb | 1+1 |
2 | 64 Kb - 576 Kb | 2+1 |
3 | 576 Kb - 4.5 Mb | 3+1 |
4 | 4.5 Mb - 36 Mb | 4+1 |
5 | 36 Mb - 292 Mb | 5+1 |
6 | 292 Mb - 2.2 Gb | 6+1 |
7 | 2.2 Gb - 4 Gb | 7+1 |
Each node is 1 sector, and holds 8 @Next tree pointers, 128 @Data sector pointers, plus 1 @Continue pointer. The @Continue pointer is used when a 64Kb boundary is reached during a sequential read.
OFFSET | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
$0000 | @Data sector #1 | @Data sector #2 | ||||||
... | ...etc... | |||||||
$01F8 | @Data sector #127 | @Data sector #128 |
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | CONTP | LBA | SLICE | HEAD / LBAHIGHEST |
@Next tree sector pointers 1-8 are sliced and are in 2 bit pieces (SLICE) in @Data sector pointers. (#1 in 1-16, #2 in 17-32 ...) Same slicing method is used as for @Next directory sector. The @Continue pointer is in data pointers 97-128, one bit in each (CONTP). Bit slicing is similar to directory next method.
The following special @Data sector pointer is used to indicate a hole in file or tree:
Byte / Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 | CONTP | 0 | SLICE | 0 | 0 | 0 | 0 | |
Byte 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Byte 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Byte 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Holes are sectors filled with $00
, or for relative files $FF
at record beginnings and $00
everywhere else. This way unused parts of relative/normal files do not eat up disk space.
$CF
for CFS disk area)-Soci/Singular-
Document by:
Kajtár Zsolt