Commodore DOS, aka CBM DOS, is the disk operating system used with
Commodore's 8-bit computers. Unlike most other
DOS systems, which are
loaded from disk into the computer's own RAM and executed there, CBM
DOS is executed internally in the drive: the
DOS resides in ROM chips
inside the drive, and is run there by one or more dedicated MOS 6502
family CPUs. Thus, data transfer between Commodore 8-bit computers and
their disk drives more closely resembles a local area network
connection than typical disk/host transfers.
2 Technical overview
2.1 1541 directory and file types
2.3 The save-with-replace bug
2.4 Command channel
At least seven distinctly numbered versions of Commodore
DOS are known
to exist; the following list gives the version numbers and related
disk drives. Unless otherwise noted, drives are 5¼-inch format. The
"lp" code designates "low profile" drives. Drives whose model number
starts with 15 connect via Commodore's unique CBM-488 serial
(TALK/LISTEN) protocols, all others use the parallel IEEE-488.
1.0 – found in the 2040 and 3040 floppy drives
2.0 – found in the 4040 and 3040 floppy drives
2.5 – found in the 8050 floppy drives
2.6 – found in the 1540, 1541, built-in SX-64 drive, 1551,
2031 (+"lp"), and 4031 floppy drives
2.7 – found in the 8050, 8250 (+"lp"), and SFD-1001 floppy
3.0 – found in the 1570, 1571, and 8280 floppy drives (8280:
8-inch), as well as the 9060 and 9090 hard drives
3.1 – found in the built-in 1571 drive of C128D/DCR computers
10.0 – found in the 1581 (3½-inch)
Version 2.6 was by far the most commonly used and known
due to its use in the 1541 as part of C64 systems.
The revised firmware for the 1571 which fixed the relative file bug
was also identified as V3.0. Thus it is not possible to tell the two
versions apart by version number alone.
1541 directory and file types
Listing the directory of a 1541 drive
The 1541 Commodore floppy disk can contain up to 144 files in a flat
namespace (no subdirectories); the directory is stored on reserved
track 18, which is the center track of a 35-track single-sided disk. A
file name may be up to 16 bytes in length and theoretically will be
unique; by using direct access methods on the directory structure, it
is possible to rename a file to that of another—although accessing
such files may be difficult or impossible. Files with identical names
usually serve no purpose except to inform or visually manage files.
One popular trick, used, for example, by The Final Cartridge III, was
to add files named "----------------" of type DEL< to the
directory, and files could then be rearranged around those lines to
form groups. Many game developers, warez group members and demoscene
hackers used some more clever custom directory entries as well.
File names may contain a shift+space character ($A0), and if the
directory listing is being viewed from BASIC, the portion of the file
name beyond the $A0 character will appear to have been separated from
the first part of the file name by a quotation mark, causing BASIC to
not consider it to be part of the full file name. This feature was
used to create directory entries such as SAVE "PROGRAM⇧
Shift+space,8,1:",8,1 which will then appear in the directory listing
as, for example, 32 "PROGRAM",8,1: PRG. When the user moved the cursor
to the beginning of the line and typed the word LOAD over the file
size and pressed Enter, BASIC will interpret that as LOAD
"PROGRAM",8,1: ..., causing the program to be loaded into memory.
Anything after the colon will not be executed, since the LOAD command
will execute the other program, never returning to the interpreter.
A null byte embedded in a file name will interrupt the listing after
loading by BASIC. If there are three null bytes, that makes it
difficult to list through BASIC. Many machine language programmers
would experiment with null bytes in an attempt to make it harder for
BASIC programmers to access their code and tamper with it.
In BASIC, the directory can be accessed as a non-executable
pseudo-BASIC program with LOAD "$0",8 (or LOAD "$1",8 in the case of a
dual drive) followed by LIST. The first line has a line number of 0 or
1 (indicating the drive number), showing in reverse video the name and
ID of the disk and a shorthand code for the
DOS version with which it
was created (codes vary only as far as the
DOS versions use
incompatible disk formats, "2A" is used by most 5.25 inch DOS
versions, "3D" by the 3.5 inch 1581). Lines after this have the size
of a file (in disk blocks) as their pseudo "line number", followed by
the file name in quotes and the three-letter type code. The last line
shows the number of unallocated blocks on the disk (again as a pseudo
"line number"), followed by the words "BLOCKS FREE."
On the Commodore 64, entering LOAD "$",8,1 will flood the screen with
garbage instead of loading the directory into BASIC RAM. This is
because the drive assigns the directory a load address of $0401
(1025), which is equivalent to the start of BASIC for the Commodore
PET, but corresponds to the default screen memory in the C64 (starting
with the second character on the first line of the screen).
Viewing the directory with a LOAD "$",8 command overwrites the BASIC
program in memory. The
DOS Wedge and various third-party cartridges
and extenders such as Epyx FastLoad,
Action Replay and The Final
Cartridge III allow viewing of the disk directory using special
commands that load the directory into screen memory without destroying
the current BASIC program. The Commodore 128's BASIC 7.0 includes a
DIRECTORY or CATALOG command (assigned on bootup to the F3 key) that
performs the same function.
The following file types are supported:
A sequential file is a data file that can be linearly read from start
to finish. SEQ files are commonly used to store documents or text
files created by a word processor or other such editor. A sequential
file is analogous to a flat file in
Linux or UNIX, in that it has no
specialized internal structure. It is not possible to position to any
arbitrary location in a sequential file, as there is no analog of the
lseek kernel call found in
UNIX-like operating systems.
PRG files normally contain executable program code, although they can
also be used for data files. The first two bytes of the PRG are read
by the kernal "load file" routine and used to determine the load
address (they are stored in a little endian format).
A relative file is a variation of the sequential file type, in which
an indexing mechanism referred to as side-sectors is present to permit
record-oriented access. Records may be a maximum of 254 bytes in size
and are addressed by a one-based cardinal number, permitting true
random access to any part of the file.
A user-specified file has an internal structure that is identical to
that of a sequential file. Commodore's original purpose for this file
type was the facilitation of
DOS development, as the file content
could be copied into a drive buffer for execution by the drive's
microprocessor. It is unknown if anyone found a use for the facility.
Some applications that use non-standard low-level disk structures save
data in USR format, which came to be considered a sort of "leave me
alone, don't try to copy or delete" indication to the user. Most
notably, GEOS' "VLIR" files show up as USR files.
An undocumented internally used file type similar in structure to a
sequential file. Creation of this file type must be accomplished by
direct manipulation of the disk directory.
The presence of an asterisk (*) prepended to the file type in a
directory listing (for example, *SEQ) indicates that the file was not
properly closed after writing. When the drive is commanded to close a
file that has been opened for writing, the associated buffer is
flushed to the disk and the block availability map (BAM) is updated to
accurately reflect which blocks have been used. If a program crash or
other problem (such as the user removing the disk while a file is
open) results in an "orphan file", also referred to as a "poison" or
"splat" file, buffers are not flushed and the BAM will not accurately
reflect disk usage, putting the disk at risk of corruption. A poison
file generally cannot be accessed (but can be opened in "modify"
mode), and an attempt to use the
DOS scratch command to delete the
file may cause filesystem corruption, such as crosslinking. The only
practical method of removing one of these files is by opening the file
in "modify" mode (and fixing it), or by validating the disk (see the
DOS validate command below), the latter which rebuilds the BAM and
removes poison file references from the directory. The infamous
save-with-replace bug could result in creation of splat files.
*DEL is a special type written into the on-disk directory entry of
files that have been deleted. Such files are not shown in a normal
directory listing, and their data blocks and directory entries will be
reused by files that are subsequently created. Some utility programs
allow the "un-deletion" of such files if their data blocks and
directory entries haven not yet been overwritten by other files. DEL
files are commonly used to insert banners or comment sections into a
File types with < after them (for example, PRG<) are "locked",
and cannot be deleted—they can be opened for reading, however. There
is no Commodore
DOS command that can explicitly set or clear this
status, but many third-party utilities were written to allow this to
be done. These utilities generally read the directory using
direct-access commands, perform the necessary modifications to the raw
data, and then write the changes back to the disk.
Accessing files is primarily an issue for the host computer. The
kernal ROM in the computer contains the necessary primitive routines
needed to access files, and the BASIC ROM contains a higher level
abstraction for file access using BASIC syntax. The components that
DOS itself are file name parsing and the secondary
address. This section will give an overview of the necessary BASIC
commands for the sake of completeness.
Opening a file on a Commodore disk unit entails the processing of a
number of parameters that are vaguely analogous to file opening
procedures in other environments. Since the
DOS is actually running in
the drive's controller, the file opening sequence must pass enough
information to the drive to assure unambiguous interpretation. A
typical statement in BASIC to write to a sequential file would be as
The parameters following the OPEN verb are as follows:
This parameter, the file number, logically identifies the opened file
within the computer's operating system and is analogous to a file
UNIX-like operating systems. It is never sent to the
drive and thus is neither known nor used by the drive's own operating
system. The file number may be in the range of 1 to 254 inclusive, is
assigned by the programmer and must be unique if more than one file is
simultaneously opened. Once the file has been opened all program input
and output procedures use the file number. In assembly language
programs, this value is often referred to as LA (logical address), the
abbreviation coming from the mnemonic that refers to the memory
location where the file number is stored.
File numbers greater than
127 cause the system to write an extra line feed after each carriage
return (useful for double spacing a document, as an example.)
This parameter, the device number, identifies a specific peripheral
attached to the computer. Devices 0 through 3 address the keyboard,
RS-232 interface, and video display, respectively, all
of which are directly controlled by the kernal ROM. Device numbers 4
and higher address devices attached to the peripheral bus, such as
printers or disk drives. In the case of a disk drive, the device
number refers to the unit's controller, not the drive mechanism(s)
within the unit. By convention, the first disk drive unit on a system
has device number 8, the second drive, if present, 9, etc., up to a
maximum of 15. The device number scheme was derived from the IEEE-488
or general purpose interface bus (GPIB) that was used with the
Commodore PET/CBM models. In assembly language programs, this value is
often referred to as FA or PA (physical address), again from the
mnemonic for the memory location where the device number is stored.
This parameter, the secondary address, which may range from 0 to 15
inclusive, refers to a specific communication channel established with
the device's controller and is passed to the device when it is
commanded to "talk" or "listen" on the peripheral bus. As with the
file number, the secondary address is determined by the programmer and
must be unique for the device in question. The range 0 to 14 inclusive
is used for passing data to or from the device, whereas 15, referred
to as the "command channel", is used to issue commands to the device's
controller (such as to rename a disk file), if the device is able to
support such an operation. In disk drives, secondary addresses 0 to 14
inclusive are mapped to buffers within the controller, hence
establishing communication with a specific file on a specific disk;
since as mentioned above the drive does not know about the file
number, it can only use the secondary address to make a difference
between several files that are open at the same time. On the other
hand, the host operating system is agnostic about the secondary
address; it is transmitted to the drive on every access to the file,
but not otherwise used by the host. In assembly language programs,
this value is often referred to as SA (secondary address).
The "0:ADDRESSBOOK,S,W" parameter is officially referred to in
Commodore documentation as the command string and is interpreted by
the controller of the device being accessed. In the case of a disk
drive unit, the formal command string structure consists of the drive
mechanism number (0:, not to be confused with the device number),
filename (ADDRESSBOOK), file type (S, sequential in this example) and
access mode (W, opened for writing in this example). In practice, some
of these parameters may be omitted. Minimally, only the filename is
required if the file is to be opened for reading.
The drive number identifies a drive mechanism attached to a disk
unit's controller and is analogous to a logical unit number in a SCSI
controller that is capable of controlling multiple mechanisms (e.g.,
the OMTI SASI controllers that were developed to work with
ST-506 hard drives in the 1980s). In floppy disk units, the
first mechanism is drive 0: and the second is 1:. It is fairly common
practice to omit the drive number when communicating with a single
drive floppy unit, as 0: is the default in such units, but since
omitting the number can trigger a few obscure bugs in the
DOS it is
not a recommended practice (a colon alone is equivalent to 0: and is
enough to avoid those bugs). An exception to this convention is with
Lt. Kernal hard disk subsystem, in which the drive number refers
to "logical units" (virtual drives created on a single physical
drive), which made syntax such as 4: or 10: necessary if a file to be
opened was not on logical unit zero (equivalent to drive mechanism
zero in a dual floppy unit).
Files can also be loaded and saved to with LOAD and SAVE commands.
File name specifiers can also be used here, for example, SAVE "FILE",8
saves the BASIC program to a PRG (program) file and SAVE
"0:FILE,SEQ,WRITE",8,1 saves the BASIC program to a sequential file.
If the secondary address isn't specified or is specified as 0 (e.g.
LOAD "FILE",8), the file is saved/loaded from the BASIC memory area
(which, on the C64, starts by default at $0801). If the secondary
address is specified as a non-zero value (e.g. LOAD "FILE",8,1), the
program is loaded starting from the address specified by the file
itself (the PRG header, which is the first two bytes of the
file)—this form of command is more common when loading machine code
Load relocation was first introduced on the VIC-20 because this
machine could start BASIC RAM in several different locations,
depending on the memory expansion that was installed. The older
Commodore PET series did not support relocation, so LOAD "FILE",8 and
LOAD "FILE",8,1 would have the same effect: the file would be loaded
into the same memory region from which it was saved. Load relocation
happens in the host, being an exception to what is said above about
the secondary address being used only device-internally. Since the PET
cannot relocate files, BASIC programs written on later Commodore
machines must be modified by using a sector editor to change the
header bytes. It is also possible to use the PET's built-in machine
language monitor to change the link address for the BASIC program
after loading it.
The command LOAD "*",8,1 will load the first program on the disk
starting from the file-specified memory location. This is one of the
most popular load commands of the platforms, the method to start
majority of commercial software, for example. Of note is the fact that
the wildcard expansion will only pick the first catalog name when no
other file on that disk has been accessed before; the name of the
last-used file is kept in memory, and subsequent LOAD "*",8,1 commands
will load that file rather than the first. (However, LOAD "0:*",8,1 or
LOAD ":*",8,1 will always load the first file on the disk.)
The directories of disks in two-drive units are accessed as LOAD "$0",
8 and LOAD "$1", 8. "0:$" and "1:$" do not access the directory but
actual files on one drive or the other that just happen to be named
"$". Partial directories can be loaded by adding a colon and a
template, for example LOAD "$0:K*=P",8 would load a partial directory
that shows only the files whose name starts with the letter K and
which are of type PRG; all such partial directories still contain the
initial disk name line and the final "BLOCKS FREE" line.
The save-with-replace bug
DOS also offers a "Save-with-Replace" command, which allows
a file to be saved over an existing file without the need to first
SCRATCH the existing file. This was done by prepending an @ symbol to
the file name during the OPEN or SAVE operation - for instance, SAVE
"@MY PROGRAM",8. For years rumors spread, beginning with the 4040
drive, of a bug in the command's implementation. At first, this was
denied by some commentators. Prizes were offered to prove the
existence of the bug. By early 1985
Compute! magazine advised
readers to avoid using the command. That year various authors
independently published articles proving that the
Save-with-Replace bug was real and including methods by which it could
Affected devices included the single-drive 1541 and dual-drive 4040;
the 8050 and 8250 did not exhibit the issue. Some commentators
suggested the bug could be avoided by always explicitly specifying the
0: drive number when saving, though it was later shown that any
disk operations without a drive number were sufficient to lead to the
bug. The bug stemmed from the fact that the affected DOS
implementations were modified versions of the
DOS contained in earlier
Commodore PET dual drives such as the 8050. This created a "phantom
drive 1:" on single-drive systems, resulting in the allocation of an
unnecessary buffer under some conditions. Since the Save-with-Replace
command used all five drive buffers, and because the method by which
the "phantom" buffer was allocated did not meet specifications, this
resulted in scrambled data being written to the disk under some
In September 1986, Philip A. Slaymaker published an article
describing in great detail the cause of the bug and providing patches
to the 1541 drive ROMs; readers with an
EPROM burner could produce
their own patched ROMs which could be swapped into the drive.
Commodore was made aware of Slaymaker's findings, and while they never
issued an official update for the original 1541's ROMs, they did fix
the bug in Revision 5 of the 1571 ROMs, and also in the ROMs for the
1541-c and 1541-II drives. Although not supported by Commodore, it is
known that the 1541-II firmware (but not that of the 1541-c) can also
be used in an original 1541 drive by using EPROMs, which will fix the
bug for that drive as well.
As previously noted, the Commodore
DOS itself is accessed via the
"command channel", using syntax like that used to access files.
Issuing commands to the
DOS and retrieving status and error messages
generated in response to commands is accomplished by opening a file to
the device using 15 as the secondary address, for example:
To retrieve and display the device status, one could code:
OPEN 1,8,15:INPUT#1,E,E$,T,S:PRINT E,E$,T,S:CLOSE 1
In the above example, E will hold the error number (if any, it will be
zero if no error exists), E$ will be a terse text description of the
error, T will represent the disk track where the error occurred, and S
will be the sector on track T to which the error refers. If no error
exists, the equivalent of 00,OK,00,00 will be returned in the four
variables. Note that INPUT# is a run mode only verb. Also, in programs
that issue many disk commands it is customary to open a file to the
device's command channel at the start of the program and not close it
until the program has finished.
Commodore BASIC versions 4.0 and later provide a pseudo-variable
referred to as DS$ that may be used to retrieve drive status in lieu
of the above code. This reserved variable is not available on earlier
versions of BASIC, so the command channel must be manually read as
demonstrated above. Note that immediately after power-on or reset, the
DOS revision will be returned. For example, a 1541 will return 73,CBM
DOS V2.6 1541,00,00. Error code 73 is common to all drive models and
may be used to determine if the drive has been reset to its power-on
BASIC 1.x and 2.x Implementation
DOS Wedge Implementation
BASIC 3.0+ Implementation
Format a disk, preparing it for use and deleting any data contained on
it. Omitting the two-character identifier parameter will perform a
quick deletion of all files on an already-formatted disk.
OPEN 15,8,15,"N0:disk name,identifier":CLOSE 15
HEADER "disk name",identifier
Delete a file from the disk (or multiple files, using wild card
OPEN 15,8,15,"S0:file name":CLOSE 15
SCRATCH "file name"
Rename a file on the disk. Note that the new name comes first (except
in the BASIC 3.0+ code)!
OPEN 15,8,15,"R0:new name=old name":CLOSE 15
@R0:new name=old name
RENAME "old name" TO "new name"
Reset the drive and read the disk BAM into its internal memory. Rarely
needed as the drive usually does this on its own, except if a disk is
exchanged for another one with the same ID.
OPEN 15,8,15,"I0:":CLOSE 15
DCLEAR (BASIC 7.0+ only)
Reconcile the BAM with the disk directory, allocate all used blocks
and free all blocks not being used by files, and delete all unclosed
files from the directory. Comparable to CHKDSK/ScanDisk tools of
Microsoft operating systems.
OPEN 15,8,15,"V0:":CLOSE 15
Duplicate a file on the same disk (or another disk in the same
two-drive unit) under a different file name. Note that the new name
comes first (except in the BASIC 3.0+ code)! Duplicating to another
disk without a two-drive unit requires using a utility program.
OPEN 15,8,15,"C0:new name=0:existing name":CLOSE 15
@C0:new name=0:existing name
COPY"existing name"TO"new name"
Duplicate an entire disk. Only available in two-drive units, otherwise
a utility program needs to be used instead. The target(!) drive number
comes first, then the source drive number (except in the BASIC 3.0+
OPEN 15,8,15,"D1=0":CLOSE 15
BACKUP D0 TO D1
There are also a command for seeking in RELative type files (RECORD#),
several block-level direct-access commands (BLOCK-READ, BLOCK-WRITE,
BUFFER-POINTER), block management (BLOCK-ALLOCATE, BLOCK-FREE), drive
memory manipulation and execution of program code on the drive's
processor (MEMORY-WRITE, MEMORY-READ, MEMORY-EXECUTE, BLOCK-EXECUTE)
and user-definable functions (USER and & commands). Some of the
theoretically user-definable functions were rededicated for accessing
new functionality in
DOS versions after 1.0.
^ a b c Whittern, Charles H. (July 1985). "SAVE with Replace
Exposed!!". The Transactor. 6 (1): 20.
^ "The Great Commodore Save/Replace Debate". Compute!. February 1985.
p. 10. Retrieved 6 October 2013.
^ a b Slaymaker, P. A. (October 1985). "Save With Replace: Debugged At
Last / Part 1". Compute!. p. 79. Retrieved 16 October 2013.
^ Slaymaker, P. A. (November 1985). "Save-With-Replace: Debugged At
Last / Part 2". Compute!. p. 111. Retrieved 30 October
^ Editors. "Save@: Gerry Neufield's Theory on an Old Bug". Info № 9,
December 1985/January 1986.
^ Excerpt of e-mail from Philip A. Slaymaker also archived at
^ Philip A. Slaymaker. "Eliminating SAVE@ and Other 1541 Bugs". The
Transactor Vol. 7 № O2, September 1986, pp. 33–35.
Immers, Richard; Neufeld, Gerald G. (1984). Inside Commodore DOS. The
Complete Guide to the 1541 Disk Operating System. DATAMOST, Inc &
Reston Publishing Company, Inc. (Prentice-Hall).
Englisch, Lothar; Szczepanowski, Norbert (1984). The Anatomy of the
1541 Disk Drive. Grand Rapids, MI: Abacus Software (translated from
the original 1983 German edition, Düsseldorf: Data Becker GmbH).
(in Finnish) Lundahl, Reijo (1986). 1541-Levyasema. Amersoft.