This chapter gives a technical description of the various files supported by the emulators.
(This section was taken from the C64S distribution.)
The T64
File Structure was developed by Miha Peternel for use in
the C64S emulator. It is easy to use and allows future extensions.
Offset | Size | Description |
0 | 64 | tape record |
64 | 32*n | file records for n directory entries |
64+32*n | varies | binary contents of the files |
Offset | Size | Description |
0 | 32 | DOS tape description + EOF (for type) |
32 | 2 | tape version ($0200) |
34 | 2 | number of directory entries |
36 | 2 | number of used entries (can be 0 in my loader) |
38 | 2 | free |
40 | 24 | user description as displayed in tape menu |
Offset | Size | Description |
0 | 1 | entry type (see below) |
1 | 1 | C64 file type |
2 | 2 | start address |
4 | 2 | end address |
6 | 2 | free |
8 | 4 | offset of file contents start within T64 file |
12 | 4 | free |
16 | 16 | C64 file name |
Valid entry types are:
Code | Explanation |
0 |
free entry |
1 |
normal tape file |
2 |
tape file with header: header is saved just before file data |
3 |
memory snapshot v0.9, uncompressed |
4 |
tape block |
5 |
digitized stream |
6 ... 255 |
reserved |
Notes:
1
.
3
, 4
and 5
are subject to change (and
are rarely used).
(This section was contributed by Peter Schepers and slightly edited by Ettore Perazzoli.)
This format was defined in 1998 as a cooperative effort between several
emulator people, mainly Per Håkan Sundell, author of the CCS64 C64
emulator, Andreas Boose of the VICE CBM emulator team and Joe
Forster/STA, the author of Star Commander. It was the first real public
attempt to create a format for the emulator community which removed
almost all of the drawbacks of the other existing image formats, namely
D64
.
The intention behind G64
is not to replace the widely used
D64
format, as D64
works fine with the vast majority of
disks in existence. It is intended for those small percentage of
programs which demand to work with the 1541 drive in a non-standard way,
such as reading or writing data in a custom format. The best example is
with speeder software such as Action Cartridge in Warp Save mode or
Vorpal which write track/sector data in another format other than
standard GCR. The other obvious example is copy-protected software
which looks for some specific data on a track, like the disk ID, which
is not stored in a standard D64
image.
G64
has a deceptively simply layout for what it is capable of
doing. We have a signature, version byte, some predefined size values,
and a series of offsets to the track data and speed zones. It is what's
contained in the track data areas and speed zones which is really at the
heart of this format.
Each track entry in simply the raw stream of GCR data, just what a read head would see when a diskette is rotating past it. How the data gets interpreted is up to the program trying to access the disk. Because the data is stored in such a low-level manner, just about anything can be done. Most of the time I would suspect the data in the track would be standard sectors, with SYNC, GAP, header, data and checksums. The arrangement of the data when it is in a standard GCR sector layout is beyond the scope of this document.
Since it is a flexible format in both track count and track byte size, there is no "standard" file size. However, given a few constants like 42 tracks and halftracks, a track size of 7928 bytes and no speed offset entries, the typical file size will a minimum of 333744 bytes.
Below is a dump of the header, broken down into its various parts. After that will be an explanation of the track offset and speed zone offset areas, as they demand much more explanation.
Addr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ---- ----------------------------------------------- 0000: 47 43 52 2D 31 35 34 31 00 54 F8 1E .. .. .. ..
Offset | Description |
$0000-0007 | File signature (GCR-1541 ) |
$0008 | G64 version (presently only $00 defined) |
$0009 | Number of tracks in image (usually $54, decimal 84) |
$000A-000B | Size of each stored track in bytes (usually 7928, or $1EF8) in LO/HI format. |
An obvious question here is "why are there 84 tracks defined when a
normal D64
disk only has 35 tracks?" Well, by definition, this
image includes all half-tracks, so there are actually 42 tracks and 42
half tracks. The 1541 stepper motor can access up to 42 tracks and the
in-between half-tracks. Even though using more than 35 tracks is not
typical, it was important to define this format from the start with what
the 1541 is capable of doing, and not just what it typically does.
At first, the defined track size value of 7928 bytes may seem to be arbitrary, but it is not. It is determined by the fastest write speed possible (speed zone 0), coupled with the average rotation speed of the disk (300 rpm). After some math, the answer that actually comes up is 7692 bytes. Why the discrepency between the actual size of 7692 and the defined size of 7928? Simply put, not all drives rotate at 300 rpm. Some can be faster or slower, so a upper safety margin of +3% was built added, in case some disks rotate slower and can write more data. After applying this safety factor, and some rounding-up, 7928 bytes per track was arrived at.
Also note that this upper limit of 7928 bytes per track really only applies to 1541 and compatible disks. If this format were applied to another disk type like the SFD1001, this value would be higher.
Below is a dump of the first section of a G64
file, showing the offsets
to the data portion for each track and half-track entry. Following that
is a dump of the speed zone offsets.
Addr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ---- ----------------------------------------------- 0000: .. .. .. .. .. .. .. .. .. .. .. .. AC 02 00 00 0010: 00 00 00 00 A6 21 00 00 00 00 00 00 A0 40 00 00 0020: 00 00 00 00 9A 5F 00 00 00 00 00 00 94 7E 00 00 0030: 00 00 00 00 8E 9D 00 00 00 00 00 00 88 BC 00 00 0040: 00 00 00 00 82 DB 00 00 00 00 00 00 7C FA 00 00 0050: 00 00 00 00 76 19 01 00 00 00 00 00 70 38 01 00 0060: 00 00 00 00 6A 57 01 00 00 00 00 00 64 76 01 00 0070: 00 00 00 00 5E 95 01 00 00 00 00 00 58 B4 01 00 0080: 00 00 00 00 52 D3 01 00 00 00 00 00 4C F2 01 00 0090: 00 00 00 00 46 11 02 00 00 00 00 00 40 30 02 00 00A0: 00 00 00 00 3A 4F 02 00 00 00 00 00 34 6E 02 00 00B0: 00 00 00 00 2E 8D 02 00 00 00 00 00 28 AC 02 00 00C0: 00 00 00 00 22 CB 02 00 00 00 00 00 1C EA 02 00 00D0: 00 00 00 00 16 09 03 00 00 00 00 00 10 28 03 00 00E0: 00 00 00 00 0A 47 03 00 00 00 00 00 04 66 03 00 00F0: 00 00 00 00 FE 84 03 00 00 00 00 00 F8 A3 03 00 0100: 00 00 00 00 F2 C2 03 00 00 00 00 00 EC E1 03 00 0110: 00 00 00 00 E6 00 04 00 00 00 00 00 E0 1F 04 00 0120: 00 00 00 00 DA 3E 04 00 00 00 00 00 D4 5D 04 00 0130: 00 00 00 00 CE 7C 04 00 00 00 00 00 C8 9B 04 00 0140: 00 00 00 00 C2 BA 04 00 00 00 00 00 BC D9 04 00 0150: 00 00 00 00 B6 F8 04 00 00 00 00 00 .. .. .. ..
Offset | Description |
$000C-000F | Offset to stored track 1.0 ($000002AC, in LO/HI format, see below for more) |
$0010-0013 | Offset to stored track 1.5 ($00000000) |
$0014-0017 | Offset to stored track 2.0 ($000021A6) |
... | |
$0154-0157 | Offset to stored track 42.0 ($0004F8B6) |
$0158-015B | Offset to stored track 42.5 ($00000000) |
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 0150: .. .. .. .. .. .. .. .. .. .. .. .. 03 00 00 00 0160: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 0170: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 0180: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 0190: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 01A0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 01B0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 01C0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 01D0: 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00 00 01E0: 00 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00 01F0: 00 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00 0200: 00 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00 0210: 00 00 00 00 02 00 00 00 00 00 00 00 01 00 00 00 0220: 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 0230: 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 0240: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 0250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02A0: 00 00 00 00 00 00 00 00 00 00 00 00 .. .. .. ..
Offset | Description |
$015C-015F | Speed zone entry for track 1 ($03, in LO/HI format, see below for more) |
$0160-0163 | Speed zone entry for track 1.5 ($03) |
... | |
$02A4-02A7 | Speed zone entry for track 42 ($00) |
$02A8-02AB | Speed zone entry for track 42.5 ($00) |
Starting here at $02AC is the first track entry (from above, it is the first entry for track 1.0)
The track offsets (from above) require some explanation. When one is set to all 0's, no track data exists for this entry. If there is a value, it is an absolute reference into the file (starting from the beginning of the file). From the track 1.0 entry we see it is set for $000002AC. Going to that file offset, here is what we see...
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 02A0: .. .. .. .. .. .. .. .. .. .. .. .. 0C 1E FF FF 02B0: FF FF FF 52 54 B5 29 4B 7A 5E 95 55 55 55 55 55 02C0: 55 55 55 55 55 55 FF FF FF FF FF 55 D4 A5 29 4A 02D0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52
Offset | Description |
$02AC-02AD | Actual size of stored track (7692 or $1E0C, in LO/HI format) |
$02AE-02AE+$1E0C | Track data |
Following the track data is filler bytes. In this case, there are 368 bytes of unused space. This space can contain anything, but for the sake of those wishing to compress these images for storage, they should all be set to the same value. In the sample I used, these are all set to $FF.
Below is a dump of the end of the track 1.0 data area. Note the actual track data ends at address $20B9, with the rest of the block being unused, and set to $FF.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 1FE0: 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 1FF0: 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 2000: A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 2010: 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 2020: 4A 52 94 A5 29 4A 52 94 A5 29 4A 52 94 A5 29 4A 2030: 55 55 55 55 55 55 FF FF FF FF FF FF FF FF FF FF 2040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2080: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2090: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 20A0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 20B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 20C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 20D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 20E0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 20F0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2100: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2110: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2120: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2130: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2140: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2150: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2160: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2170: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2180: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2190: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 21A0: FF FF FF FF FF FF .. .. .. .. .. .. .. .. .. ..
The speed offset entries can be a little more complex. The 1541 has four speed zones defined, which means the drive can write data at four distinct speeds. On a normal 1541 disk, these zones are as follows:
Track Range | Speed Zone |
1-17 | 3 (highest writing speed) |
18-24 | 2 |
25-30 | 1 |
31 and up | 0 (lowest writing speed) |
Note that you can, through custom programming of the 1541, change the speed zone of any track to something different (change the 3 to a 0) and write data differently. From the dump of the speed offset entries above, we see that all the entries are in the range of 0-3. If any entry is less than 4, this is not considered a speed offset but defines the whole track to be recorded at that one speed.
In the example I had, there were no offsets defined, so no speed zone dump can be shown. However, I can define what should be there. You will have a block of data, 1982 bytes long. Each byte is encoded to represent the speed of 4 bytes in the track offset area, and is broken down as follows:
Speed entry $FF: in binary %11111111 |'|'|'|' | | | | | | | +- 4'th byte speed (binary 11, 3 dec) | | +--- 3'rd byte speed (binary 11, 3 dec) | +----- 2'nd byte speed (binary 11, 3 dec) +------- 1'st byte speed (binary 11, 3 dec)
It was very smart thinking to allow for two speed zone settings, one in the offset block and another defining the speed on a per-byte basis. If you are working with a normal disk, where each track is one constant speed, then you don't need the extra blocks of information hanging around the image, wasting space.
What may not be obvious is the flexibility of this format to add tracks and speed offset zones at will. If a program decides to write a track out with varying speeds, and no speed offset exist, a new block will be created by appending it to the end of the image, and the offset pointer for that track set to point to the new block. If a track has no offset yet, meaning it doesn't exist (like a half-track), and one needs to be added, the same procedure applies. The location of the actual track or speed zone data is not important, meaning they do not have to be in any particular order since they are all referenced by the offsets at the beginning of the image.
(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)
First and foremost we have D64, which is basically a sector-for-sector copy of a 1540/1541 disk. There are several versions of these which I will cover shortly. The standard D64 is a 174848 byte file comprised of 256 byte sectors arranged in 35 tracks with a varying number of sectors per track for a total of 683 sectors. Track counting starts at 1, not 0, and goes up to 35. Sector counting starts at 0, not 1, for the first sector, therefore a track with 21 sectors will go from 0 to 20.
The original media (a 5.25" disk) has the tracks laid out in circles, with track 1 on the very outside of the disk (closest to the sides) to track 35 being on the inside of the disk (closest to the inner hub ring). Commodore, in their infinite wisdom, varied the number of sectors per track and data densities across the disk to optimize available storage, resulting in the chart below. It shows the sectors/track for a standard D64. Since the outside diameter of a circle is the largest (versus closer to the center), the outside tracks have the largest amount of storage.
Track | Sectors/track | # Sectors |
1-17 | 21 | 357 |
18-24 | 19 | 133 |
25-30 | 18 | 108 |
31-35 | 17 | 85 |
36-40(*) | 17 | 85 |
Track | #Sect | #SectorsIn | D64 Offset |
1 | 21 | 0 | $00000 |
2 | 21 | 21 | $01500 |
3 | 21 | 42 | $02A00 |
4 | 21 | 63 | $03F00 |
5 | 21 | 84 | $05400 |
6 | 21 | 105 | $06900 |
7 | 21 | 126 | $07E00 |
8 | 21 | 147 | $09300 |
9 | 21 | 168 | $0A800 |
10 | 21 | 189 | $0BD00 |
11 | 21 | 210 | $0D200 |
12 | 21 | 231 | $0E700 |
13 | 21 | 252 | $0FC00 |
14 | 21 | 273 | $11100 |
15 | 21 | 294 | $12600 |
16 | 21 | 315 | $13B00 |
17 | 21 | 336 | $15000 |
18 | 19 | 357 | $16500 |
19 | 19 | 376 | $17800 |
20 | 19 | 395 | $18B00 |
21 | 19 | 414 | $19E00 |
22 | 19 | 433 | $1B100 |
23 | 19 | 452 | $1C400 |
24 | 19 | 471 | $1D700 |
25 | 18 | 490 | $1EA00 |
26 | 18 | 508 | $1FC00 |
27 | 18 | 526 | $20E00 |
28 | 18 | 544 | $22000 |
29 | 18 | 562 | $23200 |
30 | 18 | 580 | $24400 |
31 | 17 | 598 | $25600 |
32 | 17 | 615 | $26700 |
33 | 17 | 632 | $27800 |
34 | 17 | 649 | $28900 |
35 | 17 | 666 | $29A00 |
36(*) | 17 | 683 | $2AB00 |
37(*) | 17 | 700 | $2BC00 |
38(*) | 17 | 717 | $2CD00 |
39(*) | 17 | 734 | $2DE00 |
40(*) | 17 | 751 | $2EF00 |
(*) Tracks 36-40 apply to 40-track images only.
The directory track should be contained totally on track 18. Sectors 1-18 contain the entries and sector 0 contains the BAM (Block Availability Map) and disk name/ID. Since the directory is only 18 sectors large (19 less one for the BAM), and each sector can contain only 8 entries (32 bytes per entry), the maximum number of directory entries is 18 * 8 = 144. The first directory sector is always 18/1, even though the t/s pointer at 18/0 (first two bytes) might point somewhere else. It then follows the same chain structure as a normal file, using a sector interleave of 3. This makes the chain links go 18/1, 18/4, 18/7 etc.
Note that you can extend the directory off of track 18, but only when reading the disk or image. Attempting to write to a directory sector not on track 18 will cause directory corruption. Each directory sector has the following layout (18/1 partial dump):
00: 12 04 81 11 00 4E 41 4D 45 53 20 26 20 50 4F 53 <- notice the T/S link 10: 49 54 A0 A0 A0 00 00 00 00 00 00 00 00 00 15 00 <- to 18/4 ($12/$04) 20: 00 00 84 11 02 41 44 44 49 54 49 4F 4E 41 4C 20 <- and how its not here 30: 49 4E 46 4F A0 11 0C FE 00 00 00 00 00 00 61 01 <- ($00/$00)
The first two bytes of the sector ($12/$04) indicate the location of the next track/sector of the directory (18/4). If the track is set to $00, then it is the last sector of the directory. It is possible, however unlikely, that the directory may *not* be competely on track 18 (some disks do exist like this). Just follow the chain anyhow.
When the directory is done, the track value will be $00. The sector link should contain a value of $FF, meaning the whole sector is allocated, but the actual value doesn't matter. The drive will return all the available entries anyways.
This is a breakdown of a standard directory sector:
Bytes | Description |
$00-$1F | First directory entry |
$20-$3F | Second dir entry |
$40-$5F | Third dir entry |
$60-$7F | Fourth dir entry |
$80-$9F | Fifth dir entry |
$A0-$BF | Sixth dir entry |
$C0-$DF | Seventh dir entry |
$E0-$FF | Eighth dir entry |
This is a breakdown of a standard directory entry:
Bytes | Description |
$00-$01 | Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector) |
$02 | File type |
$03-$04 | Track/sector location of first sector of file |
$05-$14 | 16 character filename (in PETASCII, padded with $A0) |
$15-$16 | Track/Sector location of first side-sector block (REL file only) |
$17 | REL file record length (REL file only, max. value 254) |
$18-$1D | Unused (except with GEOS disks) |
$1E-$1F | File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is <= #sectors * 254 |
The file type field is used as follows:
Bits | Description |
0-3 | The actual file type |
4 | Unused |
5 | Used only during SAVE- replacement |
6 | Locked flag (Set produces ">" locked files) |
7 | Closed flag (Not set produces "*", or "splat" files) |
The actual file type can be one of the following:
Binary | Decimal | File type |
0000 | 0 | DEL |
0001 | 1 | SEQ |
0010 | 2 | PRG |
0011 | 3 | USR |
0100 | 4 | REL |
Values 5-15 are illegal, but if used will produce very strange results. The 1541 is inconsistent in how it treats these bits. Some routines use all 4 bits, others ignore bit 3, resulting in values from 0-7.
Files, on a standard 1541, are stored using an interleave of 10. Assuming a starting track/sector of 17/0, the chain would run 17/0, 17/10, 17/20, 17/8, 17/18, etc.
*** Non-Standard & Long Directories
Most Commdore floppy disk drives use a single dedicated directory track where all filenames are stored. This limits the number of files stored on a disk based on the number of sectors on the directory track. There are some disk images that contain more files than would normally be allowed. This requires extending the directory off the default directory track by changing the last directory sector pointer to a new track, allocating the new sectors in the BAM, and manually placing (or moving existing) file entries there. The directory of an extended disk can be read and the files that reside there can be loaded without problems on a real drive. However, this is still a very dangerous practice as writing to the extended portion of the directory will cause directory corruption in the non-extended part. Many of the floppy drives core ROM routines ignore the track value that the directory is on and assume the default directory track for operations.
To explain: assume that the directory has been extended from track 18 to track 19/6 and that the directory is full except for a few slots on 19/6. When saving a new file, the drive DOS will find an empty file slot at 19/6 offset $40 and correctly write the filename and a few other things into this slot. When the file is done being saved the final file information will be written to 18/6 offset $40 instead of 19/6 causing some directory corruption to the entry at 18/6. Also, the BAM entries for the sectors occupied by the new file will not be saved and the new file will be left as a SPLAT (*) file.
Attempts to validate the disk will result in those files residing off the directory track to not be allocated in the BAM, and could also send the drive into an endless loop. The default directory track is assumed for all sector reads when validating so if the directory goes to 19/6, then the validate code will read 18/6 instead. If 18/6 is part of the normal directory chain then the validate routine will loop endlessly.
*** BAM layout
The layout of the BAM area (sector 18/0) is a bit more complicated...
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 12 01 41 00 12 FF F9 17 15 FF FF 1F 15 FF FF 1F 10: 15 FF FF 1F 12 FF F9 17 00 00 00 00 00 00 00 00 20: 00 00 00 00 0E FF 74 03 15 FF FF 1F 15 FF FF 1F 30: 0E 3F FC 11 07 E1 80 01 15 FF FF 1F 15 FF FF 1F 40: 15 FF FF 1F 15 FF FF 1F 0D C0 FF 07 13 FF FF 07 50: 13 FF FF 07 11 FF CF 07 13 FF FF 07 12 7F FF 07 60: 13 FF FF 07 0A 75 55 01 00 00 00 00 00 00 00 00 70: 00 00 00 00 00 00 00 00 01 08 00 00 03 02 48 00 80: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 90: 53 48 41 52 45 57 41 52 45 20 31 20 20 A0 A0 A0 A0: A0 A0 56 54 A0 32 41 A0 A0 A0 A0 00 00 00 00 00 B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes | Description |
$00-$01 | Track/Sector location of the first directory sector (should be set to 18/1 but it doesn't matter, and don't trust what is there, always go to 18/1 for first directory entry) |
$02 | Disk DOS version type (see note below) $41 ("A") |
$03 | Unused |
$04-$8F | BAM entries for each track, in groups of four bytes per track, starting on track 1 (see below for more details) |
$90-$9F | Disk Name (padded with $A0) |
$A0-$A1 | Filled with $A0 |
$A2-$A3 | Disk ID |
$A4 | Usually $A0 |
$A5-$A6 | DOS type, usually "2A" |
$A7-$AA | Filled with $A0 |
$AB | Unused ($00) |
$AC-$BF | For DOLPHIN DOS track 36-40 BAM entries, otherwise unused ($00) |
$C0-$D3 | For SPEED DOS track 36-40 BAM entries, otherwise unused ($00) |
$D4-$FF Unused ($00) |
Note: The BAM entries for SPEED, DOLPHIN and ProLogic DOS use the same layout as standard BAM entries. One of the interesting things from the BAM sector is the byte at offset $02, the DOS version byte. If it is set to anything other than $41 or $00, then we have what is called "soft write protection". Any attempt to write to the disk will return the "DOS Version" error code 73 ,"CBM DOS V 2.6 1541". The 1541 is simply telling you that it thinks the disk format version is incorrect. This message will normally come up when you first turn on the 1541 and read the error channel. If you write a $00 or a $41 into 1541 memory location $00FF (for device 0), then you can circumvent this type of write-protection, and change the DOS version back to what it should be.
The BAM entries require a bit (no pun intended) more of a breakdown. Take the first entry at bytes $04-$07 ($12 $FF $F9 $17). The first byte ($12) is the number of free sectors on that track. Since we are looking at the track 1 entry, this means it has 18 (decimal) free sectors. The next three bytes represent the bitmap of which sectors are used/free. Since it is 3 bytes (8 bits/byte) we have 24 bits of storage. Remember that at most, each track only has 21 sectors, so there are a few unused bits.
Bytes | Data | Description |
$04-$07 | $12 $FF $F9 $17 | Track 1 BAM |
$08-$0B | $15 $FF $FF $FF | Track 2 BAM |
$0C-$0F | $15 $FF $FF $1F | Track 3 BAM |
... | ... | ... |
$8C-$8F | $11 $FF $FF $01 | Track 35 BAM |
These entries must be viewed in binary to make any sense. We will use the first entry (track 1) at bytes 04-07:
FF=11111111, F9=11111001, 17=00010111
In order to make any sense from the binary notation, flip the bits around.
111111 11112222 01234567 89012345 67890123 -------------------------- 11111111 10011111 11101000 ^ ^ sector 0 sector 20
Since we are on the first track, we have 21 sectors, and only use up to the bit 20 position. If a bit is on (1), the sector is free. Therefore, track 1 has sectors 9, 10 and 19 used, all the rest are free. Any leftover bits that refer to sectors that don't exist, like bits 21-23 in the above example, are set to allocated.
Each filetype has its own unique properties, but most follow one simple structure. The first file sector is pointed to by the directory and follows a t/s chain, until the track value reaches $00. When this happens, the value in the sector link location indicates how much of the sector is used. For example, the following chain indicates a file 6 sectors long, and ends when we encounter the $00/$34 chain. At this point the last sector occupies from bytes $02-$34.
1 | 2 | 3 | 4 | 5 | 6 |
---- | ---- | ---- | ---- | ---- | ---- |
17/0 | 17/10 | 17/20 | 17/1 | 17/11 | 0/52 |
(11/00) | (11/0A) | (11/14) | (11/01) | (11/0B) | (0/34) |
*** Variations on the D64 layout
These are some variations of the D64 layout:
1. Standard 35 track layout but with 683 error bytes added on to the end of the file. Each byte of the error info corresponds to a single sector stored in the D64, indicating if the sector on the original disk contained an error. The first byte is for track 1/0, and the last byte is for track 35/16.
2. A 40 track layout, following the same layout as a 35 track disk, but with 5 extra tracks. These contain 17 sectors each, like tracks 31-35. Some of the PC utilities do allow you to create and work with these files. This can also have error bytes attached like variant #1.
3. The Commodore 128 allowed for "auto-boot" disks. With this, t/s 1/0 holds a specific byte sequence which the computer recognizes as boot code.
Below is a small chart detailing the standard file sizes of D64 images, 35 or 40 tracks, with or without error bytes.
Disk type | Size |
35 track, no errors | 174848 |
35 track, 683 error bytes | 175531 |
40 track, no errors | 196608 |
40 track, 768 error bytes | 197376 |
The following table (provided by Wolfgang Moser) outlines the differences between the standard 1541 DOS and the various "speeder" DOS's that exist. The 'header 7/8' category is the 'fill bytes' as the end of the sector header of a real 1541 disk.
Disk format | tracks | header 7/8 | Dos type | Diskdos vs. type |
Original CBM DOS v2.6 | 35 | $0f $0f | "2A" | $41/'A' |
*SpeedDOS+ | 40 | $0f $0f | "2A" | $41/'A' |
Professional DOS Initial | 35 | $0f $0f | "2A" | $41/'A' |
Professional DOS Version 1/Prototype | 40 | $0f $0f | "2A" | $41/'A' |
ProfDOS Release | 40 | $0f $0f | "4A" | $41/'A' |
Dolphin-DOS 2.0/3.0 | 35 | $0f $0f | "2A" | $41/'A' |
Dolphin-DOS 2.0/3.0 | 40 | $0d $0f | "2A" | $41/'A' |
PrologicDOS 1541 | 35 | $0f $0f | "2A" | $41/'A' |
PrologicDOS 1541 | 40 | $0f $0f | "2P" | $50/'P' |
ProSpeed 1571 2.0 | 35 | $0f $0f | "2A" | $41/'A' |
ProSpeed 1571 2.0 | 40 | $0f $0f | "2P" | $50/'P' |
*Note: There are also clones of SpeedDOS that exist, such as RoloDOS and DigiDOS. Both are just a change of the DOS startup string.
The location of the extra BAM information in sector 18/0, for 40 track images, will be different depending on what standard the disks have been formatted with. SPEED DOS stores them from $C0 to $D3, DOLPHIN DOS stores them from $AC to $BF and PrologicDOS stored them right after the existing BAM entries from $90-A3. PrologicDOS also moves the disk label and ID forward from the standard location of $90 to $A4. 64COPY and Star Commander let you select from several different types of extended disk formats you want to create/work with.
All three of the speeder DOS's mentioned above don't alter the standard sector interleave of 10 for files and 3 for directories. The reason is that they use a memory cache installed in the drive which reads the entire track in one pass. This alleviates the need for custom interleave values. They do seem to alter the algorithm that finds the next available free sector so that the interleave value can deviate from 10 under certain circumstances, but I don't know why they would bother.
Below is a HEX dump of a Speed DOS BAM sector. Note the location of the extra BAM info from $C0-D3.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 0070: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01 0080: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 0090: A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 00A0: A0 A0 30 30 A0 32 41 A0 A0 A0 A0 00 00 00 00 00 00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00C0: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 00D0: 11 FF FF 01 00 00 00 00 00 00 00 00 00 00 00 00
Below is a HEX dump of a Dolphin DOS BAM sector. Note the location of the extra BAM info from $AC-BF.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 0070: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01 0080: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 0090: A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 00A0: A0 A0 30 30 A0 32 41 A0 A0 A0 A0 00 11 FF FF 01 00B0: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Below is a HEX dump of a PrologicDOS BAM sector. Note that the disk name and ID are now located at $A4 instead of starting at $90.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 0070: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01 0080: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 0090: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 00A0: 11 FF FF 01 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 00B0: A0 A0 A0 A0 A0 A0 30 30 A0 32 50 A0 A0 A0 A0 00 00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*** Error codes
Here is the meaning of the error bytes added onto the end of any extended D64. The CODE is the same as that generated by the 1541 drive controller... it reports these numbers, not the error code we usually see when an error occurs.
Some of what comes below is taken from Immers/Neufeld book "Inside Commodore DOS". Note the descriptions are not completely accurate as to what the drive DOS is actually doing to seek/read/decode/write sectors, but serve as simple examples only. The "type" field is where the error usually occurs, whether it's searching for any SYNC mark, any header ID, any valid header, or reading a sector.
These first errors are "seek" errors, where the disk controller is simply reading headers and looking at descriptor bytes, checksums, format ID's and reporting what errors it sees. These errors do *not* necessarily apply to the exact sector being looked for. This fact makes duplication of these errors very unreliable.
Code : $03 Error : 21 Type : Seek Message : No SYNC sequence found.
Each sector data block and header block are preceeded by SYNC marks. If *no* sync sequence is found within 20 milliseconds (only ~1/10 of a disk rotation!) then this error is generated. This error used to mean the entire track is bad, but it does not have to be the case. Only a small area of the track needs to be without a SYNC mark and this error will be generated.
Converting this error to a D64 is very problematic because it depends on where the physical head is on the disk when a read attempt is made. If it is on valid header/sectors then it won't occur. If it happens over an area without SYNC marks, it will happen.
Code : $02 Error : 20 Type : Seek Message : Header descriptor byte not found (HEX $08, GCR $52)
Each sector is preceeded by an 8-byte GCR header block, which starts with the value $52 (GCR). If this value is not found after 90 attempts, this error is generated.
Basically, what a track has is SYNC marks, and possibly valid data blocks, but no valid header descriptors.
Code : $09 Error : 27 Type : Seek Message : Checksum error in header block
The header block contains a checksum value, calculated by XOR'ing the TRACK, SECTOR, ID1 and ID2 values. If this checksum is wrong, this error is generated.
Code : $0B Error : 29 Type : Seek Message : Disk sector ID mismatch
The ID's from the header block of the currently read sector are compared against the ones from the low-level header of 18/0. If there is a mismatch, this error is generated.
Code : $02 Error : 20 Type : Seek Message : Header block not found
This error can be reported again when searching for the correct header block. An image of the header is built and searched for, but not found after 90 read attempts. Note the difference from the first occurance. The first one only searches for a valid ID, not the whole header.
Note that error 20 occurs twice during this phase. The first time is when a header ID is being searched for, the second is when the proper header pattern for the sector being searched for is not found.
From this point on, all the errors apply to the specific sector you are looking for. If a read passed all the previous checks, then we are at the sector being searched for.
Note that the entire sector is read before these errors are detected. Therefore the data, checksum and off bytes are available.
Code : $04 Error : 22 Type : Read Message : Data descriptor byte not found (HEX $07, GCR $55)
Each sector data block is preceeded by the value $07, the "data block" descriptor. If this value is not there, this error is generated. Each encoded sector has actually 260 bytes. First is the descriptor byte, then follows the 256 bytes of data, a checksum, and two "off" bytes.
Code : $05 Error : 23 Type : Read Message : Checksum error in data block
The checksum of the data read of the disk is calculated, and compared against the one stored at the end of the sector. If there's a discrepancy, this error is generated.
Code : $0F Error : 74 Type : Read Message : Drive Not Ready (no disk in drive or no device 1)
These errors only apply when writing to a disk. I don't see the usefulness of having these as they cannot be present when only *reading* a disk.
Code : $06 Error : 24 Type : Write Message : Write verify (on format)
Code : $07 Error : 25 Type : Write Message : Write verify error
Once the GCR-encoded sector is written out, the drive waits for the sector to come around again and verifies the whole 325-byte GCR block. Any errors encountered will generate this error.
Code : $08 Error : 26 Type : Write Message : Write protect on
Self explanatory. Remove the write-protect tab, and try again.
Code : $0A Error : 28 Type : Write Message : Write error
In actual fact, this error never occurs, but it is included for completeness.
This is not an error at all, but it gets reported when the read of a sector is ok.
Code : $01 Error : 00 Type : N/A Message : No error.
Self explanatory. No errors were detected in the reading and decoding of the sector.
The advantage with using the 35 track D64 format, regardless of error bytes, is that it can be converted directly back to a 1541 disk by either using the proper cable and software on the PC, or send it down to the C64 and writing it back to a 1541. It is the best documented format since it is also native to the C64, with many books explaining the disk layout and the internals of the 1541.
(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)
This file type, created by Teemu Rantanen, is used on the X64 emulator (a UNIX-based emulator) which has been superceeded by VICE. Both VICE and X64 support the X64 file standard, with VICE also supporting the regular D64 and T64 files.
X64 is not a specific type of file, but rather encompasses *all* known C64 disk types (hard disk, floppies, etc). An X64 is created by prepending a 64-byte header to an existing image (1541, 1571, etc) and setting specific bytes which describe what type of image follows. This header has undergone some revision, and this description is based on the 1.02 version, which was the last known at the time of writing.
The most common X64 file you will see is the D64 variety, typically 174912 bytes long (174848 for the D64 and 64 bytes for the header, assuming no error bytes are appended). The header layout (as used in 64COPY) is as follows:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 0000: 43 15 41 64 01 02 01 23 00 00 00 00 00 00 00 00 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0040: XX XX XX <- standard C64 image starts here....
Bytes | Description |
$00-$03 | This is the "Magic header" ($43 $15 $41 $64) |
$04 | Header version major ($01) |
$05 | Header version minor ($01, now its up to $02) |
$06 | Device type represented |
$07 | Maximum tracks in image (only in version 1.02 or greater) 1540/41/70: 35 1571: 35 1581: 80 (Logical single-sided disk) |
$08 | Number of disk sides in image. This value must be $00 for all 1541 and 1581 formats. $00=No second side $01=Second side |
$09 | Error data flag. |
$0A-$1F | Unused, set to $00 |
$20-$3E | Disk image description (in ASCII or ISO Latin/1) |
$3F | Always set to $00 |
$40- | Standard C64 file begins here. |
The device types are:
Value | Drive type |
$00 | 1540 See note below... |
$01 | 1541 (Default) |
$02 | 1542 |
$03 | 1551 |
$04 | 1570 |
$05 | 1571 |
$06 | 1572 |
$08 | 1581 |
$10 | 2031 or 4031 |
$11 | 2040 or 3040 |
$12 | 2041 |
$18 | 4040 |
$20 | 8050 |
$21 | 8060 |
$22 | 8061 |
$30 | SFD-1001 |
$31 | 8250 |
$32 | 8280 |
The first four bytes used for the device type at position $06 ($00 to $03) are functionally the same, and are compatible with older version of X64 files. Some old X64 files might have $00 for the device type (instead of $01), but it makes no real difference.
As most instances of X64 files will be strictly 1541 images, bytes $08-$3F are set to zero, and some versions of the X64 emulator don't use bytes $08-$3F.
(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)
Similar to the D64 (1541), the 1571 drive can operate in either single-sided (1541 compatible) mode or double-sided (1571) mode. In this section I will be dealing with the double-sided mode only. For the breakdown of the single-sided mode, see the D64 section.
The D71 has 70 tracks, double that of the 1541, with a DOS file size of 349696 bytes. If the error byte block (1366 bytes) is attached, this makes the file size 351062 bytes. The track range and offsets into the D71 files are as follows:
Track | Sec/trk | # Sectors |
1-17 (side 0) | 21 | 357 |
18-24 (side 0) | 19 | 133 |
25-30 (side 0) | 18 | 108 |
31-35 (side 0) | 17 | 85 |
36-52 (side 1) | 21 | 357 |
53-59 (side 1) | 19 | 133 |
60-65 (side 1) | 18 | 108 |
66-70 (side 1) | 17 | 85 |
Track | #Sect | #SectorsIn | D71 Offset |
1 | 21 | 0 | $00000 |
2 | 21 | 21 | $01500 |
3 | 21 | 42 | $02A00 |
4 | 21 | 63 | $03F00 |
5 | 21 | 84 | $05400 |
6 | 21 | 105 | $06900 |
7 | 21 | 126 | $07E00 |
8 | 21 | 147 | $09300 |
9 | 21 | 168 | $0A800 |
10 | 21 | 189 | $0BD00 |
11 | 21 | 210 | $0D200 |
12 | 21 | 231 | $0E700 |
13 | 21 | 252 | $0FC00 |
14 | 21 | 273 | $11100 |
15 | 21 | 294 | $12600 |
16 | 21 | 315 | $13B00 |
17 | 21 | 336 | $15000 |
18 | 19 | 357 | $16500 |
19 | 19 | 376 | $17800 |
20 | 19 | 395 | $18B00 |
21 | 19 | 414 | $19E00 |
22 | 19 | 433 | $1B100 |
23 | 19 | 452 | $1C400 |
24 | 19 | 471 | $1D700 |
25 | 18 | 490 | $1EA00 |
26 | 18 | 508 | $1FC00 |
27 | 18 | 526 | $20E00 |
28 | 18 | 544 | $22000 |
29 | 18 | 562 | $23200 |
30 | 18 | 580 | $24400 |
31 | 17 | 598 | $25600 |
32 | 17 | 615 | $26700 |
33 | 17 | 632 | $27800 |
34 | 17 | 649 | $28900 |
35 | 17 | 666 | $29A00 |
36 | 21 | 683 | $2AB00 |
37 | 21 | 704 | $2C000 |
38 | 21 | 725 | $2D500 |
39 | 21 | 746 | $2EA00 |
40 | 21 | 767 | $2FF00 |
41 | 21 | 788 | $31400 |
42 | 21 | 809 | $32900 |
43 | 21 | 830 | $33E00 |
44 | 21 | 851 | $35300 |
45 | 21 | 872 | $36800 |
46 | 21 | 893 | $37D00 |
47 | 21 | 914 | $39200 |
48 | 21 | 935 | $3A700 |
49 | 21 | 956 | $3BC00 |
50 | 21 | 977 | $3D100 |
51 | 21 | 998 | $3E600 |
52 | 21 | 1019 | $3FB00 |
53 | 19 | 1040 | $41000 |
54 | 19 | 1059 | $42300 |
55 | 19 | 1078 | $43600 |
56 | 19 | 1097 | $44900 |
57 | 19 | 1116 | $45C00 |
58 | 19 | 1135 | $46F00 |
59 | 19 | 1154 | $48200 |
60 | 18 | 1173 | $49500 |
61 | 18 | 1191 | $4A700 |
62 | 18 | 1209 | $4B900 |
63 | 18 | 1227 | $4CB00 |
64 | 18 | 1245 | $4DD00 |
65 | 18 | 1263 | $4EF00 |
66 | 17 | 1281 | $50100 |
67 | 17 | 1298 | $51200 |
68 | 17 | 1315 | $52300 |
69 | 17 | 1332 | $53400 |
70 | 17 | 1349 | $54500 |
The directory structure is the same as a D64/1541. All the same filetypes apply, the directory still only holds 144 files per disk and should only exist on track 18.
The first two bytes of the sector ($12/$04 or 18/4) indicate the location of the next track/sector of the directory. If the track value is set to $00, then it is the last sector of the directory. It is possible, however unlikely, that the directory may *not* be competely on track 18 (some disks do exist like this). Just follow the chain anyhow.
When the directory is done, the track value will be $00. The sector link should contain a value of $FF, meaning the whole sector is allocated, but the actual value doesn't matter. The drive will return all the available entries anyways. This is a breakdown of a standard directory sector and entry:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 12 04 82 11 00 4A 45 54 20 53 45 54 20 57 49 4C 10: 4C 59 A0 A0 A0 00 00 00 00 00 00 00 00 00 2B 00 20: 00 00 82 0F 01 4A 53 57 20 31 A0 A0 A0 A0 A0 A0 30: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 BF 00 40: 00 00 82 06 03 53 4F 4E 20 4F 46 20 42 4C 41 47 50: 47 45 52 A0 A0 00 00 00 00 00 00 00 00 00 AE 00 60: 00 00 82 15 0D 50 4F 54 54 59 20 50 49 47 45 4F 70: 4E A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 A2 00 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes | Description |
$00-$1F | First directory entry |
$20-$3F | Second dir entry |
$40-$5F | Third dir entry |
$60-$7F | Fourth dir entry |
$80-$9F | Fifth dir entry |
$A0-$BF | Sixth dir entry |
$C0-$DF | Seventh dir entry |
$E0-$FF | Eighth dir entry |
This is a breakdown of a standard directory entry:
Bytes | Description |
$00-$01 | Track/Sector location of next directory sector ($00/$FF if its the last sector) |
$02 | File type |
$03-$04 | Track/sector location of first sector of file |
$05-$14 | 16 character filename (in PETASCII, padded with $A0) |
$15-$16 | Track/Sector location of first side-sector block (REL file only) |
$17 | REL file record length (REL file only, max. value 254) |
$18-$1D | Unused (except with GEOS disks) |
$1E-$1F | File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is <= #sectors * 254 |
The file type field is used as follows:
Bits | Description |
0-3 | The actual file type |
4 | Unused |
5 | Used only during SAVE- replacement |
6 | Locked flag (Set produces ">" locked files) |
7 | Closed flag (Not set produces "*", or "splat" files) |
The actual file type can be one of the following:
Binary | Decimal | File type |
0000 | 0 | DEL |
0001 | 1 | SEQ |
0010 | 2 | PRG |
0011 | 3 | USR |
0100 | 4 | REL |
Values 5-15 are illegal, but if used will produce very strange results. The 1571 is inconsistent in how it treats these bits. Some routines use all 4 bits, others ignore bit 3, resulting in values from 0-7.
When the 1571 is in is native ("1571") mode, files are stored with a sector interleave of 6, rather than 10 which the 1541 (and the 1571 in "1541" mode) uses. The directory still uses an interleave of 3.
*** Non-Standard & Long Directories
Most Commodore floppy disk drives use a single dedicated directory track where all filenames are stored. This limits the number of files stored on a disk based on the number of sectors on the directory track. There are some disk images that contain more files than would normally be allowed. This requires extending the directory off the default directory track by changing the last directory sector pointer to a new track, allocating the new sectors in the BAM, and manually placing (or moving existing) file entries there. The directory of an extended disk can be read and the files that reside there can be loaded without problems on a real drive. However, this is still a very dangerous practice as writing to the extended portion of the directory will cause directory corruption in the non- extended part. Many of the floppy drives core ROM routines ignore the track value that the directory is on and assume the default directory track for operations.
To explain: assume that the directory has been extended from track 18 to track 19/6 and that the directory is full except for a few slots on 19/6. When saving a new file, the drive DOS will find an empty file slot at 19/6 offset $40 and correctly write the filename and a few other things into this slot. When the file is done being saved the final file information will be written to 18/6 offset $40 instead of 19/6 causing some directory corruption to the entry at 18/6. Also, the BAM entries for the sectors occupied by the new file will not be saved and the new file will be left as a SPLAT (*) file.
Attempts to validate the disk will result in those files residing off the directory track to not be allocated in the BAM, and could also send the drive into an endless loop. The default directory track is assumed for all sector reads when validating so if the directory goes to 19/6, then the validate code will read 18/6 instead. If 18/6 is part of the normal directory chain then the validate routine will loop endlessly.
*** Bam layout The BAM is somewhat different as it now has to take 35 new tracks into account. In order to do this, most of the extra BAM information is stored on track 53/0, and the remaining sectors on track 53 are marked in the BAM as allocated. This does mean that except for one allocated sector on track 53, the rest of the track is unused and wasted. (Track 53 is the equivalent to track 18, but on the flip side of the disk). Here is a dump of the first BAM sector...
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 12 01 41 80 12 FF F9 17 15 FF FF 1F 15 FF FF 1F 10: 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 20: 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 30: 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 15 FF FF 1F 40: 15 FF FF 1F 15 FF FF 1F 11 FC FF 07 13 FF FF 07 50: 13 FF FF 07 13 FF FF 07 13 FF FF 07 13 FF FF 07 60: 13 FF FF 07 12 FF FF 03 12 FF FF 03 12 FF FF 03 70: 12 FF FF 03 12 FF FF 03 12 FF FF 03 11 FF FF 01 80: 11 FF FF 01 11 FF FF 01 11 FF FF 01 11 FF FF 01 90: A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0: A0 A0 30 30 A0 32 41 A0 A0 A0 A0 00 00 00 00 00 B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 15 15 15 E0: 15 15 15 15 15 15 15 15 15 15 15 15 15 15 00 13 F0: 13 13 13 13 13 12 12 12 12 12 12 11 11 11 11 11
Bytes | Description |
$00-$01 | Track/Sector location of the first directory sector (should be set to 18/1 but it doesn't matter, and don't trust what is there, always go to 18/1 for first directory entry) |
$02 | Disk DOS version type (see note below) $41 ('A') = 1541 |
$03 | Double-sided flag $00 - Single sided disk $80 - Double sided disk |
$04-8F | BAM entries for each track, in groups of four bytes per track, starting on track 1. |
$90-$9F | Disk Name (padded with $A0) |
$A0-$A1 | Filled with $A0 |
$A2-$A3 | Disk ID |
$A4 | Usually $A0 |
$A5-$A6 | DOS type, usually "2A" |
$A7-$AA | Filled with $A0 |
$AB-$DC | Not used ($00's) |
$DD-$FF | Free sector count for tracks 36-70 (1 byte/track). |
The "free sector" entries for tracks 36-70 are likely included here in the first BAM sector due to some memory restrictions in the 1571 drive. There is only enough memory available for one BAM sector, but in order to generate the "blocks free" value at the end of a directory listing, the drive needs to know the extra track "free sector" values. It does make working with the BAM a little more difficult, though.
These are the values that would normally be with the 4-byte BAM entry, but the rest of the entry is contained on 53/0.
Note: If the DOS version byte is set to anything other than $41 or $00, then we have what is called "soft write protection". Any attempt to write to the disk will return the "DOS Version" error code 73. The 1571 is simply telling you that it thinks the disk format version is incorrect.
The BAM entries require some explanation. Take the first entry at bytes $04-$07 ($12 $FF $F9 $17). The first byte ($12) is the number of free sectors on that track. Since we are looking at the track 1 entry, this means it has 18 (decimal) free sectors.
The next three bytes represent the bitmap of which sectors are used/free. Since it is 3 bytes (8 bits/byte) we have 24 bits of storage. Remember that at most, each track only has 21 sectors, so there are a few unused bits. These entries must be viewed in binary to make any sense. We will use the first entry (track 1) at bytes 04-07:
FF=11111111, F9=11111001, 17=00010111
In order to make any sense from the binary notation, flip the bits around.
111111 11112222 01234567 89012345 67890123 -------------------------- 11111111 10011111 11101000 ^ ^ sector 0 sector 20
Since we are on the first track, we have 21 sectors, and only use up to the bit 20 position. If a bit is on (1), the sector is free. Therefore, track 1 has sectors 9,10 and 19 used, all the rest are free.
In order to complete the BAM, we must check 53/0.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF 10: FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF 20: 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F FF FF 1F 30: FF FF 1F 00 00 00 FF FF 07 FF FF 07 FF FF 07 FF 40: FF 07 FF FF 07 FF FF 07 FF FF 03 FF FF 03 FF FF 50: 03 FF FF 03 FF FF 03 FF FF 03 FF FF 01 FF FF 01 60: FF FF 01 FF FF 01 FF FF 01 00 00 00 00 00 00 00 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Each track from 36-70 has 3 byte entries, starting at address $00.
Byte: $00-$02: $FF $FF $1F - BAM map for track 36 $03-$05: $FF $FF $1F - BAM map for track 37 ... $33-$35: $00 $00 $00 - BAM map for track 53 ... $66-$68: $FF $FF $01 - BAM map for track 70 $69-$FF: - Not used
You can break down the entries for tracks 36-70 the same way as track 1, just combine the free sector bytes from 18/0 and the BAM usage from 53 to get the full 4-byte entry.
Just like a D64, you can attach error bytes to the file, for sector error information. This block is 1366 bytes long, 1 byte for each of the 1366 sectors in the image. With the error bytes, the file size is 351062 bytes.
(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)
Like D64 and D71, this is a byte for byte copy of a physical 1581 disk. It consists of 80 tracks, 40 sectors each (0 to 39) for a size of 819200 bytes, or 3200 sectors. If the error byte block is attached, this makes the file size 822400 bytes.
There are three sectors on the directory track used for disk internals (header and BAM), leaving 37 sectors for filename entries, thus allowing for 296 files (37 * 8) to be stored at the root level of the disk.
The actual physical layout on the disk is quite different from what the user sees, but this is unimportant to the scope of this section. One important difference from the D64 and D71 is all the sector interleaves are now 1 for both files and directory storage (rather than 3 for directory and 10 for file on a D64/D71). This is due to the built-in buffering in the 1581. When reading a sector, the whole track will be buffered in memory, and any sectors being modified will be done in memory. Once it has to be written, the whole track will be written out in one step.
The track range and offsets into the D81 files are as follows:
Track | #Sect | #SectorsIn | D81 Offset |
1 | 40 | 0 | $00000 |
2 | 40 | 40 | $02800 |
3 | 40 | 80 | $05000 |
4 | 40 | 120 | $07800 |
5 | 40 | 160 | $0A000 |
6 | 40 | 200 | $0C800 |
7 | 40 | 240 | $0F000 |
8 | 40 | 280 | $11800 |
9 | 40 | 320 | $14000 |
10 | 40 | 360 | $16800 |
11 | 40 | 400 | $19000 |
12 | 40 | 440 | $1B800 |
13 | 40 | 480 | $1E000 |
14 | 40 | 520 | $20800 |
15 | 40 | 560 | $23000 |
16 | 40 | 600 | $25800 |
17 | 40 | 640 | $28000 |
18 | 40 | 680 | $2A800 |
19 | 40 | 720 | $2D000 |
20 | 40 | 760 | $2F800 |
21 | 40 | 800 | $32000 |
22 | 40 | 840 | $34800 |
23 | 40 | 880 | $37000 |
24 | 40 | 920 | $39800 |
25 | 40 | 960 | $3C000 |
26 | 40 | 1000 | $3E800 |
27 | 40 | 1040 | $41000 |
28 | 40 | 1080 | $43800 |
29 | 40 | 1120 | $46000 |
30 | 40 | 1160 | $48800 |
31 | 40 | 1200 | $4B000 |
32 | 40 | 1240 | $4D800 |
33 | 40 | 1280 | $50000 |
34 | 40 | 1320 | $52800 |
35 | 40 | 1360 | $55000 |
36 | 40 | 1400 | $57800 |
37 | 40 | 1440 | $5A000 |
38 | 40 | 1480 | $5C800 |
39 | 40 | 1520 | $5F000 |
40 | 40 | 1560 | $61800 |
41 | 40 | 1600 | $64000 |
42 | 40 | 1640 | $66800 |
43 | 40 | 1680 | $69000 |
44 | 40 | 1720 | $6B800 |
45 | 40 | 1760 | $6E000 |
46 | 40 | 1800 | $70800 |
47 | 40 | 1840 | $73000 |
48 | 40 | 1880 | $75800 |
49 | 40 | 1920 | $78000 |
50 | 40 | 1960 | $7A800 |
51 | 40 | 2000 | $7D000 |
52 | 40 | 2040 | $7F800 |
53 | 40 | 2080 | $82000 |
54 | 40 | 2120 | $84800 |
55 | 40 | 2160 | $87000 |
56 | 40 | 2200 | $89800 |
57 | 40 | 2240 | $8C000 |
58 | 40 | 2280 | $8E800 |
59 | 40 | 2320 | $91000 |
60 | 40 | 2360 | $93800 |
61 | 40 | 2400 | $96000 |
62 | 40 | 2440 | $98800 |
63 | 40 | 2480 | $9B000 |
64 | 40 | 2520 | $9D800 |
65 | 40 | 2560 | $A0000 |
66 | 40 | 2600 | $A2800 |
67 | 40 | 2640 | $A5000 |
68 | 40 | 2680 | $A7800 |
69 | 40 | 2720 | $AA000 |
70 | 40 | 2760 | $AC800 |
71 | 40 | 2800 | $AF000 |
72 | 40 | 2840 | $B1800 |
73 | 40 | 2880 | $B4000 |
74 | 40 | 2920 | $B6800 |
75 | 40 | 2960 | $B9000 |
76 | 40 | 3000 | $BB800 |
77 | 40 | 3040 | $BE000 |
78 | 40 | 3080 | $C0800 |
79 | 40 | 3120 | $C3000 |
80 | 40 | 3160 | $C5800 |
The header sector is stored at 40/0, and contains the disk name, ID and DOS version bytes, but the BAM is no longer contained here (like the D64).
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 28 03 44 00 31 35 38 31 20 55 54 49 4C 49 54 59 10: 20 56 30 31 A0 A0 47 42 A0 33 44 A0 A0 00 00 00 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes | Description |
$00-$01 | Track/Sector location of the first directory sector (should be set to 40/3 but it doesn't matter, and don't trust what is there, always go to 40/3 for first directory entry) |
$02 | Disk DOS version type (see note below) $44 ('D')=1581 |
$03 | $00 |
$04-$13 | 16 character Disk Name (padded with $A0) |
$14-$15 | $A0 |
$16-$17 | Disk ID |
$18 | $A0 |
$19 | DOS Version ("3") |
$1A | Disk version ("D") |
$1B-$1C | $A0 |
$1D-$FF | Unused (usually $00) |
The following might be set if the disk is a GEOS format (this info is based on the D64 layout, and might not prove to be true)
Bytes | Description |
$AB-$AC | Border sector (GEOS only, else set to $00) |
$AD-$BC | GEOS ID string ("geos FORMAT V1.x" GEOS only, else $00) |
$BD-$FF | Unused (usually $00) |
Note: If the DOS version byte is changed to anything other than a $44 (or $00), then we have what is called "soft write protection". Any attempt to write to the disk will return the "DOS Version" error code 73. The drive is simply telling you that it thinks the disk format version is incompatible.
The directory track should be contained totally on track 40. Sectors 3-39 contain the entries and sector 1 and 2 contain the BAM (Block Availability Map). Sector 0 holds the disk name and ID. The first directory sector is always 40/3, even though the t/s pointer at 40/0 (first two bytes) might point somewhere else. It goes linearly up the sector count, 3-4-5-6-etc. Each sector holds up to eight entries.
The first two bytes of the sector ($28/$04) indicate the location of the next track/sector of the directory (40/4). If the track is set to $00, then it is the last sector of the directory. It is possible, however unlikely, that the directory may *not* be competely on track 40. Just follow the chain anyhow.
When the directory is done (track=$00), the sector should contain an $FF, meaning the whole sector is allocated. Theactual value doesn't matter as all the entries will be returned anyways. Each directory sector has the following layout:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 28 04 81 2B 00 53 43 52 45 45 4E 20 20 33 A0 A0 10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 02 00 20: 00 00 81 2B 01 53 43 52 45 45 4E 20 20 34 A0 A0 30: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 03 00 40: 00 00 81 2B 02 53 43 52 45 45 4E 20 20 35 A0 A0 50: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 07 00 60: 00 00 81 2B 08 53 43 52 45 45 4E 20 20 36 A0 A0 70: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 08 00 80: 00 00 81 2B 14 53 43 52 45 45 4E 20 20 37 A0 A0 90: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 07 00 A0: 00 00 81 24 00 53 43 52 45 45 4E 20 20 38 A0 A0 B0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 0B 00 C0: 00 00 82 24 04 46 49 4C 45 34 32 39 33 36 39 30 D0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 07 00 E0: 00 00 82 24 06 46 49 4C 45 32 35 37 38 38 31 35 F0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 05 00
Bytes | Description |
$00-$1F | First directory entry |
$20-$3F | Second dir entry |
$40-$5F | Third dir entry |
$60-$7F | Fourth dir entry |
$80-$9F | Fifth dir entry |
$A0-$BF | Sixth dir entry |
$C0-$DF | Seventh dir entry |
$E0-$FF | Eighth dir entry |
This is a breakdown of a standard directory entry:
Bytes | Description |
$00-$01 | Track/Sector location of next directory sector |
$02 | File type |
$03-$04 | Track/sector location of first sector of file or partition |
$05-$14 | 16 character filename (in PETASCII, padded with $A0) |
$15-$16 | Track/Sector location of first SUPER SIDE SECTOR block (REL file only) |
$17 | REL file record length (REL file only) |
$18-$1B | Unused (except with GEOS disks) |
$1C-$1D | (Used during an SAVE or OPEN, holds the new t/s link) |
$1E-$1F | File or partition size in sectors, low/high byte order ($1E+$1F*256). The approx. file size in bytes is <= #sectors * 254 |
The file type field is used as follows:
Bits | Description |
0-3 | The actual file type |
4 | Unused |
5 | Used only during SAVE- replacement |
6 | Locked flag (Set produces ">" locked files) |
7 | Closed flag (Not set produces "*", or "splat" files) |
The actual file type can be one of the following:
Binary | Decimal | File type |
0000 | 0 | DEL |
0001 | 1 | SEQ |
0010 | 2 | PRG |
0011 | 3 | USR |
0100 | 4 | REL |
0101 | 5 | CBM (partition or sub-directory) |
Values 6-15 are illegal, but if used will produce very strange results.
*** Non-Standard & Long Directories
Most Commdore floppy disk drives use a single dedicated directory track where all filenames are stored. This limits the number of files stored on a disk based on the number of sectors on the directory track. There are some disk images that contain more files than would normally be allowed. This requires extending the directory off the default directory track by changing the last directory sector pointer to a new track, allocating the new sectors in the BAM, and manually placing (or moving existing) file entries there. The directory of an extended disk can be read and the files that reside there can be loaded without problems on a real drive. However, this is still a very dangerous practice as writing to the extended portion of the directory will cause directory corruption in the non-extended part. Many of the floppy drives core ROM routines ignore the track value that the directory is on and assume the default directory track for operations.
*** BAM layout
The BAM is located on 40/1 (for side 0, tracks 1-40) and 40/2 (for side 1, tracks 41-80). Each entry takes up six bytes, one for the "free sector" count and five for the allocation bitmap.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 28 02 44 BB 47 42 C0 00 00 00 00 00 00 00 00 00 10: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF 20: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF 30: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 40: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF 50: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF 60: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 70: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF 80: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF 90: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF A0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF B0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF C0: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF D0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF E0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF F0: FF FF FF FF 28 FF FF FF FF FF 24 F0 FF 2D FF FE
Bytes: $00-$01: Track/sector of next bam sector (40/2) $02: Version # ('D') $03: One's complement of version# ($BB) $04-$05: Disk ID bytes (same as 40/0 Disk ID) $06: I/O byte bit 7 set - Verify on bit 7 clear - Verify off bit 6 set - Check header CRC bit 6 clear - Don't check header CRC $07: Auto-boot-loader flag $08-$0F: Reserved for future (set to $00) $10-$15: BAM entry for track 1 (track 41, side 1) $16-$1B: BAM entry for track 2 (track 42, side 1) ... $46-$4B: BAM entry for track 10 (track 50, side 1) ... $82-$87: BAM entry for track 20 (track 60, side 1) ... $BE-$C3: BAM entry for track 30 (track 70, side 1) ... $FA-$FF: BAM entry for track 40 (track 80, side 1)
The BAM entries require some explanation, so lets look at the track 40 entry at bytes $FA-FF ($24 $F0 $FF $2D $FF $FE). The first byte ($24, or 36 decimal) is the number of free sectors on that track. The next five bytes represent the bitmap of which sectors are used/free. Since it is five bytes (8 bits/byte) we have 40 bits of storage. Since this format has 40 sectors/track, the whole five bytes are used.
F0: .. .. .. .. .. .. .. .. .. .. 24 F0 FF 2D FF FE
The last five bytes of any BAM entry must be viewed in binary to make any sense. We will once again use track 40 as our reference:
F0=11110000, FF=11111111, 2D=00101101, FF=11111111, FE=11111110
In order to make any sense from the binary notation, flip the bits around.
111111 11112222 22222233 33333333 Sector 01234567 89012345 67890123 45678901 23456789 -------------------------- -------- -------- 00001111 11111111 10110100 11111111 01111111
Note that if a bit is on (1), the sector is free. Therefore, track 40 has sectors 0-3, 17, 20, 22, 23 and 32 used, all the rest are free.
The second BAM (for side 1) contains the entries for tracks 41-80.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 00 FF 44 BB 47 42 C0 00 00 00 00 00 00 00 00 00 10: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF 20: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF 30: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 40: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF 50: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF 60: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 70: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF 80: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF 90: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF A0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF B0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF C0: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF D0: 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF E0: FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF 28 FF F0: FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF FF FF
It is laid out exactly as the side 0 BAM except for one difference. The track/sector reference for the next sector should be set to $00/$FF, indicating there is no next sector.
*** REL files The REL filetype requires some extra explaining. It was designed to make access to data *anywhere* on the disk very fast. Take a look at this directory entry...
00: 00 FF 84 27 00 41 44 44 49 54 49 4F 4E 41 4C 20 10: 49 4E 46 4F A0 27 02 FE 00 00 00 00 00 00 D2 0B
The third byte ($84) indicates this entry is a REL file and that the three normally empty entries at offset $15, $16 and $17 are now used as they are explained above. It's the track/sector chain that this entry points to, called the SUPER SIDE SECTOR, which is of interest here (in this case, 39/2). The SUPER SIDE SECTOR is very different from the D64 format. If you check the D64 entry for a REL file and do the calculations, you will find that the maximum file size of the REL file is 720 data sectors. With the new SUPER SIDE SECTOR, you can now have 126 groups of these SIDE SECTORS chains, allowing for file sizes up to (theoretically) 90720 sectors, or about 22.15 Megabytes.
Here is a dump of the beginning of the SUPER SIDE SECTOR...
00: 27 01 FE 27 01 15 09 03 0F 38 16 4A 1C 00 00 00 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes: $00-$01: Track/sector of first side sector in group 0 $02: Always $FE $03-$04: Track/sector of first side sector in group 0 (again) ... $FD-$FE: Track/sector of first side sector in group 125 $FF: Unused (likely $00)
The side sector layout is the same as the D64/1571.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 12 0A 00 FE 15 09 12 0A 0F 0B 0C 0C 09 0D 06 0E 10: 15 07 15 08 15 0A 15 0B 15 0C 15 0D 15 0E 15 0F 20: 15 10 15 11 15 12 15 13 15 14 15 15 15 16 15 17 30: 15 18 15 19 15 1A 15 1B 15 1C 15 1D 15 1E 15 1F 40: 15 20 15 21 15 22 15 23 15 24 15 25 15 26 15 27 50: 14 00 14 01 14 02 14 03 14 04 14 05 14 06 14 07 60: 14 08 14 09 14 0A 14 0B 14 0C 14 0D 14 0E 14 0F 70: 14 10 14 11 14 12 14 13 14 14 14 15 14 16 14 17 80: 14 18 14 19 14 1A 14 1B 14 1C 14 1D 14 1E 14 1F 90: 14 20 14 21 14 22 14 23 14 24 14 25 14 26 14 27 A0: 13 00 13 01 13 02 13 03 13 04 13 05 13 06 13 07 B0: 13 08 13 09 13 0A 13 0B 13 0C 13 0D 13 0E 13 0F C0: 13 10 13 11 13 12 13 13 13 14 13 15 13 16 13 17 D0: 13 18 13 19 13 1A 13 1B 13 1C 13 1D 13 1E 13 1F E0: 13 20 13 21 13 22 13 23 13 24 13 25 13 26 13 27 F0: 12 00 12 01 12 02 12 03 12 04 12 05 12 06 12 07
Bytes: $00: Track location of next side-sector ($00 if last sector) $01: Sector location of next side-sector $02: Side-sector block number (first sector is $00, the next is $01, then $02, etc) $03: REL file RECORD size (from directory entry) $04-$0F: Track/sector locations of the six other side-sectors. Note the first entry is this very sector we have listed here. The next is the next t/s listed at the beginning of the sector. All of this information must be correct. If one of these chains is $00/$00, then we have no more side sectors. Also, all of these (up to six) side sectors must have the same values in this range. $10-$FF: T/S chains of *each* sector of the data portion. When we get a $00/$00, we are at the end of the file.
*** 1581 Partitions and Sub-directories
At the beginning of this section it was stated that the 1581 can hold 296 entries "at the root level". The 1581 also has the ability to partition areas of the disk. Under the right conditions these can become sub-directories, acting as a small diskette, complete with its own directory and BAM. When you are inside of a sub-directory, no other files except those in that directory are visible, or can be affected.
To the 1581, this file will show up as a "CBM" filetype in a directory. All this does is tell the disk that a file, starting at X/Y track/sector and Z sectors large exists. Doing a validate will not harm these files as they have a directory entry, and are fully allocated in the BAM.
There are two main uses for partitions. One is to simply allocate a section of the disk to be used for direct-access reads/writes, and lock it away from being overwritten after a VALIDATE. The second is as a sub-directory, basically a small "disk within a disk".
In order to use a partition as a sub-directory, it must adhere to the following four rules:
1. If must start on sector 0 2. It's size must be in multiples of 40 sectors 3. It must be a minimum of 120 sectors long (3 tracks) 4. If must not start on or cross track 40, which limits the biggest directory to 1600 sectors (tracks 1-39).
This is a dump of a sub-directory entry:
00: 00 FF 85 29 00 50 41 52 54 49 54 49 4F 4E 20 31 10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 40 06
It is a partition starting on track 41/0, extends for 1600 sectors, and has been formatted as a sub-directory. Note that when a partition is created, the area being allocated is not touched in any way. If you want it set up as a sub-directory, you must issue the FORMAT command to the 1581 to create the central directory and BAM. Also note that from the directory entry you can't tell whether it is a sub-directory or not, just that it fits the sub-directory parameters.
The BAM track for the sub-directory exists on the first track of the partition, and has the same layout as the disk BAM on track 40. The biggest difference is the "disk name" is what what given when the partition was formatted rather than what the actual disk name is. Also, except for the free sectors in the partition area, all other sectors in the BAM will be allocated.
If the partition size doesn't match the above rules for a sub-directory, it will simply exist as a "protected" area of the disk, and can't be used as a sub-directory. Either way, it still shows up as a "CBM" type in a directory listing. Below is a dump of a 10-sector partition starting on track 5/1, which does not qualify as a sub-directory...
00: 00 00 85 05 01 53 4D 41 4C 4C 50 41 52 54 20 32 10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 0A 00
The master BAM shows the entry for this partition on track 5...
00: 28 02 44 BB 43 44 C0 00 00 00 00 00 00 00 00 00 10: 23 C1 FF FF FF FF 28 FF FF FF FF FF 28 FF FF FF 20: FF FF 28 FF FF FF FF FF 1E 01 F8 FF FF FF 28 FF ^^^^^^^^^^^^^^^^^
The breakdown of the BAM shows the allocation for this track, with sectors 1-10 allocated, as it should be.
10000000 00011111 11111111 11111111 11111111 ^ ^ ^ ^ ^ 0 10 20 30 39
Partitions and sub-directories share one very important trait. When created, the sub-directory entry simply has the starting track/sector and the size of the partition in sectors. Partitions are created linearly, meaning if one starts on 30/1 and is of size 15 sectors, then the sector range from 1 through 15 on track 30 will be allocated. If a partition size crosses a track boundary, the allocation will continue on the next track starting on sector 0, and going up.
The section allocated will *not* have a track/sector chain like a file would, but rather is dependant on the directory entry to keep it from being overwritten. You can store whatever you want to in the allocated area.
*** AUTO-BOOT LOADER
If byte $07 in the BAM is set, then when the drive is reset (and other circumstances) it will look for a USR file called "COPYRIGHT CBM 86". This file will then be loaded into the drive RAM and executed.
The format for this auto-loader file is fairly basic. It starts with a two-byte load address, a size byte, program data, and a checksum at the end.
Bytes: $00-$01: Load address, low/high format $02: Size of program (SZ) (smaller than 256 bytes) $03-($03+SZ-1): Program data $03+SZ: Checksum byte
(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)
This is a sector-for-sector copy of an 8050 floppy disk. The file size for an 8050 image is 533248 bytes. It is comprised of 256-byte sectors arranged across 77 tracks, with a varying number of sectors per track for a total of 2083 sectors. Track counting starts at 1 (not 0) and sector counting starts at 0 (not 1), therefore a track with 29 sectors will go from 0 to 28.
The original media (a 5.25" disk) has the tracks laid out in circles, with track 1 on the very outside of the disk (closest to the sides) to track 77 being on the inside of the disk (closest to the inner hub ring). Commodore, in their infinite wisdom, varied the number of sectors per track and data densities across the disk to optimize available storage, resulting in the chart below. It shows the sectors/track for a D80. Since the outside diameter of a circle is the largest (versus closer to the center), the outside tracks have the largest amount of storage.
Track Range | Sectors/track | # Sectors |
1-39 | 29 | 1131 |
40-53 | 27 | 378 |
54-64 | 25 | 275 |
65-77 | 23 | 299 |
Track | #Sect | #SectorsIn | D8x Offset |
1 | 29 | 0 | $00000 |
2 | 29 | 29 | $01D00 |
3 | 29 | 58 | $03A00 |
4 | 29 | 87 | $05700 |
5 | 29 | 116 | $07400 |
6 | 29 | 145 | $09100 |
7 | 29 | 174 | $0AE00 |
8 | 29 | 203 | $0CB00 |
9 | 29 | 232 | $0E800 |
10 | 29 | 261 | $10500 |
11 | 29 | 290 | $12200 |
12 | 29 | 319 | $13F00 |
13 | 29 | 348 | $15C00 |
14 | 29 | 377 | $17900 |
15 | 29 | 406 | $19600 |
16 | 29 | 435 | $1B300 |
17 | 29 | 464 | $1D000 |
18 | 29 | 493 | $1ED00 |
19 | 29 | 522 | $20A00 |
20 | 29 | 551 | $22700 |
21 | 29 | 580 | $24400 |
22 | 29 | 609 | $26100 |
23 | 29 | 638 | $27E00 |
24 | 29 | 667 | $29B00 |
25 | 29 | 696 | $2B800 |
26 | 29 | 725 | $2D500 |
27 | 29 | 754 | $2F200 |
28 | 29 | 783 | $30F00 |
29 | 29 | 812 | $32C00 |
30 | 29 | 841 | $34900 |
31 | 29 | 870 | $36600 |
32 | 29 | 899 | $38300 |
33 | 29 | 928 | $3A000 |
34 | 29 | 957 | $3BD00 |
35 | 29 | 986 | $3DA00 |
36 | 29 | 1015 | $3F700 |
37 | 29 | 1044 | $41400 |
38 | 29 | 1073 | $43100 |
39 | 29 | 1102 | $44E00 |
40 | 27 | 1131 | $46B00 |
41 | 27 | 1158 | $48600 |
42 | 27 | 1185 | $4A100 |
43 | 27 | 1212 | $4BC00 |
44 | 27 | 1239 | $4D700 |
45 | 27 | 1266 | $4F200 |
46 | 27 | 1293 | $50D00 |
47 | 27 | 1320 | $52800 |
48 | 27 | 1347 | $54300 |
49 | 27 | 1374 | $55E00 |
50 | 27 | 1401 | $57900 |
51 | 27 | 1428 | $59400 |
52 | 27 | 1455 | $5AF00 |
53 | 27 | 1482 | $5CA00 |
54 | 25 | 1509 | $5E500 |
55 | 25 | 1534 | $5FE00 |
56 | 25 | 1559 | $61700 |
57 | 25 | 1584 | $63000 |
58 | 25 | 1609 | $64900 |
59 | 25 | 1634 | $66200 |
60 | 25 | 1659 | $67B00 |
61 | 25 | 1684 | $69400 |
62 | 25 | 1709 | $6AD00 |
63 | 25 | 1734 | $6C600 |
64 | 25 | 1759 | $6DF00 |
65 | 23 | 1784 | $6F800 |
66 | 23 | 1807 | $70F00 |
67 | 23 | 1830 | $72600 |
68 | 23 | 1853 | $73D00 |
69 | 23 | 1876 | $75400 |
70 | 23 | 1899 | $76B00 |
71 | 23 | 1922 | $78200 |
72 | 23 | 1945 | $79900 |
73 | 23 | 1968 | $7B000 |
74 | 23 | 1991 | $7C700 |
75 | 23 | 2014 | $7DE00 |
76 | 23 | 2037 | $7F500 |
77 | 23 | 2060 | $80C00 |
The BAM (Block Availability Map) is on track 38. The D80 is only 77 tracks and so the BAM is contained on 38/0 and 38/3. The BAM interleave is 3.
The directory is on track 39, with 39/0 contains the header (DOS type, disk name, disk ID's) and sectors 1-28 contain the directory entries. Both files and the directory use an interleave of 1. Since the directory is only 28 sectors large (29 less one for the header), and each sector can contain only 8 entries (32 bytes per entry), the maximum number of directory entries is 28 * 8 = 224. The first directory sector is always 39/1. It then follows a chain structure using a sector interleave of 1 making the links go 39/1, 39/2, 39/3 etc.
When reading a disk, you start with 39/0 (disk label/ID) which points to 38/0 (BAM0), 38/3 (BAM1), and finally to 39/1 (first dir entry sector). When writing a file to a blank disk, it will start at 38/1 because 38/0 is already allocated.
Below is a dump of the header sector 39/0:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 26 00 43 00 00 00 73 61 6D 70 6C 65 20 64 38 30 10: A0 A0 A0 A0 A0 A0 A0 A0 65 72 A0 32 43 A0 A0 A0 20: A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes | Description |
$00-$01 | T/S pointer to first BAM sector (38/0) |
$02 | $43 'C' is for DOS format version |
$03 | Reserved |
$04-$05 | Unused |
$06-$16 | Disk name, padded with 0xA0 ("sample d80") |
$17 | 0xA0 |
$18-$19 | Disk ID bytes "er" |
$1A | 0xA0 |
$1B-$1C | DOS version bytes "2C" |
$1D-$20 | 0xA0 |
$21-$FF | Unused |
Below is a dump of the first directory sector, 39/1
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 27 02 82 26 01 54 45 53 54 A0 A0 A0 A0 A0 A0 A0 10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 20: 00 00 82 26 02 54 45 53 54 32 A0 A0 A0 A0 A0 A0 30: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 40: 00 00 82 26 04 54 45 53 54 33 A0 A0 A0 A0 A0 A0 50: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 05 00 60: 00 00 82 26 0B 54 45 53 54 34 A0 A0 A0 A0 A0 A0 70: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 09 00 80: 00 00 82 26 14 54 45 53 54 35 A0 A0 A0 A0 A0 A0 90: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 0C 00 A0: 00 00 82 28 00 54 45 53 54 36 A0 A0 A0 A0 A0 A0 B0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 C0: 00 00 82 28 01 54 45 53 54 37 A0 A0 A0 A0 A0 A0 D0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 E0: 00 00 82 28 02 54 45 53 54 38 A0 A0 A0 A0 A0 A0 F0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00
The first two bytes of the directory sector ($27/$02) indicate the location of the next track/sector of the directory (39/2). If the track is set to $00, then it is the last sector of the directory.
When the directory is done, the track value will be $00. The sector link should contain a value of $FF, meaning the whole sector is allocated, but the actual value doesn't matter. The drive will return all the available entries anyways. This is a breakdown of a standard directory sector:
Bytes | Description |
$00-$1F | First directory entry |
$20-$3F | Second dir entry |
$40-$5F | Third dir entry |
$60-$7F | Fourth dir entry |
$80-$9F | Fifth dir entry |
$A0-$BF | Sixth dir entry |
$C0-$DF | Seventh dir entry |
$E0-$FF | Eighth dir entry |
This is a breakdown of a standard directory entry:
Bytes | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00-$01 | Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02 | File type | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$03-$04 | Track/sector location of first sector of file | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$05-$14 | 16 character filename (in PETASCII, padded with $A0) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$15-$16 | Track/Sector location of first side-sector block (REL file only) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$17 | REL file record length (REL file only, max. value 254) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$18-$1D | Unused | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$1E-$1F | File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is <= #sectors * 254 | 0@end multitable The file type field is used as follows:
Bits | Description |
0-3 | The actual file type |
4 | Unused |
5 | Used only during SAVE- replacement |
6 | Locked flag (Set produces ">" locked files) |
7 | Closed flag (Not set produces "*", or "splat" files) |
Binary | Decimal | File type |
0000 | 0 | DEL |
0001 | 1 | SEQ |
0010 | 2 | PRG |
0011 | 3 | USR |
0100 | 4 | REL |
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 26 03 43 00 01 33 1D FF FF FF 1F 1D FF FF FF 1F 10: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D 20: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF 30: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF 40: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 50: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 60: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D 70: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF 80: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF 90: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF A0: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F B0: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1B C0: F6 FF FF 1F 1B FC FF FF 1F 1B FF FF FF 07 1B FF D0: FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF E0: FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF F0: 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF 07
Bytes | Description |
$00-$01 | T/S pointer to second BAM sector (38/3) |
$02 | DOS version byte (0x43='C') |
$03 | Reserved |
$04 | Lowest track covered by this BAM (0x01=1) |
$05 | Highest+1 track covered by this BAM (0x33=51) |
$06-$0A | BAM for track 1. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track. |
$0B-$0F | BAM for track 2 |
... | ... |
$FB-$FF | BAM for track 50 |
FF=11111111, FF=11111111, FF=11111111, 1F=00011111In order to make any sense from the binary notation, flip the bits around.
111111 11112222 222222 01234567 89012345 67890123 456789... -------------------------- --------- 11111111 11111111 11111111 11111000 ^ ^ sector 0 sector 28Since we are on the first track, we have 29 sectors, and only use up to the bit 28 position. If a bit is on (1), the sector is free. Therefore, track 1 is clean, all sectors are free. Any leftover bits that refer to sectors that don't exist, like bits 29-31 in the above example, are set to allocated. Second BAM block 38/3.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 27 01 43 00 33 4E 1B FF FF FF 07 1B FF FF FF 07 10: 1B FF FF FF 07 19 FF FF FF 01 19 FF FF FF 01 19 20: FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF 30: FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF FF 40: FF 01 19 FF FF FF 01 19 FF FF FF 01 17 FF FF 7F 50: 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 60: 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 70: FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF 80: FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 00 00 00 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes | Description |
$00-$01 | T/S pointer to second BAM sector (39/1) |
$02 | DOS version byte (0x43='C') |
$03 | Reserved |
$04 | Lowest track covered by this BAM (0x33=51) |
$05 | Highest+1 track covered by this BAM (0x43=78) |
$06-$0A | BAM for track 51. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track. |
$0B-$0F | BAM for track 52 |
... | ... |
$88-$8C | BAM for track 77 |
$8D-$FF | Not used |
(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)
This is a sector-for-sector copy of an 8250 floppy disk. The file size for an 8250 image is 1066496 bytes. It is comprised of 256-byte sectors arranged across 154 tracks, with a varying number of sectors per track for a total of 4166 sectors. Track counting starts at 1 (not 0) and sector counting starts at 0 (not 1), therefore a track with 29 sectors will go from 0 to 28.
The original media (a 5.25" disk) has the tracks laid out in circles, with track 1 on the very outside of the disk (closest to the sides) to track 77 being on the inside of the disk (closest to the inner hub ring). Commodore, in their infinite wisdom, varied the number of sectors per track and data densities across the disk to optimize available storage, resulting in the chart below. It shows the sectors/track for a D82. Since the outside diameter of a circle is the largest (versus closer to the center), the outside tracks have the largest amount of storage.
Track Range | Sectors/track | # Sectors |
1-39 | 29 | 1131 |
40-53 | 27 | 378 |
55-64 | 25 | 275 |
65-77 | 23 | 299 |
78-116 | 29 | 1131 |
117-130 | 27 | 378 |
131-141 | 25 | 275 |
142-154 | 23 | 299 |
Track | #Sect | #SectorsIn | D82 Offset |
1 | 29 | 0 | $000000 |
2 | 29 | 29 | $001D00 |
3 | 29 | 58 | $003A00 |
4 | 29 | 87 | $005700 |
5 | 29 | 116 | $007400 |
6 | 29 | 145 | $009100 |
7 | 29 | 174 | $00AE00 |
8 | 29 | 203 | $00CB00 |
9 | 29 | 232 | $00E800 |
10 | 29 | 261 | $010500 |
11 | 29 | 290 | $012200 |
12 | 29 | 319 | $013F00 |
13 | 29 | 348 | $015C00 |
14 | 29 | 377 | $017900 |
15 | 29 | 406 | $019600 |
16 | 29 | 435 | $01B300 |
17 | 29 | 464 | $01D000 |
18 | 29 | 493 | $01ED00 |
19 | 29 | 522 | $020A00 |
20 | 29 | 551 | $022700 |
21 | 29 | 580 | $024400 |
22 | 29 | 609 | $026100 |
23 | 29 | 638 | $027E00 |
24 | 29 | 667 | $029B00 |
25 | 29 | 696 | $02B800 |
26 | 29 | 725 | $02D500 |
27 | 29 | 754 | $02F200 |
28 | 29 | 783 | $030F00 |
29 | 29 | 812 | $032C00 |
30 | 29 | 841 | $034900 |
31 | 29 | 870 | $036600 |
32 | 29 | 899 | $038300 |
33 | 29 | 928 | $03A000 |
34 | 29 | 957 | $03BD00 |
35 | 29 | 986 | $03DA00 |
36 | 29 | 1015 | $03F700 |
37 | 29 | 1044 | $041400 |
38 | 29 | 1073 | $043100 |
39 | 29 | 1102 | $044E00 |
40 | 27 | 1131 | $046B00 |
41 | 27 | 1158 | $048600 |
42 | 27 | 1185 | $04A100 |
43 | 27 | 1212 | $04BC00 |
44 | 27 | 1239 | $04D700 |
45 | 27 | 1266 | $04F200 |
46 | 27 | 1293 | $050D00 |
47 | 27 | 1320 | $052800 |
48 | 27 | 1347 | $054300 |
49 | 27 | 1374 | $055E00 |
50 | 27 | 1401 | $057900 |
51 | 27 | 1428 | $059400 |
52 | 27 | 1455 | $05AF00 |
53 | 27 | 1482 | $05CA00 |
54 | 25 | 1509 | $05E500 |
55 | 25 | 1534 | $05FE00 |
56 | 25 | 1559 | $061700 |
57 | 25 | 1584 | $063000 |
58 | 25 | 1609 | $064900 |
59 | 25 | 1634 | $066200 |
60 | 25 | 1659 | $067B00 |
61 | 25 | 1684 | $069400 |
62 | 25 | 1709 | $06AD00 |
63 | 25 | 1734 | $06C600 |
64 | 25 | 1759 | $06DF00 |
65 | 23 | 1784 | $06F800 |
66 | 23 | 1807 | $070F00 |
67 | 23 | 1830 | $072600 |
68 | 23 | 1853 | $073D00 |
69 | 23 | 1876 | $075400 |
70 | 23 | 1899 | $076B00 |
71 | 23 | 1922 | $078200 |
72 | 23 | 1945 | $079900 |
73 | 23 | 1968 | $07B000 |
74 | 23 | 1991 | $07C700 |
75 | 23 | 2014 | $07DE00 |
76 | 23 | 2037 | $07F500 |
77 | 23 | 2060 | $080C00 |
78 | 29 | 2083 | $082300 |
79 | 29 | 2112 | $084000 |
80 | 29 | 2141 | $085D00 |
81 | 29 | 2170 | $087A00 |
82 | 29 | 2199 | $089700 |
83 | 29 | 2228 | $08B400 |
84 | 29 | 2257 | $08D100 |
85 | 29 | 2286 | $08EE00 |
86 | 29 | 2315 | $090600 |
87 | 29 | 2344 | $092800 |
88 | 29 | 2373 | $094500 |
89 | 29 | 2402 | $096200 |
90 | 29 | 2431 | $097F00 |
91 | 29 | 2460 | $099C00 |
92 | 29 | 2489 | $09B900 |
93 | 29 | 2518 | $09D600 |
94 | 29 | 2547 | $09F300 |
95 | 29 | 2576 | $0A1000 |
96 | 29 | 2605 | $0A2D00 |
97 | 29 | 2634 | $0A4A00 |
98 | 29 | 2663 | $0A6700 |
99 | 29 | 2692 | $0A8400 |
100 | 29 | 2721 | $0AA100 |
101 | 29 | 2750 | $0ABE00 |
102 | 29 | 2779 | $0ADB00 |
103 | 29 | 2808 | $0AF800 |
104 | 29 | 2837 | $0B1500 |
105 | 29 | 2866 | $0B3200 |
106 | 29 | 2895 | $0B4F00 |
107 | 29 | 2924 | $0B6C00 |
108 | 29 | 2953 | $0B8900 |
109 | 29 | 2982 | $0BA600 |
110 | 29 | 3011 | $0BC300 |
111 | 29 | 3040 | $0BE000 |
112 | 29 | 3069 | $0BFD00 |
113 | 29 | 3098 | $0C1A00 |
114 | 29 | 3137 | $0C3700 |
115 | 29 | 3156 | $0C5400 |
116 | 29 | 3185 | $0C7100 |
117 | 27 | 3214 | $0C8E00 |
118 | 27 | 3241 | $0CA900 |
119 | 27 | 3268 | $0CC400 |
120 | 27 | 3295 | $0CDF00 |
121 | 27 | 3322 | $0CFA00 |
122 | 27 | 3349 | $0D1500 |
123 | 27 | 3376 | $0D3000 |
124 | 27 | 3403 | $0D4B00 |
125 | 27 | 3430 | $0D6600 |
126 | 27 | 3457 | $0D8100 |
127 | 27 | 3484 | $0D9C00 |
128 | 27 | 3511 | $0DB700 |
129 | 27 | 3538 | $0DD200 |
130 | 27 | 3565 | $0DED00 |
131 | 25 | 3592 | $0E0800 |
132 | 25 | 3617 | $0E2100 |
133 | 25 | 3642 | $0E3A00 |
134 | 25 | 3667 | $0E5300 |
135 | 25 | 3692 | $0E6C00 |
136 | 25 | 3717 | $0E8500 |
137 | 25 | 3742 | $0E9E00 |
138 | 25 | 3767 | $0EB700 |
139 | 25 | 3792 | $0ED000 |
140 | 25 | 3817 | $0EE900 |
141 | 25 | 3842 | $0F0200 |
142 | 23 | 3867 | $0F1B00 |
143 | 23 | 3890 | $0F3200 |
144 | 23 | 3913 | $0F4900 |
145 | 23 | 3936 | $0F6000 |
146 | 23 | 3959 | $0F7700 |
147 | 23 | 3982 | $0F8E00 |
148 | 23 | 4005 | $0FA500 |
149 | 23 | 4028 | $0FBC00 |
150 | 23 | 4051 | $0FD300 |
151 | 23 | 4074 | $0FEA00 |
152 | 23 | 4097 | $100100 |
153 | 23 | 4120 | $101800 |
154 | 23 | 4143 | $102F00 |
The BAM (Block Availability Map) is on track 38. The D82 is 154 tracks and so the BAM is contained on 38/0, 38/3, 38/6 and 38/9. The BAM interleave is 3.
The directory is on track 39, with 39/0 contains the header (DOS type, disk name, disk ID's) and sectors 1-28 contain the directory entries. Both files and the directory use an interleave of 1. Since the directory is only 28 sectors large (29 less one for the header), and each sector can contain only 8 entries (32 bytes per entry), the maximum number of directory entries is 28 * 8 = 224. The first directory sector is always 39/1. It then follows a chain structure using a sector interleave of 1 making the links go 39/1, 39/2, 39/3 etc.
When reading a disk, you start with 39/0 (disk label/ID) which points to 38/0 (BAM0), 38/3 (BAM1), 38/6 (BAM2), 38/9 (BAM3, and finally to 39/1 (first dir entry sector). When writing a file to a blank disk, it will start at 38/1 because 38/0 is already allocated.
Below is a dump of the header sector 39/0:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 26 00 43 00 00 00 73 61 6D 70 6C 65 20 64 38 30 10: A0 A0 A0 A0 A0 A0 A0 A0 65 72 A0 32 43 A0 A0 A0 20: A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes | Description |
$00-$01 | T/S pointer to first BAM sector (38/0) |
$02 | $43 'C' is for DOS format version |
$03 | Reserved |
$04-$05 | Unused |
$06-$16 | Disk name, padded with 0xA0 ("sample d82") |
$17 | 0xA0 |
$18-$19 | Disk ID bytes "er" |
$1A | 0xA0 |
$1B-$1C | DOS version bytes "2C" |
$1D-$20 | 0xA0 |
$21-$FF | Unused |
Below is a dump of the first directory sector, 39/1
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 27 02 82 26 01 54 45 53 54 A0 A0 A0 A0 A0 A0 A0 10: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 20: 00 00 82 26 02 54 45 53 54 32 A0 A0 A0 A0 A0 A0 30: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 40: 00 00 82 26 04 54 45 53 54 33 A0 A0 A0 A0 A0 A0 50: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 05 00 60: 00 00 82 26 0B 54 45 53 54 34 A0 A0 A0 A0 A0 A0 70: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 09 00 80: 00 00 82 26 14 54 45 53 54 35 A0 A0 A0 A0 A0 A0 90: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 0C 00 A0: 00 00 82 28 00 54 45 53 54 36 A0 A0 A0 A0 A0 A0 B0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 C0: 00 00 82 28 01 54 45 53 54 37 A0 A0 A0 A0 A0 A0 D0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00 E0: 00 00 82 28 02 54 45 53 54 38 A0 A0 A0 A0 A0 A0 F0: A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00 01 00
The first two bytes of the directory sector ($27/$02) indicate the location of the next track/sector of the directory (39/2). If the track is set to $00, then it is the last sector of the directory.
When the directory is done, the track value will be $00. The sector link should contain a value of $FF, meaning the whole sector is allocated, but the actual value doesn't matter. The drive will return all the available entries anyways. This is a breakdown of a standard directory sector:
Bytes | Description |
$00-$1F | First directory entry |
$20-$3F | Second dir entry |
$40-$5F | Third dir entry |
$60-$7F | Fourth dir entry |
$80-$9F | Fifth dir entry |
$A0-$BF | Sixth dir entry |
$C0-$DF | Seventh dir entry |
$E0-$FF | Eighth dir entry |
This is a breakdown of a standard directory entry:
Bytes | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00-$01 | Track/Sector location of next directory sector ($00 $00 if not the first entry in the sector) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02 | File type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$03-$04 | Track/sector location of first sector of file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$05-$14 | 16 character filename (in PETASCII, padded with $A0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$15-$16 | Track/Sector location of first side-sector block (REL file only) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$17 | REL file record length (REL file only, max. value 254) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$18-$1D | Unused | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$1E-$1F | File size in sectors, low/high byte order ($1E+$1F*256). The approx. filesize in bytes is <= #sectors * 254 | 0@end multitable The file type field is used as follows:
Bits | Description |
0-3 | The actual file type |
4 | Unused |
5 | Used only during SAVE- replacement |
6 | Locked flag (Set produces ">" locked files) |
7 | Closed flag (Not set produces "*", or "splat" files) |
Binary | Decimal | File type |
0000 | 0 | DEL |
0001 | 1 | SEQ |
0010 | 2 | PRG |
0011 | 3 | USR |
0100 | 4 | REL |
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 26 03 43 00 01 33 1D FF FF FF 1F 1D FF FF FF 1F 10: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D 20: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF 30: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF 40: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 50: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 60: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D 70: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF 80: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF 90: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF A0: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F B0: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1B C0: F6 FF FF 1F 1B FC FF FF 1F 1B FF FF FF 07 1B FF D0: FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF E0: FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF F0: 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF 07
Bytes | Description |
$00-$01 | T/S pointer to second BAM sector (38/3) |
$02 | DOS version byte (0x43='C') |
$03 | Reserved |
$04 | Lowest track covered by this BAM (0x01=1) |
$05 | Highest+1 track covered by this BAM (0x33=51) |
$06-$0A | BAM for track 1. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track. |
$0B-$0F | BAM for track 2 |
... | ... |
$FB-$FF | BAM for track 50 |
FF=11111111, FF=11111111, FF=11111111, 1F=00011111In order to make any sense from the binary notation, flip the bits around.
111111 11112222 222222 01234567 89012345 67890123 456789... -------------------------- --------- 11111111 11111111 11111111 11111000 ^ ^ sector 0 sector 28Since we are on the first track, we have 29 sectors, and only use up to the bit 28 position. If a bit is on (1), the sector is free. Therefore, track 1 is clean, all sectors are free. Any leftover bits that refer to sectors that don't exist, like bits 29-31 in the above example, are set to allocated. Second BAM block 38/3
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 26 06 43 00 33 65 1B FF FF FF 07 1B FF FF FF 07 10: 1B FF FF FF 07 19 FF FF FF 01 19 FF FF FF 01 19 20: FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF 30: FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF FF 40: FF 01 19 FF FF FF 01 19 FF FF FF 01 17 FF FF 7F 50: 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 60: 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 70: FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF 80: FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 1D FF FF 90: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF A0: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F B0: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D C0: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF D0: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF E0: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF F0: 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F
Bytes | Description |
$00-$01 | T/S pointer to third BAM sector (38/6) |
$02 | DOS version byte (0x43='C') |
$03 | Reserved |
$04 | Lowest track covered by this BAM (0x33=51) |
$05 | Highest+1 track covered by this BAM (0x65=101) |
$06-$0A | BAM for track 51. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track. |
$0B-$0F | BAM for track 52 |
... | ... |
$FB-$FF | BAM for track 100 |
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 26 09 43 00 65 97 1D FF FF FF 1F 1D FF FF FF 1F 10: 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D 20: FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF 30: FF FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF 40: FF 1F 1D FF FF FF 1F 1D FF FF FF 1F 1D FF FF FF 50: 1F 1D FF FF FF 1F 1B FF FF FF 07 1B FF FF FF 07 60: 1B FF FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B 70: FF FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF 80: FF FF 07 1B FF FF FF 07 1B FF FF FF 07 1B FF FF 90: FF 07 1B FF FF FF 07 1B FF FF FF 07 19 FF FF FF A0: 01 19 FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 B0: 19 FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 C0: FF FF FF 01 19 FF FF FF 01 19 FF FF FF 01 19 FF D0: FF FF 01 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF E0: 7F 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F F0: 00 17 FF FF 7F 00 17 FF FF 7F 00 17 FF FF 7F 00
Bytes | Description |
$00-$01 | T/S pointer to fourth BAM sector (38/9) |
$02 | DOS version byte (0x43='C') |
$03 | Reserved |
$04 | Lowest track covered by this BAM (0x65=101) |
$05 | Highest+1 track covered by this BAM (0x97=151) |
$06-$0A | BAM for track 101. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track. |
$0B-$0F | BAM for track 102 |
... | ... |
$FB-$FF | BAM for track 150 |
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 00: 27 01 43 00 97 9B 17 FF FF 7F 00 17 FF FF 7F 00 10: 17 FF FF 7F 00 17 FF FF 7F 00 00 00 00 00 00 00 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bytes | Description |
$00-$01 | T/S pointer to first directory sector (39/1) |
$02 | DOS version byte (0x43='C') |
$03 | Reserved |
$04 | Lowest track covered by this BAM (0x97=151) |
$05 | Highest+1 track covered by this BAM (0x9B=155) |
$06-$0A | BAM for track 151. The first byte shows the "blocks free" for this track, the remaining 4 show the BAM for the track. |
$0B-$0F | BAM for track 152 |
... | ... |
$15-$19 | BAM for track 154 |
$1A-$FF | Not used |
(This section was contributed by Peter Schepers and slightly edited by Marco van den Heuvel.)
These files were created for use in the PC64 emulator, written by Wolfgang Lorenz. Each one has the same layout with the filetype being stored in the DOS extension (i.e. Pxx is a PRG, Sxx is a SEQ, Uxx is a USR and Rxx is a RELative file), and the header is only 26 bytes long.
This is a dump of a Pxx file (PRG)...
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ----------------------------------------------- 0000: 43 36 34 46 69 6C 65 00 43 52 49 53 49 53 20 4D 0010: 4F 55 4E 54 41 49 4E 00 00 00
Bytes | Description |
$00-$06 | ASCII string "C64File" |
$07 | Always $00 |
$08-$17 | Filename in PETASCII, padded with $00 (not $A0, like a D64) |
$18 | Always $00 |
$19 | REL file record size ($00 if not a REL file) |
$1A-?? | Program data |
The 'xx' in the extension of the file is usually 00, except when we have two DOS filenames which would be the same, but the C64 filenames are different! If we have two C64 filenames which are the same, they *cannot* co-exist in the same directory. If we have two files which do convert down to be the same DOS filename, the extension is incremented until an unused one is found (x01, x02, x03, up to x99). We can have up to 99 different C64 files with the same corresponding DOS names as that's all the extension will hold (from P00 to P99).
Each PC64 file only has one entry, there are no multi-file containers allowed. This could result in a large number of these files in a directory, even for only a few programs, as each C64 file will result in a PC64 file entry. The best use for a PC64 file is a single-file program, one which does not load anything else.
Go to the first, previous, next, last section, table of contents.