Programming the MEGA65 — Chapter 15: Using the Disk Drive

Oct 4, 2026 · Updated Oct 11, 2026 · @Craig Taylor

Introduction

Most of this chapter applies equally to a disk image on the SD card, the MEGA65's internal 3.5" drive and a Commodore drive on the IEC port. All three speak Commodore DOS, so ordinary file handling written for one works on the others. The MEGA65's own DOS adds features an older drive lacks, such as partitions; the text notes where that matters. Chapter 14 explained images and unit numbers; this chapter covers the drive itself, files of each type, the drive's status, and disk access from machine language.

Drives, Units and Drive Numbers

Every drive is reached through a unit number. Units 8 to 11 are reserved for disk drives, and BASIC 65's disk commands use unit 8 unless given a U argument. A unit assigned to a disk image or to the internal drive is handled inside the MEGA65; any other unit number is sent to the IEC port, where the device with that number answers (MEGA65 Book, p. 6-3).

The D argument selects a drive within a unit. It is needed only for old dual-drive units such as the Commodore 4040 or 8050, where the second drive is drive 1; every other drive is drive 0.

The internal 3.5" drive

The internal drive behaves as a Commodore 1581 and reads and writes 1581-format disks. It must be mounted before use: in the Freezer, choose the first managed drive and select INTERNAL 3.5", or type MOUNT with no arguments in BASIC to mount it as unit 8 (MEGA65 Book, pp. 6-6, 6-7).

The drive expects Double Density (DD) disks. High Density disks work if both sides of the density hole, top left when viewed from the front, are covered with tape, which makes the drive treat them as DD (MEGA65 Book, pp. 6-7, 6-8).

To format a disk, mount the drive as unit 8, insert the disk and give it a name and a two-character ID:

FORMAT "MYDISK", IXX

When asked ARE YOU SURE?, type YES and press RETURN. Formatting takes about a minute; afterwards, DIR shows an empty directory with the new name and ID.

IEC drives

External drives such as the 1541, 1571 and 1581, and modern devices such as SD2IEC and Pi1541, plug into the IEC port and need no mounting. If one needs a unit number the MEGA65 has given to a managed drive, use the Freezer's 8 and 9 keys to move the managed drive to 10 or 11 (MEGA65 Book, p. 6-9).

Files

File types

Type Contents Used with
PRG A program or memory block, starting with a two-byte load address DLOAD, DSAVE, BLOAD, BSAVE, RUN
SEQ Sequential data, read and written from start to end DOPEN, PRINT#, INPUT#, APPEND
USR Like SEQ, but marked for application-specific use DOPEN, APPEND
REL Relative file of fixed-length records, read in any order DOPEN with L, RECORD
CBM A 1581 partition, used for subdirectories MKDIR, CHDIR (internal drive and disk images only, not IEC drives)

Sequential files

A sequential file is written with PRINT# and read back with INPUT# or LINE INPUT#, in the same order. Separate fields with commas, or write each on its own line, so INPUT# can tell where one ends:

10 DOPEN#2, "SCORES", W
20 IF DS THEN PRINT DS$ : STOP
30 FOR I = 1 TO 3 : READ N$, S : PRINT#2, N$ "," S : NEXT
40 DCLOSE#2
50 DATA ALICE, 1200, BOB, 900, CAROL, 1500
100 DOPEN#2, "SCORES"
110 DO : INPUT#2, N$, S : PRINT N$, S : LOOP UNTIL ST
120 DCLOSE#2

ST becomes non-zero when the last item has been read. Adding to an existing file uses APPEND# instead of DOPEN#, and replacing a file needs it to be scratched first, or an @ before the name, which works for data files as well as programs, as in DOPEN#2, "@SCORES", W (MEGA65 Book, DOPEN). Avoid @ with 1541 and 1571 drives, as the Book advises.

Relative files

A relative file holds numbered records of a fixed length, given with L when the file is first created. RECORD moves to any record directly, which suits indexes, high-score tables and small databases where a sequential file would have to be read from the start:

10 DOPEN#3, "PLAYERS", L20
20 RECORD#3, 5 : PRINT#3, "PLAYER FIVE"
30 RECORD#3, 2 : PRINT#3, "PLAYER TWO"
40 RECORD#3, 5 : INPUT#3, A$ : PRINT A$
50 DCLOSE#3

Each record must fit its length, including the carriage return PRINT# adds.

Drive status

Every disk operation leaves a status in the drive, which BASIC 65 reads into DS and DS$. DS$ has the form code, message, track, sector. Codes below 20 mean success; the common ones are:

Code Meaning
00 OK
01 Files scratched (the track value gives how many)
20-29 Read or write errors: the disk is damaged, unformatted or write-protected
26 Write protect on
62 File not found
63 File exists
72 Disk full
74 Drive not ready: no disk

These are the standard Commodore DOS codes, which the MEGA65's drives share with the 1581. Checking DS after each DOPEN and save is the single most effective way to make a program that uses disks reliable.

Booting Disks

There are three ways to start software from a disk (MEGA65 Book, pp. 6-9, 6-10):

To make a disk of your own bootable, save its starting program as AUTOBOOT.C65. BOOT loads that file as a BASIC program and RUNs it, so a machine-language boot program needs a one-line BASIC stub that SYSes to it. To load and start a machine-language file directly, use BOOT "name", which loads the file and calls its load address (MEGA65 ROM source, BOOT).

Disk Access from Machine Language

Machine language reaches the drive through the KERNAL jump table from Chapter 11, exactly as on a C64. This routine prints the first line of a sequential file:

        lda #0          ; data and file name in bank 0
        ldx #0
        jsr $ff6b       ; SETBNK
        lda #2          ; logical file 2
        ldx #8          ; unit 8
        ldy #2          ; secondary address 2
        jsr $ffba       ; SETLFS
        lda #namelen
        ldx #<name
        ldy #>name
        jsr $ffbd       ; SETNAM
        jsr $ffc0       ; OPEN
        bcs error
        ldx #2
        jsr $ffc6       ; CHKIN: read from file 2
loop    jsr $ffcf       ; BASIN: read a byte
        cmp #13
        beq done        ; stop at the end of the line
        jsr $ffd2       ; BSOUT: print it
        jsr $ffb7       ; READST
        beq loop        ; continue while status is 0
done    jsr $ffcc       ; CLRCHN
        lda #2
        jsr $ffc3       ; CLOSE
        rts
error   rts

name    .text "SCORES,S,R"
namelen = * - name

The secondary address 2 to 14 opens a data channel; 0 and 1 are reserved for loading and saving, and 15 is the command channel, through which a program sends DOS commands and reads the status, as DISK and DS do in BASIC. SETBNK, one of the extended entries the C65 inherited from the C128, tells the KERNAL which bank the data (A) and the file name (X) are in. It must be called before OPEN, LOAD or SAVE; Chapter 11 also covers its form for 28-bit addresses.

For files on the SD card outside disk images, and for loading large files into attic RAM, use the Hypervisor services described in Chapters 8 and 14 instead.

Summary

Chapter 16 covers the control ports.