"From the old we improve the new"
SPECIAL THANKS TO: Richard Evers (Transactor Magazine)
"Thanks for having faith"
TITLE : Anatomy of the 4040 Disk Drive
AUTHOR : Hilaire Gagne
4501 Carl Street
P.O. Box 278
Hanmer, Ontario, CANADA
P0M 1Y0
TELEPHONE : 1-705-969-2189
DATE BEGUN : April 26th, 1985
DATE COMPLETED : February 18th, 1988
DESCRIPTION OF BOOK:
This book provides a complete description of the Commodore 4040 dual floppy drive. The book covers file management, data management disk management, file organization, advanced disk programming, hardware and software interfacing, RAM and ROM disassembly, and application examples.
F O R E W O R D
To begin with, I would like to thank you; the READER! I have been assembling this work since 1985; now after almost 3 years, the "ANATOMY OF THE 4040 DISK DRIVE" becomes a reality.
Some of you may wonder "WHY PURCHASE THIS BOOK" ? Well, even though the 4040 dual disk drive unit is now absolete; there still remains a very large base of these units throughout the world. Founder of the 1540/1541, 1570/1571 and now part of the new 1581 (3.5" drive) DOS, the 4040 dual drive has never quite been documented.
In the very pages of this book, you will find the beginning of COMMODORE DOS: methods and operation, even DOS BUGS !, originate here ! With a detailed assembly of early COMMODORE DOS, the inquisitive minds will now be able to fully understand the newest and oldest COMMODORE eight bit technology.
Hilaire Gagne
February 18th, 1988
O R D E R F O R M
Customer Name:
Address :
Enclosed is a money order for:
DESCRIPTION COST (Can) COST (Usa) QUANT
--------------------------------------------------------------------------
Anatomy of the 4040 dual disk drive $ 39.95 ea $ 31.95 ea
Anatomy of the 8050 dual disk drive N/A N/A N/A
Anatomy of the 1581 single 3.5" drive N/A N/A N/A
SUB-TOTAL : $ .
Postage ($ 3.00 Can/ $ 4.00 other): $ .
---------
TOTAL : $ .
Please address money order to: Hilaire Gagne
P.O. Box 278
4501 Carl Street
Hanmer, Ontario, CANADA
P0M 1Y0
(Allow 2-4 weeks for delivery)
Table of Contents
Chapter 1 - INTRODUCTION
Unpacking your 4040 dual floppy drive .......................1- 1
Hardware tree of Commodore products .........................1- 1
Recommended books for reading ...............................1- 2
Chapter 2 - DOS file management commands
DLOAD (BASIC 4.0) / LOAD (BASIC 2.0) command ................2- 1
DSAVE (BASIC 4.0) / SAVE (BASIC 2.0) command ................2- 1
BACKUP (BASIC 4.0) / DUPLICATE (BASIC 2.0) command ..........2- 2
RENAME command ..............................................2- 3
SCRATCH command .............................................2- 3
COPY (BASIC 4.0) command ....................................2- 4
CONCAT command ..............................................2- 5
Chapter 3 - DOS data management commands
DOPEN (BASIC 4.0) / OPEN (BASIC 2.0) command ................3- 1
DCLOSE (BASIC 4.0) / CLOSE (BASIC 2.0) command ..............3- 1
VERIFY (BASIC 2.0) command ..................................3- 2
PRINT# command ..............................................3- 3
GET# command ................................................3- 3
INPUT# command ..............................................3- 3
APPEND# (BASIC 4.0) command .................................3- 4
RECORD# (BASIC 4.0) / POSITION (BASIC 2.0) command ..........3- 4
FILE MODES: read ............................................3- 5
write ...........................................3- 5
append ..........................................3- 5
modify ..........................................3- 6
Chapter 4 - DOS disk management commands
HEADER (BASIC 4.0) / NEW (BASIC 2.0) command ................4- 1
COLLECT (BASIC 4.0) / VALIDATE (BASIC 2.0) command ..........4- 1
INITIALIZE (BASIC 2.0) command ..............................4- 2
CATALOG & DIRECTORY (BASIC 4.0) command .....................4- 3
LOAD "$" (BASIC 2.0) command ................................4- 3
DS$ (BASIC 4.0) / disk status (BASIC 2.0) command ...........4- 4
Diskette organization:
Track and Sectors: SYNCs & GCR .......4- 5
Sector encodement .4- 5
Sectors per track .4- 6
Directory track: BAM .................4- 6
Directory entries ...4- 7
File organization:
PRG (program files) ......................4- 8
SEQ (sequential files) ...................4- 8
REL (relative files) .....................4- 9
USR (user files) .........................4-10
DEL (deleted files) ......................4-10
Chapter 5 - Advanced disk programming
BLOCK commands: ALLOCATE ....................................5- 1
FREE ........................................5- 1
READ ........................................5- 2
WRITE .......................................5- 3
EXECUTE .....................................5- 3
POINTER .....................................5- 4
MEMORY commands: WRITE ......................................5- 5
READ .......................................5- 5
EXECUTE ....................................5- 6
USER commands: U0 (set ROM jump table) ......................5- 7
U1 or UA (block-read) ........................5- 7
U2 or UB (block-write) .......................5- 8
U3 or UC ($1300) .............................5- 9
U4 or UD ($1303) .............................5- 9
U5 or UE ($1306) .............................5-10
U6 or UF ($1309) .............................5-10
U7 or UG ($130C) .............................5-11
U8 or UH ($130F) .............................5-12
U9 or UI (NMI = $10F0) .......................5-12
U: or UJ (Power on) ..........................5-13
Chapter 6 - Hardware/software interfacing
Controller error messages ...................................6- 1
Permanent alteration of DEVICE number .......................6- 5
IEEE software controller (MOS 6502) .........................6- 6
FDC disk controller (MOS 6504) ..............................6- 7
Communicating between IEEE and FDC by use of the job queue ..6- 7
Trouble shooting (hardware) .................................6-11
Chapter 7 - IEEE software controller (MOS 6502)
Zero page ...................................................7- 1
RAM memory ..................................................7- 7
ROM memory ..................................................7-12
Chapter 8 - FORMATTING sequence used for 4040 dual floppy drive
Formatting code used for HEADER / NEW command ...............8- 1
Chapter 9 - FDC disk controller (MOS 6504)
Zero page ...................................................9- 1
RAM memory ..................................................9- 4
ROM memory ..................................................9- 5
APPENDIX A - Miscellaneous programs
How to type in programs .....................................A- 1
Anti chatter ................................................A- 2
Soft device change ..........................................A- 3
Get current disk ID's .......................................A- 4
Flash LED's .................................................A- 5
Move drive heads ............................................A- 6
Phase & density check .......................................A- 8
Read HEADER block ...........................................A-10
Speed up ....................................................A-12
DOS version code change .....................................A-13
Write protect sense test ....................................A-14
SPEED VARIATION .............................................A-16
APPENDIX B - IEEE bus definitions
IEEE bus connector pins .....................................B- 1
IEEE 488 bus signals ........................................B- 2
IEEE byte transfer sequence .................................B- 3
IEEE port pinouts ...........................................B- 5
IEEE standard definitions ...................................B- 6
APPENDIX C - IC memory/register configurations
6522 VIA (Versatile Interface Adaptor) ......................C- 1
6502 CPU ....................................................C- 2
6522 VIA control registers ..................................C- 3
Chapter 1 - INTRODUCTION
1.1 - UNPACKING YOUR 4040 DUAL FLOPPY DRIVE
Before unpacking the disk drive, inspect the shipping cartons for signs of external damage. If the carton is damaged, be especially careful when inspecting its content. Carefully remove all packing material and the contents of the carton. DO NOT discard any packing material until you have made sure you have located all the contents of the carton! The carton should contain:
1. Commodore Dual Floppy Disk Drive
2. User Manual, Part Number: 320899
3. TEST/DEMO diskette:
a. 2040/3040/4040 TEST/DEMO diskette, Part Number: 4040037
Well there it is, what the manual states on PAGE 9. After reading the pages to follow, or probably proceeding to hook up our new toy without bothering to read the rest of the manual, we turn on the dual floppy unit and begin experimenting with its features.
Several years pass, and Commodore Business Machines keep increasing their computer product line. But as time goes by, older machines become absolete. However, there still remains a large base of users who own some of Commodore's earlier technology. For those who still own a 4040 dual drive and have always wondered how it works, hopefully the following chapters will increase your knowledge on the inner workings of CBM DOS.
1.2 - HARDWARE TREE OF COMMODORE PRODUCTS
The following is a list of all known Commodore disk drives.
2040 drive - dual floppy (DOS 1) single sided 5.5"
3040 drive - dual floppy (DOS 1) single sided 5.5"
4040 drive - dual floppy (DOS 2.1) single sided 5.5"
8050 drive - dual floppy (DOS 2.5) single sided 5.5"
2031 drive - single floppy (DOS 2.6) single sided 5.5"
1541 drive - single floppy (DOS 2.6) single sided 5.5"
8250 drive - dual floppy (DOS 2.7) double sided 5.5"
SFD drive - single floppy (DOS 2.7) double sided 5.5"
D9060 drive - hard disk (DOS 3.0)
D9090 drive - hard disk (DOS 3.0)
1551 drive - single floppy (DOS 3.0) single sided 5.5"
1571 drive - single floppy (DOS 3.0) double sided 5.5"
1581 drive - single floppy (DOS 10) single sided 3.5"
1.3 - RECOMMENDED BOOKS FOR READING
TITLE : 1571 Internals
AUTHOR(S) : Rainer Ellinger
PUBLISHER : Abacus Software, Inc.
P.O. Box 7211
Grand Rapids, MI 49510,USA
TELEPHONE : 1-616-241-5510
ISBN number: 0-916439-01-1
TITLE : Disk System User Reference Guide
AUTHOR(S) : Commodore Business Machines, Inc.
PUBLISHER : Commodore Business Machines, Inc.
950 Airport Road
Westchester, PA 19380, USA
TELEPHONE :
PART number: 320972-01
TITLE : Inside Commodore DOS
AUTHOR(S) : Richard Immers and Gerald G. Neufeld
PUBLISHER : DATAMOST
20660 Nordhoff Street
Chatsworth, CA 91311-6152, USA
TELEPHONE : 1-818-709-1202
ISBN number: 0-88190-366-3
TITLE : PET/CBM and the IEEE 488 bus (GPIB)
AUTHOR(S) : Eugene Fisher and C.W. Jensen
PUBLISHER : Osborne/McGraw-Hill
630 Bancroft Way
Berkeley, CA 94710, USA
TELEPHONE :
ISBN number: 0-931988-78-0
TITLE : Programming the PET/CBM
AUTHOR(S) : Raeto Collin West
PUBLISHER : COMPUTE! Books, (Division of: Small Sytem Services, Inc.)
625 Fulton Street
P.O. Box 5406
Greensboro, North Carolina, 27403, USA
TELEPHONE : 1-919-275-9809
ISBN number: 0-942386-04-3
TITLE : The Anatomy of the 1541
AUTHOR(S) : Lothar Englisch and Norbert Szczepanowski
PUBLISHER : Abacus Software, Inc.
P.O. Box 7211
Grand Rapids, MI 49510, USA
TELEPHONE : 1-616-241-5510
ISBN number: 0-916439-01-1
TITLE : The Complete Commodore Inner Space Anthology
AUTHOR(S) : Karl J. Hildon
PUBLISHER : TRANSACTOR
501 Alden Road
P.O. Box 3250
Markham Industrial Park
Markham, Ontario, CANADA
L3R 9Z9
TELEPHONE : 1-416-764-7253
ISBN number: 0-9692086-0-X
TITLE : The MSD DOS reference guide
AUTHOR(S) : David W. Martin
PUBLISHER : The OpCode Factory
1417 South Heron Drive
Seabrook, Texas, 77586, USA
TELEPHONE :
ISBN number:
TITLE : The PET revealed
AUTHOR(S) : Nick Hampshire
PUBLISHER : Commodore Business Machines (UK), Ltd.
818 Leigh Road, Trading Estate
Slough, Berkshire
TELEPHONE : Slough (0753) 74111
ISBN number:
TITLE : User's manual for CBM 5.5" dual floppy disk drives
AUTHOR(S) : Commodore Business Machines, Inc.
PUBLISHER : Commodore Business Machines, Inc.
3330 Scott Boulevard
Santa Clara, California, 95051
TELEPHONE :
PART number: 320899
Chapter 2 - DOS file management commands
2.1 - DLOAD (BASIC 4.0) / LOAD (BASIC 2.0) command
PURPOSE : To retrieve a file stored on a diskette.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: DLOAD "filename,ex",Ddr ON Udv
LOAD "dr:filename,ex",dv,ch
dr = Desired drive number
ex = Filetype extension (D,P,R,S,U)
dv = Disk drive device number
ch = Secondary address channel number
filename = Desired file on diskette (maximum 16 characters, 13 if extension)
is used.
WILDCARDS : * ?
ROM ENTRY POINT : $D4A6 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
$ 16 (LOAD function = 0)
REGISTERS : . X = character from command buffer
. Y =
.ACC = command waiting flag
2.2 - DSAVE (BASIC 4.0) / SAVE (BASIC 2.0) command
PURPOSE : To store a file on a diskette
SUPPORTED DOS : All
RECOMMENDED SYNTAX: DSAVE "rpfilename,ex",Ddr ON Udv
SAVE "dr:rpfilename,ex",dv,ch
dr = Desired drive number
ex = Filetype extension (D,P,R,S,U)
dv = Disk drive device number
rp = File replacement indicator (`)
ch = Secondary address channel number
filename = Desired file on diskette (maximum 16 characters, 13 if extension)
is used.
WILDCARDS : `
ROM ENTRY POINT : $D4A6 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
$ 16 (LOAD function = 0)
REGISTERS : . X = character from command buffer
. Y =
.ACC = command waiting flag
2.3 - BACKUP (BASIC 4.0) / DUPLICATE (BASIC 2.0) command
PURPOSE : To perform an exact copy of a diskette onto another
diskette.
SUPPORTED DOS : Dual drive units only
RECOMMENDED SYNTAX: BACKUP Dsr TO Ddr
PRINT#ch,"Ddr=sr"
ch = Primary address channel number
sr = Source drive number
dr = Destination drive number
WILDCARDS : None
ROM ENTRY POINT : $E346 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
REGISTERS : . X = source drive number
. Y = destination drive number
.ACC = byte read from block
2.4 - RENAME command
PURPOSE : To change the current title of a file on the diskette
to a new title.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: RENAME Ddr,"filename" TO "newfilename" ON Udv
PRINT#ch,"Rdr:newfilename=filename"
ch = Primary address channel number
dr = Desired drive number
dv = Disk drive device number
filename = Current title of file on diskette (maximum 16 characters)
newfilename = Desired title for current file on diskette
(maximum 16 characters)
WILDCARDS : None
ROM ENTRY POINT : $E675 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
REGISTERS : . X =
. Y =
.ACC = desired drive number
2.5 - SCRATCH command
PURPOSE : To remove a file from a diskette.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: SCRATCH Ddr,"filename,ex" ON Udv
PRINT#ch,"Sdr:filename,ex"
ch = Primary address channel number
dr = Desired drive number
dv = Disk drive device number
ex = Filetype extension (D,P,R,S,U)
filename = Current title of file on diskette (maximum 16 characters)
WILDCARDS : ? *
ROM ENTRY POINT : $E2B7 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
REGISTERS : . X = index into file information table
. Y = pointer to directory entry
.ACC =
2.6 - COPY command
PURPOSE : To transfer files from a diskette to another.
SUPPORTED DOS : All (to certain extent)
RECOMMENDED SYNTAX: COPY Dsdr,"filename" TO Ddr,"newfilename" ON Udv
COPY Dsdr TO Ddr ON Udv
PRINT#ch,"Cdr:newfilename=sdr:filename"
PRINT#ch,"Cdr=sdr"
ch = Primary address channel number
dr = Destination drive number
sdr = Source drive number
dv = Disk drive device number
filename = Current title of file on diskette (maximum 16 characters)
newfilename = Desired title for current file on diskette
(maximum 16 characters)
WILDCARDS : ? *
ROM ENTRY POINT : $E44A (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
REGISTERS : . X = index into command buffer
. Y =
.ACC = character from command buffer
2.7 - CONCAT (BASIC 4.0) command
PURPOSE : To link one or more file so as to have one file only.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: CONCAT Dsdr,"filename" TO Ddr,"newfilename" ON Udv
dr = Destination drive number
sdr = Source drive number
dv = Disk drive device number
filename = Current title of file on diskette to be used as source
file for linking (maximum 16 characters)
newfilename = Current title of file on diskette to be used as destination
file for linking (maximum 16 characters)
WILDCARDS : None
ROM ENTRY POINT : $E587 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$437D (file stream count)
$437E (file stream count)
$437F (file stream count)
$ 16 (internal channel mode)
$ 8B (destination drive number)
$ 8C (source drive number)
$ B3 (internal read channel)
$ B4 (internal write channel)
REGISTERS : . X =
. Y =
.ACC = parameters for command
Chapter 3 - DOS data management commands
3.1 - DOPEN (BASIC 4.0) / OPEN (BASIC 2.0) command
PURPOSE : To permit user/programmer access to DOS and files on a
diskette.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: DOPEN#pa,"filename",md,Ddr ON Udv
DOPEN#pa,"rpfilename",Lrl,Ddr ON Udv
DOPEN#pa,"#bf",Ddr ON Udv
OPEN pa,dv,ch,"rpdr:filename,ex,md"
OPEN pa,dv,ch,"rpdr:filename,Lrl"
OPEN pa,dv,ch,"#bf"
pa = Primary address channel number
ch = Secondary address channel number
dv = Disk drive device number
dr = Desired drive number
bf = Optional DOS buffer number (0-14)
rp = File replacement indicator (`)
ex = Filetype extension (D,P,R,S,U)
md = File mode (R,W,A,M)
rl = Record length of RELATIVE file
filename = Desired file on diskette (maximum 16 characters)
WILDCARDS : * ?
ROM ENTRY POINT : $D4A6 (main entry point)
$F279 (beginning of OPEN command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y =
.ACC =
3.2 - DCLOSE (BASIC 4.0) / CLOSE (BASIC 2.0) command
PURPOSE : To release user/programmer access to DOS and files on a
diskette.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: DCLOSE#pa ON Udv
CLOSE pa
pa = Primary address channel number
dv = Disk drive device number
WILDCARDS : None
ROM ENTRY POINT : $D4A6 (main entry point)
$F58D (beginning of CLOSE command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y =
.ACC =
3.3 - VERIFY (BASIC 2.0) command
PURPOSE : To compare a file stored on diskette with the current
file in computer memory.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: VERIFY "dr:filename",dv
dv = Disk drive device number
dr = Desired drive number
filename = Desired file on diskette (maximum 16 characters)
WILDCARDS : * ?
ROM ENTRY POINT : None
MEMORY SET-UP : $4300 (DOS command buffer)
3.4 - PRINT# command
The PRINT# command is used to send information/data to the 4040 dual drive.
PRINT#pa,"data"
PRINT#pa,data
pa = Primary address channel number
data = Parameters or data to be sent to the disk unit
var = Variable used to contain information/data from disk: ALPHANUMERIC
NUMERIC
3.5 - GET# command
The GET# command is used to retrieve information/data from the 4040 dual drive. Only a single character of information/data may be retrieved at a time with this command.
GET#pa,var
pa = Primary address channel number
var = Variable used to contain information/data from disk: ALPHANUMERIC
NUMERIC
3.6 - INPUT# command
The INPUT# command is used to retrieve information/data from the 4040 dual drive. Information/data will be retrieved and stored in a specified variable until the following characters are encountered: , ; : * ? RETURN
INPUT#pa,var
pa = Primary address channel number
var = Variable used to contain information/data from disk: ALPHANUMERIC
NUMERIC
This command is also used to retrieve the disk status (see CHAPTER 4).
3.7 - APPEND# (BASIC 4.0) command
PURPOSE : To permit more data to be written at the end of a file
on disk.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: APPEND#pa,"filename",Ddr ON Udv
dv = Disk drive device number
dr = Desired drive number
pa = Primary address channel number
filename = Desired file on diskette (maximum 16 characters)
WILDCARDS : * ?
ROM ENTRY POINT : $D4A6 (main entry point)
$F279 (beginning of OPEN command)
$F425 (beginning of APPEND command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y =
.ACC =
3.8 - RECORD# (BASIC 4.0) / POSITION (BASIC 2.0) command
PURPOSE : To permit access of a specified record/field within a
RELATIVE file.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: RECORD#pa,rn,bp
PRINT#15,"P"+CHR$(pa+96)+CHR$(rl)+CHR$(rh)+CHR$(bp)
pa = Primary address channel number
rn = Desired record number
rl = LO byte of desired record number
rh = HI byte of desired record number
bp = Desired byte position within record
WILDCARDS : None
ROM ENTRY POINT : $FCED (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
$4379 (length of command string)
$437A (command number)
$ 16 (secondary address)
$ 45 (command buffer LO byte pointer)
REGISTERS : . X =
. Y = parameter settings
.ACC = character from command buffer
3.9 - FILE MODES
Before continuing into the different file modes possible, it should be noted that most BASIC 2.0 commands require that OPEN be performed. When using or making files, OPEN or DOPEN must be used.
There are four types of file modes, these are: Read, Write, Append, and Modify.
READ :
This mode is used to view the information/data within a file. Any file type may be opened for reading.
WRITE :
This mode is used to create and store information/data within a file. Any file type may be opened for writing.
APPEND:
This mode is used to reach the end of a current file on disk. When using this mode with PRG, REL, USR, DEL, care must be taken. Improper care may cause permanent corruption of the file in question.
MODIFY:
This mode is used to permit access to a file on disk which has not been properly closed (*).
The mode command may only be used within:
OPEN pa,dv,ch,"dr:filename,ex,md"
pa = Primary address channel
dv = Desired device number (0-15)
ch = Secondary address channel
dr = Desired drive number (0-1)
filename = Desired filename (16 characters maximum)
ex = File type extension (P, S, R, D, U)
md = Desired file mode (R, W, A, M)
The number of files which DOS can allow to be OPENed concurrently depends on the mix of SEQ, PRG, USR, DEL, and REL file types opened. The following combinations are permitted on the 4040 dual drive.
REL SEQ/PRG/USR/DEL
files opened: 0 5
1 3
2 2
3 0
Chapter 4 - DOS disk management commands
4.1 - HEADER (BASIC 4.0) / NEW (BASIC 2.0) command
PURPOSE : To make a diskette read/write compatible.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: HEADER "diskettename",Iid,Ddr ON Udv
PRINT#ch,"Ndr:diskettename,id"
dr = Desired drive number
id = Track/Sector identification marker
dv = Disk drive device number
ch = Secondary address channel number
diskettename = Desired name for diskette (maximum 16 characters)
WILDCARDS : None
ROM ENTRY POINT : $E20D (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
$4340 - 4341 (disk id location)
$1003 (job queue)
$1023 - 1024 (job header)
$1100 - 1300 (data buffers 0, 1, 2)
$ 13 (current track number)
$ 14 (current sector number)
REGISTERS : . X = index to storage location for parameters
. Y = index to next parameter to read
.ACC = parameter for command
4.2 - COLLECT (BASIC 4.0) / VALIDATE (BASIC 2.0) command
PURPOSE : To verify diskette and reconstruct a new BAM
SUPPORTED DOS : All
RECOMMENDED SYNTAX: COLLECT Ddr ON Udv
PRINT#ch,"Vdr"
dr = Desired drive number
dv = Disk drive device number
ch = Secondary address channel number
WILDCARDS : None
ROM ENTRY POINT : $E6EC (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
REGISTERS : . X =
. Y =
.ACC = parameter for command
4.3 - INITIALIZE (BASIC 2.0) command
PURPOSE : To position drive head on the directory track and read
the BAM.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"Idr"
dr = Desired drive number
dv = Disk drive device number
WILDCARDS : None
ROM ENTRY POINT : $ECC5 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$4347 (command waiting flag)
$4391 (file stream image)
REGISTERS : . X =
. Y =
.ACC = file stream image
4.4 - CATALOG & DIRECTORY (BASIC 4.0) command
PURPOSE : To display the directory track on the computer's
moniter.
SUPPORTED DOS : BASIC 4.0 (or higher)
RECOMMENDED SYNTAX: CATALOG Ddr ON Udv
DIRECTORY Ddr ON Udv
dr = Desired drive number
dv = Disk drive device number
WILDCARDS : None
ROM ENTRY POINT : $F279 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$433B (command waiting flag)
$437A (command number)
$ 11 (last program track link accessed)
$ 12 (current drive number)
$ 13 (current track number)
$ 16 (current secondary address)
REGISTERS : . X = parameters for command
. Y =
.ACC = command type
4.5 - LOAD "$" (BASIC 2.0) command
PURPOSE : To retrieve the directory from the diskette and
store it in the computer's memory.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: LOAD "$dr:pattern=ftype",dv
dr = Desired drive number
dv = Disk drive device number
pattern = Desired directory entries to view
ftype = Desired file type for directory entry to view
WILDCARDS : * ?
ROM ENTRY POINT : $F279 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
$433B (command waiting flag)
$437A (command number)
$ 11 (last program track link accessed)
$ 12 (current drive number)
$ 13 (current track number)
$ 16 (current secondary address)
REGISTERS : . X = parameters for command
. Y =
.ACC = command type
4.6 - DS$ (BASIC 4.0) / disk status (BASIC 2.0) command
PURPOSE : To retrieve the disk drive status.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: ? DS$
INPUT#pa,var,var,var,var
pa = Primary address channel number
var = ALPHANUMERIC variables (example: A$,B$,C$,D$)
WILDCARDS : None
ROM ENTRY POINT : None
MEMORY SET-UP : $43DC - 43FF (error message buffer)
REGISTERS : . X =
. Y =
.ACC =
DISKETTE ORGANIZATION
4.7 - Tracks and sectors: SYNCS & GCR
The SYNC character is used to warn the DOS that there is a HEADER BLOCK or DATA BLOCK coming. The length of a SYNC mark is usually 40 bits.
Beginning of SECTOR
..111 HEADER 1111111111111111111111111111111111111111 DATA 111111111111...
The storage format used on the disk is called: Group Code Recording. On the 4040 dual drive, there is a special converter chip which handles the conversion and de-conversion. When using locations $0041 (data input) and $0080 (data output) of the FDC controller, the data to read/write will be processed in GCR form.
HEX BINARY DECIMAL GCR
$00 0000 00 01010
$01 0001 01 01011
$02 0010 02 10010
$03 0011 03 10011
$04 0100 04 01110
$05 0101 05 01111
$06 0110 06 10110
$07 0111 07 10111
$08 1000 08 01001
$09 1001 09 11001
$0A 1010 10 11010
$0B 1011 11 11011
$0C 1100 12 01101
$0D 1101 13 11101
$0E 1110 14 11110
$0F 1111 15 10101
4.8 - Tracks and sectors: Sector encodement
There is a bit of discrepancy in the sector recording format. Below, is the diagram shown in most drive manuals. This diagram however, indicates how the retrieved track is displayed within DOS.
SYNC 08 ID1 ID2 TRK SCT CHKSUM GAP1 SYNC 07 LNKTRK LNKSCT 254 DATA CHKSUM GAP2
The actual recording structure used is shown in the diagram below:
SYNC 08 CHKSUM SCT TRK ID2 ID1 GAP1 SYNC 07 LNKTRK LNKSCT 254 DATA CHKSUM GAP2
As you can see, the HEADER BLOCK is reversed when written to the diskette.
4.9 - Track and Sectors: Sectors per track
Sector distribution by track is as follows:
# sectors zone density
track number 1 - 17 21 1 00
18 - 24 19 2 01
25 - 30 18 3 10
31 - 35 17 4 11
4.10 - Directory track: BAM
The Block Availability Map is a disk representation of available space on a diskette. As files are added or deleted from the disk directory, the BAM is altered accordingly. The BAM layout is as follows:
LOCATION: Track 18, sector 0
CONTENT : Byte number DATA DESCRIPTION
0 18 Track number of first directory block
1 1 Sector number of first directory block
2 65 DOS 2.0 format, ASCII "A"
3 0 Reserved for future DOS
4 - 143 BAM: Each track controlled by 4 bytes
BYTE 0: Total blocks free in track
BYTE 1: Sector availability ( 0- 7)
BYTE 2: Sector availability ( 8-15)
BYTE 3: Sector availability (16-end)
(1=FREE sector, 0=ALLOCATED sector)
144 - 161 Diskette name, padded with SHIFTED SPACES
162 - 163 Diskette ID number
164 160 SHIFTED SPACE
165 50 DOS version, ASCII "2"
166 65 DOS version, format "A"
167 - 170 160 SHIFTED SPACES
171 - 255 0 Unused (may display 'BLOCKS FREE' message)
4.11 - Directory track: Directory entries
In order to store information (files) on a diskette, a filename must be provided. After the file is stored on the diskette, the information needed for retrieval of the file is stored in a directory. The directory track is as follows:
LOCATION: Track 18, sectors 1 - 18
CONTENT : Byte number DATA DESCRIPTION
0 Track number of next directory block
1 Sector number of next directory block
2 - 31 File entry #1 of directory block (29 bytes)
BYTE: 1 = file type
2 = track pointer to 1st block
3 = sector pointer to 1st block
5 - 20 = file name
21 = track pointer to 1st side
sector if REL file
22 = sector pointer to 1st side
sector if REL file
23 = record length if REL file
24 - 25 = reserved for future file
information
26 = track pointer during (`)
command (replacement)
27 = sector pointer during (`)
command (replacement)
28 - 29 = number of blocks used by
file
32 - 33 Unused
34 - 63 File entry #2 of directory block (29 bytes)
64 - 65 Unused
66 - 95 File entry #3 of directory block (29 bytes)
96 - 97 Unused
98 - 127 File entry #4 of directory block (29 bytes)
128 - 129 Unused
130 - 159 File entry #5 of directory block (29 bytes)
160 - 161 Unused
162 - 191 File entry #6 of directory block (29 bytes)
192 - 193 Unused
194 - 223 File entry #7 of directory block (29 bytes)
224 - 225 Unused
226 - 255 File entry #8 of directory block (29 bytes)
FILE ORGANIZATION
There are five types of file organizations used on the 4040 dual drive: PRG, SEQ, REL, USR, DEL.
4.12 - PRG (program files)
The extension PRG denotes a file stored in the form of a computer usuable code. Usually BASIC or machine code programs created by a programmer are stored on the diskette with this extension following the size and filename.
When looking at the file stored on the diskette, one will notice that there are three major parts/blocks to the file:
Byte # Description
1st block : 0 - 1 Track/Sector of next PRoGram block
2 - 3 Load address: LO byte, HI byte
4 - 255 BASIC/machine code text
next blocks : 0 - 1 Track/Sector of next PRoGram block
2 - 255 BASIC/machine code text
last block : 0 Null byte to indicate last block of file
1 Last byte location in block
2 - ??? Last bytes of BASIC/machine code text
There are four possible PRG representations visible on the directory, these are:
TYPE HEX ASCII Description
*PRG $02 2 Unclosed program file
PRG $82 130 Program file
PRG $A2 162 Program replacement (`)
PRG< $C2 194 Locked program file
4.13 - SEQ (sequential files)
The SEQ extension usually denotes that the file stored on the diskette contains information/data. This file type usually appears upon user/programmer request (See CHAPTER 3).
It's internal structure consists of:
Byte # Description
1st block : 0 - 1 Track/Sector of next SEQuential block
2 - 255 DATA bytes of storage
next blocks : 0 - 1 Track/Sector of next SEQuential block
2 - 255 DATA bytes of storage
last block : 0 Null byte to indicate last block of file
1 Last byte location in block
2 - ??? Last DATA bytes of file
There are four possible SEQ representations visible on the directory, these are:
TYPE HEX ASCII Description
*SEQ $01 1 Unclosed sequential file
SEQ $81 129 Sequential file
SEQ $A1 161 Sequential replacement (`)
SEQ< $C1 193 Locked sequential file
4.14 - REL (relative files)
The REL extension usually denotes that the file stored on the diskette contains information/data. This file type usually appears upon user/programmer request (See CHAPTER 3).
The REL file type is divided into to parts, the SIDE SECTOR and DATA SECTOR.
SIDE SECTOR:
Byte # Description
1st block : 0 Track number of next side sector block
1 Sector number of next side sector block
2 Side sector number
3 Record length
4 - 5 Track and sector number of 1st side sector
6 - 7 Track and sector number of 2nd side sector
8 - 9 Track and sector number of 3rd side sector
10 - 11 Track and sector number of 4th side sector
12 - 13 Track and sector number of 5th side sector
14 - 15 Track and sector number of 6th side sector
16 - 255 Track and sector pointers to 120 data blocks
The largest REL file possible is 182,880 bytes long:
(120 pointers /per side sector * 6 side sectors) * 254 bytes /per block
DATA SECTOR:
Byte # Description
1st block : 0 - 1 Track/Sector of next RELative block
2 - 255 DATA bytes of storage
There are four possible REL representations visible on the directory, these are:
TYPE HEX ASCII Description
*REL $04 4 Cannot occur
REL $84 132 Relative file
REL $A4 164 Cannot occur
REL< $C4 196 Locked relative file
4.15 - USR (user files)
The USR extension usually denotes that the file stored on the diskette contains information/data. This file type usually appears upon user/programmer request (See CHAPTER 3). It may also denote a file stored in the form of a computer usuable code; usually BASIC or machine code programs created by a programmer.
A USR file follows the PRG or SEQ structure only. However, user/programmer design may also be implemented. There are four possible USR representations visible on the directory, these are:
TYPE HEX ASCII Description
*USR $03 3 Unclosed user file
USR $83 131 User file
USR $A3 163 User replacement (`)
USR< $C3 195 Locked user file
4.16 - DEL (deleted files)
The DEL extension usually denotes that the file has been removed from the directory and is not to be displayed during viewing of the directory track. This file type only be visible upon user/programmer request (See CHAPTER 3).
A DEL file may follow the PRG or SEQ structure. However, user/programmer design may also be implemented. There are four possible DEL representations visible on the directory, these are:
TYPE HEX ASCII Description
*DEL $00 0 Does not appear, scratched
DEL $80 128 Deleted file
DEL $A0 160 Deleted replacement (`)
DEL< $C0 192 Locked deleted file
Chapter 5 - Advanced disk programming
B L O C K C O M M A N D S
The BLOCK commands make up the first part of the DISK ORIENTED UTILITIES. These commands allow various access to the diskette.
5.1 - BLOCK - ALLOCATE
PURPOSE : To mark a block in the BAM as used.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"B-A:"dr;tr;se
ch = Primary address channel number
dr = Desired drive number
tr = Desired track number
se = Desired sector number
WILDCARDS : None
ROM ENTRY POINT : $E8AF (main entry point)
$E992 (beginning of ALLOCATE command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X = drive number
. Y = marker for BAM block in use (set to: #$01)
.ACC = current sector in BAM
5.2 - BLOCK - FREE
PURPOSE : To mark a block in the BAM as available.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"B-F:"dr;tr;se
ch = Primary address channel number
dr = Desired drive number
tr = Desired track number
se = Desired sector number
WILDCARDS : None
ROM ENTRY POINT : $E8AF (main entry point)
$E989 (beginning of FREE command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X = index into BIT MAP table ($EBC9)
. Y = pointer to BAM block sector
.ACC = marker used to set block free (set to: #$00)
5.3 - BLOCK - READ
PURPOSE : Enables any block from a format compatible diskette to
be read.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"B-R:"bu;dr;tr;se
ch = Primary address channel number
bu = Second secondary address channel number to use as buffer
dr = Desired drive number
tr = Desired track number
se = Desired sector number
WILDCARDS : None
ROM ENTRY POINT : $E8AF (main entry point)
$E9F5 (beginning of READ command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X = index to next character in buffer
. Y = pointer to current buffer: bu
.ACC = byte read from block
5.4 - BLOCK - WRITE
PURPOSE : Writes the current content of a specified buffer to any
track and sector of a write compatible diskette.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"B-W:"bu;dr;tr;se
ch = Primary address channel number
bu = Second secondary address channel number to use as buffer
dr = Desired drive number
tr = Desired track number
se = Desired sector number
WILDCARDS : None
ROM ENTRY POINT : $E8AF (main entry point)
$EA12 (beginning of WRITE command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (00 - 02: $1100 - $13FF) 256 bytes each
DATA BUFFER (03 - 06: $2000 - $23FF) 256 bytes each
DATA BUFFER (07 - 10: $3000 - $33FF) 256 bytes each
DATA BUFFER (11 - 14: $4000 - $43FF) 256 bytes each
REGISTERS : . X = index to next character in buffer
. Y = pointer to current buffer: bu
.ACC = byte read from block
5.5 - BLOCK - EXECUTE
PURPOSE : Reads the content from s specified track and sector into
a specified buffer, then jumps in machine language to the
start of the data in the buffer.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"B-E:"bu;dr;tr;se
ch = Primary address channel number
bu = Second secondary address channel number to use as buffer
dr = Desired drive number
tr = Desired track number
se = Desired sector number
WILDCARDS : None
ROM ENTRY POINT : $E8AF (main entry point)
$EA44 (beginning of EXECUTE command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X = pointer to current buffer: bu
. Y =
.ACC = HI/LO byte of buffer address location
5.6 - BLOCK - POINTER
PURPOSE : Sets the beginning position for writing or reading data
from/to a given sector/buffer.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"B-P:"bu;po
ch = Primary address channel number
bu = Second secondary address channel number to use as buffer
po = Byte position within sector/buffer
WILDCARDS : None
ROM ENTRY POINT : $E8AF (main entry point)
$EA5B (beginning of POINTER command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X = pointer to current buffer: bu
. Y = current channel number
.ACC = byte position of next character to write/read
in sector/buffer
M E M O R Y C O M M A N D S
The MEMORY commands make up the second part of the DISK ORIENTED UTILITIES. These commands allow various access to the ROM/RAM found within the 4040 dual drive.
5.7 - MEMORY - WRITE
PURPOSE : Enables data to be placed in the 4040 dual drive RAM. A
maximum of 34 BYTES may be sent with each use of this
command.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"M-W"CHR$(adl)CHR$(adh)CHR$(nu)CHR$(da)
ch = Primary address channel number
adl = LO byte of desired memory address
adh = HI byte of desired memory address
nu = Number of bytes to be sent
da = Data bytes to be sent
WILDCARDS : None
ROM ENTRY POINT : $E7A8 (main entry point)
$E7FC (beginning of WRITE command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y = pointer to next byte to be written in DOS
.ACC = byte to be written to DOS
5.8 - MEMORY - READ
PURPOSE : Enables data to be read from the 4040 dual drive RAM/ROM.
Only 1 BYTE may be read from the DOS at a time by use
of the GET# command.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"M-W"CHR$(adl)CHR$(adh)CHR$(nu)
ch = Primary address channel number
adl = LO byte of desired memory address
adh = HI byte of desired memory address
nu = Number of bytes to be read from DOS
WILDCARDS : None
ROM ENTRY POINT : $E7A8 (main entry point)
$E7CD (beginning of READ command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X = current byte number being read
. Y = pointer to next byte to be read from DOS
.ACC = byte read from DOS memory location
5.9 - MEMORY - EXECUTE
PURPOSE : Jumps to the desired memory address within the IEEE DOS
Controller.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"M-E"CHR$(adl)CHR$(adh)
ch = Primary address channel number
adl = LO byte of desired memory address
adh = HI byte of desired memory address
WILDCARDS : None
ROM ENTRY POINT : $E7A8 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y =
.ACC = HI/LO byte of memory address location
U S E R C O M M A N D S
The USER commands make up the third part of the DISK ORIENTED UTILITIES. These commands allow various access to the ROM/RAM, and diskette.
5.10 - U0 (Set ROM jump table)
PURPOSE : Stores $FFEA at ZERO PAGE location ($0000).
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U0:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for $FFEA
5.11 - U1 or UA (BLOCK - READ)
PURPOSE : Enables any block from a format compatible diskette to
be read.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U1:"bu;dr;tr;se
ch = Primary command address channel number
bu = Second secondary command address channel number to use as buffer
dr = Desired drive number
tr = Desired track number
se = Desired sector number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point)
$E9FE (beginning of U1/UA command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X = index to next character in buffer
. Y = pointer to current buffer: bu
.ACC = byte read from block
5.12 - U2 or UB (BLOCK - WRITE)
PURPOSE : Writes the current content of a specified buffer to any
track and sector of a write compatible diskette.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U2:"bu;dr;tr;se
ch = Primary command address channel number
bu = Second secondary command address channel number to use as buffer
dr = Desired drive number
tr = Desired track number
se = Desired sector number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point)
$EA38 (beginning of U2/UB command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (00 - 02: $1100 - $13FF) 256 bytes each
DATA BUFFER (03 - 06: $2000 - $23FF) 256 bytes each
DATA BUFFER (07 - 10: $3000 - $33FF) 256 bytes each
DATA BUFFER (11 - 14: $4000 - $43FF) 256 bytes each
REGISTERS : . X = index to next character in buffer
. Y = pointer to current buffer: bu
.ACC = byte read from block
5.13 - U3 or UC
PURPOSE : Jump to memory address located in USER JUMP TABLE.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U3:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$1300 (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (02: $1300) 256 bytes
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $1300
5.14 - U4 or UD
PURPOSE : Jump to memory address located in USER JUMP TABLE.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U4:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$1303 (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (02: $1303) 252 bytes
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $1303
5.15 - U5 or UE
PURPOSE : Jump to memory address located in USER JUMP TABLE.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U5:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$1306 (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (02: $1306) 250 bytes
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $1306
5.16 - U6 or UF
PURPOSE : Jump to memory address located in USER JUMP TABLE.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U6:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$1309 (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (02: $1309) 246 bytes
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $1309
5.17 - U7 or UG
PURPOSE : Jump to memory address located in USER JUMP TABLE.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U7:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$130C (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (02: $130C) 243 bytes
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $130C
5.18 - U8 or UH
PURPOSE : Jump to memory address located in USER JUMP TABLE.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U8:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$130F (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
DATA BUFFER (02: $130F) 240 bytes
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $130F
5.19 - U9 or UI
PURPOSE : Reset Non Maskable Interrupt vector.
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"U9:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$FFE6 (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $FFE6
5.20 - U: or UJ
PURPOSE : Perform POWER ON DIAGNOSTICS for drive (cold start).
SUPPORTED DOS : All
RECOMMENDED SYNTAX: PRINT#ch,"UJ:"
ch = Primary command address channel number
WILDCARDS : None
ROM ENTRY POINT : $E808 (main entry point: transferred to table at: $FFEA)
$D32B (table jump address set for this command)
MEMORY SET-UP : $4300 (DOS command buffer)
REGISTERS : . X =
. Y = byte from command buffer
.ACC = HI/LO pointer for: $D32B
Chapter 6 - Hardware/software interfacing
6.1 - Controller error messages
When the Floppy Disk Controller or the IEEE DOS management Controller encounter and error within DOS, a special routine located at $D953 will produce the following error numbers. Below, is a definition for each possible error number:
20: READ ERROR
(BLOCK HEADER not found). The disk controller is unable to locate the HEADER of the requested DATA BLOCK. Caused by an illegal sector number or the HEADER has been destroyed.
21: READ ERROR
(NO SYNC character). Indicates hardware failure.
22: READ ERROR
(DATA BLOCK not found). The disk controller has been requested to read or verify a DATA BLOCK that was not properly written. This error message occurs in conjunction with the BLOCK commands and indicates an illegal track and/or sector request.
23: READ ERROR
(CHECKSUM error in DATA BLOCK). This error message indicates that there is an error in one or more of the DATA bytes. The DATA has been read into DOS memory, but the checksum over the DATA is in error. This message may also indicate grounding problems.
24: READ ERROR
(Byte decoding error). The DATA or HEADER BLOCK has been read into DOS memory but a hardware error has been created due to an invalid bit pattern in the DATA byte. This message may also indicate grounding problems.
25: WRITE ERROR
(Write-verify error). This message is generated if the controller detects a mismatch between the written DATA and the DATA in DOS memory.
26: WRITE PROTECT ON
(Write sense on). This message is generated when the controller has been requested to write a DATA BLOCK while the write protect switch is depressed. Typically, this is caused by using a diskette with a write protect tab over the notch.
27: READ ERROR
(CHECKSUM error in HEADER BLOCK). The controller has detected an error in the HEADER of the requested DATA BLOCK. The BLOCK has not been read into DOS memory. This message may also indicate grounding problems.
28: WRITE ERROR
(Long DATA BLOCK). The controller attempts to detect the SYNC mark of the next HEADER after writing a DATA BLOCK. If the SYNC mark does not appear within a pre-determined time, the error message is generated. The error is caused by a bad diskette format (the DATA extends into the next BLOCK), or by hardware failure.
29: DISK ID MISMATCH
(Invalid DISK ID). This message is generated when the controller has been requested to access a diskette which has not been initialized. The message can also occur if a diskette has a bad HEADER.
30: SYNTAX ERROR
(General syntax). The DOS cannot interpret the command sent to the command channel. Typically, this is caused by an illegal number of file names, or patterns are illegally used.
31: SYNTAX ERROR
(Invalid command). The DOS does not recognize the command. The command must start in the first position.
32: SYNTAX ERROR
(Long line). The command sent is longer than 58 characters.
33: SYNTAX ERROR
(Invalid filename). Pattern matching is invalidly used in the DOPEN, OPEN, or DSAVE, SAVE commands.
34: SYNTAX ERROR
(No file given). The filename was left out of a command or the DOS does not recognize it as such. Typically, a colon (:) has been left out of the command.
39: SYNTAX ERROR
(Invalid command). This error may result if the command sent to the command channel (secondary address 15) is unrecognizable by the DOS.
50: RECORD NOT PRESENT
Result of disk reading past the last record via INPUT#, or GET# commands. This message will also occur after positioning to a record beyond the end of file in a relative file. If the intent is to expand the file by adding the new record (with a PRINT# command), the error message may be ignored. INPUT or GET should not be attempted after this error is detected without first repositioning to a valid record number.
51: OVERFLOW IN RECORD
DATA written with a PRINT# statement exceeds the defined relative record size. DATA is truncated to defined size. Typically, cause is failing to include carriage returns sent as field or record terminators when calculating the record size.
52: FILE TOO LARGE
Record position within a relative file indicates that not enough BLOCKS remain available on the disk to contain the specified number of records.
60: WRITE FILE OPEN
This message is generated when a write file that has not been closed is being opened for reading.
61: FILE NOT OPEN
This message is generated when a file that is being accessed has not been opened in the DOS. Sometimes, in this case, a message is not generated, the request is simply ignored.
62: FILE NOT FOUND
The requested file does not exist on the currently specified diskette.
63: FILE EXISTS
The file name of the file being created already exists on the diskette.
64: FILE TYPE MISMATCH
The file type on a DOPEN, OPEN command does not match the file type in the directory entry for the requested file.
65: NO BLOCK
This message occurs in conjunction with the B-A command. It indicates that the BLOCK to be allocated has been previously allocated. The parameters indicate the next higher track and sector number available. If the parameters are zeros (0), then all higher numbered BLOCKS are in use.
66: ILLEGAL TRACK OR SECTOR
The DOS has attempted to access a track or sector which does not exist in the format being used. This may also indicate a problem reading the pointer to the next BLOCK.
66: ILLEGAL SYSTEM T OR S
Special error message indicating an illegal system track or sector.
70: NO CHANNEL
(No availability). The requested channel is not available, or all channels are in use. A maximum of five (5) sequential files or three (3) relative files may be opened at one time to the DOS. Direct access channels may have six (6) opened files.
71: DIRECTORY ERROR
The BAM does not match the internal count. The error occurs when there is a problem in the BAM allocation or the BAM has been over-written in DOS memory. To correct this problem, re-initialize the diskette to restore the BAM in memory. Some active files may be terminated by the corrective action.
72: DISK FULL
Either all BLOCKS on the disk are in use or the directory is at its limit. DISK FULL is sent when two (2) BLOCKS remain available to allow the current file to be closed.
73: DOS MISMATCH
(CBM DOS V2). DOS 1 and DOS 2 are read compatible but not write compatible. Disks may be interchangeably read with either DOS, but a disk formatted on one version cannot be written upon with other versions because the format is different. This error is displayed whenever an attempt is made to write upon a disk which has been formatted in non-compatible format. This message may also appear after power-up.
76:
(Controller error). A variety of conditions indicating controller hardware problems.
6.2 - Permanent alteration of DEVICE number
The following alteration should be performed by a qualified service technician. The indicated pins should be bent, DO NOT CUT or BREAK OFF. Three pins on IC chip #6532 located at UE1 control the device number. The IC chip should CAREFULLY be removed and the appropriate pins SHOULD BE BENT !
Device number PIN 22 PIN 23 PIN 24
8 unchanged unchanged unchanged
9 unchanged unchanged BEND
10 unchanged BEND unchanged
11 unchanged BEND BEND
12 BEND unchanged unchanged
13 BEND unchanged BEND
14 BEND BEND unchanged
15 BEND BEND BEND
6.3 - IEEE software controller (MOS 6502)
The IEEE software controller acts as a "house keeping" processor. In fact, most INPUTS and OUTPUTS must pass through here. The IEEE software controller is composed of several parts of hardware, however the important IC Chips do most of the work. These are:
IC Chip #6502
This chip is located at location UN1 of the circuit board. Composed of two 1 MHz clocks, the 4040 dual drive can read information as well as write information during the same span of time. To achieve this, COMMODORE has designed the clocks to be 180 degrees phase shifted.
Communication between the IEEE software controller and the FDC controller is done via 1 Kilobyte (K) of RAM. The desired jobs are scanned for proper syntax and passed on, when needed, to the FDC controller.
There are two control IC Chips #6332 which compose the RAM for the operating system of the 4040 dual drive. To complement these, two other IC Chips were added to handle the INPUTS and OUTPUTS to various devices. These are:
IC Chip #6532
This chip can be found at location UE1 of the circuit board. Major support chip for IC Chip #6502, this particular IC Chip handles most INPUTS such as: IEEE data and handshake lines (DAV, NDAC, etc...). From here, the device number is read and the LED's on the front panel controlled.
The lower 128 BYTES of ZERO PAGE are also held within this IC Chip. For hardware purposes, the IC Chip #6532 holds exact similarity to the 6522 IC Chip.
IC Chip #6532
This chip can be found at location UC1 of the circuit board. Being another major support chip for IC Chip #6502, this particular IC Chip holds the upper 128 BYTES of ZERO PAGE.
Data from/to the IEEE bus is handled through here by use of three MC3446 buffers (located at UB1, UB2 & UD2 on the circuit board). Also done from this IC Chip, is the IEEE control for the 4 Kilobyte (K) RAMs located at: UC4, UD4, UE4, UF4, UC5, UD5, UE5 & UF5.
6.4 - FDC disk controller (MOS 6504)
The FDC disk controller controls the physical functions of the 4040 dual drive. Anything involving physical transport of the read/write head, track or sector, is done through the software (ROM) on this IC Chip. Operations to be performed by this controller are received from the IEEE software controller.
IC Chip #6522
This chip is located at UK3 on the circuit board. Its primary function is to control the drive and stepper motors of the 4040 dual drive.
IC Chip #6530
This chip is located at UM3 on the circuit board. The RAM inside this IC Chip is primarily used to store drive status information, drive select lines, write protect sense, and SYNC detect lines.
6.5 - Communicating between the IEEE and the FDC by use of the job queue
One of the most mystifying parts of the 4040 dual drive is the JOB QUEUE. This area of the 4040 dual drive serves as a link from IC Chip #6502 to IC Chip #6504. This area is composed of three parts: the DATA BUFFERS, the JOB HEADERS, and the JOB QUEUES.
The DATA BUFFERS
There are 14 data buffers on the 4040 dual drive, each buffer is linked to the IC Chip #6504 but at a different memory address. Whenever a series of instructions must be passed to the FDC controller (IC Chip #6504), the programmer must first store the data in the IEEE controller (IC Chip #6502) data buffers. From there, the machine code instructions (data) will be automatically passed to the FDC controller. The buffer layouts are as follows:
Buffer number IEEE controller FDC controller
0 $1100 - $11FF imaged to $0500 - $05FF
1 $1200 - $12FF imaged to $0600 - $06FF
2 $1300 - $13FF imaged to $0700 - $07FF
3 $2000 - $20FF imaged to $0800 - $08FF
4 $2100 - $21FF imaged to $0900 - $09FF
5 $2200 - $22FF imaged to $0A00 - $0AFF
6 $2300 - $23FF imaged to $0B00 - $0BFF
7 $3000 - $30FF imaged to $0C00 - $0CFF
8 $3100 - $31FF imaged to $0D00 - $0DFF
9 $3200 - $32FF imaged to $0E00 - $0EFF
10 $3300 - $33FF imaged to $0F00 - $0FFF
11 $4000 - $40FF imaged to $1000 - $10FF
12 (BAM drive 0) $4100 - $41FF imaged to $1100 - $11FF
13 (BAM drive 1) $4200 - $42FF imaged to $1200 - $12FF
14 (NOT USABLE!) $4300 - $43FF imaged to $1300 - $13FF
After storing the requested data in the required buffer, by use of the Chapter 5 commands, the start location of the machine code instructions must be given to the FDC controller. Incidentally, DATA BUFFERS 0 and 1 are used extensively by the DOS operating system; so make sure that the requested operations do not require the IEEE controller or the FDC controller to place information in these buffers if you plan on using them.
The JOB HEADERS
At this point, it should be mentioned that DATA BUFFERS 12, 13, and 14 are also reserved for: BAM drive 0, BAM drive 1, and $4300 - $43FF memory addresses. Now that we have covered the DATA BUFFERS, let's proceed on to the JOB HEADER. Each JOB HEADER holds the following information:
BUFFER number memory location content
0 $1021 - $1022 ID1, ID2
$1023 - $1024 track, sector
$1025 - $1026 checksum, OFF byte
$1027 - $1028 spare 1, spare 2
1 $1029 - $102A ID1, ID2
$102B - $102C track, sector
$102D - $102E checksum, OFF byte
$102F - $1030 spare 1, spare 2
2 $1031 - $1032 ID1, ID2
$1033 - $1034 track, sector
$1035 - $1036 checksum, OFF byte
$1037 - $1038 spare 1, spare 2
3 $1039 - $103A ID1, ID2
$103B - $103C track, sector
$103D - $103E checksum, OFF byte
$103F - $1040 spare 1, spare 2
4 $1041 - $1042 ID1, ID2
$1043 - $1044 track, sector
$1045 - $1046 checksum, OFF byte
$1047 - $1048 spare 1, spare 2
5 $1049 - $104A ID1, ID2
$104B - $104C track, sector
$104D - $104E checksum, OFF byte
$104F - $1050 spare 1, spare 2
6 $1051 - $1052 ID1, ID2
$1053 - $1054 track, sector
$1055 - $1056 checksum, OFF byte
$1057 - $1058 spare 1, spare 2
7 $1059 - $105A ID1, ID2
$105B - $105C track, sector
$105D - $105E checksum, OFF byte
$105F - $1060 spare 1, spare 2
8 $1061 - $1062 ID1, ID2
$1063 - $1064 track, sector
$1065 - $1066 checksum, OFF byte
$1067 - $1068 spare 1, spare 2
9 $1069 - $106A ID1, ID2
$106B - $106C track, sector
$106D - $106E checksum, OFF byte
$106F - $1070 spare 1, spare 2
10 $1071 - $1072 ID1, ID2
$1073 - $1074 track, sector
$1075 - $1076 checksum, OFF byte
$1077 - $1078 spare 1, spare 2
11 $1079 - $107A ID1, ID2
$107B - $107C track, sector
$107D - $107E checksum, OFF byte
$107F - $1080 spare 1, spare 2
12 $1081 - $1082 ID1, ID2
$1083 - $1084 track, sector
$1085 - $1086 checksum, OFF byte
$1087 - $1088 spare 1, spare 2
13 $1089 - $108A ID1, ID2
$108B - $108C track, sector
$108D - $108E checksum, OFF byte
$108F - $1090 spare 1, spare 2
14 $1091 - $1092 ID1, ID2
$1093 - $1094 track, sector
$1095 - $1096 checksum, OFF byte
$1097 - $1098 spare 1, spare 2
Once the machine code instructions (data) have been written to the desired buffer, we must now tell the FDC controller what action is to be taken. If we wish the FDC controller to execute our instructions, we must make sure of the following:
.all branch addresses must be set in accordance to the FDC buffers
example: $1100 A9 40 LDA #$40
$1102 85 03 STA $03
$1104 A5 40 LDA $40
$1106 4C 00 05 JMP $0500 (not:JMP $1100)
.HI byte of start address stored in JOB HEADER track byte
.LO byte of start address stored in JOB HEADER sector byte
It is easier to spot mistakes/bugs if you associate the JOB HEADER with its corresponding DATA BUFFER. Now that we have stored our data and set up the start address in the JOB HEADER table, we must now tell the FDC controller that there is a "JOB TO DO".
The JOB QUEUE
Now comes the DANGEROUS PART. Before going any further, I wish to stress the following point:
YOU ARE NOW CONTROLLING THE VERY HEART OF THE 4040 DUAL DRIVE
MAKE SURE TO CALCULATE AND VERIFY ALL YOUR INSTRUCTIONS, YOU
ARE BY-PASSING ALL THE DOS PROTECTION. ALL COMMAND REQUESTS
YOU HAVE INSTRUCTED WILL BE PERFORMED WITHOUT VERIFICATION OF
SYNTAX AND PHYSICAL POSSIBILITY.
Before continuing, re-read the above paragraph. You must realize that the FDC controller will listen to all your instructions. Should your instructions be harmfull to the physical parts of the 4040 dual drive, no preventive actions will be taken to stop them; unless they are implemented within your machine code instructions (data).
Let's continue. There are seven (7) pre-set operations within the FDC controller. These are:
JOB CODE (decimal) LABEL DESCRIPTION
$80 (128) READ Read track & sector specified by header
into data buffer
$90 (144) WRITE Write track & sector specified by header
from data buffer
$A0 (160) VERIFY Compare track & sector specified by
header with data buffer
$B0 (176) SEEK Find any header on track specified by
header, put in data buffer
$C0 (192) BUMP Track must be set to: 1, positions head
to track 1
$D0 (208) JUMP Jump to user ML CODE in data buffer
$E0 (224) EXECUTE Same as JUMP with head in position and
drive at speed
The JOB QUE begins at location $1003 and goes 14 bytes (ending at: $1011) for a total of 14 JOB QUEUES for 14 JOB HEADERS and 14 DATA BUFFERS. When the FDC controller has finished the requested job, bit 7 is masked off and the status is stored back into the JOB QUE where the command originated from. This status is used to generate the appropriate error message.
FDC CODE IEEE CODE DESCRIPTION
1 00 OK
2 20 HEADER BLOCK NOT FOUND
3 21 NO SYNC CHARACTER
4 22 DATA BLOCK NOT FOUND
5 23 CHECKSUM ERROR IN DATA BLOCK
6 24 BYTE DECODING ERROR
7 25 VERIFY ERROR
8 26 WRITE PROTECT SENSE ON
9 27 CHECKSUM ERROR IN HEADER BLOCK
A 28 LONG DATA BLOCK
B 29 DISK ID MISMATCH
To pass control over to the FDC Controller, you must place one of the JOB CODES in the JOB QUE corresponding to its JOB HEADER table. At this point, the FDC Controller will perform the desired action. When the requested function is completed, the FDC Controller will return the ERROR STATUS. This FDC CODE will be stored in the JOB QUE.
In order to check if the job requested is completed, simply read the value found in the JOB QUE. If it is above decimal value 128, then the job has not yet been completed. If it is below decimal value 128, then the job is completed and the value returned is the ERROR STATUS.
6.6 - TROUBLE SHOOTING (HARDWARE)
Over the years, it will become more and more difficult to find a COMMODORE service depot who will be capable of servicing the 4040 dual drive. Because of this, I have decided to add this section. Hopefully it can help the service technician in locating any problems.
Disk LED error diagnostics
Number of flashes Error Cause Component/location
1 Zero Page 6532/C1, E1
2 ROM H1
3 ROM L1
4 ROM J1
5 Zero Page 6530/K3
6504/H3
6 N/A
7 RAM 2114/D4, D5
8 RAM 2114/E4, E5
9 RAM 2144/F4, F5
10 ROM 6530/K3
6504/H3
Power supply
The power supply on the 4040 dual drive is composed of three (3) voltage regulators. These are:
VR1 & VR2: 12 volt regulators, one per drive
VR3 : 5 volt regulator for the rest of the unit
Service hints
Some other common problems are sometimes located on the ANALOG board. Below is compilation of the most common problems found on the 4040 dual drive.
Symptom Solution
1. Drive #0 has read errors. Adjust speed pot by use of:
a. "SPEED VARIATION" program
b. adjustment screw on small
block located on circuit
board behind drive chassis.
2. Drive #1 has read errors. Adjust speed pot by use of:
a. "SPEED VARIATION" program
b. adjustment screw on small
block located on circuit
board behind drive chassis.
3. Drive #1 loads and Drive #0 not Check transistors on analog:
loading. Q5, Q6, Q7, Q8.
4. Drive #0 loads and Drive #1 not Check transistors on analog:
loading. Q1, Q2, Q3, Q4.
5. Initializes by itself after warm-up. Check IC Chip #6504 (UH3).
6. Drive motor does not run. Check drive belt.
The following chart may be used as a specifications sheet.
HARDWARE MODEL:
Drives per unit : 2
Heads per drive : 1
FORMATTED STORAGE:
Capacity per unit : 340 KB
Maximum SEQuential files per drive : 168 KB
Maximum RELative files per drive : 168 KB
Disk system buffer : 4 KB
DISK FORMATS:
Tracks : 35
Sectors per track : 17-21
Bytes per sector : 256
Blocks free per unit : 1328
TRANSFER RATES (BYTES PER SECOND):
Internal to unit : 40 KB
IEEE-488 bus : 1.2 KB
ACCESS TIMES (MILLI-SECONDS):
Track to track : 30
Average track : 360
Average latency : 100
Rpm : 300
PHYSICAL DIMENSIONS:
Height (inches) : 7.0
Width (inches) : 15.0
Depth (inches) : 13.75
Weight (pounds) : 28
ELECTRICAL:
Power (watts) : 50
Voltage : 110-120 VAC.
Frequency : 60 Hz
Chapter 7 - IEEE software controller (MOS 6502)
4040 IEEE controller RAM usage
ZERO page ($0000 - $002C)
CONTENT AT
LOCATION POWER UP LABEL DESCRIPTION
----------------------------------------------------------------------------
$0000 EA USRJMP User jump table LO byte pointer
$0001 FF User jump table HI byte pointer
$0002 00 BMPNT Bit map pointer
$0003 00 Bit map pointer
$0004 04 TEMP: T0 Temp work space - CMD jump table
$0005 00 T1
$0006 00 T2
$0007 09 T3
$0008 00 T4
$0009 00
$000A 00 IP Indirect pointer variable
$000B 40
$000C 28 LSNADR Listen address: DEVICE + #$20
$000D 48 TLKADR Talker address: DEVICE + #$40
$000E 00 LSNACT Active listener flag
$000F 00 TLKACT Active talker flag
$0010 00 ADRSED Addressed flag
$0011 11 PRGTRK Last program accessed
$0012 00 DRVNUM Current drive number
$0013 00 TRACK Current track
$0014 00 SECTOR Current sector
$0015 06 LINDX Logical index
$0016 0F SA Current secondary address
$0017 6F ORGSA Original secondary address
$0018 3F DATA Temporary data byte
$0019 00 TEMP: R0 Temp work area
$001A 00 R1
$001B 00 R2
$001C 00 R3
$001D 00 R4
$001E 00 RESULT Result of multiply/divide
$001F 00
$0020 00
$0021 00
$0022 00 ACCUM Remainder of multiply/divide
$0023 00
$0024 00
$0025 00
$0026 00
$0027 05 DIRBUF Directory buffer LO byte pointer
$0028 43 Directory buffer HI byte pointer
$0029 00 BUFTAB: 0 Buffer # 0 LO byte pointer
$002A 11 Buffer # 0 HI byte pointer
$002B 00 BUFTAB: 1 Buffer # 1 LO byte pointer
$002C 12 Buffer # 1 HI byte pointer
4040 IEEE controller RAM usage (continued)
ZERO page ($002D - $0059)
CONTENT AT
LOCATION POWER UP LABEL DESCRIPTION
----------------------------------------------------------------------------
$002D 00 BUFTAB: 2 Buffer # 2 LO byte pointer
$002E 13 Buffer # 2 HI byte pointer
$002F 00 BUFTAB: 3 Buffer # 3 LO byte pointer
$0030 20 Buffer # 3 HI byte pointer
$0031 00 BUFTAB: 4 Buffer # 4 LO byte pointer
$0032 21 Buffer # 4 HI byte pointer
$0033 00 BUFTAB: 5 Buffer # 5 LO byte pointer
$0034 22 Buffer # 5 HI byte pointer
$0035 00 BUFTAB: 6 Buffer # 6 LO byte pointer
$0036 23 Buffer # 6 HI byte pointer
$0037 00 BUFTAB: 7 Buffer # 7 LO byte pointer
$0038 30 Buffer # 7 HI byte pointer
$0039 00 BUFTAB: 8 Buffer # 8 LO byte pointer
$003A 31 Buffer # 8 HI byte pointer
$003B 00 BUFTAB: 9 Buffer # 9 LO byte pointer
$003C 31 Buffer # 9 HI byte pointer
$003D 00 BUFTAB: 10 Buffer #10 LO byte pointer
$003E 31 Buffer #10 HI byte pointer
$003F 00 BUFTAB: 11 Buffer #11 LO byte pointer
$0040 40 Buffer #11 HI byte pointer
$0041 00 BAM drive # 0 LO byte pointer
$0042 41 BAM drive # 0 HI byte pointer
$0043 00 BAM drive # 1 LO byte pointer
$0044 42 BAM drive # 1 HI byte pointer
$0045 00 Command buffer LO byte pointer
$0046 43 Command buffer HI byte pointer
$0047 DD Error output buffer LO byte pointer
$0048 43 Error output buffer HI byte pointer
$0049 FF BUF0 Inactive flags for buffer (bit 7=1)
$004A FF
$004B FF
$004C FF
$004D FF
$004E FF
$004F 0E
$0050 0F
$0051 FF BUF1 Inactive flags for buffer (bit 7=1)
$0052 FF
$0053 FF
$0054 FF
$0055 FF
$0056 FF
$0057 FF
$0058 FF
$0059 00 NBKL Number of blocks low
4040 IEEE controller RAM usage (continued)
ZERO page ($005A - $0086)
CONTENT AT
LOCATION POWER UP LABEL DESCRIPTION
----------------------------------------------------------------------------
$005A 00 RECL Low record number to find REL file
$005B 00
$005C 00
$005D 00
$005E 00
$005F 00
$0060 00
$0061 00 NBKH Number of blocks high
$0062 00 RECH High record number to find REL file
$0063 00
$0064 00
$0065 00
$0066 00
$0067 00
$0068 00
$0069 00 NR Next record table
$006A 00
$006B 00
$006C 00
$006D 00 TRACK Current track
$006E 00
$006F 06 LINDX Logical index
$0070 00
$0071 00 RS Relative record size table
$0072 00
$0073 00
$0074 00
$0075 00
$0076 00
$0077 00
$0078 00
$0079 FF SS Side sector table
$007A FF
$007B FF
$007C FF
$007D FF
$007E FF
$007F FF
$0080 FF
$0081 00 F1PTR File stream 1 pointer
$0082 00 RECPTR 1st byte wanted from REL file
$0083 00 SSNUM Side sector number of REL record
$0084 00 SSIND Index into side sector
$0085 00 RELPTR Pointer to 1st byte wanted in REL
$0086 00 FILENT Directory entry (bit: IIIS SSSS)
4040 IEEE controller RAM usage (continued)
ZERO page ($0087 - $00A5)
CONTENT AT
LOCATION POWER UP LABEL DESCRIPTION
----------------------------------------------------------------------------
$0087 00
$0088 00
$0089 00
$008A 00
$008B 00 FILDAT File data (bit 7=1: search both
drives)
$008C 00
$008D 00
$008E 00
$008F 00
$0090 00 FILTYP Channel file type (bit 7=1: search
both drives)
SEQ = type 1
PRG = type 2
USR = type 3
REL = type 4
direct = type 7
$0091 00
$0092 00
$0093 00
$0094 00
$0095 00
$0096 00
$0097 00 CHNDRY Channel status
bit: 7=1 (talk)
3=0 (send EOI, talker only)
0=1 (listen)
$0098 00
$0099 00
$009A 00
$009B 00
$009C 00
$009D 00
$009E 01
$009F 88
$00A0 20 EOIFLG Temporary EOI
$00A1 00 JOBNUM Current job number
$00A2 FF LINTAB Logical index table
bit 7&6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
$00A3 FF
$00A4 FF
$00A5 FF
4040 IEEE controller RAM usage (continued)
ZERO page ($00A6 - $00D3)
CONTENT AT
LOCATION POWER UP LABEL DESCRIPTION
----------------------------------------------------------------------------
$00A6 FF
$00A7 FF
$00A8 FF
$00A9 FF
$00AA FF
$00AB FF
$00AC FF
$00AD FF
$00AE FF
$00AF FF
$00B0 FF
$00B1 86
$00B2 07
$00B3 FF
$00B4 FF
$00B5 00 CHNDAT Channel data byte
$00B6 00
$00B7 00
$00B8 00
$00B9 00
$00BA 00
$00BB 00
$00BC 30
$00BD 00 LSTCHR Channel last character pointer
$00BE 00
$00BF 00
$00C0 00
$00C1 00
$00C2 00
$00C3 00
$00C4 E7
$00C5 00 TYPE Active file type
$00C6 00 NOTUSED $00C6 - $00FF not used by DOS
$00C7 00
$00C8 00
$00C9 00
$00CA 00
$00CB 00
$00CD 00
$00CE 00
$00CF 00
$00D0 00
$00D1 00
$00D2 00
$00D3 00
4040 IEEE controller RAM usage (continued)
ZERO page ($00D4 - $00FF)
CONTENT AT
LOCATION POWER UP LABEL DESCRIPTION
----------------------------------------------------------------------------
$00D4 00
$00D5 00
$00D6 00
$00D7 00
$00D8 00
$00DA 00
$00DB 00
$00DC 00
$00DD 00
$00DE 00
$00DF 00
$00F0 00
$00F1 00
$00F2 00
$00F3 00
$00F4 00
$00F5 00
$00F6 C8
$00F7 B9
$00F8 C8
$00F9 D9
$00FA 0D
$00FB DA
$00FC 6D
$00FD DB
$00FE B7
$00FF D4
4040 IEEE controller RAM usage
RAM memory ($0100 - $1017)
LOCATION LABEL DESCRIPTION
----------------------------------------------------------------------------
$0100 - $01FF The stack
$0200 IEEEDI IEEE data in
$0201 PADDI IEEE data in direction
$0202 IEEED0 IEEE data out
$0203 PADDI IEEE data out direction
$0204
$0205
$0206
$0207
$0208 - $027F
$0280 PAD2 IEEE control port: **
$0281 PADD2 **
$0282 PBD2 **
$0283 PBDD2 **
$0284 ATNND ** ATN is IRQ causing ??
$0285 ATNPD **
$0286 ATNNE **
$0287 ATNPE **
$0288 - $0FFF Unconnected
$1000 ID Interrupt delay (** start of shared memory **)
$1001 Motor acceleration delay
$1002 Motor cutoff time
$1003 JOBS que Buffer # 0
$1004 Buffer # 1
$1005 Buffer # 2
$1006 Buffer # 3
$1007 Buffer # 4
$1008 Buffer # 5
$1009 Buffer # 6
$100A Buffer # 7
$100B Buffer # 8
$100C Buffer # 9
$100D Buffer #10
$100E Buffer #11
$100F Buffer #12
$1010 Buffer #13
$1011 Buffer #14
$1012 TRKS Job's track number
$1013
$1014
$1015
$1016
$1017
4040 IEEE controller RAM usage (continued)
RAM memory ($1018 - $1074)
LOCATION LABEL DESCRIPTION
----------------------------------------------------------------------------
$1018
$1019
$1020
$1021 - $1022 JOBHDR0 Buffer # 0: ID1 , ID2
$1023 - $1024 track , sector
$1025 - $1026 checksum, off
$1027 - $1028 spare1 , spare2
$1029 - $102A JOBHDR1 Buffer # 1: ID1 , ID2
$102B - $102C track , sector
$102D - $102E checksum, off
$102F - $1030 spare1 , spare2
$1031 - $1032 JOBHDR2 Buffer # 2: ID1 , ID2
$1033 - $1034 track , sector
$1035 - $1036 checksum, off
$1037 - $1038 spare1 , spare2
$1039 - $103A JOBHDR3 Buffer # 3: ID1 , ID2
$103B - $103C track , sector
$103D - $103E checksum, off
$103F - $1040 spare1 , spare2
$1041 - $1042 JOBHDR4 Buffer # 4: ID1 , ID2
$1043 - $1044 track , sector
$1045 - $1046 checksum, off
$1047 - $1048 spare1 , spare2
$1049 - $104A JOBHDR5 Buffer # 5: ID1 , ID2
$104B - $104C track , sector
$104D - $104E checksum, off
$104F - $1050 spare1 , spare2
$1051 - $1052 JOBHDR6 Buffer # 6: ID1 , ID2
$1053 - $1054 track , sector
$1055 - $1056 checksum, off
$1057 - $1058 spare1 , spare2
$1059 - $105A JOBHDR7 Buffer # 7: ID1 , ID2
$105B - $105C track , sector
$105D - $105E checksum, off
$105F - $1060 spare1 , spare2
$1061 - $1062 JOBHDR8 Buffer # 8: ID1 , ID2
$1063 - $1064 track , sector
$1065 - $1066 checksum, off
$1067 - $1068 spare1 , spare2
$1069 - $106A JOBHDR9 Buffer # 9: ID1 , ID2
$106B - $106C track , sector
$106D - $106E checksum, off
$106F - $1070 spare1 , spare2
$1071 - $1072 JOBHDR10 Buffer #10: ID1 , ID2
$1073 - $1074 track , sector
4040 IEEE controller RAM usage (continued)
RAM memory ($1075 - $31FF)
LOCATION LABEL DESCRIPTION
----------------------------------------------------------------------------
$1075 - $1076 checksum, off
$1077 - $1078 spare1 , spare2
$1079 - $107A JOBHDR11 Buffer #11: ID1 , ID2
$107B - $107C track , sector
$107D - $107E checksum, off
$107F - $1080 spare1 , spare2
$1081 - $1082 JOBHDR12 Buffer #12: ID1 , ID2
$1083 - $1084 track , sector
$1085 - $1086 checksum, off
$1087 - $1088 spare1 , spare2
$1089 - $108A JOBHDR13 Buffer #13: ID1 , ID2
$108B - $108C track , sector
$108D - $108E checksum, off
$108F - $1090 spare1 , spare2
$1091 - $1092 JOBHDR14 Buffer #14: ID1 , ID2
$1093 - $1094 track , sector
$1095 - $1096 checksum, off
$1097 - $1098 spare1 , spare2
$1099 NUMSEC Number of sectors per track group
$109A
$109B
$109C
$109D GAP1 Gap spacing one (default: #$09)
$109E GAP2 Gap spacing two (default: #$02)
$109F VERNUM Dos version number (default: #$41)
$10A0 ACTJOB Controller's active job
$10A1 - $10EF Not used
$10F0 - $10F1 VNMI Indirect pointer for NMI vector
$10F2 NMIFLG NMI in progress flag
$10F3 AUTOFG Automatic drive initialization flag
$10F4 - $10FF Unused RAM
$1100 - $11FF BUF0 Data buffer # 0
$1200 - $12FF BUF1 Data buffer # 1
$1300 - $13FF BUF2 Data buffer # 2
$1400 - $1CFF Unconnected
$1D00 - $1FFF FBUF Format download area
$2000 - $20FF BUF3 Data buffer # 3
$2100 - $21FF BUF4 Data buffer # 4
$2200 - $22FF BUF5 Data buffer # 5
$2300 - $23FF BUF6 Data buffer # 6
$2400 - $2FFF Unconnected
$3000 - $30FF BUF7 Data buffer # 7
$3100 - $31FF BUF8 Data buffer # 8
4040 IEEE controller RAM usage (continued)
RAM memory ($3200 - $437F)
LOCATION LABEL DESCRIPTION
----------------------------------------------------------------------------
$3200 - $32FF BUF9 Data buffer # 9
$3300 - $33FF BUF10 Data buffer #10
$3400 - $3FFF Unconnected
$4000 - $40FF BUF11 Data buffer #11
$4100 - $41B3 BAM0 BAM drive zero
$41B4 - $41FF NAMBUF Directory buffer
$4200 - $42B3 BAM1 BAM drive one
$42B4 - $42FF Not used
$4300 - $4339 CMDBUF Command buffer
$433A STRSIZ String size in command buffer
$433B TEMPSA Temporary secondary address
$433C CMD Temporary job command
$433D LSTSEC Last sector
$433E - $433F BUFUSE Available buffers (bit = 1 if used buffer)
$4340 - $4341 DSKID Current disk id - drive 0
$4342 - $4343 Current disk id - drive 1
$4344 SECINC Sector increment for sequential files
$4345 ENTFND Directory entry found flag
$4346 DIRLST Directory listing flag
$4347 CMDWAT Command waiting flag
$4348 LINUSE Available logical index (bit 1: used = 1)
( 6: command channel)
( 7: error channel)
$4349 LBUSED Last buffer used
$434A ERBLKS Number of blocks before abort
$434B REC Record size
$434C TRKSS Track of side sector
$434D SECSS Sector of side sector
$434E - $435B LSTJOB Last job entered in job que
$435C REVCNT Error recovery count (default: #$0A)
$435D - $436A ERRCNT Error count for job que
$436B - $4372 DIRENT Directory entry associated with channel
$4373 ERWORD Error word for recovery
$4374 PRGSEC Last program sector
$4375 WLINDX Write logical index
$4376 RLINDX Read logical index
$4377 NBTEMP Number of blocks temporary
$4378
$4379 CMDSIZ Length of command string + 1
$437A CMDNUM Command number
$437B CHAR Character under parser
$437C LIMIT Pointer limit in compare
$437D F1CNT File stream 1 count
$437E F2CNT File stream 2 count
$437F F3PTR File stream 3 count
4040 IEEE controller RAM usage (continued)
RAM memory ($4380 - $CFFF)
LOCATION LABEL DESCRIPTION
----------------------------------------------------------------------------
$4380 - $4385 FILTBL Table of filename positions in CMDBUF
$4386 - $438A FILTRK Track of 1st block during search (bit 7=1 to
indicated that
pattern match)
$438B - $438F FILSEC Sector of 1st block during search
$4390 PATFLG Pattern presence flag
$4391 IMAGE File stream image
$4392 DRVCNT Number of drive searches
$4393 DRVFLG Drive search flag
$4394 LSTDRV Last drive without error
$4395 FOUND Found flag in directory searches
$4396 DIRSEC Directory sector
$4397 DELSEC Sector of 1st available entry
$4398 DELIND Index of 1st available entry
$4399 LSTBUF Last block (equal to 0)
$439A INDEX Current index in buffer
$439B FILCNT Counter, file entries
$439C TYPFLG Match by type flag
$439D MODE Active file mode (Read/Write)
$439E JOBRTN Job return flag
$439F - $43DB Unused
$43DC - $43FF ERRBUF Error message buffer
$4400 - $CFFF Unconnected
4040 IEEE controller MAP
Code from $D000 - $D730
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$D000 Format code
$D2A0 Checksum byte for $D000
$D2A1 Command search table: 'ivdmbupcrsn'
$D2AC Command jump table (LO bytes)
$D2B7 Command jump table (HI bytes)
$D2C2 Structure images for commands
$D2C7 Track group table
$D2CB Mode table
$D2CF File type table
$D2D4 1st character in name of file type
$D2D9 2nd character in name of file type
$D2DE 3rd character in name of file type
$D2E3 Error flag variables
$D2E8 BAM buffer pointer (HI bytes)
$D2EA Sectors per track table (4040)
$D2EE Disk & sector definition bytes (4040)
$D2F1 Sectors per track table (3040)
$D2F5 Disk & sector definition bytes (3040)
$D2F8 Controller: jump to wait loop
$D301 Error display routine
$D32B Initialize disk for: Power Up Diagnostics
$D348 Fill ZERO PAGE ascending pattern
$D34E Test ZERO PAGE
$D362 Test three 64K-bit roms
$D3A0 Test all common ram pages $2000-$5000
$D3DC Diagnostics ok so far: test device number
$D3F4 Initialize buffer pointer table
$D46B Set up sector/track table depending on controller used
$D47A Controller error
$D47F Set up sectors/track, GAP1, dos version, format version
$D48D Set up power on message "CBM DOS V2.1"
$D492 Bump heads to track 1
$D4A6 Idle loop: does housekeeping while waiting for job
$D50A ATN irq process: IRQ on ATN, listen to PET, clear stack
$D549 Decide: secondary address, talk, listen, other
$D5CF Set listen routine: main routine
$D65C Listen routine
$D65F Set talk routine: main routine
$D66B From TALK: no talk = rts
$D69B Talk routine
$D6AF Return next available track and sector
$D6DE Disk full error
$D6E3 Find an available track
$D6F5 Find next optimum sector on track
$D72B Directory error
$D730 Test for free sectors, else indicate track as used
Code from $D73E - $D9C9
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$D73E Test lower & upper track ranges for free sectors
$D75E Disk full error
$D763 Find sector
$D778 Directory error
$D77D Mark current track as full
$D78C Read sector map from BAM
$D7B4 Test for available sectors on current track
$D7CA Directory error
$D7D2 Number of sectors for specific track table
$D7DE Sectors per track group table
$D7E2 OK error message
$D7E6 READ error message
$D7F1 FILE TOO LARGE error message
$D7FD RECORD NOT PRESENT error message
$D808 OVERFLOW IN RECORD error message
$D815 WRITE error message
$D819 WRITE PROTECT ON error message
$D826 DISK ID MISMATCH error message
$D82C SYNTAX error message
$D838 WRITE FILE OPEN error message
$D83C FILE EXISTS error message
$D845 FILE TYPE MISMATCH error message
$D84D NO BLOCK error message
$D856 ILLEGAL TRACK & SECTOR error message
$D86F FILE NOT OPEN error message
$D873 FILE NOT FOUND error message
$D877 FILE'S SCRATCHED error message
$D884 NO CHANNEL error message
$D88F DIRECTORY error message
$D894 DISK FULL error message
$D89B DOS MISMATCH error message
$D8A6 Token word: ERROR
$D8AC Token word: WRITE
$D8B2 Token word: FILE
$D8B7 Token word: OPEN
$D8BC Token word: MISMATCH
$D8C5 Token word: NOT
$D8C9 Token word: FOUND
$D8CF Token word: DISK
$D8D4 Token word: RECORD
$D8DB Transfer error message to error buffer
$D8E6 Test begin/end of error message
$D907 Transfer TOKEN to error message buffer
$D91C Controller error entry point
$D952 Process error
$D956 Clear command buffer, set LED's
$D970 Talker error recovery
$D990 Listener error recovery
$D9A8 Convert HEX to BCD
$D9B7 Convert BCD to ASCII
$D9C9 Set for OK error message
Code from $D9D4 - $E254
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$D9D4 Set up error message in error buffer
$DA13 Mark a sector as free on a track in BAM
$DA2C Turn on activity LED specified by drive
$DA42 Turn off error LED
$DA4B Directory loading function, get buffer and start it
$DACF Build last line of directory
$DB03 Transmit directory line to current buffer
$DB11 Get byte from directory
$DB2E Calculate number of free blocks
$DB55 Parse and execute command string in command buffer
$DB99 Successful command termination
$DBA1 Clear command buffer
$DBB8 Clear command input buffer
$DBC3 Command level error processing
$DBCE Simple parser routine
$DBE0 Parse colon
$DBE9 Set up command structure image and file stream pointer
$DC63 Look for special characters
$DCB0 Set all flags and look at command string
$DCD9 Command reset: clear variables, tables
$DD0A Set 1st drive and table pointers
$DD1B Set drive number
$DD34 Get drive number from command string
$DD5E Set drive from any configuration
$DD86 Toggle drive number
$DD8F Set pointer to one file stream and check type
$DDB5 Test drive number validity
$DDC2 Auto initialization routine
$DE07 Optimum search for lookup and find file
$DE61 Search table
$DE70 Lookup files in stream and fill tables with information
$DE83 Toggle to lookup other drive
$DEAD Find next file name matching any file in stream
$DED7 Find directory entry and file type
$DEFA Compare file names in stream table with the disk directory
$DFAF Check table of unfound files
$DFD0 Search directory: returns with valid entry
$E039 Continue file entry search
$E05F Transfer filename from command buffer
$E079 Transfer command buffer to other buffer
$E097 Find limit of string in command buffer
$E0BF Get file entry from directory
$E0CF Get directory entry
$E19F Clear name buffer
$E1AA New directory listing
$E1F0 Display BLOCKS FREE. message
$E201 BLOCKS FREE. message
$E20D Command: NEW (format diskette)
$E245 Initialize drive with version number
$E254 Initialize track 18, 0 and track 18, 1
Code from $E2B7 - $E8F7
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$E2B7 Command: SCRATCH (erase files)
$E313 Delete file by links
$E33B Delete directory entry
$E346 Command: DUPLICATE (backup diskette)
$E391 Copy blocks from source to destination drive
$E3A9 Copy entire track from source to destination
$E3B7 Transfer HEADER blocks to destination drive
$E3D2 READ 10 sectors from source drive
$E3F6 WRITE 10 sectors to destination drive
$E416 Transfer format code to buffers 0,1 & 2, start formatting
$E44A Command: COPY (transfer file(s) to other or same disk)
$E46C Normal parse
$E48F Indicate invalid command structure
$E494 Test if copy type is normal
$E49E Verify drive numbers for disk to disk copy
$E4C5 Copy disk to disk routines
$E4EE Pull needed variables from stack
$E519 Push needed variables onto stack
$E557 Transfer name from directory buffer to command buffer
$E567 Set up drive number and file information
$E587 Command: CONCAT (copy file(s) to one file)
$E5D3 Check files for existence
$E617 Open and set up internal read file
$E657 Get byte from internal read channel
$E675 Command: RENAME (give new name to a current file name)
$E6BC Check if input file is on hand
$E6D9 Check file for existence
$E6EC Command: VALIDATE (create new BAM on disk)
$E712 Record blocks in file onto BAM
$E738 Verify if directory entry found is properly closed
$E744 Record file entry links in new BAM
$E76C Create new BAM for diskette
$E7A7 Checksum byte for $E000
$E7A8 Command: MEMORY (direct access to DOS)
$E7CD Command: MEMORY-READ (direct read from DOS)
$E7F7 Indicate invalid command structure
$E7FC Command: MEMORY-WRITE (direct write to DOS)
$E808 User access commands
$E81E Execute user jump code
$E830 Open direct access buffer from OPEN "#"
$E83E Indicate invalid channel structure
$E843 Validate and set up requested buffer
$E8AF Search for second character (-) in command string for
BLOCK commands
$E8BA Indicate invalid command structure
$E8BF Indicate invalid command structure
$E8C4 Decide which command is being requested
$E8F1 BLOCK command summary
$E8F7 BLOCK - command jump table
Code from $E903 - $ECDF
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$E903 Get command parameters and test validity
$E935 Convert ASCII to HEX and store conversion result
$E95E Convert digit to binary by use of decimal table
$E986 Decimal table
$E989 Command: BLOCK - FREE
$E992 BLOCK - ALLOCATE command
$E9C3 No block available error
$E9CA Test for block availability
$E9D5 Test BLOCK - READ parameters and read sector in buffer
$E9DB Get a byte from buffer
$E9E1 Read sector from disk to buffer, initialize pointers
$E9F5 Command: BLOCK - READ
$E9FE Command: U1: (Block - read)
$EA12 Command: BLOCK - WRITE
$EA38 Command: U2: (Block - write)
$EA44 Command: BLOCK - EXECUTE
$EA58 Execute machine code at assigned jump address
$EA5B Command: BLOCK - POINTER
$EA70 Test for allocated buffer and open channel
$EA90 Test block operation parameters
$EAAE Find relative file
$EACC Calculate record's location: TOTAL=RCRD# x SIZE + PNTR
$EB0E Divide by #$FE (decimal 254)
$EB11 Divide by #$78 (decimal 120)
$EB13 Main division routine
$EB79 Clear RESULT memory area
$EB82 Multiply ACCUMULATION registers by 4
$EB85 Multiply ACCUMULATION registers by 2
$EB8D Add ACCUMULATION register to RESULT registers
$EB9A Mark track, sector, BAM pointer as used
$EBAF Test if requested block available
$EBC9 Bit mask table for BAM calculations
$EBD1 Double buffer: switch the active and inactive buffers
$EBE6 Set internal write channel and test if command channel
$EBF8 Main routine to write to a channel
$EC0A Test if file type USR, if not write to REL file
$EC0F Write to USR file, get next data byte
$EC19 Set for maximum channel, test buffer pointer
$EC2E Set command waiting flag
$EC32 Test if job done. If not done continue
$EC5B Retry current job .Y amount of times
$EC76 Job done properly, restore .Y register to original value
$EC7A Set last job executed back up for a retry
$EC82 Test if job completed, clear job present flag when done
$EC8F Set track, sector, ID for current buffer
$ECB1 Test for valid buffer
$ECBD Store byte in assigned buffer position
$ECC5 Command: INITIALIZE (read BAM)
$ECDF Set up job queue and locate track 18, sector 0
Code from $ECFA - $F07C
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$ECFA Read BAM from diskette in current drive
$ED1D Start double buffering, use track and sector to start
$ED35 Begin double buffering
$ED41 Set for READ job
$ED45 Set for WRITE job
$ED47 Perform requested job
$ED69 Find internal read channel
$ED84 Find internal write channel
$EDA1 Get current file type
$EDAB Set buffer pointers
$EDB3 Read byte from active buffer
$EDD2 Get byte from file and read next block if needed
$EDE6 Read next block of file
$EE0E Set last character position for last byte of file
$EE19 Write a byte to channel and write buffer out when full
$EE42 Increment pointer of active buffer
$EE4F Set drive number indicated by last job in active buffer
$EE5B Set for opening of new write channel
$EE5E Set for opening of new read channel
$EE5F Perform opening of desired channel
$EE87 Indicate channel unavailability
$EE8F De-allocate additional buffer
$EE9F Test current secondary address for command channel
$EEA6 Free read/write channels
$EECA Release buffers and corresponding channel
$EEFE Get free buffer number
$EF29 Locate buffer to steal
$EF34 Free buffer index
$EF48 Clear all channels except COMMAND channel
$EF54 Close all channels except COMMAND channel
$EF79 Find a free logical index to use
$EF8B Mark free logical index as used in table
$EF95 Get a byte from a channel
$EFA3 Read a byte over channel from any file type
$EFAD Read a byte from file
$EFC7 EOI received, set new channel status
$EFCC Test if LOAD command received
$EFD0 Test file type for random access
$EFD7 Read byte from RELative file
$EFF9 Read byte from SEQuential file
$F001 Test if "DIRECTORY" issued read
$F00C Get character from error channel
$F02B Set bytes from error buffer to be output
$F032 Set pointer for error message buffer
$F03B Initialize error message channel
$F044 Read next buffer of a file, follow links
$F057 Entrance point for direct BLOCK - READ
$F05B Entrance point for direct BLOCK - WRITE
$F06C Open internal read channel (SA = 17)
$F07C Open internal write channel (SA = 18)
Code from $F083 - $F655
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$F083 Allocate next directory block on track 18 and mark BAM
$F0C1 Set new pointer position
$F0D3 Free internal READ and WRITE channels
$F0E1 Read active buffer pointer, set directory buffer
$F0EF Direct byte read
$F0FF HI bytes indexes for buffers
$F10E Use last job for drive number and set job command
$F116 Set job up and check track and sector
$F155 Indicate track or sector unavailability
$F15D Set track and sector from values in JOB HEADER memory
$F16E Check track and sector validity
$F180 Indicate invalid format version
$F188 Determine error count and activate job
$F19D Set job and test if completed
$F1A9 Add file to directory
$F1EA Find deleted entry in directory
$F20E Write RELative file
$F279 Open channel from IEEE, parse input string
$F2B5 Test if LOAD directory command
$F2C1 Open directory as a SEQuential file
$F2D6 Test if direct access command
$F2DD Initialize drive zero
$F2EC Parse command string
$F2FD Determine mode and file type for LOAD & SAVE
$F36A Handle relative file
$F395 Test if file exists, if not open write channel
$F39F Check if file replacement command
$F3AE Indicate invalid filename structure
$F3B3 Command: REPLACE (overwrite file)
$F3F9 Test if file exists in directory
$F405 Test if MODIFY (#$03) mode requested
$F417 Verify the requested directory entry file type
$F425 Test if APPEND (#$02) mode requested
$F45B Open a file for reading
$F49B Open a file for writing
$F4BF Check mode and file type
$F4DF Append information to end of specified file
$F509 Transmit directory ($) to computer
$F536 Load directory from one drive
$F55C Search by name on both drives
$F58D Close file associated with secondary address
$F59C Close channels associated with LOAD/SAVE
$F5AC Close all files
$F5BA Close specified secondary address channel
$F5C3 Locate and close specific file type associated with
secondary address
$F5E3 Close a RELative file
$F612 Close a write channel
$F655 Write out BAM to the last active drive
Code from $F671 - $FA94
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$F671 Verify that the BAM count matches the bits
$F694 Write new BAM to diskette
$F6A4 Directory close on open write file
$F6E1 REPLACE current file data with new file data
$F722 Set "FILE CLOSED" flag, write new block count
$F747 Open internal read channel with 2 buffers
$F780 Initialize all pointers including REL file pointers
$F7A8 Set up SEQuential file
$F7B4 Initialize variables for open channel
$F7E6 Open internal write channel with 2 buffers
$F808 Test for available side sector buffer
$F821 Set up and write out side sector and data block
$F898 Put byte into side sector
$F8A0 Set/Clear file type flag
$F8B1 Test file type flag status
$F8B6 Test if write job
$F8C2 Test for active files
$F8D4 Test if directory entry matches secondary address entry
$F8F4 Write out buffer if no longer current
$F900 Put track and sector into buffer
$F90F Get track and sector from buffer
$F91C Set track link to #$00 and sector link to last character
in current buffer
$F92E Set up pointer to active buffer
$F93E Read track and sector values from HEADER
$F955 Job que: WRITE a buffer
$F95C Job que: READ a buffer
$F963 Job que: WRITE
$F96A Job que: READ
$F971 Job que: WRITE side sector
$F978 Job que: READ side sector
$F99A Set track and sector from link in buffer
$F9AA Transfer bytes from one buffer to other
$F9C6 Clear requested buffer
$F9D7 Set side sector pointer
$F9E1 Use side sector pointer to set directory buffer pointer
$F9EE Set current directory buffer and buffer table
$F9FD Test if side sector and index are within allowed range
$FA17 Position directory buffer and buffer table
$FA20 Indirect block read
$FA26 Indirect block write
$FA2A Perform block read/write
$FA4A Get side sector pointers
$FA51 Calculate side sectors
$FA6B Test side sector number and side sector index for
residence and range
$FA7C Indicate side sector out of range
$FA80 Test side sector status
$FA90 Indicate side sector out of range
$FA94 Indicate side sector not resident
Code from $FA98 - $FEBE
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$FA98 Get active buffer number
$FAA3 Get active buffer number and set last buffer used
$FABC Mark end of record then move on to next record
$FB16 Store current pointer value in buffer and set new
pointer value
$FB20 Set pointer to last record
$FB28 Set up next record in buffer
$FB49 Test if last data block in file
$FB68 Write relative data into buffer
$FB8F Test if end of buffer. If not, set up next record in
buffer
$FB97 Write record to data buffer
$FBA8 Test if overflow error and set up next record
$FBC2 Test for last record flag and EOI status
$FBCB Add new relative record to file and write data byte
$FBDC Fill balance of relative record with #$00
$FBEE Set flag to indicate that buffer needs to be updated on
disk
$FBF9 Clear flag indicating that buffer needs to be updated on
disk
$FC04 Get byte from relative record
$FC36 Set channel status to EOI (End Or Identify)
$FC3C Read last byte in record and proceed to next record in
file
$FC47 Send end of record marker, indicate RECORD NOT PRESENT
$FC56 Set pointer to last character in record
$FC84 Test for last non-zero character in buffer
$FC98 Find last non-zero character in record
$FCAE Indicate last non-zero character as present
$FCB1 Position side sector and buffer table to end of last
record
$FCE8 Indicate illegal track or sector
$FCED Command: POSITION (move to new location in relative file)
$FD4B Move to desired record and test if request valid
$FD58 Indicate desired record requested valid
$FD5B Position relative data block into active buffer and next
block into inactive buffer
$FD6F Position pointer to desired record, move to next record if
necessary
$FD7D Position proper data blocks into buffers
$FDAC Set current track and sector and begin double buffering
$FDBD Check if required block is in buffer
$FDC9 Test if desired sector has been reached
$FDCF Set null records in active buffer for extension
$FDF1 Add next record to record size
$FE05 Adjust pointer to compensate for link
$FE09 Add blocks to relative file
$FEB2 Mark current block as last one in file
$FEBE Chain through file and set side sectors
Code from $FF2E - $FFFF
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$FF2E Indicate record not present
$FF38 Generate new side sector and fix previous side sector
to reflect new side sector
$FF96 Revise previous side sector to reflect newly added side
sector
$FFBB Write side sector and update next one if needed
$FFE6 Versatile non maskable interrupt
$FFE9 Checksum byte for $F000
$FFEA .word BLKRD : block-read
$FFEC .word BLKWRT: block-write
$FFEE User command to buffer #02
$FFFA .word NMI: Non-maskable interrupt
$FFFC .word DISKINIT: power-up
$FFFE .word ATN/IRQ process
4040 IEEE disk ROM map
******************************* Format code. See CHAPTER 8 for detailed
dissassembly
D000 A5 1A LDA $1A
D002 10 2F BPL $D033
D004 78 SEI
D005 A9 C1 LDA #$C1
D007 95 03 STA $03,X
D009 A9 0F LDA #$0F
D00B 3D 9A 07 AND $079A,X
D00E 05 40 ORA $40
D010 85 40 STA $40
D012 A9 8C LDA #$8C
D014 95 05 STA $05,X
D016 58 CLI
D017 B5 05 LDA $05,X
D019 D0 FC BNE $D017
D01B 98 TYA
D01C 0A ASL
D01D 0A ASL
D01E 0A ASL
D01F 18 CLC
D020 69 21 ADC #$21
D022 85 18 STA $18
D024 A0 00 LDY #$00
D026 84 1D STY $1D
D028 C8 INY
D029 84 1A STY $1A
D02B 20 65 07 JSR $0765
D02E A4 1F LDY $1F
D030 6C 00 FC JMP ($FC00)
D033 A0 02 LDY #$02
D035 51 18 EOR ($18),Y
D037 D0 F2 BNE $D02B
D039 A9 00 LDA #$00
D03B 85 1D STA $1D
D03D 78 SEI
D03E 20 65 07 JSR $0765
D041 A9 08 LDA #$08
D043 25 82 AND $82
D045 F0 03 BEQ $D04A
D047 4C 84 06 JMP $0684
D04A 20 80 07 JSR $0780
D04D A2 FF LDX #$FF
D04F A9 DA LDA #$DA
D051 20 2E 07 JSR $072E
D054 85 4C STA $4C
D056 20 2E 07 JSR $072E
D059 20 2E 07 JSR $072E
D05C A9 DC LDA #$DC
D05E 20 2E 07 JSR $072E
D061 A2 0F LDX #$0F
D063 20 2E 07 JSR $072E
D066 85 4C STA $4C
D068 20 0D 07 JSR $070D
D06B 20 3E 07 JSR $073E
D06E 20 37 07 JSR $0737
D071 C9 0F CMP #$0F
D073 F0 03 BEQ $D078
D075 4C 82 06 JMP $0682
D078 A9 11 LDA #$11
D07A 18 CLC
D07B 6D 9D 04 ADC $049D
D07E 85 0A STA $0A
D080 A6 15 LDX $15
D082 A0 00 LDY #$00
D084 A9 00 LDA #$00
D086 18 CLC
D087 65 0A ADC $0A
D089 90 01 BCC $D08C
D08B C8 INY
D08C C8 INY
D08D CA DEX
D08E D0 F6 BNE $D086
D090 49 FF EOR #$FF
D092 38 SEC
D093 69 00 ADC #$00
D095 18 CLC
D096 6D A0 07 ADC $07A0
D099 B0 03 BCS $D09E
D09B CE 9F 07 DEC $079F
D09E AA TAX
D09F 98 TYA
D0A0 49 FF EOR #$FF
D0A2 38 SEC
D0A3 69 00 ADC #$00
D0A5 18 CLC
D0A6 6D 9F 07 ADC $079F
D0A9 10 03 BPL $D0AE
D0AB 4C 82 06 JMP $0682
D0AE A8 TAY
D0AF 8A TXA
D0B0 A2 00 LDX #$00
D0B2 38 SEC
D0B3 E5 15 SBC $15
D0B5 B0 03 BCS $D0BA
D0B7 88 DEY
D0B8 30 03 BMI $D0BD
D0BA E8 INX
D0BB D0 F5 BNE $D0B2
D0BD 86 0A STX $0A
D0BF EC 9E 04 CPX $049E
D0C2 B0 03 BCS $D0C7
D0C4 4C 82 06 JMP $0682
D0C7 18 CLC
D0C8 65 15 ADC $15
D0CA 8D 9E 07 STA $079E
D0CD 20 80 07 JSR $0780
D0D0 A9 DE LDA #$DE
D0D2 A2 FF LDX #$FF
D0DC 20 2E 07 JSR $072E
D0DF A9 DC LDA #$DC
D0E1 20 2E 07 JSR $072E
D0E4 A2 08 LDX #$08
D0E6 20 2E 07 JSR $072E
D0E9 85 4C STA $4C
D0EB A2 FF LDX #$FF
D0ED AD 9D 07 LDA $079D
D0F0 24 4D BIT $4D
D0F2 10 FC BPL $D0F0
D0F4 85 80 STA $80
D0F6 24 41 BIT $41
D0F8 4D 9C 07 EOR $079C
D0FB AC 9C 07 LDY $079C
D0FE EE 9C 07 INC $079C
D101 24 4D BIT $4D
D103 10 FC BPL $D101
D105 84 80 STY $80
D107 24 41 BIT $41
D109 4D 9C 07 EOR $079C
D10C 8D 9D 07 STA $079D
D10F A0 02 LDY #$02
D111 B1 18 LDA ($18),Y
D113 24 4D BIT $4D
D115 10 FC BPL $D113
D117 85 80 STA $80
D119 24 41 BIT $41
D11B 88 DEY
D11C 10 F3 BPL $D111
D11E A9 00 LDA #$00
D120 AC 9D 04 LDY $049D
D123 24 4D BIT $4D
D125 10 FC BPL $D123
D127 85 80 STA $80
D129 24 41 BIT $41
D12B 88 DEY
D12C D0 F5 BNE $D123
D12E A9 DE LDA #$DE
D130 20 2E 07 JSR $072E
D133 85 4C STA $4C
D135 20 2E 07 JSR $072E
D138 20 2E 07 JSR $072E
D13B A9 DC LDA #$DC
D13D 20 2E 07 JSR $072E
D140 A2 07 LDX #$07
D142 20 2E 07 JSR $072E
D145 85 4C STA $4C
D147 A0 00 LDY #$00
D149 A2 00 LDX #$00
D14B 24 4D BIT $4D
D14D 10 FC BPL $D14B
D14F 86 80 STX $80
D151 24 41 BIT $41
D153 88 DEY
D154 D0 F5 BNE $D14B
D156 A4 0A LDY $0A
D158 20 2E 07 JSR $072E
D15B 24 4D BIT $4D
D15D 10 FC BPL $D15B
D15F 86 80 STX $80
D161 24 41 BIT $41
D163 88 DEY
D164 10 F5 BPL $D15B
D166 AD 9C 07 LDA $079C
D169 C5 15 CMP $15
D16B F0 03 BEQ $D170
D16D 4C D0 05 JMP $05D0
D170 20 0D 07 JSR $070D
D173 A9 00 LDA #$00
D175 8D 9C 07 STA $079C
D178 20 3E 07 JSR $073E
D17B 20 37 07 JSR $0737
D17E C9 08 CMP #$08
D180 F0 0E BEQ $D190
D182 A9 0C LDA #$0C
D184 58 CLI
D185 E6 1D INC $1D
D187 A0 0A LDY #$0A
D189 C4 1D CPY $1D
D18B F0 79 BEQ $D206
D18D 4C 3D 05 JMP $053D
D190 20 37 07 JSR $0737
D193 8D 9D 07 STA $079D
D196 20 37 07 JSR $0737
D199 CD 9C 07 CMP $079C
D19C D0 E4 BNE $D182
D19E 4D 9D 07 EOR $079D
D1A1 A0 02 LDY #$02
D1A3 24 4D BIT $4D
D1A5 10 FC BPL $D1A3
D1A7 45 41 EOR $41
D1A9 88 DEY
D1AA 10 F7 BPL $D1A3
D1AC A8 TAY
D1AD D0 D3 BNE $D182
D1AF EE 9C 07 INC $079C
D1B2 20 3E 07 JSR $073E
D1B5 20 37 07 JSR $0737
D1B8 C9 07 CMP #$07
D1BA D0 C6 BNE $D182
D1BC A0 00 LDY #$00
D1BE 24 4D BIT $4D
D1C0 10 FC BPL $D1BE
D1C2 A5 41 LDA $41
D1C4 D0 BC BNE $D182
D1C6 88 DEY
D1C7 D0 F5 BNE $D1BE
D1C9 20 37 07 JSR $0737
D1CC D0 B4 BNE $D182
D1CE AD 9C 07 LDA $079C
D1D1 C5 15 CMP $15
D1D3 D0 A3 BNE $D178
D1D5 20 3E 07 JSR $073E
D1D8 AD 9F 07 LDA $079F
D1DB F0 03 BEQ $D1E0
D1DD 4C 82 06 JMP $0682
D1E0 AD 9E 07 LDA $079E
D1E3 38 SEC
D1E4 65 0A ADC $0A
D1E6 38 SEC
D1E7 ED A0 07 SBC $07A0
D1EA 10 05 BPL $D1F1
D1EC 49 FF EOR #$FF
D1EE 38 SEC
D1EF 69 00 ADC #$00
D1F1 C9 1C CMP #$1C
D1F3 90 03 BCC $D1F8
D1F5 4C 82 06 JMP $0682
D1F8 E6 1A INC $1A
D1FA 58 CLI
D1FB A9 24 LDA #$24
D1FD C5 1A CMP $1A
D1FF F0 03 BEQ $D204
D201 4C 2B 05 JMP $052B
D204 A9 01 LDA #$01
D206 A0 FF LDY #$FF
D208 84 1A STY $1A
D20A 6C 02 FC JMP ($FC02)
D20D 20 2E 07 JSR $072E
D210 24 4D BIT $4D
D212 10 FC BPL $D210
D214 A9 FC LDA #$FC
D216 85 4C STA $4C
D218 A9 92 LDA #$92
D21A 85 4E STA $4E
D21C A2 03 LDX #$03
D21E 20 37 07 JSR $0737
D221 24 40 BIT $40
D223 CA DEX
D224 D0 F8 BNE $D21E
D226 60 RTS
D227 A0 10 LDY #$10
D229 84 4E STY $4E
D22B 85 4C STA $4C
D22D 60 RTS
D22E 24 4D BIT $4D
D230 10 FC BPL $D22E
D232 86 80 STX $80
D234 24 41 BIT $41
D236 60 RTS
D237 24 4D BIT $4D
D239 10 FC BPL $D237
D23B A5 41 LDA $41
D23D 60 RTS
D23E A0 00 LDY #$00
D240 8C 9F 07 STY $079F
D243 24 82 BIT $82
D245 50 16 BVC $D25D
D247 24 4D BIT $4D
D249 10 F8 BPL $D243
D24B 24 41 BIT $41
D24D 24 40 BIT $40
D24F C8 INY
D250 D0 F1 BNE $D243
D252 EE 9F 07 INC $079F
D255 D0 03 BNE $D25A
D257 4C 82 06 JMP $0682
D25A 4C 43 07 JMP $0743
D25D 8C A0 07 STY $07A0
D260 24 40 BIT $40
D262 24 41 BIT $41
D264 60 RTS
D265 A0 02 LDY #$02
D267 A5 1A LDA $1A
D269 91 18 STA ($18),Y
D26B A9 00 LDA #$00
D26D 8D 9C 07 STA $079C
D270 C8 INY
D271 91 18 STA ($18),Y
D273 51 18 EOR ($18),Y
D275 88 DEY
D276 10 FB BPL $D273
D278 8D 9D 07 STA $079D
D27B A0 04 LDY #$04
D27D 91 18 STA ($18),Y
D27F 60 RTS
D280 A2 00 LDX #$00
D282 A0 00 LDY #$00
D284 A9 20 LDA #$20
D286 8D 9F 07 STA $079F
D289 A9 DC LDA #$DC
D28B 20 27 07 JSR $0727
D28E 20 2E 07 JSR $072E
D291 88 DEY
D292 D0 FA BNE $D28E
D294 CE 9F 07 DEC $079F
D297 D0 F5 BNE $D28E
D299 60 RTS
D29A 0C ???
D29B 03 ???
D29C 48 PHA
D29D 53 ???
D29E 50 AA BVC $D24A
****************************** Checksum byte for $D000
D2A0 25 ??? ;D-ROM checksum
****************************** Command Search Table: 'ivdmbupcrsn'
D2A1 49 ??? ;initialize
D2A2 56 ??? ;verify-dir
D2A3 44 ??? ;duplicate
D2A4 4D ??? ;m-
D2A5 42 ??? ;b-
D2A6 55 ??? ;user
D2A7 50 ??? ;position
D2A8 43 ??? ;copy
D2A9 52 ??? ;rename
D2AA 53 ??? ;scratch
D2AB 4E ??? ;new
******************************* Dos command jump table (Low Bytes)
D2AC C5 ??? ;initialize
D2AD EC ??? ;verify-dir
D2AE 46 ??? ;duplicate
D2AF A8 ??? ;m-
D2B0 AF ??? ;b-
D2B1 08 ??? ;user
D2B2 ED ??? ;position
D2B3 4A ??? ;copy
D2B4 75 ??? ;rename
D2B5 B7 ??? ;scratch
D2B6 0D ??? ;new
;m-
;b-
;user
;position
;copy
;rename
;scratch
;new
***************************
**** Structure images for commands (bits 0-7)
file structure 0: requires filename
#02 1: not default drive
2: not greater than one file
3: not pattern
file structure 4: requires filename
#01 5: not default drive
6: not greater than one file
7: not pattern
D2C2 51 ??? ;copy : 0101 0001
;rename : 1101 1101
;scratch: 0001 1100
;new : 1001 1110
;load : 0001 1100
******************************* Track/group table
D2C7 11 ??? ;end group #1: 17 (density 00)
;end group #2: 24 (density 01)
;end group #3: 30 (density 10)
;end group #4: 35 (density 11)
******************************* Mode table
D2CB 52 ??? ;mode: read
;mode: write
;mode: append
;mode: modify
******************************* File type table
D2CF 44 ??? ;D
D2D0 53 ??? ;S
D2D1 50 ??? ;P
D2D2 55 ??? ;U
D2D3 4C ??? ;L
******************************* 1st character in name of file type
D2D4 44 ??? ;Del
D2D5 53 ??? ;Seq
D2D6 50 ??? ;Prg
D2D7 55 ??? ;Usr
D2D8 52 ??? ;Rel
******************************* 2nd character in name of file type
D2D9 45 ??? ;dEl
D2DA 45 ??? ;sEq
D2DB 52 ??? ;pRg
D2DC 53 ??? ;uSr
D2DD 45 ??? ;rEl
******************************* 3rd character in name of file type
D2DE 4C ??? ;deL
D2DF 51 ??? ;seQ
D2DE 47 ??? ;prG
D2E1 52 ??? ;usR
D2E2 4C ??? ;reL
******************************* Error flag variables for file bits:
D2E3 00 ??? ;#$00: 0000 0000
D2E4 3F ??? ;#$3F: 0011 1111
D2E5 7F ??? ;#$7F: 0111 1111
D2E6 BF ??? ;#$BF: 1011 1111
D2E7 FF ??? ;#$FF: 1111 1111
******************************* BAM buffer pointers (High bytes)
D2E8 41 ??? ;BAM buffer pointer for drive 0
D2E9 42 ??? ;BAM buffer pointer for drive 1
******************************* Sectors per track table (4040)
D2EA 11 ??? ;group #4 maximum sectors: 00-16 (trk 31-35)
D2EB 12 ??? ;group #3 maximum sectors: 00-17 (trk 25-30)
D2EC 13 ??? ;group #2 maximum sectors: 00-18 (trk 18-24)
D2ED 15 ??? ;group #1 maximum sectors: 00-20 (trk 1-17)
******************************* Disk & sector definition bytes (4040)
D2EE 09 ??? ;GAP 1 spacing byte
D2EF 02 ??? ;GAP 2 spacing byte
D2F0 41 ??? ;Format version: A
******************************* Sectors per track table (3040)
D2F1 0E ??? ;group #4 maximum sectors: 00-13 (trk 31-35)
D2F2 0F ??? ;group #3 maximum sectors: 00-14 (trk 25-30)
D2F3 10 ??? ;group #2 maximum sectors: 00-16 (trk 18-24)
D2F4 12 ??? ;group #1 maximum sectors: 00-17 (trk 1-17)
******************************* Disk & sector definition bytes (3040)
D2F5 1C ??? ;GAP 1 spacing byte
D2F6 1E ??? ;GAP 2 spacing byte
D2F7 42 ??? ;Format version: B
******************************* Controller: jump to wait loop
D2F8 78 SEI ;transfer control over to 6504
D2F9 A9 00 LDA #$00
D2FB 8D 03 04 STA $0403 ;set job queue to no jobs: #$00
D2FE 4C 04 FC JMP $FC04 ;jump to initialize 6504 routine
******************************* Error display routine. Blinks the error
number + 1 in all three LED's
D301 A2 00 LDX #$00 ;set number of error flashes to #$00
D303 2C A6 04 BIT $04A6 ;** also becomes patch: D304 A6 04 LDX $04
D306 9A TXS ;use stack as storage register
D307 BA TSX ;restore error number
D308 A9 38 LDA #$38 ;set all LED's to on
D30A 8D 82 02 STA $0282 ;turn on LED's
D30D 98 TYA ;clear inner memory counter
D30E 18 CLC
D30F 69 01 ADC #$01 ;increment job counter
D311 D0 FC BNE $D30F ;job counter equal to zero ?, no
D313 88 DEY ;done clearing zero page ?
D314 D0 F8 BNE $D30E ;no,
D316 8C 82 02 STY $0282 ;turn off LED's
D319 98 TYA
D31A 18 CLC
D31B 69 01 ADC #$01 ;finished counting to #$FF ?
D31D D0 FC BNE $D31B ;no,
D31F 88 DEY ;finished counting to #$FF
D320 D0 F8 BNE $D31A ;no,
D322 CA DEX ;cycle for type of failure indicated ?
D323 10 E3 BPL $D308 ;no,
D325 E0 FC CPX #$FC ;does flashing cycle define the proper
hardware failure ?
D327 D0 F0 BNE $D319 ;no, finish flashing cycle
D329 F0 DC BEQ $D307 ;yes, repeat error cycle
******************************* Initialize disk for: Power Up Diagnostics
D32B 78 SEI ;set interrupt timer
D32C D8 CLD
D32D A2 FF LDX #$FF
D32F 8E 02 02 STX $0202 ;set IEEE data out port
D332 8E 03 02 STX $0203 ;activate data out direction
D335 E8 INX ;set LED's to off
D336 8E 82 02 STX $0282 ;turn off LED's
D339 A9 1C LDA #$1C
D33B 8D 80 02 STA $0280 ;initialize DAV, EOI, RFD lines
D33E A9 1F LDA #$1F
D340 8D 81 02 STA $0281 ;initialize LED's
D343 A9 38 LDA #$38 ;set LED's to on
D345 8D 83 02 STA $0283 ;store IEEE control port
******************************* Fill ZERO PAGE ascending pattern
D348 8A TXA ;set fill code for ZERO PAGE
D349 95 00 STA $00,X ;fill ZERO PAGE with corresponding location
number (ex. $01 = #$01)
D34B E8 INX ;done ?
D34C D0 FA BNE $D348 ;no,
******************************* Test ZERO PAGE
D34E 8A TXA ;set .ACC to #$00
D34F A8 TAY ;set .Y register to #$00
D350 C8 INY
D351 F6 00 INC $00,X ;increment all of ZERO PAGE by one
D353 C8 INY ;done setting section of ZERO PAGE ?
D354 D0 FB BNE $D351 ;no,
D356 B4 00 LDY $00,X ;load .Y register with ZERO PAGE value
D358 C8 INY ;is ZERO PAGE equal to #$00 ?
D359 D0 A6 BNE $D301 ;no, exit to indicate ZERO PAGE hardware
failure
D35B F6 00 INC $00,X ;User Jump Table pointer set to #$00
D35D D0 A2 BNE $D301 ;no, exit to indicate ZERO PAGE hardware
failure
D35F E8 INX ;ZERO PAGE all tested ?
D360 D0 EC BNE $D34E ;no,
******************************* Test three 64K-bit roms: exit if ok
.X = start page
D362 E6 04 INC $04 ;set for proper amount of failure flashes
D364 86 0B STX $0B ;set LO byte of Indirect Pointer to #$00
D366 A9 00 LDA #$00
D368 85 0A STA $0A ;set HI byte of Indirect Pointer to #$00
D36A A8 TAY
D36B A2 10 LDX #$10 ;test sixteen pages
D36D 18 CLC
D36E C6 0B DEC $0B ;start checking ROM backwards
D370 71 0A ADC ($0A),Y ;add up checksum
D372 C8 INY ;last byte of page checked ?
D373 D0 FB BNE $D370 ;no,
D375 CA DEX ;last page of ROM checked ?
D376 D0 F6 BNE $D36E ;no,
D378 69 00 ADC #$00
D37A AA TAX
D37B C5 0B CMP $0B ;finished checking IEEE ROM ?
D37D D0 85 BNE $D304 ;no, exit to indicate ROM hardware failure
D37F E0 D0 CPX #$D0 ;is CONTROLLER ROM currently under test ?
D381 D0 DF BNE $D362 ;no,
D383 B9 F8 D2 LDA $D2F8,Y ;load content of ROM location
D386 99 00 11 STA $1100,Y ;store content in Data Buffer #0
D389 C8 INY ;finished transfer ?
D38A D0 F7 BNE $D383 ;no,
D38C A9 D0 LDA #$D0
D38E 8D 03 10 STA $1003 ;set job queue to Execute Ml code in Data
buffer
D391 E6 04 INC $04 ;set proper amount of failure flashes
D393 C8 INY ;finished testing ?
D394 D0 FD BNE $D393 ;no,
D396 AD 03 10 LDA $1003 ;CONTROLLER ROM tested ?
D399 F0 05 BEQ $D3A0 ;yes,
D39B CA DEX
D39C 30 F5 BMI $D393 ;last page of CONTROLLER ROM left to test ?
D39E D0 DD BNE $D37D ;no,
******************************* Test all common ram pages $2000-$5000
D3A0 A9 10 LDA #$10
D3A2 85 0B STA $0B ;set for ram page
D3A4 E6 04 INC $04 ;set proper amount of failure flashes
D3A6 A2 04 LDX #$04 ;divide page into four parts
D3A8 98 TYA
D3A9 18 CLC
D3AA 65 0B ADC $0B ;do next byte in page
D3AC 91 0A STA ($0A),Y ;fill page location with byte value
D3AE C8 INY ;last byte of page ?
D3AF D0 F7 BNE $D3A8 ;no,
D3B1 E6 0B INC $0B ;increment for next page
D3B3 CA DEX ;last part of current page done ?
D3B4 D0 F2 BNE $D3A8 ;no,
D3B6 A2 04 LDX #$04 ;divide page into four parts
D3B8 C6 0B DEC $0B ;so next byte in page
D3BA 88 DEY ;last byte in page ?
D3BB 98 TYA
D3BC 18 CLC
D3BD 65 0B ADC $0B ;calculate checksum
D3BF D1 0A CMP ($0A),Y ;ok ?
D3C1 D0 BA BNE $D37D ;error during test, branch to error routine
D3C3 49 FF EOR #$FF ;flip bits of current byte in page
D3C5 91 0A STA ($0A),Y ;store result back into location
D3C7 51 0A EOR ($0A),Y ;flip bits once again
D3C9 91 0A STA ($0A),Y ;store result back into location, result $00 ?
D3CB D0 B0 BNE $D37D ;error during test, branch to error routine
D3CD 98 TYA ;another byte in page to do ?
D3CE D0 EA BNE $D3BA ;yes,
D3D0 CA DEX ;another page ?
D3D1 D0 E5 BNE $D3B8 ;yes,
D3D3 A5 0B LDA $0B ;set .ACC to current RAM page under test
D3D5 18 CLC
D3D6 69 10 ADC #$10 ;set up for next page to test
D3D8 C9 50 CMP #$50 ;last page of RAM tested ?
D3DA D0 C6 BNE $D3A2 ;no,
******************************* Diagnostics ok so far: test device number
(PINS 22,23,24 on drive board location UE1)
and test LED status
D3DC A2 FF LDX #$FF
D3DE 9A TXS ;initialize stack pointer
D3DF AD 82 02 LDA $0282 ;read LED status: bit 0-2 = device number
3-5 = LED status
D3E2 29 C7 AND #$C7 ;set LED's to off
D3E4 8D 82 02 STA $0282 ;turn off LED's : bit 0-2 = device number
3-5 = LED status
D3E7 AD 82 02 LDA $0282 ;read device number: bit 0-2 = device number
3-5 = LED status
D3EA 29 07 AND #$07 ;test PINS 22,23,24 for device number
D3EC 09 48 ORA #$48 ;add $40 to device number
D3EE 85 0D STA $0D ;set talker device number
D3F0 49 60 EOR #$60 ;add $20 to device number
D3F2 85 0C STA $0C ;set listener device number
******************************* Initialize buffer pointer table
D3F4 A2 00 LDX #$00
D3F6 A0 00 LDY #$00
D3F8 A9 00 LDA #$00
D3FA 95 29 STA $29,X ;set LO byte of BUFFER #0 to #$00
D3FC E8 INX ;set for HI byte of BUFFER
D3FD B9 FF F0 LDA $F0FF,Y ;read HI byte for current BUFFER
D400 95 29 STA $29,X ;store at BUFFER HI byte position
D402 E8 INX ;move to next BUFFER
D403 C8 INY ;move to next BUFFER
D404 C0 0E CPY #$0E ;all fifteen BUFFERS set ?
D406 D0 F0 BNE $D3F8 ;no,
D408 A9 00 LDA #$00
D40A 95 29 STA $29,X ;set LO byte of command buffer to #$00
D40C E8 INX
D40D A9 43 LDA #$43
D40F 95 29 STA $29,X ;set HI byte of command buffer to #$43
D411 E8 INX
D412 A9 DC LDA #$DC
D414 95 29 STA $29,X ;set LO byte of ERROR output buffer to #$DC
D416 E8 INX
D417 A9 43 LDA #$43
D419 95 29 STA $29,X ;set HI byte of ERROR output buffer to #$43
D41B A9 FF LDA #$FF
D41D A2 12 LDX #$12
D41F 95 A2 STA $A2,X ;set LOGICAL INDEX TABLE to #$FF
bit 6-7: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
D421 CA DEX ;last table set ?
D422 10 FB BPL $D41F ;no,
D424 A2 07 LDX #$07
D426 95 49 STA $49,X ;set SEQ file buffers to #$FF
D428 95 51 STA $51,X ;set CHANNEL buffers to #$FF
D42A 95 79 STA $79,X ;set SIDE SECTOR table to #$FF
D42C CA DEX ;all flag buffers set to #$FF ?
D42D 10 F7 BPL $D426 ;no,
D42F A9 0E LDA #$0E
D431 85 4F STA $4F ;set LO byte of SEQ file buffer to #$0E
D433 A9 0F LDA #$0F
D435 85 50 STA $50 ;set HI byte of SEQ file buffer to #$0F
D437 A9 07 LDA #$07
D439 85 B2 STA $B2 ;set HI byte of LOGICAL INDEX TABLE to #$07
D43B A9 86 LDA #$86
D43D 85 B1 STA $B1 ;set LO byte of LOGICAL INDEX TABLE to #$86
D43F A9 3F LDA #$3F
D441 8D 48 43 STA $4348 ;set available logical index
bit 6-7: error channel & command channel
1: free LOGICAL INDEX
D444 A9 01 LDA #$01
D446 85 9E STA $9E ;set channel status 7
bit 7: channel is talker to IEEE
3: send EOI on next byte (talker only)
1: channel is listener to IEEE
D448 A9 88 LDA #$88
D44A 85 9F STA $9F ;set channel status to 8
D44C A9 00 LDA $00
D44C 8D 3E 43 STA $433E ;set SEQ file buffer to unused
bit 1: indicates buffer used
D451 A9 F0 LDA #$F0
D453 8D 3F 43 STA $433F ;set CHANNEL buffer
bit 1: indicates buffer used
D456 20 0F E8 JSR $E80F ;jump to user access commands
D459 A9 DC LDA #$DC
D45B 8D F0 10 STA $10F0 ;set LO byte of NMI to #$DC
D45E A9 D3 LDA #$D3
D460 8D F1 10 STA $10F1 ;set HI byte of NMI to #$D3
D463 A9 0A LDA #$0A
D465 8D 44 43 STA $4344 ;set sector increment to #$0A
D468 8D 5C 43 STA $435C ;set error recovery count to #$0A
******************************* Set up sector/track table depending on
controller used
D46B AD 00 10 LDA $1000 ;read Interrupt Delay
D46E A2 00 LDX #$00
D470 C9 0F CMP #$0F ;disk controller under use ?
D472 F0 0B BEQ $D47F ;yes,
D474 A2 07 LDX #$07
D476 C9 64 CMP #$64 ;IEEE controller under use ?
D478 F0 05 BEQ $D47F ;yes,
******************************* Controller error
D47A E6 04 INC $04 ;set proper amount of failure flashes
D47C 4C 04 D3 JMP $D304 ;error during test, branch to error routine
******************************* Set up sectors/track, GAP1, dos version,
format version
D47F A0 00 LDY #$00
D481 BD EA D2 LDA $D2EA,X ;load amount of sectors for track group
D484 99 99 10 STA $1099,Y ;store in sectors/track table
D487 E8 INX ;set for next group
D488 C8 INY ;set for next location in table
D489 C0 07 CPY #$07 ;format version transferred ?
D48B D0 F4 BNE $D481 ;no,
******************************* Set up power on message "cbm dos v2.1"
D48D A9 73 LDA #$73 ;set for error # 73
D48F 20 CE D9 JSR $D9CE ;jump to error process routine
******************************* BUMP heads to track 1
D492 A9 01 LDA #$01
D494 8D 23 10 STA $1023 ;set track of buffer #0 to 1
D497 8D 2B 10 STA $102B ;set track of buffer #1 to 1
D49A A2 C0 LDX #$C0
D49C 8E 03 10 STX $1003 ;BUMP head of drive 0
D49F E8 INX
D4A0 8E 04 10 STX $1004 ;BUMP head of drive 1
D4A3 8E 87 02 STX $0287 ;turn off LED's
******************************* Idle loop: does housekeeping while waiting
for job
D4A6 AD 47 43 LDA $4347 ;is there a command waiting ?
D4A9 F0 0C BEQ $D4B7 ;no,
D4AB 78 SEI
D4AC A9 00 LDA #$00
D4AE 8D 47 43 STA $4347 ;set command waiting flag to 0
D4B1 8D F2 10 STA $10F2 ;set NMI in progress to 0
D4B4 20 55 DB JSR $DB55 ;parse and execute string in command buffer
D4B7 58 CLI
D4B8 A9 0E LDA #$0E
D4BA 85 07 STA $07 ;assign TEMP3 flag as logical counter
D4BC A9 00 LDA #$00
D4BE 85 04 STA $04 ;assign TEMP0 flag to current jobs
D4C0 85 05 STA $05 ;assign TEMP1 flag as current drive indicator
D4C2 A6 07 LDX $07 ;set up for index check
D4C4 B5 A2 LDA $A2,X ;check for available logical index
D4C6 C9 FF CMP #$FF ;logical index available ?
D4C8 F0 10 BEQ $D4DA ;yes,
D4CA 29 3F AND #$3F ;test index's current status (r/w,r,w,no)
D4CC 85 15 STA $15 ;store in logical index status
D4CE 20 98 FA JSR $FA98 ;get active buffer number
D4D1 AA TAX
D4D2 BD 4E 43 LDA $434E,X ;last job entered in queue
D4D5 29 01 AND #$01
D4D7 AA TAX
D4D8 F6 04 INC $04,X ;increment TEMP flag
D4DA C6 07 DEC $07 ;last logical index ?
D4DC 10 E4 BPL $D4C2 ;no,
D4DE A0 0B LDY #$0B
D4E0 B9 03 10 LDA $1003,Y ;job in queue ?
D4E3 10 05 BPL $D4EA ;no,
D4E5 29 01 AND #$01
D4E7 AA TAX
D4E8 F6 04 INC $04,X ;increment TEMP flag
D4EA 88 DEY ;last queue checked for job ?
D4EB 10 F3 BPL $D4E0 ;no,
D4ED AD 82 02 LDA $0282 ;test active LED
D4F0 29 E7 AND #$E7
D4F2 48 PHA
D4F3 A5 04 LDA $04 ;is drive 0 under use ?
D4F5 F0 04 BEQ $D4FB ;yes,
D4F7 68 PLA
D4F8 09 10 ORA #$10 ;activate LED drive 1
D4FA 48 PHA
D4FB A5 05 LDA $05 ;TEMP1 flag equal to 0 ?
D4FD F0 04 BEQ $D503 ;yes,
D4FF 68 PLA
D500 09 08 ORA #$08 ;activate LED drive 0
D502 48 PHA
D503 68 PLA
D504 8D 82 02 STA $0282 ;activate LED drive 0
D507 4C B7 D4 JMP $D4B7 ;continue housekeeping routine
******************************* ATN irq process: IRQ on ATN, listen to PET
clear stack
D50A A2 FF LDX #$FF
D50C 9A TXS ;purge stack
D50D AD 87 02 LDA $0287 ;clear ATN line from PET
D510 A9 18 LDA #$18 ;set for DAV, EOI signals
D512 0D 80 02 ORA $0280
D515 8D 80 02 STA $0280 ;free DAV, EOI lines
D518 A9 FF LDA #$FF
D51A 8D 02 02 STA $0202 ;free data lines
D51D A9 07 LDA #$07 ;set for DAC, RFD, ATN signals
D51F 0D 80 02 ORA $0280
D522 8D 80 02 STA $0280 ;free DAC, RFD, ATN lines
D525 2C 80 02 BIT $0280 ;have lines been freed ?
D528 50 04 BVC $D52E ;DAV set low
D52A 30 F9 BMI $D525 ;ATN low & ATN1 high
D52C 10 7B BPL $D5A9 ;ATN high
D52E A9 FB LDA #$FB ;set for NRFD signal
D530 2D 80 02 AND $0280
D533 8D 80 02 STA $0280 ;set NRFD line low
D536 29 20 AND #$20
D538 85 A0 STA $A0 ;temporary EOI
D53A AD 00 02 LDA $0200 ;get DATA byte from IEEE port
D53D 49 FF EOR #$FF
D53F 85 18 STA $18 ;store byte in temp data byte
D541 A9 FD LDA #$FD ;set for NDAC signal
D543 2D 80 02 AND $0280
D546 8D 80 02 STA $0280 ;set NDAC line high
******************************* Decide: Secondary Address, talk, listen,
other
D549 A0 00 LDY #$00
D54B A5 18 LDA $18 ;read data byte from temporary location
D54D 29 60 AND #$60
D54F C9 40 CMP #$40 ;is it a talk signal ?
D551 F0 29 BEQ $D57C ;yes,
D553 C9 20 CMP #$20 ;is it a listen signal?
D555 F0 06 BEQ $D55D ;yes,
D557 C9 60 CMP #$60 ;is it a secondary address ?
D559 F0 2F BEQ $D58A ;yes,
D55B D0 44 BNE $D5A1 ;no,
D55D A5 18 LDA $18 ;load in device number sent from PET
D55F C5 0C CMP $0C ;same device number ?
D561 F0 0B BEQ $D56E ;yes,
D563 C9 3F CMP #$3F ;is signal sent from PET an unlisten ?
D565 D0 02 BNE $D569 ;no,
D567 84 0E STY $0E ;set active listener flag to #$00
D569 84 10 STY $10 ;set addressed flag to #$00
D56B 4C A1 D5 JMP $D5A1
D56E 85 0E STA $0E ;set active listener flag to accessed device
D570 84 0F STY $0F ;set active talker flag to #$00
D572 A9 20 LDA #$20
D574 85 16 STA $16 ;set secondary address to #$20 (decimal 32)
D576 85 17 STA $17 ;set original secondary address to #$20
(decimal 32)
D578 85 10 STA $10 ;addressed flag not #$00 ?
D57A D0 25 BNE $D5A1 ;yes,
D57C 84 0F STY $0F ;set active talker to #$00
D57E A5 18 LDA $18 ;read byte from temporary location
D580 C5 0D CMP $0D ;equal to talker address ?
D582 D0 E5 BNE $D569 ;no,
D584 85 0F STA $0F ;set active talker to device calling
D586 84 0E STY $0E ;active listener set to #$00 ?
D588 F0 E8 BEQ $D572 ;yes,
D58A A5 10 LDA $10 ;addressed flag #$00 ?
D58C F0 13 BEQ $D5A1 ;yes,
D58E A5 18 LDA $18 ;read byte from temporary location
D590 85 17 STA $17 ;set as original secondary address
D592 48 PHA
D593 29 0F AND #$0F ;test address validity: 0-15
D595 85 16 STA $16 ;store result as current secondary address
D597 68 PLA
D598 29 F0 AND #$F0
D59A C9 E0 CMP #$E0 ;close command received ?
D59C D0 03 BNE $D5A1 ;no,
D59E 20 8D F5 JSR $F58D ;close file associated with secondary address
D5A1 2C 80 02 BIT $0280 ;IEEE control port released ?
D5A4 50 FB BVC $D5A1 ;no,
D5A6 4C 1D D5 JMP $D51D ;yes,
D5A9 A5 0E LDA $0E ;active listener to #$00 ?
D5AB F0 0F BEQ $D5BC ;yes,
D5AD A9 FA LDA #$FA ;set for ATN & DAC signal
D5AF 2D 80 02 AND $0280
D5B2 8D 80 02 STA $0280 ;set ATN, DAC lines
D5B5 58 CLI
D5B6 20 CF D5 JSR $D5CF ;set for listen mode
D5B9 4C A6 D4 JMP $D4A6 ;jump to idle loop
D5BC A9 FC LDA #$FC ;set for RFD & ATN signal
D5BE 2D 80 02 AND $0280
D5C1 8D 80 02 STA $0280 ;set RFD, ATN lines
D5C4 A5 0F LDA $0F ;active talker to #$00 ?
D5C6 F0 04 BEQ $D5CC ;yes,
D5C8 58 CLI
D5C9 20 5F D6 JSR $D65F ;set for talk mode
D5CC 4C A6 D4 JMP $D4A6 ;jump to idle loop
******************************* Set listen routine: main routine
D5CF A9 04 LDA #$04 ;set for RFD signal
D5D1 0D 80 02 ORA $0280
D5D4 8D 80 02 STA $0280 ;set RFD high
D5D7 2C 80 02 BIT $0280 ;has DAV gone low ?
D5DA 70 FB BVS $D5D7 ;no,
D5DC 20 84 ED JSR $ED84 ;open channel for writing
D5DF B0 05 BCS $D5E6 ;channel not active ?
D5E1 B5 98 LDA $98,X ;read channel status
bit 0: channel is listener to IEEE
bit 3: send EOI on next byte (talker only)
bit 7: channel is talker to IEEE
D5E3 6A ROR ;listener flag set ?
D5E4 B0 49 BCS $D62F ;no,
D5E6 A5 17 LDA $17 ;read secondary address
D5E8 29 F0 AND #$F0
D5EA C9 F0 CMP #$F0 ;secondary address already open ?
D5EC F0 41 BEQ $D62F ;no,
D5EE A5 16 LDA $16 ;current secondary address
D5F0 C9 01 CMP #$01 ;is it SAVE or LOAD ?
D5F2 F0 0E BEQ $D602 ;yes,
D5F4 2C 80 02 BIT $0280 ;has DAV gone low ?
D5F7 50 FB BVC $D5F4 ;no,
D5F9 A9 FD LDA #$FD ;set for DAC signal
D5FB 2D 80 02 AND $0280
D5FE 8D 80 02 STA $0280 ;set DAC lines
D601 60 RTS
D602 A9 FB LDA #$FB ;set for RFD signal
D604 2D 80 02 AND $0280
D607 8D 80 02 STA $0280 ;set RFD line low
D60A A9 FD LDA #$FD ;set for DAC signal
D60C 2D 80 02 AND $0280
D60F 8D 80 02 STA $0280 ;set DAC line high
D612 2C 80 02 BIT $0280 ;has DAV gone high ?
D615 50 FB BVC $D612 ;no,
D617 A9 02 LDA #$02 ;set for DAC signal
D619 0D 80 02 ORA $0280
D61C 8D 80 02 STA $0280 ;set DAC line low
D61F A9 04 LDA #$04 ;set for RFD signal
D621 0D 80 02 ORA $0280
D624 8D 80 02 STA $0280 ;set RFD line
D627 2C 80 02 BIT $0280 ;has DAV gone low ?
D62A 50 FB BVC $D627 ;no,
D62C 4C 02 D6 JMP $D602 ;return to beginning of timing loop
D62F A9 FB LDA #$FB ;set for RFD signal
D631 2D 80 02 AND $0280
D634 8D 80 02 STA $0280 ;set RFD line
D637 29 20 AND #$20
D639 85 A0 STA $A0 ;set temporary EOI flag
D63B AD 00 02 LDA $0200 ;IEEE data in
D63E 49 FF EOR #$FF
D640 85 18 STA $18 ;store byte in temporary data location
D642 78 SEI
D643 A9 FD LDA #$FD ;set for DAC signal
D645 2D 80 02 AND $0280
D648 8D 80 02 STA $0280 ;set DAC line
D64B 2C 80 02 BIT $0280 ;has DAC been polled ?
D64E 50 FB BVC $D64B ;no,
D650 A9 02 LDA #$02 ;set for DAC signal
D652 0D 80 02 ORA $0280
D655 8D 80 02 STA $0280 ;set DAC line
D658 20 F8 EB JSR $EBF8 ;write to indicated channel
D65B 58 CLI
******************************* Listen routine
D65C 4C CF D5 JMP $D5CF ;jump to main listen routine
******************************* Set talk routine: main routine
D65F 20 69 ED JSR $ED69 ;channel open for read ?
D662 B0 06 BCS $D66A ;yes,
D664 A6 15 LDX $15 ;logical index
D666 B5 98 LDA $98,X ;read channel status
bit 0: channel is listener to IEEE
bit 3: send EOI on next byte (talker only)
bit 7: channel is talker
D668 30 01 BMI $D66B ;talk mode active
D66A 60 RTS
******************************* From TALK: no talk = rts
D66B 2C 82 02 BIT $0282 ;read device/LED port: bit 0-2 = device number
3-5 = LED status
D66E 10 FB BPL $D66B ;keep polling until RFD high
D670 B5 B5 LDA $B5,X ;channel data byte
D672 49 FF EOR #$FF
D674 8D 02 02 STA $0202 ;IEEE data out
D677 B5 98 LDA $98,X ;read channel status
bit 0: channel is listener to IEEE
bit 3: send EOI on next byte (talker only)
bit 7: channel is talker
D679 09 E7 ORA #$E7 ;set for EOI & DAV signals
D67B 2D 80 02 AND $0280
D67E 8D 80 02 STA $0280 ;set EOI, DAV lines
D681 2C 82 02 BIT $0282 ;has DAV gone low ?
D684 10 0D BPL $D693 ;yes,
D686 50 F9 BVC $D681 ;no,
D688 A9 18 LDA #$18 ;set for DAV & EOI signal
D68A 0D 80 02 ORA $0280
D68D 8D 80 02 STA $0280 ;set DAV, EOI lines
D690 4C A6 D4 JMP $D4A6 ;jump to idle loop
D693 20 A3 EF JSR $EFA3 ;get a byte from channel
D696 2C 82 02 BIT $0282 ;device/LED port clear ?
bit 0-2 = device number
3-5 = LED status
D699 50 FB BVC $D696 ;no,
******************************* Talk routine
D69B A9 FF LDA #$FF
D69D 8D 02 02 STA $0202 ;IEEE data out
D6A0 A9 18 LDA #$18 ;set for DAV & EOI signals
D6A2 0D 80 02 ORA $0280
D6A5 8D 80 02 STA $0280 ;set DAV, EOI lines
D6A8 2C 82 02 BIT $0282 ;device/LED port clear ?
bit 0-2 = device number
3-5 = LED status
D6AB 70 FB BVS $D6A8 ;no,
D6AD 50 B5 BVC $D664 ;yes,
******************************* Return next available track and sector given
current T & S allocation is from track 18
towards 1 & 35 by full tracks
D6AF 20 41 F9 JSR $F941 ;get track and sector number
D6B2 A9 03 LDA #$03
D6B4 85 04 STA $04 ;set TEMP0 to #$03
D6B6 20 80 D7 JSR $D780 ;set proper BAM to use
D6B9 A5 13 LDA $13 ;read current track location of head
D6BB 0A ASL
D6BC 0A ASL
D6BD A8 TAY
D6BE B1 02 LDA ($02),Y ;has 4 BAM track bytes been checked ?
D6C0 D0 33 BNE $D6F5 ;no,
D6C2 A5 13 LDA $13 ;check current track
D6C4 C9 12 CMP #$12 ;is it the directory track (18) ?
D6C6 F0 16 BEQ $D6DE ;yes,
D6C8 90 19 BCC $D6E3 ;smaller, then check next lower track
D6CA E6 13 INC $13 ;increment to next track
D6CC A5 13 LDA $13 ;read track position of head
D6CE C9 24 CMP #$24 ;is it at end of disk (36) ?
D6D0 D0 E7 BNE $D6B9 ;no,
D6D2 A9 11 LDA #$11
D6D4 85 13 STA $13 ;set track number to 17
D6D6 A9 00 LDA #$00
D6D8 85 14 STA $14 ;set sector number to 0
D6DA C6 04 DEC $04 ;track searched for available sectors ?
D6DC D0 DB BNE $D6B9 ;no,
******************************* Disk full error
D6DE A9 72 LDA #$72 ;set for "72 DISK FULL" error
D6E0 4C C3 DB JMP $DBC3 ;jump to error process routine
******************************* Find an available track
D6E3 C6 13 DEC $13 ;has track 0 been reached ?
D6E5 D0 D2 BNE $D6B9 ;no,
D6E7 A9 13 LDA #$13
D6E9 85 13 STA $13 ;set track number to 19
D6EB A9 00 LDA #$00
D6ED 85 14 STA $14 ;set sector number to 0
D6EF C6 04 DEC $04 ;track searched for available sectors ?
D6F1 D0 C6 BNE $D6B9 ;no,
D6F3 F0 E9 BEQ $D6DE ;yes,
******************************* Find the next optimum sector on track
D6F5 A5 14 LDA $14 ;read current sector number
D6F7 18 CLC
D6F8 6D 44 43 ADC $4344 ;increment sector by step factor
D6FB 85 14 STA $14 ;set head for step to new sector position
D6FD A5 13 LDA $13 ;read current track number
D6FF 20 D2 D7 JSR $D7D2 ;find sector allocation for track group
D702 8D 3D 43 STA $433D ;store maximum sector limit for track group
D705 8D 3C 43 STA $433C ;store maximum sector limit in TEMP CMD
D708 C5 14 CMP $14 ;is sector number over allowed boundary ?
D70A B0 12 BCS $D71E ;yes,
D70C 38 SEC
D70D A5 14 LDA $14 ;read current sector number
D70F ED 3D 43 SBC $433D ;substract from maximum sector number for track
group
D712 85 14 STA $14 ;store result as current sector number, is
result 0 ?
D714 F0 08 BEQ $D71E ;yes,
D716 C6 14 DEC $14 ;decrement sector number by 1, is result 0 ?
D718 D0 04 BNE $D71E ;no,
D71A A9 00 LDA #$00
D71C 85 14 STA $14 ;set sector number to 0
D71E 20 8C D7 JSR $D78C ;read sector map for current track
D721 20 A8 D7 JSR $D7A8 ;track full ?
D724 B0 15 BCS $D73B ;yes,
D726 CE 3C 43 DEC $433C ;temporary sector count equal to #$0 ?
D729 10 05 BPL $D730 ;no,
******************************* Directory error
D72B A9 71 LDA #$71 ;set for "71 DIR" error
D72D 4C 53 D9 JMP $D953 ;jump to error process routine
******************************* Test for free sectors, else indicate track
as used
D730 A5 14 LDA $14 ;read current sector number
D732 E6 14 INC $14 ;increment sector number
D734 CD 3D 43 CMP $433D ;has all sectors for track been checked ?
D737 D0 E8 BNE $D721 ;no,
D739 F0 DF BEQ $D71A ;yes,
D73B 4C 9A EB JMP $EB9A ;indicate sectors for track as used
******************************* Test lower & upper track ranges for free
sectors
D73E A9 11 LDA #$11
D740 85 13 STA $13 ;set track number to 17
D742 20 80 D7 JSR $D780 ;set BAM for use with current drive
D745 A5 13 LDA $13 ;read track number
D747 0A ASL
D748 0A ASL
D749 A8 TAY ;set pointer to location of track in BAM
D74A B1 02 LDA ($02),Y ;available sectors on track ?
D74C D0 15 BNE $D763 ;yes,
D74E A9 24 LDA #$24 ;set for track number 36
D750 38 SEC
D751 E5 13 SBC $13 ;set pointer for upper track test
D753 0A ASL
D754 0A ASL
D755 A8 TAY ;set pointer to location of track in BAM
D756 B1 02 LDA ($02),Y ;available sectors on track ?
D758 D0 09 BNE $D763 ;yes,
D75A C6 13 DEC $13 ;all tracks on disk checked for free sectors ?
D75C D0 E7 BNE $D745 ;no,
******************************* Disk full error
D75E A9 72 LDA #$72 ;set for "72 DISK FULL" error
D760 4C C3 DB JMP $DBC3 ;jump to error process routine
******************************* Find sector
D763 98 TYA
D764 4A LSR
D765 4A LSR
D766 85 13 STA $13 ;set current track to search for free sectors
D768 A9 00 LDA #$00
D76A 85 14 STA $14 ;set sector number to 0
D76C 20 8C D7 JSR $D78C ;read sector map for current track
D76F 20 A8 D7 JSR $D7A8 ;track full ?
D772 B0 09 BCS $D77D ;yes,
D774 E6 14 INC $14 ;sector count 0 ?
D776 D0 F7 BNE $D76F ;no,
******************************* Directory error
D778 A9 71 LDA #$71 ;set for "71 DIR" error
D77A 4C 53 D9 JMP $D953 ;jump to error process routine
******************************* Mark current track as full
D77D 4C 9A EB JMP $EB9A ;Mark track, sector, BAM pointer as used
******************************* Set BAM pointer for current drive
D780 A6 12 LDX $12 ;get current drive number
D782 BD E8 D2 LDA $D2E8,X ;read BAM HI byte pointer
D785 85 03 STA $03 ;set HI byte to: drive 0: $41
drive 1: $42
D787 A9 00 LDA #$00
D789 85 02 STA $02 ;set BAM LO byte pointer to #$00
D78B 60 RTS
******************************* Read sector map from BAM
D78C A5 13 LDA $13 ;read current track number
D78E 0A ASL
D78F 0A ASL
D790 A8 TAY ;set track pointer in BAM
D791 B1 02 LDA ($02),Y ;read amount of free sectors on track
D793 85 07 STA $07 ;store in TEMP3
D795 A2 02 LDX #$02
D797 C8 INY
D798 B1 02 LDA ($02),Y ;read part of sector map for track
D79A 95 04 STA $04,X ;store in TEMP locations
D79C CA DEX ;all parts of sector map read ?
D79D 10 F8 BPL $D797 ;no,
D79F 20 B4 D7 JSR $D7B4 ;test for free sectors on current track
D7A2 A4 14 LDY $14 ;sector count 0 ?
D7A4 F0 0D BEQ $D7B3 ;yes,
D7A6 D0 02 BNE $D7AA ;no,
D7A8 A0 01 LDY #$01 ;set track indicator as full
D7AA 66 04 ROR $04 ;indicate sector part 3 for track as full
D7AC 66 05 ROR $05 ;indicate sector part 2 for track as full
D7AE 66 06 ROR $06 ;indicate sector part 1 for track as full
D7B0 88 DEY ;all sectors on track marked as full ?
D7B1 D0 F7 BNE $D7AA ;no,
D7B3 60 RTS
******************************* Test for available sectors on current track
D7B4 A2 00 LDX #$00
D7B6 A0 03 LDY #$03 ;all track information bytes tested for free
sector ?
D7B8 D0 06 BNE $D7C0 ;no,
D7BA E8 INX ;check next sector in current track part
D7BB 4A LSR ;all sectors in current track part tested ?
D7BC B0 FC BCS $D7BA ;yes,
D7BE D0 FB BNE $D7BB ;no,
D7C0 B9 03 00 LDA $0003,Y ;read sector part of track
D7C3 88 DEY ;last part of track tested for free sectors ?
D7C4 10 F5 BPL $D7BB ;no,
D7C6 E4 07 CPX $07 ;result part same as BAM reading for track ?
D7C8 F0 07 BEQ $D7D1 ;yes,
******************************* Directory error
D7CA A9 71 LDA #$71 ;set for "71 DIR" error
D7CC A0 00 LDY #$00
D7CE 4C 53 D9 JMP $D953 ;jump to error process routine
D7D1 60 RTS
******************************* Number of sectors for specific track table
D7D2 A2 04 LDX #$04
D7D4 DD DD D7 CMP $D7DD,X ;maximum number of sectors for current track ?
D7D7 CA DEX ;set for test of next track group
D7D8 B0 FA BCS $D7D4 ;no,
D7DA BD 99 10 LDA $1099,X ;read maximum sectors allowed for track
D7DD 60 RTS
******************************* Sectors per track group table
D7DE 24 ??? ;maximum sectors for track group #1
D7DF 1F ??? ;maximum sectors for track group #2
D7E0 19 ??? ;maximum sectors for track group #3
D7E1 12 ??? ;maximum sectors for track group #4
******************************* OK error message
D7E2 00 ;error # 00
D7E3 A0 4F CB ; oK
******************************* READ error messages
D7E6 20 ;error # 20 (BLOCK HEADER NOT FOUND)
D7E7 21 ;error # 21 (NO SYNC CHARACTER)
D7E8 22 ;error # 22 (DATA BLOCK NOT PRESENT)
D7E9 23 ;error # 23 (CHECKSUM ERROR IN DATA BLOCK)
D7EA 24 ;error # 24 (BYTE DECODING ERROR)
D7EB 27 ;error # 27 (CHECKSUM ERROR IN HEADER BLOCK)
D7EC D2 45 41 44 ;Read
D7F0 89 ;pointer to token word: error
******************************* FILE TOO LARGE error message
D7F1 52 ;error # 52
D7F2 83 ;pointer to token word: file
D7F3 20 54 4F 4F 20 4C 41 52 ; too lar
D7FB 47 C5 ;gE
******************************* RECORD NOT PRESENT error message
D7FD 50 ;error # 50
D7FE 8B ;pointer to token word: record
D7FF 06 ;pointer to token word: not
D801 20 50 52 45 53 45 4E D4 ; presenT
******************************* OVERFLOW IN RECORD error message
D808 51 ;error # 51
D809 CF 56 45 52 46 4C 4F 57 ;Overflow
D811 20 49 4E ; in
D814 8B ;pointer to token word: record
******************************* WRITE error messages
D815 25 ;error # 25 (WRITE-VERIFY ERROR)
D816 28 ;error # 28 (LONG DATA BLOCK)
D817 8A ;pointer to token word: write
D818 89 ;pointer to token word: error
******************************* WRITE PROTECT ON error message
D819 26 ;error # 26 (WRITE SENSE ON)
D81A 8A ;pointer to token word: write
D81B 20 50 52 4F 54 45 43 54 ; protect
D823 20 4F CE ; oN
******************************* DISK ID MISMATCH error message
D826 29 ;error # 29 (INVALID DISK ID)
D827 88 ;pointer to token word: disk
D828 20 49 44 ; id
D82B 85 ;pointer to token word: mismatch
******************************* SYNTAX error messages
D82C 30 ;error # 30 (GENERAL SYNTAX)
D82D 31 ;error # 31 (INVALID COMMAND)
D82E 32 ;error # 32 (LONG LINE)
D82F 33 ;error # 33 (INVALID FILE NAME)
D830 34 ;error # 34 (NO FILE GIVEN)
D831 D3 59 4E 54 41 58 ;Syntax
D837 89 ;pointer to token word: error
******************************* WRITE FILE OPEN error message
D838 60 ;error # 60
D839 8A ;pointer to token word: write
D83A 03 ;pointer to token word: file
D83B 84 ;pointer to token word: open
******************************* FILE EXISTS error message
D83C 63 ;error # 63
D83D 83 ;pointer to token word: file
D83E 20 45 58 49 53 54 D3 ; existS
******************************* FILE TYPE MISMATCH error message
D845 64 ;error # 64
D846 83 ;pointer to token word: file
D847 20 54 59 50 45 ; type
D84C 85 ;pointer to token word: mismatch
******************************* NO BLOCK error message
D84D 65 ;error # 65
D84E CE 4F 20 42 4C 4F 43 CB ;No blocK
******************************* ILLEGAL TRACK & SECTOR error messages
D856 66 ;error # 66 (ILLEGAL TRACK & SECTOR)
D857 67 ;error # 67 (ILLEGAL SYSTEM T or S)
D858 C9 4C 4C 45 47 41 4C ;Illegal
D85F 20 54 52 41 43 4B 20 4F ; track o
D867 52 20 53 45 43 54 4F D2 ;r sectoR
******************************* FILE NOT OPEN error message
D86F 61 ;error # 61
D870 83 ;pointer to token word: file
D871 06 ;pointer to token word: not
D872 84 ;pointer to token word: open
******************************* FILE NOT FOUND error message
D873 62 ;error # 62
D874 83 ;pointer to token word: file
D875 06 ;pointer to token word: not
D876 87 ;pointer to token word: found
******************************* FILE'S SCRATCHED error message
D877 01 ;error # 01
D878 83 ;pointer to token word: file
D879 53 20 53 43 52 41 54 43 ;s scratc
D881 48 45 C4 ;heD
******************************* NO CHANNEL error message
D884 70 ;error # 70 (NO CHANNEL AVAILABLE)
D885 CE 4F 20 43 48 41 4E 4E ;No chann
D88D 45 CC ;eL
******************************* DIRECTORY error message
D88F 71 ;error # 71
D890 C4 49 52 ;Dir
D893 89 ;pointer to token word: error
******************************* DISK FULL error message
D894 72 ;error # 72
D895 88 ;pointer to token word: disk
D896 20 46 55 4C CC ; fulL
******************************* DOS MISMATCH error message
D89B 73 ;error # 73 (CBM DOS V2)
D89C C3 42 4D 20 44 4F 53 ;Cbm dos
D8A3 20 56 B2 ; v2
******************************* Token word: ERROR
D8A6 09
D8A7 C5 52 52 4F D2 ;ErroR
******************************* Token word: WRITE
D8AC 0A
D8AD D7 52 49 54 C5 ;WritE
******************************* Token word: FILE
D8B2 03
D8B3 C6 49 4C C5 ;FilE
******************************* Token word: OPEN
D8B7 04
D8B8 CF 50 45 CE ;OpeN
******************************* Token word: MISMATCH
D8BC 05
D8BD CD 49 53 4D 41 54 43 C8 ;MismatcH
******************************* Token word: NOT
D8C5 06
D8C6 CE 4F D4 ;NoT
******************************* Token word: FOUND
D8C9 07
D8CA C6 4F 55 4E C4 ;FounD
******************************* Token word: DISK
D8CF 08
D8D0 C4 49 53 CB ;DisK
******************************* Token word: RECORD
D8D4 0B
D8D5 D2 45 43 4F 52 C4 ;RecorD
******************************* Transfer error message to error buffer
D8DB DD E2 D7 CMP $D7E2,X ;error number 0 ?
D8DE F0 06 BEQ $D8E6 ;yes,
D8E0 E8 INX
D8E1 E0 F9 CPX #$F9 ;end of error message table ?
D8E3 90 F6 BCC $D8DB ;no, skip this error message
D8E5 60 RTS
******************************* Test for begin/end of error message
D8E6 E8 INX
D8E7 BD E2 D7 LDA $D7E2,X ;bit 7 of character set ?
D8EA 10 FA BPL $D8E6 ;no,
D8EC 29 7F AND #$7F
D8EE C9 10 CMP #$10 ;token needs to be transferred ?
D8F0 90 15 BCC $D907 ;yes,
D8F2 91 47 STA ($47),Y ;transfer character to buffer
D8F4 C8 INY
D8F5 E8 INX
D8F6 BD E2 D7 LDA $D7E2,X ;bit 7 of character set ?
D8F9 10 F3 BPL $D8EE ;no,
D8FB 48 PHA
D8FC 29 7F AND #$7F
D8FE C9 10 CMP #$10 ;token needs to be transferred ?
D900 90 06 BCC $D908 ;yes,
D902 91 47 STA ($47),Y ;transfer character to buffer
D904 C8 INY
D905 68 PLA
D906 60 RTS
******************************* Transfer TOKEN to error message buffer
D907 48 PHA
D908 48 PHA
D909 A9 20 LDA #$20
D90B 91 47 STA ($47),Y ;transfer a blank/space in buffer
D90D C8 INY
D90E 68 PLA
D90F 86 07 STX $07 ;store current position in error message
D911 A2 C4 LDX #$C4 ;set for beginning of token table
D913 20 DB D8 JSR $D8DB ;transfer token to error buffer
D916 A6 07 LDX $07 ;reset position in error message
D918 68 PLA ;another token ?
D919 10 DA BPL $D8F5 ;no,
D91B 60 RTS
******************************* Controller error entry point
D91C 48 PHA ;save controller status code
D91D 86 A1 STX $A1 ;store job number
D91F 8A TXA
D920 0A ASL
D921 0A ASL
D922 0A ASL
D923 AA TAX
D924 BD 23 10 LDA $1023,X ;read track position of head
D927 85 13 STA $13 ;set as current track
D929 BD 24 10 LDA $1024,X ;read sector position of head
D92C 85 14 STA $14 ;set as current sector
D92E 68 PLA ;read controller status code
D92F 29 0F AND #$0F ;is controller status code 0 ?
D931 D0 02 BNE $D935 ;no,
D933 A9 06 LDA #$06 ;set for error code #$06 (decimal 6)
D935 09 20 ORA #$20 ;add #$20 (decimal 32) to error code
D937 AA TAX ;transfer code
D938 CA DEX
D939 CA DEX
D93A 8A TXA ;transfer subtracted code
D93B 48 PHA ;save error code number
D93C AD 7A 43 LDA $437A ;read command number
D93F C9 01 CMP #$01 ;is it OPEN or VALIDATE ?
D941 D0 0F BNE $D952 ;no,
D943 A9 FF LDA #$FF
D945 8D 7A 43 STA $437A ;set command code to #$FF
D948 68 PLA ;read error code number
D949 20 D4 D9 JSR $D9D4 ;generate error message
D94C 20 FA EC JSR $ECFA ;load BAM
D94F 4C 56 D9 JMP $D956 ;jump to error process routine
******************************* Process error
D952 68 PLA ;read error code number
D953 20 D4 D9 JSR $D9D4 ;generate error message
******************************* Clear command buffer, set LED's
D956 20 B8 DB JSR $DBB8 ;erase command buffer
D959 A9 00 LDA #$00
D95B 8D 73 43 STA $4373 ;set error word for recovery to 0
D95E AD 82 02 LDA $0282 ;read LED status: bit 0-2 = device number
3-5 = LED status
D961 09 20 ORA #$20 ;set for ERROR LED on
D963 8D 82 02 STA $0282 ;turn on LED: bit 0-2 = device number
3 = LED drive 1
4 = LED drive 0
5 = ERROR LED
D966 20 D3 F0 JSR $F0D3 ;free internal channels
D969 A9 00 LDA #$00
D96B 85 45 STA $45 ;set CMD low pointer to 0
D96D A2 FF LDX #$FF
D96F 9A TXS ;purge stack
******************************* Talker error recovery
D970 A5 17 LDA $17 ;read original secondary address
D972 29 1F AND #$1F ;test channel validity: 0-31
D974 85 16 STA $16 ;store result as current secondary address
D976 C9 0F CMP #$0F ;result 15, command channel ?
D978 F0 2B BEQ $D9A5 ;yes,
D97A 78 SEI
D97B A5 0E LDA $0E ;is LISTENER active ?
D97D D0 11 BNE $D990 ;yes,
D97F A5 0F LDA $0F ;is TALKER active ?
D981 F0 22 BEQ $D9A5 ;no,
D983 20 69 ED JSR $ED69 ;open channel for read
D986 AD 80 02 LDA $0280 ;read current signal status
D989 09 10 ORA #$10 ;set for DAV signal
D98B 8D 80 02 STA $0280 ;set DAV line
D98E D0 0D BNE $D99D
******************************* Listener error recovery
D990 20 84 ED JSR $ED84 ;open channel for write
D993 A9 04 LDA #$04 ;set for RFD signal
D995 0D 80 02 ORA $0280 ;read current signal status
D998 29 FE AND #$FE
D99A 8D 80 02 STA $0280 ;set RFD line
D99D 20 A1 ED JSR $EDA1 ;valid file type ?
D9A0 B0 03 BCS $D9A5 ;no,
D9A2 20 9F EE JSR $EE9F ;free channel
D9A5 4C A6 D4 JMP $D4A6 ;jump to idle loop
******************************* Convert HEX to BCD
D9A8 AA TAX ;transfer HEX value to .X register
D9A9 A9 00 LDA #$00
D9AB F8 SED ;set decimal mode
D9AC E0 00 CPX #$00 ;.X register value 0 ?
D9AE F0 07 BEQ $D9B7 ;yes,
D9B0 18 CLC ;clear carry flags
D9B1 69 01 ADC #$01 ;increment .ACC
D9B3 CA DEX ;decrement value in .X register
D9B4 4C AC D9 JMP $D9AC ;continue with conversion routine
******************************* Convert BCD to ASCII
D9B7 D8 CLD ;clear decimal mode
D9B8 AA TAX ;transfer BCD value to .X register
D9B9 4A LSR
D9BA 4A LSR
D9BB 4A LSR
D9BC 4A LSR
D9BD 20 C1 D9 JSR $D9C1 ;convert most significant digit to ASCII
D9C0 8A TXA
D9C1 29 0F AND #$0F ;erase top 4 bits
D9C3 09 30 ORA #$30 ;add 0
D9C5 91 47 STA ($47),Y ;store result in buffer
D9C7 C8 INY ;do next part of BCD number
D9C8 60 RTS
******************************* Set for OK error message
D9C9 20 42 DA JSR $DA42 ;erase error flag
D9CC A9 00 LDA #$00
D9CE A0 00 LDY #$00
D9D0 84 13 STY $13 ;set current track to 0
D9D2 84 14 STY $14 ;set current sector to 0
******************************* Set up error message in error buffer
D9D4 A0 00 LDY #$00
D9D6 A2 DC LDX #$DC
D9D8 86 47 STX $47 ;set LO byte for error buffer
D9DA A2 43 LDX #$43
D9DC 86 48 STX $48 ;set HI byte for error buffer
D9DE 20 B8 D9 JSR $D9B8 ;convert error number to ASCII and store in
error buffer
D9E1 A9 2C LDA #$2C
D9E3 91 47 STA ($47),Y ;store comma after error number
D9E5 C8 INY
D9E6 AD DC 43 LDA $43DC ;read first byte of error number
D9E9 85 BC STA $BC ;send to IEEE port
D9EB 8A TXA
D9EC A2 00 LDX #$00
D9EE 20 DB D8 JSR $D8DB ;transfer error message to error buffer
D9F1 A9 2C LDA #$2C
D9F3 91 47 STA ($47),Y ;store comma after error message
D9F5 C8 INY
D9F6 A5 13 LDA $13 ;read track number
D9F8 20 A8 D9 JSR $D9A8 ;convert track number to ASCII and store in
error buffer
D9FB A9 2C LDA #$2C
D9FD 91 47 STA ($47),Y ;store comma (,) after error number
D9FF C8 INY
DA00 A5 14 LDA $14 ;read sector number
DA02 20 A8 D9 JSR $D9A8 ;convert sector number to ASCII and store in
error buffer
DA05 88 DEY
DA06 98 TYA ;mark end of error message
DA07 18 CLC
DA08 69 DC ADC #$DC ;calculate length/end of error message
DA0A 85 C4 STA $C4 ;store in Channel Last character pointer
DA0C E6 47 INC $47 ;set for IEEE transfer of all bytes in buffer
DA0E A9 88 LDA #$88
DA10 85 9F STA $9F ;set channel to TALK
DA12 60 RTS
******************************* Mark a sector as free on a track and BAM
DA13 20 80 D7 JSR $D780 ;set BAM for current drive
DA16 20 AF EB JSR $EBAF ;erase bit for sector in BAM
DA19 38 SEC ;block freed ?
DA1A D0 0F BNE $DA2B ;yes,
DA1C B1 02 LDA ($02),Y ;read current track map from BAM
DA1E 1D C9 EB ORA $EBC9,X ;mark sector as free in map
DA21 91 02 STA ($02),Y ;store new track map in BAM
DA23 A4 04 LDY $04 ;read BLOCK FREE counter
DA25 B1 02 LDA ($02),Y ;read current track count
DA27 69 00 ADC #$00 ;add free block
DA29 91 02 STA ($02),Y ;store new track count
DA2B 60 RTS
******************************* Turn on activity LED specified by drive
DA2C A9 E7 LDA #$E7
DA2E 2D 82 02 AND $0282 ;erase LED bits: bit 0-2 = device number
3-5 = LED status
DA31 48 PHA
DA32 A5 12 LDA $12 ;drive 0 under use ?
DA34 F0 05 BEQ $DA3B ;yes,
DA36 68 PLA
DA37 09 08 ORA #$08 ;drive 1 under use ?
DA39 D0 03 BNE $DA3E ;yes,
DA3B 68 PLA
DA3C 09 10 ORA #$10 ;set for LED drive 0
DA3E 8D 82 02 STA $0282 ;turn on specified LED: bit 0-2 = device number
3-5 = LED status
DA41 60 RTS
******************************* Turn off error LED
DA42 AD 82 02 LDA $0282 ;read LED status: bit 0-2 = device number
3-5 = LED status
DA45 29 DF AND #$DF
DA47 8D 82 02 STA $0282 ;turn off LED: bit 0-2 = device number
3-5 = LED status
DA4A 60 RTS
******************************* Directory loading function, get the buffer
and get it started
DA4B A9 00 LDA #$00
DA4D 85 16 STA $16 ;set secondary address to 0
DA4F A9 01 LDA #$01
DA51 20 5E EE JSR $EE5E ;set pointer position in appropriate buffer
DA54 A9 00 LDA #$00
DA56 20 C1 F0 JSR $F0C1 ;reset buffer to null
DA59 A6 15 LDX $15 ;read number of channels
DA5B A9 00 LDA #$00
DA5D 95 BD STA $BD,X ;clear pointer to end of buffer entrance
DA5F 20 98 FA JSR $FA98 ;get number of buffers chosen
DA62 AA TAX
DA63 A5 12 LDA $12 ;read current drive number
DA65 9D 4E 43 STA $434E,X ;arrange drive table buffer
DA68 A9 01 LDA #$01
DA6A 20 B1 EC JSR $ECB1 ;write LO byte of BASIC load location
DA6D A9 04 LDA #$04
DA6F 20 B1 EC JSR $ECB1 ;write HI byte of BASIC load location
DA72 A9 01 LDA #$01
DA74 20 B1 EC JSR $ECB1 ;write fill byte for line pointer
DA77 20 B1 EC JSR $ECB1 ;write fill byte for line pointer
DA7A AD 77 43 LDA $4377 ;get drive number
DA7D 20 B1 EC JSR $ECB1 ;write as LO byte for line number
DA80 A9 00 LDA #$00
DA82 20 B1 EC JSR $ECB1 ;write HI byte for line number
DA85 20 03 DB JSR $DB03 ;transfer disk name to buffer
DA88 20 98 FA JSR $FA98 ;get current buffer number
DA8B 0A ASL ;double,
DA8C AA TAX
DA8D D6 29 DEC $29,X ;decrement buffer position
DA8F D6 29 DEC $29,X ;decrement buffer position
DA91 A9 00 LDA #$00
DA93 20 B1 EC JSR $ECB1 ;write end of BASIC
DA96 A9 01 LDA #$01
DA98 20 B1 EC JSR $ECB1 ;write BASIC line place holder
DA9B 20 B1 EC JSR $ECB1 ;write BASIC line place holder
DA9E 20 BF E0 JSR $E0BF ;read entry from directory
DAA1 90 2C BCC $DACF ;branch if all entries processed
DAA3 AD 77 43 LDA $4377 ;read LO byte of file block count
DAA6 20 B1 EC JSR $ECB1 ;write as LO byte of BASIC line number
DAA9 AD 78 43 LDA $4378 ;read HI byte of file block count
DAAC 20 B1 EC JSR $ECB1 ;write as HI byte of BASIC line number
DAAF 20 03 DB JSR $DB03 ;transfer directory entry to buffer
DAB2 A9 00 LDA #$00
DAB4 20 B1 EC JSR $ECB1 ;write END-OF-BASIC LINE byte
DAB7 D0 DD BNE $DA96 ;continue if buffer memory available
DAB9 20 98 FA JSR $FA98 ;read current number of buffers in use
DABC 0A ASL ;double current amount
DABD AA TAX ;preserve current character pointer
DABE A9 00 LDA #$00
DAC0 95 29 STA $29,X ;reset position for current buffer to #$00
DAC2 A9 88 LDA #$88
DAC4 A4 15 LDY $15 ;read current channel number
DAC6 8D 46 43 STA $4346 ;set flag to indicate more directory to come
DAC9 99 98 00 STA $0098,Y ;set channel mode to read
DACC A5 18 LDA $18 ;read data byte
DACE 60 RTS
******************************* Build last line of directory
DACF AD 77 43 LDA $4377 ;read LO byte of free block count
DAD2 20 B1 EC JSR $ECB1 ;write as LO byte of BASIC line number
DAD5 AD 78 43 LDA $4378 ;read HI byte of free block count
DAD8 20 B1 EC JSR $ECB1 ;write as HI byte of BASIC line number
DADB 20 03 DB JSR $DB03 ;write BLOCKS FREE. to buffer
DADE 20 98 FA JSR $FA98 ;read current number of buffers in use
DAE1 0A ASL ;double current amount
DAE2 AA TAX ;preserve current character pointer
DAE3 D6 29 DEC $29,X ;decrement pointer position
DAE5 D6 29 DEC $29,X ;decrement pointer position
DAE7 A9 00 LDA #$00
DAE9 20 B1 EC JSR $ECB1 ;write END-OF-BASIC program byte 1
DAEC 20 B1 EC JSR $ECB1 ;write END-OF-BASIC program byte 2
DAEF 20 B1 EC JSR $ECB1 ;write END-OF-BASIC program byte 3
DAF2 20 98 FA JSR $FA98 ;read current buffer number
DAF5 0A ASL ;double current buffer number
DAF6 A8 TAY
DAF7 B9 29 00 LDA $0029,Y ;read remaining bytes in buffer
DAFA A6 15 LDX $15 ;set as pointer to amount of remaining bytes
DAFC 95 BD STA $BD,X ;set pointer to last character position
DAFE D6 BD DEC $BD,X ;decrement pointer by one
DB00 4C B9 DA JMP $DAB9 ;set channel status for exit
******************************* Transmit directory line to current buffer
DB03 A0 00 LDY #$00
DB05 B9 B4 41 LDA $41B4,Y ;read character from directory buffer
DB08 20 B1 EC JSR $ECB1 ;write to current buffer
DB0B C8 INY
DB0C C0 1B CPY #$1B ;directory line transmitted ?
DB0E D0 F5 BNE $DB05 ;no,
DB10 60 RTS
******************************* Get byte from directory
DB11 20 B3 ED JSR $EDB3 ;get byte from file, END-OF-FILE ?
DB14 F0 01 BEQ $DB17 ;yes,
DB16 60 RTS
DB17 85 18 STA $18 ;save last data byte
DB19 A4 15 LDY $15 ;get number of channels
DB1B B9 BD 00 LDA $00BD,Y ;all bytes of data transferred ?
DB1E F0 08 BEQ $DB28 ;yes,
DB20 A9 80 LDA #$80 ;set for READ/EOI
DB22 99 98 00 STA $0098,Y ;set channel status
DB25 A5 18 LDA $18 ;get last data byte
DB27 60 RTS
DB28 48 PHA ;store last data byte
DB29 20 96 DA JSR $DA96 ;produce directory line
DB2C 68 PLA ;read last data byte
DB2D 60 RTS
******************************* Calculate number of free blocks
DB2E A6 12 LDX $12 ;read current drive number
DB30 BD E8 D2 LDA $D2E8,X ;get high byte pointer for drive BAM
DB33 85 05 STA $05 ;store as TEMP1 (buffer pointer HI)
DB35 A0 04 LDY #$04
DB37 A9 00 LDA #$00
DB39 85 04 STA $04 ;store as TEMP2 (buffer pointer LO)
DB3B AA TAX
DB3C 18 CLC
DB3D 71 04 ADC ($04),Y ;add free sectors to counter, over #$FF
(decimal 255) ?
DB3F 90 01 BCC $DB42 ;no,
DB41 E8 INX ;increment high byte of counter
DB42 C8 INY ;skip FREE sectors on track byte
DB43 C8 INY ;skip sectors 0-7
DB44 C8 INY ;skip sectors 8-15
DB45 C8 INY ;skip sectors 16-23
DB46 C0 48 CPY #$48 ;is this track 18 ?
DB48 F0 F8 BEQ $DB42 ;yes,
DB4A C0 90 CPY #$90 ;is this the last track ?
DB4C D0 EE BNE $DB3C ;no,
DB4E 8D 77 43 STA $4377 ;store LO byte of free blocks counter
DB51 8E 78 43 STX $4378 ;store HI byte of free blocks counter
DB54 60 RTS
******************************* Parse and execute string in command buffer
DB55 20 C9 D9 JSR $D9C9 ;produce OK error message
DB58 A5 17 LDA $17 ;get last secondary address, close command ?
DB5A 10 09 BPL $DB65 ;yes,
DB5C 29 0F AND #$0F ;set for command channel test
DB5E C9 0F CMP #$0F ;is it the command channel
DB60 F0 03 BEQ $DB65 ;yes,
DB62 4C 79 F2 JMP $F279 ;jump to OPEN a channel routine
DB65 20 B0 DC JSR $DCB0 ;set parameters for command processing
DB68 B1 45 LDA ($45),Y ;get character from command buffer
DB6A 8D 7B 43 STA $437B ;store it
DB6D A2 0A LDX #$0A ;set .X register for number of disk commands
DB6F BD A1 D2 LDA $D2A1,X ;read possible commands table
DB72 CD 7B 43 CMP $437B ;is this the desired command ?
DB75 F0 08 BEQ $DB7F ;yes,
DB77 CA DEX ;last possible command in table checked ?
DB78 10 F5 BPL $DB6F ;no,
DB7A A9 31 LDA #$31 ;set for "31 SYNTAX ERROR", invalid command
DB7C 4C C3 DB JMP $DBC3 ;jump to process command error routine
DB7F 8E 7A 43 STX $437A ;save command number
DB82 E0 08 CPX #$08 ;is desired command "RENAME" ?
DB84 90 03 BCC $DB89 ;no,
DB86 20 E9 DB JSR $DBE9 ;check syntax of command
DB89 AE 7A 43 LDX $437A ;get command number
DB8C BD AC D2 LDA $D2AC,X ;read LO byte of command jump address
DB8F 85 04 STA $04 ;set as TEMP0
DB91 BD B7 D2 LDA $D2B7,X ;read HI byte of command jump address
DB94 85 05 STA $05 ;set as TEMP1
DB96 6C 04 00 JMP ($0004) ;jump to calculated command address
******************************* Successful command termination
DB99 AD 73 43 LDA $4373 ;is there an error word to recover ?
DB9C D0 25 BNE $DBC3 ;yes,
DB9E A0 00 LDY #$00 ;set for "OK" message
DBA0 98 TYA
******************************* Clear command buffer
DBA1 84 13 STY $13 ;set track to #$00
DBA3 84 14 STY $14 ;set sector to #$00
DBA5 84 45 STY $45 ;set LO byte of command buffer to #$00
DBA7 20 D4 D9 JSR $D9D4 ;produce "OK" error message
DBAA 20 42 DA JSR $DA42 ;turn off error LED
DBAD A5 12 LDA $12 ;read current drive number
DBAF 8D 94 43 STA $4394 ;set as last drive without error
DBB2 20 B8 DB JSR $DBB8 ;clear command input buffer
DBB5 4C D3 F0 JMP $F0D3 ;close internal read/write channels
******************************* Clear command input buffer
DBB8 A0 39 LDY #$39 ;set for overwriting of 57 character positions
DBBA A9 00 LDA #$00
DBBC 99 00 43 STA $4300,Y ;set position to #$00
DBBF 88 DEY ;all positions done ?
DBC0 10 FA BPL $DBBC ;no,
DBC2 60 RTS
******************************* Command level error processing
DBC3 A0 00 LDY #$00
DBC5 84 13 STY $13 ;set track to #$00
DBC7 84 14 STY $14 ;set sector to #$00
DBC9 4C 53 D9 JMP $D953 ;jump to process error routines
******************************* Simple parser routine
DBCC A2 00 LDX #$00
DBCE 8E 80 43 STX $4380 ;clear pointer to drive number position
DBD1 A9 3A LDA #$3A
DBD3 20 63 DC JSR $DC63 ;has colon (:) character been found ?
DBD6 F0 05 BEQ $DBDD ;no,
DBD8 88 DEY ;step pointer back to colon (:)
DBD9 88 DEY ;step pointer back to drive number
DBDA 8C 80 43 STY $4380 ;store position number for drive number
DBDD 4C 5E DD JMP $DD5E ;jump to set drive number and turn on LED
******************************* Parse colon
DBE0 A0 00 LDY #$00 ;set start position for search
DBE2 A2 00 LDX #$00 ;set number of filenames found
DBE4 A9 3A LDA #$3A ;set for colon (:) search
DBE6 4C 63 DC JMP $DC63 ;search through input command buffer
******************************* Set up command structure image and file
stream pointer
DBE9 20 E0 DB JSR $DBE0 ;colon (:) in input command buffer found ?
DBEC D0 05 BNE $DBF3 ;yes,
DBEE A9 34 LDA #$34 ;set for "34 SYNTAX ERROR", no file given
DBF0 4C C3 DB JMP $DBC3 ;jump to process command error routine
DBF3 88 DEY ;step pointer back to colon (:)
DBF4 88 DEY ;step pointer back to drive number
DBF5 8C 80 43 STY $4380 ;store position number for drive number
DBF8 8A TXA ;has a filename been found ?
DBF9 D0 F3 BNE $DBEE ;no,
DBFB A9 3D LDA #$3D ;set for equal (=) search
DBFD 20 63 DC JSR $DC63 ;search through input command buffer
DC00 8A TXA ;has a filename been found ?
DC01 F0 02 BEQ $DC05 ;yes,
DC03 A9 40 LDA #$40 ;set bit 6 as flag for more files
DC05 09 21 ORA #$21 ;set bits 0 & 5 to indicate 1st filename
DC07 8D 91 43 STA $4391 ;save bit flag
DC0A E8 INX
DC0B 8E 7D 43 STX $437D ;set file stream 1 count
DC0E 8E 7E 43 STX $437E ;set file stream 2 count
DC11 AD 90 43 LDA $4390 ;pattern (* ?) presence flag active ?
DC14 F0 0D BEQ $DC23 ;no,
DC16 A9 80 LDA #$80
DC18 0D 91 43 ORA $4391
DC1B 8D 91 43 STA $4391 ;set flag in file stream image
DC1E A9 00 LDA #$00
DC20 8D 90 43 STA $4390 ;clear search routine wildcard flag
DC23 98 TYA ;end of command line found ?
DC24 F0 29 BEQ $DC4F ;yes,
DC26 9D 80 43 STA $4380,X ;save position of filename
DC29 AD 7D 43 LDA $437D ;read file stream 1 count
DC2C 8D 7F 43 STA $437F ;set stream as number for second naming
DC2F A9 8D LDA #$8D ;set for SHIFTed RETURN search
DC31 20 63 DC JSR $DC63 ;search through input command buffer
DC34 E8 INX
DC35 8E 7E 43 STX $437E ;store current number of commas (,) found
DC38 CA DEX
DC39 AD 90 43 LDA $4390 ;pattern (* ?) presence flag active ?
DC3C F0 02 BEQ $DC40 ;no,
DC3E A9 08 LDA #$08 ;set for: 0000 1000
DC40 EC 7D 43 CPX $437D ;any more filenames found ?
DC43 F0 02 BEQ $DC47 ;no,
DC45 09 04 ORA #$04 ;set filenames after equal (=) flag
DC47 09 03 ORA #$03 ;set flag for equal (=) character on hand
DC49 4D 91 43 EOR $4391 ;combine previous flags
DC4C 8D 91 43 STA $4391 ;set as new syntax flag
DC4F AD 91 43 LDA $4391 ;read syntax flag for command
DC52 AE 7A 43 LDX $437A ;compare on hand command numbers
DC55 3D BB D2 AND $D2BB,X ;does command numbers match allowable syntax ?
DC58 D0 01 BNE $DC5B ;no,
DC5A 60 RTS
DC5B 8D 73 43 STA $4373 ;save incorrect syntax type
DC5E A9 30 LDA #$30 ;set for "30 SYNTAX ERROR", general syntax
DC60 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Look for special characters
DC63 8D 7B 43 STA $437B ;store character to go under parse
DC66 CC 79 43 CPY $4379 ;is this the end of the command string ?
DC69 B0 2F BCS $DC9A ;yes,
DC6B B1 45 LDA ($45),Y ;get character from input command buffer
DC6D C8 INY ;set pointer for next character
DC6E CD 7B 43 CMP $437B ;character found in input command buffer ?
DC71 F0 29 BEQ $DC9C ;yes,
DC73 C9 2A CMP #$2A ;is it a pattern match (*) ?
DC75 F0 04 BEQ $DC7B ;yes,
DC77 C9 3F CMP #$3F ;is it a wildcard (?) ?
DC79 D0 03 BNE $DC7E ;no,
DC7B EE 90 43 INC $4390 ;set wildcard flag
DC7E C9 2C CMP #$2C ;is it a comma (,) ?
DC80 D0 E4 BNE $DC66 ;no,
DC82 98 TYA ;save comma (,) position
DC83 9D 81 43 STA $4381,X ;set start position of next parameter
DC86 AD 90 43 LDA $4390 ;read wildcard flag
DC89 29 7F AND #$7F ;clear wildcard flag, found a joker ?
DC8B F0 08 BEQ $DC95 ;no,
DC8D A9 80 LDA #$80 ;set wildcard flag
DC8F 9D 86 43 STA $4386,X ;identify name as filename with joker
DC92 8D 90 43 STA $4390 ;set wildcard identifier
DC95 E8 INX ;increment number of parameters found
DC96 E0 04 CPX #$04 ;five files maximum opened ?
DC98 90 CC BCC $DC66 ;no,
DC9A A0 00 LDY #$00
DC9C AD 79 43 LDA $4379 ;read length of command line
DC9F 9D 81 43 STA $4381,X ;save as start position of last parameter
DCA2 AD 90 43 LDA $4390 ;get wildcard flag of last filename
DCA5 29 7F AND #$7F ;wildcard in parameter on hand ?
DCA7 F0 05 BEQ $DCAE ;no,
DCA9 A9 80 LDA #$80 ;set wildcard flag
DCAB 9D 86 43 STA $4386,X ;identify name as filename with joker
DCAE 98 TYA ;set current position in input line
DCAF 60 RTS
******************************* Set all flags and look at command string
DCB0 A4 45 LDY $45 ;is LO byte of input buffer set to #$00 ?
DCB2 F0 14 BEQ $DCC8 ;yes,
DCB4 88 DEY ;adjust buffer pointer, #$00 ?
DCB5 F0 10 BEQ $DCC7 ;yes,
DCB7 B9 00 43 LDA $4300,Y ;get character from buffer
DCBA C9 0D CMP #$0D ;is it a RETURN ?
DCBC F0 0A BEQ $DCC8 ;yes,
DCBE 88 DEY ;step back pointer
DCBF B9 00 43 LDA $4300,Y ;get character from buffer
DCC2 C9 0D CMP #$0D ;is it a RETURN ?
DCC4 F0 02 BEQ $DCC8 ;yes,
DCC6 C8 INY ;step pointer foward
DCC7 C8 INY ;step pointer foward, back to current position
DCC8 8C 79 43 STY $4379 ;save pointer position in command
DCCB C0 3B CPY #$3B ;end of command buffer reached ?
DCCD A0 FF LDY #$FF ;command line too long ?
DCCF 90 08 BCC $DCD9 ;no,
DCD1 8C 7A 43 STY $437A ;save incorrect syntax type
DCD4 A9 32 LDA #$32 ;set for "32 SYNTAX ERROR", long line
DCD6 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Command reset: clear variables, tables
DCD9 A0 00 LDY #$00
DCDB 98 TYA
DCDC 85 45 STA $45 ;set LO byte of input command buffer
DCDE 8D 4B 43 STA $434B ;set record size to #$00
DCE1 85 C5 STA $C5 ;set active file type to #$00
DCE3 8D 9C 43 STA $439C ;set match by type flag to #$00
DCE6 85 81 STA $81 ;set file stream 1 pointer to #$00
DCE8 8D 7F 43 STA $437F ;set file stream 3 count to #$00
DCEB 8D 7D 43 STA $437D ;set file stream 1 count to #$00
DCEE 8D 7E 43 STA $437E ;set file stream 2 count to #$00
DCF1 8D 90 43 STA $4390 ;set pattern presence flag to #$00
DCF4 8D 73 43 STA $4373 ;set error recovery word to #$00
DCF7 A2 05 LDX #$05
DCF9 9D 7F 43 STA $437F,X ;set filename table to #$00
DCFC 95 85 STA $85,X ;set directory table to #$00
DCFE 95 8A STA $8A,X ;set file data table to #$00
DD00 9D 85 43 STA $4385,X ;set track number of file table to #$00
DD03 9D 8A 43 STA $438A,X ;set sector number of file table to #$00
DD06 CA DEX ;maximum five possible files opened, set ?
DD07 D0 F0 BNE $DCF9 ;no,
DD09 60 RTS
******************************* Set 1st drive and table pointers
DD0A AD 7E 43 LDA $437E ;read file stream 2 count
DD0D 8D 7D 43 STA $437D ;set as file stream 1 count
DD10 A9 01 LDA #$01
DD12 8D 7E 43 STA $437E ;set file stream 2 count to #$01
DD15 8D 7F 43 STA $437F ;set file stream 3 count to #$01
DD18 AC 94 43 LDY $4394 ;read last drive without error
******************************* Set drive number
DD1B A2 00 LDX #$00
DD1D 86 81 STX $81 ;set file stream 1 pointer
DD1F BD 80 43 LDA $4380,X ;find start position of name in buffer
DD22 20 34 DD JSR $DD34 ;get drive number from buffer
DD25 A6 81 LDX $81 ;read number of current file parameters
DD27 9D 80 43 STA $4380,X ;save position in command string
DD2A 98 TYA
DD2B 95 8B STA $8B,X ;set drive number for file
DD2D E8 INX ;do next file
DD2E EC 7E 43 CPX $437E ;all files ready for work ?
DD31 90 EA BCC $DD1D ;no,
DD33 60 RTS
******************************* Get drive number from command string
DD34 AA TAX ;set .X register to position of filename
DD35 A9 3A LDA #$3A ;set for colon (:) search
DD37 DD 01 43 CMP $4301,X ;is it a colon ?
DD3A F0 0C BEQ $DD48 ;yes,
DD3C DD 00 43 CMP $4300,X ;pointer pointing at colon (:) ?
DD3F D0 16 BNE $DD57 ;no,
DD41 E8 INX
DD42 98 TYA ;read drive number
DD43 29 01 AND #$01 ;find which drive to be active
DD45 A8 TAY ;set .Y register as drive to be used
DD46 8A TXA ;set .X register to current position in buffer
DD47 60 RTS
DD48 BD 00 43 LDA $4300,X ;read drive number from command string
DD4B E8 INX ;skip drive indicator byte
DD4C E8 INX ;skip colon (:) byte
DD4D C9 30 CMP #$30 ;is it drive 0 ?
DD4F F0 F2 BEQ $DD43 ;yes,
DD51 C9 31 CMP #$31 ;is it drive 1 ?
DD53 F0 EE BEQ $DD43 ;yes,
DD55 D0 EB BNE $DD42 ;incorrect drive number
DD57 98 TYA ;transfer drive number found
DD58 09 80 ORA #$80 ;set improper drive flag
DD5A 29 81 AND #$81 ;is it drive 0 or 1 ?
DD5C D0 E7 BNE $DD45 ;no,
******************************* Set drive from any configuration
DD5E A9 00 LDA #$00
DD60 8D 91 43 STA $4391 ;clear file stream image flag
DD63 AC 80 43 LDY $4380 ;get current position in input buffer
DD66 B1 45 LDA ($45),Y ;read character from input buffer
DD68 20 B5 DD JSR $DDB5 ;is it a legal drive number ?
DD6B 10 12 BPL $DD7F ;yes,
DD6D C8 INY ;move pointer in input buffer
DD6E CC 79 43 CPY $4379 ;end of command string ?
DD71 B0 06 BCS $DD79 ;yes,
DD73 AC 79 43 LDY $4379 ;set pointer to end of command string
DD76 88 DEY ;last character in input buffer a command ?
DD77 D0 ED BNE $DD66 ;no,
DD79 CE 91 43 DEC $4391 ;set file stream image to colon (:) position
DD7C AD 94 43 LDA $4394 ;read last drive number without error
DD7F 29 01 AND #$01
DD81 85 12 STA $12 ;set as current drive number
DD83 4C 2C DA JMP $DA2C ;jump to turn on specified LED routine
******************************* Toggle drive number
DD86 A5 12 LDA $12 ;read current drive number
DD88 49 01 EOR #$01
DD8A 29 01 AND #$01 ;switch drive
DD8C 85 12 STA $12 ;set as new drive
DD8E 60 RTS
******************************* Set pointer to one file stream and check
type
DD8F A0 00 LDY #$00 ;set for first filename in table
DD91 AD 7D 43 LDA $437D ;read position of filename
DD94 CD 7E 43 CMP $437E ;same as file type identifier position
DD97 F0 16 BEQ $DDAF ;yes,
DD99 CE 7E 43 DEC $437E ;set pointer to file type
DD9C AC 7E 43 LDY $437E ;read file type
DD9F B9 80 43 LDA $4380,Y ;take pointer to end of filename
DDA2 A8 TAY
DDA3 B1 45 LDA ($45),Y ;get file type from input buffer
DDA5 A0 04 LDY #$04 ;set for test of possible file types
DDA7 D9 D4 D2 CMP $D2D4,Y ;is this the correct file type ?
DDAA F0 03 BEQ $DDAF ;yes,
DDAC 88 DEY ;all possible file types checked ?
DDAD D0 F8 BNE $DDA7 ;no,
DDAF 98 TYA ;transfer file type
DDB0 0A ASL
DDB1 8D 9C 43 STA $439C ;set file type flag
DDB4 60 RTS
******************************* Test drive number validity
DDB5 C9 30 CMP #$30 ;is it drive 0 ?
DDB7 F0 06 BEQ $DDBF ;yes
DDB9 C9 31 CMP #$31 ;is it drive 1 ?
DDBB F0 02 BEQ $DDBF ;yes,
DDBD 09 80 ORA #$80 ;set improper drive flag
DDBF 29 81 AND #$81 ;set validity status of drive number
DDC1 60 RTS
******************************* Auto initialization routine
DDC2 A2 FF LDX #$FF
DDC4 8E 9E 43 STX $439E ;clear job error flag
DDC7 20 DF EC JSR $ECDF ;set head to track 18, sector 0
DDCA C9 03 CMP #$03 ;was SYNC mark located ?
DDCC F0 07 BEQ $DDD5 ;yes,
DDCE C9 02 CMP #$02 ;was HEADER BLOCK found ?
DDD0 90 13 BCC $DDE5 ;yes,
DDD2 4C 1C D9 JMP $D91C ;jump to controller error routine
DDD5 AC 92 43 LDY $4392 ;has drive number changed ?
DDD8 F0 F8 BEQ $DDD2 ;yes,
DDDA A9 00 LDA #$00
DDDC 8D 92 43 STA $4392 ;clear active drive search flag
DDDF 20 86 DD JSR $DD86 ;toggle drive
DDE2 4C C2 DD JMP $DDC2 ;do next drive
DDE5 8A TXA
DDE6 0A ASL
DDE7 0A ASL
DDE8 0A ASL
DDE9 A8 TAY
DDEA A5 12 LDA $12 ;read current drive number
DDEC 0A ASL
DDED AA TAX
DDEE B9 21 10 LDA $1021,Y ;read ID1 from disk
DDF1 DD 40 43 CMP $4340,X ;same as in memory ?
DDF4 D0 0E BNE $DE04 ;no,
DDF6 B9 22 10 LDA $1022,Y ;read ID2 from disk
DDF9 DD 41 43 CMP $4341,X ;same as in memory ?
DDFC D0 06 BNE $DE04 ;no,
DDFE A5 A1 LDA $A1 ;get current job number
DE00 20 92 EC JSR $EC92 ;set header for current buffer
DE03 60 RTS
DE04 4C FA EC JMP $ECFA ;jump to initialize drive routine
******************************* Optimum search for lookup and find file
DE07 A9 00 LDA #$00
DE09 85 04 STA $04 ;clear TEMP0
DE0B 8D 93 43 STA $4393 ;clear drive search flag
DE0E 48 PHA
DE0F AE 7E 43 LDX $437E ;read file stream 2 count
DE12 68 PLA
DE13 05 04 ORA $04 ;set for last entry
DE15 48 PHA
DE16 A9 01 LDA #$01
DE18 85 04 STA $04 ;set flag for drive on hand
DE1A CA DEX ;filenames counter needs to be checked ?
DE1B 30 0F BMI $DE2C ;no,
DE1D B5 8B LDA $8B,X ;is file drive number set ?
DE1F 10 04 BPL $DE25 ;yes,
DE21 06 04 ASL $04
DE23 06 04 ASL $04 ;adjust drive flag byte
DE25 4A LSR ;drive 1 chosen ?
DE26 90 EA BCC $DE12 ;no,
DE28 06 04 ASL $04 ;is search to be done from drive 1 ?
DE2A D0 E6 BNE $DE12 ;no,
DE2C 68 PLA
DE2D AA TAX
DE2E BD 60 DE LDA $DE60,X ;get access control byte
DE31 48 PHA
DE32 29 03 AND #$03 ;determine allowable drives
DE34 8D 92 43 STA $4392 ;set number of possible drive searches
DE37 68 PLA
DE38 0A ASL ;is this the correct drive ?
DE39 10 22 BPL $DE5D ;no,
DE3B A5 8B LDA $8B ;read drive number for first file
DE3D 29 01 AND #$01
DE3F 85 12 STA $12 ;set as current drive
DE41 AD F3 10 LDA $10F3 ;is automatic initialization flag set ?
DE44 D0 14 BNE $DE5A ;yes,
DE46 20 C2 DD JSR $DDC2 ;initialize current drive
DE49 AD 92 43 LDA $4392 ;is drive available ?
DE4C F0 0C BEQ $DE5A ;yes,
DE4E A5 12 LDA $12 ;read current drive number
DE50 48 PHA
DE51 20 86 DD JSR $DD86 ;switch drive number
DE54 20 C2 DD JSR $DDC2 ;initialize current drive
DE57 68 PLA
DE58 85 12 STA $12 ;read current drive number
DE5A 4C 2C DA JMP $DA2C ;jump to turn on LED for current drive
DE5D 2A ROL
DE5E 4C 3D DE JMP $DE3D ;proceed to set control byte for another drive
******************************* Search table: bits 0-1: number of drives
bit 6: take control byte
for drive number
bit 7: drive number of
control byte
DE61 00 ???
DE62 80 ???
DE63 41 ???
DE64 01 ???
DE65 01 ???
DE66 01 ???
DE67 01 ???
DE68 81 ???
DE69 81 ???
DE6A 81 ???
DE6B 81 ???
DE6C 42 ???
DE6D 42 ???
DE6E 42 ???
DE6F 42 ???
******************************* Lookup files in stream and fill tables
with information
DE70 20 07 DE JSR $DE07 ;set drive for file to search
DE73 A9 00 LDA #$00
DE75 8D 98 43 STA $4398 ;clear index of first available entry
DE78 20 D0 DF JSR $DFD0 ;is indicator for search entry set ?
DE7B D0 1A BNE $DE97 ;yes,
DE7D CE 92 43 DEC $4392 ;another drive available for check ?
DE80 10 01 BPL $DE83 ;yes,
DE82 60 RTS
******************************* Toggle to lookup other drive
DE83 A9 01 LDA #$01
DE85 8D 93 43 STA $4393 ;set drive search flag for other drive
DE88 20 86 DD JSR $DD86 ;switch to other drive
DE8B 20 2C DA JSR $DA2C ;turn on LED for drive
DE8E F0 E3 BEQ $DE73 ;no, unavailable drive
DE90 D0 E1 BNE $DE73 ;no, incorrect drive
DE92 20 39 E0 JSR $E039 ;found filename for search ?
DE95 F0 10 BEQ $DEA7 ;no,
DE97 20 FA DE JSR $DEFA ;search for number of filename patterns
DE9A AD 95 43 LDA $4395 ;store number of times pattern occurred
DE9D F0 01 BEQ $DEA0 ;all files not found yet,
DE9F 60 RTS
DEA0 AD 45 43 LDA $4345 ;file found ?
DEA3 30 ED BMI $DE92 ;no,
DEA5 10 F0 BPL $DE97 ;yes,
DEA7 AD 95 43 LDA $4395 ;is flag for file found ?
DEAA F0 D1 BEQ $DE7D ;yes,
DEAC 60 RTS
******************************* Find next file name matching any file in
stream & return with entry found in table
DEAD 20 27 E0 JSR $E027 ;has file been found in directory ?
DEB0 F0 1A BEQ $DECC ;no,
DEB2 D0 28 BNE $DEDC ;yes,
DEB4 A9 01 LDA #$01
DEB6 8D 93 43 STA $4393 ;set for access on both drives
DEB9 20 86 DD JSR $DD86 ;toggle drive
DEBC 20 2C DA JSR $DA2C ;activate LED
DEBF A9 00 LDA #$00
DEC1 8D 98 43 STA $4398 ;reset index for 1st available entry
DEC4 20 D0 DF JSR $DFD0 ;has file been found ?
DEC7 D0 13 BNE $DEDC ;yes,
DEC9 8D 95 43 STA $4395 ;set file found flag
DECC AD 95 43 LDA $4395 ;last entry of directory ?
DECF D0 28 BNE $DEF9 ;no,
DED1 CE 92 43 DEC $4392 ;all drives searched ?
DED4 10 DE BPL $DEB4 ;yes,
DED6 60 RTS
******************************* Find directory entry and file type
DED7 20 39 E0 JSR $E039 ;is there another directory entry ?
DEDA F0 F0 BEQ $DECC ;no,
DEDC 20 FA DE JSR $DEFA ;very entry with searched flag
DEDF AE 45 43 LDX $4345 ;is this the correct entry ?
DEE2 10 07 BPL $DEEB ;yes,
DEE4 AD 95 43 LDA $4395 ;directory still available for search ?
DEE7 F0 EE BEQ $DED7 ;yes,
DEE9 D0 0E BNE $DEF9 ;no,
DEEB AD 9C 43 LDA $439C ;is there a file type ?
DEEE F0 09 BEQ $DEF9 ;no,
DEF0 B5 8B LDA $8B,X ;read file type for directory entry
DEF2 29 1E AND #$1E
DEF4 CD 9C 43 CMP $439C ;same as requested file type ?
DEF7 D0 DE BNE $DED7 ;no,
DEF9 60 RTS
******************************* Compare file names in stream table with the
disk directory
DEFA A2 FF LDX #$FF
DEFC 8E 45 43 STX $4345 ;clear entry flag
DEFF E8 INX
DF00 8E 90 43 STX $4390 ;clear wildcard flag
DF03 20 AF DF JSR $DFAF ;is unfound files table empty ?
DF06 F0 06 BEQ $DF0E ;no,
DF08 60 RTS
DF09 20 BA DF JSR $DFBA ;does unfound files table need to be scanned ?
DF0C D0 FA BNE $DF08 ;no,
DF0E A5 12 LDA $12 ;read current drive number
DF10 55 8B EOR $8B,X
DF12 4A LSR ;same as drive number as file entry
DF13 90 0B BCC $DF20 ;yes,
DF15 29 40 AND #$40 ;default drive ?
DF17 F0 F0 BEQ $DF09 ;no,
DF19 A9 02 LDA #$02
DF1B CD 92 43 CMP $4392 ;both drives need to be scanned ?
DF1E F0 E9 BEQ $DF09 ;yes,
DF20 BD 80 43 LDA $4380,X ;read position of file name
DF23 AA TAX
DF24 20 97 E0 JSR $E097 ;find limit of command string
DF27 A0 03 LDY #$03
DF29 4C 3F DF JMP $DF3F ;verify names with command string
DF2C BD 00 43 LDA $4300,X ;read character from command buffer
DF2F D1 27 CMP ($27),Y ;equal to contents of directory buffer ?
DF31 F0 0A BEQ $DF3D ;yes,
DF33 C9 3F CMP #$3F ;is it a wildcard (?) ?
DF35 D0 D2 BNE $DF09 ;no,
DF37 B1 27 LDA ($27),Y ;read character from directory buffer
DF39 C9 A0 CMP #$A0 ;end of filename ?
DF3B F0 CC BEQ $DF09 ;yes,
DF3D E8 INX
DF3E C8 INY
DF3F EC 7C 43 CPX $437C ;has limit been reached ?
DF42 B0 09 BCS $DF4D ;yes,
DF44 BD 00 43 LDA $4300,X ;read character from command buffer
DF47 C9 2A CMP #$2A ;is it a wildcard (*) ?
DF49 F0 0C BEQ $DF57 ;yes,
DF4B D0 DF BNE $DF2C ;no,
DF4D C0 13 CPY #$13 ;is ASCII code smaller than RETURN code ?
DF4F B0 06 BCS $DF57 ;no,
DF51 B1 27 LDA ($27),Y ;read character from directory buffer
DF53 C9 A0 CMP #$A0 ;end of filename ?
DF55 D0 B2 BNE $DF09 ;no,
DF57 AE 7F 43 LDX $437F ;read position of directory entry
DF5A 8E 45 43 STX $4345 ;set file found flag
DF5D BD 86 43 LDA $4386,X ;find file entry point
DF60 29 80 AND #$80 ;set for pattern matching flag
DF62 8D 90 43 STA $4390 ;set pattern present flag
DF65 9D 86 43 STA $4386,X ;set for filename in table
DF68 AD 9A 43 LDA $439A ;read first sector location of filename
DF6B 29 E0 AND #$E0
DF6D 85 04 STA $04 ;store in TEMP4
DF6F A5 14 LDA $14 ;read current sector number
DF71 05 04 ORA $04
DF73 95 86 STA $86,X ;set directory position of filename
DF75 A0 00 LDY #$00
DF77 B1 27 LDA ($27),Y ;get file type
DF79 C8 INY ;increment buffer pointer
DF7A 48 PHA ;store original file type
DF7B 29 40 AND #$40 ;isolate status of scratch protect mode
DF7D 85 04 STA $04 ;store scratch protect status
DF7F 68 PLA ;recall file type
DF80 0A ASL
DF81 29 1E AND #$1E ;file type properly closed ?
DF83 B0 02 BCS $DF87 ;yes,
DF85 09 20 ORA #$20 ;set for unclosed file type
DF87 05 04 ORA $04 ;set for calculated file type
DF89 85 04 STA $04 ;set new file type status
DF8B A9 80 LDA #$80 ;set wildcard flag
DF8D 35 8B AND $8B,X ;read current file type data
DF8F 05 12 ORA $12 ;set for proper drive
DF91 05 04 ORA $04 ;fade in bits from new filetypes
DF93 95 8B STA $8B,X ;save as new file type data
DF95 B1 27 LDA ($27),Y ;get track number for current file
DF97 1D 86 43 ORA $4386,X
DF9A 9D 86 43 STA $4386,X ;store result in track table
DF9D C8 INY
DF9E B1 27 LDA ($27),Y ;get sector number for current file
DFA0 9D 8B 43 STA $438B,X ;store result in sector table
DFA3 AD 4B 43 LDA $434B ;file has determined record lengths ?
DFA6 D0 07 BNE $DFAF ;yes,
DFA8 A0 15 LDY #$15 ;set for record length byte
DFAA B1 27 LDA ($27),Y ;read current record length
DFAC 8D 4B 43 STA $434B ;set as current record length
******************************* Check table of unfound files
DFAF A9 FF LDA #$FF
DFB1 8D 95 43 STA $4395 ;set found flag to zero
DFB4 AD 7E 43 LDA $437E ;read current position of directory entry
DFB7 8D 7F 43 STA $437F ;store as current position of directory entry
DFBA CE 7F 43 DEC $437F ;another directory entry to process ?
DFBD 10 01 BPL $DFC0 ;yes,
DFBF 60 RTS
DFC0 AE 7F 43 LDX $437F ;get number of filename
DFC3 BD 86 43 LDA $4386,X ;file type found ?
DFC6 30 02 BMI $DFCA ;no,
DFC8 D0 F0 BNE $DFBA ;yes,
DFCA A9 00 LDA #$00
DFCC 8D 95 43 STA $4395 ;set last file in directory
DFCF 60 RTS
******************************* Search directory: returns with valid entry
DFD0 A0 00 LDY #$00
DFD2 8C 97 43 STY $4397 ;set deleted sector to #$00
DFD5 88 DEY
DFD6 8C 45 43 STY $4345 ;set directory entry found to #$ff
DFD9 A9 12 LDA #$12
DFDB 85 13 STA $13 ;set for track 18
DFDD A9 01 LDA #$01
DFDF 85 14 STA $14 ;set for sector 1
DFE1 8D 99 43 STA $4399 ;set for last buffer used
DFE4 20 6C F0 JSR $F06C ;open internal channel for read
DFE7 AD 99 43 LDA $4399 ;is there another sector ?
DFEA D0 01 BNE $DFED ;yes,
DFEC 60 RTS
DFED A9 07 LDA #$07
DFEF 8D 9B 43 STA $439B ;set for amount of file entries per block
DFF2 A9 00 LDA #$00
DFF4 20 EF F0 JSR $F0EF ;read byte from buffer
DFF7 8D 99 43 STA $4399 ;store in next block byte
DFFA 20 E1 F0 JSR $F0E1 ;set active buffer pointer
DFFD CE 9B 43 DEC $439B ;process next directory entry
E000 A0 00 LDY #$00
E002 B1 27 LDA ($27),Y ;get file type, deleted ?
E004 D0 18 BNE $E01E ;no,
E006 AD 97 43 LDA $4397 ;deleted entry found ?
E009 D0 2E BNE $E039 ;yes,
E00B 20 3E F9 JSR $F93E ;read current sector
E00E A5 14 LDA $14 ;read current sector number
E010 8D 97 43 STA $4397 ;set as sector number for file
E013 A5 27 LDA $27 ;get current index
E015 AE 98 43 LDX $4398 ;read index for 1st available entry
E018 8D 98 43 STA $4398 ;was index deleted before ?
E01B F0 1C BEQ $E039 ;yes,
E01D 60 RTS
E01E A2 01 LDX #$01
E020 EC 98 43 CPX $4398 ;looking for deleted entry ?
E023 D0 2C BNE $E051 ;no,
E025 F0 12 BEQ $E039 ;yes,
E027 A9 12 LDA #$12
E029 85 13 STA $13 ;set for track 18
E02B AD 96 43 LDA $4396 ;read sector number
E02E 85 14 STA $14 ;set as current sector number
E030 20 6C F0 JSR $F06C ;open internal read channel (secondary addr=17)
E033 AD 9A 43 LDA $439A ;read current index buffer
E036 20 C1 F0 JSR $F0C1 ;set buffer pointer
******************************* Continue file entry search
E039 A9 FF LDA #$FF
E03B 8D 45 43 STA $4345 ;clear entry found flag
E03E AD 9B 43 LDA $439B ;all file entries in block processed ?
E041 30 08 BMI $E04B ;yes,
E043 A9 20 LDA #$20 ;set number of bytes per file entry
E045 20 42 EE JSR $EE42 ;move to next file entry
E048 4C FA DF JMP $DFFA ;process next file entry
E04B 20 44 F0 JSR $F044 ;read next block from directory
E04E 4C E7 DF JMP $DFE7 ;process next directory sector
E051 A5 27 LDA $27 ;read directory buffer pointer
E053 8D 9A 43 STA $439A ;set as current index pointer
E056 20 3E F9 JSR $F93E ;get header block
E059 A5 14 LDA $14 ;read current sector number
E05B 8D 96 43 STA $4396 ;store as current directory sector
E05E 60 RTS
******************************* Transfer filename from command buffer
.X = starting index in buffer
.Y = buffer number
.ACC = string size
E05F 48 PHA ;store length of filename
E060 20 97 E0 JSR $E097 ;find position of name in input string
E063 20 79 E0 JSR $E079 ;determine and copy name in buffer
E066 68 PLA ;recall length of filename
E067 38 SEC
E068 ED 3A 43 SBC $433A ;substract from allowed string length
E06B AA TAX ;does string need padding ?
E06C F0 0A BEQ $E078 ;no,
E06E 90 08 BCC $E078 ;no,
E070 A9 A0 LDA #$A0
E072 91 27 STA ($27),Y ;store SHIFTED SPACE in buffer
E074 C8 INY ;increment file name length counter
E075 CA DEX ;another SHIFTED SPACE needed ?
E076 D0 FA BNE $E072 ;yes,
E078 60 RTS
******************************* Transfer command buffer to other buffer
.X = starting index in command buffer
.Y = buffer number
E079 98 TYA ;set .ACC equal to current buffer number
E07A 0A ASL ;double buffer number
E07B A8 TAY ;set .Y register as new buffer number
E07C B9 29 00 LDA $0029,Y ;read LO byte in buffer table
E07F 85 27 STA $27 ;set as low byte for directory buffer
E081 B9 2A 00 LDA $002A,Y ;read HI byte in buffer table
E084 85 28 STA $28 ;set as high byte for directory buffer
E086 A0 00 LDY #$00
E088 BD 00 43 LDA $4300,X ;read byte from input buffer
E08B 91 27 STA ($27),Y ;store in assigned directory buffer
E08D C8 INY ;all bytes read ?
E08E F0 06 BEQ $E096 ;yes,
E090 E8 INX
E091 EC 7C 43 CPX $437C ;another command byte to be read ?
E094 90 F2 BCC $E088 ;yes,
E096 60 RTS
******************************* Find limit of string in command buffer
.X = end of string pointer
E097 A9 00 LDA #$00
E099 8D 3A 43 STA $433A ;set string size to #$00
E09C 8A TXA ;transfer start position pointer to .ACC
E09D 48 PHA
E09E BD 00 43 LDA $4300,X ;get character from command buffer
E0A1 C9 2C CMP #$2C ;is it a comma (,) ?
E0A3 F0 14 BEQ $E0B9 ;yes,
E0A5 C9 3D CMP #$3D ;is it an equal (=) ?
E0A7 F0 10 BEQ $E0B9 ;yes,
E0A9 EE 3A 43 INC $433A ;increment size pointer
E0AC E8 INX ;do next next character
E0AD A9 0F LDA #$0F
E0AF CD 3A 43 CMP $433A ;has maximum file name length been reached ?
E0B2 90 05 BCC $E0B9 ;yes,
E0B4 EC 79 43 CPX $4379 ;end of command string been reached ?
E0B7 90 E5 BCC $E09E ;no,
E0B9 8E 7C 43 STX $437C ;set limit for command string
E0BC 68 PLA
E0BD AA TAX ;retrieve start position pointer
E0BE 60 RTS
******************************* Get file entry from directory
E0BF A5 16 LDA $16 ;read current secondary address
E0C1 48 PHA ;preserve it
E0C2 A5 15 LDA $15 ;read current number of active channels
E0C4 48 PHA ;preserve it
E0C5 20 CF E0 JSR $E0CF ;get file entry
E0C8 68 PLA ;retrieve active channels
E0C9 85 15 STA $15 ;restore
E0CB 68 PLA ;retrieve secondary address
E0CC 85 16 STA $16 ;restore
E0CE 60 RTS
******************************* Get directory entry
E0CF A9 11 LDA #$11
E0D1 85 16 STA $16 ;set secondary address to #$11 (decimal 17)
E0D3 20 69 ED JSR $ED69 ;set read channel
E0D6 20 E1 F0 JSR $F0E1 ;read active buffer pointer
E0D9 AD 45 43 LDA $4345 ;directory entry found ?
E0DC 10 0C BPL $E0EA ;yes,
E0DE AD 93 43 LDA $4393 ;drive search flag for both drives active ?
E0E1 D0 0C BNE $E0EF ;yes,
E0E3 20 F0 E1 JSR $E1F0 ;get BLOCKS FREE message and write to buffer
E0E6 18 CLC
E0E7 4C 9E E1 JMP $E19E ;exit - end of directory
E0EA AD 93 43 LDA $4393 ;drive search flag for both drives active ?
E0ED F0 1F BEQ $E10E ;yes,
E0EF CE 93 43 DEC $4393 ;drive search flag now inactive ?
E0F2 D0 0D BNE $E101 ;no,
E0F4 CE 93 43 DEC $4393 ;set drive search flag to inactive
E0F7 20 86 DD JSR $DD86 ;change to other drive
E0FA 20 F0 E1 JSR $E1F0 ;get BLOCKS FREE message and write to buffer
E0FD 38 SEC
E0FE 4C 86 DD JMP $DD86 ;change to other drive
E101 A9 00 LDA #$00
E103 8D 78 43 STA $4378 ;set HI byte of blocks free count to #$00
E106 8D 93 43 STA $4393 ;set drive search flag to #$00
E109 20 AA E1 JSR $E1AA ;get new directory listing
E10C 38 SEC
E10D 60 RTS
E10E A2 18 LDX #$18 ;length of directory line is #$18 (decimal 24)
E110 A0 1D LDY #$1D ;set directory padding to #$1D (decimal 29)
E112 B1 27 LDA ($27),Y ;read HI byte of file block count
E114 8D 78 43 STA $4378 ;is HI block count for this file name #$00 ?
E117 F0 02 BEQ $E11B ;yes,
E119 A2 16 LDX #$16 ;set .X register to directory length minus 2
E11B 88 DEY ;set for LO byte of block count
E11C B1 27 LDA ($27),Y ;read LO byte of file block count
E11E 8D 77 43 STA $4377 ;set as LO block count for file name
E121 E0 16 CPX #$16 ;is file length #$16 (decimal 22) ?
E123 F0 0A BEQ $E12F ;yes,
E125 C9 0A CMP #$0A ;is file length #$0A (decimal 10) ?
E127 90 06 BCC $E12F ;yes,
E129 CA DEX ;decrement length of file entry
E12A C9 64 CMP #$64 ;is length #$64 (decimal 100) ?
E12C 90 01 BCC $E12F ;yes,
E12E CA DEX ;remove SHIFTED SPACE
E12F 20 9F E1 JSR $E19F ;delete buffer for directory
E132 B1 27 LDA ($27),Y ;read file type
E134 48 PHA
E135 0A ASL ;is file locked ?
E136 10 05 BPL $E13D ;no,
E138 A9 3C LDA #$3C ;set .ACC for locked file indicator (<)
E13A 9D B5 41 STA $41B5,X ;store after file type
E13D 68 PLA
E13E 29 0F AND #$0F ;mask off higher bits of file type
E140 A8 TAY
E141 B9 DE D2 LDA $D2DE,Y ;get 3rd character of file type abbreviation
E144 9D B4 41 STA $41B4,X ;build short name for directory purpose
E147 CA DEX
E148 B9 D9 D2 LDA $D2D9,Y ;get 2nd character of file type abbreviation
E14B 9D B4 41 STA $41B4,X ;continue building short name for directory
E14E CA DEX
E14F B9 D4 D2 LDA $D2D4,Y ;get 1st character of file type abbreviation
E152 9D B4 41 STA $41B4,X ;finish building short name for directory
E155 CA DEX
E156 CA DEX ;is file properly closed ?
E157 B0 05 BCS $E15E ;yes,
E159 A9 2A LDA #$2A ;set .ACC for unclosed file indicator (*)
E15B 9D B5 41 STA $41B5,X ;store before file type
E15E A9 A0 LDA #$A0
E160 9D B4 41 STA $41B4,X ;store a SHIFTED SPACE for padding
E163 CA DEX
E164 A0 12 LDY #$12 ;set for buffer position of file name
E166 B1 27 LDA ($27),Y ;read character for file name
E168 9D B4 41 STA $41B4,X ;store in directory buffer
E16B CA DEX
E16C 88 DEY
E16D C0 03 CPY #$03 ;all characters in file name transferred ?
E16F B0 F5 BCS $E166 ;no,
E171 A9 22 LDA #$22 ;set .ACC for a quotation mark (")
E173 9D B4 41 STA $41B4,X ;store before file name
E176 E8 INX
E177 E0 20 CPX #$20 ;last character in file name ?
E179 B0 0B BCS $E186 ;yes,
E17B BD B4 41 LDA $41B4,X ;read next character from directory buffer
E17E C9 22 CMP #$22 ;is character a quotation mark (") ?
E180 F0 04 BEQ $E186 ;yes,
E182 C9 A0 CMP #$A0 ;is character a SHIFTED SPACE ?
E184 D0 F0 BNE $E176 ;no,
E186 A9 22 LDA #$22 ;set .ACC for a quotation mark (") ?
E188 9D B4 41 STA $41B4,X ;store at end of file name
E18B E8 INX
E18C E0 20 CPX #$20 ;last character in file name ?
E18E B0 0A BCS $E19A ;yes,
E190 A9 7F LDA #$7F
E192 3D B4 41 AND $41B4,X ;disable reverse video effect for character
E195 9D B4 41 STA $41B4,X ;another character to process ?
E198 10 F1 BPL $E18B ;yes,
E19A 20 D7 DE JSR $DED7 ;find directory entry and file type
E19D 38 SEC ;set flag for more entries to be done
E19E 60 RTS
******************************* Clear name buffer
E19F A0 1B LDY #$1B ;set length of name buffer (decimal 27)
E1A1 A9 20 LDA #$20 ;character to blank buffer with (decimal 32)
E1A3 99 B3 41 STA $41B3,Y ;set position in name buffer to blank
E1A6 88 DEY ;last character in name buffer blanked ?
E1A7 D0 FA BNE $E1A3 ;no,
E1A9 60 RTS
******************************* New directory listing
E1AA 20 9F E1 JSR $E19F ;clear name buffer
E1AD A9 FF LDA #$FF
E1AF 85 04 STA $04 ;set TEMP4 to #$FF (decimal 255)
E1B1 A6 12 LDX $12 ;read current drive
E1B3 8E 77 43 STX $4377 ;set as temporary number of blocks
E1B6 A9 00 LDA #$00
E1B8 8D 78 43 STA $4378 ;set HI byte of temporary block count to #$00
E1BB BD E8 D2 LDA $D2E8,X ;read BAM pointer for selected drive
E1BE 85 28 STA $28 ;set as current BAM to use
E1C0 A9 90 LDA #$90 ;set LO byte of buffer pointer
E1C2 85 27 STA $27 ;set for use with BAM pointer
E1C4 A0 16 LDY #$16 ;set for length of diskette name
E1C6 B1 27 LDA ($27),Y ;read byte from BAM
E1C8 C9 A0 CMP #$A0 ;is it a SHIFTED SPACE ?
E1CA D0 0B BNE $E1D7 ;no,
E1CC A9 31 LDA #$31 ;set for ASCII version "1"
E1CE 2C ??? ;comma (,)
** also becomes patch: E1CE 2C B1 27 BIT $27B1
E1CF B1 27 LDA ($27),Y ;read byte from BAM
E1D1 C9 A0 CMP #$A0 ;is it a SHIFTED SPACE ?
E1D3 D0 02 BNE $E1D7 ,no,
E1D5 A9 20 LDA #$20
E1D7 99 B6 41 STA $41B6,Y ;store a blank in directory buffer
E1DA 88 DEY ;another byte to read ?
E1DB 10 F2 BPL $E1CF ;yes,
E1DD A9 12 LDA #$12 ;set for REVERSE VIDEO code
E1DF 8D B4 41 STA $41B4 ;store in directory buffer
E1E2 A9 22 LDA #$22 ;set for quotation mark (")
E1E4 8D B5 41 STA $41B5 ;store in directory buffer
E1E7 8D C6 41 STA $41C6 ;store at end of diskette name also
E1EA A9 20 LDA #$20
E1EC 8D C7 41 STA $41C7 ;store blank after end quote
E1EF 60 RTS
******************************* Display BLOCKS FREE. message
E1F0 20 9F E1 JSR $E19F ;clear name buffer
E1F3 A0 0B LDY #$0B ;set for length of last line message
E1F5 B9 01 E2 LDA $E201,Y ;read byte from memory
E1F8 99 B4 41 STA $41B4,Y ;build BLOCKS FREE. message and send to buffer
E1FB 88 DEY ;all characters transferred ?
E1FC 10 F7 BPL $E1F5 ;no,
E1FE 4C 2E DB JMP $DB2E ;jump to calculate number of blocks free
******************************* BLOCKS FREE. message
E201 42 4C 4F 43 4B 53 ;blocks
E207 20 46 52 45 45 2E ; free.
******************************* Command: NEW (format diskette)
E20D 20 0A DD JSR $DD0A ;set 1st drive and table pointers
E210 A5 8B LDA $8B ;is drive valid ?
E212 10 05 BPL $E219 ;yes,
E214 A9 33 LDA #$33 ;set for "33 SYNTAX ERROR", invalid file name
E216 4C C3 DB JMP $DBC3 ;jump to process command error routine
E219 29 01 AND #$01
E21B 85 12 STA $12 ;set as current drive number
E21D 20 2C DA JSR $DA2C ;turn on LED for specified drive
E220 20 80 D7 JSR $D780 ;set BAM pointer for active drive
E223 A5 12 LDA $12 ;read current drive number
E225 0A ASL
E226 AA TAX
E227 AC 81 43 LDY $4381 ;read length in command table
E22A CC 79 43 CPY $4379 ;command NEW or clear ?
E22D F0 16 BEQ $E245 ;clear,
E22F B9 00 43 LDA $4300,Y ;read disk ID1 from command buffer
E232 9D 40 43 STA $4340,X ;set as current ID1 for formatting
E235 B9 01 43 LDA $4301,Y ;read disk ID2 from command buffer
E238 9D 41 43 STA $4341,X ;set as current ID2 for formatting
E23B A9 01 LDA #$01
E23D 85 13 STA $13 ;set track equal to #$01
E23F 20 16 E4 JSR $E416 ;jump to format diskette routine
E242 4C 54 E2 JMP $E254 ;jump to set BAM routine
******************************* Initialize drive with version number
E245 20 FA EC JSR $ECFA ;initialize diskette in drive
E248 A0 02 LDY #$02
E24A B1 02 LDA ($02),Y ;read current DOS version of diskette
E24C CD 9F 10 CMP $109F ;diskette formatted on this type of drive ?
E24F F0 03 BEQ $E254 ;yes,
E251 4C 80 F1 JMP $F180 ;jump to process wrong version error
******************************* Initialize track 18, 0:
byte 00 - 01: next T & S
02 : DOS version
03 :
04 - 143: BAM for all tracks
144 - 161: diskette name
164 : SHIFTED SPACE
165 - 166: DOS type identifier
Initialize track 18, 1: first directory
block
E254 A9 00 LDA #$00
E256 A8 TAY
E257 91 02 STA ($02),Y ;clear BAM buffer
E259 C8 INY ;entire buffer cleared ?
E25A D0 FB BNE $E257 ;no,
E25C A5 12 LDA $12 ;read current drive number
E25E 18 CLC
E25F 69 0C ADC #$0C
E261 85 A1 STA $A1 ;set current job to: #$0D (decimal 13/drive 0)
#$0E (decimal 14/drive 1)
E263 0A ASL
E264 AA TAX
E265 A9 90 LDA #$90
E267 95 29 STA $29,X ;set for buffer offset of 144 bytes
E269 A0 01 LDY #$01
E26B 84 14 STY $14 ;set for sector #$01 (decimal 1)
E26D A9 FF LDA #$FF
E26F 91 02 STA ($02),Y ;write #$FF (decimal 255) to second position
in track 18, sector 1
E271 A9 12 LDA #$12
E273 85 13 STA $13 ;set for track #$12 (decimal 18)
E275 20 5B F0 JSR $F05B ;clear directory entries for trk, 18, sctr 1
E278 20 6F E7 JSR $E76F ;create new Block Allocation Map
E27B A0 02 LDY #$02
E27D AD 9F 10 LDA $109F ;read DOS VERSION
E280 91 02 STA ($02),Y ;store DOS VERSION
E282 20 9A EB JSR $EB9A ;mark track, sector, BAM pointer as used
E285 C6 14 DEC $14 ;set for sector 0 of track 18
E287 20 9A EB JSR $EB9A ;mark track, sector, BAM pointer as used
E28A A4 A1 LDY $A1 ;read current job number
E28C AE 80 43 LDX $4380 ;read file table length
E28F A9 1B LDA #$1B
E291 20 5F E0 JSR $E05F ;transfer diskette name to buffer
E294 A0 12 LDY #$12 ;set for buffer offset of 18 bytes
E296 A5 12 LDA $12 ;read current drive number
E298 0A ASL
E299 AA TAX
E29A BD 40 43 LDA $4340,X ;read disk ID1
E29D 91 27 STA ($27),Y ;store in directory buffer
E29F C8 INY
E2A0 BD 41 43 LDA $4341,X ;read disk ID2
E2A3 91 27 STA ($27),Y ;store in directory buffer
E2A5 C8 INY
E2A6 C8 INY
E2A7 A9 32 LDA #$32
E2A9 91 27 STA ($27),Y ;store DOS TYPE ("2") in directory buffer
E2AB C8 INY
E2AC AD 9F 10 LDA $109F ;read current DOS VERSION ("A") number
E2AF 91 27 STA ($27),Y ;store in directory buffer
E2B1 20 5B F0 JSR $F05B ;write to disk
E2B4 4C 99 DB JMP $DB99 ;jump to send "00, OK, 00, 00" message
******************************* Command: SCRATCH (erase files)
E2B7 20 8F DD JSR $DD8F ;set pointer to one file stream and check type
E2BA 20 18 DD JSR $DD18 ;set current drive number
E2BD 20 07 DE JSR $DE07 ;set optimum search for lookup and find file
E2C0 A9 00 LDA #$00
E2C2 85 19 STA $19 ;set file count to #$00
E2C4 20 BF DE JSR $DEBF ;another entry found ?
E2C7 30 3F BMI $E308 ;no,
E2C9 20 C2 F8 JSR $F8C2 ;file currently under use ?
E2CC 90 35 BCC $E303 ;yes,
E2CE A0 00 LDY #$00
E2D0 B1 27 LDA ($27),Y ;read file type from directory
E2D2 29 40 AND #$40 ;is this file locked ?
E2D4 D0 2D BNE $E303 ;yes,
E2D6 20 3B E3 JSR $E33B ;delete directory entry
E2D9 A0 13 LDY #$13
E2DB B1 27 LDA ($27),Y ;pointer for side sector active ?
E2DD F0 0A BEQ $E2E9 ;no,
E2DF 85 13 STA $13 ;set as new track
E2E1 C8 INY
E2E2 B1 27 LDA ($27),Y ;get side sector number
E2E4 85 14 STA $14 ;set as current sector
E2E6 20 13 E3 JSR $E313 ;delete by links and free blocks
E2E9 AE 45 43 LDX $4345 ;read entry found flag
E2EC A9 20 LDA #$20
E2EE 35 8B AND $8B,X ;file not closed properly ?
E2F0 D0 0F BNE $E301 ;yes,
E2F2 BD 86 43 LDA $4386,X ;read next track of file
E2F5 29 7F AND #$7F ;disable pattern matching flag
E2F7 85 13 STA $13 ;set as current track number
E2F9 BD 8B 43 LDA $438B,X ;read next sector location of file
E2FC 85 14 STA $14 ;set as current sector number
E2FE 20 13 E3 JSR $E313 ;delete by links and free blocks
E301 E6 19 INC $19 ;increment file count
E303 20 AD DE JSR $DEAD ;another file name to delete ?
E306 10 C1 BPL $E2C9 ;yes,
E308 A5 19 LDA $19 ;read file count
E30A 85 13 STA $13 ;set as current track number
E30C A9 01 LDA #$01
E30E A0 00 LDY #$00
E310 4C A3 DB JMP $DBA3 ;jump to produce "FILES SCRATCHED" message
******************************* Delete file by links
E313 20 13 DA JSR $DA13 ;mark sector as free on track and BAM
E316 20 6C F0 JSR $F06C ;open internal read channel
E319 A9 00 LDA #$00
E31B 20 C1 F0 JSR $F0C1 ;set pointer
E31E 20 D2 ED JSR $EDD2 ;read byte from file
E321 85 13 STA $13 ;set as current track number
E323 20 D2 ED JSR $EDD2 ;read byte from file
E326 85 14 STA $14 ;set as current sector number
E328 A5 13 LDA $13 ;last track & sector link of file ?
E32A D0 06 BNE $E332 ;no,
E32C 20 55 F6 JSR $F655 ;write out bit map to disk
E32F 4C 9F EE JMP $EE9F ;jump to free channel routine
E332 20 13 DA JSR $DA13 ;mark sector as free on track and BAM
E335 20 44 F0 JSR $F044 ;read next data block for current file
E338 4C 19 E3 JMP $E319 ;do next link in file
******************************* Delete directory entry
E33B A0 00 LDY #$00
E33D 98 TYA
E33E 91 27 STA ($27),Y ;adjust directory entry to DEL
E340 20 63 F9 JSR $F963 ;write adjustment to disk
E343 4C 82 EC JMP $EC82 ;jump to wait until write job complete routine
******************************* Command: DUPLICATE (backup diskette)
.Y = pointer for current character
position
E346 20 9E E4 JSR $E49E ;test for proper syntax
E349 A5 8C LDA $8C ;read source drive number
E34B 85 12 STA $12 ;set as current drive number
E34D A9 18 LDA #$18 ;set for both LED's
E34F 0D 82 02 ORA $0282
E352 8D 82 02 STA $0282 ;set LED's for drive 1 & drive 0
E355 20 FA EC JSR $ECFA ;initialize source drive
E358 20 80 D7 JSR $D780 ;set BAM pointer for current drive
E35B A0 02 LDY #$02
E35D B1 02 LDA ($02),Y ;read format version from disk
E35F CD 9F 10 CMP $109F ;same as format version for disk unit ?
E362 F0 03 BEQ $E367 ;yes,
E364 4C 80 F1 JMP $F180 ;set for "73,CBM DOS V2,00,00" error
E367 20 86 DD JSR $DD86 ;toggle drive number
E36A 0A ASL
E36B A8 TAY
E36C 49 02 EOR #$02
E36E AA TAX
E36F BD 40 43 LDA $4340,X ;read ID1 of source drive
E372 99 40 43 STA $4340,Y ;set as ID1 for destination drive
E375 BD 41 43 LDA $4341,X ;read ID2 of source drive
E378 99 41 43 STA $4341,Y ;set as ID2 for destination drive
E37B 20 80 D7 JSR $D780 ;set BAM pointer for current drive
E37E A0 02 LDY #$02
E380 AD 9F 10 LDA $109F ;read format version for disk unit
E383 91 02 STA ($02),Y ;set as format version for diskette
E385 20 54 EF JSR $EF54 ;clear all dos channels
E388 A9 01 LDA #$01
E38A 85 13 STA $13 ;set for track 1 on destination drive
E38C 20 16 E4 JSR $E416 ;format destination drive
E38F A5 13 LDA $13 ;read current track number
******************************* Copy blocks from source to destination drive
E391 20 D2 D7 JSR $D7D2 ;read maximum sectors for current track
E394 85 14 STA $14 ;set as end limit
E396 C6 14 DEC $14 ;do next sector
E398 20 A9 E3 JSR $E3A9 ;copy entire track to destination drive
E39B E6 13 INC $13 ;do next track
E39D A5 13 LDA $13 ;read current track number
E39F C9 24 CMP #$24 ;all tracks on source disk copied ?
E3A1 D0 EC BNE $E38F ;no,
E3A3 20 FA EC JSR $ECFA ;initialize destination drive
E3A6 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Copy entire track from source to destination
E3A9 20 B7 E3 JSR $E3B7 ;transfer HEADER images to destination drive
E3AC 20 D2 E3 JSR $E3D2 ;read 10 sectors from source drive
E3AF 20 F6 E3 JSR $E3F6 ;write 10 sectors to destination drive
E3B2 A5 14 LDA $14 ;all sectors done ?
E3B4 10 F3 BPL $E3A9 ;no,
E3B6 60 RTS
******************************* Transfer HEADER blocks to destination drive
E3B7 A5 12 LDA $12 ;read current drive number
E3B9 49 01 EOR #$01
E3BB 8D 3C 43 STA $433C ;set temporary job command
E3BE A9 0A LDA #$0A
E3C0 85 06 STA $06 ;set TEMP2 to #$0A (decimal 10)
E3C2 A5 06 LDA $06 ;read TEMP2
E3C4 20 92 EC JSR $EC92 ;transfer HEADER images to buffer
E3C7 C6 14 DEC $14 ;another sector ?
E3C9 30 06 BMI $E3D1 ;no,
E3CB C6 06 DEC $06 ;TEMP2 no longer positive value ?
E3CD 10 F3 BPL $E3C2 ;no,
E3CF E6 06 INC $06 ;increment TEMP2
E3D1 60 RTS
******************************* READ 10 sectors from source drive
E3D2 AD 3C 43 LDA $433C ;read temporary job command
E3D5 09 80 ORA #$80 ;change job type to READ
E3D7 8D 3C 43 STA $433C ;set job to READ
E3DA A6 06 LDX $06 ;read TEMP2 value into .X register
E3DC AD 3C 43 LDA $433C ;read current job command
E3DF 20 16 F1 JSR $F116 ;set up job to do
E3E2 E0 0A CPX #$0A ;all 10 sectors read ?
E3E4 F0 03 BEQ $E3E9 ;yes,
E3E6 E8 INX ;sector count #$00 ?
E3E7 D0 F3 BNE $E3DC ;no,
E3E9 A6 06 LDX $06 ;read TEMP2
E3EB 20 82 EC JSR $EC82 ;wait until assigned job is completed
E3EE E0 0A CPX #$0A ;all 10 sectors read ?
E3F0 F0 03 BEQ $E3F5 ;yes,
E3F2 E8 INX ;sector count #$00 ?
E3F3 D0 F6 BNE $E3EB ;no,
E3F5 60 RTS
******************************* WRITE 10 sectors to destination drive
E3F6 A9 90 LDA #$90 ;set for WRITE job
E3F8 05 12 ORA $12 ;add in drive number
E3FA 8D 3C 43 STA $433C ;set job to WRITE
E3FD A6 06 LDX $06 ;read TEMP2 value into .X register
E3FF 20 16 F1 JSR $F116 ;set up job to do
E402 E0 0A CPX #$0A ;all 10 sectors written ?
E404 F0 03 BEQ $E409 ;yes,
E406 E8 INX ;sector count #$00 ?
E407 D0 F6 BNE $E3FF ;no,
E409 A6 06 LDX $06 ;read TEMP2
E40B 20 82 EC JSR $EC82 ;wait until assigned job is completed
E40E E0 0A CPX #$0A ;all 10 sectors written ?
E410 F0 03 BEQ $E415 ;yes,
E412 E8 INX ;sector count #$00 ?
E413 D0 F6 BNE $E40B ;no,
E415 60 RTS
******************************* Transfer format code to buffers 0,1 & 2
start controller formatting
E416 A0 00 LDY #$00
E418 B9 00 D0 LDA $D000,Y ;read format codes from ROM
E41B 99 00 11 STA $1100,Y ;transfer to RAM
E41E B9 00 D1 LDA $D100,Y ;read format codes from ROM
E421 99 00 12 STA $1200,Y ;transfer to RAM
E424 B9 00 D2 LDA $D200,Y ;read format codes from ROM
E427 99 00 13 STA $1300,Y ;transfer to RAM
E42A C8 INY ;all codes transferred ?
E42B D0 EB BNE $E418 ;no,
E42D A9 00 LDA #$00
E42F 20 92 EC JSR $EC92 ;transfer HEADER image to buffer
E432 A5 12 LDA $12 ;read current drive number
E434 09 E0 ORA #$E0
E436 8D 03 10 STA $1003 ;activate EXECUTE code in buffer (FORMAT)
E439 AD 03 10 LDA $1003 ;formatting of diskette finished ?
E43C 30 FB BMI $E439 ;no,
E43E C9 01 CMP #$01 ;disk formatted ok ?
E440 F0 07 BEQ $E449 ;yes,
E442 A9 03 LDA #$03
E444 A2 00 LDX #$00
E446 4C 1C D9 JMP $D91C ;jump to process encountered error type
E449 60 RTS
******************************* Command: COPY (transfer file(s) to other or
same disk). Check for type and parse
special case
E44A 20 E0 DB JSR $DBE0 ;colon found ?
E44D D0 1D BNE $E46C ;no,
E44F 20 9E E4 JSR $E49E ;test for proper syntax
E452 A9 2A LDA #$2A
E454 A2 27 LDX #$27
E456 8E 81 43 STX $4381 ;set maximum length to #$27 (decimal 39)
E459 9D 00 43 STA $4300,X ;store wildcard (*) at end of command buffer
E45C E8 INX
E45D 8E 79 43 STX $4379 ;set command size to #$27 + #$01 (decimal 40)
E460 A2 01 LDX #$01
E462 8E 7D 43 STX $437D ;set file count1 to #$01 (decimal 1)
E465 E8 INX
E466 8E 7E 43 STX $437E ;set file count2 to #$02 (decimal 2)
E469 4C E1 E4 JMP $E4E1 ;set for optimum search of files in tables
******************************* Normal parse
E46C 20 F3 DB JSR $DBF3 ;set up command structure image and file
pointer
E46F 20 18 DD JSR $DD18 ;set drive number
E472 AD 91 43 LDA $4391 ;read file copy image
E475 29 55 AND #$55 ;concat or normal (0101 0101) ?
E477 D0 1B BNE $E494 ;no,
E479 AE 80 43 LDX $4380 ;read pattern from file table
E47C BD 00 43 LDA $4300,X ;read byte from command buffer
E47F C9 2A CMP #$2A ;is it a wildcard (*) ?
E481 D0 11 BNE $E494 ;no,
E483 A2 01 LDX #$01
E485 8E 7D 43 STX $437D ;set file count1 to #$01 (decimal 1)
E488 E8 INX
E489 8E 7E 43 STX $437E ;set file count2 to #$02 (decimal 2)
E48C 4C C5 E4 JMP $E4C5 ;copy requested files
******************************* Indicate invalid command structure
E48F A9 30 LDA #$30 ;set for "30 SYNTAX ERROR", general syntax
E491 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Test if copy type is normal
E494 AD 91 43 LDA $4391 ;read file copy image
E497 29 D9 AND #$D9 ;normal copy ?
E499 D0 F4 BNE $E48F ;no,
E49B 4C 87 E5 JMP $E587 ;yes,
******************************* Verify drive numbers for disk to disk copy
E49E A9 3D LDA #$3D ;set for disk to disk copying (=)
E4A0 20 63 DC JSR $DC63 ;is this a disk to disk copy request ?
E4A3 D0 05 BNE $E4AA ;yes,
E4A5 A9 30 LDA #$30 ;set for "30 SYNTAX ERROR", general syntax
E4A7 4C C3 DB JMP $DBC3 ;jump to process command error routine
E4AA B9 00 43 LDA $4300,Y ;read source drive number from command buffer
E4AD 20 B5 DD JSR $DDB5 ;valid drive number ?
E4B0 30 F3 BMI $E4A5 ;no,
E4B2 85 8C STA $8C ;store source drive number in table
E4B4 88 DEY
E4B5 88 DEY
E4B6 B9 00 43 LDA $4300,Y ;read destination drive number from command
buffer
E4B9 20 B5 DD JSR $DDB5 ;valid drive number ?
E4BC 30 E7 BMI $E4A5 ;no,
E4BE C5 8C CMP $8C ;same drive number as source ?
E4C0 F0 E3 BEQ $E4A5 ;yes,
E4C2 85 8B STA $8B ;store destination drive number in table
E4C4 60 RTS
******************************* Copy disk to disk routines
E4C5 AD 81 43 LDA $4381 ;read byte from file data table
E4C8 85 04 STA $04 ;store in TEMP0
E4CA A0 28 LDY #$28
E4CC AE 79 43 LDX $4379 ;read current command string length into .X
E4CF 8C 79 43 STY $4379 ;set command string length to #$28 (decimal 40)
E4D2 88 DEY
E4D3 CA DEX
E4D4 BD 00 43 LDA $4300,X ;read filename from directory buffer
E4D7 99 00 43 STA $4300,Y ;transfer to command buffer
E4DA E4 04 CPX $04 ;all transferred ?
E4DC D0 F4 BNE $E4D2 ;no,
E4DE 8C 81 43 STY $4381 ;store new position of filename
E4E1 20 07 DE JSR $DE07 ;lookup and find file
E4E4 20 67 E5 JSR $E567 ;set for copy of file according to type and
specification
E4E7 20 BF DE JSR $DEBF ;filename in entry table found ?
E4EA 10 2D BPL $E519 ;yes,
E4EC 30 28 BMI $E516 ;no,
******************************* Pull needed variables from stack
E4EE 68 PLA
E4EF 8D 96 43 STA $4396 ;reset previous directory sector
E4F2 68 PLA
E4F3 8D 81 43 STA $4381 ;reset previous file table value
E4F6 68 PLA
E4F7 8D 99 43 STA $4399 ;reset previous buffer position
E4FA 68 PLA
E4FB 8D 9B 43 STA $439B ;reset previous file entries counter
E4FE 68 PLA
E4FF 8D 9A 43 STA $439A ;reset previous index in buffer
E502 68 PLA
E503 8D 95 43 STA $4395 ;reset previous flag for directory search
E506 68 PLA
E507 8D 98 43 STA $4398 ;reset previous index of 1st available entry
E50A 68 PLA
E50B 8D 93 43 STA $4393 ;reset previous drive search flag
E50E 20 67 E5 JSR $E567 ;set for copy of file according to type and
specification
E511 20 AD DE JSR $DEAD ;file name found in table ?
E514 10 03 BPL $E519 ;yes,
E516 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Push needed variables onto stack
E519 AD 93 43 LDA $4393 ;preserve drive search flag
E51C 48 PHA
E51D AD 98 43 LDA $4398 ;preserve index for 1st available entry
E520 48 PHA
E521 AD 95 43 LDA $4395 ;preserve flag for directory search
E524 48 PHA
E525 AD 9A 43 LDA $439A ;preserve index in buffer
E528 48 PHA
E529 AD 9B 43 LDA $439B ;preserve file entries counter
E52C 48 PHA
E52D AD 99 43 LDA $4399 ;preserve buffer position
E530 48 PHA
E531 AD 81 43 LDA $4381 ;preserve file table value
E534 48 PHA
E535 AD 96 43 LDA $4396 ;preserve directory sector
E538 48 PHA
E539 20 57 E5 JSR $E557 ;transfer filename
E53C A9 01 LDA #$01
E53E 8D 7D 43 STA $437D ;set file count1 to #$01 (decimal 1)
E541 8D 7E 43 STA $437E ;set file count2 to #$01 (decimal 1)
E544 20 70 DE JSR $DE70 ;lookup files in stream and fill table with
information
E547 A9 01 LDA #$01
E549 8D 7D 43 STA $437D ;set file count1 to #$01 (decimal 1)
E54C A9 02 LDA #$02
E54E 8D 7E 43 STA $437E ;set file count2 to #$02 (decimal 2)
E551 20 D3 E5 JSR $E5D3 ;check if file already exists. If not, copy it
E554 4C EE E4 JMP $E4EE ;pull needed variables from stack
******************************* Transfer name from directory buffer to
command buffer
E557 A0 03 LDY #$03
E559 8C 80 43 STY $4380 ;store in file table
E55C B1 27 LDA ($27),Y ;read byte from directory buffer
E55E 99 00 43 STA $4300,Y ;store in command buffer
E561 C8 INY
E562 C0 13 CPY #$13 ;all bytes copied from directory buffer ?
E564 D0 F6 BNE $E55C ;no,
E566 60 RTS
******************************* Set up for drive number and file information
E567 A9 00 LDA #$00
E569 8D 4B 43 STA $434B ;set record size to #$00
E56C 8D 92 43 STA $4392 ;set number of drive searches to #$00
E56F 8D 86 43 STA $4386 ;set track pointer to #$00
E572 8D 87 43 STA $4387 ;set sector pointer to #$00
E575 A5 8C LDA $8C ;get drive number
E577 29 01 AND #$01 ;mask off bits: 1-7
E579 85 12 STA $12 ;set as current drive number
E57B 09 01 ORA #$01
E57D 8D 97 43 STA $4397 ;set for sector #$01 (decimal 1)
E580 AD 81 43 LDA $4381 ;read file information from table
E583 8D 80 43 STA $4380 ;store as file information for destination copy
E586 60 RTS
******************************* Command: CONCAT (copy file(s) to one file)
E587 20 70 DE JSR $DE70 ;lookup files in stream and fill tables with
information
E58A AD 73 43 LDA $437E ;read file count2
E58D C9 03 CMP #$03 ;less than 3 filenames in command ?
E58F 90 3C BCC $E5CD ;no,
E591 A5 8B LDA $8B ;read destination drive number
E593 C5 8C CMP $8C ;same as source drive number ?
E595 D0 36 BNE $E5CD ;no,
E597 A5 86 LDA $86 ;read number of files appearing in destination
directory block
E599 C5 87 CMP $87 ;same as source drive ?
E59B D0 30 BNE $E5CD ;no,
E59D 20 BC E6 JSR $E6BC ;check if input file exists
E5A0 A9 01 LDA #$01
E5A2 8D 7F 43 STA $437F ;set file count3 to #$01 (decimal 1)
E5A5 20 17 E6 JSR $E617 ;open and set up internal read file
E5A8 20 A1 ED JSR $EDA1 ;file type RELative ?
E5AB F0 04 BEQ $E5B1 ;yes,
E5AD C9 02 CMP #$02 ;file type PRoGram ?
E5AF D0 05 BNE $E5B6 ;no,
E5B1 A9 64 LDA #$64 ;set for "64 FILE TYPE MISMATCH" error
E5B3 20 C3 DB JSR $DBC3 ;jump to process command error routine
E5B6 A9 12 LDA #$12
E5B8 85 16 STA $16 ;set internal write channel to #$12
(decimal 18)
E5BA A5 B3 LDA $B3 ;get internal read channel
E5BC 85 B4 STA $B4 ;store in internal write channel
E5BE A9 FF LDA #$FF
E5C0 85 B3 STA $B3 ;set internal read channel to #$FF
(decimal 255)
E5C2 20 DF F4 JSR $F4DF ;append file
E5C5 A2 02 LDX #$02
E5C7 20 E5 E5 JSR $E5E5 ;copy second file to input file
E5CA 4C 99 DB JMP $DB99 ;jump to indicate command termination status
E5CD 20 D3 E5 JSR $E5D3 ;copy file
E5D0 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Check files for existence
E5D3 20 D9 E6 JSR $E6D9 ;check if file exists
E5D6 A5 8B LDA $8B ;read destination drive number
E5D8 29 01 AND #$01
E5DA 85 12 STA $12 ;set as current drive number
E5DC 20 7C F0 JSR $F07C ;open internal write channel
E5DF 20 A9 F1 JSR $F1A9 ;add file to directory track
E5E2 AE 7D 43 LDX $437D ;read number destination file names
E5E5 8E 7F 43 STX $437F ;set as number of source file names
E5E8 20 17 E6 JSR $E617 ;open and set internal read file for directory
E5EB A9 08 LDA #$08
E5ED 85 A0 STA $A0 ;set EOI flag to #$08 (decimal 8)
E5EF 4C F5 E5 JMP $E5F5 ;proceed to read a byte from disk
E5F2 20 E6 EB JSR $EBE6 ;write out byte to destination file
E5F5 20 57 E6 JSR $E657 ;read byte from source file
E5F8 A9 80 LDA #$80 ;set for EOI (last character)
E5FA 20 B1 F8 JSR $F8B1 ;last character from source file copied ?
E5FD F0 F3 BEQ $E5F2 ;no,
E5FF 20 A1 ED JSR $EDA1 ;file type RELative ?
E602 F0 03 BEQ $E607 ;yes,
E604 20 E6 EB JSR $EBE6 ;write out byte to destination file
E607 AE 7F 43 LDX $437F ;read file count3
E60A E8 INX
E60B EC 7E 43 CPX $437E ;more files to copy ?
E60E 90 D5 BCC $E5E5 ;yes,
E610 A9 12 LDA #$12
E612 85 16 STA $16 ;set internal write channel to #$12
(decimal 18)
E614 4C BA F5 JMP $F5BA ;close channels and files
******************************* Open and set up internal read file
E617 AE 7F 43 LDX $437F ;read number of filenames
E61A B5 8B LDA $8B,X ;get drive number of filename from file data
table
E61C 29 01 AND #$01
E61E 85 12 STA $12 ;set as current drive number
E620 A9 12 LDA #$12
E622 85 13 STA $13 ;set as track #$12 (decimal 18)
E624 B5 86 LDA $86,X ;get sector number for filename from file entry
table
E626 29 1F AND #$1F
E628 85 14 STA $14 ;set as current sector number
E62A 20 6C F0 JSR $F06C ;open internal read channel (secondary
address = 17)
E62D AE 7F 43 LDX $437F ;read number of filenames
E630 B5 86 LDA $86,X ;get filename entry from table
E632 29 E0 AND #$E0
E634 09 02 ORA #$02
E636 20 C1 F0 JSR $F0C1 ;set pointer (.ACC = new pointer value)
E639 AE 7F 43 LDX $437F ;read file count2 position
E63C B5 8B LDA $8B,X ;read file data information for filename
E63E 29 0E AND #$0E ;mask off to get file type
E640 4A LSR
E641 85 C5 STA $C5 ;set as current file type
E643 A9 00 LDA #$00
E645 8D 4B 43 STA $434B ;set record size to #$00 (decimal 0)
E648 20 5B F4 JSR $F45B ;open file for reading
E64B A0 01 LDY #$01 ;set pointer to retrieve file type from disk
E64D 20 A1 ED JSR $EDA1 ;file type RELative ?
E650 F0 01 BEQ $E653 ;yes,
E652 C8 INY
E653 98 TYA ;set for retrieval of track number from disk
E654 4C C1 F0 JMP $F0C1 ;set pointer (.ACC = new pointer value)
******************************* Get byte from internal read channel
E657 A9 11 LDA #$11
E659 85 16 STA $16 ;set internal read channel to #$11 (decimal 17)
E65B 20 95 EF JSR $EF95 ;read byte
E65E 85 18 STA $18 ;store in temporary data byte
E660 A6 15 LDX $15 ;read logical file index
E662 B5 98 LDA $98,X ;retrieve channel status
E664 29 08 AND #$08 ;mask off bits to determine EOI (end of file)
E666 85 A0 STA $A0 ;was EOI (end of file) sent ?
E668 D0 0A BNE $E674 ;yes,
E66A 20 A1 ED JSR $EDA1 ;file type RELative ?
E66D F0 05 BEQ $E674 ;yes,
E66F A9 80 LDA #$80
E671 20 A2 F8 JSR $F8A2 ;set logical index and file type flags
E674 60 RTS
******************************* Command: RENAME (give new name to a current
filename in directory)
E675 20 18 DD JSR $DD18 ;set drive number
E678 A5 8C LDA $8C ;read drive for source filename
E67A 29 01 AND #$01 ;mask off all bits except drive
E67C 85 8C STA $8C ;set as current source filename drive number
E67E C5 8B CMP $8B ;same as destination filename drive number ?
E680 F0 02 BEQ $E684 ;yes,
E682 09 80 ORA #$80
E684 85 8B STA $8B ;set flag for destination drive to #$80
(decimal 128) = search both drives
E686 20 70 DE JSR $DE70 ;lookup files in stream and fill tables with
information
E689 20 D9 E6 JSR $E6D9 ;check if filename exists already
E68C A5 8C LDA $8C ;read source drive number
E68E 29 01 AND #$01
E690 85 12 STA $12 ;set as current drive number
E692 A5 87 LDA $87 ;read sector number for destination filename
E694 48 PHA ;preserve it
E695 29 1F AND #$1F
E697 85 14 STA $14 ;set as current sector number
E699 20 5C F9 JSR $F95C ;read directory sector
E69C 20 82 EC JSR $EC82 ;wait until command is executed
E69F 68 PLA ;retrieve old destination sector number
E6A0 29 E0 AND #$E0
E6A2 09 05 ORA #$05
E6A4 20 C1 F0 JSR $F0C1 ;set new pointer position
E6A7 20 98 FA JSR $FA98 ;get active buffer number
E6AA A8 TAY
E6AB AE 80 43 LDX $4380 ;read position indicator for new filename
E6AE A9 10 LDA #$10 ;set for maximum filename length to #$10
(decimal 16)
E6B0 20 5F E0 JSR $E05F ;transfer filename from command buffer
E6B3 20 63 F9 JSR $F963 ;write directory sector
E6B6 20 82 EC JSR $EC82 ;wait until command is executed
E6B9 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Check if input file is onhand
E6BC A5 8C LDA $8C ;read file type of second filename
E6BE 29 0E AND #$0E ;isolate file type
E6C0 4A LSR
E6C1 85 C5 STA $C5 ;set as current file type
E6C3 AE 7E 43 LDX $437E ;read current filename length
E6C6 CA DEX
E6C7 EC 7D 43 CPX $437D ;new filename length exceeds current length ?
E6CA 90 0C BCC $E6D8 ;no,
E6CC BD 86 43 LDA $4386,X ;read track link for current file name
E6CF 29 7F AND #$7F ;is it #$00 ?
E6D1 D0 F3 BNE $E6C6 ;no,
E6D3 A9 62 LDA #$62 ;set for "62 FILE NOT FOUND" error
E6D5 4C C3 DB JMP $DBC3 ;jump to process command error routine
E6D8 60 RTS
******************************* Check file for existence
E6D9 20 BC E6 JSR $E6BC ;verify that input file is onhand
E6DC BD 86 43 LDA $4386,X ;read track link for current file name
E6DF 29 7F AND #$7F ;does file already exist ?
E6E1 F0 05 BEQ $E6E8 ;no,
E6E3 A9 63 LDA #$63 ;set for "63 FILE EXISTS" error
E6E5 4C C3 DB JMP $DBC3 ;jump to process command error routine
E6E8 CA DEX ;all file names tested from directory for
possible existence with desired file name ?
E6E9 10 F1 BPL $E6DC ;no,
E6EB 60 RTS
******************************* Command: VALIDATE (create new BAM on disk by
calculating total space used on disk by all
active file types. Remove all inproperly
closed files)
E6EC 20 CC DB JSR $DBCC ;verify that proper command structure has been
sent
E6EF 20 FA EC JSR $ECFA ;initialize drive, get DISKETTE NAME and ID
E6F2 20 6C E7 JSR $E76C ;set new Block Allocation Map (BAM)
E6F5 A9 00 LDA #$00
E6F7 8D 98 43 STA $4398 ;set index for 1st available entry to #$00
E6FA 20 D0 DF JSR $DFD0 ;directory entry found ?
E6FD D0 39 BNE $E738 ;yes,
E6FF A9 00 LDA #$00
E701 85 14 STA $14 ;set current sector number to #$00 (decimal 0)
E703 A9 12 LDA #$12
E705 85 13 STA $13 ;set track number to #$12 (decimal 18)
E707 20 44 E7 JSR $E744 ;record in new BAM links for directory track
E70A A5 12 LDA $12 ;read current drive number
E70C 20 5C F6 JSR $F65C ;write new BAM to track 18, sector 0
E70F 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Record blocks in file into BAM
E712 C8 INY
E713 B1 27 LDA ($27),Y ;read track number for current filename
E715 48 PHA ;preserve it
E716 C8 INY
E717 B1 27 LDA ($27),Y ;read sector number for current filename
E719 48 PHA ;preserve it
E71A A0 13 LDY #$13
E71C B1 27 LDA ($27),Y ;read side track number, is it #$00 ?
E71E F0 0A BEQ $E72A ;yes,
E720 85 13 STA $13 ;set side track number as current track number
E722 C8 INY
E723 B1 27 LDA ($27),Y ;read side sector number
E725 85 14 STA $14 ;set side sector number as current sector
number
E727 20 44 E7 JSR $E744 ;record in new BAM side track/sector links for
current RELative file
E72A 68 PLA ;retrieve sector number for current file
E72B 85 14 STA $14 ;set as current sector number
E72D 68 PLA ;retrieve track number for current file
E72E 85 13 STA $13 ;set as current track number
E730 20 44 E7 JSR $E744 ;record new BAM links of current file on disk
E733 20 27 E0 JSR $E027 ;more filenames in directory to do ?
E736 F0 C7 BEQ $E6FF ;no,
******************************* Verify if directory entry found is properly
closed. If so, record in new BAM
E738 A0 00 LDY #$00
E73A B1 27 LDA ($27),Y ;is current filename in directory properly
properly closed ?
E73C 30 D4 BMI $E712 ;yes,
E73E 20 3B E3 JSR $E33B ;delete entry from directory and update BAM
E741 4C 33 E7 JMP $E733 ;do next directory entry
******************************* Record file entry links in new BAM
E744 20 80 D7 JSR $D780 ;set BAM pointer for current drive
E747 20 9A EB JSR $EB9A ;mark current track & sector as used in BAM
E74A 20 6C F0 JSR $F06C ;open internal read channel (secondary
address = 17)
E74D A9 00 LDA #$00
E74F 20 C1 F0 JSR $F0C1 ;set pointer (.ACC = new pointer value)
E752 20 B3 ED JSR $EDB3 ;read byte from data block indicating next
available track for current file
E755 85 13 STA $13 ;set as current track number
E757 20 B3 ED JSR $EDB3 ;read byte from data block indicating next
available sector for current file
E75A 85 14 STA $14 ;set as current sector number
E75C A5 13 LDA $13 ;is this the last data block for current file ?
E75E D0 03 BNE $E763 ;no,
E760 4C 9F EE JMP $EE9F ;free channels associated with secondary
address
E763 20 9A EB JSR $EB9A ;mark current track & sector as used in BAM
E766 20 44 F0 JSR $F044 ;read next data block for current file
E769 4C 4D E7 JMP $E74D ;proceed to test validity
******************************* Create new BAM for diskette
E76C 20 80 D7 JSR $D780 ;set BAM pointer for current drive
E76F A0 00 LDY #$00
E771 A9 12 LDA #$12
E773 91 02 STA ($02),Y ;store #$12 (decimal 18) to position 0 in BAM
E775 C8 INY
E776 98 TYA
E777 91 02 STA ($02),Y ;store #$01 (decimal 1) to position 1 in BAM
E779 C8 INY
E77A C8 INY
E77B C8 INY
E77C A9 00 LDA #$00
E77E 85 04 STA $04 ;clear 1st part of sectors for current track
E780 85 05 STA $05 ;clear 2nd part of sectors for current track
E782 85 06 STA $06 ;clear 3rd part of sectors for current track
E784 98 TYA
E785 4A LSR
E786 4A LSR
E787 20 D2 D7 JSR $D7D2 ;get maximum number of sectors possible for
current track
E78A 91 02 STA ($02),Y ;store maximum sector for current track in BAM
E78C C8 INY
E78D AA TAX
E78E 38 SEC
E78F 26 04 ROL $04 ;set 1st part of sector map for track as free
E791 26 05 ROL $05 ;set 2nd part of sector map for track as free
E793 26 06 ROL $06 ;set 3rd part of sector map for track as free
and set up non valid sectors as used
E795 CA DEX ;all parts initialized ?
E796 D0 F6 BNE $E78E ;no,
E798 B5 04 LDA $04,X ;read part of sector map for current track
E79A 91 02 STA ($02),Y ;store in BAM according to track location
E79C C8 INY
E79D E8 INX
E79E E0 03 CPX #$03 ;all parts for current track written to BAM ?
E7A0 90 F6 BCC $E798 ;no,
E7A2 C0 90 CPY #$90 ;all sector maps for tracks calculated ?
E7A4 90 D6 BCC $E77C ;no,
E7A6 60 RTS
******************************* Checksum byte for $E000
E7A7 45 ??? ;E-ROM checksum
******************************* Command: MEMORY (direct access to DOS)
E7A8 AD 01 43 LDA $4301 ;read 2nd byte from command buffer
E7AB C9 2D CMP #$2D ;is 2nd byte from buffer a dash (-) ?
E7AD D0 48 BNE $E7F7 ;no,
E7AF AD 03 43 LDA $4303 ;read 4th byte from command buffer
E7B2 85 04 STA $04 ;set as LO byte for memory address
E7B4 AD 04 43 LDA $4304 ;read 5th byte from command buffer
E7B7 85 05 STA $05 ;set as HI byte for memory address
E7B9 A0 00 LDY #$00
E7BB AD 02 43 LDA $4302 ;read 3rd byte from command buffer
E7BE C9 57 CMP #$57 ;is 3rd byte a W (Write) ?
E7C0 F0 3A BEQ $E7FC ;yes,
E7C2 C9 52 CMP #$52 ;is 3rd byte a R (Read) ?
E7C4 F0 07 BEQ $E7CD ;yes,
E7C6 C9 45 CMP #$45 ;is 3rd byte a E (Execute) ?
E7C8 D0 2D BNE $E7F7 ;no,
E7CA 6C 04 00 JMP ($0004) ;jump to execute memory address indicated
******************************* Command: MEMORY-READ (direct read from DOS)
E7CD B1 04 LDA ($04),Y ;read byte from specified memory address
E7CF 85 18 STA $18 ;store byte in temporary data location
E7D1 AD 79 43 LDA $4379 ;read length of command string sent from
computer
E7D4 C9 06 CMP #$06 ;more than one memory address to read ?
E7D6 90 19 BCC $E7F1 ;no,
E7D8 AE 05 43 LDX $4305 ;read amount of bytes to still left to retrieve
E7DB CA DEX ;all desired memory bytes read ?
E7DC F0 13 BEQ $E7F1 ;yes,
E7DE 8A TXA
E7DF 18 CLC
E7E0 65 04 ADC $04 ;calculate last memory location to read & send
E7E2 E6 04 INC $04 ;do next memory location
E7E4 85 C4 STA $C4 ;save end address
E7E6 A5 04 LDA $04 ;read LO byte found in TEMP0
E7E8 85 47 STA $47 ;set as LO address byte for error output buffer
E7EA A5 05 LDA $05 ;read HI byte found in TEMP1
E7EC 85 48 STA $48 ;set as HI address byte for error output buffer
E7EE 4C 3B F0 JMP $F03B ;continue reading desired memory locations
E7F1 20 69 ED JSR $ED69 ;find unused read channel
E7F4 4C 32 F0 JMP $F032 ;terminate MEMORY-READ command
******************************* Indicate invalid command structure
E7F7 A9 31 LDA #$31 ;set for "31 SYNTAX ERROR", invalid command
E7F9 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Command: MEMORY-WRITE (direct write to DOS)
E7FC B9 06 43 LDA $4306,Y ;get byte value from command string
E7FF 91 04 STA ($04),Y ;store at desired memory address
E801 C8 INY
E802 CC 05 43 CPY $4305 ;another byte to read and write to a desired
memory address ?
E805 90 F5 BCC $E7FC ;yes,
E807 60 RTS
******************************* User access commands
E808 AC 01 43 LDY $4301 ;read 2nd byte from command buffer
E80B C0 30 CPY #$30 ;is it U0 command ?
E80D D0 09 BNE $E818 ;no,
E80F A9 EA LDA #$EA
E811 85 00 STA $00 ;set LO byte of user jump table to #$EA
E813 A9 FF LDA #$FF
E815 85 01 STA $01 ;set HI byte of user jump table to #$FF
E817 60 RTS
E818 20 1E E8 JSR $E81E ;execute user jump code
E81B 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Execute user jump code
E81E 88 DEY ;decrement user command code by one
E81F 98 TYA
E820 29 0F AND #$0F ;isolate LO order bits
E822 0A ASL ;calculate buffer index
E823 A8 TAY
E824 B1 00 LDA ($00),Y ;read byte from user jump address
E826 85 0A STA $0A ;set as LO byte of Indirect Pointer (IP)
E828 C8 INY ;do next byte
E829 B1 00 LDA ($00),Y ;read byte from user jump address
E82B 85 0B STA $0B ;set as HI byte of Indirect Pointer (IP)
E82D 6C 0A 00 JMP ($000A) ;jump to calculated memory location
******************************* Open direct access buffer from OPEN "#"
E830 AE 79 43 LDX $4379 ;read length of command string
E833 CA DEX ;specific buffer number (#) to open ?
E834 D0 0D BNE $E843 ;yes,
E836 A9 01 LDA #$01 ;set for buffer number (#) 1
E838 20 5E EE JSR $EE5E ;set up buffer number (#)
E83B 4C 87 E8 JMP $E887 ;set logical index table
******************************* Indicate invalid channel structure
E83E A9 70 LDA #$70 ;set for "70 NO CHANNEL", available
E840 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Validate and set up requested buffer
E843 A0 01 LDY #$01
E845 20 10 E9 JSR $E910 ;get requested buffer number
E848 AE 8B 43 LDX $438B ;read desired buffer number
E84B E0 0C CPX #$0C ;is it greater than #$0C (decimal 12) ?
E84D B0 EF BCS $E83E ;yes,
E84F A9 00 LDA #$00
E851 85 04 STA $04 ;clear LO byte of user jump address
E853 85 05 STA $05 ;clear HI byte of user jump address
E855 38 SEC
E856 26 04 ROL $04 ;move LO pointer until requested buffer reached
E858 26 05 ROL $05 ;move HI pointer until requested buffer reached
E85A CA DEX ;buffer pointer set to requested buffer ?
E85B 10 F9 BPL $E856 ;no,
E85D A5 04 LDA $04 ;read buffer available flag
E85F 2D 3E 43 AND $433E ;buffer already in use ?
E862 D0 DA BNE $E83E ;yes,
E864 A5 05 LDA $05 ;read next buffer number to test
E866 2D 3F 43 AND $433F ;already in use ?
E869 D0 D3 BNE $E83E ;yes,
E86B A5 04 LDA $04 ;read buffer bit from table
E86D 0D 3E 43 ORA $433E
E870 8D 3E 43 STA $433E ;indicate buffer as being used
E873 A5 05 LDA $05 ;read next buffer number to test
E875 0D 3F 43 ORA $433F
E878 8D 3F 43 STA $433F ;indicate buffer as being used
E87B A9 00 LDA #$00
E87D 20 5E EE JSR $EE5E ;set up read channel
E880 A6 15 LDX $15 ;read current channel number into .X register
E882 AD 8B 43 LDA $438B ;read current sector number
E885 95 49 STA $49,X ;store sector number in channel sector table
E887 A6 16 LDX $16 ;read current secondary address
E889 B5 A2 LDA $A2,X ;store as current sector channel direction
bits 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
#$FF: = no active channel
E88B 09 40 ORA #$40
E88D 95 A2 STA $A2,X ;set current channel direction to 01 (bit 7-6)
E88F A4 15 LDY $15 ;read current channel number into .Y register
E891 A9 FF LDA #$FF
E893 99 BD 00 STA $00BD,Y ;set last channel character sent to #$FF
(decimal 255)
E896 A9 89 LDA #$89
E898 99 98 00 STA $0098,Y ;set channel ready status to 1000 1001
bit 7 = channel is talker (set to 1)
3 = channel is send EOI (talker only)
0 = channel is listener (set to 1)
E89B B9 49 00 LDA $0049,Y ;read buffer number
E89E 99 B5 00 STA $00B5,Y ;set as 1st character
E8A1 0A ASL
E8A2 AA TAX
E8A3 A9 01 LDA #$01
E8A5 95 29 STA $29,X ;set buffer pointer to beginning of buffer
E8A7 A9 0E LDA #$0E
E8A9 99 90 00 STA $0090,Y ;set to direct file type (bit 7 = search both
drives)
SEQ = type 1
PRG = type 2
USR = type 3
REL = type 4
direct = type 7
E8AC 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Search for second character (-) in command
string for BLOCK commands
E8AF A0 00 LDY #$00
E8B1 A2 00 LDX #$00
E8B3 A9 2D LDA #$2D ;set for dash (-) character
E8B5 20 63 DC JSR $DC63 ;has character been located ?
E8B8 D0 0A BNE $E8C4 ;yes,
******************************* Indicate invalid command structure
E8BA A9 31 LDA #$31 ;set for "31 SYNTAX ERROR", invalid command
E8BC 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Indicate invalid command structure
E8BF A9 30 LDA #$30 ;set for "30 SYNTAX ERROR", general syntax
E8C1 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Decide which command is being requested
E8C4 8A TXA ;any extra parameters found ?
E8C5 D0 F8 BNE $E8BF ;no,
E8C7 A2 05 LDX #$05 ;set pointer to maximum number BLOCK commands
E8C9 B9 00 43 LDA $4300,Y ;read character from input buffer
E8CC DD F1 E8 CMP $E8F1,X ;is it a valid command ?
E8CF F0 05 BEQ $E8D6 ;yes,
E8D1 CA DEX ;character tested against all possible BLOCK
commands from table ?
E8D2 10 F8 BPL $E8CC ;no,
E8D4 30 E4 BMI $E8BA ;yes,
E8D6 8A TXA ;transfer command number value to .ACC
E8D7 09 80 ORA #$80
E8D9 8D 7A 43 STA $437A ;set as current command number value
E8DC 20 03 E9 JSR $E903 ;get command parameters and test
E8DF AD 7A 43 LDA $437A ;read current command number value
E8E2 0A ASL ;double it
E8E3 AA TAX
E8E4 BD F8 E8 LDA $E8F8,X ;read byte for command jump address
E8E7 85 05 STA $05 ;set as HI byte for command jump address
E8E9 BD F7 E8 LDA $E8F7,X ;read byte for command jump address
E8EC 85 04 STA $04 ;set as LO byte for command jump address
E8EE 6C 04 00 JMP ($0004) ;jump to perform desired BLOCK command
******************************* BLOCK command summary
E8F1 41 ??? ;A - (allocate)
E8F2 46 ??? ;F - (free )
E8F3 52 ??? ;R - (read )
E8F4 57 ??? ;W - (write )
E8F5 45 ??? ;E - (execute )
E8F6 50 ??? ;P - (pointer )
******************************* BLOCK - command jump table
E8F7 92 E9 ??? ; - Allocate
E8F9 89 E9 ??? ; - Free
E8FB F5 E9 ??? ; - Read
E8FD 12 EA ??? ; - Write
E8FF 44 EA ??? ; - Execute
E901 5B EA ??? ; - Pointer
******************************* Get command parameters and test validity
E903 A0 00 LDY #$00
E905 A2 00 LDX #$00
E907 A9 3A LDA #$3A ;set for colon (:) character
E909 20 63 DC JSR $DC63 ;colon (:) found in input buffer ?
E90C D0 02 BNE $E910 ;no,
E90E A0 03 LDY #$03 ;set pointer to 4th character in buffer
E910 B9 00 43 LDA $4300,Y ;get 4th character from input buffer
E913 C9 20 CMP #$20 ;is it a space ( ) ?
E915 F0 08 BEQ $E91F ;yes,
E917 C9 1D CMP #$1D ;is it a cursor right (CRSR right) ?
E919 F0 04 BEQ $E91F ;yes,
E91B C9 2C CMP #$2C ;is it a comma (,) ?
E91D D0 07 BNE $E926 ;no,
E91F C8 INY ;move pointer to next character
E920 CC 79 43 CPY $4379 ;end of input buffer ?
E923 90 EB BCC $E910 ;no,
E925 60 RTS
E926 20 35 E9 JSR $E935 ;convert ASCII to HEX (binary) and store
E929 EE 7D 43 INC $437D ;increment current number of parameters
E92C AC 7F 43 LDY $437F ;read total number of parameters
E92F E0 04 CPX #$04 ;reached maximum possible parameters ?
E931 90 EC BCC $E91F ;no,
E933 B0 8A BCS $E8BF ;yes, too many parameters error
******************************* Convert ASCII to HEX (binary) and store
conversion result in appropriate tables
.Y register = pointer into command buffer
E935 A9 00 LDA #$00
E937 85 04 STA $04 ;clear TEMP0
E939 85 05 STA $05 ;clear TEMP1
E93B 85 07 STA $07 ;clear TEMP3
E93D A2 FF LDX #$FF
E93F B9 00 43 LDA $4300,Y ;read next character from input buffer
E942 C9 40 CMP #$40 ;numeric value ?
E944 B0 18 BCS $E95E ;no,
E946 C9 30 CMP #$30 ;ASCII digit ?
E948 90 14 BCC $E95E ;no,
E94A 29 0F AND #$0F ;mask off high order bits
E94C 48 PHA ;preserve new result for later reference
E94D A5 05 LDA $05 ;read current value found in TEMP1
E94F 85 06 STA $06 ;store in TEMP2
E951 A5 04 LDA $04 ;read current value found in TEMP0
E953 85 05 STA $05 ;store in TEMP1
E955 68 PLA ;retrieve previously calculated result
E956 85 04 STA $04 ;store in TEMP0
E958 C8 INY ;increment pointer to next character
E959 CC 79 43 CPY $4379 ;end of input buffer ?
E95C 90 E1 BCC $E93F ;no,
******************************* Convert digit to binary by use of decimal
table
E95E 8C 7F 43 STY $437F ;save current buffer pointer position
E961 18 CLC
E962 A9 00 LDA #$00
E964 E8 INX
E965 E0 03 CPX #$03 ;reached maximum possible decimal numbers
E967 B0 0F BCS $E978 ;yes, too many decimal digits
E969 B4 04 LDY $04,X ;read part of decimal number
E96B 88 DEY ;all parts added up ?
E96C 30 F6 BMI $E964 ;no,
E96E 7D 86 E9 ADC $E986,X ;result calculate above 256 ?
E971 90 F8 BCC $E96B ;no,
E973 18 CLC
E974 E6 07 INC $07 ;HI byte incremented by one ?
E976 D0 F3 BNE $E96B ;yes,
E978 48 PHA
E979 AE 7D 43 LDX $437D ;get parameter number
E97C A5 07 LDA $07 ;read binary value (HI byte)
E97E 9D 86 43 STA $4386,X ;store result as track number for first block
E981 68 PLA
E982 9D 8B 43 STA $438B,X ;store result as sector number of first block
E985 60 RTS
******************************* Decimal table
E986 01 ??? ;decimal value of: 1
E987 0A ??? ;decimal value of: 10
E988 64 ??? ;decimal value of: 100
******************************* BLOCK - FREE command. De-allocate a block
used on disk
E989 20 93 EA JSR $EA93 ;get track and sector number
E98C 20 13 DA JSR $DA13 ;mark a sector as free on a track and BAM
E98F 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* BLOCK - ALLOCATE command. Allocate a block
used on disk
E992 20 93 EA JSR $EA93 ;get track and sector number
E995 A6 12 LDX $12 ;read current drive number
E997 BD E8 D2 LDA $D2E8,X ;read BAM buffer pointer for drive 0
E99A 85 03 STA $03 ;set as buffer to use
E99C 20 8C D7 JSR $D78C ;read sector map from BAM for track
E99F 20 A8 D7 JSR $D7A8 ;valid track and sector number ?
E9A2 B0 26 BCS $E9CA ;yes,
E9A4 A6 14 LDX $14 ;read current sector number
E9A6 E8 INX ;increment value by one
E9A7 86 14 STX $14 ;store as new sector number
E9A9 8E 73 43 STX $4373 ;set as sector number to display if error
E9AC E4 19 CPX $19 ;all sectors on this track done ?
E9AE 90 EF BCC $E99F ;no,
E9B0 A9 00 LDA #$00
E9B2 85 14 STA $14 ;set sector number to 0
E9B4 A6 13 LDX $13 ;read current track number
E9B6 E8 INX ;increment value by one
E9B7 86 13 STX $13 ;set as new track number
E9B9 E0 24 CPX #$24 ;last track on disk ?
E9BB B0 06 BCS $E9C3 ;yes,
E9BD 20 A6 EA JSR $EAA6 ;set sector requested as allocated
E9C0 4C 9C E9 JMP $E99C ;do next requested sector
******************************* No block available error
E9C3 85 13 STA $13 ;set current track number to #$00
E9C5 A9 65 LDA #$65 ;set for "65 NO BLOCK" error
E9C7 4C 53 D9 JMP $D953 ;jump to process error and message
******************************* Test for block availability
E9CA AE 73 43 LDX $4373 ;is desired block available ?
E9CD D0 F6 BNE $E9C5 ;no,
E9CF 20 9A EB JSR $EB9A ;set desired block as used
E9D2 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Test BLOCK-READ parameters and read sector
in buffer
E9D5 20 90 EA JSR $EA90 ;test parameters and get track and sector
E9D8 4C 57 F0 JMP $F057 ;read sector in buffer
******************************* Get a byte from buffer
E9DB 20 AB ED JSR $EDAB ;set buffer pointer
E9DE A1 29 LDA ($29,X) ;read byte from buffer
E9E0 60 RTS
******************************* Read sector from disk to buffer, initialize
pointers, set channel direction
E9E1 20 D5 E9 JSR $E9D5 ;get parameters and read sector
E9E4 A9 00 LDA #$00
E9E6 20 C1 F0 JSR $F0C1 ;set new pointer
E9E9 20 DB E9 JSR $E9DB ;get a byte from buffer
E9EC 99 BD 00 STA $00BD,Y ;set as last data byte to be transferred
E9EF A9 89 LDA #$89
E9F1 99 98 00 STA $0098,Y ;set channel ready status to 1000 1001
bit 7 = channel is talker (set to 1)
3 = channel is send EOI (talker only)
0 = channel is listener (set to 1)
E9F4 60 RTS
******************************* BLOCK - READ command. Read requested
sector from disk
E9F5 20 E1 E9 JSR $E9E1 ;set up to read requested sector
E9F8 20 E5 EF JSR $EFE5 ;read in sector
E9FB 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* U1: (Block-read) command
E9FE 20 03 E9 JSR $E903 ;get command parameters and test validity
EA01 20 E1 E9 JSR $E9E1 ;read sector from disk to buffer, set pointers
EA04 B9 BD 00 LDA $00BD,Y ;read number of bytes to read in
EA07 99 B5 00 STA $00B5,Y ;set as number of bytes to send
EA0A A9 FF LDA #$FF
EA0C 99 BD 00 STA $00BD,Y ;set as last byte to read and send
EA0F 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* BLOCK - WRITE command. Write requested
sector to disk
EA12 20 90 EA JSR $EA90 ;test parameters and get track and sector
EA15 20 E1 F0 JSR $F0E1 ;read active buffer pointer
EA18 A8 TAY
EA19 88 DEY
EA1A C9 02 CMP #$02 ;pointer at start of data range ?
EA1C B0 02 BCS $EA20 ;no,
EA1E A0 01 LDY #$01
EA20 A9 00 LDA #$00
EA22 20 C1 F0 JSR $F0C1 ;set new pointer
EA25 98 TYA
EA26 20 B1 EC JSR $ECB1 ;write byte in buffer
EA29 8A TXA
EA2A 48 PHA
EA2B 20 5B F0 JSR $F05B ;write out sector to disk
EA2E 68 PLA
EA2F AA TAX
EA30 A4 15 LDY $15 ;read current logical index
EA32 20 E7 EF JSR $EFE7 ;set channel for read/write
EA35 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* U2: (Block-write) command
EA38 20 03 E9 JSR $E903 ;get command parameters and test validity
EA3B 20 90 EA JSR $EA90 ;test parameters and get track and sector
EA3E 20 5B F0 JSR $F05B ;write out sector to disk
EA41 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* BLOCK - EXECUTE command. Read requested
sector and execute as machine code
EA44 20 D5 E9 JSR $E9D5 ;test parameter validity and read sector
EA47 A9 00 LDA #$00
EA49 85 04 STA $04 ;set LO byte of jump address to #$00
EA4B A6 A1 LDX $A1 ;read buffer number to use
EA4D BD FF F0 LDA $F0FF,X ;read HI byte from buffer table
EA50 85 05 STA $05 ;set HI byte of jump address
EA52 20 58 EA JSR $EA58 ;execute machine code starting at jump address
EA55 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Execute machine code at assigned jump
address
EA58 6C 04 00 JMP ($0004) ;jump to assigned machine code address and
execute
******************************* BLOCK - POINTER command. Position pointer
to a requested byte in sector
EA5B 20 70 EA JSR $EA70 ;allocate buffer number and open channel
EA5E A5 A1 LDA $A1 ;read buffer number to use
EA60 0A ASL
EA61 AA TAX
EA62 AD 8C 43 LDA $438C ;get new buffer position
EA65 95 29 STA $29,X ;set as LO byte pointer in buffer table
EA67 20 AB ED JSR $EDAB ;set buffer pointer
EA6A 20 E7 EF JSR $EFE7 ;set channel for read/write
EA6D 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Test for allocated buffer and open channel
EA70 A6 81 LDX $81 ;get parameter number
EA72 E6 81 INC $81 ;set to next assignment
EA74 BD 8B 43 LDA $438B,X ;load .ACC with file's secondary address
EA77 A8 TAY
EA78 88 DEY ;eliminate secondary address 0
EA79 88 DEY ;eliminate secondary address 1
EA7A C0 0C CPY #$0C ;is end result #$0C (decimal 12) ?
EA7C 90 05 BCC $EA83 ;yes,
EA7E A9 70 LDA #$70 ;set for "70 NO CHANNEL" error, invalid
secondary address
EA80 4C C3 DB JMP $DBC3 ;jump to process command error routine
EA83 85 16 STA $16 ;set new active secondary address
EA85 20 69 ED JSR $ED69 ;unused read channel found ?
EA88 B0 F4 BCS $EA7E ;no,
EA8A 20 98 FA JSR $FA98 ;get active buffer number
EA8D 85 A1 STA $A1 ;set as current job number
EA8F 60 RTS
******************************* Test block operation parameters. Set up
drive, track, and sector
EA90 20 70 EA JSR $EA70 ;test for allocated buffer and open channel
EA93 A6 81 LDX $81 ;get parameter number
EA95 BD 8B 43 LDA $438B,X ;read drive number of 1st block for file
searches
EA98 29 01 AND #$01 ;mask off default drive bit
EA9A 85 12 STA $12 ;set as current drive number
EA9C BD 8D 43 LDA $438D,X ;read sector number of 1st block for file
searches
EA9F 85 14 STA $14 ;set as current sector number
EAA1 BD 8C 43 LDA $438C,X ;read track number of 1st block for file
searches
EAA4 85 13 STA $13 ;set as current track number
EAA6 20 6E F1 JSR $F16E ;test track and sector validity
EAA9 85 19 STA $19 ;store sector zone in TEMPWORK0
EAAB 4C 2C DA JMP $DA2C ;turn on activity LED specified by drive
******************************* Find relative file
INPUTS: OUTPUTS:
------ -------
.record # (LO byte) .side sector #
.record # (HI byte) .index into side
sector
.record size .pointer into
sector
.pointer into record
EAAE 20 CC EA JSR $EACC ;calculate record's location in bytes
EAB1 20 0E EB JSR $EB0E ;divide result by #$FE (decimal 254)
EAB4 A5 23 LDA $23 ;get remainder of division
EAB6 85 85 STA $85 ;set as pointer into last sector
EAB8 20 11 EB JSR $EB11 ;divide result by #$78 (decimal 120)
EABB E6 85 INC $85 ;increment pointer past track marker
EABD E6 85 INC $85 ;increment pointer past sector marker
EABF A5 1E LDA $1E ;get remainder of division
EAC1 85 83 STA $83 ;set as pointer to current side sector
EAC3 A5 23 LDA $23 ;get remainder of first division
EAC5 0A ASL ;multiply times two
EAC6 18 CLC
EAC7 69 10 ADC #$10 ;calculate side sector index
EAC9 85 84 STA $84 ;set as current side sector index
EACB 60 RTS
******************************* Calculate a record's location in bytes
TOTAL = RCRD # x RCRD SIZE + RCRD PNTR
EACC 20 79 EB JSR $EB79 ;clear RESULT memory
EACF 85 25 STA $25 ;clear ACCUMULATION memory location
EAD1 A6 15 LDX $15 ;read index into pointer for buffer to use
EAD3 B5 59 LDA $59,X ;read LO record pointer found in buffer
EAD5 85 23 STA $23 ;store in calculation area
EAD7 B5 61 LDA $61,X ;read HI record pointer found in buffer
EAD9 85 24 STA $24 ;is HI record pointer value found in
calculation area greater than #$00 ?
EADB D0 04 BNE $EAE1 ;yes,
EADD A5 23 LDA $23 ;is LO record pointer value found in
calculation area equal to #$00 ?
EADF F0 0B BEQ $EAEC ;yes,
EAE1 A5 23 LDA $23 ;get LO byte of record pointer
EAE3 38 SEC
EAE4 E9 01 SBC #$01 ;substract #$01 (decimal 1) from current value
EAE6 85 23 STA $23 ;is new LO record pointer value #$00 ?
EAE8 B0 02 BCS $EAEC ;no,
EAEA C6 24 DEC $24 ;decrement HI record pointer value
EAEC B5 71 LDA $71,X ;read LO record size byte found in table
EAEE 85 04 STA $04 ;store value in TEMP0
EAF0 46 04 LSR $04 ;addition needed before performing
multiplication ?
EAF2 90 03 BCC $EAF7 ;no,
EAF4 20 8D EB JSR $EB8D ;add current results to:
RCRD PNTR/RCRD SIZE/RCRD #
EAF7 20 85 EB JSR $EB85 ;multiply, RCRD PNTR/RCRD SIZE/RCRD # by two
EAFA A5 04 LDA $04 ;multiply/addition calculations finished ?
EAFC D0 F2 BNE $EAF0 ;no,
EAFE A5 82 LDA $82 ;read pointer into record value
EB00 18 CLC
EB01 65 1E ADC $1E ;add #$01 (decimal 1) to current value
EB03 85 1E STA $1E ;is new pointer value smaller than #$00 ?
EB05 90 06 BCC $EB0D ;no,
EB07 E6 1F INC $1F ;incremented RCRD SIZE pointer equal to #$00 ?
EB09 D0 02 BNE $EB0D ;no,
EB0B E6 20 INC $20 ;incremented RCRD # pointer by one
EB0D 60 RTS
******************************* Divide by #$FE (decimal 254)
EB0E A9 FE LDA #$FE
EB10 2C ??? ;** also becomes patch: EB10 2C A9 78 BIT $78A9
******************************* Divide by #$78 (decimal 120)
EB11 A9 78 LDA #$78
******************************* Main division routine
EB13 85 04 STA $04 ;store divisor value to use in TEMP0
EB15 A2 03 LDX #$03
EB17 B5 22 LDA $22,X ;read content from ACCUMULATION table
EB19 48 PHA ;preserve it
EB1A B5 1D LDA $1D,X ;read content from RESULT table
EB1C 95 22 STA $22,X ;transfer to ACCUMULATION table
EB1E 68 PLA ;retrieve value
EB1F 95 1D STA $1D,X ;store in RESULT table
EB21 CA DEX ;all 3 math registers transferred ?
EB22 D0 F3 BNE $EB17 ;no,
EB24 20 79 EB JSR $EB79 ;clear RESULT memory
EB27 A2 00 LDX #$00
EB29 B5 23 LDA $23,X ;read content from ACCUMULATION register +1
EB2B 95 22 STA $22,X ;transfer content to ACCUMULATION register -1
EB2D E8 INX
EB2E E0 04 CPX #$04 ;all 4 registers copied down by one ?
EB30 90 F7 BCC $EB29 ;no,
EB32 A9 00 LDA #$00
EB34 85 25 STA $25 ;clear last ACCUMULATION register
EB36 24 04 BIT $04 ;must a division by 256 be performed ?
EB38 30 09 BMI $EB43 ;yes,
EB3A 06 22 ASL $22 ;set carry flag
EB3C 08 PHP ;preserve it
EB3D 46 22 LSR $22 ;unset carry flag
EB3F 28 PLP ;retrieve value with carry set indicator
EB40 20 86 EB JSR $EB86 ;perform: 2 * (.X/256) = .X/128
EB43 20 8D EB JSR $EB8D ;add current results to:
RCRD PNTR/RCRD SIZE/RCRD #
EB46 20 85 EB JSR $EB85 ;multiply, RCRD PNTR/RCRD SIZE/RCRD # by two
EB49 24 04 BIT $04 ;must a division by 120 be performed ?
EB4B 30 03 BMI $EB50 ;no,
EB4D 20 82 EB JSR $EB82 ;perform: .ACC = 4 * (2 * .ACC) = 8* .ACC
EB50 A5 22 LDA $22 ;read in remainder from calculation
EB52 18 CLC
EB53 65 23 ADC $23 ;add with content from ACCUMULATION register 1
EB55 85 23 STA $23 ;does new ACCUMULATION1 result force a carry ?
EB57 90 06 BCC $EB5F ;no,
EB59 E6 24 INC $24 ;increment ACCUMULATION2, equal to #$00 ?
EB5B D0 02 BNE $EB5F ;no,
EB5D E6 25 INC $25 ;increment ACCUMULATION register 3
EB5F A5 25 LDA $25 ;read value found in ACCUMULATION register 3
EB61 05 24 ORA $24 ;smaller than 256 ?
EB63 D0 C2 BNE $EB27 ;no,
EB65 A5 23 LDA $23 ;read value found in ACCUMULATION register 1
EB67 38 SEC
EB68 E5 04 SBC $04 ;content smaller than divisor factor ?
EB6A 90 0C BCC $EB78 ;yes,
EB6C E6 1E INC $1E ;increment RESULT0, equal to #$00
EB6E D0 06 BNE $EB76 ;no,
EB70 E6 1F INC $1F ;increment RESULT1, equal to #$00
EB72 D0 02 BNE $EB76 ;no,
EB74 E6 20 INC $20 ;increment RESULT2
EB76 85 23 STA $23 ;store new remainder value
EB78 60 RTS
******************************* Clear RESULT memory area
EB79 A9 00 LDA #$00
EB7B 85 1E STA $1E ;clear RESULT register 0
EB7D 85 1F STA $1F ;clear RESULT register 1
EB7F 85 20 STA $20 ;clear RESULT register 2
EB81 60 RTS
******************************* Multiply ACCUMULATION registers by 4
EB82 20 85 EB JSR $EB85 ;multiply ACCUMULATION registers by 2
******************************* Multiply ACCUMULATION registers by 2
EB85 18 CLC
EB86 26 23 ROL $23 ;multiply ACCUMULATION register 1 by 2
EB88 26 24 ROL $24 ;multiply ACCUMULATION register 2 by 2
EB8A 26 25 ROL $25 ;multiply ACCUMULATION register 3 by 2
EB8C 60 RTS
******************************* Add ACCUMULATION register to RESULT
registers:
RESULT = RESULT + ACCUMULATION 1,2,3
EB8D 18 CLC
EB8E A2 FD LDX #$FD ;set for #$FD (decimal 253)
EB90 B5 21 LDA $21,X ;read value from RESULT register 0
EB92 75 26 ADC $26,X ;add value from ACCUMULATION register 0
EB94 95 21 STA $21,X ;store as new RESULT register value
EB96 E8 INX ;all 254 registers added ?
EB97 D0 F7 BNE $EB90 ;no,
EB99 60 RTS
******************************* Mark track, sector, BAM pointer as used
EB9A 20 AF EB JSR $EBAF ;is desired block available ?
EB9D F0 0F BEQ $EBAE ;no,
EB9F B1 02 LDA ($02),Y ;read current block value from bit map
EBA1 5D C9 EB EOR $EBC9,X ;set desired block as used
EBA4 91 02 STA ($02),Y ;store new block value in bit map
EBA6 A4 04 LDY $04
EBA8 B1 02 LDA ($02),Y ;read sector free count for current track
EBAA E9 00 SBC #$00 ;substract one
EBAC 91 02 STA ($02),Y ;store new sector count for track in bit map
EBAE 60 RTS
******************************* Test if requested block available
EBAF A5 13 LDA $13 ;read current track number
EBB1 0A ASL
EBB2 0A ASL ;calculate BAM index for track
EBB3 85 04 STA $04 ;store BAM index for track
EBB5 A5 14 LDA $14 ;read current sector number
EBB7 4A LSR ;divide sector number by 2
EBB8 4A LSR ;divide new value by 2
EBB9 4A LSR ;divide new value by 2
EBBA 38 SEC
EBBB 65 04 ADC $04 ;add 1 to newly calculated result
EBBD A8 TAY
EBBE A5 14 LDA $14 ;read current sector number
EBC0 29 07 AND #$07 ;calculate bit position of sector in BAM
EBC2 AA TAX
EBC3 B1 02 LDA ($02),Y ;read BAM byte corresponding to requested
sector number
EBC5 3D C9 EB AND $EBC9,X ;test if available (.Z flag = 0)
EBC8 60 RTS
******************************* Bit mask table for BAM calculations
EBC9 01 ??? ;decimal 1
EBCA 02 ??? ;decimal 2
EBCB 04 ??? ;decimal 4
EBCC 08 ??? ;decimal 8
EBCD 10 ??? ;decimal 16
EBCE 20 ??? ;decimal 32
EBCF 40 ??? ;decimal 64
EBD0 80 ??? ;decimal 128
******************************* Double buffer: switch the active and
inactive buffers
EBD1 A6 15 LDX $15 ;read current channel number
EBD3 B5 49 LDA $49,X ;read buffer 1 status
EBD5 49 80 EOR #$80 ;change status of buffer 1, active/inactive
EBD7 95 49 STA $49,X ;set new status for buffer 1
EBD9 B5 51 LDA $51,X ;read buffer 2 status
EBDB 49 80 EOR #$80 ;change status of buffer 2, active/inactive
EBDD 95 51 STA $51,X ;set new status for buffer 2
EBDF 20 98 FA JSR $FA98 ;get active buffer number
EBE2 AA TAX
EBE3 4C 82 EC JMP $EC82 ;jump to wait until job done routine
******************************* Set internal write channel and test if
command channel
EBE6 A2 12 LDX #$12
EBE8 86 16 STX $16 ;set current secondary address to #$12
(decimal 18)
EBEA 20 84 ED JSR $ED84 ;find unused internal write channel
EBED 20 2C DA JSR $DA2C ;turn on activity LED specified by drive
EBF0 A5 16 LDA $16 ;read current secondary address
EBF2 C9 0F CMP #$0F ;command channel ?
EBF4 F0 23 BEQ $EC19 ;yes,
EBF6 D0 08 BNE $EC00 ;no,
******************************* Main routine to write to a channel
EBF8 A5 17 LDA $17 ;read original secondary address value
EBFA 29 8F AND #$8F
EBFC C9 0F CMP #$0F ;command channel ?
EBFE B0 19 BCS $EC19 ;yes,
EC00 20 A1 ED JSR $EDA1 ;read current file type, SEQ ?
EC03 B0 05 BCS $EC0A ;no,
EC05 A5 18 LDA $18 ;get data byte
EC07 4C 19 EE JMP $EE19 ;jump to write byte to channel for SEQ file
******************************* Test if file type USR, if not write to REL
file
EC0A D0 03 BNE $EC0F ;USR ? yes,
EC0C 4C 97 FB JMP $FB97 ;jump to write to REL
******************************* Write to USR file, get next data byte
EC0F A5 18 LDA $18 ;get data byte
EC11 20 B1 EC JSR $ECB1 ;write byte to channel
EC14 A4 15 LDY $15 ;read channel number for next data byte
EC16 4C E7 EF JMP $EFE7 ;jump to direct file character get routine
******************************* Set for maximum channel, test buffer
pointer or write until last byte
EC19 A9 06 LDA #$06
EC1B 85 15 STA $15 ;set for highest possible channel number
EC1D 20 E1 F0 JSR $F0E1 ;read active buffer pointer
EC20 C9 3B CMP #$3B ;is buffer full ?
EC22 F0 05 BEQ $EC29 ;yes,
EC24 A5 18 LDA $18 ;get data byte
EC26 20 B1 EC JSR $ECB1 ;write byte to channel
EC29 A5 A0 LDA $A0 ;last byte (EOI) ?
EC2B F0 01 BEQ $EC2E ;yes
EC2D 60 RTS
******************************* Set command waiting flag
EC2E EE 47 43 INC $4347 ;increment command waiting flag
EC31 60 RTS
******************************* Test if job done. If not done, continue.
If OK then return, else redo job
EC32 BD 03 10 LDA $1003,X ;is current job completed ?
EC35 30 49 BMI $EC80 ;no,
EC37 C9 02 CMP #$02 ;job completed properly ?
EC39 90 3D BCC $EC78 ;yes,
EC3B DE 5D 43 DEC $435D,X ;job to be retried ?
EC3E 10 3A BPL $EC7A ;yes,
EC40 2C 9E 43 BIT $439E ;job queue returned with hard error ?
EC43 30 33 BMI $EC78 ;no,
EC45 2C 5C 43 BIT $435C ;has the amount of attempts to correct the
problem expired ?
EC48 30 29 BMI $EC73 ;yes,
EC4A 98 TYA
EC4B 48 PHA
EC4C BD 4E 43 LDA $434E,X ;read last job executed
EC4F 29 01 AND #$01 ;set corresponding drive number for job
EC51 09 C0 ORA #$C0 ;set for head placement of drive to track 1
EC53 9D 03 10 STA $1003,X ;set current job for drive to: BUMP
EC56 BD 03 10 LDA $1003,X ;is job completed ?
EC59 30 FB BMI $EC56 ;no,
******************************* Retry current job .Y amount of times
EC5B AD 5C 43 LDA $435C ;read number of attempts value to determine
how many times job can be reattempted
EC5E 29 3F AND #$3F ;isolate recovery count value
EC60 A8 TAY
EC61 BD 4E 43 LDA $434E,X ;read last job executed
EC64 9D 03 10 STA $1003,X ;set as current job
EC67 BD 03 10 LDA $1003,X ;is job completed ?
EC6A 30 FB BMI $EC67 ;no,
EC6C C9 02 CMP #$02 ;job completed properly ?
EC6E 90 06 BCC $EC76 ;yes,
EC70 88 DEY ;has the amount of attempts to correct the
problem expired ?
EC71 D0 EE BNE $EC61 ;no,
EC73 4C 1C D9 JMP $D91C ;jump to controller error entry point routine
******************************* Job done properly, restore .Y register to
original value
EC76 68 PLA
EC77 A8 TAY
EC78 18 CLC ;set .C to indicate no jobs present
EC79 60 RTS
******************************* Set last job executed back up for a retry
EC7A BD 4E 43 LDA $434E,X ;read last job executed
EC7D 9D 03 10 STA $1003,X ;set as current job
EC80 38 SEC ;set .C to indicate job present
EC81 60 RTS
******************************* Test if job completed, clear job present
flag when job completed properly
EC82 20 32 EC JSR $EC32 ;has job been executed and terminated ?
EC85 B0 FB BCS $EC82 ;no,
EC87 48 PHA
EC88 A9 00 LDA #$00
EC8A 8D 9E 43 STA $439E ;clear job present flag
EC8D 68 PLA
EC8E 60 RTS
******************************* Set track, sector, ID for current buffer
EC8F 20 98 FA JSR $FA98 ;get active buffer number
EC92 0A ASL ;multiply by 2
EC93 0A ASL ;multiply new value by 2
EC94 0A ASL ;multiply new value by 2
EC95 A8 TAY
EC96 A5 13 LDA $13 ;read current track number
EC98 99 23 10 STA $1023,Y ;set as job track number
EC9B A5 14 LDA $14 ;read current sector number
EC9D 99 24 10 STA $1024,Y ;set as job sector number
ECA0 A5 12 LDA $12 ;read current drive number
ECA2 0A ASL
ECA3 AA TAX
ECA4 BD 40 43 LDA $4340,X ;read ID1 for current drive
ECA7 99 21 10 STA $1021,Y ;set as job ID1 for disk
ECAA BD 41 43 LDA $4341,X ;read ID2 for current drive
ECAD 99 22 10 STA $1022,Y ;set as job ID2 for disk
ECB0 60 RTS
******************************* Test for valid buffer
ECB1 48 PHA
ECB2 20 98 FA JSR $FA98 ;is there and active buffer number ?
ECB5 10 06 BPL $ECBD ;yes,
ECB7 68 PLA
ECB8 A9 61 LDA #$61 ;set for "61 FILE NOT OPEN" error
ECBA 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Store byte in assigned buffer position
ECBD 0A ASL ;multiply buffer number by 2
ECBE AA TAX
ECBF 68 PLA
ECC0 81 29 STA ($29,X) ;store byte in assigned buffer position
ECC2 F6 29 INC $29,X ;increment buffer pointer
ECC4 60 RTS
******************************* Command: INITIALIZE (read BAM)
ECC5 20 CC DB JSR $DBCC ;test for proper syntax and drive number
ECC8 20 FA EC JSR $ECFA ;read BAM from diskette
ECCB AD 91 43 LDA $4391 ;both drives request initialisation ?
ECCE 10 0C BPL $ECDC ;no,
ECD0 20 86 DD JSR $DD86 ;toggle drive number
ECD3 20 2C DA JSR $DA2C ;turn on activity LED specified by drive
ECD6 20 FA EC JSR $ECFA ;read BAM from diskette
ECD9 20 86 DD JSR $DD86 ;toggle drive number
ECDC 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Set up job queue and locate track 18,
sector 0
ECDF A5 12 LDA $12 ;read current drive number
ECE1 18 CLC
ECE2 69 0C ADC #$0C ;add job queue value to drive value
ECE4 85 A1 STA $A1 ;set as current job number
ECE6 A2 12 LDX #$12
ECE8 86 13 STX $13 ;set track number to #$12 (decimal 18)
ECEA A2 00 LDX #$00
ECEC 86 14 STX $14 ;set sector number to #$00
ECEE 20 92 EC JSR $EC92 ;set track, sector, ID's for current drive
ECF1 A6 A1 LDX $A1 ;read current job number
ECF3 A5 12 LDA $12 ;read current drive number
ECF5 09 B0 ORA #$B0 ;set for search of sector #$00 on specified
drive: SEEK
ECF7 4C 9D F1 JMP $F19D ;perform requested job
******************************* Read BAM from diskette in current drive
ECFA 20 54 EF JSR $EF54 ;clear all channels
ECFD 20 DF EC JSR $ECDF ;set up job queue and locate track 18, sector 0
ED00 A9 00 LDA #$00
ED02 99 24 10 STA $1024,Y ;set job track number to #$00
ED05 A5 12 LDA $12 ;read current drive number
ED07 09 80 ORA #$80 ;set job type to READ
ED09 20 9D F1 JSR $F19D ;perform requested job
ED0C A5 12 LDA $12 ;read current drive drive number
ED0E 0A ASL
ED0F AA TAX
ED10 B9 21 10 LDA $1021,Y ;read job disk ID1 number
ED13 9D 40 43 STA $4340,X ;set as ID1 value
ED16 B9 22 10 LDA $1022,Y ;read job disk ID2 number
ED19 9D 41 43 STA $4341,X ;set as ID2 value
ED1C 60 RTS
******************************* Start double buffering, use track and sector
as starting block
ED1D 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
ED20 20 41 ED JSR $ED41 ;set for READ job
ED23 20 82 EC JSR $EC82 ;wait until job completed
ED26 20 B3 ED JSR $EDB3 ;read 1st byte from second data block
ED29 85 13 STA $13 ;set as current track
ED2B 20 B3 ED JSR $EDB3 ;read 2nd byte from second data block
ED2E 85 14 STA $14 ;set as current sector
ED30 A5 13 LDA $13 ;last data block in file chain ?
ED32 D0 01 BNE $ED35 ;no,
ED34 60 RTS
******************************* Begin double buffering
ED35 20 D1 EB JSR $EBD1 ;perform double buffering for data block 1
ED38 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
ED3B 20 41 ED JSR $ED41 ;set for READ job
ED3E 4C D1 EB JMP $EBD1 ;jump to perform double buffering for data
block 2
******************************* Set for READ job
ED41 A9 80 LDA #$80 ;is job type other than read ?
ED43 D0 02 BNE $ED47 ;no,
******************************* Set for WRITE job
ED45 A9 90 LDA #$90 ;set job type to write
******************************* Perform requested job
ED47 8D 3C 43 STA $433C ;set temporary job command
ED4A 20 98 FA JSR $FA98 ;get active buffer number
ED4D AA TAX
ED4E 20 0E F1 JSR $F10E ;test track & sector validity, read buffer
number
ED51 8A TXA
ED52 48 PHA ;preserve buffer number
ED53 0A ASL ;calculate index into buffer table
ED54 AA TAX
ED55 A9 00 LDA #$00
ED57 95 29 STA $29,X ;store #$00 (decimal 0) in calculate buffer
table
ED59 20 A1 ED JSR $EDA1 ;read current file type
ED5C C9 04 CMP #$04 ;is it SEQ ?
ED5E B0 06 BCS $ED66 ;no,
ED60 F6 59 INC $59,X ;increment LO byte of block count, still smaller
than #$FF (decimal 255) ?
ED62 D0 02 BNE $ED66 ;yes,
ED64 F6 61 INC $61,X ;increment HI byte of block count
ED66 68 PLA ;restore previous buffer number
ED67 AA TAX
ED68 60 RTS
******************************* Find internal read channel
ED69 A5 16 LDA $16 ;read current secondary address
ED6B C9 13 CMP #$13 ;is secondary address greater than #$13
(decimal 19) ?
ED6D 90 02 BCC $ED71 ;no,
ED6F 29 0F AND #$0F ;mask off secondary address above #$0F
(decimal 15)
ED71 C9 0F CMP #$0F ;secondary address #$0F (decimal 15) ?
ED73 D0 02 BNE $ED77 ;no,
ED75 A9 10 LDA #$10 ;set secondary address error value to #$10
(decimal 16)
ED77 AA TAX
ED78 38 SEC ;set channel status flag
ED79 B5 A2 LDA $A2,X ;channel status set for read mode ?
bit 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
ED7B 30 06 BMI $ED83 ;no,
ED7D 29 0F AND #$0F ;establish internal channel read channel number
ED7F 85 15 STA $15 ;set as current logical index
ED81 AA TAX
ED82 18 CLC ;clear channel status flag
ED83 60 RTS
******************************* Find internal write channel
ED84 A5 16 LDA $16 ;read current secondary address
ED86 C9 13 CMP #$13 ;is secondary address greater than #$13
(decimal 19) ?
ED88 90 02 BCC $ED8C ;no,
ED8A 29 0F AND #$0F ;mask off secondary address above #$0F
(decimal 15)
ED8C AA TAX
ED8D B5 A2 LDA $A2,X ;channel status set for write mode ?
bit 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
ED8F A8 TAY ;preserve channel status
ED90 0A ASL ;flag set for write channel ?
ED91 90 0A BCC $ED9D ;no,
ED93 30 0A BMI $ED9F ;channel available ? no,
ED95 98 TYA ;retrieve channel status
ED96 29 0F AND #$0F ;mask off all high order bits
ED98 85 15 STA $15 ;set as current active channel
ED9A AA TAX
ED9B 18 CLC ;clear channel status flag
ED9C 60 RTS
ED9D 30 F6 BMI $ED95 ;channel inactive ? yes,
ED9F 38 SEC ;set channel status flag
EDA0 60 RTS
******************************* Get current file type
EDA1 A6 15 LDX $15 ;read current channel number
EDA3 B5 90 LDA $90,X ;get appropriate file type for channel
EDA5 4A LSR ;divide file type by 2
EDA6 29 07 AND #$07 ;mask off high order bits eliminating file
type 7 (direct)
EDA8 C9 04 CMP #$04 ;REL file type ? (.Z=1 if yes)
EDAA 60 RTS
******************************* Set buffer pointers
.X = buffer number
.Y = channel number
EDAB 20 98 FA JSR $FA98 ;get active buffer number
EDAE 0A ASL ;multiply buffer number by 2
EDAF AA TAX
EDB0 A4 15 LDY $15 ;read current channel number
EDB2 60 RTS
******************************* Read byte from active buffer and set .Z flag
if last data byte
EDB3 20 AB ED JSR $EDAB ;set buffer pointers
EDB6 B9 BD 00 LDA $00BD,Y ;last character pointer in buffer #$00 ?
EDB9 F0 12 BEQ $EDCD ;yes,
EDBB A1 29 LDA ($29,X) ;read data byte from buffer
EDBD 48 PHA ;preserve it
EDBE B5 29 LDA $29,X ;read LO pointer of buffer pointer
EDC0 D9 BD 00 CMP $00BD,Y ;end of buffer reached ?
EDC3 D0 04 BNE $EDC9 ;no,
EDC5 A9 FF LDA #$FF
EDC7 95 29 STA $29,X ;set LO buffer pointer to #$FF (decimal 255)
EDC9 68 PLA ;retrieve data byte
EDCA F6 29 INC $29,X ;set LO buffer pointer to #$00
EDCC 60 RTS
EDCD A1 29 LDA ($29,X) ;read data byte from buffer
EDCF F6 29 INC $29,X ;move buffer pointer to next data byte in
buffer
EDD1 60 RTS
******************************* Get byte from file and read next block of
file if needed. Set EOI if end of file
EDD2 20 B3 ED JSR $EDB3 ;last byte from active buffer read ?
EDD5 D0 36 BNE $EE0D ;no,
EDD7 85 18 STA $18 ;store data byte
EDD9 B9 BD 00 LDA $00BD,Y ;end of buffer reached ?
EDDC F0 08 BEQ $EDE6 ;no,
EDDE A9 80 LDA #$80 ;set for EOI byte marker
EDE0 99 98 00 STA $0098,Y ;store EOI on channel status
bit 7: = 1 (channel is talker to IEEE)
3: = 0 (send EOI on next byte)
0: = 1 (channel is listener to IEEE)
EDE3 A5 18 LDA $18 ;retrieve last data byte read
EDE5 60 RTS
******************************* Read next block of file
EDE6 20 D1 EB JSR $EBD1 ;toggle current active and inactive buffers
EDE9 A9 00 LDA #$00
EDEB 20 C1 F0 JSR $F0C1 ;set new pointer position
EDEE 20 B3 ED JSR $EDB3 ;read byte from active buffer
EDF1 C9 00 CMP #$00 ;last sector of file ?
EDF3 F0 19 BEQ $EE0E ;yes,
EDF5 85 13 STA $13 ;set as current track number
EDF7 20 B3 ED JSR $EDB3 ;read byte from active buffer
EDFA 85 14 STA $14 ;set as current sector number
EDFC 20 D1 EB JSR $EBD1 ;toggle current active and inactive buffers
EDFF 20 4F EE JSR $EE4F ;set drive number according to last job done
EE02 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
EE05 20 41 ED JSR $ED41 ;set for READ job
EE08 20 D1 EB JSR $EBD1 ;toggle current active and inactive buffers
EE0B A5 18 LDA $18 ;read last data byte stored
EE0D 60 RTS
******************************* Set last character position for last byte of
file
EE0E 20 B3 ED JSR $EDB3 ;read byte from active buffer
EE11 A4 15 LDY $15 ;read current channel number
EE13 99 BD 00 STA $00BD,Y ;set as last character position in buffer
EE16 A5 18 LDA $18 ;read last data byte stored
EE18 60 RTS
******************************* Write a byte to channel and write buffer out
to disk if full
EE19 20 B1 EC JSR $ECB1 ;is current buffer full ?
EE1C F0 01 BEQ $EE1F ;yes,
EE1E 60 RTS
EE1F 20 4F EE JSR $EE4F ;set drive number according to last job done
EE22 20 AF D6 JSR $D6AF ;find free sector on disk
EE25 A9 00 LDA #$00
EE27 20 C1 F0 JSR $F0C1 ;set new pointer position to beginning of
buffer
EE2A A5 13 LDA $13 ;read current track number
EE2C 20 B1 EC JSR $ECB1 ;write track number in buffer
EE2F A5 14 LDA $14 ;read current sector number
EE31 20 B1 EC JSR $ECB1 ;write sector number in buffer
EE34 20 45 ED JSR $ED45 ;set for WRITE job
EE37 20 D1 EB JSR $EBD1 ;toggle current active and inactive buffers
EE3A 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
EE3D A9 02 LDA #$02
EE3F 4C C1 F0 JMP $F0C1 ;set new pointer position to 3rd byte in buffer
******************************* Increment pointer of active buffer
EE42 85 04 STA $04 ;store current pointer position
EE44 20 E1 F0 JSR $F0E1 ;read active buffer pointer
EE47 18 CLC
EE48 65 04 ADC $04 ;add buffer pointer value to current buffer
pointer position value
EE4A 95 29 STA $29,X ;store value in buffer
EE4C 85 27 STA $27 ;store value in directory buffer
EE4E 60 RTS
******************************* Set drive number indicated by last job in
active buffer
EE4F 20 98 FA JSR $FA98 ;get active buffer number
EE52 AA TAX
EE53 BD 4E 43 LDA $434E,X ;read last job executed
EE56 29 01 AND #$01 ;calculate appropriate drive number
EE58 85 12 STA $12 ;set as current drive number
EE5A 60 RTS
******************************* Set for opening of new write channel
EE5B 38 SEC ;write channel active ?
EE5C B0 01 BCS $EE5F ;yes,
******************************* Set for opening of new read channel
EE5E 18 CLC ;activate read channel
******************************* Perform opening of desired channel
EE5F 08 PHP ;preserve read/write flag status
EE60 85 04 STA $04 ;store number of buffers needed
EE62 20 9F EE JSR $EE9F ;free read/write channels
EE65 20 79 EF JSR $EF79 ;find an available channel and allocate it
EE68 85 15 STA $15 ;set as current channel number
EE6A A6 16 LDX $16 ;read current secondary address
EE6C 28 PLP ;retrieve read/write status, open
read channel ?
EE6D 90 02 BCC $EE71 ;yes,
EE6F 09 80 ORA #$80 ;set for open write channel
EE71 95 A2 STA $A2,X ;store channel status
bits 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
EE73 29 3F AND #$3F ;establish number of internal channels
EE75 A8 TAY
EE76 A9 FF LDA #$FF
EE78 99 49 00 STA $0049,Y ;de-allocate associated flags for buffer
EE7B 99 51 00 STA $0051,Y ;de-allocate associated buffer
EE7E C6 04 DEC $04 ;all buffers needed allocated ?
EE80 30 1C BMI $EE9E ;yes,
EE82 20 FE EE JSR $EEFE ;new buffer allocated ?
EE85 10 08 BPL $EE8F ;yes,
******************************* Indicate channel unavailability
EE87 20 CA EE JSR $EECA ;release all allocated buffers
EE8A A9 70 LDA #$70 ;set for "70 NO CHANNEL", no channel available
EE8C 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* De-allocate additional buffer
EE8F 99 49 00 STA $0049,Y ;de-allocate associated flags for buffer
EE92 C6 04 DEC $04 ;all buffers needed allocated ?
EE94 30 08 BMI $EE9E ;yes,
EE96 20 FE EE JSR $EEFE ;new buffer allocated ?
EE99 30 EC BMI $EE87 ;no,
EE9B 99 51 00 STA $0051,Y ;de-allocate associated buffer
EE9E 60 RTS
******************************* Test current secondary address for command
channel.
EE9F A5 16 LDA $16 ;read current secondary address
EEA1 C9 0F CMP #$0F ;is secondary address #$0F (decimal 15) ?
EEA3 D0 01 BNE $EEA6 ;no,
EEA5 60 RTS
******************************* Free read/write channels
EEA6 A6 16 LDX $16 ;read current secondary address
EEA8 B5 A2 LDA $A2,X ;read current channel status
bits 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
EEAA C9 FF CMP #$FF ;is this an active channel ?
EEAC F0 1B BEQ $EEC9 ;no,
EEAE 29 3F AND #$3F ;calculate channel number
EEB0 85 15 STA $15 ;set as current channel number
EEB2 A9 FF LDA #$FF
EEB4 95 A2 STA $A2,X ;set associated channel to inactive
bits 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
EEB6 20 CA EE JSR $EECA ;release all allocated buffers
EEB9 A6 15 LDX $15 ;read current channel number
EEBB A9 01 LDA #$01 ;set bit flag to "channel free"
EEBD CA DEX ;all channels done ?
EEBE 30 03 BMI $EEC3 ;yes,
EEC0 0A ASL ;multiply bit flag by 2 now gives #$00 result ?
EEC1 D0 FA BNE $EEBD ;no,
EEC3 0D 48 43 ORA $4348 ;calculate free channels left
EEC6 8D 48 43 STA $4348 ;store as new amount of free channels left
EEC9 60 RTS
******************************* Release buffers and corresponding channel
EECA A6 15 LDX $15 ;get current channel number
EECC B5 49 LDA $49,X ;read buffer #0 status
EECE C9 FF CMP #$FF ;is it already free ?
EED0 F0 09 BEQ $EEDB ;yes,
EED2 48 PHA ;preserve current buffer #0 index value
EED3 A9 FF LDA #$FF
EED5 95 49 STA $49,X ;set buffer #0 status to free, #$FF
(decimal 255)
EED7 68 PLA ;retrieve buffer value
EED8 20 34 EF JSR $EF34 ;free buffer #0
EEDB A6 15 LDX $15 ;get current channel number
EEDD B5 51 LDA $51,X ;read buffer #1 status
EEDF C9 FF CMP #$FF ;is it already free ?
EEE1 F0 09 BEQ $EEEC ;yes,
EEE3 48 PHA ;preserve current buffer #1 index value
EEE4 A9 FF LDA #$FF
EEE6 95 51 STA $51,X ;set buffer #1 status to free, #$FF
(decimal 255)
EEE8 68 PLA ;retrieve buffer value
EEE9 20 34 EF JSR $EF34 ;free buffer #1
EEEC A6 15 LDX $15 ;get current channel number
EEEE B5 79 LDA $79,X ;read side sector status
EEF0 C9 FF CMP #$FF ;is it already free ?
EEF2 F0 09 BEQ $EEFD ;yes,
EEF4 48 PHA ;preserve side sector value
EEF5 A9 FF LDA #$FF
EEF7 95 79 STA $79,X ;set side sector to free, #$FF
(decimal 255)
EEF9 68 PLA
EEFA 20 34 EF JSR $EF34 ;free side sector buffer
EEFD 60 RTS
******************************* Get a free buffer number. If successful,
initialize $1003 and $434E
.Y = channel number
.ACC = buffer number
EEFE A9 FF LDA #$FF
EF00 85 05 STA $05 ;clear TEMP1 flag
EF02 A2 0F LDX #$0F
EF04 2E 3E 43 ROL $433E ;displace buffer index by one bit
EF07 2E 3F 43 ROL $433F ;displace buffer index by one bit
EF0A B0 05 BCS $EF11 ;buffer occupied ? yes,
EF0C 86 05 STX $05 ;store free buffer location
EF0E 38 SEC ;allocate buffer, buffer allocated ?
EF0F B0 18 BCS $EF29 ;yes,
EF11 CA DEX ;all buffers tested for availability ?
EF12 10 F0 BPL $EF04 ;no,
EF14 A6 05 LDX $05 ;read buffer status, ok to steal ?
EF16 30 0F BMI $EF27 ;no,
EF18 BD 03 10 LDA $1003,X ;job in progress ?
EF1B 30 FB BMI $EF18 ;yes,
EF1D A9 00 LDA #$00
EF1F 9D 03 10 STA $1003,X ;clear assigned job queue
EF22 A5 12 LDA $12 ;read current drive number
EF24 9D 4E 43 STA $434E,X ;store drive number in last job perform flag
for assigned job queue
EF27 8A TXA ;give up, no buffer available
EF28 60 RTS
******************************* Locate a buffer to steal
EF29 2E 3E 43 ROL $433E ;displace buffer index by one bit
EF2C 2E 3F 43 ROL $433F ;displace buffer index by one bit
EF2F CA DEX ;all buffer indexes tested ?
EF30 10 F7 BPL $EF29 ;no,
EF32 30 E0 BMI $EF14 ;found a possible buffer ?
******************************* Free buffer index
EF34 29 0F AND #$0F ;mask off HI order bits
EF36 A8 TAY ;transfer result to .Y register
EF37 C8 INY ;increment counter
EF38 A2 10 LDX #$10 ;set for total number of buffers #$10
(decimal 16)
EF3A 6E 3F 43 ROR $433F ;displace buffer index by one bit
EF3D 6E 3E 43 ROR $433E ;displace buffer index by one bit
EF40 88 DEY ;have we counted down to #$00 ?
EF41 D0 01 BNE $EF44 ;no,
EF43 18 CLC ;clear buffer
EF44 CA DEX ;all buffers free ?
EF45 10 F3 BPL $EF3A ;no,
EF47 60 RTS
******************************* Clear all channels except COMMAND channel
EF48 A9 0E LDA #$0E
EF4A 85 16 STA $16 ;set current secondary address to #$0E
(decimal 14)
EF4C 20 9F EE JSR $EE9F ;free requested read/write channel
EF4F C6 16 DEC $16 ;all channels closed ?
EF51 D0 F9 BNE $EF4C ;no,
EF53 60 RTS
******************************* Close all channels except COMMAND channel
EF54 A9 0E LDA #$0E
EF56 85 16 STA $16 ;set current secondary address to #$0E
(decimal 14)
EF58 A6 16 LDX $16 ;get current secondary address number
EF5A B5 A2 LDA $A2,X ;read current channel status
bit 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
EF5C C9 FF CMP #$FF ;channel already closed ?
EF5E F0 14 BEQ $EF74 ;yes,
EF60 29 3F AND #$3F ;mask off HI order bits
EF62 85 15 STA $15 ;set as current channel number
EF64 20 98 FA JSR $FA98 ;get active buffer number
EF67 AA TAX
EF68 BD 4E 43 LDA $434E,X ;read next job code
EF6B 29 01 AND #$01 ;test drive number
EF6D C5 12 CMP $12 ;ok to close channel for requested drive ?
EF6F D0 03 BNE $EF74 ;no,
EF71 20 9F EE JSR $EE9F ;free requested read/write channel
EF74 C6 16 DEC $16 ;all channels done ?
EF76 10 E0 BPL $EF58 ;no,
EF78 60 RTS
******************************* Find a free logical index to use
.Y = counter for channels
EF79 A0 00 LDY #$00
EF7B A9 01 LDA #$01 ;set for testing of a free channel
EF7D 2C 48 43 BIT $4348 ;free channel available ?
EF80 D0 09 BNE $EF8B ;yes,
EF82 C8 INY ;increment channel counter
EF83 0A ASL ;all possible channels tested ?
EF84 D0 F7 BNE $EF7D ;no,
EF86 A9 70 LDA #$70 ;set for "70 NO CHANNEL" error
EF88 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Mark free logical index as used in table
.ACC = new logical index
EF8B 49 FF EOR #$FF ;toggle bit mask
EF8D 2D 48 43 AND $4348 ;mark bit position as used
EF90 8D 48 43 STA $4348 ;store new logical index status
EF93 98 TYA ;transfer new logical index status
EF94 60 RTS
******************************* Get a byte from a channel
EF95 20 69 ED JSR $ED69 ;find internal read channel
EF98 20 2C DA JSR $DA2C ;turn on activity LED specified by drive
EF9B 20 A3 EF JSR $EFA3 ;read a byte over channel from any file type
EF9E A6 15 LDX $15 ;read current channel number
EFA0 B5 B5 LDA $B5,X ;read channel data byte
EFA2 60 RTS
******************************* Read a byte over channel from any file type
EFA3 A6 15 LDX $15 ;read current channel number
EFA5 20 A1 ED JSR $EDA1 ;current file type REL ?
EFA8 D0 03 BNE $EFAD ;no,
EFAA 4C 04 FC JMP $FC04 ;jump to read byte from RELative file routine
******************************* Read a byte from file
EFAD A5 16 LDA $16 ;get current secondary address
EFAF C9 0F CMP #$0F ;is this the command channel ?
EFB1 F0 59 BEQ $F00C ;yes,
EFB3 B5 98 LDA $98,X ;read channel status
bit 7 = 1 (channel is talker to IEEE)
3 = 0 (send EOI on next byte, talker only)
0 = 1 (channel is listener to IEEE)
EFB5 29 08 AND #$08 ;last byte sent was EOI ?
EFB7 D0 13 BNE $EFCC ;no,
EFB9 20 A1 ED JSR $EDA1 ;get current file type
EFBC C9 07 CMP #$07 ;random access file type under use ?
EFBE D0 07 BNE $EFC7 ;no,
EFC0 A9 89 LDA #$89 ;set for "direct file remains active" status
EFC2 95 98 STA $98,X ;store new channel status
bit 7 = 1 (channel is talker to IEEE)
3 = 0 (send EOI on next byte, talker only)
0 = 1 (channel is listener to IEEE)
EFC4 4C D7 EF JMP $EFD7 ;jump to get byte from RELative file buffer
******************************* EOI received, set new channel status
EFC7 A9 00 LDA #$00 ;set channel status to "NOT READY"
EFC9 95 98 STA $98,X ;store new channel status
bit 7 = 1 (channel is talker to IEEE)
3 = 0 (send EOI on next byte, talker only)
0 = 1 (channel is listener to IEEE)
EFCB 60 RTS
******************************* Test if LOAD command received
EFCC A5 16 LDA $16 ;current secondary address #$00 ?
EFCE F0 31 BEQ $F001 ;yes,
******************************* Test file type for random access
EFD0 20 A1 ED JSR $EDA1 ;get current file type
EFD3 C9 04 CMP #$04 ;file type RELative ?
EFD5 90 22 BCC $EFF9 ;no,
******************************* Read byte from RELative file
EFD7 20 AB ED JSR $EDAB ;set buffer pointers
EFDA B5 29 LDA $29,X ;read character pointer value
EFDC D9 BD 00 CMP $00BD,Y ;reached last position yet ?
EFDF D0 04 BNE $EFE5 ;no,
EFE1 A9 00 LDA #$00
EFE3 95 29 STA $29,X ;reset character pointer value to #$00
EFE5 F6 29 INC $29,X ;move pointer to next character in buffer
EFE7 A1 29 LDA ($29,X) ;read data byte from buffer
EFE9 99 B5 00 STA $00B5,Y ;store data byte
EFEC B5 29 LDA $29,X ;read character pointer value
EFEE D9 BD 00 CMP $00BD,Y ;reached last position yet ?
EFF1 D0 05 BNE $EFF8 ;no,
EFF3 A9 81 LDA #$81 ;set channel status for EOI
EFF5 99 98 00 STA $0098,Y ;store new channel status
bit 7 = 1 (channel is talker to IEEE)
3 = 0 (send EOI on next byte, talker only)
0 = 1 (channel is listener to IEEE)
EFF8 60 RTS
******************************* Read byte from SEQuential file
EFF9 20 D2 ED JSR $EDD2 ;get byte from file and set for next file block
EFFC A6 15 LDX $15 ;read current channel number
EFFE 95 B5 STA $B5,X ;store data byte
F000 60 RTS
******************************* Test if "DIRECTORY" issued read
F001 AD 46 43 LDA $4346 ;is this a DIRECTORY listing ?
F004 F0 F3 BEQ $EFF9 ;no,
F006 20 11 DB JSR $DB11 ;get byte from directory
F009 4C FC EF JMP $EFFC ;jump to process byte from directory track
******************************* Get character from error channel
F00C 20 E1 F0 JSR $F0E1 ;read active buffer pointer
F00F C9 DB CMP #$DB ;pointer set to error buffer ?
F011 D0 18 BNE $F02B ;no,
F013 A5 28 LDA $28 ;get pointer HI byte
F015 C9 43 CMP #$43 ;is it pointing to #$43 (directory buffer)
F017 D0 12 BNE $F02B ;no,
F019 A9 0D LDA #$0D ;set for #$0D (decimal 13)
F01B 85 18 STA $18 ;store a carriage RETURN value in temporary
data byte location
F01D 20 42 DA JSR $DA42 ;turn off LED
F020 A9 00 LDA #$00
F022 20 CE D9 JSR $D9CE ;set track and sector to #$00, set up error
message
F025 C6 47 DEC $47 ;set pointer to start of error message
F027 A9 80 LDA #$80 ;set for EOI (End Or Identify)
F029 D0 12 BNE $F03D ;jump to store channel status
******************************* Set bytes from error buffer to be output
F02B 20 B3 ED JSR $EDB3 ;read byte from error buffer, set .Z flag if
last data byte
F02E 85 18 STA $18 ;store in temporary data byte location
F030 D0 09 BNE $F03B ;reached end of buffer ? no,
******************************* Set pointer for error message buffer
F032 A9 DB LDA #$DB
F034 20 C1 F0 JSR $F0C1 ;set buffer pointer for error buffer
F037 A9 43 LDA #$43
F039 95 2A STA $2A,X ;set pointer HI byte
******************************* Initialize error message channel
F03B A9 88 LDA #$88 ;set for "READ" and "EOI"
F03D 85 9F STA $9F ;set channel status
F03F A5 18 LDA $18 ;read byte from temporary data byte location
F041 85 BC STA $BC ;store byte in output channel
F043 60 RTS
******************************* Read next buffer of a file, follow links in
first two bytes. End of file if:
byte 0 = #$00
1 = last character position in block
F044 20 98 FA JSR $FA98 ;get active buffer number
F047 0A ASL ;double it
F048 AA TAX
F049 A9 00 LDA #$00
F04B 95 29 STA $29,X ;set pointer to start position in buffer
F04D A1 29 LDA ($29,X) ;read byte 0 from buffer, is it #$00 ?
F04F F0 05 BEQ $F056 ;yes,
F051 D6 29 DEC $29,X ;set buffer pointer to end of current block
F053 4C D2 ED JMP $EDD2 ;get byte from file and set up next block
F056 60 RTS
******************************* Entrance point for direct BLOCK-READ
F057 A9 80 LDA #$80 ;set for READ SECTOR job, job to do ?
F059 D0 02 BNE $F05D ;yes,
******************************* Entrance point for direct BLOCK-WRITE
F05B A9 90 LDA #$90 ;set for WRITE SECTOR job
F05D 05 12 ORA $12 ;add in selected drive number
F05F 8D 3C 43 STA $433C ;store result in temporary job command location
F062 A5 A1 LDA $A1
F064 20 92 EC JSR $EC92 ;set track, sector, ID for current buffer
F067 A6 A1 LDX $A1 ;read current buffer number
F069 4C A0 F1 JMP $F1A0 ;perform requested job
******************************* Open internal read channel (SA = 17)
F06C A9 11 LDA #$11 ;set for #$11 (decimal 17)
F06E 85 16 STA $16 ;set current secondary address number
F070 A9 01 LDA #$01
F072 85 C5 STA $C5 ;set SEQ file type
F074 20 47 F7 JSR $F747 ;open an internal read channel with 2 buffers
F077 A9 02 LDA #$02
F079 4C C1 F0 JMP $F0C1 ;set buffer pointer position
******************************* Open internal write channel (SA = 18)
F07C A9 12 LDA #$12 ;set for #$12 (decimal 18)
F07E 85 16 STA $16 ;set current secondary address number
F080 4C E6 F7 JMP $F7E6 ;jump to open internal write channel
******************************* Allocate next directory block on track 18
and mark as used in BAM
F083 20 3E F9 JSR $F93E ;set track and sector values
F086 A9 01 LDA #$01
F088 85 04 STA $04 ;set number of sector to allocate
F08A AD 44 43 LDA $4344 ;read sector increment value
F08D 48 PHA ;preserve it
F08E A9 03 LDA #$03
F090 8D 44 43 STA $4344 ;set new sector increment to #$03
F093 20 B6 D6 JSR $D6B6 ;return next available track and sector
F096 68 PLA ;retrieve sector increment
F097 8D 44 43 STA $4344 ;reset normal sector increment
F09A A9 00 LDA #$00
F09C 20 C1 F0 JSR $F0C1 ;set buffer pointer position
F09F A5 13 LDA $13 ;get track number
F0A1 20 B1 EC JSR $ECB1 ;write track number in valid buffer
F0A4 A5 14 LDA $14 ;get sector number
F0A6 20 B1 EC JSR $ECB1 ;write sector number to valid buffer
F0A9 20 45 ED JSR $ED45 ;set WRITE job
F0AC 20 82 EC JSR $EC82 ;wait until job completed
F0AF A9 00 LDA #$00
F0B1 20 C1 F0 JSR $F0C1 ;set buffer pointer position
F0B4 20 B1 EC JSR $ECB1 ;all fill bytes written to buffer ?
F0B7 D0 FB BNE $F0B4 ;no,
F0B9 20 B1 EC JSR $ECB1 ;set track link to #$00
F0BC A9 FF LDA #$FF
F0BE 4C B1 EC JMP $ECB1 ;set sector link to #$FF
******************************* Set new pointer position
. X = index to current buffer
.ACC = new pointer position
F0C1 85 04 STA $04 ;store pointer position in temporary location
F0C3 20 98 FA JSR $FA98 ;get active buffer number
F0C6 0A ASL ;double it
F0C7 AA TAX
F0C8 B5 2A LDA $2A,X ;read HI byte of buffer pointer
F0CA 85 28 STA $28 ;set as HI byte of directory buffer pointer
F0CC A5 04 LDA $04 ;get new pointer position
F0CE 95 29 STA $29,X ;set as LO byte of buffer pointer
F0D0 85 27 STA $27 ;set as LO byte of directory buffer pointer
F0D2 60 RTS
******************************* Free internal READ and WRITE channels
F0D3 A9 11 LDA #$11 ;set for #$11 (decimal 17)
F0D5 85 16 STA $16 ;set as current secondary address number
F0D7 20 9F EE JSR $EE9F ;clear internal read channel
F0DA A9 12 LDA #$12 ;set for #$12 (decimal 18)
F0DC 85 16 STA $16 ;set as current secondary address number
F0DE 4C 9F EE JMP $EE9F ;clear internal write channel
******************************* Read active buffer pointer, set directory
buffer
.X = index to current buffer
F0E1 20 98 FA JSR $FA98 ;get active buffer number
F0E4 0A ASL ;double it
F0E5 AA TAX
F0E6 B5 2A LDA $2A,X ;read HI byte of buffer pointer
F0E8 85 28 STA $28 ;set as HI byte of directory buffer
F0EA B5 29 LDA $29,X ;read LO byte of buffer pointer
F0EC 85 27 STA $27 ;set as LO byte of directory buffer
F0EE 60 RTS
******************************* Direct byte read
. X = index to current buffer
.ACC = byte number to read
F0EF 85 06 STA $06 ;set LO byte of buffer pointer for desired byte
F0F1 20 98 FA JSR $FA98 ;get active buffer number
F0F4 AA TAX
F0F5 BD FF F0 LDA $F0FF,X ;read HI byte from buffer index table
F0F8 85 07 STA $07 ;set as HI byte of buffer pointer
F0FA A0 00 LDY #$00
F0FC B1 06 LDA ($06),Y ;read byte from assigned buffer
F0FE 60 RTS
******************************* HI byte indexes for buffers
F0FF 11 ??? ;buffer # 0, HI byte: $1100
F100 12 ??? ;buffer # 1, HI byte: $1200
F101 13 ??? ;buffer # 2, HI byte: $1300
F102 20 ??? ;buffer # 3, HI byte: $2000
F103 21 ??? ;buffer # 4, HI byte: $2100
F104 22 ??? ;buffer # 5, HI byte: $2200
F105 23 ??? ;buffer # 6, HI byte: $2300
F106 30 ??? ;buffer # 7, HI byte: $3000
F107 31 ??? ;buffer # 8, HI byte: $3100
F108 32 ??? ;buffer # 9, HI byte: $3200
F109 33 ??? ;buffer #10, HI byte: $3300
F10A 40 ??? ;buffer #11, HI byte: $4000
F10B 41 ??? ;buffer #12, HI byte: $4100
F10C 42 ??? ;buffer #13, HI byte: $4200
F10D 43 ??? ;buffer #14, HI byte: $4300
******************************* Use last job for drive number and set job
command
F10E BD 4E 43 LDA $434E,X ;get last job issued
F111 29 01 AND #$01 ;add in drive number
F113 0D 3C 43 ORA $433C ;calculate new job command
******************************* Set job up and check track and sector
. X = job number
.ACC = command for job
F116 48 PHA ;preserve new job command
F117 86 A1 STX $A1 ;store buffer number in use
F119 8A TXA
F11A 0A ASL ;multiply buffer number by two
F11B 0A ASL ;multiply new result by two
F11C 0A ASL ;multiply new result by two
F11D AA TAX
F11E BD 24 10 LDA $1024,X ;read job header table sector number
F121 8D 3C 43 STA $433C ;store sector number
F124 BD 23 10 LDA $1023,X ;track number equal to #$00 ?
F127 F0 2C BEQ $F155 ;yes,
F129 C9 24 CMP #$24 ;track number below #$24 (decimal 36) ?
F12B B0 28 BCS $F155 ;yes,
F12D AA TAX
F12E 68 PLA ;retrieve new job command
F12F 48 PHA ;preserve new job command
F130 29 F0 AND #$F0 ;test job type
F132 C9 90 CMP #$90 ;is it a WRITE job ?
F134 D0 52 BNE $F188 ;no,
F136 68 PLA ;retrieve new job command
F137 48 PHA ;preserve new job command
F138 4A LSR ;shall drive 1 be used ?
F139 B0 05 BCS $F140 ;yes,
F13B AD 02 41 LDA $4102 ;format version number for drive 0 present ?
F13E 90 03 BCC $F143 ;yes,
F140 AD 02 42 LDA $4202 ;format version number for drive 1 present ?
F143 F0 05 BEQ $F14A ;no,
F145 CD 9F 10 CMP $109F ;format version compatible to DOS version ?
F148 D0 36 BNE $F180 ;no,
F14A 8A TXA ;transfer track number
F14B 20 D2 D7 JSR $D7D2 ;calculate maximum sector number for track
F14E CD 3C 43 CMP $433C ;valid sector number ?
F151 F0 02 BEQ $F155 ;no,
F153 B0 33 BCS $F188 ;yes,
******************************* Indicate track or sector unavailability
F155 20 5D F1 JSR $F15D ;set track and sector number for error
F158 A9 66 LDA #$66 ;set for "66 ILLEGAL TRACK OR SECTOR" error
F15A 4C 53 D9 JMP $D953 ;jump to process error message
******************************* Set track and sector from values in JOB
HEADER memory
F15D A5 A1 LDA $A1 ;get current buffer number
F15F 0A ASL ;multiply by two
F160 0A ASL ;multiply new result by two
F161 0A ASL ;multiply new result by two
F162 AA TAX
F163 BD 23 10 LDA $1023,X ;read track number
F166 85 13 STA $13 ;set as current track number
F168 BD 24 10 LDA $1024,X ;read sector number
F16B 85 14 STA $14 ;set as current sector number
F16D 60 RTS
******************************* Check track and sector validity
F16E A5 13 LDA $13 ;read track number, is it #$00 ?
F170 F0 E6 BEQ $F158 ;yes,
F172 C9 24 CMP #$24 ;is it smaller than #$24 (decimal 36) ?
F174 B0 E2 BCS $F158 ;no,
F176 20 D2 D7 JSR $D7D2 ;calculate maximum sector number for track
F179 C5 14 CMP $14 ;sector number below #$00 ?
F17B F0 DB BEQ $F158 ;yes,
F17D 90 D9 BCC $F158 ;sector number larger than allowable for this
track ?
F17F 60 RTS
******************************* Indicate invalid format version
F180 20 5D F1 JSR $F15D ;set track and sector number for error
F183 A9 73 LDA #$73 ;set for "73 CBM DOS V2.1" error, DOS version
F185 4C 53 D9 JMP $D953 ;jump to process error message
******************************* Determine error count and activate job
F188 A6 A1 LDX $A1 ;get current buffer number
F18A AD 5C 43 LDA $435C ;read error recovery count value
F18D 29 1F AND #$1F ;determine number of attempts before generation
of a hard error
F18F 9D 5D 43 STA $435D,X ;store result of calculation in current error
count buffer
F192 68 PLA ;retrieve job code
F193 8D 3C 43 STA $433C ;store in temporary job command location
F196 9D 03 10 STA $1003,X ;set in JOB QUE assigned to buffer
F199 9D 4E 43 STA $434E,X ;store in last job table
F19C 60 RTS
******************************* Set job and test if completed
F19D 8D 3C 43 STA $433C ;store job code in temporary job command
location
F1A0 AD 3C 43 LDA $433C ;read job code found in temporary location
F1A3 20 16 F1 JSR $F116 ;set job up and check track and sector
F1A6 4C 82 EC JMP $EC82 ;jump to test job completion
******************************* Add file to directory
F1A9 A5 16 LDA $16 ;read current secondary address
F1AB 48 PHA ;preserve it
F1AC A5 15 LDA $15 ;read channel number
F1AE 48 PHA ;preserve it
F1AF A5 14 LDA $14 ;read current sector number
F1B1 48 PHA ;preserve it
F1B2 A5 13 LDA $13 ;read current track number
F1B4 48 PHA ;preserve it
F1B5 A9 11 LDA #$11 ;set for #$11 (decimal 17)
F1B7 85 16 STA $16 ;set current secondary address number
F1B9 20 3E F9 JSR $F93E ;set track and sector values
F1BC A5 C5 LDA $C5 ;read current file type
F1BE 48 PHA ;preserve it
F1BF A5 8B LDA $8B ;read new file data byte
F1C1 29 01 AND #$01 ;determine drive number
F1C3 85 12 STA $12 ;set as current drive number
F1C5 A6 A1 LDX $A1 ;get current job number
F1C7 5D 4E 43 EOR $434E,X ;test against last job performed
F1CA 4A LSR ;use same drive number ?
F1CB 90 0C BCC $F1D9 ;yes,
F1CD A2 01 LDX #$01
F1CF 8E 98 43 STX $4398 ;set for search of a deleted directory entry
F1D2 20 D0 DF JSR $DFD0 ;available directory entry in block ?
F1D5 F0 1D BEQ $F1F4 ;no,
F1D7 D0 28 BNE $F201 ;yes,
F1D9 AD 97 43 LDA $4397 ;directory sector number set ?
F1DC F0 0C BEQ $F1EA ;no,
F1DE C5 14 CMP $14 ;same as current sector number ?
F1E0 F0 1F BEQ $F201 ;yes,
F1E2 85 14 STA $14 ;set new current sector number
F1E4 20 57 F0 JSR $F057 ;read next directory block
F1E7 4C 01 F2 JMP $F201 ;write new directory entry and store file
******************************* Find deleted entry in directory
F1EA A9 01 LDA #$01
F1EC 8D 98 43 STA $4398 ;set for search of a deleted directory entry
F1EF 20 39 E0 JSR $E039 ;deleted directory entry available ?
F1F2 D0 0D BNE $F201 ;yes,
F1F4 20 83 F0 JSR $F083 ;read next directory block of track 18
F1F7 A5 14 LDA $14 ;read current sector number
F1F9 8D 97 43 STA $4397 ;set directory sector number
F1FC A9 02 LDA #$02
F1FE 8D 98 43 STA $4398 ;set for search of a deleted directory entry
F201 AD 98 43 LDA $4398 ;read pointer value
F204 20 C1 F0 JSR $F0C1 ;set buffer pointer position
F207 68 PLA ;retrieve file type
F208 85 C5 STA $C5 ;set as active file type
F20A C9 04 CMP #$04 ;is it an REL file ?
F20C D0 02 BNE $F210 ;no,
******************************* Write RELative file
F20E 09 80 ORA #$80 ;mark file type as closed
F210 20 B1 EC JSR $ECB1 ;write file type to buffer
F213 68 PLA ;retrieve track link number
F214 8D 86 43 STA $4386 ;set as track number for file
F217 20 B1 EC JSR $ECB1 ;write track link to buffer
F21A 68 PLA ;retrieve sector link number
F21B 8D 8B 43 STA $438B ;set as sector number of file
F21E 20 B1 EC JSR $ECB1 ;write sector link to buffer
F221 20 98 FA JSR $FA98 ;get active buffer number
F224 A8 TAY
F225 AD 80 43 LDA $4380 ;get file name pointer
F228 AA TAX
F229 A9 10 LDA #$10 ;set length of filename to #$10 (decimal 16)
F22B 20 5F E0 JSR $E05F ;transfer filename from command buffer
F22E A0 10 LDY #$10 ;set pointer to end of filename
F230 A9 00 LDA #$00
F232 91 27 STA ($27),Y ;store #$00 in rest of directory entry
F234 C8 INY
F235 C0 1B CPY #$1B ;all bytes after filename nulled ?
F237 90 F9 BCC $F232 ;no,
F239 A5 C5 LDA $C5 ;read active file type
F23B C9 04 CMP #$04 ;is it an REL file ?
F23D D0 13 BNE $F252 ;no,
F23F A0 10 LDY #$10 ;set pointer to end of filename
F241 AD 4C 43 LDA $434C ;get track number of first side sector
F244 91 27 STA ($27),Y ;write after filename in directory entry
F246 C8 INY ;move pointer to side sector location
F247 AD 4D 43 LDA $434D ;get side sector number of first side sector
F24A 91 27 STA ($27),Y ;write after filename in directory entry
F24C C8 INY ;move pointer to record length location
F24D AD 4B 43 LDA $434B ;get record length
F250 91 27 STA ($27),Y ;write after filename in directory entry
F252 20 5B F0 JSR $F05B ;write newly updated directory block
F255 68 PLA ;retrieve channel
F256 85 15 STA $15 ;set as current channel number
F258 AA TAX
F259 68 PLA ;retrieve secondary address
F25A 85 16 STA $16 ;set as current secondary address
F25C AD 97 43 LDA $4397 ;read directory sector number
F25F 29 1F AND #$1F ;calculate index number
F261 85 86 STA $86 ;store in file entry table
F263 AD 98 43 LDA $4398 ;read newly stored file position
F266 29 E0 AND #$E0 ;calculate sector
F268 05 86 ORA $86 ;add in index
F26A 85 86 STA $86 ;store new index/sector value
F26C 9D 6B 43 STA $436B,X ;set directory entry position allocated for new
file entry
F26F A5 C5 LDA $C5 ;get file type
F271 0A ASL ;multiply by two
F272 29 1E AND #$1E ;clear drive number bit
F274 05 12 ORA $12 ;add in current drive number
F276 85 8B STA $8B ;set drive number corresponding to file
F278 60 RTS
******************************* Open channel from IEEE, parse the input
string that is sent as an open data channel
(LOAD or SAVE). Channels are allocated and
the directory is searched for the filename
contained in the string.
F279 A5 16 LDA $16 ;read current secondary address
F27B 8D 3B 43 STA $433B ;store in temporary secondary address location
F27E 20 B0 DC JSR $DCB0 ;set all flags and look at command string
F281 8E 7A 43 STX $437A ;store command number found
F284 AE 00 43 LDX $4300 ;read first character from command string
F287 AD 3B 43 LDA $433B ;is this a LOAD command ?
F28A D0 29 BNE $F2B5 ;no,
F28C E0 2A CPX #$2A ;LOAD last referenced program ? (*)
F28E D0 25 BNE $F2B5 ;no,
F290 A5 11 LDA $11 ;is there a track link for last program ?
F292 F0 49 BEQ $F2DD ;no,
F294 4A LSR
F295 85 13 STA $13 ;store link in current track number location
F297 A9 00 LDA #$00
F299 2A ROL
F29A 85 12 STA $12 ;set drive number for last program accessed
F29C 09 04 ORA #$04 ;calculate file type and add in drive number
F29E 85 8B STA $8B ;store in file data table
F2A0 20 2C DA JSR $DA2C ;turn on activity LED for specified drive
F2A3 AD 74 43 LDA $4374 ;read sector link for last program accessed
F2A6 85 14 STA $14 ;set as current sector number
F2A8 20 47 F7 JSR $F747 ;open an internal read channel with 2 buffers
F2AB A5 8B LDA $8B ;read file data
F2AD A6 15 LDX $15 ;get file type
F2AF 99 90 00 STA $0090,Y ;store in file type table
F2B2 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Test if LOAD directory command
F2B5 E0 24 CPX #$24 ;LOAD directory track ? ($)
F2B7 D0 1D BNE $F2D6 ;no,
F2B9 AD 3B 43 LDA $433B ;is this a LOAD command ?
F2BC D0 03 BNE $F2C1 ;no,
F2BE 4C 09 F5 JMP $F509 ;LOAD directory from disk
******************************* Open directory as a SEQuential file
F2C1 20 CC DB JSR $DBCC ;test syntax for command received
F2C4 A9 12 LDA #$12
F2C6 85 13 STA $13 ;set track number to #$12 (decimal 18)
F2C8 A9 00 LDA #$00
F2CA 85 14 STA $14 ;set sector number to #$00
F2CC 20 47 F7 JSR $F747 ;open internal read channel with 2 buffers
F2CF A5 12 LDA $12 ;get current drive number
F2D1 09 02 ORA #$02 ;calculate file type and add in drive number
F2D3 4C AD F2 JMP $F2AD ;read directory track and send as file
******************************* Test if direct access command
F2D6 E0 23 CPX #$23 ;is this a direct access request ? (#)
F2D8 D0 12 BNE $F2EC ;no,
F2DA 4C 30 E8 JMP $E830 ;open a direct access buffer
******************************* Initialize drive zero
F2DD A9 04 LDA #$04 ;calculate file type (2 * PRG)
F2DF 8D 9C 43 STA $439C ;set file type to PRG
F2E2 A9 00 LDA #$00
F2E4 85 12 STA $12 ;set current drive number to #$00
F2E6 8D 94 43 STA $4394 ;set as last drive without error
F2E9 20 FA EC JSR $ECFA ;read BAM from diskette in current drive
******************************* Parse command string
F2EC 20 E0 DB JSR $DBE0 ;colon (:) found in parsed command string ?
F2EF D0 04 BNE $F2F5 ;no,
F2F1 A2 00 LDX #$00 ;start position of parameters equal to #$00 ?
F2F3 F0 0C BEQ $F301 ;yes,
F2F5 8A TXA ;parameters separated by a comma ?
F2F6 F0 05 BEQ $F2FD ;yes,
F2F8 A9 30 LDA #$30 ;set for "30 SYNTAX ERROR", general syntax
F2FA 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Determine mode and file type for LOAD & SAVE
F2FD 88 DEY ;colon (:) position #$00 ?
F2FE F0 01 BEQ $F301 ;yes,
F300 88 DEY ;move pointer to character before colon (:)
F301 8C 80 43 STY $4380 ;store current pointer position in file table
F304 A9 8D LDA #$8D ;set for SHIFTED CARRIAGE RETURN
F306 20 63 DC JSR $DC63 ;look for character
F309 E8 INX
F30A 8E 7E 43 STX $437E ;store current file count value
F30D 20 0A DD JSR $DD0A ;set 1st drive and table pointers
F310 20 07 DE JSR $DE07 ;determine optimum search pattern
F313 20 BF DE JSR $DEBF ;search directory for requested file entry
F316 A2 00 LDX #$00
F318 8E 4B 43 STX $434B ;set record size to #$00
F31B 8E 9D 43 STX $439D ;set active file mode to #$00 (READ)
F31E 86 C5 STX $C5 ;set active file type to #$00 (DEL)
F320 E8 INX
F321 EC 7D 43 CPX $437D ;more parameters ?
F324 B0 10 BCS $F336 ;no,
F326 20 BF F4 JSR $F4BF ;test for file type and mode
F329 E8 INX
F32A EC 7D 43 CPX $437D ;more than one parameter ?
F32D B0 07 BCS $F336 ;no,
F32F C0 04 CPY #$04 ;is this a REL file ?
F331 F0 37 BEQ $F36A ;yes,
F333 20 BF F4 JSR $F4BF ;set file type and mode
F336 AE 3B 43 LDX $433B ;retrieve secondary address
F339 86 16 STX $16 ;set as current secondary address
F33B E0 02 CPX #$02 ;is command a LOAD or SAVE ?
F33D B0 0B BCS $F34A ;no,
F33F 8E 9D 43 STX $439D ;set mode from value in secondary address
F342 A5 C5 LDA $C5 ;is active file type a DEL ?
F344 D0 1A BNE $F360 ;no,
F346 A9 02 LDA #$02
F348 85 C5 STA $C5 ;set active file type to PRG
F34A A5 C5 LDA $C5 ;is active file type a DEL ?
F34C D0 12 BNE $F360 ;no,
F34E A5 8B LDA $8B ;get file type from table
F350 29 0E AND #$0E ;calculate file type
F352 4A LSR
F353 85 C5 STA $C5 ;set as active file type
F355 AD 86 43 LDA $4386 ;get first track link from file table
F358 29 3F AND #$3F ;does file exist ?
F35A D0 04 BNE $F360 ;yes,
F35C A9 01 LDA #$01
F35E 85 C5 STA $C5 ;set active file type to #$01 (SEQ)
F360 AD 9D 43 LDA $439D ;read active file mode
F363 C9 01 CMP #$01 ;is it WRITE ?
F365 F0 1A BEQ $F381 ;yes,
F367 4C F9 F3 JMP $F3F9 ;perform LOAD operation
******************************* Handle relative file
F36A BC 80 43 LDY $4380,X ;get pointer from file table
F36D B9 00 43 LDA $4300,Y ;get REL file record size
F370 8D 4B 43 STA $434B ;set as current record size
F373 AD 86 43 LDA $4386 ;get track link for file
F376 29 3F AND #$3F ;does file exist ?
F378 D0 BC BNE $F336 ;yes,
F37A A9 01 LDA #$01
F37C 8D 9D 43 STA $439D ;is active file mode #$01 (WRITE)
F37F D0 B5 BNE $F336 ;yes,
F381 AD 86 43 LDA $4386 ;get track link for file
F384 29 80 AND #$80 ;calculate file type
F386 AA TAX ;is this a DEL file ?
F387 D0 16 BNE $F39F ;no,
F389 A9 20 LDA #$20 ;set for OPEN WRITE
F38B 24 8B BIT $8B ;does file pattern match for OPEN WRITE ?
F38D F0 06 BEQ $F395 ;yes,
F38F 20 3B E3 JSR $E33B ;delete directory entry and write new sector
F392 4C 9B F4 JMP $F49B ;open a write file
******************************* Test if file exists. If not, open a write
channel
F395 AD 86 43 LDA $4386 ;get track link for file
F398 29 3F AND #$3F ;does file exist ?
F39A D0 03 BNE $F39F ;yes,
F39C 4C 9B F4 JMP $F49B ;open a write file
******************************* Check if file replacement command
F39F AD 00 43 LDA $4300 ;read first character from command buffer
F3A2 C9 40 CMP #$40 ;is this a replace command ? (`)
F3A4 F0 0D BEQ $F3B3 ;yes,
F3A6 8A TXA ;does file exist already ?
F3A7 D0 05 BNE $F3AE ;no,
F3A9 A9 63 LDA #$63 ;set for "63 FILE EXISTS" error
F3AB 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Indicate invalid filename structure
F3AE A9 33 LDA #$33 ;set for "33 SYNTAX ERROR", invalid filename
F3B0 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Command: REPLACE (overwrite file)
F3B3 A5 8B LDA $8B ;read file information from directory entry
F3B5 29 0E AND #$0E ;calculate file type
F3B7 4A LSR
F3B8 C5 C5 CMP $C5 ;do file types match ?
F3BA D0 64 BNE $F420 ;no,
F3BC C9 04 CMP #$04 ;is this a REL file ?
F3BE F0 60 BEQ $F420 ;yes,
F3C0 20 E6 F7 JSR $F7E6 ;open a write channel with 2 buffers
F3C3 A5 15 LDA $15 ;get active buffer number
F3C5 8D 75 43 STA $4375 ;set as write buffer number
F3C8 A9 11 LDA #$11 ;set internal read channel
F3CA 85 16 STA $16 ;set current secondary address to #$11
(decimal 17)
F3CC 20 69 ED JSR $ED69 ;find internal read channel
F3CF AD 9A 43 LDA $439A ;read pointer position into buffer
F3D2 20 C1 F0 JSR $F0C1 ;set new pointer position
F3D5 A0 00 LDY #$00
F3D7 B1 27 LDA ($27),Y ;get file type from directory buffer
F3D9 09 20 ORA #$20 ;set file replacement flag
F3DB 91 27 STA ($27),Y ;store new file type in directory buffer
F3DD A0 1A LDY #$1A
F3DF A5 13 LDA $13 ;read current file track link
F3E1 91 27 STA ($27),Y ;set as replacement track link for current file
F3E3 C8 INY
F3E4 A5 14 LDA $14 ;read current file sector link
F3E6 91 27 STA ($27),Y ;set as replacement sector link for current
file
F3E8 A5 86 LDA $86 ;read directory entry information
F3EA AE 75 43 LDX $4375 ;get active write buffer number
F3ED 9D 6B 43 STA $436B,X ;store information in file entry table
F3F0 20 3E F9 JSR $F93E ;set track and sector values
F3F3 20 5B F0 JSR $F05B ;write directory block to diskette
F3F6 4C A7 F4 JMP $F4A7 ;overwrite old file with new data
******************************* Test if file exists in directory
F3F9 AD 86 43 LDA $4386 ;get track link for file
F3FC 29 3F AND #$3F ;does file exist ?
F3FE D0 05 BNE $F405 ;yes,
F400 A9 62 LDA #$62 ;set for "62 FILE NOT FOUND" error
F402 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Test if MODIFY (#$03) mode requested
F405 AD 9D 43 LDA $439D ;read active file mode
F408 C9 03 CMP #$03 ;is this active mode MODIFY ?
F40A F0 0B BEQ $F417 ;yes,
F40C A9 20 LDA #$20 ;set for replacement file open flag
F40E 24 8B BIT $8B ;is file already open ?
F410 F0 05 BEQ $F417 ;yes,
F412 A9 60 LDA #$60 ;set for "60 FILE NOT OPEN" error
F414 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Verify the requested directory entry file
type
F417 A5 8B LDA $8B ;read file information from directory entry
F419 4A LSR
F41A 29 0F AND #$0F ;calculate file type
F41C C5 C5 CMP $C5 ;do file types match ?
F41E F0 05 BEQ $F425 ;yes,
F420 A9 64 LDA #$64 ;set for "64 FILE TYPE MISMATCH" error
F422 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Test if APPEND (#$02) mode requested
F425 A0 00 LDY #$00
F427 8C 7F 43 STY $437F ;clear file stream 2 count
F42A AE 9D 43 LDX $439D ;read active file mode
F42D E0 02 CPX #$02 ;is this active mode APPEND ?
F42F D0 1A BNE $F44B ;no,
F431 C9 04 CMP #$04 ;is this a REL file ?
F433 F0 EB BEQ $F420 ;yes,
F435 B1 27 LDA ($27),Y ;read file type from directory entry
F437 29 4F AND #$4F ;set APPEND flag
F439 91 27 STA ($27),Y ;store file type back in directory
F43B A5 16 LDA $16 ;read current secondary address
F43D 48 PHA ;preserve it
F43E A9 11 LDA #$11 ;set internal read channel
F440 85 16 STA $16 ;set current secondary address to #$11
(decimal 17)
F442 20 3E F9 JSR $F93E ;set track and sector values
F445 20 5B F0 JSR $F05B ;write directory block to diskette
F448 68 PLA ;retrieve original secondary address
F449 85 16 STA $16 ;set as current secondary address
F44B 20 5B F4 JSR $F45B ;open file for read
F44E AD 9D 43 LDA $439D ;read active file mode
F451 C9 02 CMP #$02 ;is this active mode APPEND ?
F453 D0 52 BNE $F4A7 ;no,
F455 20 DF F4 JSR $F4DF ;read until end of file and add in new data
F458 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Open a file for reading
F45B A0 13 LDY #$13
F45D B1 27 LDA ($27),Y ;read track number of first side sector from
directory
F45F 8D 4C 43 STA $434C ;set as current side sector track number
F462 C8 INY
F463 B1 27 LDA ($27),Y ;read sector number of first side sector from
directory
F465 8D 4D 43 STA $434D ;set as current side sector number
F468 C8 INY
F469 B1 27 LDA ($27),Y ;read record length for file
F46B AE 4B 43 LDX $434B ;read last record length
F46E 8D 4B 43 STA $434B ;set new record length for file
F471 8A TXA ;is record length #$00 ?
F472 F0 0A BEQ $F47E ;yes,
F474 CD 4B 43 CMP $434B ;does requested record exists ?
F477 F0 05 BEQ $F47E ;yes,
F479 A9 50 LDA #$50 ;set for "50 RECORD NOT PRESENT" error
F47B 20 C3 DB JSR $DBC3 ;indicate error message
F47E AE 7F 43 LDX $437F ;read filename pointer
F481 BD 86 43 LDA $4386,X ;get track number for file entry
F484 29 3F AND #$3F ;extract track number
F486 85 13 STA $13 ;set as current track
F488 BD 8B 43 LDA $438B,X ;get sector for file entry
F48B 85 14 STA $14 ;set as sector number
F48D 20 47 F7 JSR $F747 ;open internal read channel with 2 buffers
F490 A4 15 LDY $15 ;get channel number
F492 AE 7F 43 LDX $437F ;get filename pointer
F495 B5 86 LDA $86,X ;get sector number for file
F497 99 6B 43 STA $436B,Y ;set first block sector number for file
F49A 60 RTS
******************************* Open a file for writing
F49B A5 8B LDA $8B ;read file information from table
F49D 29 01 AND #$01 ;calculate drive number
F49F 85 12 STA $12 ;set as current drive number
F4A1 20 E6 F7 JSR $F7E6 ;open a write channel with 2 buffers
F4A4 20 A9 F1 JSR $F1A9 ;add file to directory
F4A7 A5 16 LDA $16 ;read current secondary address
F4A9 C9 02 CMP #$02 ;is this a PRG file type ?
F4AB B0 0F BCS $F4BC ;no,
F4AD 20 41 F9 JSR $F941 ;set track and sector values
F4B0 A5 13 LDA $13 ;read current track number
F4B2 0A ASL
F4B3 05 12 ORA $12 ;add in drive number
F4B5 85 11 STA $11 ;set new last program track accessed flag
F4B7 A5 14 LDA $14 ;read current sector number
F4B9 8D 74 43 STA $4374 ;set new last program sector accessed flag
F4BC 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Check mode and file type
F4BF BC 80 43 LDY $4380,X ;get pointer into file command buffer
F4C2 B9 00 43 LDA $4300,Y ;get mode or file type from command string
F4C5 A0 04 LDY #$04 ;set for maximum number of modes:
0 = R (read)
1 = W (write)
2 = A (append)
3 = M (modify)
F4C7 88 DEY ;all file mode possibilities tested ?
F4C8 30 08 BMI $F4D2 ;yes,
F4CA D9 CB D2 CMP $D2CB,Y ;is selected file mode valid ?
F4CD D0 F8 BNE $F4C7 ;no,
F4CF 8C 9D 43 STY $439D ;set as active file mode
F4D2 A0 05 LDY #$05 ;set for maximum number of file types:
0 = D (deleted)
1 = S (sequential)
2 = P (program)
3 = U (user)
4 = R (relative)
F4D4 88 DEY ;all file type possibilities tested ?
F4D5 30 07 BMI $F4DE ;yes,
F4D7 D9 CF D2 CMP $D2CF,Y ;is selected file type valid ?
F4DA D0 F8 BNE $F4D4 ;no,
F4DC 84 C5 STY $C5 ;set as active file type
F4DE 60 RTS
******************************* Append information to end of specified file
F4DF 20 5B E6 JSR $E65B ;read data byte
F4E2 A9 80 LDA #$80 ;set for EOI marker
F4E4 20 B1 F8 JSR $F8B1 ;all data bytes read ?
F4E7 F0 F6 BEQ $F4DF ;yes,
F4E9 20 9A F9 JSR $F99A ;set track and sector link from buffer
F4EC A6 14 LDX $14 ;read current sector number
F4EE E8 INX ;increment sector number
F4EF 8A TXA ;still room for more bytes in this sector ?
F4F0 D0 05 BNE $F4F7 ;yes,
F4F2 20 1F EE JSR $EE1F ;write sector buffer to disk
F4F5 A9 02 LDA #$02
F4F7 20 C1 F0 JSR $F0C1 ;set new pointer position
F4FA A6 15 LDX $15 ;get active buffer number
F4FC A9 01 LDA #$01
F4FE 95 98 STA $98,X ;set channel status
bit 0 = 1 (channel is listener to IEEE)
bit 3 = 0 (send EOI - talker only)
bit 7 = 1 (channel is talker to IEEE)
F500 A9 80 LDA #$80 ;set channel status to #$10 (write)
F502 05 15 ORA $15 ;add in active buffer number
F504 A6 16 LDX $16 ;get current secondary address
F506 95 A2 STA $A2,X ;store file status in logical index table
bit 7-6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
F508 60 RTS
******************************* Transmit directory ($) to computer
F509 A9 0B LDA #$0B ;set for LOAD command
F50B 8D 7A 43 STA $437A ;set as current command number
F50E AE 79 43 LDX $4379 ;get command length + 1
F511 CA DEX ;is there a command string ?
F512 D0 17 BNE $F52B ;yes,
F514 A9 2A LDA #$2A ;set for wildcard pattern (*)
F516 8D 00 43 STA $4300 ;store in command string
F519 A9 80 LDA #$80 ;set search both drives flag
F51B 8D 86 43 STA $4386 ;set wildcard (*) flag during first block
search
F51E 0D 94 43 ORA $4394 ;add in drive number
F521 85 8B STA $8B ;set type and wildcard (*) flag for first file
F523 EE 7D 43 INC $437D ;increment file stream count 1
F526 EE 7E 43 INC $437E ;increment file stream count 2; reached #$00
F529 D0 41 BNE $F56C ;no,
F52B CA DEX ;load by filenames ?
F52C D0 26 BNE $F554 ;yes,
F52E AD 01 43 LDA $4301 ;get drive number from command buffer
F531 20 B5 DD JSR $DDB5 ;ASCII code representing drive 0 found ?
F534 30 1E BMI $F554 ;yes,
******************************* Load directory from one drive
F536 29 01 AND #$01
F538 85 8B STA $8B ;set marker to indicate that directory will be
pulled from drive 1
F53A 85 12 STA $12 ;set current drive to #$01
F53C 20 FA EC JSR $ECFA ;read BAM from diskette in drive 1
F53F EE 7D 43 INC $437D ;increment file stream count 1
F542 EE 7E 43 INC $437E ;increment file stream count 2
F545 EE 80 43 INC $4380 ;move to next position in command string
F548 A9 80 LDA #$80
F54A 8D 86 43 STA $4386 ;set file marker to indicate that file has been
closed properly
F54D A9 2A LDA #$2A ;set for wildcard pattern (*)
F54F 8D 01 43 STA $4301 ;is second character position in command
buffer set to (*) ?
F552 D0 18 BNE $F56C ;yes,
F554 20 E0 DB JSR $DBE0 ;has a colon (:) been found ?
F557 D0 05 BNE $F55E ;no,
F559 20 D9 DC JSR $DCD9 ;clear variables and necessary tables
******************************* Search by name on both drives
F55C A0 03 LDY #$03 ;set pointer to first character in first
directory entry of directory block
F55E 88 DEY ;move to directory block sector link
F55F 88 DEY ;move to directory block track link
F560 8C 80 43 STY $4380 ;store current pointer position
F563 20 FB DB JSR $DBFB ;set file image structure to search for in
directory
F566 20 8F DD JSR $DD8F ;set pointer to filename and check type
F569 20 18 DD JSR $DD18 ;set drive number to pull directory from
F56C 20 07 DE JSR $DE07 ;determine best directory search method
F56F 20 AA E1 JSR $E1AA ;set up directory heading line
F572 20 BF DE JSR $DEBF ;get filename search mask from table
F575 20 4B DA JSR $DA4B ;load in directory block
F578 20 B3 ED JSR $EDB3 ;read byte from directory buffer
F57B A6 15 LDX $15 ;get active buffer number
F57D 95 B5 STA $B5,X ;send byte to IEEE
F57F A5 12 LDA $12 ;read current drive number
F581 8D 94 43 STA $4394 ;set as last drive number without error
F584 09 04 ORA #$04 ;set for SEQ file type
F586 95 90 STA $90,X ;set channel send mode to SEQ
F588 A9 00 LDA #$00
F58A 85 45 STA $45 ;set command buffer LO byte to #$00
F58C 60 RTS
******************************* Close file associated with secondary
address
F58D A5 16 LDA $16 ;directory load function needs to be closed ?
F58F D0 0B BNE $F59C ;no,
F591 A9 00 LDA #$00
F593 8D 46 43 STA $4346 ;clear directory listing flag
F596 20 9F EE JSR $EE9F ;get channel used during directory load
F599 4C D3 F0 JMP $F0D3 ;jump to free channel routine
******************************* Close channels associated with LOAD/SAVE
F59C C9 0F CMP #$0F ;all channel need to be closed ?
F59E F0 0C BEQ $F5AC ;yes,
F5A0 20 BA F5 JSR $F5BA ;close specified channel
F5A3 A5 16 LDA $16 ;read current secondary address
F5A5 C9 02 CMP #$02 ;LOAD/SAVE channel needs to be closed ?
F5A7 90 F0 BCC $F599 ;yes,
F5A9 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Close all files
F5AC A9 0E LDA #$0E
F5AE 85 16 STA $16 ;set current secondary address to #$0E
(decimal 14)
F5B0 20 BA F5 JSR $F5BA ;close specified channel
F5B3 C6 16 DEC $16 ;all channels closed ?
F5B5 10 F9 BPL $F5B0 ;no,
F5B7 4C 99 DB JMP $DB99 ;jump to indicate command termination status
******************************* Close specified secondary address channel
F5BA A6 16 LDX $16 ;get current secondary address
F5BC B5 A2 LDA $A2,X ;read specified channel status
F5BE C9 FF CMP #$FF ;is channel already closed ?
F5C0 D0 01 BNE $F5C3 ;no,
F5C2 60 RTS
******************************* Locate and close specific file type
associated with secondary address
F5C3 29 0F AND #$0F ;determine buffer number
F5C5 85 15 STA $15 ;store buffer number
F5C7 20 A1 ED JSR $EDA1 ;get current file type
F5CA C9 07 CMP #$07 ;is it a direct access type ?
F5CC F0 0F BEQ $F5DD ;yes,
F5CE C9 04 CMP #$04 ;is it an REL type ?
F5D0 F0 11 BEQ $F5E3 ;yes,
F5D2 20 84 ED JSR $ED84 ;internal write channel found ?
F5D5 B0 09 BCS $F5E0 ;no,
F5D7 20 12 F6 JSR $F612 ;close SEQ write channel
F5DA 20 A4 F6 JSR $F6A4 ;close directory channel
F5DD 20 55 F6 JSR $F655 ;write BAM out to diskette
F5E0 4C 9F EE JMP $EE9F ;clear internal write channel
******************************* Close a RELative file
F5E3 20 F4 F8 JSR $F8F4 ;write out BAM if modified
F5E6 20 D1 EB JSR $EBD1 ;toggle current active and inactive buffers
F5E9 20 B1 FC JSR $FCB1 ;position side sector and buffer table pointer
to the end of the last record
F5EC A6 83 LDX $83 ;get current side sector number
F5EE 86 08 STX $08 ;store in TEMP4 location
F5F0 E6 08 INC $08 ;increment current side sector number by one
F5F2 A9 00 LDA #$00
F5F4 85 05 STA $05 ;clear TEMP1 location
F5F6 85 06 STA $06 ;clear TEMP2 location
F5F8 A5 84 LDA $84 ;read pointer value into side sector
F5FA 38 SEC
F5FB E9 0E SBC #$0E ;substract side sector offset
F5FD 85 07 STA $07 ;store result in TEMP3 location
F5FF 20 56 FA JSR $FA56 ;calculate number of side sector blocks needed
F602 A6 15 LDX $15 ;get active buffer number
F604 A5 05 LDA $05 ;read LO byte of side sector block count
F606 95 59 STA $59,X ;store in record table as LO pointer value
F608 A5 06 LDA $06 ;read HI byte of side sector block count
F60A 95 61 STA $61,X ;store in record table as HI pointer value
F60C 20 A4 F6 JSR $F6A4 ;close open write file in directory
F60F 4C 9F EE JMP $EE9F ;clear internal write channel
******************************* Close a write channel
F612 A6 15 LDX $15 ;get active buffer number
F614 B5 59 LDA $59,X ;read number of bytes written in current sector
F616 15 61 ORA $61,X ;has more than one data block been written ?
F618 D0 0C BNE $F626 ;yes,
F61A 20 E1 F0 JSR $F0E1 ;get current buffer pointer position
F61D C9 02 CMP #$02 ;has more than one byte been written in current
data block ?
F61F D0 05 BNE $F626 ;yes,
F621 A9 0D LDA #$0D ;set for #$0D (decimal 13), carriage return
F623 20 B1 EC JSR $ECB1 ;write byte to assigned buffer
F626 20 E1 F0 JSR $F0E1 ;get current buffer pointer position
F629 C9 02 CMP #$02 ;has more than one byte been written in current
data block ?
F62B D0 0F BNE $F63C ;yes,
F62D 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
F630 A6 15 LDX $15 ;get active buffer number
F632 B5 59 LDA $59,X ;any bytes written to buffer ?
F634 D0 02 BNE $F638 ;yes,
F636 D6 61 DEC $61,X ;decrement number of data blocks written by one
F638 D6 59 DEC $59,X ;decrement number of bytes written by one
F63A A9 00 LDA #$00
F63C 38 SEC
F63D E9 01 SBC #$01 ;calculate number of bytes written in current
sector
F63F 48 PHA ;preserve result
F640 A9 00 LDA #$00
F642 20 C1 F0 JSR $F0C1 ;set new pointer position
F645 20 B1 EC JSR $ECB1 ;write #$00 as track link in current sector
F648 68 PLA ;retrieve result from bytes written calculation
F649 20 B1 EC JSR $ECB1 ;write last data byte position in current
sector
F64C 20 45 ED JSR $ED45 ;write sector out to diskette
F64F 20 82 EC JSR $EC82 ;wait until write job completed
F652 4C D1 EB JMP $EBD1 ;toggle active and inactive buffer
******************************* Write out the BAM to the last active drive
F655 20 98 FA JSR $FA98 ;find active buffer number
F658 AA TAX
F659 BD 4E 43 LDA $434E,X ;get last job performed
F65C 29 01 AND #$01 ;remove drive number
F65E 48 PHA ;preserve new BAM flag
F65F AA TAX
F660 A9 00 LDA #$00
F662 85 14 STA $14 ;set current sector number to #$00
F664 BD E8 D2 LDA $D2E8,X ;get HI byte pointer for BAM corresponding
to current drive
F667 85 09 STA $09 ;store TEMP location
F669 A9 00 LDA #$00
F66B 85 08 STA $08 ;clear TEMP4 location
F66D A9 01 LDA #$01
F66F 85 13 STA $13 ;set current track number to #$01
******************************* Verify that the BAM block count matches the
bits
F671 A5 13 LDA $13 ;read current track number
F673 0A ASL ;move into track bytes reserved for track
F674 0A ASL ;set for beginning of next track BAM bits
test
F675 A8 TAY
F676 B1 08 LDA ($08),Y ;read sector count total for current track
F678 85 07 STA $07 ;store in TEMP4 location
F67A C8 INY
F67B B1 08 LDA ($08),Y ;read first part of sector count for track
F67D 85 04 STA $04 ;store in TEMP0 location
F67F C8 INY
F680 B1 08 LDA ($08),Y ;read second part of sector count for track
F682 85 05 STA $05 ;store in TEMP1 location
F684 C8 INY
F685 B1 08 LDA ($08),Y ;read third part of sector count for track
F687 85 06 STA $06 ;store in TEMP2 location
F689 20 B4 D7 JSR $D7B4 ;verify track bits with new BAM image for track
F68C E6 13 INC $13 ;do next track
F68E A5 13 LDA $13 ;get current track number
F690 C9 24 CMP #$24 ;all tracks in BAM tested ?
F692 D0 DD BNE $F671 ;no,
******************************* Write new BAM to diskette
F694 A9 12 LDA #$12
F696 85 13 STA $13 ;set current track number to #$12 (decimal 18)
F698 68 PLA ;retrieve new BAM flag marker
F699 A8 TAY
F69A 18 CLC
F69B 69 0C ADC #$0C ;add in BAM write job
F69D AA TAX
F69E 98 TYA
F69F 09 90 ORA #$90 ;set job code to: WRITE
F6A1 4C 9D F1 JMP $F19D ;perform job
******************************* Directory close on open write file
F6A4 A6 15 LDX $15 ;get active buffer number
F6A6 8E 75 43 STX $4375 ;set as write index flag
F6A9 A5 16 LDA $16 ;get current secondary address
F6AB 48 PHA ;preserve it
F6AC BD 6B 43 LDA $436B,X ;get directory sector number for current file
F6AF 48 PHA ;preserve it
F6B0 29 1F AND #$1F ;determine sector number
F6B2 85 14 STA $14 ;set as current sector number
F6B4 68 PLA ;retrieve current secondary address
F6B5 29 E0 AND #$E0 ;calculate sector offset
F6B7 09 02 ORA #$02 ;extract current index into active buffer
F6B9 8D 9A 43 STA $439A ;set as current index into active buffer
F6BC B5 90 LDA $90,X ;read file type for current file
F6BE 29 01 AND #$01 ;determine which drive to use
F6C0 85 12 STA $12 ;set as current drive number
F6C2 A9 12 LDA #$12
F6C4 85 13 STA $13 ;set current track number to #$12 (decimal 18)
F6C6 20 98 FA JSR $FA98 ;get active buffer number
F6C9 48 PHA ;preserve it
F6CA 85 A1 STA $A1 ;set as current job number
F6CC 20 57 F0 JSR $F057 ;read directory sector
F6CF A0 00 LDY #$00
F6D1 BD FF F0 LDA $F0FF,X ;read byte from allocated buffer
F6D4 85 1A STA $1A ;store in TEMPR1 location
F6D6 AD 9A 43 LDA $439A ;get index position into current active buffer
F6D9 85 19 STA $19 ;store value in TEMPR0 location
F6DB B1 19 LDA ($19),Y ;read file type from directory entry
F6DD 29 20 AND #$20 ;is current file open ?
F6DF F0 41 BEQ $F722 ;yes,
******************************* REPLACE current file data with new file data
F6E1 20 A1 ED JSR $EDA1 ;is this a RELative file entry ?
F6E4 F0 44 BEQ $F72A ;yes,
F6E6 B1 19 LDA ($19),Y ;get file type for current file
F6E8 29 8F AND #$8F ;set file replacement flag
F6EA 91 19 STA ($19),Y ;set as new file type for current file
F6EC C8 INY
F6ED B1 19 LDA ($19),Y ;get track link of first block for file
F6EF 85 13 STA $13 ;set as current track number
F6F1 84 06 STY $06 ;store pointer to beginning of directory entry
in TEMP2 location
F6F3 A0 1B LDY #$1B ;set new pointer position to #$1B (decimal 27)
F6F5 B1 19 LDA ($19),Y ;extract replacement link to last sector
F6F7 48 PHA ;preserve it
F6F8 88 DEY
F6F9 B1 19 LDA ($19),Y ;is replacement track link #$00 ?
F6FB D0 0A BNE $F707 ;no,
F6FD 85 13 STA $13 ;set as current track number
F6FF 68 PLA ;retrieve last sector link
F700 85 14 STA $14 ;set as current sector number
F702 A9 67 LDA #$67 ;set for "67 ILLEGAL SYSTEM T or S", invalid
track number
F704 20 53 D9 JSR $D953 ;generate error message
F707 48 PHA ;preserve track link
F708 A9 00 LDA #$00
F70A 91 19 STA ($19),Y ;clear replacement track link location
F70C C8 INY
F70D 91 19 STA ($19),Y ;clear replacement sector link location
F70F 68 PLA ;retrieve replacement track link value
F710 A4 06 LDY $06 ;read original directory entry pointer value
F712 91 19 STA ($19),Y ;set new track link number
F714 C8 INY
F715 B1 19 LDA ($19),Y ;read current sector link number
F717 85 14 STA $14 ;set as current sector number
F719 68 PLA ;retrieve replacement sector link value
F71A 91 19 STA ($19),Y ;set new sector link value
F71C 20 13 E3 JSR $E313 ;delete old file
F71F 4C 2A F7 JMP $F72A ;write new block size for replaced file
******************************* Set "file closed" flag, and write new block
count for replaced file. Write new sector
F722 B1 19 LDA ($19),Y ;get file type for current file
F724 29 0F AND #$0F ;mask off HI order bits
F726 09 80 ORA #$80 ;set FILE CLOSED flag
F728 91 19 STA ($19),Y ;set as new file type for current file
F72A AE 75 43 LDX $4375 ;get active write buffer index
F72D A0 1C LDY #$1C
F72F B5 59 LDA $59,X ;get LO block count for current file
F731 91 19 STA ($19),Y ;set as new LO block count for replaced file
F733 C8 INY
F734 B5 61 LDA $61,X ;get HI block count for current file
F736 91 19 STA ($19),Y ;set as new HI block count for replaced file
F738 68 PLA ;retrieve original buffer number
F739 AA TAX
F73A A9 90 LDA #$90 ;set job code to: WRITE
F73C 05 12 ORA $12 ;add in drive number
F73E 20 9D F1 JSR $F19D ;perform job
F741 68 PLA ;retrieve original secondary address
F742 85 16 STA $16 ;set as current secondary address
F744 4C 84 ED JMP $ED84 ;find internal write channel
******************************* Open internal read channel with 2 buffers.
Inserts secondary address in logical index
table. Initializes all pointers, including
RELative file pointers.
F747 A9 02 LDA #$02 ;set for opening of two buffers
F749 20 5E EE JSR $EE5E ;allocate two data buffers
F74C 20 B4 F7 JSR $F7B4 ;clear pointers
F74F A5 C5 LDA $C5 ;get active file type
F751 48 PHA ;preserve it
F752 0A ASL ;double file type
F753 05 12 ORA $12 ;add in drive number
F755 95 90 STA $90,X ;store file information in file table
F757 20 1D ED JSR $ED1D ;read first one or two data block of file
F75A A6 15 LDX $15 ;get active buffer number
F75C A5 13 LDA $13 ;another sector in file available for read ?
F75E D0 04 BNE $F764 ;yes,
F760 A5 14 LDA $14 ;get pointer to last character position in this
sector
F762 95 BD STA $BD,X ;store as pointer into current active buffer
F764 68 PLA ;retrieve file type
F765 C9 04 CMP #$04 ;is this a REL file ?
F767 D0 3F BNE $F7A8 ;no,
F769 A4 16 LDY $16 ;read current secondary address
F76B B9 A2 00 LDA $00A2,Y ;read channel status
bit 7 & 6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
F76E 09 40 ORA #$40 ;set channel status to: 01 (read/write)
F770 99 A2 00 STA $00A2,Y ;set new channel status
bit 7 & 6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
F773 AD 4B 43 LDA $434B ;get record size value
F776 95 71 STA $71,X ;store in RELative record size table
F778 20 FE EE JSR $EEFE ;buffer available for use with side sectors ?
F77B 10 03 BPL $F780 ;yes,
F77D 4C 87 EE JMP $EE87 ;indicate no buffer available for side sectors
******************************* Initialize all pointers including REL file
pointers
F780 A6 15 LDX $15 ;get active side sector buffer
F782 95 79 STA $79,X ;store in side sector table
F784 AC 4C 43 LDY $434C ;read track number for side sector
F787 84 13 STY $13 ;set as current track number
F789 AC 4D 43 LDY $434D ;read sector number for side sector
F78C 84 14 STY $14 ;set as current track number
F78E 20 92 EC JSR $EC92 ;set track, sector, ID for current buffer
F791 20 78 F9 JSR $F978 ;read side sector block
F794 20 82 EC JSR $EC82 ;wait until job completed
F797 A6 15 LDX $15 ;get active side sector buffer
F799 A9 02 LDA #$02
F79B 95 69 STA $69,X ;set next record pointer to #$02
F79D A9 00 LDA #$00
F79F 20 C1 F0 JSR $F0C1 ;set new pointer position
F7A2 20 3C FC JSR $FC3C ;set up first record
F7A5 4C 41 F9 JMP $F941 ;restore track and sector
******************************* Set up SEQuential file
F7A8 20 D2 ED JSR $EDD2 ;read a byte from active buffer
F7AB A6 15 LDX $15 ;get current active buffer number
F7AD 95 B5 STA $B5,X ;send byte out through IEEE
F7AF A9 88 LDA #$88 ;set for "ready to talk" status
F7B1 95 98 STA $98,X ;set channel status
bit 7 = channel is talker (set to 1)
3 = channel is send EOI (talker only)
0 = channel is listener (set to 1)
F7B3 60 RTS
******************************* Initialize variables for open channel. Sets
active buffer number. Buffer pointer = 2
F7B4 A6 15 LDX $15 ;get active buffer number
F7B6 A5 12 LDA $12 ;read current drive number
F7B8 B4 49 LDY $49,X ;get main buffer number
F7BA 99 4E 43 STA $434E,Y ;set as last job performed
F7BD B4 51 LDY $51,X ;read alternate buffer number
F7BF 99 4E 43 STA $434E,Y ;set as last job performed
F7C2 99 03 10 STA $1003,Y ;set as current job
F7C5 B5 49 LDA $49,X ;get main buffer number
F7C7 0A ASL ;double it
F7C8 A8 TAY
F7C9 A9 02 LDA #$02
F7CB 99 29 00 STA $0029,Y ;set pointer to first data byte in buffer
F7CE B5 51 LDA $51,X ;get alternate buffer number
F7D0 09 80 ORA #$80 ;set buffer inactive flag
F7D2 95 51 STA $51,X ;store new buffer status
F7D4 0A ASL ;double it
F7D5 A8 TAY
F7D6 A9 02 LDA #$02
F7D8 99 29 00 STA $0029,Y ;set pointer to first data byte in buffer
F7DB A9 00 LDA #$00
F7DD 95 59 STA $59,X ;clear LO block count
F7DF 95 61 STA $61,X ;clear HI block count
F7E1 A9 00 LDA #$00
F7E3 95 BD STA $BD,X ;set flag to scan next SEQ data block
F7E5 60 RTS
******************************* Open internal write channel with 2 buffers
F7E6 20 3E D7 JSR $D73E ;get first track and sector
F7E9 A9 02 LDA #$02
F7EB 20 5B EE JSR $EE5B ;set for opening of two new write channels
F7EE 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
F7F1 20 B4 F7 JSR $F7B4 ;initialize pointers
F7F4 A6 15 LDX $15 ;get current active buffer
F7F6 A5 C5 LDA $C5 ;get current active file type
F7F8 48 PHA ;preserve it
F7F9 0A ASL ;double it
F7FA 05 12 ORA $12 ;add in drive number
F7FC 95 90 STA $90,X ;store file information in file type table
SEQ = type 1
PRG = type 2
USR = type 3
REL = type 4
direct = type 7
F7FE 68 PLA ;retrieve active file type
F7FF C9 04 CMP #$04 ;is this a REL file ?
F801 F0 05 BEQ $F808 ;yes,
F803 A9 01 LDA #$01 ;set for "active listener" status
F805 95 98 STA $98,X ;set channel status
bit 7 = channel is talker (set to 1)
3 = channel is send EOI (talker only)
0 = channel is listener (set to 1)
F807 60 RTS
******************************* Test for available side sector buffer
F808 A4 16 LDY $16 ;get current secondary address
F80A B9 A2 00 LDA $00A2,Y ;read channel status
bit 7 & 6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
F80D 29 3F AND #$3F ;preserve channel status bits only
F80F 09 40 ORA #$40 ;set channel status to: 01 (read/write)
F811 99 A2 00 STA $00A2,Y ;set new channel status
bit 7 & 6: 00 = read channel
10 = write channel
01 = read/write channel
11 = no channel
F814 AD 4B 43 LDA $434B ;get record size value
F817 95 71 STA $71,X ;store in RELative record size table
F819 20 FE EE JSR $EEFE ;buffer available for use with side sector ?
F81C 10 03 BPL $F821 ;yes,
F81E 4C 87 EE JMP $EE87 ;indicate no buffer available for side sector
******************************* Set up and write out side sector and data
block
F821 A6 15 LDX $15 ;get active buffer number
F823 95 79 STA $79,X ;store as new side sector buffer number
F825 20 C6 F9 JSR $F9C6 ;clear the side sector buffer
F828 20 AF D6 JSR $D6AF ;find next available track and sector
F82B A5 13 LDA $13 ;read current track number
F82D 8D 4C 43 STA $434C ;set as current side sector track number
F830 A5 14 LDA $14 ;read current sector number
F832 8D 4D 43 STA $434D ;set as current side sector number
F835 A6 15 LDX $15 ;get active buffer number
F837 B5 79 LDA $79,X ;get side sector buffer number
F839 20 92 EC JSR $EC92 ;set track, sector, ID for current buffer
F83C A9 00 LDA #$00
F83E 20 EE F9 JSR $F9EE ;set buffer pointer by use of current side
sector pointer
F841 A9 00 LDA #$00
F843 20 98 F8 JSR $F898 ;store null link
F846 A9 11 LDA #$11 ;set side sector offset to: offset + 1
F848 20 98 F8 JSR $F898 ;store side sector offset
F84B A9 00 LDA #$00 ;set side sector number
F84D 20 98 F8 JSR $F898 ;store side sector number
F850 AD 4B 43 LDA $434B ;read current record size
F853 20 98 F8 JSR $F898 ;store record size
F856 A5 13 LDA $13 ;read current side sector track number
F858 20 98 F8 JSR $F898 ;store track number
F85B A5 14 LDA $14 ;read current side sector number
F85D 20 98 F8 JSR $F898 ;store sector number
F860 A9 10 LDA #$10 ;set side sector offset
F862 20 EE F9 JSR $F9EE ;set buffer pointer by use of current side
sector pointer
F865 20 41 F9 JSR $F941 ;get track and sector for side sector
F868 A5 13 LDA $13 ;read current track number
F86A 20 98 F8 JSR $F898 ;store track number
F86D A5 14 LDA $14 ;read current sector number
F86F 20 98 F8 JSR $F898 ;store sector number
F872 20 71 F9 JSR $F971 ;write out side sector block to diskette
F875 20 82 EC JSR $EC82 ;wait until job completed
F878 A9 02 LDA #$02
F87A 20 C1 F0 JSR $F0C1 ;set new pointer position for data block
F87D A6 15 LDX $15 ;get active buffer number
F87F 38 SEC
F880 A9 00 LDA #$00
F882 F5 71 SBC $71,X ;calculate last record position
F884 95 69 STA $69,X ;store result in next record table
F886 20 CF FD JSR $FDCF ;null records in active data buffer
F889 20 1C F9 JSR $F91C ;set track link to #$00 and sector link to last
character position in buffer
F88C 20 63 F9 JSR $F963 ;write out nulled record block
F88F 20 82 EC JSR $EC82 ;wait until job completed
F892 20 55 F6 JSR $F655 ;write out BAM to diskette under use
F895 4C 97 F7 JMP $F797 ;finish opening channel
******************************* Put byte into side sector
F898 48 PHA ;preserve byte to send
F899 A6 15 LDX $15 ;get current active buffer number
F89B B5 79 LDA $79,X ;get current side sector number
F89D 4C BD EC JMP $ECBD ;store byte in assigned buffer position
******************************* Set/Clear file type flag
F8A0 90 06 BCC $F8A8 ;clear flag request ? yes,
F8A2 A6 15 LDX $15 ;get current active buffer number
F8A4 15 90 ORA $90,X ;flag set ?
F8A6 D0 06 BNE $F8AE ;yes,
F8A8 A6 15 LDX $15 ;get current active buffer number
F8AA 49 FF EOR #$FF ;invert bits
F8AC 35 90 AND $90,X ;clear flag
F8AE 95 90 STA $90,X ;store new flag status
F8B0 60 RTS
******************************* Test file type flag status
F8B1 A6 15 LDX $15 ;get current active buffer number
F8B3 35 90 AND $90,X ;determine flag status
F8B5 60 RTS
******************************* Test if write job
F8B6 20 98 FA JSR $FA98 ;get active buffer number
F8B9 AA TAX
F8BA BD 4E 43 LDA $434E,X ;read last job entered in que status
F8BD 29 F0 AND #$F0 ;determine job command code number
F8BF C9 90 CMP #$90 ;was it a WRITE job ? (.Z = 1)
F8C1 60 RTS
******************************* Test for active files
Not active (.C = 1) .X = 18
Active (.C = 0) .X = entry found
.Y = channel status
F8C2 A2 00 LDX #$00 ;set secondary address to #$00
F8C4 86 06 STX $06 ;store in TEMP2 location
F8C6 B5 A2 LDA $A2,X ;get buffer corresponding to secondary address
F8C8 C9 FF CMP #$FF ;is it active ?
F8CA D0 08 BNE $F8D4 ;yes,
F8CC A6 06 LDX $06 ;read secondary address count
F8CE E8 INX ;do next secondary address channel
F8CF E0 10 CPX #$10 ;all secondary address channel tested ?
F8D1 90 F1 BCC $F8C4 ;no,
F8D3 60 RTS
******************************* Test if directory entry matches secondary
address entry
F8D4 86 06 STX $06 ;save secondary address value
F8D6 29 3F AND #$3F ;determine channel type
F8D8 A8 TAY
F8D9 B9 90 00 LDA $0090,Y ;get file information from table
F8DC 29 01 AND #$01 ;extract drive number
F8DE 85 05 STA $05 ;store in TEMP1 location
F8E0 AE 45 43 LDX $4345 ;get directory entry flag
F8E3 B5 8B LDA $8B,X ;read file information for secondary address
F8E5 29 01 AND #$01 ;extract drive number
F8E7 C5 05 CMP $05 ;same drive number ?
F8E9 D0 E1 BNE $F8CC ;no,
F8EB B9 6B 43 LDA $436B,Y ;get directory entry information
F8EE D5 86 CMP $86,X ;file information matches secondary address
information ?
F8F0 D0 DA BNE $F8CC ;no,
F8F2 18 CLC
F8F3 60 RTS
******************************* Write out buffer if no longer current
F8F4 20 A3 FA JSR $FAA3 ;should buffer be re-written to disk ?
F8F7 50 06 BVC $F8FF ;no,
F8F9 20 63 F9 JSR $F963 ;write buffer out to disk
F8FC 20 82 EC JSR $EC82 ;wait until job completed
F8FF 60 RTS
******************************* Put track and sector into buffer
F900 20 2E F9 JSR $F92E ;set up current buffer pointers
F903 A5 13 LDA $13 ;read current track number
F905 91 27 STA ($27),Y ;store in directory buffer
F907 C8 INY
F908 A5 14 LDA $14 ;read current sector number
F90A 91 27 STA ($27),Y ;store in directory buffer
F90C 4C EE FB JMP $FBEE ;set flag to indicate that buffer needs to be
written out to diskette
******************************* Get track and sector from buffer
F90F 20 2E F9 JSR $F92E ;set up current buffer pointers
F912 B1 27 LDA ($27),Y ;read track value from directory buffer
F914 85 13 STA $13 ;set as current track number
F916 C8 INY
F917 B1 27 LDA ($27),Y ;read sector value from directory buffer
F919 85 14 STA $14 ;set as current sector number
F91B 60 RTS
******************************* Set track link to #$00 and sector link to
point to last character in current buffer
F91C 20 2E F9 JSR $F92E ;set up current buffer pointers
F91F A9 00 LDA #$00
F921 91 27 STA ($27),Y ;set track link to #$00
F923 C8 INY
F924 A6 15 LDX $15 ;get active buffer number
F926 B5 69 LDA $69,X ;read pointer position into current buffer
F928 AA TAX
F929 CA DEX ;decrement pointer by one
F92A 8A TXA
F92B 91 27 STA ($27),Y ;set sector link to mark last character in
buffer
F92D 60 RTS
******************************* Set up pointer to active buffer
F92E 20 98 FA JSR $FA98 ;get active buffer number
F931 0A ASL
F932 AA TAX
F933 B5 2A LDA $2A,X ;read HI byte of buffer pointer
F935 85 28 STA $28 ;set as HI byte for directory buffer
F937 A9 00 LDA #$00 ;set LO byte of buffer pointer to #$00
F939 85 27 STA $27 ;set as LO byte for directory buffer
F93B A0 00 LDY #$00
F93D 60 RTS
******************************* Read track and sector values from HEADER
F93E 20 69 ED JSR $ED69 ;find internal read channel
F941 20 98 FA JSR $FA98 ;get active buffer number
F944 85 A1 STA $A1 ;set as current job number
F946 0A ASL ;multiply buffer number by two
F947 0A ASL ;multiply new result by two
F948 0A ASL ;multiply new result by two
F949 A8 TAY ;set HEADER buffer corresponding with current
buffer
F94A B9 23 10 LDA $1023,Y ;read track value from JOB HEADER table for
current buffer
F94D 85 13 STA $13 ;set as current track number
F94F B9 24 10 LDA $1024,Y ;read sector value from JOB HEADER table for
current buffer
F952 85 14 STA $14 ;set as current sector number
F954 60 RTS
******************************* Job que: WRITE a buffer
F955 A9 90 LDA #$90 ;set job: WRITE
F957 8D 3C 43 STA $433C ;is this a WRITE job ?
F95A D0 28 BNE $F984 ;yes,
******************************* Job que: READ a buffer
F95C A9 80 LDA #$80 ;set job: READ
F95E 8D 3C 43 STA $433C ;is this a READ job ?
F961 D0 21 BNE $F984 ;yes,
******************************* Job que: WRITE
F963 A9 90 LDA #$90 ;set job: WRITE
F965 8D 3C 43 STA $433C ;is this a WRITE job ?
F968 D0 26 BNE $F990 ;yes,
******************************* Job que: READ
F96A A9 80 LDA #$80 ;set job: READ
F96C 8D 3C 43 STA $433C ;is this a READ job ?
F96F D0 1F BNE $F990 ;yes,
******************************* Job que: WRITE side sector
F971 A9 90 LDA #$90 ;set job: WRITE
F973 8D 3C 43 STA $433C ;is this a WRITE job ?
F976 D0 02 BNE $F97A ;yes,
******************************* Job que: READ side sector
F978 A9 80 LDA #$80 ;set job: READ
F97A 8D 3C 43 STA $433C ;set for READ job
F97D A6 15 LDX $15 ;get active buffer number
F97F B5 79 LDA $79,X ;get side sector buffer number
F981 AA TAX ;is buffer used ?
F982 10 13 BPL $F997 ;yes,
F984 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
F987 20 98 FA JSR $FA98 ;get active buffer number
F98A AA TAX
F98B A5 12 LDA $12 ;read current drive number
F98D 9D 4E 43 STA $434E,X ;assign drive number to buffer
F990 20 F9 FB JSR $FBF9 ;clear "write out buffer" flag
F993 20 98 FA JSR $FA98 ;get active buffer number
F996 AA TAX
F997 4C 0E F1 JMP $F10E ;set drive number and job command
******************************* Set track and sector from link in buffer
F99A A9 00 LDA #$00
F99C 20 C1 F0 JSR $F0C1 ;set new pointer position
F99F 20 B3 ED JSR $EDB3 ;read track link byte from active buffer
F9A2 85 13 STA $13 ;set as current track number
F9A4 20 B3 ED JSR $EDB3 ;read sector link byte from active buffer
F9A7 85 14 STA $14 ;set as current sector number
F9A9 60 RTS
******************************* Transfer bytes from one buffer to other
.Y = source buffer number
.X = destination buffer number
.ACC = number of bytes
F9AA 48 PHA ;preserve number of bytes to move counter
F9AB A9 00 LDA #$00
F9AD 85 04 STA $04 ;clear TEMP0 location
F9AF 85 06 STA $06 ;clear TEMP2 location
F9B1 B9 FF F0 LDA $F0FF,Y ;get source buffer HI byte address
F9B4 85 05 STA $05 ;set source buffer number
F9B6 BD FF F0 LDA $F0FF,X ;get destination buffer HI byte address
F9B9 85 07 STA $07 ;set destination buffer number
F9BB 68 PLA ;retrieve bytes to move counter
F9BC A8 TAY
F9BD 88 DEY ;decrement byte counter
F9BE B1 04 LDA ($04),Y ;read byte from source buffer
F9C0 91 06 STA ($06),Y ;store in destination buffer
F9C2 88 DEY ;all bytes transferred ?
F9C3 10 F9 BPL $F9BE ;no,
F9C5 60 RTS
******************************* Clear requested buffer
.ACC = buffer number
F9C6 A8 TAY
F9C7 B9 FF F0 LDA $F0FF,Y ;get buffer HI byte address
F9CA 85 05 STA $05 ;set buffer number
F9CC A9 00 LDA #$00
F9CE 85 04 STA $04 ;set buffer LO byte address
F9D0 A8 TAY
F9D1 91 04 STA ($04),Y ;null current position in buffer
F9D3 C8 INY ;all bytes in buffer nulled ?
F9D4 D0 FB BNE $F9D1 ;no,
F9D6 60 RTS
******************************* Set side sector pointer
F9D7 A9 00 LDA #$00
F9D9 20 E1 F9 JSR $F9E1 ;set buffer pointer for current buffer
F9DC A0 02 LDY #$02
F9DE B1 27 LDA ($27),Y ;read side sector pointer from directory buffer
F9E0 60 RTS
******************************* Use side sector pointer to set directory
buffer pointer
F9E1 85 27 STA $27 ;set LO byte address of directory buffer
F9E3 A6 15 LDX $15 ;get active buffer number
F9E5 B5 79 LDA $79,X ;get side sector buffer number
F9E7 AA TAX
F9E8 BD FF F0 LDA $F0FF,X ;read HI byte address for current buffer
F9EB 85 28 STA $28 ;set as HI byte address of directory buffer
F9ED 60 RTS
******************************* Set directory buffer & buffer table with
current side sector pointer
F9EE 48 PHA ;preserve LO byte address
F9EF 20 E1 F9 JSR $F9E1 ;set directory buffer pointer
F9F2 48 PHA ;preserve HI byte address
F9F3 8A TXA
F9F4 0A ASL ;multiply side sector buffer number by two
F9F5 AA TAX
F9F6 68 PLA ;retrieve HI byte address
F9F7 95 2A STA $2A,X ;set current buffer HI byte address
F9F9 68 PLA ;retrieve LO byte address
F9FA 95 29 STA $29,X ;set current buffer LO byte address
F9FC 60 RTS
******************************* Test if side sector and index are within
the allowed range
.V = 0 (within range)
= 1 (out of range)
F9FD 20 6B FA JSR $FA6B ;is side sector number and index within range ?
FA00 30 0E BMI $FA10 ;no,
FA02 50 13 BVC $FA17 ;yes,
FA04 A6 15 LDX $15 ;get active buffer number
FA06 B5 79 LDA $79,X ;get side sector buffer number
FA08 20 20 FA JSR $FA20 ;read in side sector
FA0B 20 6B FA JSR $FA6B ;is side sector number and index within range ?
FA0E 10 07 BPL $FA17 ;yes,
FA10 20 B1 FC JSR $FCB1 ;set side sector and buffer table to end of
last record
FA13 2C E5 D2 BIT $D2E5 ;set flags to indicate side sector and index
are out of range
FA16 60 RTS
******************************* Position directory buffer and buffer table
FA17 A5 84 LDA $84 ;read side sector pointer
FA19 20 EE F9 JSR $F9EE ;set directory buffer and buffer table
FA1C 2C E4 D2 BIT $D2E4 ;set flags to indicate side sector and index
are within range
FA1F 60 RTS
******************************* Indirect block read
.ACC = current buffer number
FA20 85 A1 STA $A1 ;store buffer number as current job
FA22 A9 80 LDA #$80 ;is this a READ job ?
FA24 D0 04 BNE $FA2A ;yes,
******************************* Indirect block write
.ACC = current buffer number
FA26 85 A1 STA $A1 ;store buffer number as current job
FA28 A9 90 LDA #$90 ;set for WRITE job
******************************* Perform block read/write
.X = active buffer number
.ACC = current buffer number
FA2A 48 PHA ;preserve job code
FA2B B5 90 LDA $90,X ;get filetype for channel
FA2D 29 01 AND #$01 ;extract drive number
FA2F 85 12 STA $12 ;set as current drive number
FA31 68 PLA ;retrieve job code
FA32 05 12 ORA $12 ;add in drive number
FA34 8D 3C 43 STA $433C ;store job code in temporary job location
FA37 B1 27 LDA ($27),Y ;get track number from directory buffer
FA39 85 13 STA $13 ;set as current track number
FA3B C8 INY
FA3C B1 27 LDA ($27),Y ;get sector number from directory buffer
FA3E 85 14 STA $14 ;set as current sector number
FA40 A5 A1 LDA $A1 ;get buffer number
FA42 20 92 EC JSR $EC92 ;set track, sector, ID for current buffer
FA45 A6 A1 LDX $A1 ;get buffer number
FA47 4C A0 F1 JMP $F1A0 ;perform request job command
******************************* Get side sector pointers
FA4A A6 15 LDX $15 ;get active buffer number
FA4C B5 79 LDA $79,X ;get side sector buffer number
FA4E 4C E4 F0 JMP $F0E4 ;set new directory buffer pointers
******************************* Calculate side sectors
FA51 A9 78 LDA #$78 ;set number of side sector pointers in a buffer
FA53 20 61 FA JSR $FA61 ;add number for (side sectors needed * #$78)
(decimal 120)
FA56 CA DEX ;all side sectors considered ?
FA57 10 F8 BPL $FA51 ;no,
FA59 A5 07 LDA $07 ;get number of side sector indices needed
FA5B 4A LSR ;divide by two
FA5C 20 61 FA JSR $FA61 ;add number for side sectors needed
FA5F A5 08 LDA $08 ;get number of side sector blocks needed
FA61 18 CLC
FA62 65 05 ADC $05 ;add number for side sector blocks needed
FA64 85 05 STA $05 ;is result below #$FF (decimal 255)
FA66 90 02 BCC $FA6A ;yes,
FA68 E6 06 INC $06 ;increment HI byte for result
FA6A 60 RTS
******************************* Test side sector number and side sector
index for residence and range
.N = range .V = residence ERROR #
0 = ok 0 = yes ER0
0 = maybe 1 = no ER1
1 = no 0 = yes ER2
1 = no 1 = no ER3
FA6B 20 D7 F9 JSR $F9D7 ;set pointer and get side sector number
FA6E C5 83 CMP $83 ;correct side sector ?
FA70 D0 0E BNE $FA80 ;no,
FA72 A4 84 LDY $84 ;read pointer into side sector buffer value
FA74 B1 27 LDA ($27),Y ;is side sector present ?
FA76 F0 04 BEQ $FA7C ;no,
FA78 2C E4 D2 BIT $D2E4 ;set flags to indicate residence or range
valid
FA7B 60 RTS
******************************* Indicate side sector out of range
FA7C 2C E6 D2 BIT $D2E6 ;set flags to indicate residence or range
invalid
FA7F 60 RTS
******************************* Test side sector status
FA80 A5 83 LDA $83 ;read side sector number
FA82 C9 06 CMP #$06 ;side sector value out range ?
FA84 B0 0A BCS $FA90 ;yes,
FA86 0A ASL ;multiply side sector number by two
FA87 A8 TAY
FA88 A9 04 LDA #$04 ;set LO byte of pointer to #$04
FA8A 85 27 STA $27 ;store pointer value in directory buffer
FA8C B1 27 LDA ($27),Y ;is side sector resident within range ?
FA8E D0 04 BNE $FA94 ;no,
******************************* Indicate side sector out of range
FA90 2C E7 D2 BIT $D2E7 ;set flags to indicate side sector way out of
range
FA93 60 RTS
******************************* Indicate side sector not resident
FA94 2C E5 D2 BIT $D2E5 ;set flags to indicate invalid side sector
residence or range
FA97 60 RTS
******************************* Get active buffer number
.X = logical index
.ACC = active buffer number
.N = no active buffer (set to 1)
FA98 A6 15 LDX $15 ;get active buffer number
FA9A B5 49 LDA $49,X ;is first buffer active ?
FA9C 10 02 BPL $FAA0 ;yes,
FA9E B5 51 LDA $51,X ;get second buffer number
FAA0 29 BF AND #$BF ;clear buffer bit
FAA2 60 RTS
******************************* Get active buffer number and set last
buffer used
.X = logical index
.ACC = active buffer number
.N = no active buffer (set to 1)
.V = buffer needs updating
FAA3 A6 15 LDX $15 ;get active buffer number
FAA5 8E 49 43 STX $4349 ;set as last buffer used
FAA8 B5 49 LDA $49,X ;is first buffer active ?
FAAA 10 09 BPL $FAB5 ;yes,
FAAC 8A TXA
FAAD 18 CLC
FAAE 69 08 ADC #$08 ;add in maximum possible channels to active
buffer number
FAB0 8D 49 43 STA $4349 ;store new result as last buffer used
FAB3 B5 51 LDA $51,X ;get second buffer number
FAB5 85 05 STA $05 ;store in TEMP1 location
FAB7 29 1F AND #$1F ;set .N and .V flags as required
FAB9 24 05 BIT $05 ;test buffer status
FABB 60 RTS
******************************* Mark end of record then move on to next
record
FABC A9 60 LDA #$60 ;set for get record and overflow flag
FABE 20 A8 F8 JSR $F8A8 ;clear record and overflow flag
FAC1 A9 80 LDA #$80 ;set last record flag
FAC3 20 B1 F8 JSR $F8B1 ;beyond last record ?
FAC6 D0 41 BNE $FB09 ;no,
FAC8 A6 15 LDX $15 ;get current active channel number
FACA F6 59 INC $59,X ;has LO address counter reached #$00 ?
FACC D0 02 BNE $FAD0 ;no,
FACE F6 61 INC $61,X ;increment HI address counter
FAD0 A6 15 LDX $15 ;get current active channel number
FAD2 B5 69 LDA $69,X ;is there another record to move to ?
FAD4 F0 2E BEQ $FB04 ;no,
FAD6 20 E1 F0 JSR $F0E1 ;read active buffer pointer
FAD9 A6 15 LDX $15 ;read current active channel number
FADB D5 69 CMP $69,X ;same buffer ?
FADD 90 03 BCC $FAE2 ;no,
FADF 20 28 FB JSR $FB28 ;set up next buffer
FAE2 A6 15 LDX $15 ;read current active channel number
FAE4 B5 69 LDA $69,X ;get pointer to next record
FAE6 20 C1 F0 JSR $F0C1 ;advance to next record
FAE9 A1 29 LDA ($29,X) ;read first byte from record
FAEB 85 18 STA $18 ;store in temporary data location
FAED A9 60 LDA #$60 ;set for get record and overflow flag
FAEF 20 A8 F8 JSR $F8A8 ;clear record and overflow flag
FAF2 20 F1 FD JSR $FDF1 ;advance record pointer
FAF5 48 PHA ;preserve current record pointer, has a block
boundary been crossed ?
FAF6 90 28 BCC $FB20 ;no,
FAF8 A9 00 LDA #$00
FAFA 20 EF F0 JSR $F0EF ;is this the last data block for file ?
FAFD D0 21 BNE $FB20 ;no,
FAFF 68 PLA ;retrieve record pointer
FB00 C9 02 CMP #$02 ;is pointer pointing to sector link ?
FB02 F0 12 BEQ $FB16 ;yes,
FB04 A9 80 LDA #$80
FB06 20 A2 F8 JSR $F8A2 ;set last record flag
FB09 20 AB ED JSR $EDAB ;set buffer pointers
FB0C B5 29 LDA $29,X ;read byte from active buffer
FB0E 99 BD 00 STA $00BD,Y ;store as last character pointer
FB11 A9 0D LDA #$0D ;set for carriage return #$0D (decimal 13)
FB13 85 18 STA $18 ;store in temporary data location
FB15 60 RTS
******************************* Store current pointer value in buffer and
set new pointer value
FB16 20 21 FB JSR $FB21 ;set pointer to last character
FB19 A6 15 LDX $15 ;read current active channel number
FB1B A9 00 LDA #$00
FB1D 95 69 STA $69,X ;clear pointer to next record
FB1F 60 RTS
******************************* Set pointer to last character
FB20 68 PLA ;retrieve pointer position to next character
FB21 A6 15 LDX $15 ;read current active channel
FB23 95 69 STA $69,X ;store pointer to next record
FB25 4C 56 FC JMP $FC56 ;set pointer to last character in record
******************************* Set up next record in buffer
FB28 20 4F EE JSR $EE4F ;set drive number used in last job
FB2B 20 9A F9 JSR $F99A ;set new track and sector values from link in
buffer
FB2E 20 A3 FA JSR $FAA3 ;should buffer be updated on disk ?
FB31 50 16 BVC $FB49 ;no,
FB33 20 63 F9 JSR $F963 ;write modified buffer to diskette
FB36 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FB39 A9 02 LDA #$02
FB3B 20 C1 F0 JSR $F0C1 ;set new pointer position
FB3E 20 B6 F8 JSR $F8B6 ;was last job equal to WRITE ?
FB41 D0 24 BNE $FB67 ;no,
FB43 20 5C F9 JSR $F95C ;read in needed buffer
FB46 4C 82 EC JMP $EC82 ;wait until job completed
******************************* Test if last data block in file
FB49 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FB4C 20 B6 F8 JSR $F8B6 ;was last job equal to WRITE ?
FB4F D0 06 BNE $FB57 ;no,
FB51 20 5C F9 JSR $F95C ;read in needed buffer
FB54 20 82 EC JSR $EC82 ;wait until job completed
FB57 20 9A F9 JSR $F99A ;set new track and sector values from link in
buffer
FB5A A5 13 LDA $13 ;last data block of file ?
FB5C F0 09 BEQ $FB67 ;yes,
FB5E 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FB61 20 5C F9 JSR $F95C ;read in needed buffer
FB64 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FB67 60 RTS
******************************* Write relative data into buffer
FB68 20 EE FB JSR $FBEE ;mark buffer as being updated and ready for
transfer to disk
FB6B 20 98 FA JSR $FA98 ;get active buffer number
FB6E 0A ASL ;double it
FB6F AA TAX
FB70 A5 18 LDA $18 ;read data byte stored in temporary location
FB72 81 29 STA ($29,X) ;store byte in buffer
FB74 B4 29 LDY $29,X ;read LO pointer value for current buffer
FB76 C8 INY ;end of buffer ?
FB77 D0 09 BNE $FB82 ;no,
FB79 A4 15 LDY $15 ;read current active channel number
FB7B B9 69 00 LDA $0069,Y ;is there another record ?
FB7E F0 0A BEQ $FB8A ;no,
FB80 A0 02 LDY #$02
FB82 98 TYA
FB83 A4 15 LDY $15 ;read current active channel number
FB85 D9 69 00 CMP $0069,Y ;is value in record table used as a pointer ?
FB88 D0 05 BNE $FB8F ;no,
FB8A A9 20 LDA #$20 ;set for "RECORD FULL"
FB8C 4C A2 F8 JMP $F8A2 ;set overflow flag
******************************* Test if end of buffer. If not, set up next
record in buffer
FB8F F6 29 INC $29,X ;end of buffer ?
FB91 D0 03 BNE $FB96 ;no,
FB93 20 28 FB JSR $FB28 ;set up next record in buffer
FB96 60 RTS
******************************* Write record to data buffer
FB97 A9 A0 LDA #$A0 ;set for testing if this is the last record
or if the overflow is set
FB99 20 B1 F8 JSR $F8B1 ;any flags set ?
FB9C D0 24 BNE $FBC2 ;yes,
FB9E A5 18 LDA $18 ;get data to send from temporary location
FBA0 20 68 FB JSR $FB68 ;store data in buffer
FBA3 A5 A0 LDA $A0 ;was EOI signal detected ?
FBA5 F0 0D BEQ $FBB4 ;no,
FBA7 60 RTS
******************************* Test if overflow error and set up next
record
FBA8 A9 20 LDA #$20 ;set for testing of overflow flag
FBAA 20 B1 F8 JSR $F8B1 ;is there an overflow error ?
FBAD F0 05 BEQ $FBB4 ;no,
FBAF A9 51 LDA #$51 ;set for "51 OVERFLOW IN RECORD" error
FBB1 8D 73 43 STA $4373 ;store error status
FBB4 20 DC FB JSR $FBDC ;clear rest of record
FBB7 20 3C FC JSR $FC3C ;set up for next record
FBBA AD 73 43 LDA $4373 ;is there an error detected ?
FBBD F0 0B BEQ $FBCA ;no,
FBBF 4C C3 DB JMP $DBC3 ;jump to process command error routine
******************************* Test for last record flag and EOI status
FBC2 29 80 AND #$80 ;was last record flag detected ?
FBC4 D0 05 BNE $FBCB ;no,
FBC6 A5 A0 LDA $A0 ;was EOI signal detected ?
FBC8 F0 DE BEQ $FBA8 ;no,
FBCA 60 RTS
******************************* Add new relative record to file and write
data byte
FBCB A5 18 LDA $18 ;get data from temporary location
FBCD 48 PHA ;preserve it
FBCE 20 09 FE JSR $FE09 ;add new record to relative file
FBD1 68 PLA ;retrieve data
FBD2 85 18 STA $18 ;store in temporary location
FBD4 A9 80 LDA #$80 ;set for last record flag mode
FBD6 20 A8 F8 JSR $F8A8 ;clear last record flag status
FBD9 4C 9E FB JMP $FB9E ;write record to data buffer
******************************* Fill balance of relative record with #$00
FBDC A9 20 LDA #$20 ;set for testing of overflow flag
FBDE 20 B1 F8 JSR $F8B1 ;has an overflow occured ?
FBE1 D0 0A BNE $FBED ;yes,
FBE3 A9 00 LDA #$00
FBE5 85 18 STA $18 ;store data in temporary location
FBE7 20 68 FB JSR $FB68 ;write data byte in temporary location to
buffer
FBEA 4C DC FB JMP $FBDC ;do balance of record until overflow detected
FBED 60 RTS
******************************* Set flag to indicate that buffer needs to
be updated on disk
FBEE 20 A3 FA JSR $FAA3 ;get active buffer number
FBF1 09 40 ORA #$40 ;set buffer needs updating flag
FBF3 AE 49 43 LDX $4349 ;get buffer pointer value
FBF6 95 49 STA $49,X ;store new buffer status
FBF8 60 RTS
******************************* Clear flag indicating that buffer needs
to be updated on disk
FBF9 20 A3 FA JSR $FAA3 ;get active buffer number
FBFC 29 BF AND #$BF ;clear buffer update request flag
FBFE AE 49 43 LDX $4349 ;get buffer pointer value
FC01 95 49 STA $49,X ;store new buffer status
FC03 60 RTS
******************************* Get byte from relative record
FC04 A9 80 LDA #$80 ;set for testing of EOI signal
FC06 20 B1 F8 JSR $F8B1 ;last byte in file encountered ?
FC09 D0 3C BNE $FC47 ;yes,
FC0B A9 40 LDA #$40 ;set for active REL file type
FC0D 20 A2 F8 JSR $F8A2 ;set file type and buffers for current file
FC10 20 AB ED JSR $EDAB ;set buffer pointers for current record
FC13 B5 29 LDA $29,X ;read LO buffer pointer value
FC15 D9 BD 00 CMP $00BD,Y ;has next record been reached ?
FC18 F0 22 BEQ $FC3C ;yes,
FC1A F6 29 INC $29,X ;all bytes in current record read ?
FC1C D0 06 BNE $FC24 ;no,
FC1E 20 28 FB JSR $FB28 ;set up next record in buffer
FC21 20 AB ED JSR $EDAB ;set buffer pointers for current record
FC24 A1 29 LDA ($29,X) ;read byte from buffer
FC26 99 B5 00 STA $00B5,Y ;send byte to IEEE channel
FC29 A9 89 LDA #$89 ;set channel status to: 1000 1001
FC2B 99 98 00 STA $0098,Y ;set new channel status
bit 7 = 1 (channel is talker to IEEE)
3 = 0 (send EOI)
0 = 1 (channel is listener to IEEE)
FC2E B5 29 LDA $29,X ;read LO buffer pointer value
FC30 D9 BD 00 CMP $00BD,Y ;has next record been reached ?
FC33 F0 01 BEQ $FC36 ;yes,
FC35 60 RTS
******************************* Set channel status to EOI (End Or Identify)
FC36 A9 81 LDA #$81 ;set channel status to: 1000 0001
FC38 99 98 00 STA $0098,Y ;set new channel status
bit 7 = 1 (channel is talker to IEEE)
3 = 0 (send EOI)
0 = 1 (channel is listener to IEEE)
FC3B 60 RTS
******************************* Read last byte in record and proceed to
next record in file
FC3C 20 BC FA JSR $FABC ;mark end of record and move to next record
FC3F 20 AB ED JSR $EDAB ;set buffer pointers for current record
FC42 A5 18 LDA $18 ;get data byte from temporary location
FC44 4C 26 FC JMP $FC26 ;send byte to IEEE channel
******************************* Send end of record marker, indicate RECORD
NOT PRESENT error
FC47 A6 15 LDX $15 ;read active channel number
FC49 A9 0D LDA #$0D ;set for carriage return #$0D (decimal 13)
FC4B 95 B5 STA $B5,X ;send to IEEE channel
FC4D A9 81 LDA #$81 ;set channel status to: 1000 0001
FC4F 95 98 STA $98,X ;set new channel status
bit 7 = 1 (channel is talker to IEEE)
3 = 0 (send EOI)
0 = 1 (channel is listener to IEEE)
FC51 A9 50 LDA #$50 ;set for "50 RECORD NOT PRESENT" error
FC53 20 C3 DB JSR $DBC3 ;set up and display error
******************************* Set pointer to last character in record
FC56 A6 15 LDX $15 ;read active channel number
FC58 B5 69 LDA $69,X ;read next record location pointer
FC5A 85 1A STA $1A ;store in TEMPR1 location
FC5C C6 1A DEC $1A ;decrement pointer value
FC5E C9 02 CMP #$02 ;pointer set to beginning of data in sector ?
FC60 D0 04 BNE $FC66 ;no,
FC62 A9 FF LDA #$FF
FC64 85 1A STA $1A ;set pointer to end of data block
FC66 B5 71 LDA $71,X ;read record size value for current file
FC68 85 1B STA $1B ;store in TEMPR2 location
FC6A 20 E1 F0 JSR $F0E1 ;get active buffer pointer value
FC6D A6 15 LDX $15 ;read active channel number
FC6F C5 1A CMP $1A ;still in current buffer ?
FC71 90 18 BCC $FC8B ;yes,
FC73 F0 16 BEQ $FC8B ;yes,
FC75 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FC78 20 98 FC JSR $FC98 ;last non-zero character in record found ?
FC7B 90 07 BCC $FC84 ;yes,
FC7D A6 15 LDX $15 ;read active channel number
FC7F 95 BD STA $BD,X ;store in last character table
FC81 4C D1 EB JMP $EBD1 ;toggle active and inactive buffers
******************************* Test for last non-zero character in buffer
FC84 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FC87 A9 FF LDA #$FF
FC89 85 1A STA $1A ;store in TEMPR1 location
FC8B 20 98 FC JSR $FC98 ;last non-zero character in record found ?
FC8E B0 03 BCS $FC93 ;no,
FC90 20 E1 F0 JSR $F0E1 ;get active buffer pointer value
FC93 A6 15 LDX $15 ;read active channel number
FC95 95 BD STA $BD,X ;store in last character table
FC97 60 RTS
******************************* Find last non-zero character in record
FC98 20 2E F9 JSR $F92E ;set up pointer to start of buffer
FC9B A4 1A LDY $1A ;read starting offset value
FC9D B1 27 LDA ($27),Y ;is data byte read from buffer #$00 ?
FC9F D0 0D BNE $FCAE ;no,
FCA1 88 DEY ;move pointer back
FCA2 C0 02 CPY #$02 ;found start of record ?
FCA4 90 04 BCC $FCAA ;no,
FCA6 C6 1B DEC $1B ;is record size #$00 ?
FCA8 D0 F3 BNE $FC9D ;no,
FCAA C6 1B DEC $1B ;decrement record size
FCAC 18 CLC ;indicate that record was not found
FCAD 60 RTS
******************************* Indicate last non-zero character as present
FCAE 98 TYA ;transfer pointer position for last non-zero
character
FCAF 38 SEC ;indicate last non-zero character located
FCB0 60 RTS
******************************* Position side sector and buffer table to end
of last record
FCB1 20 D7 F9 JSR $F9D7 ;set side sector pointer to #$00
FCB4 85 83 STA $83 ;set as new side sector number
FCB6 A9 04 LDA #$04
FCB8 85 27 STA $27 ;set LO byte address of directory buffer
FCBA A0 0A LDY #$0A ;is side sector offset smaller than #$06
(decimal 6) ?
FCBC D0 04 BNE $FCC2 ;no,
FCBE 88 DEY ;decrement current offset value
FCBF 88 DEY ;has sector offset gone below #$00 ?
FCC0 30 26 BMI $FCE8 ;yes,
FCC2 B1 27 LDA ($27),Y ;is this the last side sector ?
FCC4 F0 F8 BEQ $FCBE ;no,
FCC6 98 TYA
FCC7 4A LSR
FCC8 C5 83 CMP $83 ;is this the last side sector ?
FCCA F0 09 BEQ $FCD5 ;yes,
FCCC 85 83 STA $83 ;set new side sector number as current side
sector
FCCE A6 15 LDX $15 ;read active channel number
FCD0 B5 79 LDA $79,X ;get side sector value from table
FCD2 20 20 FA JSR $FA20 ;perform indirect read of last side sector
FCD5 A0 00 LDY #$00
FCD7 84 27 STY $27 ;set LO byte address of directory buffer
FCD9 B1 27 LDA ($27),Y ;is track link in buffer set to #$00 ?
FCDB D0 0B BNE $FCE8 ;no,
FCDD C8 INY
FCDE B1 27 LDA ($27),Y ;get sector link value from buffer and treat as
last character position in buffer
FCE0 A8 TAY
FCE1 88 DEY ;decrement pointer to last character in buffer
by one
FCE2 84 84 STY $84 ;set as index into current side sector
FCE4 98 TYA
FCE5 4C EE F9 JMP $F9EE ;set directory buffer and buffer table with
current side sector pointer
******************************* Indicate illegal track or sector
FCE8 A9 67 LDA #$67 ;set for "67 ILLEGAL SYSTEM T OR S" error
FCEA 20 53 D9 JSR $D953 ;generate error message
******************************* Command: POSITION (move to new location in a
relative file)
FCED 20 B0 DC JSR $DCB0 ;initialize pointers and tables
FCF0 AD 01 43 LDA $4301 ;read second byte from command buffer
FCF3 85 16 STA $16 ;set as current secondary address
FCF5 20 69 ED JSR $ED69 ;is there an internal read channel available ?
FCF8 90 05 BCC $FCFF ;yes,
FCFA A9 70 LDA #$70 ;set for "70 NO CHANNEL" error
FCFC 20 C3 DB JSR $DBC3 ;set up and display error
FCFF A9 E0 LDA #$E0 ;set flag modes: 1110 0000
FD01 20 A8 F8 JSR $F8A8 ;clear indicated flags (last record, get byte,
overflow)
FD04 20 A1 ED JSR $EDA1 ;is current file type REL ?
FD07 F0 05 BEQ $FD0E ;yes,
FD09 A9 64 LDA #$64 ;set for "64 FILE TYPE MISMATCH" error
FD0B 20 C3 DB JSR $DBC3 ;set up and display error
FD0E B5 90 LDA $90,X ;read file information from table
SEQ = type 1
PRG = type 2
USR = type 3
REL = type 4
direct = type 7
FD10 29 01 AND #$01 ;determine drive number
FD12 85 12 STA $12 ;set as current drive number
FD14 AD 02 43 LDA $4302 ;read third byte from command buffer
FD17 95 59 STA $59,X ;set as LO byte of record number
FD19 AD 03 43 LDA $4303 ;read fourth byte from command buffer
FD1C 95 61 STA $61,X ;set as HI byte of record number
FD1E A6 15 LDX $15 ;read active channel number
FD20 A9 89 LDA #$89 ;set channel status to: 1000 1001
FD22 95 98 STA $98,X ;set new channel status
bit 7 = channel is talker (set to 1)
3 = channel is send EOI (talker only)
0 = channel is listener (set to 1)
FD24 AD 04 43 LDA $4304 ;is pointer position into desired record set to
#$00 ?
FD27 F0 10 BEQ $FD39 ;yes,
FD29 38 SEC
FD2A E9 01 SBC #$01 ;is pointer value now decremented to start of
record ?
FD2C F0 0B BEQ $FD39 ;yes,
FD2E D5 71 CMP $71,X ;is pointer value within record range ?
FD30 90 07 BCC $FD39 ;yes,
FD32 A9 51 LDA #$51 ;set for "51 OVERFLOW IN RECORD" error
FD34 8D 73 43 STA $4373 ;set error status
FD37 A9 00 LDA #$00
FD39 85 82 STA $82 ;set byte requested from record to #$00
FD3B 20 AE EA JSR $EAAE ;calculate side sector pointers
FD3E 20 FD F9 JSR $F9FD ;has side sector pointer gone beyond last
record in file
FD41 50 08 BVC $FD4B ;no,
FD43 A9 80 LDA #$80 ;set flag mode: 1000 0000
FD45 20 A2 F8 JSR $F8A2 ;set flag to indicate last record reached
FD48 4C 47 FC JMP $FC47 ;jump to indicate record not present error
******************************* Move to desired record and test if request
valid
FD4B 20 5B FD JSR $FD5B ;move to desired record
FD4E A9 80 LDA #$80 ;set flag mode: 1000 0000
FD50 20 B1 F8 JSR $F8B1 ;is this an attempt to go beyond last record ?
FD53 F0 03 BEQ $FD58 ;no,
FD55 4C 47 FC JMP $FC47 ;jump to indicate record not present error
******************************* Indicate desired record requested valid
FD58 4C 99 DB JMP $DB99 ;indicate successful command termination
******************************* Position relative data block into active
buffer and next block into inactive buffer
FD5B 20 7D FD JSR $FD7D ;position data blocks into buffers
FD5E A5 85 LDA $85 ;get pointer position into desired record
FD60 20 C1 F0 JSR $F0C1 ;set new pointer position
FD63 A6 15 LDX $15 ;read active channel number
FD65 B5 71 LDA $71,X ;read record size value from table
FD67 38 SEC
FD68 E5 82 SBC $82 ;is determined sector offset valid ?
FD6A B0 03 BCS $FD6F ;yes,
FD6C 4C E8 FC JMP $FCE8 ;indicate illegal track or sector error
******************************* Position pointer to desired record, move to
next record if necessary
FD6F 18 CLC
FD70 65 85 ADC $85 ;has desired position within record
been reached ?
FD72 90 03 BCC $FD77 ;yes,
FD74 69 01 ADC #$01 ;add one to current pointer value
FD76 38 SEC
FD77 20 F5 FA JSR $FAF5 ;set up next record
FD7A 4C 21 FC JMP $FC21 ;finish setting up for next record
******************************* Position proper data blocks into buffers
FD7D A5 27 LDA $27 ;read LO byte address of directory buffer
FD7F 85 1C STA $1C ;store in TEMPR3 location
FD81 A5 28 LDA $28 ;read HI byte address of directory buffer
FD83 85 1D STA $1D ;store in TEMPR4 location
FD85 20 BD FD JSR $FDBD ;is desired block in buffer ?
FD88 F0 44 BEQ $FDCE ;yes,
FD8A 20 F4 F8 JSR $F8F4 ;clean buffer
FD8D 20 0F F9 JSR $F90F ;get track and sector link from buffer
FD90 A5 13 LDA $13 ;is there another data block for file ?
FD92 F0 18 BEQ $FDAC ;no,
FD94 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FD97 20 BD FD JSR $FDBD ;is desired block in buffer ?
FD9A D0 10 BNE $FDAC ;no,
FD9C 20 0F F9 JSR $F90F ;get track and sector link from buffer
FD9F A5 13 LDA $13 ;is this the last data block of file ?
FDA1 F0 2B BEQ $FDCE ;yes,
FDA3 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FDA6 20 5C F9 JSR $F95C ;read in next block of file
FDA9 4C D1 EB JMP $EBD1 ;toggle active and inactive buffers
******************************* Set current track and sector and begin
double buffering
FDAC A0 00 LDY #$00
FDAE B1 1C LDA ($1C),Y ;read track value from directory buffer
FDB0 85 13 STA $13 ;set as current track number
FDB2 C8 INY
FDB3 B1 1C LDA ($1C),Y ;read sector value from directory buffer
FDB5 85 14 STA $14 ;set as current sector number
FDB7 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FDBA 4C 1D ED JMP $ED1D ;begin double buffering
******************************* Check is required block is in buffer
FDBD 20 41 F9 JSR $F941 ;read track and sector values from HEADER
FDC0 A0 00 LDY #$00
FDC2 B1 1C LDA ($1C),Y ;read track value from directory buffer
FDC4 C5 13 CMP $13 ;has desired track been reached ?
FDC6 F0 01 BEQ $FDC9 ;yes,
FDC8 60 RTS
******************************* Test if desired sector has been reached
FDC9 C8 INY
FDCA B1 1C LDA ($1C),Y ;read sector value from directory buffer
FDCC C5 14 CMP $14 ;has desired sector been reached ? (.Z = 1)
FDCE 60 RTS
******************************* Set null records in active buffer for
extension
ENTRY: last record position in previous
buffer
EXIT : last record position in buffer for
next null buffer or to set last
character
FDCF 20 2E F9 JSR $F92E ;set pointers to start of data buffers
FDD2 A0 02 LDY #$02 ;set pointer for third position in data buffer
FDD4 A9 00 LDA #$00
FDD6 91 27 STA ($27),Y ;store #$00 in data buffer
FDD8 C8 INY ;entire buffer filled ?
FDD9 D0 FB BNE $FDD6 ;no,
FDDB 20 F1 FD JSR $FDF1 ;calculate position of next record
FDDE 95 69 STA $69,X ;store new record value in table
FDE0 A8 TAY
FDE1 A9 FF LDA #$FF
FDE3 91 27 STA ($27),Y ;set opening record value for next record
FDE5 20 F1 FD JSR $FDF1 ;all records in block set ?
FDE8 90 F4 BCC $FDDE ;no,
FDEA D0 04 BNE $FDF0 ;another sector block needed ? no,
FDEC A9 00 LDA #$00
FDEE 95 69 STA $69,X ;set position of next record to start of next
sector
FDF0 60 RTS
******************************* Add next record to record size
.C = 1 (buffer boundary has been crossed)
FDF1 A6 15 LDX $15 ;read active channel number
FDF3 B5 69 LDA $69,X ;get next record pointer value
FDF5 38 SEC ;is there another record ?
FDF6 F0 0D BEQ $FE05 ;no,
FDF8 18 CLC
FDF9 75 71 ADC $71,X ;will added record run into next sector ?
FDFB 90 0B BCC $FE08 ;no,
FDFD D0 06 BNE $FE05 ;record fills entire sector ? no,
FDFF A9 02 LDA #$02
FE01 2C E3 D2 BIT $D2E3 ;set flag to indicate another is needed
FE04 60 RTS
******************************* Adjust pointer to compensate for link
FE05 69 01 ADC #$01 ;add one to pointer value to compensate for
link
FE07 38 SEC ;set flag to indicate no more sectors
FE08 60 RTS
******************************* Add blocks to relative file
FE09 20 4F EE JSR $EE4F ;set drive number
FE0C 20 B1 FC JSR $FCB1 ;set up end of file
FE0F 20 7D FD JSR $FD7D ;position proper data blocks into the buffers
FE12 A5 84 LDA $84 ;get side sector index value
FE14 85 1A STA $1A ;store in TEMPR1 location
FE16 A5 83 LDA $83 ;get side sector number
FE18 85 19 STA $19 ;store in TEMPR0 location
FE1A A9 00 LDA #$00
FE1C 85 1B STA $1B ;clear TEMPR2 location
FE1E A9 00 LDA #$00
FE20 85 82 STA $82 ;clear pointer into to record
FE22 20 AE EA JSR $EAAE ;calculate side sector pointers
FE25 20 2E DB JSR $DB2E ;calculate number of free blocks
FE28 A4 15 LDY $15 ;read active channel number
FE2A B6 71 LDX $71,Y ;get record size from table
FE2C CA DEX ;decrement size by one
FE2D 8A TXA
FE2E 18 CLC
FE2F 65 85 ADC $85 ;does next record span into next sector ?
FE31 90 0C BCC $FE3F ;no,
FE33 E6 84 INC $84 ;increment side sector index value by one
FE35 E6 84 INC $84 ;pointer still in current side sector ?
FE37 D0 06 BNE $FE3F ;yes,
FE39 E6 83 INC $83 ;increment side sector number by one
FE3B A9 10 LDA #$10
FE3D 85 84 STA $84 ;set side sector offset to #$10 (decimal 17)
FE3F A5 1A LDA $1A ;get side sector index from TEMPR1 location
FE41 18 CLC
FE42 69 02 ADC #$02 ;add two to side sector index value
FE44 20 EE F9 JSR $F9EE ;set directory buffer & buffer table
FE47 A5 83 LDA $83 ;get side sector number
FE49 C9 06 CMP #$06 ;is there more than 6 side sectors ?
FE4B 90 05 BCC $FE52 ;no,
FE4D A9 52 LDA #$52 ;set for "52 FILE TOO LARGE" error
FE4F 20 C3 DB JSR $DBC3 ;set up and display error
FE52 A5 84 LDA $84 ;get side sector index value
FE54 38 SEC
FE55 E5 1A SBC $1A ;calculation result still indicates blocks
available ?
FE57 B0 03 BCS $FE5C ;yes,
FE59 E9 0F SBC #$0F ;substract side sector offset from current
result
FE5B 18 CLC
FE5C 85 07 STA $07 ;store new result in TEMP3 as side sector
indices
FE5E A5 83 LDA $83 ;get side sector number
FE60 E5 19 SBC $19 ;determine number of side sectors needed
FE62 85 08 STA $08 ;store new result in TEMP4 location
FE64 A2 00 LDX #$00
FE66 86 05 STX $05 ;clear TEMP1 location
FE68 86 06 STX $06 ;clear TEMP2 location
FE6A AA TAX
FE6B 20 56 FA JSR $FA56 ;calculate number of blocks needed
FE6E A5 06 LDA $06 ;HI byte count of blocks needed above #$FF
(decimal 255) ?
FE70 D0 07 BNE $FE79 ;yes,
FE72 A6 05 LDX $05 ;read LO byte count of blocks needed
FE74 CA DEX ;just one side sector laid out ?
FE75 D0 02 BNE $FE79 ;no,
FE77 E6 1B INC $1B ;indicate that one block is to be used
FE79 CD 78 43 CMP $4378 ;is there enough blocks free on diskette ?
FE7C 90 09 BCC $FE87 ;yes,
FE7E D0 CD BNE $FE4D ;no,
FE80 AD 77 43 LDA $4377 ;test LO byte for blocks free on diskette
FE83 C5 05 CMP $05 ;is there enough blocks free on diskette ?
FE85 90 C6 BCC $FE4D ;no,
FE87 A9 01 LDA #$01
FE89 20 EF F0 JSR $F0EF ;get the sector link
FE8C 18 CLC
FE8D 69 01 ADC #$01 ;add in next record
FE8F A6 15 LDX $15 ;read active channel number
FE91 95 69 STA $69,X ;store next record value in table
FE93 20 AF D6 JSR $D6AF ;get next available track and sector
FE96 20 00 F9 JSR $F900 ;set track and sector link by use of values
returned from track/sector search
FE99 A5 1B LDA $1B ;only this sector block needed ?
FE9B D0 15 BNE $FEB2 ;yes,
FE9D 20 63 F9 JSR $F963 ;write current last record to diskette
FEA0 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FEA3 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
FEA6 20 AF D6 JSR $D6AF ;get next available track and sector
FEA9 20 00 F9 JSR $F900 ;set track and sector link by use of values
returned from track/sector search
FEAC 20 CF FD JSR $FDCF ;clear all records in current buffer
FEAF 4C BE FE JMP $FEBE ;chain through file and set side sectors
******************************* Mark current block as last one in file
FEB2 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FEB5 20 8F EC JSR $EC8F ;set track, sector, ID for current buffer
FEB8 20 CF FD JSR $FDCF ;clear all records in current buffer
FEBB 20 1C F9 JSR $F91C ;set track link to indicate last data block
and set sector link to point to last byte
******************************* Chain through file and set side sectors
FEBE 20 63 F9 JSR $F963 ;write current block to diskette
FEC1 20 0F F9 JSR $F90F ;get track and sector from buffer
FEC4 A5 13 LDA $13 ;get current track number
FEC6 48 PHA ;preserve it
FEC7 A5 14 LDA $14 ;get current sector number
FEC9 48 PHA ;preserve it
FECA 20 41 F9 JSR $F941 ;read track and sector values from HEADER
FECD A5 14 LDA $14 ;get current sector number
FECF 48 PHA ;preserve it
FED0 A5 13 LDA $13 ;get current track number
FED2 48 PHA ;preserve it
FED3 20 4A FA JSR $FA4A ;get side sector pointers
FED6 AA TAX ;another side sector needed ?
FED7 D0 0A BNE $FEE3 ;no,
FED9 20 38 FF JSR $FF38 ;get another side sector
FEDC A9 10 LDA #$10 ;set side sector offset to #$10 (decimal 17)
FEDE 20 EE F9 JSR $F9EE ;set directory buffer and buffer table
FEE1 E6 19 INC $19 ;increment side sector count
FEE3 68 PLA ;retrieve track value from HEADER
FEE4 20 98 F8 JSR $F898 ;store byte in side sector
FEE7 68 PLA ;retrieve sector value from HEADER
FEE8 20 98 F8 JSR $F898 ;store byte in side sector
FEEB 68 PLA ;retrieve sector value
FEEC 85 14 STA $14 ;set as current sector number
FEEE 68 PLA ;retrieve track value
FEEF 85 13 STA $13 ;is there another block in file ?
FEF1 F0 0F BEQ $FF02 ;no,
FEF3 A5 19 LDA $19 ;read side sector count
FEF5 C5 83 CMP $83 ;all side sectors blocks done ?
FEF7 D0 A7 BNE $FEA0 ;no,
FEF9 20 4A FA JSR $FA4A ;get side sector pointers
FEFC C5 84 CMP $84 ;almost done chaining through file ?
FEFE 90 A0 BCC $FEA0 ;yes,
FF00 F0 B0 BEQ $FEB2 ;yes, one more block left to do
FF02 20 4A FA JSR $FA4A ;get side sector pointers
FF05 48 PHA ;preserve it
FF06 A9 00 LDA #$00
FF08 20 E1 F9 JSR $F9E1 ;set directory buffer pointer by use of side
sector pointer value
FF0B A9 00 LDA #$00
FF0D A8 TAY
FF0E 91 27 STA ($27),Y ;set track link in buffer to #$00 (last block)
FF10 C8 INY ;move pointer to sector link location
FF11 68 PLA ;retrieve side sector pointer value
FF12 38 SEC
FF13 E9 01 SBC #$01 ;determine position of last byte in block
FF15 91 27 STA ($27),Y ;store in sector link position
FF17 20 71 F9 JSR $F971 ;write out current block of side sectors to
diskette
FF1A 20 82 EC JSR $EC82 ;wait until job completed
FF1D 20 55 F6 JSR $F655 ;write out BAM to diskette
FF20 20 AE EA JSR $EAAE ;calculate side sector pointers
FF23 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FF26 20 FD F9 JSR $F9FD ;is side sector and index within range ?
FF29 70 03 BVS $FF2E ;no,
FF2B 4C 5B FD JMP $FD5B ;position relative data block into active
buffer and next block into inactive buffer
******************************* Indicate record not present
FF2E A9 80 LDA #$80 ;set last record flag mode
FF30 20 A2 F8 JSR $F8A2 ;set indicated flag mode
FF33 A9 50 LDA #$50 ;set for "50 RECORD NOT PRESENT" error
FF35 20 C3 DB JSR $DBC3 ;set up and display error
******************************* Generate new side sector and fix previous
side sector to reflect new side sector
FF38 20 AF D6 JSR $D6AF ;get next available track and sector
FF3B 20 D1 EB JSR $EBD1 ;toggle active and inactive buffers
FF3E 20 F4 F8 JSR $F8F4 ;write out buffer if no longer current on disk
FF41 20 98 FA JSR $FA98 ;get active buffer number
FF44 48 PHA ;preserve it
FF45 20 C6 F9 JSR $F9C6 ;clear buffer
FF48 A6 15 LDX $15 ;read active channel number
FF4A B5 79 LDA $79,X ;read side sector value from table
FF4C A8 TAY
FF4D 68 PLA ;retrieve active buffer number
FF4E AA TAX
FF4F A9 10 LDA #$10 ;set side sector offset to #$10 (decimal 17)
FF51 20 AA F9 JSR $F9AA ;move sixteen bytes from previous side sector
to other buffer
FF54 A9 00 LDA #$00
FF56 20 E1 F9 JSR $F9E1 ;set directory buffer pointer by use of side
sector pointer value
FF59 A0 02 LDY #$02
FF5B B1 27 LDA ($27),Y ;get side sector number
FF5D 48 PHA ;preserve it
FF5E A9 00 LDA #$00
FF60 20 C1 F0 JSR $F0C1 ;set new pointer position to start of side
sector buffer
FF63 68 PLA ;retrieve side sector number
FF64 18 CLC
FF65 69 01 ADC #$01 ;increment side sector number by one
FF67 91 27 STA ($27),Y ;store new result in buffer
FF69 0A ASL ;multiply side sector number by two
FF6A 69 04 ADC #$04 ;add four to result
FF6C 85 1C STA $1C ;store in TEMPR3 location
FF6E A8 TAY
FF6F 38 SEC
FF70 E9 02 SBC #$02 ;substract two from result
FF72 85 1D STA $1D ;store in TEMPR4 location
FF74 A5 13 LDA $13 ;get current track number
FF76 85 1A STA $1A ;store in TEMPR1 location
FF78 91 27 STA ($27),Y ;store in side sector
FF7A C8 INY
FF7B A5 14 LDA $14 ;get current sector number
FF7D 85 1B STA $1B ;store in TEMPR2 location
FF7F 91 27 STA ($27),Y ;store in side sector
FF81 A0 00 LDY #$00
FF83 98 TYA
FF84 91 27 STA ($27),Y ;store track link in new side sector to #$00
FF86 C8 INY
FF87 A9 11 LDA #$11
FF89 91 27 STA ($27),Y ;set sector link to indicate last non-zero as
being after the side sector offset
FF8B A9 10 LDA #$10 ;set for #$10 (decimal 17)
FF8D 20 C1 F0 JSR $F0C1 ;set new pointer position into side sector
FF90 20 55 F9 JSR $F955 ;write out side sector block to disk
FF93 20 82 EC JSR $EC82 ;wait until job completed
******************************* Revise previous side sector to reflect
newly added side sector
FF96 A6 15 LDX $15 ;read active channel number
FF98 B5 79 LDA $79,X ;get side sector buffer number
FF9A 48 PHA ;preserve it
FF9B 20 A3 FA JSR $FAA3 ;get active buffer number and set flags
FF9E A6 15 LDX $15 ;read active channel number
FFA0 95 79 STA $79,X ;swap active buffer number and side sector
buffer number
FFA2 68 PLA ;retrieve side sector buffer number
FFA3 AE 49 43 LDX $4349 ;get last buffer used
FFA6 95 49 STA $49,X ;set buffer as inactive
FFA8 A9 00 LDA #$00
FFAA 20 C1 F0 JSR $F0C1 ;set pointer position to start of buffer
FFAD A0 00 LDY #$00
FFAF A5 13 LDA $13 ;get current track number
FFB1 91 27 STA ($27),Y ;set as new side sector track link
FFB3 C8 INY
FFB4 A5 14 LDA $14 ;get current sector number
FFB6 91 27 STA ($27),Y ;set as new side sector link
FFB8 4C C8 FF JMP $FFC8 ;write side sector to diskette
******************************* Write side sector and update next one if
needed
FFBB 20 98 FA JSR $FA98 ;get active buffer number
FFBE A6 15 LDX $15 ;read active channel number
FFC0 20 20 FA JSR $FA20 ;read next side sector buffer number
FFC3 A9 00 LDA #$00
FFC5 20 C1 F0 JSR $F0C1 ;set pointer position to start of buffer
FFC8 C6 1D DEC $1D ;decrement side sector number by one
FFCA C6 1D DEC $1D ;decrement side sector number by one
FFCC A4 1C LDY $1C ;get pointer value into buffer
FFCE A5 1A LDA $1A ;get side sector track number
FFD0 91 27 STA ($27),Y ;store in buffer
FFD2 C8 INY
FFD3 A5 1B LDA $1B ;get side sector number
FFD5 91 27 STA ($27),Y ;store in buffer
FFD7 20 63 F9 JSR $F963 ;write current block to diskette
FFDA 20 82 EC JSR $EC82 ;wait until job completed
FFDD A4 1D LDY $1D ;read side sector count
FFDF C0 03 CPY #$03 ;any more to update ?
FFE1 B0 D8 BCS $FFBB ;yes,
FFE3 4C D1 EB JMP $EBD1 ;jump to toggle active and inactive buffers
******************************* Versatile non maskable interrupt
FFE6 6C F0 10 JMP ($10F0) ;perform NMI reset
******************************* Checksum byte for $F000
FFE9 11 ??? ;F-ROM checksum
******************************* .Word BLKRD (U1 or UA): $E9FE
FFEA FE E9 ??? ;user block-read
******************************* .Word BLKWRT (U2 or UB): $EA38
FFEC 38 EA ??? ;user block-write
******************************* User command to buffer #02 (U3 - U8)
FFEE 00 13 ??? ;buffer 2 link (U3 or UC): $1300
FFF0 03 13 ??? ;buffer 2 link (U4 or UD): $1303
FFF2 06 13 ??? ;buffer 2 link (U5 or UE): $1306
FFF4 09 13 ??? ;buffer 2 link (U6 or UF): $1309
FFF6 0C 13 ??? ;buffer 2 link (U7 or UG): $130C
FFF8 0F 13 ??? ;buffer 2 link (U8 or UH): $130F
******************************* .Word NMI (U9 or UI): $FFE6
FFFA E6 FF ???
******************************* .Word DISKINIT (U: or UJ): $D32B
FFFC 2B D3 ???
******************************* .Word ATN/IRQ process : $D50A
FFFE 0A D5 ???
Chapter 8 - FORMATTING sequence used for 4040 dual floppy drive
4040 Format codes MAP
Code from $0500 - $07A0
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$0500 Beginning of format codes
$0504 Bump head to track one, initialize buffer pointers to
point to buffer #0: $0421
$052B Initialize track number and move head to desired track
number
$053D Format current track
$054A Erase track with SYNC
$0561 Write OFF bytes and verify SYNC & OFF bytes
$0578 Initialize track capacity
$05D0 Set up sectors for current track. Write HEADER block
to disk
$05ED Write checksum
$0601 Write sector number
$060F Write track, ID2, ID1
$061E Write nine (9) #$00 bytes (GAP 1)
$062E Write DATA block to disk
$0647 Write two hundred and fifty six (256) #$00 bytes to disk
$0656 Write checksum to disk, write GAP 2 to disk
$0666 Test if last sector of track
$0670 Verify SYNC and header identifier '08'
$0682 Disk error
$0690 Verify track, all sectors
$06B2 Verify DATA block
$06E0 Calculate interleave between first and last sector number
$06F8 Check if last track of disk done
$070D Send two OFF bytes, set for normal read mode
$0727 Set Periphal Control Register
$072E Send a byte to the disk
$0737 Read a byte from the disk
$073E Test if SYNC properly written
$0743 Test if SYNC properly written
$074F Test for SYNC 65536 times
$0765 Calculate checksum for current track, sector
$0780 Write #$00 to disk 8192 times
$079A Format code work values
4040 Format code
0500 A5 1A LDA $1A ;is format already in progress ?
0502 10 2F BPL $0533 ;yes,
****************************** Bump head to track one, initialize
buffer pointers to point to buffer
#0: $0421
0504 78 SEI ;set the interrupt
0505 A9 C1 LDA #$C1 ;set for: 1100 0001
0507 95 03 STA $03,X ;set drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
0509 A9 0F LDA #$0F ;set for: 0000 1111
050B 3D 9A 07 AND $079A,X ;AND with #$0C if drv 0, #$03 if drv 1
050E 05 40 ORA $40 ;determine drive motor to activate
0510 85 40 STA $40 ;set PORT B status
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
0512 A9 8C LDA #$8C ;set for: -70 (2*35 tracks outwards)
0514 95 05 STA $05,X ;set number of steps to new track
0516 58 CLI ;clear the interrupt
0517 B5 05 LDA $05,X ;has motor reached track #$00 ?
0519 D0 FC BNE $0517 ;no,
051B 98 TYA
051C 0A ASL ;multiply job number by two
051D 0A ASL ;multiply new result by two
051E 0A ASL ;multiply new result by two
051F 18 CLC
0520 69 21 ADC #$21 ;add in pointer (buffer #0)
0522 85 18 STA $18 ;set LO pointer into HDRS table: $0421
0524 A0 00 LDY #$00
0526 84 1D STY $1D ;set error count to 0: 00, OK, 00, 00
0528 C8 INY
0529 84 1A STY $1A ;set for track #$01
****************************** Initialize track number and move head
to desired track number
052B 20 65 07 JSR $0765 ;calculate track, sector, checksum
052E A4 1F LDY $1F ;get current job number
0530 6C 00 FC JMP ($FC00) ;indirect jump to $FC54: test motor status,
turn on if not and set time for acceleration
0533 A0 02 LDY #$02 ;set for extraction of track number: $0423
0535 51 18 EOR ($18),Y ;on right track ?
0537 D0 F2 BNE $052B ;no,
0539 A9 00 LDA #$00
053B 85 1D STA $1D ;set error count to 0: 00, OK, 00, 00
****************************** Format current track
053D 78 SEI ;set the interrupt
053E 20 65 07 JSR $0765 ;calculate track, sector, checksum
0541 A9 08 LDA #$08 ;set for test of bit 3 (WPSW)
0543 25 82 AND $82 ;is PORT B write protect switch on ?
0545 F0 03 BEQ $054A ;no,
0547 4C 84 06 JMP $0684 ;yes,
***************************** Erase track with SYNC
054A 20 80 07 JSR $0780 ;write #$00 to disk 8192 times
054D A2 FF LDX #$FF ;bit mask: 1111 1111
054F A9 DA LDA #$DA ;set PCR for write (D) & 1010 (A): (1101 1010)
0551 20 2E 07 JSR $072E ;write #$FF to disk
0554 85 4C STA $4C ;set periphal control register: (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
0556 20 2E 07 JSR $072E ;write #$FF to disk
0559 20 2E 07 JSR $072E ;write #$FF to disk
055C A9 DC LDA #$DC ;set PCR for write (D) & normal (C): (1101 1100)
055E 20 2E 07 JSR $072E ;write #$FF to disk
****************************** Write OFF bytes and verify SYNC & OFF bytes
0561 A2 0F LDX #$0F ;bit mask: 0000 1111
0563 20 2E 07 JSR $072E ;write #$0F to disk (OFF byte)
0566 85 4C STA $4C ;periphal control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
0568 20 0D 07 JSR $070D ;send two OFF bytes, set for normal read mode
056B 20 3E 07 JSR $073E ;test if SYNC has been properly written
056E 20 37 07 JSR $0737 ;read a byte from the disk
0571 C9 0F CMP #$0F ;has byte #$0F been properly written ?
0573 F0 03 BEQ $0578 ;yes,
0575 4C 82 06 JMP $0682 ;error detected: OFF byte not written
****************************** Initialize track capacity
0578 A9 11 LDA #$11 ;set for #$11 (decimal 17)
057A 18 CLC
057B 6D 9D 04 ADC $049D ;add #$11 to GAP1 (pre-set to: #$09)
057E 85 0A STA $0A ;store result in number of spaces for format
0580 A6 15 LDX $15 ;read maximum sectors for current track
0582 A0 00 LDY #$00
0584 A9 00 LDA #$00
0586 18 CLC
0587 65 0A ADC $0A ;calculate sector excess, 256 bytes needed ?
0589 90 01 BCC $058C ;yes,
058B C8 INY ;increment index by 256 bytes
058C C8 INY ;increment index by 256 bytes
058D CA DEX ;all sectors calculated ?
058E D0 F6 BNE $0586 ;no,
0590 49 FF EOR #$FF ;turn number into a negative value
0592 38 SEC
0593 69 00 ADC #$00 ;set up subsraction from total track capacity
0595 18 CLC
0596 6D A0 07 ADC $07A0 ;need to borrow during substraction ?
0599 B0 03 BCS $059E ;no,
059B CE 9F 07 DEC $079F ;correct HI byte
059E AA TAX
059F 98 TYA
05A0 49 FF EOR #$FF ;turn number into a negative value
05A2 38 SEC
05A3 69 00 ADC #$00 ;set calculation from remaining bytes
05A5 18 CLC
05A6 6D 9F 07 ADC $079F ;sufficient track capacity ?
05A9 10 03 BPL $05AE ;yes,
05AB 4C 82 06 JMP $0682 ;error detected: track capacity too small
05AE A8 TAY
05AF 8A TXA ;get number of remaining bytes
05B0 A2 00 LDX #$00
05B2 38 SEC
05B3 E5 15 SBC $15 ;can number of sectors still be substracted ?
05B5 B0 03 BCS $05BA ;yes,
05B7 88 DEY ;decrement index, result negative ?
05B8 30 03 BMI $05BD ;yes,
05BA E8 INX ;increment number of remaining bytes, zero ?
05BB D0 F5 BNE $05B2 ;no,
05BD 86 0A STX $0A ;store GAP2 size
05BF EC 9E 04 CPX $049E ;is calculate size smaller than GAP2 size
set by dos ?
05C2 B0 03 BCS $05C7 ;no,
05C4 4C 06 82 JMP $0682 ;error detected: not enough spaces for GAP2
05C7 18 CLC
05C8 65 15 ADC $15 ;add number of sector to track to remainder
05CA 8D 9E 07 STA $079E ;store total
05CD 20 80 07 JSR $0780 ;write #$00 to track 8192 times
***************************** Set up sectors for current track. Write
HEADER block to disk
05D0 A9 DE LDA #$DE ;set PCR for write (D) & fill/sync (E)
(1101 1110)
05D2 A2 FF LDX #$FF ;bit mask: 1111 1111
05D4 20 2E 07 JSR $072E ;write #$FF to disk
05D7 85 4C STA $4C ;periphal control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
05D9 20 2E 07 JSR $072E ;write #$FF to disk
05DC 20 2E 07 JSR $072E ;write #$FF to disk
05DF A9 DC LDA #$DC ;set PCR for write (D) & normal (C):
(1101 1100)
05E1 20 2E 07 JSR $072E ;write #$FF to disk
05E4 A2 08 LDX #$08 ;header block identifier: '08'
05E6 20 2E 07 JSR $072E ;send header identifier to PORT A:
05E9 85 4C STA $4C ;set periphal control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
05EB A2 FF LDX #$FF ;bit mask: 1111 1111
****************************** Write checksum
05ED AD 9D 07 LDA $079D ;read checksum for current track, sector
05F0 24 4D BIT $4D ;new interrupt ?
05F2 10 FC BPL $05F0 ;no,
05F4 85 80 STA $80 ;write checksum to disk
05F6 24 41 BIT $41 ;clear PORT A: data input
05F8 4D 9C 07 EOR $079C ;check if checksum correspond to track, sector
05FB AC 9C 07 LDY $079C ;load .Y register with current sector number
05FE EE 9C 07 INC $079C ;increment current sector counter
****************************** Write sector number
0601 24 4D BIT $4D ;new interrupt ?
0603 10 FC BPL $0601 ;no,
0605 84 80 STY $80 ;write sector number to disk
0607 24 41 BIT $41 ;clear PORT A: data input
0609 4D 9C 07 EOR $079C ;calculate checksum for new sector
060C 8D 9D 07 STA $079D ;store new checksum
****************************** Write track, ID2, ID1
060F A0 02 LDY #$02 ;set pointer for extraction of HEADER BYTES:
$0423
0611 B1 18 LDA ($18),Y ;read header byte
0613 24 4D BIT $4D ;new interrupt ?
0615 10 FC BPL $0613 ;no,
0617 85 80 STA $80 ;write header bytes
0619 24 41 BIT $41 ;clear PORT A: data input
061B 88 DEY ;all header bytes written ?
061C 10 F3 BPL $0611 ;no,
****************************** Write 9 #$00 bytes (GAP1)
061E A9 00 LDA #$00
0620 AC 9D 04 LDY $049D ;GAP1 size set by dos
0623 24 4D BIT $4D ;new interrupt
0625 10 FC BPL $0623 ;no,
0627 85 80 STA $80 ;write GAP1 to disk
0629 24 41 BIT $41 ;clear PORT A: data input
062B 88 DEY ;all GAP1 bytes written ?
062C D0 F5 BNE $0623 ;no,
****************************** Write DATA block to disk
062E A9 DE LDA #$DE ;set PCR for write (D) & fill/sync (E)
(1101 1110)
0630 20 2E 07 JSR $072E ;write #$FF to disk
0633 85 4C STA $4C ;set periphal control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
0635 20 2E 07 JSR $072E ;write #$FF to disk
0638 20 2E 07 JSR $072E ;write #$FF to disk
063B A9 DC LDA #$DC ;set PCR for write (D) & normal (C): (1101 1100)
063D 20 2E 07 JSR $072E ;write #$FF to disk
0640 A2 2E 07 LDX #$07 ;data block identifier: '07'
0642 20 2E 07 JSR $072E ;send data identifier to PORT A:
0645 85 4C STA $4C ;set periphal control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
****************************** Write 256, #$00 bytes to disk
0647 A0 00 LDY #$00 ;counter for writing data block
0649 A2 00 LDX #$00 ;value of data block
064B 24 4D BIT $4D ;new interrupt ?
064D 10 FC BPL $064B ;no,
064F 86 80 STX $80 ;write #$00 to disk
0651 24 41 BIT $41 ;clear PORT A: data input
0653 88 DEY ;has the data block been totally written ?
0654 D0 F5 BNE $064B ;no,
****************************** Write checksum to disk, write GAP2 to disk
0656 A4 0A LDY $0A ;get number of spaces for format
0658 20 2E 07 JSR $072E ;write checksum to disk (#$00)
065B 24 4D BIT $4D ;new interrupt ?
065D 10 FC BPL $065B ;no,
065F 86 80 STX $80 ;send byte to PORT A: data out
0661 24 41 BIT $41 ;clear PORT A: data input
0663 88 DEY ;has designated number of spaces for GAP2
been written
0664 10 F5 BPL $065B ;no,
****************************** Test if last sector of track
0666 AD 9C 07 LDA $079C ;get current sector
0669 C5 15 CMP $15 ;is this the last sector ?
066B F0 03 BEQ $0670 ;yes,
066D 4C D0 05 JMP $05D0 ;no,
****************************** Verify SYNC and header identifier '08'
0670 20 0D 07 JSR $070D ;send two OFF bytes, set for normal read mode
0673 A9 00 LDA #$00
0675 8D 9C 07 STA $079C ;set sector counter to #$00
0678 20 3E 07 JSR $073E ;test if SYNC properly written
067B 20 37 07 JSR $0737 ;get '08' header identifier
067E C9 08 CMP #$08 ;is it there ?
0680 F0 0E BEQ $0690 ;yes,
****************************** Disk error
0682 A9 0C LDA #$0C ;set for #$0C (decimal 12)
0684 58 CLI ;clear the interrupt
0685 E6 1D INC $1D ;increment error counter
0687 A0 0A LDY #$0A ;set for 10 format attempts per track
0689 C4 1D CPY $1D ;attempts to format track expired ?
068B F0 79 BEQ $0706 ;yes, disk error: BAD DISK !
068D 4C 3D 05 JMP $053D ;no, try reformatting track
****************************** Verify track, all sectors
0690 20 37 07 JSR $0737 ;get checksum
0693 8D 9D 07 STA $079D ;store it
0696 20 37 07 JSR $0737 ;get sector number
0699 CD 9C 07 CMP $079C ;is this the right sector
069C D0 E4 BNE $0682 ;error detected: overlapped sectors
069E 4D 9D 07 EOR $079D ;calculate header checksum: sector, track,
ID1, ID2
06A1 A0 02 LDY #$02
06A3 24 4D BIT $4D ;new interrupt ?
06A5 10 FC BPL $06A3 ;no,
06A7 45 41 EOR $41 ;calculate checksum
06A9 88 DEY ;has sector, track, ID1, ID2 been read ?
06AA 10 F7 BPL $06A3 ;no,
06AC A8 TAY ;is accumulator (checksum) correct ?
06AD D0 D3 BNE $0682 ;no, error detected: "CHECKSUM ERROR IN HEADER
BLOCK"
06AF EE 9C 07 INC $079C ;increment sector counter
****************************** Verify DATA block
06B2 20 3E 07 JSR $073E ;test if SYNC properly written
06B5 20 37 07 JSR $0737 ;get '07' data identifier
06B8 C9 07 CMP #$07 ;is it there ?
06BA D0 C6 BNE $0682 ;no, disk error: BAD DISK !
06BC A0 00 LDY #$00 ;set data counter
06BE 24 4D BIT $4D ;new interrupt ?
06C0 10 FC BPL $06BE ;no,
06C2 A5 41 LDA $41 ;get data byte
06C4 D0 BC BNE $0682 ;not equal to #$00 ? error detected:DATA FAULT
06C6 88 DEY ;has all 256 bytes been tested ?
06C7 D0 F5 BNE $06BE ;no,
06C9 20 37 07 JSR $0737 ;get checksum
06CC D0 B4 BNE $0682 ;not #$00 ? error detected: "CHECKSUM ERROR IN
DATA BLOCK"
06CE AD 9C 07 LDA $079C ;get current sector
06D1 C5 15 CMP $15 ;have all sectors been verified ?
06D3 D0 A3 BNE $0678 ;no,
06D5 20 3E 07 JSR $073E ;test if SYNC properly written
06D8 AD 9F 07 LDA $079F ;number of spaces for GAP2 correct ?
06DB F0 03 BEQ $06E0 ;yes,
06DD 4C 82 06 JMP $0682 ;error detected: BAD SPACING (GAP2)
****************************** Calculate interleave between first and last
sector
06E0 AD 9E 07 LDA $079E ;read remainder of track size
06E3 38 SEC
06E4 65 0A ADC $0A ;add in number of spaces for format
06E6 38 SEC
06E7 ED A0 07 SBC $07A0 ;substract SYNC encounter value
06EA 10 05 BPL $06F1 ;positive result ? yes,
06EC 49 FF EOR #$FF ;turn negative result ot positive value
06EE 38 SEC
06EF 69 00 ADC #$00 ;add in #$00
06F1 C9 1C CMP #$1C ;interleave between first and last sector
greater than #$1C (decimal 28) ?
06F3 90 03 BCC $06F8 ;yes,
06F5 4C 82 06 JMP $0682 ;error detected: interleave space too small
****************************** Check if last track of disk done
06F8 E6 1A INC $1A ;increment track number
06FA 58 CLI ;clear the interrupt
06FB A9 24 LDA #$24 ;set accumulator to maximum tracks per disk
06FD C5 1A CMP $1A ;is track counter equal to #$24 (decimal 36) ?
06FF F0 03 BEQ $0704 ;yes,
0701 4C 2B 05 JMP $052B ;no,
0704 A9 01 LDA #$01 ;set for error: 00, OK, 00, 00 (done!)
0706 A0 FF LDY #$FF
0708 84 1A STY $1A ;store #$FF in format count (no active job)
070A 6C 02 FC JMP ($FC02) ;format finished jump to $FF08
***************************** Send two OFF bytes, set for normal read mode
070D 20 2E 07 JSR $072E ;send byte in x register to PORT A:
0710 24 4D BIT $4D ;new interrupt ?
0712 10 FC BPL $0710 ;no,
0714 A9 FC LDA #$FC ;set PCR for read (F) & normal (C)
0716 85 4C STA $4C ;set periphal control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
0718 A9 92 LDA #$92 ;set for: 1001 0010
071A 85 4E STA $4E ;set interrupt enable register
071C A2 03 LDX #$03 ;set for read of 3 bytes from disk
071E 20 37 07 JSR $0737 ;read byte from disk
0721 24 40 BIT $40 ;clear PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
0723 CA DEX ;all bytes read ?
0724 D0 F8 BNE $071E ;no,
0726 60 RTS
****************************** Set PCR for write mode
0727 A0 10 LDY #$10 ;bit mask: 0001 0000
0729 84 4E STY $4E ;set enable CB1 interrupt
072B 85 4C STA $4C ;set periphal control register
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detected 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
072D 60 RTS
****************************** Send a byte to the disk
072E 24 4D BIT $4D ;new interrupt ?
0730 10 FC BPL $072E ;no,
0732 86 80 STX $80 ;send byte to PORT A: data out
0734 24 41 BIT $41 ;clear PORT A: data input
0736 60 RTS
****************************** Read a byte from the disk
0737 24 4D BIT $4D ;new interrupt ?
0739 10 FC BPL $0737 ;no,
073B A5 41 LDA $41 ;read byte from disk PORT A: data input
073D 60 RTS
****************************** Test if SYNC properly written
073E A0 00 LDY #$00
0740 8C 9F 07 STY $079F ;set byte counter
****************************** Test if SYNC properly written
0743 24 82 BIT $82 ;PORT B status reveals SYNC detected ?
bit 0 switch 0 = drive #0
1 = drive #1
1-2 frequency (bit density)
3 write protect 1 = yes
6 sync detect 1 = no, 0 = yes
0745 50 16 BVC $075D ;yes,
0747 24 4D BIT $4D ;TIMER still counting ?
0749 10 F8 BPL $0743 ;yes,
074B 24 41 BIT $41 ;clear PORT`A: data input
074D 24 40 BIT $40 ;clear PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
****************************** Test for SYNC 65536 times
074F C8 INY ;test 256 times
0750 D0 F1 BNE $0743 ;try again ? yes,
0752 EE 9F 07 INC $079F ;test 256 times
0755 D0 03 BNE $075A ;try again ? yes,
0757 4C 82 06 JMP $0682 ;error detected: "BYTE DECODING ERROR", no SYNC
075A 4C 43 07 JMP $0743 ;keep testing for SYNC
075D 8C A0 07 STY $07A0 ;store amount of times needed to find SYNC
0760 24 40 BIT $40 ;clear PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
0762 24 41 BIT $41 ;clear PORT`A: data input
0764 60 RTS
****************************** Calculate checksum for current track, sector
0765 A0 02 LDY #$02 ;set pointer to extract track number
0767 A5 1A LDA $1A ;read current track being done
0769 91 18 STA ($18),Y ;store track number in table: $0423
076B A9 00 LDA #$00 ;set for sector #$00
076D 8D 9C 07 STA $079C ;store sector number
0770 C8 INY ;move up pointer
0771 91 18 STA ($18),Y ;store sector number in table: $0424
0773 51 18 EOR ($18),Y ;calculate checksum for current header block
0775 88 DEY ;all header bytes calculated ?
0776 10 FB BPL $0773 ;no,
0778 8D 9D 07 STA $079D ;read checksum counter
077B A0 04 LDY #$04 ;set pointer to checksum byte location in header
table
077D 91 18 STA ($18),Y ;store checksum value in table: $0425
077F 60 RTS
****************************** Write #$00, 8192 times to disk
0780 A2 00 LDX #$00
0782 A0 00 LDY #$00
0784 A9 20 LDA #$20 ;set byte counter to #$20 (decimal 32)
0786 8D 9F 07 STA $079F ;store in byte counter
0789 A9 DC LDA #$DC ;set PCR for write (D) & normal (C): 1101 1100
078B 20 27 07 JSR $0727 ;set IER & PCR for output
078E 20 2E 07 JSR $072E ;write #$00 to disk
0791 88 DEY ;has #$00 been written 256 times
0792 D0 FA BNE $078E ;no,
0794 CE 9F 07 DEC $079F ;#$00 written 8192 times ?
0797 D0 F5 BNE $078E ;no,
0799 60 RTS
****************************** Format code work values
079A 0C ??? ;AND byte for drive 0: 0000 1100
079B 03 ??? ;AND byte for drive 1: 0000 0011
079C 48 ??? ;current sector counter
079D 53 ??? ;temporary storage for checksum value
079E 50 ??? ;remainder of track size
079F AA ??? ;byte counter
07A0 25 ??? ;number of attempts before SYNC encountered
Chapter 9 - FDC disk controller (MOS 6504)
4040 Disk controller RAM usage
ZERO page ($0000 - $003F)
LOCATION LABEL DESCRIPTION
---------------------------------------------------------------------------
$0000 CLOCK Controllers clock
$0001 - $0002 MTRTM Motor timer: drive 0/drive 1
(+) when motor fully on
$0003 - $0004 DRVST Drive status words bits 0-5 track #
bit 6 stepping 0=no
1=yes
bit 7 accelerating 0=no
1=yes
$0005 - $0006 STEPS Number of steps to new track
$0007 COW Used with interrupt
$0008 SEEKDIS Closest seek distance
$0009 SEEKDIR Closest seek direction
$000A DTRCK Number of spaces for format
$000B DSECT Number of sectors until desired sector
$000C CSECT Closest sector from current position
$000D - $0011 STAB Sector header table: (id1,id2,trk,sct,chksm)
same format as in HDRS table
$0012 DRIVE Current drive #
$0013 TRACK Track number for closest seek
bits 0-1 part of id
bits 2-7 track number
$0014 NEXTS Next sector on drive
$0015 SECTR Number of sectors/track
$0016 - $0017 BUFPT Lo/hi pointer into BUFS table
$0018 - $0019 HDRPNT Lo/hi pointer into HDRS table, if $FF then no
job
$001A FTNUM Format count: $FF = no action
$001B - $001C IP (* indirect pointer *)
$001D CNT Error count
$001E JOB Current job being done
$001F JOBNUM Current job id
$0020 - $003F Stack for 6504
4040 Controller data read usage
MOS 6522 ($0040 - $004F)
LOCATION LABEL DESCRIPTION
---------------------------------------------------------------------------
$0040 VB Port b
bits 0-1 stepper motor drive #1
bits 2-3 stepper motor drive #1
bit 4 motor 1 off
bit 5 motor 0 off
bit 6-7 unused
$0041 DIN Port a: data input
$0042 VDDRB Data direction register b
$0043 Appears unused by FDC
$0044 TILL Timer 1 latch and counter low
$0045 TIMER Timer 1 counter high
$0046 - $004A Appears unused by FDC
$004B ACR Auxiliary control register
$004C PCR Peripheral control register
bit 0 set to 0
ca1: byte ready 1=yes, 0=no
bits 1-3 ca2 : fill/sync
normal : xC
sync/fill: xE
bit 4 set to 1
cb1: error detected 1=yes, 0=no
bits 5-7 cb2 : read/write
write : Dx
read : Fx
$004D IFR Int flag register
$004E IER Int enable register
4040 Controller data write usage
MOS 6530 ($0080 - $008F)
LOCATION LABEL DESCRIPTION
---------------------------------------------------------------------------
$0080 DOUT Port a: data out
$0081 EOUT Direction port a
$0082 PB Port b
bit 0 switch 0=drive #0
1=drive #1
bits 1-2 frequency (bit density)
bit 3 write protect 1=yes
bit 6 sync detect 1=no, 0=yes
$0083 DDRB Data direction register b
$0084 - $008E Appears unused by FDC
$008F MITAT Timer/1024
4040 Controller data storage/retrieve usage
COMMON RAM (6504: $0400 - $04FF)
(6502: $1000 - $10FF)
LOCATION LABEL DESCRIPTION
---------------------------------------------------------------------------
$0400 TICK Interrupt interval
$0401 DELAY Motor acceleration delay
$0402 CUTMT Motor cutoff time
$0403 - $0411 JOBS Job que
bit 7 0=ignore, 1=job present
bits 6-4 mode
000:read (8) (0):read data block
001:write (9) (1):write data block
010:verify (A) (2):verify data block written
011:seek (B) (3):seek specific track and
sector
100:bump (C) (4):restore placement of head
to trk: 1
101:jump (D) (5):jump to buffer code
110:execute(E) (6):start motor then jump
$0412 - $0420 Appears unused by FDC
$0421 - $0498 HDRS Headers of current blocks: 15*8
-3: sync 2 : track #(bits 7-6 part of id)
-2: sync 3 : sector #
-1: '08' 4 : checksum
0: id1 5 : off
1: id2 6,7: spare
$0499 - $049C TAB1 Number of sectors/track initialized by DOS
$049D GAP1 Gap 1 size set by DOS
$049E GAP2 Gap 2 size set by DOS: used in format for min.
number of bytes
$049F VERNUM DOS version number
$04A0 ACTJOB Active job number
Data on diskette preceded by: sync,sync,'07'
Checksum follows 256 data bytes, then 16
spacing bytes
$0500 - $13FF BUFS Set of 15: 1-block(256 word) buffers
4040 Disk controller MAP
Code from $FC00 - $FE7E
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$FC09 Word "JOHN", Initialize controller
$FC54 START: Test for a valid job
$FC65 Test for job type, turn current drive motor on if not
$FC80 Test motor speed
$FC8A Test head status
$FC8D Test next JOBs queue
$FC92 Test if head needs transporting
$FC99 Initialize JOBS and JOBID by .Y register offset
$FCAF Test if head is on right track
$FCBC Find closest seek
$FCCF Decrement .Y register loop for all jobs
$FCD2 Set up seek for closest track
$FCEF BYTE used to test motor status: #$F3, #$FC
$FCF1 TRACK zone bytes: #$1F, #$19, #$12, #$11
$FCF4 Check if motor to speed, if not, branch to $FCED
$FCF8 Set up for track zone
$FCFC Check for track zone
$FD02 Set number of sectors/track from result of $FCFC
$FD20 JOB ROUTINE: execute (mode E:110)
$FD2A JOB ROUTINE: bump (mode C:100)
$FD3F Decide which sector to service
$FD52 Check which job type, check track, drive
$FD98 Adjust header pointer: job*8+hi byte of HDRS into HDRPT
$FDA5 Calculate job type for selected queue
$FDBB Fix sector number for fake seek
$FDC4 JOB ROUTINE: read (mode 8:000)
$FDCB Get the bytes, store in BUFPT,Y, initialize checksum
$FDDD Start reading data: initialize checksum, search for header
and start of data
$FDF0 JOB ROUTINE: write (mode 9:001)
$FDFD Disable CB1 flag, get correct block
$FE08 Write sync mode, load fill code
$FE17 Reset port A, set 1st sync
$FE22 Store normal code in PCR, set 2nd sync, checksum
$FE32 Write block, write checksum, change job to verify
$FE57 JOB ROUTINE: verify (mode A:010)
$FE5A Get byte and compare with contents of buffer, add up
checksum
$FE6B End reading data, final checksum compare
$FE76 Check if "DECODING ERROR"
$FE7E Verify error
$FE82 Seek to determine next sector number, initialize
checksum, get block header
$FE8D Get a byte, store in STAB, update checksum
$FEA7 Load job number and type, test if seek
$FEAF Check if ID in HDRPT,Y = STAB,Y
Code from $FE82 - $FFFF
LOCATION DESCRIPTION
---------------------------------------------------------------------------
$FEBC JOB ROUTINE: seek (mode B:011)
$FEBE Get complete header from STAB,Y into (HDRPT),Y
$FEC6 Set for error #$01 (00, OK,00,00)
$FEC8 Jump to error handling routine
$FECB Checksum error
$FECF Mismatch error
$FED3 Search for a specific block
$FED7 Compute checksum, set up search for a sector
$FEE4 JSR: head set .Y for compare (all bytes in HDR must be
identical)
$FEE9 Compare to header loop, loop entire header
$FF02 Search for block head: .X = maximum number of trials
$FF08 Send job status, make motor stay on longer and check for
job type
$FF1E Purge stack (#$3F)
$FF24 Get a byte, compare to start of header
$FF2C Watch for sync character
$FF3E Hunt for sync characters: set timer for 20ms limit
$FF51 Get a byte
$FF58 Send two bytes, set normal read mode
$FF62 Change EOUT and PCR to send sync
$FF79 Byte to be sent is in .X
$FF82 Interrupt for a few milliseconds, set next interrupt,
reset timer
$FF8E Service motor: check if motor on and stepping flag set
$FFA8 Service stepper motor
$FFAA Check if on track, if on track: clear stepping tag,
check next stepper
$FFB7 Check direction, step in or step out
$FFC6 Step in (+)
$FFCD Step out (-)
$FFD5 Store new stepper position, test if DRVST ready
$FFE4 Pop the stack of .A and .X then RTI
$FFE8 Cycle increment for drives: #$04, #$01
Status word for drives : #$20, #$10
AND bytes for drives : #$0C, #$03
$FFFC .word john: $FC09:initialize
$FFFE .word irqh: $FF82:interrupt
4040 Disk controller ROM map
****************************** Main job entry points
FC00 54 FC ??? ;start of idle loop
FC02 08 FF ??? ;job status entry point
****************************** Begin at new interrupt count
FC04 AD 00 04 LDA $0400 ;new interrupt ?
FC07 D0 FB BNE $FC04 ;no,
****************************** Word "JOHN", Initialize controller
FC09 A2 3F LDX #$3F ;set .X for: 0011 1111
FC0B 9A TXS ;store #$3F in the stack pointer
FC0C D8 CLD ;clear decimal mode
FC0D 8E 00 04 STX $0400 ;set interrupt interval to: #$3F (dec. 63)
FC10 A9 00 LDA #$00
FC12 95 00 STA $00,X ;store #$00 at end of stack
FC14 D5 00 CMP $00,X ;is end of stack equal to stored value ?
FC16 D0 FE BNE $FC16 ;no,
FC18 9D 03 04 STA $0403,X ;store #$00 in HDRS table
FC1B CA DEX ;all JOBS & HDRS tables cleared ?
FC1C 10 F4 BPL $FC12 ;no,
FC1E 86 40 STX $40 ;set PORT B to #$FF: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FC20 86 42 STX $42 ;set data direction register to: #$FF
FC22 8E 02 04 STX $0402 ;set motor cutoff time to: #$FF
FC25 86 81 STX $81 ;set direction PORT`A to: #$FF
FC27 86 1A STX $1A ;set format count to: #$FF (no action)
FC29 A9 07 LDA #$07 ;bit mask: 0000 0111
FC2B 85 83 STA $83 ;set data direction register b to: #$07
FC2D A9 FC LDA #$FC ;set PCR to read (F) & normal (C)
FC2F 85 4C STA $4C ;peripheral control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bits 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detect 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
FC31 A9 92 LDA #$92 ;set .ACC for: 0101 1100
FC33 85 4E STA $4E ;set interrupt enable register
FC35 A9 01 LDA #$01 ;set .ACC for: 0000 0001
FC37 85 4B STA $4B ;set auxiliary control register to: #$00
FC39 4A LSR
FC3A 85 44 STA $44 ;set TIMER latch 1 and COUNTER low bytes to: #$00
FC3C 85 16 STA $16 ;set HI buffer pointer to: #$00
FC3E A9 0F LDA #$0F
FC40 8D 00 04 STA $0400 ;set INTERRUPT interval to: #$0F (dec. 15)
FC43 85 8F STA $8F ;set TIMER to: #$0F (TIMER/1024) = 15.36 ms
FC45 A9 80 LDA #$80 ;set .ACC for: 0101 0000
FC47 85 03 STA $03 ;set drive 0 status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FC49 85 04 STA $04 ;set drive 1 status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FC4B A9 32 LDA #$32
FC4D 8D 04 04 STA $0401 ;set motor acceleration delay to: #$32 (dec. 50)
FC50 A9 04 LDA #$04
FC52 85 19 STA $19 ;set HI header pointer to: #$04
****************************** START: Test for a valid job
.Y = job queue number
.ACC = job
FC54 A0 0E LDY #$0E ;set for #$0E jobs scan (dec. 14)
FC56 58 CLI ;clear interrupt
FC57 B9 03 04 LDA $0403,Y ;does this queue have a job to do ?
FC5A 10 31 BPL $FC8D ;no,
FC5C C9 D0 CMP #$D0 ;is the job equal to #$D0 (execute ml user
code from data buffer)
FC5E D0 05 BNE $FC65 ;no,
FC60 84 1F STY $1F ;store which job queue is being processed
FC62 4C 20 FD JMP $FD20 ;jump to EXECUTE routine
****************************** Turn current drive motor on if needed
FC65 29 01 AND #$01 ;test which drive
FC67 AA TAX ;set .X register to indicate selected drive
FC68 85 12 STA $12 ;set the current drive number
FC6A 78 SEI ;set interrupt
FC6B A5 40 LDA $40 ;read PORT B: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FC6D 3D EA FF AND $FFEA,X ;is motor for selected drive off ?
FC70 F0 0E BEQ $FC80 ;no,
FC72 A5 40 LDA $40 ;read PORT B: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FC74 5D EA FF EOR $FFEA,X ;turn on selected drive motor
FC77 85 40 STA $40 ;store PORT B: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FC79 A5 00 LDA #$00
FC7B 6F 01 04 ADC $0401 ;motor acceleration delay: #$32 (dec. 50)
FC7E 95 01 STA $01,X ;set motor TIMER of selected drive to:#$32
****************************** Test motor speed
FC80 B5 03 LDA $03,X ;get drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FC82 30 06 BMI $FC8A ;motor not up to proper speed ?
FC84 A5 00 LDA #$00
FC86 95 01 STA $01,X ;set motor TIMER to #$00: turn off motor
FC88 B5 03 LDA $03,X ;get drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
****************************** Test head status
FC8A 0A ASL ;head currently stepping ?
FC8B 10 05 BPL $FC92 ;no,
****************************** Test next JOBs queue
FC8D 88 DEY ;is this the last job queue to test ?
FC8E 10 C6 BPL $FC56 ;no,
FC90 D0 C2 BNE $FC54 ;no jobs, start over
****************************** Test if head needs transporting
FC92 58 CLI ;clear the interrupt
FC93 A9 40 LDA #$40 ;initialize to maximum distance+1 (dec. 64)
FC95 85 08 STA $08 ;set closest seek distance
FC97 A0 0E LDY #$0E ;set for maximum number of jobs
****************************** Initialize JOBS and JOBID by .Y register
offset
.Y = maximum job number
FC99 84 1F STY $1F ;current job number
FC9B 20 A5 FD JSR $FDA5 ;is there a job in selected queue ?
FC9E 10 2F BPL $FCCF ;no,
FCA0 29 01 AND #$01 ;test selected drive bit
FCA2 C5 12 CMP $12 ;is this the right drive ?
FCA4 D0 29 BNE $FCCF ;no,
FCA6 A5 1E LDA $1E ;get current job being done
FCA8 C9 40 CMP #$40 ;is job type #$40 (BUMP THE HUB) ?
FCAA D0 03 BNE $FCAF ;no,
FCAC 4C 2A FD JMP $FD2A ;jump to BUMP routine
****************************** Test if head on right track
FCAF B5 03 LDA $03,X ;read drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FCB1 29 3F AND #$3F ;isolate track number
FCB3 85 13 STA $13 ;store track number for closest seek
bits 0-1 = part of ID
2-7 = track number
FCB5 F0 3D BEQ $FCF4 ;track equal to #$00 ? yes,
FCB7 38 SEC
FCB8 F1 18 SBC ($18),Y ;has track been reached ?
FCBA F0 38 BEQ $FCF4 ;yes,
****************************** Find closest seek
FCBC 85 0A STA $0A ;store result from track calculation
FCBE 10 05 BPL $FCC5 ;stepping out required ? yes,
FCC0 18 CLC
FCC1 49 FF EOR #$FF ;calculate distance to track for: IN step
FCC3 69 01 ADC #$01 ;add one to result
FCC5 C5 08 CMP $08 ;all queues tested for possible use of current
track ?
FCC7 B0 06 BCS $FCCF ;no,
FCC9 85 08 STA $08 ;set closest seek distance
FCCB A5 0A LDA $0A ;number of spaces for format
FCCD 85 09 STA $09 ;closest seek direction
****************************** Decrement .Y register loop for all jobs
FCCF C6 1F DEC $1F ;has job been performed ?
FCD1 10 C8 BPL $FC9B ;no,
****************************** Set up seek for closest track
FCD2 A5 08 LDA $08 ;get seek distance
FCD5 24 09 BIT $09 ;seek direction inwards ?
FCD7 30 05 BMI $FCDE ;yes,
FCD9 18 CLC
FCDA 49 FF EOR #$FF ;calculate distance to track
FCDC 69 01 ADC #$01 ;add one to result
FCDE 85 08 STA $08 ;store new seek distance
FCE0 0A ASL
FCE1 78 SEI ;set the interrupt
FCE2 95 05 STA $05,X ;store number of steps to new track
FCE4 A9 40 LDA #$40 ;set for: 0100 0000
FCE6 15 03 ORA $03,X ;add in drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FCE8 18 CLC
FCE9 65 08 ADC $08 ;add in desired track
FCEB 95 03 STA $03,X ;store drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FCED D0 A1 BNE $FC90 ;another job to do ? yes,
****************************** BYTE used to test motor status
FCEF F3 ??? ;motor status drive 0
FCF0 FC ??? ;motor status drive 1
****************************** TRACK zone bytes
FCF1 1F ??? ;track zone: 31-35
FCF2 19 ??? ;track zone: 25-30
FCF3 12 ??? ;track zone: 18-24
****************************** Check if motor to speed, if not, branch to
$FCED
FCF4 B5 03 LDA $03,X ;get drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FCF6 30 F5 BMI $FCED ;motor up to speed ? no,
****************************** Set up for track zone
FCF8 A2 04 LDX #$04 ;set for minimum track zone
FCFA B1 18 LDA ($18),Y ;read track number from HDRS table
****************************** Check for track zone
FCFC DD EF FC CMP $FCEF,X ;is track part of this track zone ?
FCFF CA DEX ;all track zones tested ?
FD00 B0 FA BCS $FCFC ;no,
****************************** Set number of sectors per track and density
from result of $FCFC
FD02 BD 99 04 LDA $0499,X ;read sectors per track table
FD05 85 15 STA $15 ;set as number of sectors per track
FD07 8A TXA
FD08 0A ASL ;multiply byt two
FD09 85 08 STA $08 ;set as closest seek distance
FD0B A5 82 LDA $82 ;read PORT B status:
bit 0 switch 0 = drive #0
1 = drive #1
1-2 frequency (bit density)
3 write protect 1 = no
6 sync detect 1 = no, 0 = yes
FD0D 29 F8 AND #$F8 ;bit mask: 1111 1000
FD0F 05 08 ORA $08 ;calculate track density for zone
FD11 05 08 ORA $12 ;add in drive number
FD13 85 82 STA $82 ;set PORT`B status:
bit 0 switch 0 = drive #0
1 = drive #1
1-2 frequency (bit density)
3 write protect 1 = no
6 sync detect 1 = no, 0 = yes
FD15 A6 12 LDX $12 ;get current drive number
FD17 A5 1E LDA $1E ;get current job being done
FD19 C9 60 CMP #$60 ;is job type #$60 (EXECUTE ML CODE WITH MOTOR
ON) ?
FD1B F0 03 BEQ $FD20 ;yes,
FD1D 4C 82 FE JMP $FE82 ;no,
****************************** JOB ROUTINE: mode=110 (E)=execute
(6)=start motor then
jump
FD20 A5 1F LDA $1F ;get current job number
FD22 18 CLC
FD23 69 05 ADC #$05 ;add in buffer index
FD25 85 17 STA $17 ;set HI pointer to USER assigned ML CODE area
FD27 6C 16 00 JMP ($0016) ;jump to user assigned buffer code
****************************** JOB ROUTINE: mode=100 (C)=bump
(4)=restore placement
of head to track
#$01
FD2A 78 SEI ;set the interrupt
FD2B A9 C1 LDA #$C1 ;bit mask: 1100 0001
FD2D 95 03 STA $03,X ;set drive status: bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FD2F A9 0F LDA #$0F
FD31 3D EC FF AND $FFEC,X ;AND with #$0C if drv 0, #$03 if drv 1
FD34 05 40 ORA $40 ;add in PORT B status
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FD36 85 40 STA $40 ;store new PORT B status
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FD38 A9 8C LDA #$8C ;amount to step motor: -70 (2*35 tracks outward)
FD3A 95 05 STA $05,X ;set number of steps to new track
FD3C 4C C6 FE JMP $FEC6 ;jump to job completed routine
****************************** Decide which sector to service
FD3F A9 7F LDA #$7F
FD41 85 0C STA $0C ;set current sector number to #$7F (decimal 127)
FD43 A5 10 LDA $10 ;read sector number from header table
FD45 18 CLC
FD46 69 02 ADC #$02 ;add two to current sector count
FD48 C5 15 CMP $15 ;number of sectors greater than amount allowed
for this track ?
FD4A 90 02 BCC $FD4E ;no,
FD4C A9 00 LDA #$00
FD4E 85 14 STA $14 ;store desired sector number
FD50 A2 0E LDX #$0E ;set .X for scanning all job queues
****************************** Check which job type, check track, drive
FD52 86 1F STX $1F ;set for last job queue
FD54 A2 FF LDX #$FF
FD56 20 A5 FD JSR $FDA5 ;is there a job to do ?
FD59 10 33 BPL $FD8E ;no,
FD5B 85 08 STA $08 ;store job code in temporary location
FD5D B1 18 LDA ($18),Y ;is head on desired track ?
FD5F C5 13 CMP $13 ;correct track number ?
bit 0-1 = part of id
2-7 = track number
FD61 D0 2B BNE $FD8E ;no,
FD63 A5 08 LDA $08 ;load up job to perform
FD65 29 01 AND #$01 ;isolate drive number
FD67 C5 12 CMP $12 ;is this the correct drive ?
FD69 D0 23 BNE $FD8E ;no,
FD6B 98 TYA
FD6C C9 60 CMP #$60 ;is job type #$60 (EXECUTE ML CODE WITH MOTOR
ON) ?
FD6E F0 1E BEQ $FD8E ;yes,
FD70 C8 INY
FD71 38 SEC
FD72 B1 18 LDA ($18),Y ;get desired sector number
FD74 E5 14 SBC $14 ;result of sector substraction positive ?
FD76 10 03 BPL $FD7B ;yes, (sector is coming up)
FD78 18 CLC
FD79 65 15 ADC $15 ;add value of next sector back in
FD7B 85 0B STA $0B ;store result as number of sectors until desired
sector
FD7D 38 SEC
FD7E E5 0C SBC $0C ;distance to other sector request closer ?
FD80 10 0C BPL $FD8E ;yes,
FD82 A6 1F LDX $1F ;read current job number
FD84 A5 0B LDA $0B ;get amount of sectors before requested sector
FD86 85 0C STA $0C ;set as closest sector from current position
FD88 8A TXA
FD89 18 CLC
FD8A 69 05 ADC #$05 ;add in buffer index
FD8C 85 17 STA $17 ;set as HI pointer into BUFS table
FD8E C6 1F DEC $1F ;all jobs in queue finished ?
FD90 10 C4 BPL $FD56 ;yes,
FD92 8A TXA ;any jobs to do found ?
FD93 10 03 BPL $FD98 ;yes,
FD95 4C 54 FC JMP $FC54 ;jump to START
****************************** Adjust header pointer: job*8+hi byte of
HDRS into HDRPNT
FD98 8E A0 04 STX $04A0 ;store active job number
FD9B 86 1F STX $1F ;store as current job number
FD9D 20 A5 FD JSR $FDA5 ;calculate job type and index pointers
FDA0 A5 1E LDA $1E ;get current job being done
FDA2 4C C4 FD JMP $FDC4 ;jump to READ BLOCK routine
****************************** Calculate job type for selected queue and
set buffer pointers
.Y = byte position in buffer
.ACC = job number
FDA5 A4 1F LDY $1F ;get current job number
FDA7 B9 03 04 LDA $0403,Y ;read job queue status:
bit 7 job : 0=ignore, 1=job present
bits 6-4 mode:
000: read (8) (0): read data block
001: write (9) (1): write data block
010: verify (A) (2): verify data block
written
011: seek (B) (3): seek specific
track & sector
100: bump (C) (4): restore placement
of head: trk 1
101: jump (D) (5): jump to buffer
code
110: execute (E) (6): start motor then
jump
bit 0 drive: 0=#B, 1=#A
FDAA 48 PHA ;preserve job
FDAB 29 70 AND #$70 ;clear bits: 6, 5, 4
FDAD 85 1E STA $1E ;save calculated command code
FDAF 98 TYA
FDB0 0A ASL ;multiply job number by two
FDB1 0A ASL ;multiply new result by two
FDB2 0A ASL ;multiply new result by two
FDB3 69 21 ADC #$21 ;add in buffer index
FDB5 85 18 STA $18 ;set as LO pointer into HDRS table: #$FF=no job
FDB7 A0 02 LDY #$02 ;set pointer to byte position #$02
FDB9 68 PLA ;retrieve job number
FDBA 60 RTS
****************************** Fix sector number for fake seek
FDBB A0 03 LDY #$03 ;set pointer for extraction of sector number
FDBD B1 18 STA ($18),Y ;get sector number from HDRS table
FDBF 85 10 STA $10 ;store value in sector header table
FDC1 4C 3F FD JMP $FD3F ;jump to DECIDE SECTOR TO SERVICE routine
****************************** JOB ROUTINE: mode=000 (8)=read
(0)=read data block
FDC4 C9 00 CMP #$00 ;is job type #$00 (READ DATA BLOCK) ?
FDC6 D0 28 BNE $FDF0 ;no,
FDC8 20 DD FD JSR $FDDD ;jump to START READING DATA routine
****************************** Get the bytes, store in BUFPT,Y, initialize
checksum
FDCB 24 4D BIT $4D ;new interrupt ?
FDCD 10 FC BPL $FDCB ;no,
FDCF A5 41 LDA $41 ;read PORT A: data input
FDD1 91 16 STA ($16),Y ;store into assigned buffer
FDD3 45 08 EOR $08 ;calculate new checksum
FDD5 85 08 STA $08 ;store new checksum result
FDD7 C8 INY ;all bytes read ?
FDD8 D0 F1 BNE $FDCB ;no,
FDDA 4C 6B FE JMP $FE6B ;jump to END READING DATA routine
****************************** Start reading data: initialize checksum,
search for header and start of data
FDDD A0 00 LDY #$00
FDDF A0 00 STY $08 ;set checksum value to #$00
FDE1 20 D3 FE JSR $FED3 ;find desired sector
FDE4 20 3E FF JSR $FF3E ;get DATA BLOCK identifier: '07'
FDE7 C9 07 CMP #$07 ;is this the beginning of the DATA BLOCK ?
FDE9 F0 04 BEQ $FDEF ;yes,
FDEB A9 04 LDA #$04 ;set for "DATA BLOCK NOT PRESENT" error
FDED D0 0B BNE $FDFA ;abort job,
FDEF 60 RTS
****************************** JOB ROUTINE: mode=001 (9)=write
(1)=write data block
FDF0 C9 20 CMP #$20 ;is job type #$20 (VERIFY DATA BLOCK WRITTEN) ?
FDF2 10 63 BPL $FE57 ;yes,
FDF4 A5 82 LDA $82 ;read PORT B status:
bit 0 switch 0 = drive #0
1 = drive #1
1-2 frequency (bit density)
3 write protect 1 = yes
6 sync detect 1 = no, 0 = yes
FDF6 29 08 AND #$08 ;"WRITE PROTECT ON" error ?
FDF8 F0 03 BEQ $FDFD ;no,
FDFA 4C 08 FF JMP $FF08 ;abort job,
****************************** Disable CB1 flag, get correct block
FDFD A9 10 LDA #$10 ;set for: 0001 0000
FDFF 85 4E STA $4E ;set interrupt enable register
FE01 20 D3 FE JSR $FED3 ;skip SYNC and find proper HEADER BLOCK
FE04 AE 9D 04 LDX $049D ;read GAP1 size set by dos: #$09
FE07 CA DEX ;set GAP1 size to: #$08
****************************** Write SYNC mode, load fill code
FE08 24 4D BIT $4D ;new interrupt ?
FE0A 10 FC BPL $FE08 ;no,
FE0C 24 41 BIT $41 ;read GAP1 bytes
FE0E CA DEX ;last GAP1 byte ?
FE0F D0 F7 BNE $FE08 ;no,
FE11 A9 DE LDA #$DE ;set PCR to write (D) & fill/sync (E)
FE13 85 4C STA $4C ;peripheral control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bit 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detect 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
FE15 A9 DC LDA #$DC ;set PCR for write (D) & normal (C)
****************************** Reset PORT a, set 1st SYNC
FE17 A2 FF LDX #$FF
FE19 20 79 FF JSR $FF79 ;send byte
FE1C 20 79 FF JSR $FF79 ;send byte
FE1F 20 79 FF JSR $FF79 ;send byte
****************************** Store normal code mode in PCR, set 2nd
SYNC, checksum
FE22 24 4D BIT $4D ;new interrupt ?
FE24 10 FC BPL $FE22 ;no,
FE26 24 41 BIT $41 ;read PORT a: data input
FE28 85 4C STA $4C ;peripheral control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bit 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detect 1=yes, 0=no
bits 5-7
cb2:read/write
write : Dx
read : Fx
FE2A A9 07 LDA #$07 ;data block identifier: '07'
FE2C 85 80 STA $80 ;send to PORT a: data out
FE2E A0 00 LDY #$00
FE30 84 08 STY $08 ;set checksum value to: #$00
****************************** Write block, write checksum, change job to
verify
FE32 24 4D BIT $4D ;new interrupt ?
FE34 10 FC BPL $FE32 ;no,
FE36 24 41 BIT $41 ;reset PORT A: data input
FE38 B1 16 LDA ($16),Y ;load DATA byte to send to disk
FE3A 85 80 STA $80 ;write assigned byte to disk
FE3C 45 08 EOR $08 ;calculate new checksum
FE3E 85 08 STA $08 ;store new checksum total
FE40 C8 INY ;is this the 256th byte ?
FE41 D0 EF BNE $FE32 ;no,
FE43 AA TAX ;load up checksum
FE44 20 79 FF JSR $FF79 ;send byte
FE47 20 58 FF JSR $FF58 ;write two OFF bytes
FE4A A4 1F LDY $1F ;get current job number
FE4C B9 03 04 LDA $0403,Y ;get current job in queue:
bit 7 job : 0=ignore, 1=job present
bits 6-4 mode:
000: read (8) (0): read data block
001: write (9) (1): write data block
010: verify (A) (2): verify data block
written
011: seek (B) (3): seek specific
track & sector
100: bump (C) (4): restore placement
of head: trk 1
101: jump (D) (5): jump to buffer
code
110: execute (E) (6): start motor then
jump
bit 0 drive: 0=#B, 1=#A
FE4F 49 30 EOR #$30 ;set for: 0001 1110
FE51 99 03 04 STA $0403,Y ;store job code back in current queue:
bit 7 job : 0=ignore, 1=job present
bits 6-4 mode:
000: read (8) (0): read data block
001: write (9) (1): write data block
010: verify (A) (2): verify data block
written
011: seek (B) (3): seek specific
track & sector
100: bump (C) (4): restore placement
of head: trk 1
101: jump (D) (5): jump to buffer
code
110: execute (E) (6): start motor then
jump
bit 0 drive: 0=#B, 1=#A
FE54 4C BB FD JMP $FDBB ;jump to FIX SECTOR FAKE SEEK routine
****************************** JOB ROUTINE: mode=010 (A)=verify
(2)=verify data block
written
FE57 20 DD FD JSR $FDDD ;read header block and set beginning data block
****************************** Get byte and compare with contents of
buffer, add up checksum
FE5A 24 4D BIT $4D ;new interrupt ?
FE5C 10 FC BPL $FE5A ;no,
FE5E A5 41 LDA $41 ;read byte from PORT A: data input
FE60 D1 16 CMP ($16),Y ;has byte been correctly written ?
FE62 D0 1A BNE $FE7E ;no,
FE64 45 08 EOR $08 ;calculate checksum
FE66 85 08 STA $08 ;store new checksum value
FE68 C8 INY ;is this the 256th byte ?
FE69 D0 EF BNE $FE5A ;no,
****************************** End reading data, final checksum compare
FE6B 20 51 FF JSR $FF51 ;get checksum byte
FE6E C5 08 CMP $08 ;does checksum match recorded checksum ?
FE70 F0 04 BEQ $FE76 ;yes,
FE72 A9 05 LDA #$05 ;set for "CHECKSUM ERROR IN DATA BLOCK" error
FE74 D0 0A BNE $FE80 ;abort job,
****************************** Check if decoding error
FE76 A9 10 LDA #$10 ;set for "BYTE DECODING ERROR" error
FE78 24 4D BIT $4D ;has DECODING ERROR occurred ?
FE7A F0 4A BEQ $FEC6 ;no,
FE7C D0 02 BNE $FE80 ;abort job,
****************************** Verify error
FE7E A9 07 LDA #$07 ;set for "VERIFY ERROR" error
FE80 D0 46 BNE $FEC8 ;abort job,
****************************** Seek to determine next sector number,
initialize checksum, get block header
FE82 A9 00 LDA #$00
FE84 85 08 STA $08 ;set checksum value to: #$00
FE86 A2 06 LDX #$06 ;set attempts to read HEADER BLOCK to: 6
FE88 20 02 FF JSR $FF02 ;get HEADER BLOCK
FE8B A0 04 LDY #$04 ;set HEADER BLOCK storage pointer
****************************** Get a byte, store in STAB, update checksum
FE8D 24 4D BIT $4D ;new interrupt ?
FE8F 10 FC BPL $FE8D ;no,
FE91 A5 41 LDA $41 ;read byte from PORT A: data input
FE93 99 0D 00 STA $000D,Y ;store byte HDR table
FE96 45 08 EOR $08 ;calculate checksum
FE98 85 08 STA $08 ;store new checksum value
FE9A 88 DEY ;all bytes read ?
FE9B 10 F0 BPL $FE8D ;no,
FE9D C9 00 CMP #$00 ;do header checksums match ?
FE9F D0 2A BNE $FECB ;no,
FEA1 A5 0F LDA $0F ;get track number
FEA3 A6 12 LDX $12 ;get current drive number
FEA5 95 03 STX $03,X ;set drive status: bit 0-5 = track
6 = stepping (1=yes)
5 = accel. (1=yes)
****************************** Load job number and type, test if seek
FEA7 A5 1E LDA $1E ;get current job being done
FEA9 C9 30 CMP #$30 ;is job type #$30 (SEEK SPECIFIC TRACK
& SECTOR) ?
FEAB F0 0F BEQ $FEBC ;yes,
FEAD A0 01 LDY #$01 ;set for checking of ID2, ID1
****************************** Check if ID in HDRPT,Y = STAB,Y
FEAF B1 18 LDA ($18),Y ;get ID from buffer containing master ID's
FEB1 D9 0D 00 CMP $000D,Y ;does ID match master ID ?
FEB4 D0 19 BNE $FECF ;no,
FEB6 88 DEY ;set for ID2
FEB7 10 F6 BPL $FEAF ;do next ID
FEB9 4C 3F FD JMP $FD3F ;jump to DECIDE SECTOR TO SERVICE routine
****************************** JOB ROUTINE: mode=011 (B)=seek
(3)=seek specific
track & sector
FEBC A0 04 LDY #$04 ;set up for transfer of HEADER BLOCK
****************************** Get complete header from STAB,Y into
(HDRPT),Y
FEBE B9 0D 00 LDA $000D,Y ;read byte from header
FEC1 91 18 STA ($18),Y ;store in assigned header buffer
FEC3 88 DEY ;all bytes transferred ?
FEC4 10 F8 BPL $FEBE ;no,
****************************** Set for error #$01 (00, OK,00,00)
FEC6 A9 01 LDA #$01 ;set for "00, OK,00,00" error
****************************** Jump to error handling routine
FEC8 4C 08 FF JMP $FF08 ;jump to SEND JOB STATUS routine
****************************** Checksum error
FECB A9 09 LDA #$09 ;set for "CHECKSUM ERROR IN SEEKED HEADER"
FECD D0 FA BNE $FEC8 ;abort job,
****************************** Mismatch error
FECF A9 0B LDA #$0B ;set for "DISK ID MISMATCH" error
FED1 D0 F5 BNE $FEC8 ;abort job,
****************************** Search for a specific block
FED3 A0 03 LDY #$03 ;set for calculation of ID1, ID2, TRK, SCT
FED5 A9 00 LDA #$00 ;set checksum value to #$00
****************************** Compute checksum, set up search for a
sector
FED7 51 18 EOR ($18),Y ;calculate checksum of HEADER BLOCK
FED9 88 DEY ;another header byte to calculate ?
FEDA 10 FB BPL $FED7 ;yes,
FEDC A0 04 LDY #$04 ;set buffer pointer to checksum byte location
FEDE 91 18 STA ($18),Y ;store result of checksum in buffer
FEE0 A4 1F LDY $1F ;get current job number
FEE2 A2 5A LDX #$5A ;set attempts to read HEADER BLOCK to: 90
****************************** JSR: head set .Y for compare (all bytes
in HDR must be identical)
FEE4 20 02 FF JSR $FF02 ;locate HEADER BLOCK for sector
FFE7 A0 04 LDY #$04 ;set for end of HEADER BLOCK
****************************** Compare to header loop, loop entire header
FEE9 24 4D BIT $4D ;new interrupt ?
FEEB 10 FC BPL $FEE9 ;no,
FEED A5 41 LDA $41 ;read HEADER BLOCK checksum
FEEF D1 18 CMP ($18),Y ;is this the correct sector ?
FEF1 D0 F1 BNE $FEE4 ;no,
FEF3 88 DEY ;all bytes for HEADER BLOCK read ?
FEF4 10 F3 BPL $FEE9 ;no,
FEF6 C8 INY ;move pointer back up
FEF7 A5 40 LDA $40 ;read PORT B status:
0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FEF9 09 80 ORA #$80 ;set motor as still: 1000 0000
FEFB 85 40 STA $40 ;set new PORT B status:
0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FEFD 29 7F AND #$7F ;turn off motor: 0111 1111
FEFF 85 40 STA $40 ;set new PORT B status:
0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FF01 60 RTS
****************************** Search for block head
.X = maximum number of trials
FF02 58 CLI ;clear the interrupt
FF03 CA DEX ;attempts to find HEADER BLOCK expired ?
FF04 10 1E BPL $FF24 ;no,
FF06 A9 02 LDA #$02 ;set for "CAN'T FIND HEADER BLOCK" error
****************************** Send job status, make motor stay on longer
and check job type
FF08 A4 1F LDY $1F ;read current job number
FF0A 99 03 04 STA $0403,Y ;store result of job in same queue:
bit 7 job : 0=ignore, 1=job present
bits 6-4 mode:
000: read (9) (0): read data block
001: write (8) (1): write data block
010: verify (A) (2): verify data block
written
011: seek (B) (3): seek specific
track & sector
100: bump (C) (4): restore placement
of head: trk 1
101: jump (D) (5): jump to buffer
code
110: execute (E) (6): start motor then
jump
bit 0 drive: 0=#B, 1=#A
FF0D 48 PHA
FF0E A6 12 LDX $12 ;set for current drive
FF10 A5 00 LDA $00 ;set .ACC to current clock time
FF12 6F 02 04 ADC $0402 ;add .ACC to motor cutoff time
FF15 95 01 STA $01,X ;set deceleration time
FF17 68 PLA
FF18 4A LSR ;has drive stopped spinning ?
FF19 D0 03 BNE $FF1E ;yes,
FF1B 4C BB FD JMP $FDBB ;jump to FIX SECTOR FAKE SEEK routine
****************************** Purge stack (#$3F)
FF1E A2 3F LDX #$3F ;set .X for: 0011 1111
FF20 9A TXS ;set stack pointer and go into "IDLE LOOP" mode
FF21 4C 54 FC JMP $FC54 ;jump to START
****************************** Get a byte, compare to start of header
FF24 20 3E FF JSR $FF3E ;get HEADER BLOCK identifier: '08'
FF27 C9 08 CMP #$08 ;is this the beginning of the HEADER BLOCK ?
FF29 D0 D7 BNE $FF02 ;no,
FF2B 60 RTS
****************************** Watch for sync character
FF2C 24 82 BIT $82 ;PORT B status reveals SYNC detected ?
bit 0 switch 0 = drive #0
1 = drive #1
1-2 frequency (bit density)
3 write protect 1 = yes
6 sync detect 1 = no, 0 = yes
FF2E 50 0D BVC $FF3D ;no,
FF30 24 4D BIT $4D ;is there a sync ?
FF32 10 F8 BPL $FF2C ;yes,
FF34 24 41 BIT $41 ;clear PORT A: data input
FF36 24 40 BIT $40 ;clear PORT B: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FF38 CA DEX ;amount of attempts to test up ?
FF39 D0 F1 BNE $FF2C ;no,
FF3B 24 82 BIT $82 ;clear PORT B:
bit 0 switch 0 = drive #0
1 = drive #1
1-2 frequency (bit density)
3 write protect 1 = yes
6 sync detect 1 = no, 0 = yes
FF3D 60 RTS
****************************** Hunt for sync characters: set timer for
20ms limit
FF3E 78 SEI ;set the interrupt
FF3F A9 D0 LDA #$D0 ;set TIMER to #$D0 (decimal 208)
FF41 85 45 STA $45 ;TIMER 1 counter high
FF43 A9 03 LDA #$03 ;set for "NO SYNC CHARACTER" error
FF45 24 45 BIT $45 ;is TIMER up ?
FF47 10 BF BPL $FF08 ;yes,
FF49 24 82 BIT $82 ;PORT B status reveals SYNC detected ?
bit 0 switch 0 = drive #0
1 = drive #1
1-2 frequency (bit density)
3 write protect 1 = yes
6 sync detect 1 = no, 0 = yes
FF4B 70 F8 BVS $FF45 ;no,
FF4D 24 40 BIT $40 ;clear PORT B status
0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FF4F 24 41 BIT $41 ;clear interrupt flag register
****************************** Get a byte
FF51 24 4D BIT $4D ;new interrupt ?
FF53 10 FC BPL $FF51 ;no,
FF55 85 41 LDA $41 ;get a byte from PORT A: data input
FF57 60 RTS
****************************** Send two bytes, set normal read mode
FF58 20 79 FF JSR $FF79 ;send byte
FF5B A2 00 LDX #$00 ;set byte to send: #$00
FF5D 20 79 FF JSR $FF79 ;send byte
FF60 A9 FC LDA #$FC ;set PCR for read (F) & normal (C)
****************************** Change EOUT and PCR to send SYNC
FF62 24 4D BIT $4D ;new interrupt
FF64 10 FC BPL $FF62 ;no,
FF66 85 4C STA $4C ;peripheral control register (PCR)
bit 0 set to 1
ca1:byte ready 1=yes, 0=no
bit 1-3
ca2:fill/sync
normal : xC
fill/sync: xE
bit 4 set to 1
cb1:error detect 1=yes, 0=no
bit 5-7
cb2:read/write
write : Dx
read : Fx
FF68 A9 92 LDA #$92 ;set for: 1001 0010
FF6A 85 4E STA $4E ;set interrupt enable register
FF6C 20 51 FF JSR $FF51 ;get a byte
FF6F 24 40 BIT $40 ;clear PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FF71 20 51 FF JSR $FF51 ;get a byte
FF74 24 40 BIT $40 ;clear PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FF76 4C 51 FF JMP $FF51 ;jump to GET A BYTE routine
****************************** Byte to be sent is in .X
FF79 24 4D BIT $4D ;new interrupt ?
FF7B 10 FC BPL $FF79 ;no,
FF7C 86 80 STX $80 ;send byte to PORT A: data out
FF7F 24 41 BIT $41 ;reset port for new byte
FF81 60 RTS
****************************** Interrupt for a few milliseconds, set next
interrupt, reset timer
FF82 48 PHA ;preserve content of .ACC
FF83 8A TXA
FF84 48 PHA ;preserve content of .X
FF85 AD 00 04 LDA $0400 ;read interrupt interval
FF88 85 8F STA $8F ;reset TIMER
FF8A E6 00 INC $00 ;increment controller clock
FF8C A2 01 LDX #$01 ;set for drive 1
****************************** Service motor: check if motor on and
stepping flag set
FF8E A5 00 LDA $00 ;read controller clock
FF90 D5 01 CMP $01,X ;motor TIMER on (running) ?
FF92 D0 16 BNE $FFAA ;yes,
FF94 BD EA FF LDA $FFEA,X ;get status word for corresponding drive
FF97 16 03 ASL $03,X ;calculate new drive status
bit 0-5 = track
6 = stepping (1=yes)
7 = accel. (1=yes)
FF99 24 40 BIT $40 ;test PORT B: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FF9B B0 08 BCS $FFA5 ;stepping flag set ? yes,
FF9D 38 SEC
FF9E BD EA FF LDA $FFEA,X ;get status word for corresponding drive
FFA1 45 40 EOR $40 ;calculate PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FFA3 85 40 STA $40 ;set new PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FFA5 D0 01 BNE $FFA8 ;stepping job completed ? no,
FFA7 18 CLC
****************************** Service stepper motor
FFA8 76 06 ROR $03,X ;perform drive step: bit 0-5 = track
6 = stepping
7 = accel.
****************************** Check if on track, if on track: clear
stepping tag, check next stepper
FFAA B5 05 LDA $05,X ;is number of steps to new track equal to
zero ?
FFAC D0 09 BNE $FFB7 ;no,
FFAE 85 03 LDA $03,X ;get drive status: bit 0-5 = track
6 = stepping
7 = accel.
FFB0 29 BF AND #$BF ;set for: 1011 1111 (clear bit 6)
FFB2 95 03 STA $03,X ;set new drive status: bit 0-5 = track
6 = stepping
7 = accel.
FFB4 4C E1 FF JMP $FFE1 ;jump to STEPPER POSITION routine
****************************** Check direction, step in or step out
FFB7 0A ASL ;multiply by two
FFB8 A5 40 LDA $40 ;read PORT B: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FFBA 3D EF FC AND $FCEF,X ;isolate cycle bits for assigned drive
FFBD 85 07 STA $07 ;set result as new interrupt time
FFBF A5 40 LDA $40 ;read PORT B status:
bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FFC1 3D EC FF AND $FFEC,X ;head stepping inwards ?
FFC4 B0 07 BCS $FFCD ;no,
****************************** Step in (+)
FFC6 D6 05 DEC $05,X ;decrement number of steps to new track
FFC8 7D E8 FF ADC $FFE8,X ;full cycle completed ?
FFCB D0 05 BNE $FFD2 ;no,
****************************** Step out (-)
FFCD F6 05 INC $05,X ;increment number of steps to new track
FFCF FD E8 FF SBC $FFE8,X ;read service cycle
FFD2 3D EC FF AND $FFEC ;cycle stepper
****************************** Store new stepper position, test if DRVST
ready
FFD5 05 07 ORA $07 ;calculate new PORT B by use of interrupt result
FFD7 85 40 STA $40 ;set PORT B: bit 0-1 = stepper motor drv 1
2-3 = stepper motor drv 0
4 = motor 1 off
5 = motor 0 off
FFD9 85 03 LDA $03,X ;get drive status: bit 0-5 = track
6 = stepping
7 = accel.
FFDB 30 04 BMI $FFE1 ;accelerating ? no,
FFDD A5 00 LDA $00 ;read controller clock
FFDF 95 01 STA $01,X ;set motor TIMER
FFE1 CA DEX ;time up ?
FFE2 10 AA BPL $FF8E ;no,
****************************** Pop the STACK of .A and .X then RTI
FFE4 68 PLA ;retrieve .X
FFE5 AA TAX
FFE6 68 PLA ;retrieve .ACC
FFE7 40 RTI
****************************** Stepper control bytes
FFE8 04 ??? ;cycle increment drive 0: (0000 0100)
FFE9 01 ??? ;cycle increment drive 1: (0000 0001)
FFEA 20 ??? ;status word drive 0 : (0010 0000)
FFEB 10 ??? ;status word drive 1 : (0001 0000)
FFEC 0C ??? ;cycle byte for drive 0 : (0000 1100)
FFED 03 ??? ;cycle byte for drive 1 : (0000 0011)
FFEE AA ???
FFEF AA ???
FFF0 AA ???
FFF1 AA ???
FFF2 AA ???
FFF3 AA ???
FFF4 AA ???
FFF5 AA ???
FFF6 AA ???
FFF7 AA ???
FFF8 AA ???
FFF9 AA ???
FFFA AA ???
FFFB 18 ???
****************************** .Word john: $FC09: initialize
FFFC 09 FC ???
****************************** .Word irqh: $FF82: interrupt
FFFE 82 FF ???
APPENDIX A - Miscellaneous programs
A.1 - How to type in programs
There is a description underneath each program so as to explain what this particular utility will do. The memory addresses used within the drive are listed as well as any machine code instructions which may be required to perform the routines listed within the programs.
Before typing in the programs, make sure to have set your computer in LOWER CASE. Below, is a list of notations which represent special key sequences which need to be pressed on your keyboard.
Notation Description Sequence
{clr/home} Clear screen Press SHIFT + CLR/HOME
{home} Home cursor Press HOME
{lft} Cursor left Press SHIFT + CRSR LEFT/RIGHT
{rgt} Cursor right Press CRSR LEFT/RIGHT
{up} Cursor up Press SHIFT + CRSR UP/DOWN
{dwn} Cursor down Press CRSR UP/DOWN
4040 ANTI-CHATTER
10 open 15,8,15
20 print#15,"m-w";chr$(92)chr$(67)chr$(1)chr$(138)
30 close 15
Description: This routine disables the chatter operation in the 4040.
Note : Location $435C MUST contain the value of $8A. Other values
do not properly set the "TIME OUT" on the error recovery.
The drive will not "BUMP the hub" on errors encountered.
Drive memory addresses and/or machine code routines:
$435C = Error recovery count
4040 SOFT DEVICE CHANGE
10 print "{clr/home}"
20 input "new device number *{lft}{lft}{lft}";dn
30 open 15,8,15
40 print#15,"m-w"chr$(12)chr$(0)chr$(2)chr$(dn+32)chr$(dn+64)
50 close 15
Description: This routine changes the current device number to any other
device number (range 8-15).
Note : If unit is turned off and on again, the device number is reset
to it's original number.
Drive memory addresses and/or machine code routines:
$000C = Listen address
$000D = Talker address
4040 GET CURRENT DISK ID'S
10 open 15,8,15
20 print#15,"m-r"chr$(64)chr$(67)chr$(4)
30 for x=1 to 4
40 get#15,x$(x)
50 x(x)=asc(x$(x)+chr$(0))
60 next x
70 close 15
80 id$(0)=chr$(x(1))+chr$(x(2))
90 id$(1)=chr$(x(3))+chr$(x(4))
100 print "{clr/home}"
110 print "disk id for drive 0: "id$(0)
120 print "disk id for drive 1: "id$(1)
Description: This routine returns the current DISK DRIVE id's for the 4040
drive 0 and drive 1.
Note : The id's returned are those which are found in the disk's track
18, sector 0. No id is returned if drive has not been previously initialized.
Drive memory addresses and/or machine code routines:
$4340 - $4341 = Current disk id (drive 0)
$4342 - $4343 = Current disk id (drive 1)
4040 FLASH LED'S
10 print "{clr/home}"
20 open 15,8,15
30 for y=1 to 20
40 read v
50 y$=y$+chr$(v)
60 next y
70 data 0, 0,173, 1, 17,172, 0, 17,162,255,141,130, 2,202,208,250,136
80 data 208,247, 96
90 print#15,"m-w"chr$(0)chr$(17)chr$(20)y$
100 print"{home}{dwn}{dwn}flash which led (<0>/<1>/<e>rror)
110 get le$:if le$="0" then le=16:goto 120
120 if le$="1" then le=8:goto 120
130 if le$<>"e" then 80
140 le=32
150 print#15,"m-w"chr$(0)chr$(17)chr$(2)chr$(64)chr$(le)
160 for x=1 to 10
170 print#15,"m-w"chr$(0)chr$(17)chr$(2)chr$(64)chr$(le)
180 print#15,"m-e"chr$(2)chr$(17)
190 print#15,"m-w"chr$(0)chr$(17)chr$(2)chr$(128)chr$(0)
200 print#15,"m-e"chr$(0)chr$(17)
210 next x
220 close 15
Description: This routine will flash SELECTED led on the 4040 unit.
Note : Selected led will flash 10 times. User code assembly required.
User code resides in BUFFER #0.
Drive memory addresses and/or machine code routines:
$0282 = PBD2
$1100 00 ???
$1101 00 ???
$1102 AD 01 11 LDA $1101
$1105 AC 00 11 LDY $1100
$1108 A2 FF LDX #$FF
$110A 8D 82 02 STA $0282
$110D CA DEX
$110E D0 FA BNE $110A
$1110 88 DEY
$1111 D0 F7 BNE $110A
$1113 60 RTS
4040 HEAD MOVE
10 print "{clr/home}":se$=" "
20 input"enter drive *{lft}{lft}{lft}";d
30 if d=0 then d$="0":dr=12:df=243:ad=4:goto 50
40 d$="1":dr=3:df=252:ad=1
50 open 15,8,15,"i"+d$
60 for x=1 to 12
70 read cd
80 in$=in$+chr$(cd)
90 next x
100 data 169, 64,133, 3,165, 64,141, 64, 5, 76,198,254
110 for x=1 to 12
120 read cd
130 ou$=ou$+chr$(cd)
140 next x
150 data 169, 64,133, 3,173, 65, 5,133, 64, 76,198,254
160 print#15,"m-w"chr$(0)chr$(17)chr$(12)in$
170 print#15,"m-w"chr$(35)chr$(16)chr$(2)chr$(5)chr$(0)
180 jb=208
190 print#15,"m-w"chr$(3)chr$(16)chr$(1)chr$(jb)
200 print#15,"m-r"chr$(64)chr$(17)chr$(1)
210 get#15,x$
220 x=asc(x$+chr$(0))
230 bi=x and dr
240 print "{home}{dwn}{dwn}{dwn}commands: <U>p/<D>own/<Q>uit"
250 print "{home}{dwn}{dwn}{dwn}{dwn}{dwn}head stepping: ";se$;
260 print ", step: {lft}{lft}{lft}";bi
270 geta$
280 if a$="u" then bi=bi+ad:se$="in "
290 if a$="d" then bi=bi-ad:se$="out"
300 if a$="q" then print:close 15:end
310 bi=bi and dr
320 r=(x and df) or bi
330 print#15,"m-w"chr$(65)chr(17)chr$(1)chr$(r)
340 print#15,"m-w"chr$(0)chr$(17)chr$(12)ou$
350 print#15,"m-w"chr$(35)chr$(16)chr$(2)chr$(5)chr$(0)
360 print#15,"m-w"chr$(3)chr$(16)chr$(1)chr$(jb)
370 goto 160
Description: This routine displays the stepping pattern of the 4040 head.
Note : BUFFER #0 is the work buffer. The stepper location is read and
displayed to the screen. Cycling the bits produce the following results:
Drive 0 (bits 2-3): 00-01-10-11-00 moves head inwards
11-10-01-00-11 moves head outwards
Drive 1 (bits 0-1): 00-01-10-11-00 moves head inwards
11-10-01-00-11 moves head outwards
Drive memory addresses and/or machine code routines:
$0003 = 6404 drive status word
$0040 = MOS 6522: port b
$0500 - $05FF = Data buffer #0 on 6404
$1003 = Job queue
$1023 - $1024 = Track, sector buffer #0
$1100 - $11FF = Data buffer #0 on 6502 imaged from data buffer #0 of 6404
Data set #1: $1100 A9 40 LDA #$40
$1102 85 03 STA $03
$1104 A5 40 LDA $40
$1106 8D 40 05 STA $0540
$1109 4C C6 FE JMP $FEC6
Data set #2: $1100 A9 40 LDA #$40
$1102 85 03 STA $03
$1104 AD 41 05 LDA $0541
$1107 85 40 STA $40
$1109 4C C6 FE JMP $FEC6
4040 PHASE & DENSITY CHECK
10 print "{clr/home}"
20 input"enter drive *{lft}{lft}{lft}";d
30 if d=0 then d$="0":dr=12:goto 50
40 d$="1":dr=3
50 open 15,8,15,"i"+d$
60 open 1,8,5,"#4"
70 for x=1 to 13
80 read cd
90 in$=in$+chr$(cd)
100 next x
110 data 165, 64,141, 64, 5,165,130,141, 65, 5, 76,198,254
120 print "{home}{dwn}{dwn}press <space> to pause"
130 print "{home}{dwn}{dwn}{dwn}{dwn}track phase density{dwn}"
140 for tr=1 to 35
150 print#15,"u1:";5;d;tr;0
160 print#15,"m-w"chr$(0)chr$(17)chr$(13)in$
170 print#15,"m-w"chr$(35)chr$(16)chr$(2)chr$(5)chr$(0)
180 jb=208
190 print#15,"m-w"chr$(3)chr$(16)chr$(1)chr$(jb)
200 print#15,"m-r"chr$(64)chr$(17)chr$(1)
210 get#15,ph$
220 ph=asc(ph$+chr$(0))
230 print#15,"m-r"chr$(65)chr$(17)chr$(1)
240 get#15,de$
250 de=asc(de$+chr$(0))
260 print tab(2);tr;tab(11);ph and dr;tab(22);de and 6
270 get ps$:if ps$<>chr$(32) then 290
280 get ps$:if ps$<>chr$(32) then 280
290 next tr
300 close 15
Description: This routine returns the phase pattern along with the density
value for all the tracks of the 4040.
Note : BUFFER #0 is the work buffer. Two locations are read in and
displayed to the screen. One location is the stepping tag and the other the density select. It seems that the head is on track at every ODD value and that the head is in between tracks at every EVEN value.
Drive memory addresses and/or machine code routines:
$0040 = MOS 6522: port b
$0082 = MOS 6530: port b
$0500 - $05FF = Data buffer #0 on 6404
$1003 = Job queue
$1023 - $1024 = Track, sector buffer #0
$1100 - $11FF = Data buffer #0 on 6502 imaged from data buffer #0 of 6404
Data set #1: $1100 A5 40 LDA $40
$1102 8D 40 05 STA $0540
$1105 A5 82 LDA $82
$1107 8D 41 05 STA $0541
$110A 4C C6 FE JMP $FEC6
4040 READ HEADER BLOCK
10 print "{clr/home}"
20 open 15,8,15
30 input"track *{lft}{lft}{lft}";tr
40 input"sector *{lft}{lft}{lft}";se
50 print#15,"m-w"chr$(67)chr$(16)chr$(2)chr$(tr)chr$(se)
60 jb=176
70 print#15,"m-w"chr$(7)chr$(16)chr$(1)chr$(jb)
80 print#15,"m-r"chr$(7)chr$(16)chr$(1)
90 get#15,er$(1)
100 er(1)=asc(er$(1)+chr$(0))
110 if er(1)>127 then 80
120 print#15,"m-w"chr$(67)chr$(16)chr$(2)chr$(tr)chr$(se)
130 jb=128
140 print#15,"m-w"chr$(7)chr$(16)chr$(1)chr$(jb)
150 print#15,"m-r"chr$(7)chr$(16)chr$(1)
160 get#15,er$(2)
170 er(2)=asc(er$(2)+chr$(0))
180 if er(2)>127 then 150
190 print#15,"m-r"chr$(65)chr$(16)chr$(8)
200 for x=1 to 8
210 get#15,a$(x)
220 a(x)=asc(a$(x)+chr$(0))
230 next x
240 close 15
250 print "{home}{dwn}{dwn}{dwn}{dwn}"
260 print "seek status :"er(1)
270 print "read status :"er(2)
280 print "id1 :"a(1)
290 print "id2 :"a(2)
300 print "id1+id2 : "chr$(a(1))+chr$(a(2))
310 print "track :"a(3)
320 print "sector :"a(4)
330 print "checksum :"a(5)
340 print "off :"a(6)
350 print "spare1 :"a(7)
360 print "spare2 :"a(8)
Description: This routine returns the header block status of any 4040 track
and sector.
Note : BUFFER #4 is the buffer in which the result of the operation is
found. The routine is composed of 3 parts: SEEK, READ, display information.
Drive memory addresses and/or machine code routines:
$1007 = Job queue
$1041 = Id1
$1042 = Id2
$1043 = Track
$1044 = Sector
$1045 = Checksum
$2100 - $21FF = Data buffer #4
4040 SPEED-UP
10 open 15,8,15
20 print#15,"m-w"chr$(0)chr$(16)chr$(10)chr$(2)chr$(2)
30 close 15
Description: This routine speeds up the 4040 read/write operation.
Note : Location $1000 SHOULD NEVER hold a value smaller than #$0A.
Smaller values may cause severe hardware failure. It is also noted that the read/write efficiency drops in the outer tracks.
Drive memory addresses and/or machine code routines:
$1000 = Interrupt delay
$1001 = Motor acceleration delay
$1002 = Motor cutoff time
A.1 - How to type in programs
There is a description underneath each program so as to explain what this particular utility will do. The memory addresses used within the drive are listed as well as any machine code instructions which may be required to perform the routines listed within the programs.
Before typing in the programs, make sure to have set your computer in LOWER CASE. Below, is a list of notations which represent special key sequences which need to be pressed on your keyboard.
Notation Description Sequence
{clr/home} Clear screen Press SHIFT + CLR/HOME
{home} Home cursor Press HOME
{lft} Cursor left Press SHIFT + CRSR LEFT/RIGHT
{rgt} Cursor right Press CRSR LEFT/RIGHT
{up} Cursor up Press SHIFT + CRSR UP/DOWN
{dwn} Cursor down Press CRSR UP/DOWN
4040 DOS VERSION CODE CHANGE
10 print "{clr/home}"
20 input "dos version code to set drive to *{lft}{lft}{lft}";cd
30 open 15,8,15
40 print#15,"m-w"chr$(159)chr$(16)chr$(1)chr$(cd)
50 close 15
Description: This routine permits read/write to any 4040 formatted disks
which the dos character $41 (A) had been altered.
Note : This location usually contains ASCII value of 65 which will
represent the dos version (2A).
Drive memory addresses and/or machine code routines:
$109F = Dos version number
4040 WRITE PROTECT TEST
10 print "{clr/home}"
20 input"enter drive *{lft}{lft}{lft}";d
30 d$=chr$(169)+chr$(d)
40 for x=1 to 5
50 read cd
60 d$=d$+chr$(cd)
70 next x
80 data 133,130, 76,198,254
90 for x=1 to 11
100 read cd
110 sw$=sw+chr$(cd)
120 next x
130 data 234,165,130, 41, 9,141, 19, 5, 76,198,254
140 open 15,8,15
150 print#15,"m-w"chr$(0)chr$(17)chr$(7)d$
160 print#15,"m-w"chr$(17)chr$(16)chr$(2)chr$(5)chr$(0)
170 jb=208
180 print#15,"m-w"chr$(3)chr$(16)chr$(1)chr$(jb)
190 print#15,"m-r"chr$(3)chr$(16)chr$(1)
200 get#15,b$
210 b=asc(b$+chr$(0))
220 if b>127 then 190
230 close 15
240 open 15,8,15
250 print#15,"m-w"chr$(0)chr$(17)chr$(11)sw$
260 print#15,"m-w"chr$(17)chr$(16)chr$(2)chr$(5)chr$(0)
270 print#15,"m-w"chr$(3)chr$(16)chr$(1)chr$(jb)
280 print#15,"m-r"chr$(3)chr$(16)chr$(1)
290 get#15,b$
300 b=asc(b$+chr$(0))
310 if b>127 then 280
320 print#15,"m-r"chr$(19)chr$(17)chr$(1)
330 get#15,c$
340 c=asc(c$+chr$(0))
350 if c=8 and d=0 then sa$="on":goto 340
360 if c=9 and d=1 then sa$="on":goto 340
370 sa$="off"
380 print "{home}{dwn}{dwn}{dwn}write protect switch drive";d;"is ";sa$
390 close 15
Description: This routine will scan the write protect sense switch in order to
determine if the switch is ON or OFF. All processing done by the 6504.
Note : BUFFER #0 is the work buffer. Two routines of which one sets
the drive to test and two, tests the write protect switch.
Drive memory addresses and/or machine code routines:
$0082 = 6404 port b
$0519 = State of switch stored at 6404 buffer zero
$1003 = Job queue
$1023 - $1024 = Track, sector buffer #0
$1100 - $11FF = Data buffer
$1119 = State of switch imaged from 6404
Data set #1: $1100 A9 ?? LDA #$??
$1102 82 82 STA $82
$1104 4C C6 FE JMP $FEC6
Data set #2: $1100 A5 82 LDA $82
$1102 A9 09 AND #$82
$1104 8D 13 05 STA $0513
$1107 4C C6 FE JMP $FEC6
4040 SPEED TEST
10 print "{clr/home}":sp$=""
20 print "speed check on unit 8, drive 0 & 1"
30 open 15,8,15
40 for x=0 to 182
50 read a
60 print#15,"m-w"chr$(x)chr$(17)chr$(1)chr$(a)
70 next x
80 ps=0:sc=0:jb=192:dr=0
90 print#15,"m-w"chr$(35)chr$(16)chr$(2)chr$(0)chr$(10)
100 print#15,"m-w"chr$(3)chr$(16)chr$(1)chr$(jb+dr)
110 print#15,"m-r"chr$(3)chr$(16)
120 get#15,a$
130 a=asc(a$+chr$(0))
140 if a>127 then 110
150 print "{home}{dwn}{dwn}{dwn}adjust speed deviation to: 0 or +/- 1 ms"
160 for i=1 to 2000:tq=ti:next i
170 print#15,"m-w"chr$(1)chr$(17)chr$(1)chr$(7)
180 print#15,"m-w"chr$(35)chr$(16)chr$(1)chr$(36)
190 print#15,"m-w"chr$(18)chr$(16)chr$(1)chr$(36)
200 jb=224:print#15,"m-w"chr$(3)chr$(16)chr$(1)chr$(jb+dr)
210 jb=192
220 print#15,"m-r"chr$(3)chr$(16)
230 get#15,a$
240 a=asc(a$+chr$(0))
250 if a>127 then 220
260 for i=1 to 4
270 print#15,"m-r"chr$(i+2)chr$(17)
280 get#15,a$
290 sv(i)=asc(a$+chr$(0))
300 next i
310 no=0:if sv(3)=0 or sv(4)=0 then no=1
320 if no then 340
330 goto 390
340 sc=sc+1:if sc<3 then 170
350 print "{home}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}";
360 print "{dwn}{dwn}write protect/sync failure on drive";dr:print#15,"uj"
370 close 15:end
380 print "{home}{dwn}{dwn}{dwn}write protect switch drive";d;"is ";sa$
390 sa=(256*sv(4)+sv(2)-1998)
400 sb=(256*sv(3)+sv(1)-1998)
410 sd=int((sa+sb)/20+.5)
420 print "{home}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}speed deviation";
430 print " is {lft}{lft}{lft}{lft}{lft}"sd"ms/rev, on drive {lft}";
440 print "{lft}"dr
450 ps=1:print "{home}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}";
460 print "speed adjusted for drive {lft}"dr"? y/n"
470 if abs(sd)>5 then 550
480 print#15,"m-w"chr$(1)chr$(17)chr$(1)chr$(60)
490 get a$:if a$="y" then 550
500 if a$="n" and abs(sd)<2 then 550
510 if ti-tq<7000 then 180
520 print "{home}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}{dwn}";
530 print "{dwn}{dwn}speed test stopped after 2 minutes !":print#15,"uj"
540 close 15:end
550 dr=dr+1:if dr>1 then print#15,"uj":close 15:end
560 ps=0:sc=0:jb=192:goto 90
570 data 76, 7, 5, 0, 0, 0, 0,120,162, 16,134, 78,162, 40,169,220
580 data 133, 76,169, 0,168, 32,167, 5,136,208,250,202,208,247,162,222
590 data 169
600 data 255,134, 76,162, 4, 32,167, 5,202,208,250,169,252,133, 76,169
610 data 146,133, 78,162, 4, 32,176, 5,202,208,250,120,160, 0,140, 4
620 data 5
630 data 140, 6, 5,140, 3, 5,140, 5, 5,140,183, 5,140,184, 5,132
640 data 69,169, 98,133, 68,169, 64,133, 75, 36,130,112, 48,162, 1, 36
650 data 130
660 data 80, 54,132, 69, 36,130, 80, 17,165, 77, 10, 16,247,165, 68,254
670 data 3, 5,208,240,254, 5, 5,208,235,202,240,226,169, 1,133, 75
680 data 88
690 data 173,252,255,240, 3,108, 2,252, 76,249,254,206,183, 5,208,199
700 data 206,184, 5,208,194,240,228,206,183, 5,208,193,206,184, 5,208
710 data 188
720 data 240,216, 36, 77, 16,252,133,128, 36, 65, 96, 36, 77, 16,252,165
730 data 65, 96
Description: This routine will test the timing speed for drive 0 and drive 1
Note : BUFFER #0 is the work buffer. A routine is transferred to
this buffer and then passed on to the controller. The disks must be formatted and there must not be any write protect labels.
Drive memory addresses and/or machine code routines:
$0041 = port a: data input
$0044 = timer 1 latch and counter low
$0045 = timer 1 counter high
$004B = auxiliary control register
$004C = peripheral control register
$004D = int flag register
$004E = int enable register
$0080 =6404 port a
$0082 = 6404 port b
$0519 = State of switch stored at 6404 buffer zero
$1003 = Job queue
$1023 - $1024 = Track, sector buffer #0
$1100 - $11FF = Data buffer
$1119 = State of switch imaged from 6404
Data set #1: $0500 4C 07 05 JMP $0507
$0503 00 BRK
$0504 00 BRK
$0505 00 BRK
$0506 00 BRK
$0507 78 SEI
$0508 A2 10 LDX #$10
$050A 86 4E STX $4E
$050C A2 28 LDX #$28
$050E A9 DC LDA #$DC
$0510 85 4C STA $4C
$0512 A9 00 LDA #$00
$0514 A8 TAY
$0515 20 A7 05 JSR $05A7
$0518 88 DEY
$0519 D0 FA BNE $0515
$051B CA DEX
$051C D0 F7 BNE $0515
$051E A2 DE LDX #$DE
$0520 A9 FF LDA #$FF
$0522 86 4C STX $4C
$0524 A2 04 LDX #$04
$0526 20 A7 05 JSR $05A7
$0529 CA DEX
$052A D0 FA BNE $0526
$052C A9 FC LDA #$FC
$052E 85 4C STA $4C
$0530 A9 92 LDA #$92
$0532 85 4E STA $4E
$0534 A2 04 LDX #$04
$0536 20 B0 05 JSR $05B0
$0539 CA DEX
$053A D0 FA BNE $0536
$053C 78 SEI
$053D A0 00 LDY #$00
$053F 8C 04 05 STY $0504
$0542 8C 06 05 STY $0506
$0545 8C 03 05 STY $0503
$0548 8C 05 05 STY $0505
$054B 8C B7 05 STY $05B7
$054E 8C B8 05 STY $05B8
$0551 84 45 STY $45
$0553 A9 62 LDA #$62
$0555 85 44 STA $44
$0557 A9 40 LDA #$40
$0559 85 4B STA $4B
$055B 24 82 BIT $82
$055D 70 30 BVS $058F
$055F A2 01 LDX #$01
$0561 24 82 BIT $82
$0563 50 36 BVC $059B
$0565 84 45 STY $45
$0567 24 82 BIT $82
$0569 50 11 BVC $057C
$056B A5 4D LDA $4D
$056D 0A ASL
$056E 10 F7 BPL $0567
$0570 A5 44 LDA $44
$0572 FE 03 05 INC $0503,X
$0575 D0 F0 BNE $0567
$0577 FE 05 05 INC $0505,X
$057A D0 EB BNE $0567
$057C CA DEX
$057D F0 E2 BEQ $0561
$057F A9 01 LDA #$01
$0581 85 4B STA $4B
$0583 58 CLI
$0584 AD FC FF LDA $FFFC
$0587 F0 03 BEQ $058C
$0589 6C 02 FC JMP ($FC02)
$058C 4C F9 FE JMP $FEF9
$058F CE B7 05 DEC $05B7
$0592 D0 C7 BNE $055B
$0594 CE B8 05 DEC $05B8
$0597 D0 C2 BNE $055B
$0599 F0 E4 BEQ $057F
$059B CE B7 05 DEC $05B7
$059E D0 C1 BNE $0561
$05A0 CE B8 05 DEC $05B8
$05A3 D0 BC BNE $0561
$05A5 F0 D8 BEQ $057F
$05A7 24 4D BIT $4D
$05A9 10 FC BPL $05A7
$05AB 85 80 STA $80
$05AD 24 41 BIT $41
$05AF 60 RTS
$05B0 24 4D BIT $4D
$05B2 10 FC BPL $05B0
$05B4 A5 41 LDA $41
$05B6 60 RTS
APPENDIX B - IEEE bus definitions
B.1 - IEEE Bus connector pins
DIO1 DIO5
DIO2 DIO6
DIO3 DIO7
DIO4 DIO8
EOI REN
DAV DAV ground
NRFD NRFD ground
NDAC NDAC ground
IFC IFC ground
SRQ SRQ ground
ATN ATN ground
Shield/Earth ground Signal ground
B.2 - IEEE 488 bus signals
TYPE PIN LINE DESCRIPTION
-----------------------------------------------------------------------------
Manager ATN The controller (PET/CBM) sets this signal low
while it is sending commands on the data bus. When
ATN is low, only peripheral addresses and control
messages are on the data bus. When ATN is high,
only previously assigned devices can transfer data
Transfer DAV When DAV is low, this signifies that data is valid
on the data bus.
Manager EOI When the last byte of data is being transferred,
the talker has the option of setting EOI low. The
controller always sets EOI low while the last data
byte is being transferred from the controller.
Manager IFC The controller sends its internal reset signal as
IFC low (true) to initialize all devices to the
idle state. When the controller is switched on or
reset, IFC goes low for about 100 milliseconds.
Transfer NDAC This signal is held low (true) by the listener
while reading. When the data byte has been read,
the listener sets NDAC high. This signals the
talker that data has been accepted.
Transfer NRFD When NRFD is low (true), one or more listeners are
not ready for the next byte of data. When all
devices are ready, NRFD goes high.
Manager SRQ Not implemented in BASIC, but available to the
user
Manager REN REN is held low by the bus controller. The PET/CBM
has a pin grounded that keeps REN permanently low.
Data DIO1 - 8 These signals represent the bits of information on
the data bus. When a DIO signal is low, it will
represent 1 and when high 0.
General GROUND Ground connections. There are six control and
management signal ground returns, one data signal
ground return and one chassis shield ground lead.
B.3 - IEEE Byte transfer sequence (talker)
B.3 - IEEE Byte transfer sequence (listener)
B.4 - IEEE Port pinouts
1 2 3 4 5 6 7 8 9 10 11 12
A B C D E F H J K L M N
PIN # PIN # (*) MNEMONIC DEFINITION
-----------------------------------------------------------------------------
1 1 DIO1 Data input/output line #1
2 2 DIO2 Data input/output line #2
3 3 DIO3 Data input/output line #3
4 4 DIO4 Data input/output line #4
5 5 EOI End or identify
6 6 DAV Data valid
7 7 NRFD Not ready for data
8 8 NDAC Data not accepted
9 9 IFC Interface clear
10 10 SRQ Service request
11 11 ATN Attention
12 12 GND Chassis ground (IEEE cable shield)
A 13 DIO5 Data input/output line #5
B 14 DIO6 Data input/output line #6
C 15 DIO7 Data input/output line #7
D 16 DIO8 Data input/output line #8
E 17 REN Remote enable
F 18 GND DAV ground
H 19 GND NRFD ground
J 20 GND NDAC ground
K 21 GND IFC ground
L 22 GND SRQ ground
M 23 GND ATN ground
N 24 GND Data ground (DIO1 - 8)
(*) Pin numbers for standard IEEE cable connector
B.5 - IEEE Standard definitions
NAME DEFINITION
-----------------------------------------------------------------------------
AC Addressed command
ACDS Accept data state
ACG Addressed command group
ACRS Acceptor ready state
AD Addressed
AH Acceptor handshake
AH1 Complete capability
AH0 No capability
AIDS Acceptor idle state
ANRS Acceptor not ready state
ANSI American National Standard's Institute
APRS Affirmative poll response state
ATN Attention
AWNS Acceptor wait for new state
C Controller
CACS Controller addressed state
CADS Controller idle state
CAWS Controller active wait state
CIDS Controller idle state
CPPS Controller parallel poll state
CPWS Controller parallel poll wait state
CSBS Controller standy state
CSNS Controller service not requested state
CSRS Controller service request state
CSWS Controller synchronous wait state
CTRS Controller transfer state
DAB Data byte
DAC Data accepted
DAV Data valid
DC Device clear
DCAS Device clear active state
DCIS Device clear idle state
DCL Device clear
DD Device dependent
DIO Data input
DT Data trigger
DTAS Device trigger active state
DTIS Device trigger state
END End
EOI End or identify
EOS End of string
F Active false
(F) Passive false
GET Group execute trigger
NAME DEFINITION
-----------------------------------------------------------------------------
GTL Go to local
gts Go to standby
IDY Identify
IFC Interface clear
ist Individual status
L or LE Listener or extended listener
LACS Listener active status
LADS Listener addressed state
LAG Listener address group
LIDS Listener idle state
LLO Local lockout
LOCS Local state
lon Listener only
LPAS Listener primary addressed state
(lpe) Local poll enable
LPIS Listener primary idle state
ltn Listen
Lun Local unlisten
LWLS Local with lockout state
M Multiline
MLA or (MLA) My listen address
MSA or (MSA) My secondary address
MTA or (MTA) My talk address
nba New byte available
NDAC Not data accepted
NPRS Negative poll response state
NRFD Not ready for data
NUL Null byte
OSA Other secondary address
OTA Other talk address
PACS Parallel poll addressed to configure state
PCG Primary command group
POFS Power off
pon Power on
PP Parallel poll
PPAS Parallel poll active state
PPC Parallel poll configure
PPD or (PPD) Parallel poll disable
PPE or (PPE) Parallel poll enable
PPIS Parallel poll idle state
PPR Parallel poll response
PPSS Parallel poll standby state
PPU Parallel poll unconfigure
PUCS Parallel poll unaddressed to configure state
rdy Ready (for next message)
REMS Remote state
REN Remote enable
NAME DEFINITION
-----------------------------------------------------------------------------
RFD Ready for data
RL Remote local
rpp Request parallel poll
RQS Request service
rsc Request system control
rsv Request service
rtl Return to local
RWLS Remote with lockout state
SACS System control active state
SCG Secondary command group
SDC or (SDC) Selected device clear
SDYS Source delay state
SE Secondary
SGNS Source generated state
SH Source handshake
SIAS System central interface clear active state
sic Send interface clear
SIDS Source idle state
SIIS System control interface clear active state
SINS System control interface clear not active state
SIWS Source idle wait state
SNAS System control not active state
SPAS Serial poll active state
SPD Serial poll disable
SPE Serial poll enable
SPIS Serial poll idle state
SPMS Serial poll mode state
SR Service request
SRAS System control remote enable active state
sre Send remote enable
SRIS System control remote enable idle state
SRNS System control remote enable not active state
SRQ Service request
SRQS Service request state
ST Status
STB Status byte
STRS Source transfer state
SWNS Source wait for new cycle state
T or (TE) Talker or extended talker
T Active true
(T) Passive true
TACS Talker active state
TADS Talker addressed state
TAG Talk address group
tca Take control asynchronously
tcs Take control synchronously
TCT or (TCT) Take control
TIDS Talker idle state
ton Talk only
TPAS Talker primary address state
U Uniline message
NAME DEFINITION
-----------------------------------------------------------------------------
UC Universal command
UCG Universal command group
UNL Unlisten
UNT Untalk
APPENDIX C - IC memory/register configurations
C.1 - 6522 VIA (Versatile Interface Adaptor)
Vss CA1
PA0 CA2
PA1 RS0
PA2 RS1
PA3 RS2
PA4 RS3
PA5 Reset
PA6 D0
PA7 D1
PB0 D2
PB1 D3
PB2 D4
PB3 D5
PB4 D6
PB5 D7
PB6 O2
PB7 CS1
CB1 CS2
CB2 R/W
Vcc IRQ
C.2 - 6502 CPU
Vss Reset
RDY O2 OUT
O1 OUT S.O.
IRQ O0 IN
N.C. N.C.
NMI N.C.
SYNC R/W
Vcc DB0
AB0 DB1
AB1 DB2
AB2 DB3
AB3 DB4
AB4 DB5
AB5 DB6
AB6 DB7
AB7 AB15
AB8 AB14
AB9 AB13
AB10 AB12
AB11 Vss
C.3 - 6522 VIA control registers
AUXILLARY CONTROL REGISTER (Chip Address + 11)
7 6 5 4 3 2 1 0
Timer 1 Ctrl T2 Shift Reg Control Latch Ctrl
control
0 0 PA Latch disabled, PB Latch
disabled
1 1 PA Latch enabled, PB Latch
enabled
0 0 0 Shift Register Disabled
0 0 1 Shift IN: shift controlled by Timer 2
0 1 0 Shift IN: shift rate controlled by O2
0 1 1 Shift IN: shift rate controlled by
External Clock source
1 0 0 Shift OUT: Free-Running Mode, rate
controlled by Timer 2
1 0 1 SHIFT OUT: rate controlled by Timer 2
1 1 0 SHIFT OUT: rate controlled by O2
1 1 1 SHIFT OUT: rate controlled by External
Clock source
0 Decrement Counter 2 at O2 clock rate (in one-shot mode)
1 Decrement Counter 2 on pulses from PB6
0 One-Shot Mode
1 Free-Running Mode
0 PB7 disabled
1 PB7 enabled
PERIPHERAL CONTROL REGISTER (Chip Address + 12)
7 6 5 4 3 2 1 0
CB2 Control CB1 IRQ CA2 Control CA1 IRQ
Control Control
0 A
1 B
0 0 0 C
0 0 1 D
0 1 0 E
0 1 1 F
1 0 0 G
1 0 1 H
1 1 0 I
1 1 1 J
0 K
1 L
0 0 0 M
0 0 1 N
0 1 0 O
0 1 1 P
1 0 0 Q
1 0 1 R
1 1 0 S
1 1 1 T
DESCRIPTION
A Interrupt Flag Reg Bit1 = 1 on CA1 going low
B Interrupt Flag Reg Bit1 = 1 on CA1 going high
Interrupt Flag Reg Bit1 cleared by reading I/O Port A
C Input Mode: IFR Bit0 = 1 on CA2 going low (cleared by R/W on I/O Port A)
D Independent Int. Input Mode: IFR Bit0 = 1 on CA2 going low (Bit0 not
cleared by R/W on I/O Port A)
C Input Mode: IFR Bit0 = 1 on CA2 going high (cleared by R/W on I/O Port A)
F Independent Int. Input Mode: IFR Bit0 = 1 on CA2 going high (Bit0 not
cleared by R/W on I/O Port A)
G Output Mode w/Handshaking: CA2 goes low on R/W I/O Port A (CA2 goes
high on pulse from CA1)
H Pulse Output Mode: CA2 goes low for one O2 cycle for R/W on I/O Port A
I Manual Output Mode: CA2 set low
J Manual Output Mode: CA2 set high
K Interrupt Flag Reg Bit4 = 1 on CB1 going low
L Interrupt Flag Reg Bit4 = 1 on CB1 going high
Interrupt Flag Reg Bit4 cleared by reading I/O Port A
M Input Mode: IFR Bit3 = 1 on CB2 going low (cleared by R/W on I/O Port B)
N Independent Int. Input Mode: IFR Bit3 = 1 on CB2 going low (Bit3 not
cleared by R/W on I/O Port B)
O Input Mode: IFR Bit3 = 1 on CB2 going high (cleared by R/W on I/O Port B)
P Independent Int. Input Mode: IFR Bit3 = 1 on CB2 going high (Bit3 not
cleared by R/W on I/O Port B)
Q Output Mode w/Handshaking: CB2 goes low on R/W I/O Port B (CB2 goes
high on pulse from CB1)
R Pulse Output Mode: CB2 goes low for one O2 cycle for R/W on I/O Port B
S Manual Output Mode: CB2 set low
T Manual Output Mode: CB2 set high
INTERRUPT FLAG REGISTER (Chip Address + 13)
7 6 5 4 3 2 1 0
IRQ T1 T2 CB1 CB2 SR CA1 CA2
A
B
C
D
E
F
G
H
Flag set Flag cleared
A Transition at CA2 Reading/Writing I/O Port A
B Transition at CA1 Reading/Writing I/O Port A
C 8 Bits Shifted IN/OUT Reading/Writing Shift Reg
D Transition at CB2 Reading/Writing I/O Port B
E Transition at CB1 Reading/Writing I/O Port B
F Timer 2 Timeout Reading T2 low/Writing T2 High
G Timer 1 Timeout Reading T1 low/Writing T1 High
H Interrupt Occurring Clearing any interrupt
INTERRUPT ENABLE REGISTER (Chip Address + 14)
7 6 5 4 3 2 1 0
S/C T1 T2 CB1 CB2 SR CA1 CA2
0 0 0 0 0 0 0 Interrupt Disabled
1 1 1 1 1 1 1 Interrupt Enabled
Set Enable Flag: (write 1 OR'd with Flag Bit n=1)
Clear Enable Flag: (write 0 OR'd with Flag Bit n=1)