The VIC-1541 disk drive is a single-sided, single-density (SS/SD) 5.25” floppy drive connected to the C64 via the serial bus (IEC bus). It contains its own 6502 CPU and 2KB of RAM.
| Tracks | Sectors/Track | Cumulative Sectors |
|---|---|---|
| 1-17 | 21 | 0-356 |
| 18-24 | 19 | 357-490 |
| 25-30 | 18 | 491-598 |
| 31-35 | 17 | 599-682 |
Every disk operation goes through logical files. The steps are:
SETLFS — assign logical file number, device, secondary addressSETNAM — assign filenameOPEN — open the fileCHKIN/CHKOUT — redirect input/output to the fileBASIN/BSOUT — read/write dataCLOSE — close the fileFrom BASIC, use: OPEN LFN, DEV, SA, "FILENAME"
| Type | SA Range | Description |
|---|---|---|
| Program | 0-1 | Machine language or BASIC programs |
| Sequential | 2 | Sequential data files (read/write, not both at once) |
| Relative | any+SA | Fixed-length record random-access files |
| Command | 15 | Command channel (send DOS commands, read error) |
LOAD "FILENAME",8 ' Load BASIC program
LOAD "FILENAME",8,1 ' Load at original address (ML programs)
SAVE "FILENAME",8 ' Save BASIC program
SAVE "@:FILENAME",8 ' Save and overwrite existing file
VERIFY "FILENAME",8 ' Verify saved file matches memory
LOAD "$",8 ' Load directory as BASIC program
LIST ' Display directory
OPEN 15,8,15,"COMMAND" ' Open command channel with command
CLOSE 15 ' Close command channel
10 OPEN 15,8,15 : REM Open command channel
20 INPUT#15,EN,EM$,ET,ES : REM Read error: number,message,track,sector
30 PRINT EN;EM$;ET;ES
40 CLOSE 15
The error channel should be read after every disk operation.
OPEN 15,8,15,"N0:DISKNAME,ID" : CLOSE 15
' N0: = NEW on drive 0; ID = 2-char disk ID (e.g., "A1")
' WARNING: Destroys all data on disk
OPEN 15,8,15,"S0:FILENAME" : CLOSE 15
' Wildcards supported: S0:TEST* deletes all files starting with TEST
OPEN 15,8,15,"R0:NEWNAME=OLDNAME" : CLOSE 15
OPEN 15,8,15,"C0:DEST=0:SOURCE" : CLOSE 15
OPEN 15,8,15,"V0:" : CLOSE 15
' Reclaims space from improperly closed files
OPEN 15,8,15,"I0:" : CLOSE 15
' Re-reads BAM; use after swapping disks
* — matches any sequence of characters? — matches any single characterOPEN 15,8,15,"S0:TEST*" : CLOSE 15 ' scratch all TEST files
Sequential files are read or written in order only (not random access).
10 OPEN 1,8,2,"MYDATA,S,W" ' LFN=1, DEV=8, SA=2, write sequential
20 PRINT#1,"LINE 1 DATA"
30 PRINT#1,"LINE 2 DATA"
40 PRINT#1,NUMBER ' Numbers also work
50 CLOSE 1
10 OPEN 1,8,2,"MYDATA,S,R" ' SA=2, read sequential
20 IF ST<>0 THEN 60 ' ST = status byte; non-zero = EOF/error
30 INPUT#1,LINE$
40 PRINT LINE$
50 GOTO 20
60 CLOSE 1
OPEN 1,8,2,"MYDATA,S,A" ' SA=2 with ,A flag appends
Relative files provide random access to fixed-length records.
10 OPEN 2,8,2,"MYREL,L," + CHR$(RECLEN)
' RECLEN = record length in bytes (1-254)
20 OPEN 15,8,15
30 RN = 5 ' desired record number (1-based)
40 LO = (RN-1) AND 255
50 HI = INT((RN-1)/256)
60 PRINT#15,"P" CHR$(2) CHR$(LO) CHR$(HI) CHR$(0)
' Channel 2 (the data file's SA), then record# low, high, byte offset
' After positioning:
PRINT#2, FIELD1$, FIELD2$ ' write
INPUT#2, FIELD1$, FIELD2$ ' read (re-position first)
| Code | Message | Meaning |
|---|---|---|
| 00 | OK | No error |
| 01 | FILES SCRATCHED | Normal after SCRATCH |
| 20 | READ ERROR | Block header not found |
| 21 | READ ERROR | No sync character found |
| 22 | READ ERROR | Data block not found |
| 23 | READ ERROR | Checksum error in data |
| 24 | READ ERROR | Byte decoding error |
| 25 | WRITE ERROR | Write verify error |
| 26 | WRITE PROTECT ON | Write-protect tab covered |
| 27 | READ ERROR | Checksum error in header |
| 28 | WRITE ERROR | Long data block |
| 29 | DISK ID MISMATCH | Wrong disk in drive |
| 30 | SYNTAX ERROR | DOS command syntax error |
| 31 | SYNTAX ERROR | Invalid command |
| 32 | SYNTAX ERROR | Long line |
| 33 | SYNTAX ERROR | Invalid filename |
| 34 | SYNTAX ERROR | No file given |
| 39 | SYNTAX ERROR | Invalid command |
| 50 | RECORD NOT PRESENT | Past end of relative file |
| 51 | OVERFLOW IN RECORD | Wrote past end of record |
| 52 | FILE TOO LARGE | Relative file too large |
| 60 | WRITE FILE OPEN | File still open for writing |
| 61 | FILE NOT OPEN | File not open |
| 62 | FILE NOT FOUND | File does not exist |
| 63 | FILE EXISTS | File already exists (overwrite with @) |
| 64 | FILE TYPE MISMATCH | Wrong file type for operation |
| 65 | NO BLOCK | Block already allocated |
| 66 | ILLEGAL TRACK OR SECTOR | Bad T/S reference |
| 67 | ILLEGAL SYSTEM T OR S | Bad system track/sector |
| 70 | NO CHANNEL | No free logical channel |
| 71 | DIR ERROR | Directory error (use VALIDATE) |
| 72 | DISK FULL | No free blocks |
| 73 | CBM DOS Vxx.x | Power-on/INITIALIZE message |
| 74 | DRIVE NOT READY | No disk or drive error |
The 1541 allows reading/writing individual sectors directly.
OPEN 15,8,15
OPEN 2,8,2,"#" ' open direct-access channel
PRINT#15,"B-R:2 0 " TRACK " " SECTOR
' Read into drive buffer; then read bytes via GETIN or INPUT#
' Write buffer to disk after filling via BSOUT:
PRINT#15,"B-W:2 0 " TRACK " " SECTOR
PRINT#15,"B-P:2 " POS ' set byte position in buffer (0-255)
Track 18, Sector 0 = BAM (Block Availability Map)
BAM format:
Track 18, Sectors 1-18 = Directory
Each directory sector holds 8 directory entries (32 bytes each):
; Open logical file 1 to disk drive 8, secondary address 2, filename "DATA"
LDA #1 ; logical file number
LDX #8 ; device (disk)
LDY #2 ; secondary address
JSR $FFBA ; SETLFS
LDA #4 ; filename length
LDX #<FNAME
LDY #>FNAME
JSR $FFBD ; SETNAM
JSR $FFC0 ; OPEN
BCS error ; carry set = error
LDX #1 ; logical file number
JSR $FFC9 ; CHKOUT - redirect output to file
LDA #65 ; character 'A'
JSR $FFD2 ; BSOUT - write to file
JSR $FFCC ; CLRCH - restore default channels
LDA #1
JSR $FFC3 ; CLOSE
FNAME .TEXT "DATA"
Powered by TurnKey Linux.