This in-depth guide for the Commodore 1541 disk drive owner, unravels the mysteries of using the 1541 for programs, sequ
874 105 36MB
English Pages 507 [524] Year 1985
Table of contents :
Chapter 1: Programming the VIC-1541 1
1.1 Getting started 1
1.1.1 After Unpacking 1
1.1.2 The Disk Operating System 4
1.1.3 The TEST/DEMO Diskette 4
1.1.4 Fomatting New Diskettes 5
1.1.5 Some Facts about a 1541 Diskette 5
1.1.6 Fundamentals of Disk Techniques 6
1.2 Program Management on Diskette 9
1.2.1 Save - Storing BASIC Programs 9
1.2.2 LOAD - Loading BASIC Programs 10
1.2.3 VERIFY - Checking Stored Programs 11
1.2.4 SAVE "@: ... " - Replacing Programs 12
1.2.5 Loading Machine Language Programs 13
1.2.6 Storing Machine Language Programs 15
1.3 Disk System Commands 19
1.3.1 Transmitting Commands to the Disk Drive 19
1.3.2 NEW - Formatting Diskettes 20
1.3.3 Reading the Error Channel 22
1.3.4 LOAD"$",8 - Loading the Directory 24
1.3.5 SCRATCH - Deleting Files 26
1.3.6 RENAME - Renaming Files 28
1.3.7 COPY - Copying Files 31
1.3.8 INITIALIZE - Initializing the Diskette 32
1.3.9 VALIDATE - "Cleaning Up" the Diskette 33
1.3.10 ? * - The Wildcards 34
1.4 Sequential Data Storage 37
1.4.1 The Principle 37
1.4.2 Opening a Sequential Data File 39
1.4.3 Transferring Data Between Disk and Computer 42
1.4.4 Adding Data to Sequential Files 46
1.4.5 Closing a Sequential File 47
1.4.6 Redirecting the Screen Output 48
1.4.7 Sequential Files as Tables in the Computer 50
1.4.8 Searching Tables 53
1.4.9 Simple Sorting of Tables 57
1.4.10 MAILING LIST MANAGEMENT with Sequential
Data Storage 60
1.4.11 Uses for Sequential Storage 70
1.5 Relative Data Storage 71
1.5.1 The Principle 71
1.5.2 The Advantage over Sequential Storage 72
1.5.3 Opening a Relative File 73
1.5.4 Preparing Data for Relative Storage 76
1.5.5 Transferring Data 78
1.5.6 Closing a Relative File 83
1.5.7 Searching Records with the Binary Method 83
1.5.8 Searching Records with a Separate Index File 87
1.5.9 Changing Records 90
1.5.10 Expanding a Relative File 92
1.5.11 Home Accounting with Relative Data Storage 93
1.6 Additional File Structures 105
1.6.1 Direct Addressing 105
1.6.2 Indirect Addressing 107
1. 7 Disk Error Messages and their Causes 109
1.8 Overview of Commands with a Comparison of BASIC 2.0 _
BASIC 4.0 - BASIC 7.0 - DOS 5.1 115
1.8.1 BASIC 4.0 - BASIC 7.0 Commands 116
1.8.2 BASIC 7.0 commands 122
Chapter 2: Advanced Programming 125
2.1 Direct Access of any Block of the Diskette 125
2.2 The Direct Access Commands 129
2.2.1 The Block-Read Command 129
2.2.2 The Block-Pointer Command 130
2.2.3 The Block-Write Command 131
2.2.4 The Block-Allocate Command 133
2.2.5 The Block-Free Command 134
2.2.6 The Block-Execute Command 135
2.3 Uses of Direct Access 137
2.4 Accessing the DOS - The Memory Commands 139
2.4.1 The Memory-Read Command 139
2.4.2 The Memory-Write Command 141
2.4.3 The Memory-Execute Command 142
2.4.4 The User Commands 143
2.4.5 Additional Possibilities for the User Commands 145
Chapter 3: Technical Information 147
3.1 TheConstructionoftheVIC-l541 147
3.1.1 Block Diagram of the Disk Drive 147
3.1.2 DOS Memory Map - ROM, RAM, I/O 148
3.1.3 Layout of the I/O Ports (VIA 6522) 149
3.1.4 The Layout of the Important Memory Locations 150
3.2 Operation of the DOS - An Overview 155
3.2.1 The Disk Controller Routines 156
3.3 The Structure of the VIC-1541 Diskette 159
3.3.1 The BAM of the VIC-1541 159
3.3.2 The Directory 161
3.3.3 The Directory Format 164
3.3.4 The Diskette Recording Process 170
3.4 The Organization of Relative Files 175
3.5 DOS 2.6 ROM Listings 181
Chapter 4: Programs and Tips for Using the 1541 Disk Drive 415
4.1 Utility Programs 415
4.1.1 Displaying all File Parameters 415
4.1.2 Scratch-protect Files - File Protect 422
4.1.3 Backup Program - Copying a Diskette 429
4.1.4 Copying Individual Files to another Diskette 432
4.1.5 Reading the Directory from within a Program 434
4.1.6 Searching for "Hidden" Files 435
4.1.7 Changing the Disk Name and the ID 438
4.1.8 Software Write Protect 441
4.1.9 Invisible Directory 442
4.2 The Utility Programs on the TESTIDEMO Disk 445
4.2.1 DOS 5.1 445
4.2.2 COPY/ALL 446
4.2.3 DISK ADDR CHANGE 447
4.2.4 DIR 448
4.2.5 VIEW BAM 448
4.2.6 CHECK DISK 448
4.2. 7 DISPLAY T &S 449
4.2.8 PERFORMANCE TEST 449
4.3 BASIC Extensions and Programs for the 1541 451
4.3.1 Input Strings of Desired Length from the Disk 451
4.3.2 Easy Preparation of Data Records 456
4.3.3 Spooling - Printing Directly from the Disk 465
4.4 Overlay Technique and Chaining Machine Language Programs 469
4.5 Merge - Appending BASIC Programs 473
4.6 Disk Monitor for the Commodore 64 and VIC 20 475
4.7 Using "WEDGE" Commands from BASIC Programs 497
Chapter 5: The Larger CBM Disks 499
5.1 IEEE-Bus and Serial Bus 499
5.2 Overview of the "large" CBM Disk Drives 503
The New Anatomy of the 1541 Disk Drive A Complete Guide to Using the Commodore Disk Drive By Lothar Englisch & Norbert Szczepanowski
A Data Becker Product Published by: Abacus Software P.O. Box 7211 Grand Rapids, MI 45910
Second Edition, First Printing, September 1985 Printed in the U.S.A.
Copyright (C) 1983,1984 Copyright (C) 1984,1985
DATA BECKER, GmbH Merowingerstr. 30 4000 Dusseldorf W. Germany ABACUS Software, Inc. P.O. Box 7211 Grand Rapids, MI 49510
This book is copyrighted. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, through photocopying, recording, or otherw , ise, without the prior written permission of ABACUS Sofware, Inc.
ISBN 0-916439-01-1
Table of Contents Chapter 1: Programming the VIC-1541
1
1.1 Getting started 1.1.1 After Unpacking 1.1.2 The Disk Operating System 1.1.3 The TEST/DEMO Diskette 1.1.4 Fomatting New Diskettes 1.1.5 Some Facts about a 1541 Diskette 1.1.6 Fundamentals of Disk Techniques
1 1 4 4
1.2 Program Management on Diskette 1.2.1 Save - Storing BASIC Programs 1.2.2 LOAD - Loading BASIC Programs 1.2.3 VERIFY - Checking Stored Programs 1.2.4 SAVE "@: ... " - Replacing Programs 1.2.5 Loading Machine Language Programs 1.2.6 Storing Machine Language Programs
5 5 6
9 9
10 11
12 13 15
1.3 Disk System Commands 1.3.1 Transmitting Commands to the Disk Drive 1.3.2 NEW - Formatting Diskettes 1.3.3 Reading the Error Channel 1.3.4 LOAD"$",8 - Loading the Directory 1.3.5 SCRATCH - Deleting Files 1.3.6 RENAME - Renaming Files 1.3.7 COPY - Copying Files 1.3.8 INITIALIZE - Initializing the Diskette 1.3.9 VALIDATE - "Cleaning Up" the Diskette 1.3.10 ? * - The Wildcards
19 19 20 22 24 26 28 31 32 33 34
1.4 Sequential Data Storage 1.4.1 The Principle 1.4.2 Opening a Sequential Data File 1.4.3 Transferring Data Between Disk and Computer 1.4.4 Adding Data to Sequential Files 1.4.5 Closing a Sequential File 1.4.6 Redirecting the Screen Output
37 37 39 42 46 47 48
1.4.7 1.4.8 1.4.9 1.4.10
Sequential Files as Tables in the Computer Searching Tables Simple Sorting of Tables MAILING LIST MANAGEMENT with Sequential Data Storage 1.4.11 Uses for Sequential Storage
1.5 Relative Data Storage 1.5.1 The Principle 1.5.2 The Advantage over Sequential Storage 1.5.3 Opening a Relative File 1.5.4 Preparing Data for Relative Storage 1.5.5 Transferring Data 1.5.6 Closing a Relative File 1.5.7 Searching Records with the Binary Method 1.5.8 Searching Records with a Separate Index File 1.5.9 Changing Records 1.5.10 Expanding a Relative File 1.5.11 Home Accounting with Relative Data Storage
50 53 57 60 70 71 71 72 73 76 78 83 83 87 90 92 93
1.6 Additional File Structures 1.6.1 Direct Addressing 1.6.2 Indirect Addressing
105 105 107
1. 7 Disk Error Messages and their Causes
109
1.8 Overview of Commands with a Comparison of BASIC 2.0 _ BASIC 4.0 - BASIC 7.0 - DOS 5.1 1.8.1 BASIC 4.0 - BASIC 7.0 Commands 1.8.2 BASIC 7.0 commands
115 116 122
Chapter 2: Advanced Programming
125
2.1 Direct Access of any Block of the Diskette
125
2.2 The Direct Access Commands 2.2.1 The Block-Read Command 2.2.2 The Block-Pointer Command 2.2.3 The Block-Write Command 2.2.4 The Block-Allocate Command
129 129 130 131 133
2.2.5 2.2.6
The Block-Free Command The Block-Execute Command
134 135
2.3 Uses of Direct Access
137
2.4 Accessing the DOS - The Memory Commands 2.4.1 The Memory-Read Command 2.4.2 The Memory-Write Command 2.4.3 The Memory-Execute Command 2.4.4 The User Commands 2.4.5 Additional Possibilities for the User Commands
139 139 141 142 143 145
Chapter 3: Technical Information
147
3.1 TheConstructionoftheVIC-l541 3.1.1 Block Diagram of the Disk Drive 3.1.2 DOS Memory Map - ROM, RAM, I/O 3.1.3 Layout of the I/O Ports (VIA 6522) 3.1.4 The Layout of the Important Memory Locations
147 147 148 149 150
3.2 Operation of the DOS - An Overview 3.2.1 The Disk Controller Routines
155 156
3.3 The Structure of the VIC-1541 Diskette 3.3.1 The BAM of the VIC-1541 3.3.2 The Directory 3.3.3 The Directory Format 3.3.4 The Diskette Recording Process
159 159 161 164 170
3.4 The Organization of Relative Files
175
3.5 DOS 2.6 ROM Listings
181
Chapter 4: Programs and Tips for Using the 1541 Disk Drive
415
4.1 Utility Programs 4.1.1 Displaying all File Parameters 4.1.2 Scratch-protect Files - File Protect 4.1.3 Backup Program - Copying a Diskette
415 415 422 429
4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9
Copying Individual Files to another Diskette Reading the Directory from within a Program Searching for "Hidden" Files Changing the Disk Name and the ID Software Write Protect Invisible Directory
432 434 435 438 441 442
4.2 The Utility Programs on the TESTIDEMO Disk 4.2.1 DOS 5.1 4.2.2 COPY/ALL 4.2.3 DISK ADDR CHANGE 4.2.4 DIR 4.2.5 VIEW BAM 4.2.6 CHECK DISK 4.2. 7 DISPLAY T &S 4.2.8 PERFORMANCE TEST
445 445 446 447 448 448 448 449 449
4.3 BASIC Extensions and Programs for the 1541 4.3.1 Input Strings of Desired Length from the Disk 4.3.2 Easy Preparation of Data Records 4.3.3 Spooling - Printing Directly from the Disk
451 451 456 465
4.4 Overlay Technique and Chaining Machine Language Programs
469
4.5 Merge - Appending BASIC Programs
473
4.6 Disk Monitor for the Commodore 64 and VIC 20
475
4.7 Using "WEDGE" Commands from BASIC Programs
497
Chapter 5: The Larger CBM Disks
499
5.1 IEEE-Bus and Serial Bus
499
5.2 Overview of the "large" CBM Disk Drives
503
ABACUS Software
The Anatomy of the 1541
Chapter 1: Programming the VIC-1541
1.1 Getting Started There it sits, your new Commodore VIC-1S41 disk drive. It's fast and efficient but also intimidating. But have no fear. We will instruct you in the ways of disk programming. The first part of this book gives the beginner an intensive look at the VIC-1S41. At least one example follows each command, thereby explaining its functions and capabilities. You will be surprised how easy the operation of your disk drive can be once you understand the "basics." Beginners probably use the disk drive just to store programs. But a disk drive can be used in many other ways, storing and retrieving data other than programs. This book attempts to uncover these other ways. Experienced programmers should not ignore the first chapter. There may be some sections that may shed light on disk usage. This is especially true concerning relative fIles and data management.
1.1.1 After Unpacking As the proud owner of a new disk drive for your Commodore 64, you probably had just one thought in mind as you left the store where you purchased it: get this "thing" hooked up to the '64 and try it out as soon as possible. When you took the drive out of the box, you noticed that the following parts are included along with it: A power cord A serial connection cable A TESTIDEMO diskette A user's manual Because the VIC-1S41 is not supplied with power from the computer, as is the case with most other computers, it has its own provisions for power. The 120 volt line cord is inserted into the appropriate socket on the back of the device: 1
ABACUS Softwa re
The Anatom y of the 1541
/
Now we need the cable which first looks somewhat like a hi-fi connector cable. It will carrya ll of the data to and from the C64. Connect one of the two ends to the back of the drive:
2
ABACUS Software
The Anatomy of the 1541
It doesn't matter which of the two sockets you use. The two sockets are not provided so that you can connect two '64s to one drive, something which you should never do. The second connection is intended for a printer or for a second drive. If a second drive and a printer are connected, the second drive connects the printer with the computer.
To use the disk drive, the other end of the cable must still be connected to the C64:
When both devices, the disk drive and the C64, are now turned on, you can begin with the first, hopefully successful tests. You will probably want to know if the drive is working properly. To find this out, insert the diskette included with the drive into the drive and close the disk door. Now enter the following command: LOAD "$",8 The RETURN key must be pressed after this string of characters! The disk drive begins to work, indicated by the operating noise and the red LED. A moment later the light is off and you can enter the second command: LIST Don't forget the RETURN key here either. You now see the directory of the TESTIDEMO diskette on the screen. You will learn more about this later.
3
ABACUS Software
1.1.2
The Anatomy of the 1541
The Disk Operating System
The disk drive is a rather complicated device which coordinates mechanical hardware and electronic circuitry to allow the storage of data on the diskette. When the Commodore 64 or VIC-20 needs to read from or write to the disk, it sends commands to the drive along the heavy black cable that connects the drive to the computer. The commands sent by the computer are understood at the disk drive by a built-in program called the Disk Operating System (DOS). The DOS is a lengthy program contained on ROM (Read Only Memory) in the disk drive and it carries out the activities of the drive as commanded by the Commodore 64 or VIC-20. The version of DOS contained in the VIC-lS41 carries the designation CBM DOS V2.6. The Commodore 64 and VIC-20 contain a version of BASIC called COMMODORE BASIC V2.0. Other versions of BASIC (e.g. BASIC 4.0, found in the Commodore 8032) have more advanced disk commands which the VIC-lS41 can also understand. In order to use these advanced disk functions, you have to simulate them in BASIC 2.0. At the end of the chapter is a listing of the BASIC 2.0 commands together with the corresponding BASIC 4.0 commands, as found on the larger Commodore computers.
1.1.3 The TEST/DEMO Diskette The VIC-lS41 disk drive is packaged with a diskette called TESTIDEMO. Some of the programs contained on it cannot be used without adequate knowledge of the way the disk drive works. For now, lay this diskette aside. It will be described in detail later.
4
The Anatomy of the 1541
ABACUS Software
1.1.4
Form atting New Diske ttes
Brand new diskettes must be prepared before using them to store data. Preparing them is called formatting. What does formatting accomplish? Each disk drive mechanism has its ation own special characteristics. A diskette is divided into tracks and inform ). record graph phono a of s is written along each track (similar to the groove r. The number of tracks per diskette varies from one manufacturer to anothe vary. also can which of r Each track is divided into sectors, the numbe During formatting, blank sectors are written to the diskette. A sector is own written to each track-and-sector location and each sector receives its A e. diskett the on n positio "address." This allows the DOS to identify its was sector is also given a code so that the DOS can recognize if this diskette drive disk 541 VIC-1 the for formatted by this type of disk drive. The code and is 2A. The remainder of the sector (called a block) is used to store data accommodates exactly 256 characters. The final purpose of formatting is to construct the directory for the the diskette. The directory is a "table of contents" of the files stored on bility Availa Block the diskette. There is also a special data block (called y in Map or BAM) which indicates if a given block on the diskette is alread the of 18 track on kept are use or available for use. The directory and BAM diskette.
1.1.5 Some Facts about a 1541 Diske tte Diskette: Number of tracks: Sectors per track: Bytes per block: Total number of blocks: Number of free blocks Entries in the directory:
35 17 to 21 (depending on track) 256 683 664 (the directory occupies the remainder) 144 per diskette
5
ABACUS Software
The Anatomy of the 1541
Mechanism: - intelligent peripheral with its own processor and control system - connection to serial bus from CBM 64 or VIC-20, device number 4-15 (8 standard)
1.1.6 Fundamentals of Disk Techniques Diskettes are small round pieces of magnetic film enclosed in square, black jackets. This diskette is prepared for storage by the disk drive. In this process it is divided into tracks and these tracks in tum are divided into sectors. The number of tracks and the number of sectors on a track is dependent on the type of drive. Most use 40 or 80 tracks. The Commodore VIC-1541 drive uses 35 tracks. The following diagram clarifies the division of the disk into tracks and sectors on the 1541:
TRACKS 1-17 (21 SECTORS) TRACKS 18-24 (19 SECTORS) TRACKS 25-30 (18 SECTORS) TRACKS 31-35 (17 SECTORS)
The closer a track is to the center of the disk, the smaller its circumference and the fewer the number of sectors on it. The varying 6
The Anatomy of the 1541
ABACUS Softwa re
tracks is numbe r of sector s is necess ary so that the data density on all of the on the tracks in ing occurr close to equal. Otherw ise the numbe r of errors tracks. outer in ing occurr inside would be greate r than the numbe r of errors is The proced ure by which the diskette is divide d into tracks and sectors has it after until te disket the called "forma tting." Data canno t be placed on been formatted. Let's take a look at the openin gs on the disk jacket:
WRIT E-PRO TECT NOTC H
CENT ER HOLE SLOT FOR READ IWRIT E HEAD
The center hole is placed on the axis of the motor in the drive which h the consta ntly rotates the disk.T he read/write head accesses the disk throug motor read/w rite slot. The head can be positio ned to any track with a second d with called a steppe r motor. Chang ing from track is therefo re accom plishe is disk the the steppe r motor. But how is the desire d sector selecte d? Since be only need head consta ntly turnin g during data access es, the magne tic sector activa ted at the approp riate time. The head recogn izes the addres sed d desire any allows by means of a marke r contai ned on every sector . This sector on the diskette to be accessed. tor The write- protec t notch is optica lly tested by a LED-P hotolT ransis the and it h throug pass Assem bly. If this notch remain s open, the light can es a disk is recogn ized as not being write- protec ted. If one attach
7
ABACUS Software
The Anatomy of the 1541
write-p rotect tab over this notch, the light beam will be broken and the drive recognizes the protec ted diskette. If the tab is attached, every write access to the disk will be rejecte d by the drive. It can no longer be forma tted or written to any other way. It is especi ally impor tant to put write protec t tabs on valuab le disks. All progra m disket tes should be protec ted, and also all data diskettes which will be mainly read from and not written to.
IData tran sfer C64 VIC-15411
8
The Anatomy of the 1541
ABACUS Software
1.2 Progr am Mana geme nt on Diskette The most comm on use of the disk drive is for storing programs. a Storing programs with a disk drive is considerably easier than with of speed the is drive disk the of tage cassette recorder. The greatest advan data transfer to and from the computer. Here's a comparison: Saving a 3 Kbyte program takes: - 75 seconds with the VIC-1530 Datasette - 12 seconds with the VIC-1541 disk drive An additional advantage is that a diskette can store more programs than the the cassette. To load a program, you can consult the directory to see store to you allows drive te casset the selection of programs. Even though time more than one program on a tape, searching for that program is very consuming. Before trying any of the following examples in this chapter, you should remember that the diskette must first be formatted as explained in section 1.3.2 in order to be able to save programs onto it.
1.2.1
SA VE - Storin g BASIC Progr ams Command:
SAVE "name",8
Parameter(s):
"name" - name of the program to be saved
Task:
Save a BASIC program
Example:
SAVE "DEMO 1",8 saves the program with the name "DEM01"
9
ABACUS Software
The Anatomy of the 1541
Perha ps you previo usly owned a datasette on which you stored programs. In this case the commands to save programs onto diskette should look familiar to you. The SAVE command for the disk drive is essent ially the same as for the cassette drive. You need only tell the computer that the program is to be saved onto the disk drive and not on cassette. This is done by adding the device number (usually 8) to the SAVE command. Norma lly the drive is preset to respond to this device number. Now write a small BASIC program and save it with the command: SAVE " TEST " ,8 Type in a NEW command so the program in the computer's memo ry erased. In the following section you will learn how the program can is be retrieved.
1.2.2
LOAD - Loadi ng BASI C Progr ams
Command:
LOAD "name",8
Parameter( s):
"name" - name of the program to be loaded·
Task:
Load a BASIC program
Example:
LOAD "DEMOI",8 loads the program called "DEMO 1"
,,-
As with the SAVE command, this command is similar to the LOAD comm and for the datasette with the addition of the device number. Now load in the previously saved program with: LOAD "TES T",8 10
The Anatomy or the 1541
ABACUS Software
You can check the program by using the LIST command. Any previous It is progra m in memory has now been replaced by the progra m "TEST". us previo the ing replac t possible to load a program into the memory withou called is ry memo in ms progra m in memo ry. Comb ining two progra "merging." An example of merging is presented in section 4.5.
1.2.3
VERI FY - Check ing Store d Progr ams
Command:
VERIFY "name",8
Parameter(s):
"name" - name of the program to be verified
Task:
Compare a program in the computer with a program on the diskette.
Example:
VERIFY "DEMOI",8 compares the program in memory with the program "DEMO 1" on the disk.
is When you have saved a program on disk with the SAVE command, it ut (witho ly proper writtep was m progra often desirable to make sure that the ing error). You can do this with the VERIFY command. It has the follow format:
VERI FY" filena me" ,8 Earlier you saved a progra m with SAVE "TEST" ,8. This progra m shouldt still be in memory. Using VERIFY, check the program in memory agains ter the program stored on diskette. If both programs are identical, the compu responds with OK. To try this out, type a few BASIC lines and then give the following commands: 11
ABACUS Software
The Anatomy of the 1541
SAVE "TES T2",8 VERIFY "TES T2",8 Your compu ter will respon d with OK if it is performing correctly.
1.2.4
SAVE" @: ... " - Replacing Progr ams
If you try to save your small TEST progra m on the disk again, the compu ter will respon d with a FILE EXIST S error and will not compl ete the SAVE . The operat ing system of the VIC-1 541 disk drive does not allow two progra ms to be saved under the same name. This is logical becaus e the compu ter would not be able to distinguish betwe en two progra ms with the same name. Howe ver, you may want to update a progra m on disket te that was previously saved. There are three ways to accomplish this: 1. 2. 3.
Save the program under a different name First erase the old progra m from the disk and save the new one under the old name Use the prefIx @O: in front of the fIle name in the SAVE comm and
This is used as follows:
SA VE" @O:TEST" ,8 If you forget to put the charac ters @O: in front of the filename and try to save a progra m whose name is already contained on the diskette, you get the FILE EXIST S error.
ATTE NTIO N: The developers of the DOS apparently had a bad day when they wrote the part which allows you to replace files by means of the at-sign. There a programming bug somewhere in this section of the DOS. Briefly: is The DOS of the VIC-1541 contains an error which causes the organization of a diskette to be destroyed when a program is saved on a nearly jull disk with 12
The Anatom y of the 1541
ABACUS Softwa re
m the at-sign. This can have the result that when you want to load progra avoid should you "A", progra m "B" will be loaded instead. For this reason rep/acing programs with the at-sign and choose some other method!
For those who would like to know more about saving programs with on the at-sign: The new program may not exceed the remaining free space realize will you file, the disk. If you follow how the DOS overwrites the why: 1.
A free block is designated as the first block of the progra m and its location is stored in the directory entry of the old copy.
2. The new copy of the program is stored in a free area of the diskette. 3. The address of the new files is placed in the address of the old file. 4.
All of the blocks of the old copy are marked as free.
Since the new file is saved onto free blocks on the disk before the the blocks making up the old file are freed, the new file may not exceed the exceed does r; amount of free space on the diskette. If the new progra free space, the save procedure is halted. and It is likely that the error in the DOS lies in step 3 of this procedure that the address of the old file is not put in the proper place.
1.2.5
Loadi ng Mach ine Langu age Progr ams
Machine language programs are handled a little differently from BASIC by programs. A machine language program is transferred to the computer the used, is 1 s addres ary second When using a secondary address of 1. ing program is loaded "absolutely," that is, it is loaded into memory beginn le: examp An file. disk the of bytes two at the address specified in the first
LOAD "MAC HPGR M" ,8,1
13
ABACUS Softwa re
The Anatomy of the 1541
loads the machine language program at an absolute address. For examp the program may be set up to load at the decimal address 49152, and le, started by the comm and "SYS 49152". Should you load a machi is language program without the secondary address, you will most likely ne see the message "SYNTAX ERROR IN .... " if you type RUN. Likewise, trying to LIST the machine language program will display nonsense. Unfortunately, machine language programs are not differentiated from BASIC programs in the directory. Both have the file type PRG. Usually, if typing RUN results in SYNTAX ERROR IN .... , you know that the program is not written in BASIC and should be treated as machine language program. In this case it must be loaded with the comm a LOAD "program" ,8,1. It cannot be started with RUN however! You and must first find the execution address of this program. In a Section 4.1.1 is a program that lists all the file parameters of program. One of the parameters is the load address. This load addres a s usually the initial execution address of the program and can be called is with the comm and SYS load address. You can find the load address of a program with the following program: 10 20 30 40 50 60 70 80
OPEN 1,8,2 , "prog ramn ame,S ,R" GET# l,X$: IF X$="" THEN X$=C HR$(O ) LB=A SC(X$ ) GET# l,X$: IF X$="" THEN X$=C HR$(O ) HB=ASC (X$) CLOSE 1 AD=H B*256 +LB PRINT"LOAD ADDR ESS:" ;AD
The program shows the load address of "programname". Here the program file is opened as a sequential data file. The starting addres s stored as the first two bytes of the file and read using the GET comm is and and appropriately constructed. The first byte is the low byte and the second byte the high byte of the two-byte address. If the function of this progra m is unclear, handling sequential files is clarified in the next sections.
14
---~-
>---------------
The Anatomy of the 1541
ABACUS Softwa re
1.2.6
Storin g Mach ine Langu age Progr ams
a Machi ne language programs are usually written with an assembler or ge langua ne Machi m. progra this machine language monitor and saved using of the programs can also be written from BASIC with the individual bytes ge langua ne machi A ents. statem program stored as decimal values in DATA s: follow ents statem DATA program written in BASIC with the help of 10 20 30 40 50 60 80 90
SA= start ing addr ess EA=e nding addr ess FOR I=SA TO EA READ X POKE I,X NEXT I
DATA DATA
in In this example, the decimal value of the starting address is placed the of values al decim The 20. line line 10 and the ending addres s in individual bytes of the machine language program are typed into the DATA statements of the program, separated by commas. in Naturally, you can save any machine language program that you find and s tediou a er, howev is, This m. progra this book in the form of a BASIC the complicated process. A more elegant and time-saving method is to store the e execut can you way This form. true machine language program in its ing. LOAD after iately immed sion conver icated program without any compl ry: The following program will save such a program that is already in memo 10 20 30 40 50 60 70 80 90
SA= start ing addr ess EA=e nding addr ess OPEN 1,8,1 , "prog ramn ame" HB=I NT(S A/256 ) :LB=S A-HB *256 PRIN T#l,C HR$( LB);C HR$( HB); FOR I=SA TO EA PRIN T#l,C HR$( PEEK (I»; NEXT I CLOSE 1
15
ABACUS Software
The Anatomy of the 1541
This routine assumes that the machine language program is already in the memory of the computer. If a program is already encoded into DATA statements, the following routine can be used to produced a pure machi ne language program: 10 20 30 40 50 60
SA= starti ng addr ess EA=e nding addr ess OPEN 1,8,1 , "prog ramn ame" HB=I NT(S A/256 ) :LB=S A-HB *256 PRIN T#l,C HR$( LB);C HR$( HB); FOR I=SA TO EA
70 READ X
80 PRIN T#l,C HR$( X); 90 NEXT I 100 CLOSE 1 110 DATA . . . . . . . . . . . . . . . . . . . . . . . . . . 120 DATA . . . . . . . . . . . . . . . . . . . . . . . . . .
The addresses and DATA statements must be filled in. The above program writes a machine language program to disk which can later loaded with the command LOAD "programname",8,1. Then the prograbe can be executed with the command SYS (starting address). Machi m ne language programs can also be loaded and executed from a BASIC program. Such a program might have this fonn: 10 IF A=O THEN A=1:L OAD "prog ramna me",8 ,1 20 SYS (star ting addre ss)
The IF command in line 10 is puzzling at first. It must be present becaus after performing a LOAD from within a program, the BASIC interpretere begins executing again at the first line of the new BASIC program. Becau se the machine language program doesn't usually overlay the BASIC progra m in memory, the original BASIC program remains intact and is therefore is re-executed. If you use the routine: 10 LOAD "prog ramna me",8 ,1 20 SYS (star ting addre ss)
the program proceeds to LOAD "programname" again, and the SYS command is never executed. If the variable A is present, the progra m 16
The Anatomy of the 1541
ABACUS Software
branches to line 20 at the end of the fIrst command on line 10. This loader m. can be placed on the diskette together with the machine language prograthe give only need you m, progra ge langua To execute the machine commands:
LOAD "load er" ,8
RUN
ge This has the advantage that the starting address of the machine langua . loader the of SYS the in ed includ is it program need not be known since
17
ABACUS Software
1.3
The Anatomy of the 1541
Disk System Commands
As already mentioned, the VIC-1541 disk drive is similar to the the earlier, larger disk drives of the Commodore family--the CBM 4040, 8050, 8250. They are all intelligent peripheral device with their own processors and operating system. The Disk Operating System (OOS) occupies no space in the memory of the Commodore 64 or VIC-20 and yet offers a flexible set of efficient commands. These commands effectively expand the built-in commands of your Commodore computer. Because the disk drive is an intelligent peripheral, the commands of the DOS can be executed independently of the computer. But because the commands are not found in the version of BASIC supplied in the Commodore 64 or VIC-20, you will have to communicate to the disk using a special method. When the commands are sent to the disk drive, the DOS interprets and carries out the desired task.
1.3.1 Transmitting Commands to the Disk Drive Commands intended for the disk drive are sent over a channel. You can communicate with the disk drive over any of the 15 available channels, but channel 15 is reserved as the command channel. Data transfer over this channel takes place as follows: - open the channel - data transfer - close the channel
(OPEN) (PRINT#) (CLOSE)
In the OPEN command you specify a logical file number (between 1 and 127), the device number of the disk drive (usually 8), and the secondary address (15 for the command channel). You can also send a command to the device as illustrated below:
OPEN lfn,8,15,"command" or OPEN lfn,8,15:PRINT#lfn,"command" 19
ABACUS Software
The Anatomy of the 1541
The number 8 is the device number of the disk drive and the number 15 is the secondary address or channel number. The parameter Ifn is the logica file numbe r which is used in subsequent comm ands (PRINT#, INPUT l #, GET#). It can be a numbe r in the range 1-127. The "command" can either follow the OPEN statement directly, or it can be transferred with a PRINT comm and following the opening. Any number of system commands can # be transmitted until the channel is closed, but must be referenced by the logica l file number used in the OPEN command.
1.3.2
NEW - Form atting Diskettes
Command:
NEW:name,id
Parameter( s):
name - name of the diskette (16 characters max.) id - disk identification (2 characters)
Task:
Format a diskette
Example:
OPEN 15,8,15,"NEW:TEST DISK,NH" formats the disk with the name "TEST DISK" and the ID "NR".
The comm and to forma t a diskette is called NEW and can, as every other command, be abbreviated to its fIrst letter (N). As already mentio ned, the comm and can follow an OPEN comm and or be given in a PRINT # command. The NEW command has the following format:
NEW :diskn ame,i d The parameter diskname may contain up to 16 characters and is stored in the header of the diskette directory. The parameter ID (identifIcation) consis ts of two arbitrary characters, so that the DOS can recognize if a different diskett e 20
ABACUS Software
The Anatomy of the 1541
has been used. Since you can freely choose the ID, this allows you to uniquely identify each diskette. Here is an example for formatting a disk:
OPEN 1,8,15,"NEW:ABCDISK,KL" This command can be abbreviated to:
OPEN 1,8,15,"N:ABCDISK,KL" You need only use the command once--when you first use a brand new diskette. Fonnatting takes about 80 seconds. Fonnatting uses the processor of the 1541 drive while the processor of the computer is not needed; you can continue to work with the computer. To use the command with a PRINT# statement, the following commands must be given:
OPEN 1,8,15 :REM to open the channel PRINT#1,"N:ABCDISK,KL" The number 1 in the PRINT# command is the logical file number corresponding to the OPEN command. Other commands may also be transmitted over this channel after the PRINT# statement. When no more commands are to be transmitted, the channel must be closed. This is accomplished through the use of the CLOSE statement. Give the following command after fonnatting:
CLOSE 1 Now the command channel is closed. The number 1 is again the logical file number of the corresponding OPEN command. NOTE: If no ID is given in the NEW command, the diskette is not formatted, only a new directory is put on and all of the files erased! This is naturally possible only for diskettes which are already fonnatted.
21
ABACUS Software
The Anatomy of the 1541
Once more, the two ways of sending system commands to the disk drive: Opening with simultaneous command transmission:
OPEN 1,8,1 5," ........ .. . CLOS E 1
Opening with subsequent command transmission:
OPEN 1,8,15 PRIN T#I," ....... . .. PRIN T#I," ....... . ..
CLOS E 1 Combination of both ways:
OPEN 1,8,1 5," ........ .. PRIN T#l," ....... . .. PRIN T#I," ....... .. .
CLOS E 1
1.3.3 Readi ng the Error Chann el When the Comm odore 64 or VIC-20 is incorrectly pro(~Tammed, it responds with an error message. Disk comm ands are carrIed out and verified by the processor of the disk drive. Therefore the computer canno directly display error messages that are produced by the disk drive. Errorst are indicated by the flashing red LEi) on the disk drive. In order to 22
ABACUS Software
The Anatomy of the 1541
detennine which error has occurred, the computer must read the error from channel 15. To do this, channel 15 must be OPENed, if this has not already been done. Then the error can be read with the INPUT# command. An error is sent back to the computer in four fields:
Field 1: Field 2: Field 3: Field 4:
Error number Description of the error (string) Track number Sector number
The track and sector infonnation indicate where the error occurred (if these fields are relevant to the command). These four fields of the error message must be read into four variables. You can use an INPUT# statement followed by four variables. An example of reading the error channel:
OPEN 1,8,15 (if not already open) INPUT#I,EN,DE$,TR,SE CLOSE 1 The INPUT# statement must be entered from within a program. It is not legal to issue an INPUT# statement from command mode. 10 OPEN 1,8,15 20 INPUT#l,EN,DE$,TR,SE 30 PRINT EN; DE$; TR; SE (to display the error) 40 CLOSE 1
To understand the operation of this program, first create the following error:
OPEN 1,8,15,"NEW ABCDISK,Tl" CLOSE 1 When you have given these commands, the red LED on the disk drive begins to blink. Did you spot the error? A colon is missing from the command NEW. Now type in the program to read the error channel and enter RUN. The error will appear on the screen:
34 SYNTAX ERROR 0 0
23
ABACUS Software
The Anatomy of the 1541
The 34 is the number of the error, which is explained later. The track and sector fields are 0 because this information is not relevant to this error. If you read the error channel when an error has not occurred, the message:
o OK 0
0
is returned. In any case, if the red LED on the drive blinks, check the syntax of the command, since most errors can be easily recognized. Otherwise, you can simply read the error channel to find the error which the DOS has detected. A detailed description of the error message and their causes follows in section 1.6.
1.3.4 LOAD"$",8 - Loading the Directory The directory is a "table of contents" of the diskette. All the files on the diskette are cataloged here. Be sure to note that loading the directory has a disadvantage: any program previously in memory is overlayed by the directory information, effectively destroying the program. The directory is loaded by typing:
LOAD "$",8 and can be viewed with the LIST command. Try LOADing the directory of the TESTIDEMO diskette that accompanies your disk drive. Insert this diskette into the disk drive and enter LOAD "$",8 to load the directory. Then display the directory by using the LIST command. What appears on the next page should be shown on the screen. A lot of information is kept in the directory. Let's look at the first line, the header of the directory. The number 0 in this line means that this directory is of the diskette in drive O. Other disk drives such as the 4040, contain two disk drives--drive 0 and drive 1. On the 1541 the drive number is always O. Next follows the name and ID of the diskette as set up by formatting. The characters 2A symbolize the disk format. If this format is not 2A then this diskette was not formatted with a 1541 drive.
24
ABACUS Software
o 13 5 4 1
4
11 4 4
6 4
14 9 5 13
The Anatomy of the 1541
"1541 test/ deme, " "how to use" "how part two" "vic-20 wedge" "c-64 wedge" "dos 5.1" "copy/all" "disk addr change" "dir" "view barn" "check disk" "display t&s" "performance test" "sequential file" "random file"
zx 2a prg prg prg prg prg prg prg prg prg prg prg prg prg prg
Next are the individual file names, their lengths in blocks in the first column and the file types in the last column. This diskette contains three main ftle types: PRG These are PROORAM ftles, written in either BASIC or machine language
SEQ Sequential data ftles, explained later REL This is another fonn of data storage, also explained later The length of the files is given in blocks. Each block contains 256 bytes. You can find the approximate size of a program by subtracting 2 bytes from each 256-byte block that the file occupies. Finally, at the end of the directory is the number of free blocks remaining on the disk. When you add the lengths of the files and the number of free blocks, the result is the total number of available blocks on a diskette (664).
25
ABACUS Software
The Anatomy of the 1541
If you own a printer, this directory can be printed as you would print a program listing. Use the following commands:
OPEN 1,4 CMDI LIST PRINT#1 CLOSE 1
open the printer the printer is now linked to the screen the directory will be printed send a RETURN to the printer close the printer again
It is assumed that the directory is already loaded with the LOAD"$",8 command before these commands are executed. By inserting a wildcard when loading the directory, you can cause only part of the directory to be loaded, such as only the programs. This is explained in section 1.3.10.
1.3.5
SCRATCH - Deleting Files
Command:
SCRATCH:namel,name2,name,3 ...
Parameter(s):
name 1 - name' of the file to be deleted (multiple files separated by commas)
Task:
Delete a file from the disk.
Example:
OPEN 1,8,15,"SCRATCH:DEM01" deletes the program with the name DEMO 1.
Sometimes an unneeded file must be removed from the diskette. The SCRA TCH command is provided for doing so. Before using this command, you must be sure that the name given in the SCRATCH command corresponds with the file to be deleted. An unintentionally deleted file can ruin many hours or even days of work, so be careful before using this command. 26
ABACUS Software
Anatomy of the 1541
To delete a file, the following format should be used:
PRINT#ifn, " SCRATCH: filenamel, filename2, ... " More than one file can be deleted by using a single command. But remember that only 40 characters at a time can be sent over the transmission channel to the disk drive. For example, to erase a file with the name TEST, the following commands are used:
OPEN l,8,l5,"S:TEST" CLOSE 1 If channel 15 is already open, only the PRINT# command is required:
PRINT#l," S:TEST" It is possible to delete the entire contents of a diskette. This is discussed in section 1.3.10, the wildcard character (*):
PRINT#l,"S:*" But be very careful! Make sure that you do not need any of the files on the diskette before using this command. After completing the operation the error channel transfers the message:
01 FILES SCRATCHED nn 00 where nn is the number of deleted files. This message can be read with the routine given in section 1.3.3.
27
ABACUS Software
1.3.6
Anatomy of the 1541
RENAME - Renaming Files
Command:
RENAME:new=old
Parameter(s):
new - new program name old - previous program name
Task:
Change the name of files on the disk.
Example:
OPEN 1,8,15,"RENAME:DEM02=DEMOI" changes the name of "DEMO 1" to "DEM02".
You can also change the name of a file on the diskette. The command RENAME is provided for this purpose. It has the following format:
RENAME:newname=oldname For example, if you want to change the name of the file from TEST to PEST you would use the following commands:
OPEN 1,8,15," R:PEST=TEST" CLOSE 1 or
OPEN 1,8,15 PRINT#I," R:PEST=TEST" CLOSE 1 Note that you cannot rename a file until it is CLOSEd. This command offers you a safe way of updating programs. Assume that we want to load the program" SUPERPROG" from disk, edit it, and then save the new version. The following procedure has proven itself in practice:
28
ABACUS Software
Anatomy of the 1541
1. Load the old version of the program
LOAD "SUPERPROG",8 2. Run or edit the program 3. Save the prof;!Iam with a dummy name
SA VE "SUPERPROG.NEW",8 4. Verify the save
VERIFY "SUPERPROG.NEW",8 5. Delete the old version of the prof;!Iam
OPEN 1,8,15,"S:SUPERPROG" 6. Rename the new version
PRINT#l,"R:SUPERPROG=SUPERPROG.NEW" 7. Close the command channel
CLOSE 1 Another, not quite so safe method, is the following: 1. Load the old version of the program
LOAD "SUPERPROG",8
29
ABACUS Software
Anatomy of the 1541
2. Run or edit the pro~ram 3. Delete the old version of the pro~ram
OPEN 1,8,15 ,"S:S UPER PROG " 4. Close the command channel
CLOSE 1 5. Save the pr01~ram
SAVE "SUP ERPR OG", 8 6. Verify the save
VERIFY "SUP ERPR OG", 8 Step 5 may come before step. 4. Note the following safety hierarchy in replacing one version of a program with another: Certainty factor
Method
Very high
Load old - change old - save new - verify new - delete old - rename new
High
Load old - change old - delete old - save new - verify new
"Luck"
Save with at-sign
When developing a program, it is advisable to save it from time to time. A power -outag e could have disastrous results. It is recom mende d that you
30
ABACUS Software
Anatomy of the 1541
always save the program under a new name (such as TESTI, TEST2, TEST3, ... ) and then delete all of the old versions of the program when you are done. This methcx.l saves time but is still safe.
1.3.7
COPY - Copying Files
Command:
COPY :new=old 1,old2,old3, ...
Parameter(s):
new - new file old x - files to copied over
Task:
Chains separate files into one.
Example:
OPEN 1,8, I5,"COPY :DATA=DATI ,DA T2,DAT3" combines the files DATI, DAT2, and DAT3 into one file called "DATA".
Using this command, a file can by copied on a diskette. Several different sequential files can be used to create a new file. If, for example, you have a data record for each month of your household expenses and they have the names EXP.Ol, EXP.02, etc. you can combine them into quarters (EXP.QI for example) with this command. The COpy command has the format:
COPY :newfile=oldfiIe l,oldfile2, ... So, the named data records can be combined as follows:
OPEN 1,8,15," C:EXP.Ql=EXP.Ol,EXP.02,EXP.03" CLOSE 1 This method of combining data records cannot be used for programs. Only a single program can be copied on the diskette. Also the name of the new file must not already exist on the diskette. 31
ABACUS Software
Anatomy of the 1541
The COpy command is rarely used. This is because copying files onto the same diskette usually makes no sense. The only sensible use of the command is to combine several sequential or user files into a single file. Copying files from one diskette to another diskette is much more sensible. This is indispensible for data security. If you own two disk drives, you can assign the device number 9 to one of them and use the program COPY/ALL to copy files from one to the other. This program is found on the TESTIDEMO diskette. We have also thought of those of you who have only one disk drive. A utility program is included in section 4.1 to allow you to copy individual files and even the entire diskette.
1.3.8
INITIALIZE - Initializing the Diskette
Command:
INITIALIZE
Parameter(s):
none
Task:
Resets the BAM
Example:
OPEN 1,8,15,"INITIALIZE" or OPEN 1,8,15,"1"
The DOS requires that a BAM (Block Allocation Map) be present on each disk. The BAM is a layout of the usage of the blocks on each diskette. It marks each block on the diskette as free for use or allocated (already in use). If you change diskettes in the drive and the new diskette has the same ID as the old diskette, the DOS will not recognize the fact that you have changed diskettes. The BAM of the new diskette will be different, but the DOS will still be working with the old BAM. 32
Anatomy of the 1541
ABACUS Softwa re
t Therefore, each diskette should be given a unique ID when you forma the force can You ID. nt differe a e diskett each it. It is a good practice to give disk drive to read the BAM of a new diskette by issuing the INITIALIZE command. This command has the following format:
PRIN T#lfn ," INITI ALIZ E" or shortened to
PRIN T#lfn ," I" Example:
OPEN 1,8,15,"1" CLOSE 1 ly If you change diskettes and also change data records, then we strong the ing chang after and comm LIZE INITIA the recom mend that you use diskettes, to be safe.
1.3.9 VAL IDAT E· "Clea ning Up" the Diskette Command:
VALIDA1E
Parameter( s):
none
Task:
Free all allocated blocks which do not belong to any file.
Example:
OPEN 1,8,15,"VALIDATE"
The VALIDA TE comm and frees all allocated blocks that are not and assigned to normally CLOSEd files. For example, if you OPEN a file
33
ABACUS Softwa re
Anatomy of the 1541
transfer data to that file, but forget to CLOS E it, the V ALID ATE comm and can be used to free the data blocks that were written to. If you use the direct access comm ands, be sure to allocate them (using the BLOC K-ALL OCAT E command) or the VALID ATE comm and will free them again. The comm and has an additio nal function: If a file is delete d using the SCRA TCH comm and, the file type in the first byte of the file entry is set to O. It no longer appear s in the directory. If you now change this byte back to its old file type with the DOS monit or (descr ibed later) or other direct access comm ands, V ALID A TE will restore the file. If it has not been overw ritten, it will be the same as before the SCRA TCH comm and. The comm and has the following format:
PRIN T#lfn ," VALID A TE" or the shorte r form
PRIN T#lfn ," V" An example:
OPEN 1,8,15 ,"V" CLOS E 1 If you have a disket te such that the sum of the file length s plus numbe r of free blocks does not equal the total numbe r availa ble (664), the use the VALID ATE comm and to restore it.
Anoth er examp le: If you try to store a progra m or data record that uses more than the numbe r of free blocks, the DOS will give the error DISK FULL . If the disk had shown some blocks free before, the numbe r is now zero. The VALID ATE comm and will restore the original free blocks.
1.3.10 ?
* - The
Wildc ards
There are two wildca rd charac ters--t he asteris k (*) and the questi on mark (?). The asteris k at a given place in the filenam e symbo lizes that the first or all files on the disket te which begin with the charac ters before the asterisk are relevant. An example:
34
ABACUS Software
Anatomy of the 1541
LOAD"TEST*" ,8 This command loads the first program that begins with the first four letters "TEST". The command:
LOAD" *" ,8 loads the first program on the diskette because there are no characters in front of the asterisk. The asterisk in the SCRATCH command has a different effect. If used in the SCRATCH command, not only the first file will be deleted, but all files. For instance, the command:
OPEN 1,8,15,"S:TEST*" CLOSE 1 erases all files beginning with the the letters "TEST". This must be taken into account! Loading the directory with an asterisk can also select certain files. An example:
LOAD"$A *",8 loads only the directory of the files that begin with the letter" A". The DOS offers an additional use of the asterisk that has not been mentioned yet. It can also select file types if the asterisk is followed by the first letter of the desired file type. Here is a summary:
*=S *=P *=R *=U
selects only sequential files selects program files selects relative files selects user-files
For example, the command:
LOAD "$*=P",8 causes only the directory entries of programs (PRO) to be loaded and shown when you type LIST. This can also be used with the SCRATCH command to delete all sequential files, for instance. Here is the command:
35
ABACUS Software
Anatomy of the 1541
OPEN 1,8,15," S:*=S" CLOSE 1 With the question mark, certain characters of a fIlename can be declared "not relevant." To illustrate the function of the question mark, here are two examples of shortened fIlenames and their effects: A?????
- refers to a six-letter fIlename, the fIrst character of which is A
????TEST
- refers to an eight-character filename, the last four letters of which are TEST
A combination of asterisks and question marks is allowed. You should notice, however, that an asterisk followed by question marks has no meaning. Two examples of combinations of asterisks and question marks: ???? *
- refers to all flle names that have four characters before a period TEST.??* - refers to all file names having at least 7characters, of which the fIrst five are"TEST." TEST-??O 1*=S - refers to all sequential files whose names have at least nine characters, the first five being TEST- and the eighth and ninth being 01
36
Anatomy of the 1541
ABACUS Softwa re
1.4
Sequential Data Storage
A disk drive can be used for more than just storing programs. If you need a have written a progra m that manages a large quantity of data, you it is but , fastest the not is fast way of organizing it. Sequential data storage to rable compa is d the easies t metho d of manag ing data. This metho as m progra a in ined sequential storage on a cassette, which can be mainta follows: 1. Load the program 2. Read the entire data file into the memory of the computer 3. Work with the data in memory (change, delete, combine) 4. Write the new fIle on an external medium (cassette, diskette) 5. Exit the program The maxim um numb er of data items that the progra m can handle item depends on the size of the computer's memory because a single data end, that To e. diskett cannot be changed or erased directly on the cassette or ten rewrit then and the entire set of data items must be read in, changed, drive disk a on faster again. Readi ng and rewriting the data occurs much than on cassette. data It is worth mentioning that programs which work with sequential the Only disk. with work on casset tes can be easily modif ied to d. corresponding OPEN commands need be change
1.4.1
The Princ iple
r A sequential data file consists of several data records that are furthe tes illustra and file s addres and name a is ing divided into fields. The follow ses the principle of sequen tial data storage. Individual names and addres fields l severa of ts consis record A file. this of s compr ise the data record like (last name, first name, etc.). The structure of the file looks something this:
37
ABACUS Software
Anatomy of the 1541
FILE Record 1 Record 2 Record 3 Record 4 Record 5
The data records of a file are stored one after another (sequentially) as are the the fields within each record. The fields and records may be of any length. For example, field 1 of record 1 may be longer than field 1 of record 2. This is possible because the fields are separated from each other by a special character (the RETURN character), which is generated by the PRINT# statement. When read back into the computer by the INPUT# statement, the RETURN character is recognized as a field separator. Each field is associated with a variable when written with a PRINT# statement or read with an INPUT# statement. How does the computer know, when reading the data, where each field ends? Each field ends with a RETURN character. The RETURN character has the decimal ASCII value 13. An example of a telephone directory file illustrates this. Our telephone directory file has three fields:
FIELD 1: FIELD 2: FIELD 3:
LAST NAME FIRST NAME TELEPHONE EXTENSION
38
Anatomy of the 1541
ABACUS Software
FILE Record Record 2 Record 3
ted You can see that the fields are of different lengths and are all separa written y aticall autom by a RETU RN character. This RETU RN character is ent after the data field by a PRINT # statement, provided the PRINT # statem ter). charac RN is not followed by a semicolon (which suppresses the RETU T# These data items are assign ed to the variab les with an INPU next the read to order statement. After that, another INPUT # must follow in writing field, and so on. The following sections explain the fundamentals of programs using sequential data storage.
1.4.2 Open ing a Seque ntial Data File To create a sequen tial data file, you must first OPEN the file. When opening a file to be written to, the following is carried out:
1. The disket te is check ed to see if an existing file has the same name. If so, the error message FILE EXISTS is given by the DOS. 2. The file entry in the directo ry is written. In the file type it is noted that this file is not yet CLOSEd. This appears in a directory listing with an asterisk which preceeds the file type. 3. A free block is found, into which the first data items are written. The address (track and sector) of this free block is stored in the file entry of the directory. 39
ABACUS Software
Anatomy of the 1541
4. The number of blocks in the file is set to 0, because no blocks of the file have been written yet. The OPEN command specifies for what purpose (mode) the file is to used (reading or writing). The format of the OPEN command looks be like this:
OPEN Ifn,8, sa," filena me,fi letype ,mode " When the logical file number (lfn) is between 1 and 127, a PRINT statement sends a RETURN character to the file after each variable. If # logical file number is greater than 127 (128-255), the PRINT# statem the ent sends an additi onalli nefeed after each RETURN. This is necessary for printe rs that do not provid e an automatic linefeed after a RETU RN character, for example. The secondary address (sa) can be a value between 2 and 14. The secondary address indicates the channel over which the compu ter is transfer data to and from the disk drive. Secondary addresses 0 and 1 to are reserved by the DOS for saving and loading programs. Secondary addres 15 is designated as the command and error channel. Should several files s open at once, they must all use different secondary addresses, as only be file can use a channel. If, however, a file is opened with the secondone ary address of a previously opened file, the previous file is closed. A maximum of 3 channels can be opened with the VIC-1541 at a When utilizing relative data files, the DOS requires 2 channels pertime. file. Therefore, the following maximum combinations are possible:
- 1 relative and 1 sequential file, or - 3 seque ntial files When specif ying the filename to be written to (in the OPEN command), you must be sure that the file name does not already exist on the diskette. If a file that already exists is to be to opened for writing, the file must first be deleted. The @-sign method should not be used. For examp le:
OPEN 1,8,15 ,"S:A DDRE SSES ":CLO SE 1 OPEN 1,8,2, " ADDR ESSE S,S,W "
40
ABACUS Software
Anatomy of the 1541
The file type must be given when the file is opened. The file type may be shortened to one of following:
S U P R
- sequential file - user file - program - relative file
User files are sequential files that are listed in the directory with the file type USR.They are not data files in the true sense. This file type is usually used when output that normally goes to the screen (BASIC listing, directory) is sent to the disk. In section 1.4.6 you find a description of this technique. The last parameter (mode) establishes how the channel will used. There are four possibilities:
W R A M
Write a file (WRITE - section 1.4.3) Read a file (READ - section 1.4.4) Add to a sequential file (APPEND - section 1.4.4) read a file that has not been closed (It discovered" by us in the DOS listing and explained in Section 1.4.5)
Now open a sequential file with the name SEQU.TEST for writing:
OPEN 1,8,2,"SEQU.TEST,S,W" If you now load the directory with LOAD" $",8 and then LIST it, you see this file listed with an asterisk before the file type:
o
SEQU.TEST
*SEQ
But you are no longer allowed to close this file! After a file is OPENed and data written to it, it must be closed before the directory is loaded! The command/error channel 15 may be opened while a file is open, but when channe115 is closed, all other channels are closed as well. You must take note of this.
41
ABACUS Software
Anatomy of the 1541
Now some examples of the OPEN command: OPEN 1,8,2," SEQU. TEST,S,R"
-
open a sequential fIle for reading - open a user fIle for writing - open a program fIle for reading - open a sequential fIle for appending data - open the unclosed customer fIle for reading
OPEN 2,8,3,"SEQU.TEST,U,W" OPEN 3,8,4,"TEST,P,R" OPEN 4,8,5,"SEQU.TEST,S,A" OPEN 5,8,6,"CSTMRS.1983,S,M"
1.4.3 Transferring Data Between Disk and Computer After opening a file for writing, you transfer data to be stored to the diskette with the PRINT# statement. This statement transmits an additional RETURN that is required for separating data. In the following example, a file is OPENed, data written to it, and the file is CLOSEd again. PRINT# can also be used as a direct command, that is, outside of the program, so the following commands can be typed one after the other and executed. Now open a file with the name "TEST':
OPEN 1,8,2,"TEST,S,W" You should notice that the red LED on the disk drive is lit. It signals the fact that a file was OPENed. You can now write to the file named TEST. Here is how we would write a name and address record consisting of 4 fields:
PRINT#l," SAM" PRINT#l," HARRIS" PRINT#1,"2001 MAIN STREET" PRINT#l," ANYTOWN" Now these data items have been written to the file, so we close the file with CLOSE 1. The red LED should go out. In order to read this data again, you must open the file in the read mode (R). Because the INPUT# statement cannot be used in the direct mode, a small program must be written: 42
ABACUS Software
Anatomy of the 1541
10 20 30 40 50
OPEN 1,8,2, "TEST,S,R" INPUT#l,NF$ INPUT#l,LN$ INPUT#l,ST$ INPUT#l,CT$ 60 CLOSE 1 70 PRINT"FIRST NAME: " ;NF$ 80 PRINT"LAST NAME: " ; LN$ 90 PRINT"STREET: ";ST$ H;CT$ 100 PRINT"CITY:
The program is simple to explain: Line 10
The file TEST is opened for reading
Lines 20-50
The data are read in the same order as they were written. Variables are used so that the data can be printed later.
Line 60
The file is closed.
Lines 70-100 The data are printed out on the screen. When you enter this program and type RUN, the data will appear on the screen as written earlier:
FIRST NAME: LAST NAME: STREET: CITY:
SAM HARRIS 2001 MAIN STREET ANYTOWN
Four INPUT# statements were used to read the data because the name and address record is composed of four fields. But when a record is written that has, say, 20 fields, it is very time-consuming to type out 20 INPUT# statements. A loop can make this much simpler. This is obvious in this example:
43
ABACUS Software
Anatomy of the 1541
10 20 30 40 50 60
OPEN 1,8,2 ,"TE ST,S ,R" FOR I=l TO 4 INPU T#l,D $(I) NEXT I CLOSE 1 PRIN T"FIR ST NAME: n;D$ (l) 70 PRINT "LAST NAME: ";D$( 2) 80 PRINT "STRE ET: ";D$( 3) 90 PRINT"CIT~: n;D$( 4)
Here, instead of four separate string variables, an array with index 1-4 is used. It should be noted that in BASIC 2.0, the array must be dimensioned with a DIM statement if an index higher than 10 is used. Should we want to read in 20 fields, the statement DIM D$(20) must be gi ven before any are read. There are still more ways of shortening input and output of data. With the INPUT statement for keyboard input, several variables can be given in one line, separated by commas. For example:
INPU T NF$,L N$,TE With this statement, three variables must be entered, such as:
NICH OLAS ,MUL LER, 7465 The read data can be printed on the screen with:
PRIN T NF$,L N$,TE In this manner, sequential data can be written and later read back again. The only difference is that the string variables containing the data in be written must be separated by commas enclosed in quotes. For examp to if you wish to write the previous variables to a file, the PRINT# statem le, ent command must changed as follows:
PRIN T#l,N F$" ,"LN$ " ,liTE Numeric variables need only be separated with a comma from the other variables. To read the data, use the command:
44
Anatomy of the 1541
ABACUS Softwa re
INPU T#l,N F$,LN $, TE Becau se the maxim um numbe r of characters read by an INPU T# ally statement may not exceed 88, this method of reading is only margin nt differe a long, ters charac useful. If a field in a record is more than 88 each statement must be used. This is the GET# statement, which reads of record a read to want individual character, one at a time. Suppose you string a in placed be can which a field is 100 characters long. This record variable with the following routine: 10 20 30 40 50 60 70 80
OPEN 1, 8, . . . . . . . . . . . . . . D$=" " FOR I=l TO 100 GET# l,X$ D$=D$+X$ NEXT I GET# l,X$ CLOSE 1
At the end of this program, the string variable D$ will contain the 100 DOS characters of the data field. After opening a sequential data file, the We read. be to ter establishes a pointer that always points to next charac assume that the data was written with a PRINT# statement without a trailing After semicolon, so that a RETURN was written at the end of the data item. The RN. RETU this to reading the first 100 characters, the pointer points of end the at found RN next GET# in line 70 is necessary to read the RETU the not and field next the the field. Then the next GET# statement can read RETURN. In the above example, we used data records with a constant length of of 100 characters. According to the rules of sequential access, the length only can ent statem # INPUT the Since nt. data records need not be consta to read a maxim um of 88 characters, we will use the GET# statement this: recognize the RETURN as the end of a field. Such a routine looks like 10 20 30 40 50 60
OPEN 1,8, . . . . . . . . . . . . . . . . . . . . . . S$="" GET# l,X$ IF X$=C HR$(1 3) THEN 80 S$=S$ +X$ IF ST 64 THEN 30
45
ABACUS Software
Anatomy of the 1541
70 CLOSE l:END 80 PRINT S$ 90 GOTO 20
Here a file with variable record length is read and printed on the screen. Naturally, you can use the data in other ways instead of printing it on the screen. To avoid the problem of reading data records of more than 88 characters, divide the record into several parts, which you can combine after reading them.
1.4.4
Adding Data to Sequential Files
If you want to add data to a sequential file, you have to read the entire file into memory, add the data, and write the new file back to the diskette again. This is a very time-consuming process. For this reason, the DOS offers an easier alternative to add to a sequential data file without reading the entire file. This is made possible through the OPEN mode A (Append). If you have a sequential data file, as in the previous section, you can add data to it by selecting the A mode in the OPEN command. An example follows. Give the following commands:
OPEN 1,8,2,"TEST2,S,W" PRINT#l,"lst DATA RECORD" CLOSE 1 Now you have a sequential data file containing one data record. This file can be expanded with two more records as follows:
OPEN 1,8,2,"TEST2,S,A" PRINT#1,"2nd DATA RECORD" PRINT#1,"3rd DATA RECORD" CLOSE 1
46
ABACUS Software
Anatomy of the 1541
Now the file TEST2 has three data records. You can check this with the following program: 100 110 120 130 140 150
OPEN 1,8,2, "TEST2,S,R" FOR I=l TO 3 INPUT#l,DR$ PRINT DR$ NEXT I CLOSE 1
After the program starts, the data record is read and printed on the screen. You can see that the append A mode makes it quick and easy to expand a sequential data fIle.
1.4.5
Closing a Sequential File
OPENed data files can be closed with the CLOSE command. This command has the format:
CLOSE Ifn The parameter lfn is the logical file number of the file that was used in the OPEN statement. Should several files need to be closed a CLOSE statement must be given for each one. When the last file is closed, the red LED on the drive goes out. As you already know, data are sent to the disk drive over a channel. This channel uses memory inside the disk (called a buffer) in which the data transmitted by the computer is stored. When this buffer is full, its contents are written to the diskette. When the file is closed, any data still in the buffer is written to the diskette. An unclosed file is incomplete and is also not recognized by the DOS as a properly closed file. The DOS allows no read access in the R (Read) mode and responds WRITE FILE OPEN when trying to read an unclosed file.
47
ABACUS Softwa re
Anatomy of the 1541
This could be a proble m if the DOS did not allow any read access to a file. For this reason, the DOS offers the M mode. A file that is marke d as an improperly closed file can be read in this mode. It is logical to then write these records to a second file which can then be properly closed. In this way one can "rescue" a file. The following program will transfer an improperly closed file (origin al me) to a correctly closed me (destination file): 100 110 120 130 140 150 160 170 180 190
INPUT "ORIG INAL FILE NAME";S$ INPUT"DESTINATION FILE NAME";D$ OPEN 1,8,2 ,S$+ ",S,M " OPEN 2,8,3 ,D$+ ",S,W " INPU T#l,X $ PRIN T#2,X $ IF ST 64 THEN 140 CLOSE l:CLO SE 2 OPEN 1,8,1 5,"S: "+S$ CLOSE 1
At the compl etion of the progra m, the unnee ded origin al file is delete d (scratched) .
1.4.6 Redir ecting the Scree n Outpu t Any output appearing on the video screen (PRINT, LIST, etc) can be redirected to a sequential data file. This is accomplished through the CMD command, which has the following format:
CMD Ifn For this to occur, a file of type USR must be opened. To transfer a BASIC progra m listing , for instan ce, as a sequen tial file on disket te, use the following commands:
OPEN 1,8,2, "TES T.LIS T,U,W " CMD 1 LIST 48
ABACUS Software
Anatomy of the 1541
CLOSE 1 The command CLOSE 1 causes further output to be sent to the screen. Storing a program as a sequential file on disk is very useful, if, for example, you would like to read a program with a word processor to edit it. It is assumed that the word processor in this case reads data stored in ASCII code. This is how the listings in this book were transferred from a Commodore 64 to a Commodore 8032 for final printing. In order to print this file on the screen again, you need the following routine: 10 20 30 40 50
OPEN 1,8,2, "TEST.LIST,U,R" GET#l,X$ PRINT X$ IF ST64 THEN 20 CLOSE 1
This routine is a loop that reads every character (byte) of the file and displays it on the screen. The end of the file is signalled by the status variable (ST) which is set to 64 at the end of the file. To send a sequential fIle to the printer, use the following program: 10 20 30 40 50 60
OPEN 1,8,2,"TEST.LIST,U,R" OPEN 2,4 GET#l,X$ PRINT#2,X$ IF ST64 THEN 30 CLOSE 1
Here it is ao;sumed that the printer is connected as device address 4.
49
ABACUS Software
Anatomy of the 1541
1.4.7 Sequential Files as Tables in the Computer Sequential data files must reside completely in the computer for data management. Most of the time, a two dimensional table can be used. This table is also called an array or matrix, because a data element can be addressed through the input of two coordinates. To this end, you use a two dimensional variable, which must be reserved with a DIM statement. The first dimension corresponds to the data record, the second dimension to the field inside the record. This diagram shows an example of a table: Field 1
Field 2
Field 3
Table
Record 1
in the
Record 2
Computer
Record 3 Record 4 Record 5 Record 6
This table is a file composed of six records which have three fields each. The variable D$ is reserved with DIM D$(6,3). To read a sequential file as a table, it is necessary to create such a file with, for example, six records with three fields each. For this purpose, use the following program: 100 110 120 130 140 150 160 170 180 190
OPEN 1,8,2, "TABFILE,S,W" FOR X=l TO 6 PRINT CHR$(147) PRINT"RECORD ";X PRINT"---------" FOR Y=l TO 3 PRINT"FIELD n;y;n: "; INPUT X$ PRINT#l,X$ NEXT Y
50
ABACUS Software
Anatomy of the 1541
200 NEXT X 210 CLOSE 1
Two nested loops are used here, whose variables are numbered with the record and field. Enter six data records. When the program is done, these records will be contained on the diskette with the filename of T ABFILE. A tip: save this program with SAVE"TABPROG",8 so you can use it later. This file can now be loaded into the computer as a table. Two nested loops indexed for the table are necessary: 100 110 120 130 140 150 160 170
OPEN 1,8,2,"TABFILE.SEQ,S,R" DIM D$(6,3) FOR X=l TO 6 FOR Y=l TO 3 INPUT#l,D$(X,Y) NEXT Y NEXT X CLOSE 1
This program places data into the table. You can check this with PRINT statements to see if the data has been stored in the right place. Because each field can be addressed with indices, you can give a command like PRINT D$(l,2) to see the second field of record one. It is meaningful to be able to display the fields of a given record. Use the following routine for this purpose, after you have saved the previous program: 100 110 120 130 140
INPUT" RECORD NUMBER: "; X PRINT"------------------" PRINT"FIELD 1: ";D$(X,l) PRINT"FIELD 2: ";D$(X,2) PRINT"FIELD 3: ";D$(X,3)
Notice that the first index (the record number) after the input is used as the variable in the field output. The second index (field number) is then constant. This table can now be altered as desired. Add the following lines to the preceeding program:
51
ABACUS Software
160 170 180 190 200 210 220 230 240
Anatomy of the 1541
PRINT"------------------lf INPUT"FIELD TO CHANGE:";Y INPUT"NEW CONTENTS: ";D$(X,Y) PRINT"OK" PRINT"FURTHER CHANGES (YIN)?" GET X$:IF X$="" THEN 210 IF X$="Y" THEN 100 IF X$="N" THEN END GOTO 210
Here the number of the field to be changed is used as the second index, which is adjacent to the index of the record whose element is being changed. This modified table must now be written to the diskette again. You can use the following routine. Don't forget to save the previous edit program first! 100 105 110 120 130 140 150 160
OPEN 1,8, 15, "S:TABFILE,S,W" OPEN 1,8,2, "TABFILE,S,W" FOR X=l TO 6 FOR Y=l TO 3 PRINT#l,D$(X,Y) NEXT Y NEXT X CLOSE 1
This routine also is relatively short because of the use of nested loops. The old file is erased before the new file is stored. This is done in line 100. Accessing data through the use of the table is very fast. The access time is independent of the size. The size of the table and therefore the quantity of data is dependent on the memory capacity of the computer, however. The large storage area of the Commodore 64 is excellent for table management. If you write a data management program that occupies 8K bytes, then 30K bytes still remain for storing data. If you consider that storing a name and address record of about 80 characters, you can still store 384 records in memory! And this with an access time that cannot be surpassed by refined data management techniques (indexed sequential, relative). But with larger quantities of riata, sequential storage is no longer feasible.
52
ABACUS Software
1.4.8
Anatomy of the 1541
Searching Tables
As mentioned in the table processing section, each data record of a table can be indexed. Because the table is two dimensional, the fIrst index selects the data record. If a record of the table is to be changed or accessed, the operator must know the record number. The record number can be a part or customer number. There are files, however, for which there is no suitable method of numbering. In such files, the number of the record must be found through a search of all the records. Here is a practical example: First of all, create a data file with the following program. Names and telephone numbers are saved in the example: 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240
OPEN 1,8,2, "TELEDAT,S,W" PRINT CHR$(147) INPUT"LAST NAME : " ; LN$ INPUT"FIRST NAME :";FN$ INPUT"AREA CODE :";AC$ INPUT"NUMBER :" ;NU$ PRINT"INFORMATION CORRECT (YIN)?" GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 170 IF X$="N" THEN 110 PRINT#l,LN$", "FN$","AC$", "NU$ PRINT"MORE INPUT (YIN)?" GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 200 IF X$="N" THEN 240 GOTO 110 CLOSE 1
Program Documentation: Line 100
The sequential ftle "TELEDAT' is opened for writing
Line 110
The screen is cleared
Lines 120-150
The four fields are entered from the keyboard
Lines 160-180
If the data are not correct, they can be entered again
53
ABACUS Software
Anatomy of the 1541
Line 190
The four fields are written to disk
Lines 200-220
Here the execution of the program can be ended
Line 230
Input will be continued
Line 240
The file opened in line 100 is closed
Type this program in, RUN it, and enter some data. Save the the program on diskette so you can combine it with other routines later if you like. In the last section of this chapter is a complete program for managing your telephone numbers. If you have entered some data, you would probably like to find a telephone number. To do so, you could print the entire file on the screen or printer and find it yourself. This is, however, a wasteful method, especially if you have entered many records.
The search for the telephone number corresponding to a given name can be performed by the computer. It runs through the whole list, looking for the desired name. Once found, it gives you the complete record which contains that name. The following routine accomplishes this: 100 OPEN l,8,2,"TE~EDAT,S,R" 110 DIM D$(100,4):X=1 120 INPUT#l,D$(X,l),D$(X,2),D$(X,3), D$(X,4) 130 IF ST64 THEN X=X+1:GOTO 120 140 CLOSE 1 150 PRINT CHR$(147) 160 PRINT"DESIRED NAME: ";N$ 170 FOR I=l TO X 180 ID D$(I,l)=N$ THEN 210 190 NEXT I 200 PRINT"NAME NOT FOUND! ":GOTO 280 210 PRINT"NAME FOUND:" 220 PRINT"-----------" 230 PRINT"LAST NAME: ";D$(I,l) 240 PRINT"FIRST NAME: ";D$(I,2) 250 PRINT"AREA CODE: ";D$(I,3) 260 PRINT"NUMBER: ";D$ (I, 4)
54
ABACUS Software
Anatomy of the 1541
270 PRINT"-----------" 280 PRINT"MORE (YIN)?" 290 GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 290 300 IF X$="Y" THEN 150 310 PRINT"PROGRAM DONE" : END
Program Documentation Line 100
The sequential file "TELEDAT" is opened for reading
Line 110
The table is dimensioned for 100 records and the index is set to one
Line 120
The data records are read into the table
Line 130
The status variable ST is checked for end of file (indicated by a value of 64). If the end has not been reached, the index is incremented and a new record is read.
Line 140
The file opened in line 100 is closed
Line 150
The screen is cleared
Line 160
The last name to be searched for is read from the keyboard and placed in the variable N$
Lines 170- 190
The loop searches the table of records, checking the name fields against the desired name. If the position is found, the program branches to the output routine
Line 200
The name was not found
Lines 210-270
The record containing the desired name is displayed
Lines 280-310
The possibility to search for a new name is allowed
You will notice that this search is quite fast when the data is already loaded into the computer. Searching the computer's memory is faster than searching the diskette. The program can be easily changed to search for a 55
ABACUS Software
Anatomy of the 1541
desired field other than the name. You might want to search for an area code, for instance. This program stops the search when the first matching data record is found. This is not always desired, however. If, for instance, you wish to search the table looking for a particular area code and want all matches to be displayed, a different routine is needed. The routine must continue the search after the first match is found. The next program takes care of this:
100 OPEN 1,8,2, "TELEDAT,S,R" 110 DIM D$(100,4) :X=l 120 INPUT#1,D$(X,1),D$(X,2),D$(X,3), D$(X,4) 130 IF ST64 THEN X=X+1:GOTO 120 140 CLOSE 1 150 PRINT CHR$(147) 160 PRINT"AREA CODE TO SEARCH FOR: n;AC$ 170 FOR I=l TO X 180 IF D$(I,3)=AC$ THEN 210 190 NEXT I 200 PRINT"END OF DATA! ":GOTO 270 210 PRINT"----------------" 220 PRINT"LAST NAME: " ; D$ (I, 1) 230 PRINT"FIRST NAME: ";D$(I,2) 240 PRINT"AREA CODE: ";D$(I,3) 250 PRINT"NUMBER: ";D$ (I, 4) 260 PRINT"----------------" 270 PRINT"MORE (YIN)?" 280 GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 280 290 IF X$="Y" THEN 190 300 PRINT"SEARCH DONE!":END Here the search is continued if a record with the appropriate area code is found. This happens in line 290, which branches back to the loop instead of ending the program. After searching all of the records, the program responds END OF DATA. If you understand the operation of this program, you can now develop a search for the last name. With the help of the previous programs, this should present no difficulty.
56
ABACUS Software
1.4.9
Anatomy of the 1541
Simple Sorting of Tables
In data processing, it is often necessary to sort data into numeric or alphabetic order. This has always been a time-intensive task, which the programmer has tried to shorten by using better sorting methods. Sorting is certainly time consuming when performed with the programming language BASIC, which is relatively slow. Why should we sort the data at all? Suppose you had a telephone book in which the names were not ordered. You would have search the entire book from beginning to end to find a name. Sorting offers advantages when searching data. The computer can also search sorted data faster. There are several search methods which differ mainly in their speed of execution. The simplest method compares each data item with every other. If a table is supposed to be sorted in ascending order, the first item in the table is compared to the second. If the first is greater, it is exchanged with the second. After that, the first will be compared to the third, and so on, until the last item is reached. Now the smallest item is at the beginning, in the right place. The next time through, the first item is no longer needed. A flowchart of the program logic appears on the next page. This sort program starts using an index of 1, which is stored in the variable I. The second index is the variable X, which receives a value one greater than I. Then the first item is compared to the second. If the value of TA(I) is greater then TA(X), the program must use a temporary variable, TA(O), to make the exchange between the two. After this, the value of X is incremented, to three, and TA(I) is again compared to TA(X), etc. When the last item in the table is reached, (X> last index), the first item will be the smallest, and the index I is incremented by one. Now the second item is compared to every other (starting with the third), and so on. This sort method looks quite complicated at first glance. Comparisons in memory are done relatively quickly, however. This method is sufficient for small quantities of data.
57
ABACUS Software
Anatomy of the 1541
Simple Sort
TA(O)=TA(I) .--------- T A(I)= T A(X) TA(X)=TA(O)
>-"0
>--"0
58
ABACUS Software
Anatomy of the 1541
In order to run this program, a table must be constructed. This example uses a table with twelve items containing alphanumeric data (strings). The table is filled by the following routine: 100 110 120 130
DIM TA$(12) FOR I=l TO 12 INPUT TA$(I) NEXT I
This program allows you to enter twelve strings, which are then sorted with the following program: 140 150 160 170 180 190 200 210 220 230 240
I=l X=I+l IF TA$(I) < TA$(X) THEN 180 TA$(O)=TA$(I) :TA$ (I)=TA$ (X) : TA$(X)=TA$(O) X=X+l IF X O THEN 590 GOSUB2230:RETURN GOSUB 2030 OPEN 1,8,2,"@:"+NF$+",S,W" FORI=lTOX P R I NT # 1 , D$ (I, 1) " , "D $ (I, 2) " , "D $ (I , 3) ; PRINT#l,D$ (1,4)", "D$ (1,5)", "D$ (I, 6)", "D$ (1,7) NEXT PRINT"DATA IS SAVED":CLOSE1:RETURN PRINT"RETURN FOR MORE" INPUTX$:RETURN REM ********** REM INPUT DATA REM ********** IFX>OTHEN730 GOSUB2030:INPUT"FILENAME ";NF$ X=X+1 GOSUB2030 PRINT"INPUT DATA:" PRINT"-----------":PRINT I=X:GOSUB2110 FORI=lT07:PRINTCHR$(145); : NEXT FORI=lT07:PRINTTAB(12); :INPUTD$(X,I) :NEXT PRINT:PRINT"CORRECT (YiN)?" GETX$:IFX$"N"ANDX$"Y"THEN810 IFX$="Y"THEN840 GOTO 740 PRINT"MORE INPUT (YiN)?" GETX$:IFX$"N"ANDX$"Y"THEN850 IFX$="Y"THEN730 RETURN
65
Anatomy of the 1541
ABACUS Software
880 REM ********* 890 REM EDIT DATA 900 REM ********* 910 IF X>OTHEN930 920 GOSUB2230:RETURN 930 GOSUB2030 940 INPUT"NAME 1: "; N1$ 950 INPUT"NAME 2: n;N2$ 960 FORI=lTOX 970 IF 0$ (I,l)=N1$ANDD$(I,2)=N2$THEN1010 980 NEXTI 990 PRINT"NAME NOT FOUND!" 1000 PRINT"RETURN FOR MORE":INPUTX$:RETURN 1010 GOSUB2030 :";0$(1,1) 1020 PRINT"-l- NAME 1 :";0$(1,2) 1030 PRINT"-2- NAME 2 :";0$(1,3) 1040 PRINT"-3- STREET 1050 PRINT"-4- CITY STATE :";0$(1,4) :";D$(I,5) 1060 PRINT"-5- ZIP CODE 1070 PRINT"-6- TELEPHONE :";D$(I,6) 1080 PRINT"-7- NOTES :";0$(1,7) 1090 PRINT"NO. OF FIELD TO CHANGE: ":PRINT"(9=NO CHANGES)" 1100 GETX$:IFVAL(X$)OTHEN1240 1230 GOSUB2230:RETURN 1240 GOSUB2030:PRINT"OUTPUT TO PRINTER (P) OR SCREEN (S)?" 1250 GETX$:IFX$"S"ANDX$"P"THEN1250
66
ABACUS Software
1260 1270 1280 1290 1300 1310 1320 1330 1340 1350 1360 1370 1380 1390 1400 1410 1420 1430 1440 1450 1460 1470 1480 1490 1500 1510 1520 1530 1540 1550 1560 1570 1580 1590 1600 1610 1620
Anatomy of the 1541
O$=X$:IFO$="S"THEN1300 PRINT:PRINT"PAPER (P) OR MAILING LABELS (M}?" GETX$:IFX$"P"ANDX$"M"THEN1280 D$=X$ GOSUB2030 PRINT"ENTER THE SEARCH DATA:" PRINT"PRESS RETURN BY IRRELEVANT FIELDS." PRINT"----------------------------------": PRINT I=0:GOSUB2110 FORI=lT07:PRINTCHR$(145); :S$(I}="":NEXT FORI=lT07:PRINTTAB(12}; :INPUTS$(I} :NEXT IFO$="S"ORD$="M"THEN1450 GOSUB2030:PRINT"PRINTER READY (Y}?" GETX$:IFX$"Y"THEN1390 OPEN 1,4 PRINT#l,"NAME 1"iSPC(8}i"NAME 2"iSPC(8); "STREET";SPC(lO}i PRINT#l,"CITY STATE"iSPC(4}i "ZIP CODE TELEPHONE NOTES" FORI=lT079:PRINT#1,"="; :NEXT:PRINT#l CLOSEI FORI=lTOX FORY=lT07 IFS$(Y}=LEFT$(D$(I,Y},LEN(S$(Y} }}THENZ=Z+l: GOT01480 NEXTY IFZ=7THENGOSUB1550 Z=O:NEXTI PRINT:PRINT"END OF DATA!":PRINT PRINT"RETURN FOR MORE":PRINT INPUTX$ RETURN IFO$="S"THEN1730 IFD$="M"THEN1670 OPENl,4 PRINT#1,D$(I,1};SPC(14-LEN(D$(I,1))); PRINT#1,D$(I,2) ;SPC(14-LEN(D$(I,2))); PRINT#l,D$ (1,3); SPC (16-LEN (D$ (1,3))); PRINT#1,D$(I,4) ;SPC(15-LEN(D$(I,4))); PRINT#1,D$(I,5) ;SPC(8-LEN(D$(I,5))); 67
ABACUS Software
1630 1640 1650 1660 1670 1680 1690 1700 1710 1720 1730 1740 1750 1760 1770 1780 1790 1800 1810 1820 1830 1840 1850 1860 1870 1880 1890 1900 1910 1920 1930 1940 1950 1960 1970 1980 1990 2000 2010 2020
Anatomy of the 1541
PRINT#l,D$ (I, 6) ;SPC (12-LEN (D$ (I, 6»); PRINT#1,D$(I,7) PRINT#1:CLOSE1 RETURN OPEN2,4 PRINT#2 FORJ=lT05:PRINT#2,D$(I,J) :NEXT PRINT#2:PRINT#2:PRINT#2 CLOSE2 RETURN GOSUB2030:GOSUB2110 PRINT:PRINT"MORE (Y)?" GETX$:IFX$"Y"THEN1750 RETURN REM *********** REM DELETE DATA REM *********** IFX>OTHEN1820 GOSUB2230:RETURN GOSUB2030 INPUT"NAME 1 : ";N1$ INPUT"NAME 2 : ";N2$ FORI=lTOX IFD$(I,1)=Nl$ANDD$(I,2)=N2$THEN1900 NEXTI PRINT"NAME NOT FOUND!":PRINT PRINT"RETURN FOR MORE":INPUTX$:RETURN GOSUB2030:GOSUB2110 PRINT:PRINT"DELETE RECORD (YiN)?" GETX$:IFX$"Y"ANDX$"N"THEN1920 IFX$="N"THENRETURN FORY=ITOX-1 FORJ=lT06 D$(Y,J)=D$(Y+1,J) NEXTJ,Y FORJ=lT06:D$(X,J)="":NEXTJ X=X-1 PRINT"RECORD IS DELETED!" PRINT"RETURN FOR MORE" INPUTX$:RETURN
68
Anatomy of the 1541
ABACUS Software
2030 REM ***** ***** ***** 2040 REM PROGRAM HEADING 2050 REM ***** ***** ***** 2060 PRIN TCHR $(147 )i 2070 PRIN TTAB (8)i"= ==== ==== ==== ==== ==== ==" LIS T 2080 PRINT TAB( 8) i"M A I LIN G ====" ==== ==== ==== ==== i"=== 8) TAB( 2090 PRINT N 2100 RETUR 2110 REM ***** ***** ** 2120 REM PRINT RECORD 2130 REM ***** ***** ** iD$ (1,1) 2140 PRINT"NAME 1 I,2) iD$( 2 E 2150 PRINT"NAM (1,3) iD$ ET "STRE 2160 PRINT iD$( I,4) 2170 PRIN T"CIT Y STATE iD$ (1,5) CODE T"ZIP 2180 PRIN iD$ (I, 6) E PHON "TELE 2190 PRINT iD$( I,7) ES "NOT 2200 PRINT 2220 RETURN 2230 REM ***** *** 2240 REM NO DATA! 2250 REM ***** *** 2260 GOSUB2030 2270 PRINT"NO DATA IN MEMORY! ":PRI NT 2280 PRINT"RETURN FOR MORE" 2290 INPUTX$:RETURN
69
ABACUS Software
Anatomy of the 1541
1.4.11 Uses for Sequential Storage The great advantage of sequential storage as compared to relative and direct access storage, is that a lot of data can be written to the diskette quickly. Data of varying lengths can be stored together, without requiring the records to be of a definite length. It makes sense to make use of this advantage in cases in which the file must not be permanently divided into parts. Examples are:
* Bookkeeping files In a bookkeeping journal, all entries are recorded continuously. Changes should not be made to these entries. Instead, adjustment entries should be made to effect changes.
* Analysis files You analyze a direct access file, looking for, say, all customers with whom you have done more than 2000 dollars of business in a certain zip code, and write the found records in a sequential file for later access. Naturally, sequential files also offer a substitute for direct access files, as discussed in this chapter, if the user does not possess further programming knowledge. We must certainly recommend that you work through the other methods of data storage though, because they offer significant advantages.
70
ABACUS Software
1.5
Anatomy of the 1541
Relative Data Storage
Relative data storage and its programming is not described in the VIC-1S41 user's manual. The reason may lie in the fact that the Commodore 64 and the VIC-20 have no commands to process relative files using BASIC 2.0. Therefore, it is in principle not possible to use relative data storage on the Commodore 64 and VIC-20--but only in principle. We have developed a few tricks that work within the limitations of BASIC 2.0 and permit the Commodore 64 and also the VIC-20 to use relative data storage. The examples may seem to be somewhat complicated at first--for example, information about the record lengths will be transmitted to the disk using CHR$(x) codes--but they provide for a very easy method of data storage.
1.5.1 The Principle When using relative record data processing, the data records are numbered. It is assumed that all records in a relative file have the same length and that the record number of every record is known or can be calculated. To find a record, it is not necessary to search through the entire file. Only the record number need be given to access that record. Using the record number, the DOS can find where the record is "relative" to the beginning of the file on the diskette and can read it directly. Therefore, the entire file need not be read into the computer, only the desired records. The management of a relative file follows this pattern:
Create a relative file: 1. The file is opened. With this the length of a record is established. 2. The last record is marked. 3. The file is closed.
Write a record: 1. The file is opened. 2. The file is positioned on the record to be written. 3. The record is written. 71
Anatomy of the 1541
ABACUS Software
4. The file is closed.
Read a record: 1. The file is opened. 2. The file is positioned over the record to be read. 3. The record is read. 4. The file is closed. This is only an outline. In the following sections these processes will be explained in detail.
1.5.2 The Advantage over Sequential Storage The greatest advantages of relative storage are:
* *
faster access to individual records does not require much of the computer's memory
It has already been mentioned that the sequential file must reside completely in the computer's memory for processing. Using sequential techniques, it may be necessary to search the entire file to find a given record. The record must be read and compared during the search process. But if a sequential file cannot be entirely loaded into memory, this method of search is impossible.
Using relative data files, the processing is much simpler. By using the record number, a desired record can be read individually. The file size is not limited to the computer's memory. So, for example, a program that uses all 3.5K bytes of a standard VIC-20 can manage a file with up to 163 Kbytes! The advantages of relative over sequential file management are large enough that many of you, once acquainted with the techniques, will prefer to use them.
72
ABACUS Software
1.5.3
Anatomy of the 1541
Opening a Relative File
Relative files are also opened with the OPEN command. The command differs only slightly from that for sequential files. Take a look at the format of the OPEN command:
OPEN lfn,da,channel, "filename,L," +CHR$(recordlength) The first four parameters are identical to those for sequential files. They are logical file number, device address (normally 8), channel (2-14), and name of the file. Next follows an L which informs the DOS that a relative file should be opened, whose record length follows. This record length is transmitted with a CHR$ code. The length is between 1 and 254. Thus each record of a relative file is limited to a maximum of 254 characters. If the record length is less than 88, the record can be read with an INPUT# statement. For this, it is necessary that the PRINT# statement transfer the record with a trailing RETURN. A PRINT# statement sends a RETURN when it is not terminated with a semicolon. This RETURN is now a part of the record. When you want to read records with INPUT#, the record length must be increased by one. A file composed of 80-character records, to be read by the INPUT# statement, would be opened as follows:
OPEN 1,8,2,"FILE.REL,L," +CHR$(81) Here a relative file with the name "FILE.REL" is opened using channel 2. The record length should total 81 characters. Records comprised of 80 characters should be sent with a PRINT# statement, with no trailing semicolon. It is important to note that only one relative file can be opened at a time. If you want to work with two relative files, you must always close the first
before opening the second. One sequential file may be opened in addition to one relative file. When a relative file is opened for the first time, the DOS creates as many "null" or unused records as can fit in a single 254 byte block. It
73
ABACUS Software
Anatomy of the 1541
create s these "null" record s by writin g a record with a CHR$ (255) at the beginning of each record. This is called formatting a relative file. If you want to expan d a relativ e file beyon d the initial numbe r of record s that the DOS formatted, you can referen ce the last record numbe r that you want to write (by positioning to that record number) and the DOS autom aticall y formats the record s betwe en the curren t end of file and the new last record numb er by writin g record s contai ning CHR$ (255). Formatting takes time to complete. If you try to read a record whose numbe r greate r than that of the last record , the DOS returns the error RECO RD NOT PRES ENT. Howe ver, if you write a record which is greate r than the highes t curren t record , all record s less than the new record numbe r are also written with CHR$ (255). Subsequently accessing these record does not result in an error.
If you want to avoid long delays while relative records are formatted (as the file is expan ded), then you should refere nce the last record numbe r immed iately after openin g the file. The formatting of the null record s takes place at that time instead of at a more inconvenient time.
To positio n the DOS for a specif ic relativ e record you must send a position comm and over the comm and channel (15), as shown here: PRIN T#lfn ," P" +CHR $(cha nnel) +CHR $(low )+CH R$(hi gh)+ CHR$ (byte) If you are positio ning to a record which is beyon d the curren t end of file, the DOS presen ts the messa ge RECO RD NOT PRES ENT to the disk error chann el. If this record is to be writte n, then you can ignore the messa ge. The follow ing PRINT # statem ent is carried out in spite of the error message.
The param eters low and high in the P comm and design ate the record numbe r. The maxim um value that can be given with one byte is 255, but a relativ e file contai ns up to 65535 records. Theref ore, the record numbe r must be transm itted in two bytes. These two bytes are calcul ated with the following formula: HB=I NT(R N/256 ) LB=R N-HB *256 74
Anatomy of the 154l
ABACUS Software
HB = High Byte (parameter high) LB = Low Byte (parameter low) RN = Record Number The last parameter (byte) serves to position to a specific location wnh1ll the given record. An example:
PRINT#2," pIt +CHR$(2)+CHR$(lO)+CHR$(1 )+CHR$(5) Here the file is positioned to the fifth byte of the 266th record. This is coded as a low byte of 10 and a high byte of 1 (high byte * 256 + lov, byte = record number). To read or write a complete record, the file is positioned to the first byte of the record. If the last parameter is not given, the trailing RETlJRN (CHR$(13» is taken as the character location. The corresponding BASIC program to establish a file of 1 80-character records looks like this:
100 RN=100 110 HB=INT(RN/256) 120 LB=RN-HB*256 1300PEN1,8,2,"FILE.REL,L,"+CHR$(80) 140 OPEN2,8,15 150 PRINT#2,"P"+CHR$(2)+CHR$(LB)+ CHR$(HB)+CHR$(l) 160 PRINT#1,CHR$(255) 170 CLOSE l:CLOSE 15 Freeing 100 records takes some time. The creation of this file about ten minutes. Notice that of the 80 characters in a record, on1y be used to hold data, because transferring data with a PRINT# command adds a trailing RETURN.
75
ABACUS Software
Anatomy of the 1541
1.5.4 Prepa ring Data for Relative Stora ge As already mentioned, you cannot change the record length of a relativ e file. If a record consists of several fields, these fields must be combi ned. It is important that these fields always be in the same position so that they can be separated later. Let's work through a problem: We want to manag e an inventory using relativ e storage techniques. To that end, the following fields are necessary: PART NUMB ER DESC RIPTI ON QUAN TITY COST PRICE Recor d length
4 CHAR ACTE RS 15 CHAR ACTE RS 5 CHAR ACTE RS 6 CHAR ACTE RS 6 CHAR ACTE RS 36 bytes
The inventory contains approximately 200 items with a record length of 36 bytes. This inventory file can now be created: 100 110 120 130 140
RN=2 00:RE M NUMBER OF INVENTORY ITEMS RL=3 6 :REM RECORD LENGTH OPEN 1,8,2 , "INVE N,L, "+CH R$(36 ) OPEN 2,8,1 5 PRIN T#2," P"+C HR$( 2)+CH R$(20 0)+ CHR$ (O)+C HR$(l ) 150 PRIN T#1,C HR$( 255) 160 CLOSE l:CLO SE 2
Now the file is create d and all records are written. Let's suppo se that the invent ory is presen t as a sequen tial file. It consis ts of 200 record s, the fields of which are ordered one after the other. These fields must be written to the relativ e file. This is not simple , howev er, becau se many of the descriptions are not the full fifteen characters in length. The structu re of the relative file looks as follows:
76
--------
~-----------
Anatom y of the 1541
ABACUS Softwa re
POSITI ON
11111 11111 22222 22222 33333 33 12345 67890 12345 67890 12345 6 67890 12345
FIELD
PM$- DE$- ------- ----Q$ ---C$ ----P$ ----
CONTENTS
1
2 3
1/8 in. sheet No. 10 screw Valve A3A4
200 1/2 in.
1344 11.40 20.30 7.00 4.00 1231 1243 11.45 16.40
tubing 2321
3.35
4.10
les: The fields will be read from the sequential file into the following variab
Part numb er Description Quant ity Cost Price
PN$ DE$ Q$ C$ P$
The following command chains these fields together:
RC$ = PN$ + DE$ + Q$ + C$ + P$ The record variable RC$ does not have the desired structure. The se the reason is that the quantity immediately follows the description. Becaufifteen always not is ption descri quantity must begin at position 20 and the the characters long, we have a problem. In order to read the records from are that fields all ore, Theref ed. relative file, the structure must be observ this shorter than the planned length must be padded with blanks. Taking this: into account, the chaining goes like
" BL$=" RC$=PN$+ LEFf$ (BL$, 4. LEN (PN$)) RC$=RC$+DE$+LEFT$(BL$,15·LEN(DE$) RC$=RC$+Q$+LEFT$(BL$,5. LEN (Q$)) RC$=RC$+C$+LEFf$(BL$,6.LEN(C$») RC$=RC$+P$+LEFT$(BL$,6·LEN(P$»
77
ABACUS Softwa re
Anatomy of the 1541
This concatenation looks more complicated than it really is. Each field must be filled with enough blanks to bring it to its appropriate length . The blanks are added to the individual fields from the string BL$, defined at the beginning. Let's go through an example: Suppo se the first part numb er is 8. The length of this string LEN(PN$), is then one. The maximum length of this field (4) minus , the actual length (1) is 3. The string PN$ must therefore be padded with three blanks, LEFf$ (BL$, 3). Each record of the old sequential file must be prepared in this manne r before it can be transferred to the relative file. Naturally, the above is true for all input values to be used in a relativ e file. Therefore you must always remember to use a routine to fill each field with blanks to its full length when working with relative data processing.
1.5.5 Trans ferrin g Data In principle, transferring data to and from a relative file does not differ from sequential storage. Records are written with PRINT# and read with INPUT# or GET#. The only difference is that before a record is written read, the file must be positioned to that record. This is accomplished or the P command. This example program illustrates what we have discus with sed: 100 105 110 120 130 140 150 160 170
BL$= " " OPEN 1,8,2 ,"TES T.RE L,L," +CHR $(41) OPEN 2,8,1 5 PRIN T#2," P"+C HR$( 2)+CH R$(10 0)+ CHR$ (O)+C HR$(l ) PRIN T#1,C HR$( 255) PRINT CHR$ (147) PRINT "INPU T RECORD:" PRIN T"-- ----- ----- -" INPUT"RECORD NUMBER (1-10 0) "; RN
78
ABACUS Software
Anatomy of the 1541
180 IF RN100 THEN PRINTCHR$(145);: GOT0160 190 INPUT"FIELD 1 (MAX.10 CHAR.) : "iF1$ 200 IF LEN(F1$»10 THEN PRINTCHR$(145) i : GOT0190 210 INPUT"FIELD 2 (MAX. 5 CHAR.) : "iF2$ 220 IF LEN(F2$»5 THEN PRINTCHR$(145) i :GOT0210 230 INPUT"FIELD 3 (MAX.10 CHAR.) : "iF3$ 240 IF LEN(F3$»10 THEN PRINTCHR$(145);: GOT0230 250 INPUT"FIELD 4 (MAX.15 CHAR.) : "iF4$ 260 IF LEN(F4$»15 THEN PRINTCHR$(145) i : GOT0250 270 PRINT"CORRECT (YiN)?" 280 GETX$:IF X$"Y" AND X$"N" THEN 280 290 IF X$="N" THEN 140 300 RC$=F1$+LEFT$(BL$,10-LEN(F1$)) 310 RC$=RC$+F2$+LEFT$(BL$,5-LEN(F2$)) 320 RC$=RC$+F3$+LEFT$(BL$,10-LEN(F3$)) 330 RC$=RC$+F4$+LEFT$(BL$,15-LEN(F4$)) 340 PRINT#2,"P"+CHR$(2)+CHR$(RN)+ CHR$(O)+CHR$(l) 350 PRINT#l,RC$ 360 PRINT"MORE INPUT (YiN)?" 370 GETX$:IF X$"Y" AND X$"N" THEN 370 380 IF X$="Y" THEN 140 390 CLOSE l:CLOSE 2:END The following line-oriented documentation explains the operation of the program: A blank-character string with 15 blanks is defined. The relative file is opened with a length of 15. The command channel 15 is opened. To initialize the relative file, the head is positioned over the first byte of the last (lOOth) record. The last record is freed and the initialization begun. 130 The screen is erased. 140 150-260 The record no. and fields 1-4 are entered and checked for correct length. 270-290 The entered data can be corrected.
100 105 110 120
79
Anatomy of the 1541
ABACUS Software
300-330 The record is prepared. 340 The head is positioned over the first byte of the record. The record is written to the disk. 350 360-380 New data can be entered. 390 The program ends. Now write some records with this program, but don't forget to save it in case you need it later. Certainly it also necessary to read and change existing records. To do this, the relative file is opened, the file is positioned to the appropriate record, and the record is read. This record must then be divided into its fields. Let's read a record that was recorded with the previous program. The following routine reads the record: 100 110 115 120 130 140 160 170 250
OPEN 1,8,2,"TEST.REL,L,"+CHR$(41) OPEN 2,8,15 PRINT CHR$(147) INPUT"RECORD NUMBER :";RN PRINT#2,"P"+CHR$(2)+CHR$(RN)+ CHR$(O)+CHR$(l) INPUT#l,RC$ IF ASC(RC$)255 THEN PRINT"RECORD NOT FOUND!":GOT0250 PRINT RC$ CLOSE l:CLOSE 2
This routine reads a specified record. If this record has never been written, it is recognized by the value 255 with which every record was marked at the creation of the file. A record that is found is displayed. You can see that the four fields are in the same positions. If you want to divide the record into its individual parts, you must use the function MID$. For example, in order to extract field 1 of the record, give the following statements in the direct mode after the record is found and read:
Fl$=MID$(RC$,l,lO) PRINT Fl$
80
Anatomy of the 1541
ABACUS Softwa re
Now the variable Fl$ contains the first field, as written by the first d by program. The division of records into individual fields is accomplishe lines: ing follow the change or building on the previous program. Add Fl$=M ID$(R C$,1, 10) F2$= MID$ (RC$ ,11,S) F3$= MID$ (RC$ ,16,10 ) F4$= MID$ (RC$ ,26,1S ) PRIN T"FIE LD 1: ";F1$ PRIN T"FIE LD 2: ";F2$ PRIN T"FIE LD 3: H;F3$ PRIN T"FIE LD 4: n;F4$ PRINT"MORE (Y/N) ?" GETX $:IF X$ "Y" AND X$ "N" THEN 260 270 IF X$="Y " THEN 115 280 CLOSE l:CLO SE 2
170 180 190 200 210 220 230 240 250 260
Here the record is separated into the individual fields and the fields are ns of displayed. It is important for the MID$ function that the exact positio the within eter param first The ined. the fields within the record be mainta second The . record the ning contai le parent heses is the string variab by parameter is the position at which the number of characters represented d selecte the with done may work r Furthe the parameter will be taken out. fields inside L1e program. the So far we have read the records with the INPUT# statement. If the with read be longer no can it ters, charac 88 than record is longer ent is INPUT# statement. The way to get around the limited INPUT# statem with time a at with the GET# statement. The bytes of a record are read one a this comm and and assembled into a single string. Suppose you have tenth the read to relative file with 128-character records. Now you want the record of this file and place it in the variable RC$. The example of following routine illustrates reading this with GET#: 100 OPEN 1,8,2 , "TES T.GE T,L," +CHR $(128 ) 110 OPEN 2,8,1 5 120 PRIN T#2," P"+C HR$( 2)+CH R$(10 )+ CHR$ (O)+C HR$ (1) 130 Re$= ""
81
ABACUS Software
140 150 160 170
Anatomy of the 1541
FOR I=l TO 128 GET#l,X$ RC$=RC$+X$ NEXT I
After running this routine, the record is contained in the variable Re$. If this record had been written with a PRINT# statement without a trailing semicolon, the last character in the string will be a RETURN. To ignore this RETURN, allow the loop in line 140 to run only to 127. The last character of the record (RETURN) is not read. As already mentioned, the last parameter of the P command specifies at which character the transfer of data should begin. If, for instance, in the 127-character record of the previous example, you want to read positions 40-60 into a field, the head must be positioned over the 40th character and the next 21 bytes read. The following routine clarifies this: 100 OPEN 1,8,2, "TEST.GET,L, "+CHR$(128) 110 OPEN 2,8,15 120 PRINT#2, "P"+CHR$ (2)+CHR$ (10)+ CHR$ (O)+CHR$ (40) 130 F$="" 140 FOR I=l TO 21 150 GET#l,X$ 160 F$=F$+X$ 170 NEXT I
In line 120, the head is positioned over the the 40th byte of the tenth record in line 120 and the loop in lines 140- 170 reads the following 21 bytes (bytes 40-60 of the record) into F$.
82
ABACUS Software
Anatomy of the 1541
You see then that the entire record need not be read if you only want to work with part of it.
1.5.6
Closing a Relative File
There is no difference between closing a relative file and closing a sequential file. Because the command channel must always be open to send the position command when working with relative storage, it must also be closed.
1.5.7 Searching Records with the Binary Method Normally each record is accessed by record number. But what if you want to search for a specific name in a relative file and the record number is not known? It is possible to read each record and compare each for the desired name. But this is very time consuming if the file has many records. If the file is kept in name order, the records can be searched using an alternative method. This method is called a binary search. In order to use a binary search, the relative file must be arranged in sorted order. Using the above example, relative record 1 must contain a name with the lowest collating sequence while the last relative record must contain a name with the highest collating sequence. Thus the name AARON might be contained in relative record 1 and ZEPHYR might be contained in the last relative record of the file and all other names would be ordered throughout. When records are added to the file, then the records must be reordered. Similarly if a name is changed, the records must again be reordered. The binary search can be explained using a simple example. When you want to find a name in the telephone book, you don't search through it sequentially. You open the book in the middle and compare the first letter of the desired name with the first letter of names on the page. If the desired name comes before these, you tum halfway into the first section of the book, and so on. You go through it systematically.
83
ABACUS Software
Anatomy of the 1541
The binary search is not a sequential search. It identifies a record halfway through the remaining number of records. The following example will clarify this: There exists the following relative file, sorted in ascending order:
Record number Contents 1 1985 2 1999 3 2005 4 2230 5 2465 6
7 8 9
10 11 12 13
14 15
2897 3490 3539 4123 5000 5210 6450 6500 6550 6999
Within these fifteen records we will search for a contents of 3490. It is not known which record it is stored in. We must first know how many records are in the file. In this case, there are fifteen. We divide this by two. The middle of the file is record eight with the contents 3539. We determine if the contents of this record are equal to the target value, and if not, whether they are larger or smaller. In this case, they (3539) are larger. This means the record we are looking for is in the first half of the file. So we divide eight by two and examine the contents of record four, 2230. Since 2230 is less than 3490, it lies between four and eight. We again divide by two and add this to record 4 which results in record 6, the contents of which are 2897. 2897 is less than 3490, so our target lies between records six and eight. Record seven is indeed the record we are looking for.
84
ABACUS Software
Anatomy of the 1541
The principle of the binary search is to determine by the result of each comparison whether to search upwards or downwards until the search data is found. The maximum number of comparisons can be found using the following formula:
S=INT(LOG(N)/LOG(2)+1) S is the number of comparisons (searches) and N is the number of records in the file. In a sorted relative data file with 1000 records, no more than ten comparisons will be necessary to find the desired record! Let's create a relative data file with fifteen records to test the binary search: 100 110 120 130 140 150 160
Ol?EN1,8,2, "BINARY.REL,L, "+CHR$(5) FORI=lT015 READ RC$ l?RINT#l,RC$ NEXT I CLOSE l:CLOSE 2:END DATA 1985,1999,2005,2230,2465,2897, 3490,3539 170 DATA 4123,5000,5210,6450,6500,6550, 6999
This program puts the fifteen records in a file called BINARY.REL using the values given in lines 160-170. The position command is not necessary because the data will be written straight through from first to last record. After opening the file the pointer points to the first record. This file is designed to be searched with the binary method. The following program is based on the logic of the binary search: 100 110 120 140 150 160 170 180 190
Ol?EN1,8,2, "BINARY.REL,L, "+CHR$(5) Ol?EN2,8,15 l?RINTCHR$(147) N=15: REM NUMBER OF RECORDS I=LOG(N)/LOG(2) IF I-INT(I)O THEN I=INT(I)+l M=I-1 I=2""I X=I/2
85
ABACUS Software
Anatomy of the 1541
210 INPUT"RECORD TO FIND (* TO END) : ";SR$ 220 IF SR$="*" THEN 320 230 IF M:BO >:B8 >:CO >:C8 >:DO >:D8 >:EO >:E8 >:FO >:F8
AO 00 00 2F AO 00 00 4B 48 00
AO 00 00 53 AO 00 00 20 41 00
00 00 54 AO 00 00 44 52 47 45 00 00 00 00
00 OB 31 AO 00 06 49 20 00 04
00 00 32 AO 00 00 53 43 00 00
· ..... .. · .... T12 /SOl File type . . . Track, 1st block
· ..... ..
· .... DIS K ADDR C HANGE ... Sector, 1st block
· ..... ..
This is an section from the directory (track 18, sector 1) of the TEST /DEM O diskette. You can follow the organization of the file DISK with ADDR CHANGE. The entry of this file begins at byte $E2 and ends $82 type file byte $FF. This is a PRG file, which can be recognized by the from t eviden in byte $E2. This file comprises 4 blocks on the disk. This is data bytes $FE and $FF. Bytes $E3 and $E4 of the entry address the first 0). block of the file ($10, $00, corresponding to track 16, sector Let's look at a section of this block: Address of the
>:00 110 97 >:08 >: 10 32 93 >: 18 49 >: 20 45 >:28 47 >:30 41 >:38 99 >: 40 4F >: 48
OAlo l 35 39 00 39 13 11 56 45 53 53 45 20 4D 22 22 11 46 46
04 34 04 11 20 20 50 00 54 20
OF 36 6E 11 41 43 52 59 55 41
04 38 00 11 44 48 4F 04 52 4C
64 2C 99 44 44 41 47 6F 4E 4C
00 31 22 52 52 4E 52 00 20 20
. . . . . . $ 'lst block
.5946 8,1 2.9 .... ..... . DR IVE ADDR ESS CHAN GE PROGR AM" .y./. " .TURN OFF ALL II
This block contains the first part of the program. It is stored on the diskette exactly as it is stored in the computer's memory. The BASIC only commands are converted to one-byte codes called tokens. This is why l ecima hexad the of tion transla hand the text can be recognized in the right 167
ABACUS Softwa re
Anatomy of the 1541
codes. The first two bytes of this data block indicate the second data block ($10 and $OA, track 16, sector 10) from which this section follows: >:00 >:08 >:10 >: 18 >:20 >: 28 >:30 >:38 >:40 >: 48
r-~.....,r-:--:---::-::---::-;:--:-:--;:-::-~:'-----:-;:
110 00 8F 52 45 36 48 44 B4 20
14134 30 00 ID 05 AO 8D 203 330 30 3A 20 20 46 49 4E 44 20 44 49 56 45 20 54 59 50 00 39 05 AA 00 8D 20 30 30 3A 20 8F 20 43 41 4E 47 45 20 41 44 52 4 5 5 3 5 3 0 0 68 05 00 992 211 544 845 53 45 4C 45 43 54 45
-- Address of the .. 40 ... third block .. 300: FIND D RIVE TYP E.9 . . . 600: C HANGE AD DRE S S. ( . .. ".THE SELECTE
The progra m is contin ued in this block. Bytes $00 and $01 point to the third data block of the file ($10, $14, track 16, sector 20): >:00 110 081 31 30 30 30 00 23 >:08 06 54 01 8B 20 43 B2 32 >: 10 35 34 20 A7 20 4D 54 B2 >: 18 31 31 39 3A 20 SF 3A 20 >:20 32 30 33 31 20 56 32 2E >:28 36 00 45 06 5E 01 8B 20 >:30 43 B2 32 32 36 20 A7 20 >:38 4D 54 B2 35 30 3A 20 8F >: 40 3A 20 32 30 34 30 20 56 >:48 31 2E 32 00 67 06 68 01
. . 1 0 00 . # Address of the . T.. C 2 fourth block 54 HT 119: .. 2031 V2. 6.E. C 226 HT 50: : 2040 V 1. 2.
. (.
This is the next to the last block of the program. You have no doubt recognized that the data blocks are in the same track, but are not contig uous. The first data block is block O. The next is block 10, 10 blocks from the first block. 9 blocks are always skipped between data blocks of a file. The third data block is block numbe r 20. The DOS begins again with the first block if the calculated block oversteps the highest block. Becau se track 16 contai ns 21 blocks , the last data block is block numbe r 8. The first two bytes of this third block address it:
168
--~-~-
---------------
Anatomy of the 1541
ABACUS Softwa re
>:00 >: 08 >: 10 >: 18 > :20 >: 28 >:30 >:38 >: 40 >: 48
5A 34 20 30 31 C7 31 2C C6 30
42 30 53 30 35 28 36 5A 28 29
B2 00 54 00 2C 31 29 43 5A 29
31 14 20 45 22 37 3A 24 43 00
20 07 A7 07 4D 32 Al 3A 24 66
Characters in last block
ZB 1
A7 AE 20 B8 2D 29 23 5A
Numbe r of ',:00 00 >:08 00 >:10 11 >:18 11 >:20 11 >:28 11 >:30 11 >:38 10 >:40 10 >:48 00 >:50 00 >:58 00 >:60 00 >:68 00 >:70 00 >:78 00 >:80 00 >:88 00 >:90 00 >:98 00 >:AO 00 >:A8 00 >:BO 00 >:B8 00 >:CO 00 >:C8 00 >:DO 00 >:D8 00 >:EO 00 >:E8 00 >:FO 00 >:F8 00
47 00 00 02 04 06 08 08 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 11 11 11 11 11 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
64 00 DB OD OF 11 13 12 DE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 00 11 11 11 11 11 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
OA 00 00 00 01 11 03 11 05 11 07 11 09 11 06 10 02 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
176
00 00 DC DE 10 12 14 10 DC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
.G.$ .... ......... ....... II
..............
....
II
..........
......... ....... ......... ....... '"
......... .....
10
..............
...... " ........ ......... ....... .......... '" .... .......... ....... " .. ,. .......... ......... .......
......... ....... .......
.........
'"
......... .......
...... '"
..
....
,.
..
"
..........
"
.........
"
......
............
&
............
10
..
II
"
..
iO
......
10
..
.......... ... " .. ......... .......
......... .......
....
., .......... ......... ....... ......... .......
..
.,
.......... ...
......... ....... ......
to
10
......
ABACUS Software
Anatomy of the 1541
The first two bytes point to the track and sector of the next side-sector block, as usual. In our case, no further side-sector blocks exist ($00) and only $47 = 71 bytes of this sector are used. Byte 2 contains the number of the side-sector block, 00. A relative file can contain a maximum of 6 such blocks; the numbering goes from 0 to 5. The record length, $64 (100), is in byte 3. The next twelve bytes (bytes 4 through 15) contain the track and sector pointers (two bytes each) to the 6 side-sector blocks (00,00 means the block is not yet used). Starting at byte 16 ($10) are the pointers to the data, and the track and sector pointers to the first 120 data blocks (in our case, only 28 pointers). Using the record number and record length, the DOS can calculate in which block the data lies and at which position within the block the record begins. Take the following example, for instance: To read the 70th record from the file with a record length of 100 characters, you can perform the following calculations:
(70-1)
*
100 / 254
We get a quotient of 27 and a remainder of 42. The DOS now knows that the record can be found in the 27th data block at the 42+2 or 44th position. Here's an explanation of the calculation. Each block contains 256 bytes, the first two of which are used as a pointer to the next block. 254 bytes are then left over for data storage. We can calculate the byte number from the start of the file (which is record 1) from the record number and record length. If we divide this value by the number of bytes per block, we get the number of the block containing the record. The remainder of the division gives the position within the block (add 2, because the first two bytes serve as a pointer). If the record overlaps the end of the block, the next block must also be read. In our example, the 27th data block lies in track $10 = 16 and sector SOC = 12. If we read this block, we get the following picture:
177
ABACUS Softwa re
>:00 00 F3 00 00 00 >:08 00 00 00 00 00 >:10 00 00 00 00 00 >:18 00 00 00 00 00 >:20 00 00 00 00 00 >:28 00 00 00 00 44 >:30 20 46 4E 52 20 >:38 46 52 44 20 37 >:40 00 00 00 00 00 >:48 00 00 00 00 00 >:50 00 00 00 00 00 >:58 00 00 00 00 00 >:60 00 00 00 00 00 >:68 00 00 00 00 00 >:70 00 00 00 00 00 >:78 00 00 00 00 00 >:80 00 00 00 00 00 >:88 00 00 00 00 00 >:90 FF 00 00 00 00 >:98 00 00 00 00 00 >:AO 00 00 00 00 00 >:A8 00 00 00 00 00 >:BO 00 00 00 00 00 >:B8 00 00 00 00 00 >:co 00 00 00 00 00 >:C8 00 00 00 00 00 >:DO 00 00 00 00 00 >:D8 00 00 00 00 00 >:EO 00 00 00 00 00 >:E8 00 00 00 00 00 >:FO 00 00 00 00 FF >:F8 00 00 00 00 00
Anatom y of the 1541
00 00 00 00 00 41 52 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 54 45 OD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 41 43 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
......... ....... .... .., .......... ...... ., ........ ......... ....... ......... .......
.... DATA FOR REC ORD 70 .. ill"
............
.... '" .......... ......... ....... .......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ............
II
..
......... ....... ......... ....... ......... ....... ......... ....... 10
..............
......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ......
III
........
......... ....... ......... .......
If we get a block numbe r greate r than 120 from the calculation, the pointer can no longer be found on the first side-sector block, but in the next side-sector blocks. In this case, you divide the block numbe r by 120, the quotient being the number of the side-sector block. The remainder gives the location of the pointer within this block. For instance, to find record numbe r 425, divide by 120, getting a quotient 3, remainder 65. Therefore, you must read side-sector block 3 and get the pointer to the 65th data block. Betwe en 2 and 4 block accesses are necessary to access a record in a relative data file,
178
ABACUS Software
Anatomy of the 1541
When creating or expanding a relative file, the following takes place: First, a directory entry is created for the relative file, containing the record length. Two channels are reserved for the relative file, one for the data, the other for the side-sectors. If a record pointer is set to a specific record, the DOS first checks to see if the record already exists. If so, the corresponding block is read and the buffer pointer is set so that the contents can be accessed. If not, the record is created. All records preceding this record number which do not already exist are also created. The first byte of a new record is written to contain $FF (255), and the rest of the record is filled with $00. If the corresponding record is at the beginning of a block, the rest of the block is filled with empty records. Each time a non-existing record is accessed, the error message 50,RECORD NOT PRESENT is returned. When writing a new record, this is not considered an error, but indicates that a new record was created.
You can use this method for creating a new file if you know the maximum number of data records. You simply set the record pointer to this record and write $FF (CHR$(255» to this record. By allocating a file like this, the error message 50 no longer appears. You also know if there is sufficient space on the diskette. If not, the error message 52, FILE TOO LARGE is returned. With a maximum of 6 side sectors, a relative file can contain 6 * 120 * 254 = 182,880 bytes. In the case of the VIC 1541, this is more than the capacity of the whole diskette. With the bigger 8050 drive, which contains more than 500K of storage, this may present a limitation. But DOS version 2.7 has an expansion of the side-sector procedure ("super side-sector"), with which a relative file may contain up to 23 MB. DOS 2.7 is contained in the CBM 8250 and the Commodore hard drives as well as the newer 8050 drives (see section 5.2). Because a relative file requires two data channels and the VIC 1541 has only 3 channels available, only one relative file can be open at a time. The third channel can still be used for a sequential file open at the same time. With the larger CBM drives, more channels are available (3 relative files open simultaneously, see also section 5.2).
179
Anatomy of the 1541
ABACUS Software
3.5 DOS 2.6 R01\'1 LIST INGS
***** ***** ***** ***** ***** ***** SEI 78 C100 LDA #$F7 A9 F7 C101 $lCOO AND 2D 00 1C C103 PHA 48 C106 LDA $7F AS 7F C107 $C110 BEQ FO 05 C109 PLA 68 C10B ORA #$00 09 00 C10C BNE $Cl13 DO 03 C10E PLA 68 CII0 ORA #$08 09 08 C111 STA $lCOO lC 8D 00 C113 CLI 58 C116 RTS 60 C117
turn LED on erase LED bit drive numb er O? not drive 0, turn LED off turn LED on
***** ***** ***** ***** ***** ***** SEI 78 C118 LDA #$08 A9 08 C119 $lCOO ORA lC OD 00 CIIB $lCOO STA lC 8D 00 CIIE CLI 58 C121 RTS 60 C122
turn LED on
***** ***** ***** ***** ***** ***** LDA #$00 A9 00 C123 STA $026C 8D 6C 02 C125
clea r erro r flags
C128 C12B
8D 6D 02 60
STA $026D RTS
***** ***** ***** ***** ***** ***** C12C C12D C12E
78 8A 48
SEI TXA PHA
LED on
clea r coun ter for LED flash clea r bit numb er prep are for LED flash after erro r save X regis ter
181
ABACUS Software
Anatomy or the 1541
C12F C131
A9 50 8D 6C 02
LDA #$50 STA $026C
C134 C136 C139 C13C C13F C142 C143 C144 C145
A2 BD 8D OD 8D 68
LDX LDA STA ORA STA PLA TAX CLI RTS
00 CA 6D 00 00
FE 02 1C 1C
AA
58 60
#$00 $FECA,X $026D $lCOO $lCOO
C146 C148
A9 00 8D F9 02
LDA #$00 STA $02F9
C14B C14E C150
AD 8E 02 85 7F 20 BC E6
LDA $028E STA $7F JSR $E6BC
C153 C155 C157 C159 C15B
A5 10 29 C9 FO
LDA BPL AND CMP BEQ
C15D
4C B4 D7
JMP $D7B4
C160
20 B3 C2
JSR $C2B3
C163 C165 C168 C16A C16D
B1 8D A2 BD CD
LDA STA LDX LDA CMP
C170 C172 C173
FO 08 CA 10 F5
A3 75 02 OB 89 FE 75 02
8 store bit for LED turn LED on get x register back
******************************
84 09 OF OF 03
cntr for LED flash to 80
$84 $C160 #$OF #$OF $C160
($A3),Y $0275 #$OB $FE89,X $0275
BEQ $C17A DEX BPL $C16A
182
interpret command from computer clear flag for no BAM write last drive number drive number prepare 'ok' message secondary address data address 15, command channel yes, interpret filename as command else to OPEN command determine line len and clear flags get first character and store 11 commands compare to first character found?
ABACUS Software
Anatomy of the 1541
C175 C177 C17A C17D C17F CI81
A9 4C 8E EO 90 20
31 C8 C1 2A 02 09 03 EE C1
LDA JMP STX CPX BCC JSR
#$31 $C1C8 $022A #$09 $C184 $C1EE
C184 C18"? C18A C18C C18F C191
AE BD 85 BD 85 6C
2A 95 6F A1 70 6F
LDX LDA STA LDA STA JMP
$022A $FE95,X $6F $FEA1,X $70 ( $006F)
02 FE FE 00
****************************** C194 C196
A9 00 8D F9 02
LDA #$00 STA $02F9
C199 CI9C
AD 6C 02 DO 2A
LDA $026C BNE $C1C8
C19E CIAO CIAI CIA3 C1A5 C1A7 CIi\A ClAD CIAF ClB2 ClB3 CIB5 CIB7 C1BA
AO 98 84 84 84 20 20 A5 8D AA A9 95 20 4C
LDY TYA STY STY STY JSR JSR LDA STA TAX LDA STA JSR JMO
00 80 81 A3 C7 E6 23 C1 7F 8E 02 00 FF BD C1 DA D4
not found 31, 'syntax error' number of cmd word command number < 9? test for 'R' , 'S' , and 'N' command number jump address 10 jump address hi jump to command prepare error msg after executing cmd clear flag for no BAM write error flag set? yes, then set error message
#$00 $80 $81 $A3 $E6C7 $C123 $7F $028E #$00 $FF,X $C1BD $D4DA
****************************** 1-\0 28 LDY #$28 C1BD LDA #$00 A9 00 C1BF
183
error number 0 track number 0 sector number 0 prepare 'ok' msg erase error flag drive number save as last drv #
erase input buffer close internal channel erase input buffer erase 41 characters
ABACUS Software
C1C1 C1C4 C1C5 C1C7
99 00 02 88 10 FA 60
Anatomy of the 1541
STA $0200,Y DEY BPL $C1C1 RTS
****************************** C1C8 C1CA C1CC C1CE
AO 84 84 4C
00 80 81 45 E6
LDY STY STY JMP
#$00 $80 $81 $E645
****************************** C1D1 A2 00 LDX #$00 C1D3 STX $027A 8E 7A 02 C1D6 A9 3A LDA #$3A C1D8 20 68 C2 JSR $C268 C1DB C1DD C1DE C1DF
FO 05 88 88 8C 7A 02
BEQ $C1E2 DEY DEY STY $027A
CIE2
4C 68 C3
JMP $C368
$200 to $228
output error msg (track & sector 0) track = 0 sector = 0 error number in A, generate error msg check input
1 '
~lne
pointer to drive # I
•
I
test line t.o ' • to end no colon found?
I
or
points to drive # (before colon) get drive # and turn LED on
****************************** C1E5 AO 00 LDY #$00 C1E7 A2 00 LDX #$00 C1E9 A9 3A LDA #$3A C1EB 4C 68 C2 JMP $C268
check input line ptr to input buffer counter for commas
****************************** C1EE JSR $CIE5 20 E5 C1
check input line test line to ' . , or end colon found?
C1F1 C1F3 C1F5 C1F8
DO 05 A9 34 4C C8 C1 88
BNE $CIF8 LDA #$34 JMP $CIC8 DEY 184
I
•
I
test line to colon or to end
34,
'syntax error'
ABACUS Software
Anatomy of the 1541
C1F9 C1FA C1FD C1FE
88 8C 7A 02 8A DO F3
DEY STY $027A TXA BNE $C1F3
C200 C202 C205 C206 C208 C20A C20C
A9 20 8A FO A9 09 8D
LDA JSR TXA BEQ LDA ORA STl'1.
C20F C2l0 C2l3 C2l6 C219 C21B C21D C220 C223 C225 C228 C229 C22B C22E
E8 8E 8E AD FO A9 OD 8D A9 8D 98 FO 9D
C231 C234 C236 C239 C23A C23D C23E C24A C243 C245 C248 C24A C24C
8D A9 20 E8 8E CA AD FO A9 EC FO 09 09
3D 68 C2 02 40 21 8B 02 77 78 8A OD 80 8B 8B 00 8A
02 02 02 02 02 02
29 7A 02 AD 77 02 79 02 8D 68 C2 78 02 8A 02 02 08 77 02 02 04 03
INX S'I,·( STX LDA BEQ LDA ORA STA LDA STA TYA BEQ STA LDA STA LDA JSR INX STX DEX LDA BEQ LDA. CPX BEQ ORA ()P,A
#$3D $C268 $C20A #$40 #$21 $028B $0277 $0278 $028A $C228 #$80 $028B $028B #$00 $028A $C254 $027A,X $0277 $0279 #$8D $C268
set ptr to pos of the " , " before yes, then error'
colon drive # the 11 • " 'syntax
'='
check input to 1==' comma found? no set bit 6 and bit 0 and 5 flag for syntax check
wildcard found? no set bit 7 reset wildcard flag '=' found? no number of commas before '='
$0278
shift CR check line to end increment comma ctr store # of commas
$028A $C245 #$08 $0277 $C24C #$04 #$03
wildcard found? no set bit 3 comma after '='? no set bit 2 set bits 0 and 1
185
ABACUS Software
Anatomy of the 1541
C24E C251
4D 8B 02 8D 8B 02
EOR $028B STA $028B
C254 C257 C25A
AD BB 02 AE 2A 02
3D A5 FE
LDA $028B LDX $022A AND $FEA5,X
C25D C25F C260 C263 C265
DO 60 8D A9 4C
BNE RTS STA LDA JMP
01 6C 02 30 C8 C1
$C260 $026C #$30 $C1C8
****************************** C268 C26B C26E C270
8D CC BO B1
C272 C273 C276 C278 C27A C27C C27E C280 C283 C285 C287 C288 C28B C28E C290 C292 C294 C296
C8 CD FO C9 FO C9 DO EE C9 DO 98 9D AD 29 FO A9 95 8D
C299 C29A
E8 EO 04
75 02 74 02 2E A3 75 02 28 2A 04 3F 03 8A 02 2C E4 7B 02 8A 02 7F 07 80 E7 8A 02
STA CPY BCS LDA INY CMP BEQ CMP BEQ CMP BNE INC CMP BNE TYA STA LDA AND BEQ LDA STA STA
$0275 $0274 $C29E ($A3),Y
as flag for syntax check syntax flag command number combine with check byte syntax error? set error flag 30,
'syntax error'
search characters in input buffer save character already done? yes get char from buffer
$0275 $C2AO #$2A $C280 #$3F $C283 $028A #$2C $C26B
compared with char found '* ,
$027B,X $028A #$7F $C299 #$80 $E7,X $028A
note comma position wildcard flag
INX CPX #$04
186
'? ' set wildcard flag
,, ,
no wildcard note flag and save as wildcard flag inc comma counter 4 commas already?
Anatomy of the 1541
ABACUS Software
C29C C29E C2AO C2A3 C2A6 C2A9 C2AB C2AD C2AF C2B1 C2B2
90 AO AD 9D AD 29 FO A9 95 98 60
CD 00 74 02 7B 02 8A 02 7F 04 80 E7
BCC LOY LOA STA LDA AND BEQ LDA STA TYA RTS
$C26B #$00 $0274 $027B ,X $028A #$7F $C2B1 #$80 $E7,X
***** ***** ***** ***** ***** ***** LDY $A3 A4 A3 C2B3 C2B5 C2B7 C2B8 C2BA
FO 14 88 FO 10 B9 00 02
C2BD C2BF C2C1 C2C2 C2C5 C2C7 C2C9 C2CA
C9 FO 88 B9 C9 FO C8 C8
C2CB C2CE
8C 74 02 CO 2A
C2DO C2D2 C2D4 C2D7 C2D9
AO 90 8C A9 4C
OD OA 00 02 OD 02
FF 08 2A 02 32 C8 C1
BEQ $C2CB DEY BEQ $C2CA LDA $0200 ,Y CMP BEQ DEY LDA CMP BEQ INY INY
set flag for ln end wild card flag no wild card set flag
check line lengt h ptr in comm and inpu t buff er zero?
#$OD $C2CB
one? char from inpu t buff er 'CR' yes, line end
$0200 ,Y #$OD $C2CB
prece ding char acter 'CR' yes
STY $0274 CPY #$2A LDY BCC STY LDA JMP
no, conti nue
#$FF $C2DC $022A #$32 $C1C8
187
poin ter to old value again same line lengt h comp are with 42 char acter s smal ler, then ok 32, 'synt ax erro r' line too long
ABACUS Software
Anatomy of the 1541
****************************** C2DC C2DE C2DF
AO 00 98 85 A3
C2E1 C2E4 C2E7 C2EA C2EC C2EF C2F2 C2F5 C2F8 C2FB C2FD
8D 8D 8D 85 8D 8D 8D 8D 8D A2 9D
58 4A 96 D3 79 77 78 8A 6C 05 79
C300 C302 C304 C306 C308 C30B C30E C30F C311
95 95 95 95 9D 9D CA DO 60
D7 DC E1 E6 7F 02 84 02 EC
LDY #$00 TYA STA $A3 02 02 02 02 02 02 02 02 02
STA STA STA STA STA STA STA STA STA LDX STA
$0258 $024A $0296 $D3 $0279 $0277 $0278 $028A $026C #$05 $0279,X
STA STA STA STA STA STA DEX BNE RTS
$D7,X $DC,X $E1, X $E6, X $027F,X $0284,X
A6 D3
pointer to input buffer 10 record length file type comma counter
"
"
wildcard flag error flag flags for line analysis directory sectors buffer pointers drive numbers wildcard flags track numbers sector numbers
$C2FD
****************************** C312 AD 78 02 LDA $0278 C315 8D 77 02 STA $0277 C318 A9 01 LDA #$01 C31A 8D 78 02 STA $0278 C31D 8D 79 02 STA $0279 C320 AC 8E 02 LDY $028E C323 A2 00 LDX #$00 C325 86 D3 STX $D3 C327 BD 7A 02 LDA $027A,X C32A 20 3C C3 JSR $C33C C32D
clear flag for command input
LDX $D3
188
preserve drive # number of commas save # of drive numbers last drive number position of the get drive no. before colon
Anatomy of the 1541
ABACUS Software
C32F C332 C333 C335 C336 C339 C33B
9D 98 95 E8 EC 90 60
7A 02 E2 78 02 EA
STA TYA STA INX CPX BCC RTS
$027A
save exact position
$E2,X
drive # in tablE::
$0278 $C325
got all drive #s? no, continue
****************************** TAX AA C33C LDY #$00 C33D AO 00 LDA #$3A C33F A9 3A DD 01 02 CMP $0201,X C341 FO OC BEQ $C352 C344 DD 00 02 CMP $0200,X C346 BNE $C361 DO 16 C349 INX C34B E8 TYA C34C 98 AND #$01 C34D 29 01 TAY C34F A8 TXA 8A C350 RTS C351 60 00 02
LDA INX INX CMP BEQ CMP BEQ BNE TYA ORA
colon behind it? yes colon here? no drive number
get drive number
#$30 $C34D #$31 $C34D $C34C
'0' ? yes '1' ? yes no,use last drive # last drive number set bit 7, unclear drive # clear remaining bits
BD E8 E8 C9 FO C9 FO DO 98 09
C364
29 81
AND #$81
C366
DO E7
BNE $C34F
80
' .,
$0200,X
C352 C355 C356 C357 C359 C35B C35D C35F C361 C362
30 F2 31 EE EB
search for drive # note position
#$80
****************************** LDA #$00 A9 00 C368 STA $028B 8D 8B 02 C36A
189
get drive number clear syntax flag
Anatomy of the 1541
ABACUS Software
C36D C370
AC 7A 02 Bl A3
LDY $027A LDA ($A3),Y
C372 C375 C377 C378 C37B C37D C380 C381
20 10 C8 CC BO AC 88 DO
BD C3 11
$C3BD $C388
ED
JSR BPL INY CPY BCS LDY DEY BNE
C383 C386 C388 C38A C38C
CE A9 29 85 4C
8B 02 00 01 7F 00 Cl
DEC LDA AND STA JMP
$028B #$00 #$01 $7F $CIOO
74 02 06 74 02
$0274 $C383 $0274 $C370
pos in cmd line get chars from cmd buffer get drive number certain number? increment pOlnter line end? yes search line for drive no.
drive number turn LED on
****************************** C38F A5 7F LDA $7F 49 01 EOR #$01 C391 29 01 AND #$01 C393 STA $7F 85 7F C395 C397 RTS 60
reverse drive # drive number switch bit 0
****************************** LDY #$00 C398 AO 00 C39A AD 77 02 LDA $0277 CMP $0278 C39D CD 78 02 C3AO FO 16 BEQ $C3B8 C3A2 CE 78 02 DEC $0278 C3A5 AC 78 02 LDY $0278 LDA $027A,Y B9 7A 02 C3A8
establish file type
C3AB C3AC C3AE
A8 Bl A3 AO 04
TAY LDA ($A3),Y LDY #$04
C3BO C3B3 C3B5
D9 BB FE FO 03 88
CMP $FEBB,Y BEQ $C3B8 DEY
190
'='
found?
no get pointer set pointer to char behind '=' char from buffer compare with marker for file type 'S' , 'P' , 'U' , 'R' match?
ABACUS Software
Anatomy of the 1541
C3B6 C3B8 C3B9
DO F8 98 8D 96 02
BNE $C3BO TYA STA $0296
C3BC
60
RTS
****************************** C3BD CMP #$30 C9 30 C3BF FO 06 BEQ $C3C7 CMP #$31 C3C1 C9 31 FO 02 BEQ $C3C7 C3C3 09 80 ORA #$80 C3C5 C3C7 C3C9
29 81 60
note file type (1-4) check drive number '0 ' '1 ' no zero or one, then set bit 7
AND #$81 RTS
****************************** C3CA A9 00 LDA #$00 STA $6F C3CC 85 6F C3CE 8D 8D 02 STA $028D 48 PHA C3D1 C3D2 AE 78 02 LDX $0278 C3D5 PLA 68 ORA $6F 05 6F C3D6 PHA C3D8 48 LDA #$01 C3D9 A9 01 STA $6F C3DB 85 6F DEX C3DD CA BMI $C3EF C3DE 30 OF B5 E2 LDA $E2,X C3EO 10 04 BPL $C3E8 C3E2 ASL $6F 06 6F C3E4 ASL $6F C3E6 06 6F 4A LSR A C3E8 BCC $C3D5 C3E9 90 EA $6F ASL 06 6F C3EB $C3D5 BNE DO E6 C3ED PLA C3EF 68 TAX AA C3FO LDA $C43F,X BD 3F C4 C3F1 PHA 48 C3F4 191
verify drive number
# of drive numbers
get syntax flag
Anatomy of the 1541
ABACUS Software
3E E2 01 7F 8C 02 28 3D C6 12 8F C3
AND STA PLA ASL BPL LDA AND STA LDA BEQ JSR BEQ JSR
A $C43C $E2 #$01 $7F $028C $C434 $C63D $C420 $C38F
00 8C 02 3D C6 1E 74 CS C1
LDA STA JSR BEQ LDA JSR
#$00 $02SC $C63D $C439 #$74 $C1CS
C3F5 C3F7 C3FA C3FB C3FC C3FE C400 C402 C404 C407 C409 C40C C40E
29 8D 68 OA 10 A5 29 85 AD FO 20 FO 20
C411 C413 C416 C419 C41B C41D
A9 8D 20 FO A9 20
C420
20 SF C3
JSR $C3SF
C423 C426 C427
20 3D C6 OS 20 SF C3
JSR $C63D PHP JSR $C3SF
C42A C42B C42D C42F C432 C434 C437 C439 C43C
2S FO A9 SD FO 20 DO 4C 2A
PLP BEQ LDA STA BEQ JSR BNE JMP ROL
C43D
4C 00 C4
03 8C 02
OC 00 SC 02 05 3D C6 E2 00 C1
#$03 $028C
$C439 #$00 $02SC $C439 $C63D $C41B $C100 A
JMP $C400
192
isolate drive #
initialze drive error? switch to other drive initialize drive no error? 74, 'drive not ready' initialize drive switch to other drive no error? number of drives initialize drive error? Turn LED on drive # from carry after bit 0
Anatomy of the 1541
ABACUS Software
***** ***** ***** ***** ***** ***** C440 C448
flags for drive check
00 80 41 01 01 01 01 81 81 81 81 42 42 42 42
***** ***** ***** ***** ***** ***** CA C3 00 92 02 AC C5
JSR LDA STA JSR
$C3CA #$00 $0292 $C5AC
C44F C452 C454 C457
20 A9 8D 20
C45A C45C C45F C461
DO 19 CE 8C 02 10 01 60
C462 C464 C467 C46A C460
A9 80 20 20 4C
C470
20 17 C6
JSR $C617
C473 C475 C478 C47B C470
FO 10 20 D8 C4 AD 8F 02 FO 01 60
BEQ JSR LDA BEQ RTS
$C485 $C4D8 $028F $C47E
C47E C481 C483 C485 C488 C48A
AD 53 02 30 ED 10 FO AD 8F 02 FO 02 60
LOA BMI BPL LOA BEQ RTS
$0253 $C470 $C475 $028F $C45C
C48B
20 04 C6
JSR $C604
C48E
FO 1A
BEQ $C4AA
01 8D 8F 00 52
02 C3 C1 C4
BNE $C475 DEC $028C BPL $C462 RTS LOA STA JSR JSR JMP
#$01 $0280 $C38F $C100 $C452
193
searc h for file in direc tory initi alize drive poin ter read first direc tory block entry prese nt? drive numb er clear ? no
chang e drive turn LEO on and searc h searc h for next file in direc tory not found ? verif y dir entry more files ?
file not found ? yes
searc h next direc tory block not found ?
ABACUS Software
Anatomy of the 1541
C490
DO 28
C492 C494 C497 C49A C49D C49F C4A2 C4A5 C4A7 C4AA C4AD C4AF C4B2 C4B4
A9 8D 20 20 A9 8D 20 DO 8D AD DO CE 10 60
01 8D 8F 00 00 92 AC 13 8F 8F 28 8C DE
C4B5 C4B8 C4BA C4BD C4CO C4C2 C4C5 C4C7
20 FO 20 AE 10 AD FO DO
17 FO D8 53 07 8F EE OE
C4C9 C4CC C4CE C4DO C4D2
AD FO B5 29 CD
96 02 09 E7 07 96 02
C4D5 C4D7
DO DE 60
BNE $C4B5 RTS
C4D8 C4DA C4DD C4DE C4E1 C4E4
A2 8E E8 8E 20 FO
LDX STX INX STX JSR BEQ
BNE $C4BA 02 C3 C1 02 C5 02 02 02
C6 C4 02 02
FF 53 02 8A 02 89 C5 06
LDA STA JSR JSR LDA STA JSR BNE STA LDA BNE DEC BPL RTS
#$01 $028D $C38F $C100 #$00 $0292 $C5AC $C4BA $028F $028F $C4D7 $028C $C492
JSR BEQ JSR LDX BPL LDA BEQ BNE
$C617 $C4AA $C4D8 $0253 $C4C9 $028F $C4B5 $C4D7
LDA BEQ LDA AND CMP
$0296 $C467 $E7,X #$07 $0296
#$FF $0253 $028A $C589 $C4EC 194
change drive turn LED on read dir block found?
next entry in dir not found? check entry file found? yes no, then done
file type same as desired file type? no
flag for file found set pointer to file
Anatomy of the 1541
ABACUS Software
C4E6
60
C4E7 C4EA C4EC C4EE C4FO C4Fl C4F3 C4F5 C4F7 C4F9 C4FC C4FE C501 C502 C505 C507
20 DO A5 55 4A 90 29 FO A9 CD FO BD
RTS 94 C5 FA 7F E2 OB 40 FO 02 8C 02 E9 7A 02
AA
20 A6 C6 AO 03 4C ID C5
C50A
BD 00 02
C50D C50F C511 C513 C515 C517
Dl FO C9 DO B1 C9
C519 C51B C51C C51D
FO cc E8 C8 EC 76 02
C520 C522 C525 C527 C529
BO BD C9 FO DO
C52B C52D
CO 13 BO 06
94 OA 3F D2 94 AO
09 00 02 2A OC DF
JSR BNE LDA EOR LSR BCC AND BEQ LDA CMP BEQ LDA TAX JSR LDY JMP
$C594 $C4E6 $7F $E2,X A $C4FE #$40 $C4E7 #$02 $028C $C4E7 $027A ,X
ptr to next file end, then done drive numb er
$C6A6 #$03 $C51D
get len of filen ame
LDA $0200 ,X CMP BEQ CMP BNE LDA CMP
($94) ,Y $C51B #$3F $C4E7 ($94) ,Y #$AO
BEQ $C4E7 INX INY CPX $0276 BCS LDA CMP BEQ BNE
$C52B $0200 ,X #$2A $C535 $C50A
CPY #$13 BCS $C535
195
searc h both drive s yes
get chars out of comm and line same char in dir? yes I? I no shif t blank , end of name? yes incre ment poin ter end of the name in the comm and? yes next char acter I* I yes, file found else cont searc h 19 reach ed end of name
ABACUS Software
C52F C531
B1 94 C9 AO
C533 C535 C538 C53B C53D C53F C542 C545 C547 C549 C54B C54D C54F C550 C551
DO AE 8E B5 29 80 AD 95 A5 95 AO B1 C8 48 29
B2 79 53 E7 80 8A 94 DD 81 D8 00 94
C553 C555 C556 C558 C55A C55C C55E C560 C562 C564
85 68 29 30 09 29 05 85 A9 35
6F
C566 C568 C56A C56C C56E C570 C572 C574 C577 C578 C57A
05 95 B5 29 05 95 Bl 9D C8 Bl 9D
Anatomy of the 1541
LDA ($,94 ),Y CMP #$AO 02 02 02 02
40
DF 02 20 27 6F 6F 80 E7 6F E7 E2 80 7F E2 94 80 02 94 85 02
BNE LDX STX LDA AND STA LOA STA LDA STA LDY LDA INY PHA AND STA PLA AND BMI ORA AND ORA STA LDA AND ORA STA LDA AND ORA STA LDA STA INY LDA STA
$C4E7 $0279 $0253 $E7,X #$80 $028A $0294 $DD,X $81 $D8,X #$00
shif t blank , end of name not found
secto r # of the dir ente r in table
($94) ,Y
file type
#$40
isola te scrat chprote ct bit ( 6) and save
$6F #$DF $C55C #$20 #$27 $6F $6F #$80 $E7,X $6F,X $E7,X $E2,X #$80 $7F $E2,X
clea r bit 7 set bit 5 clea r bits 3 and 4 get bit 6 again isola te flag for wildc ard write in table drive numb er
($94) ,Y
$0280 ,X
first track of file
($94) ,Y
$0285 ,X
196
get secto r from dir
Anatomy of the 1541
ABACUS Software
C57D C580 C582 C584 C586 C589 C58B C58E C591 C594 C597 C599
58 07 15 94 58 FF 8F AD 78 8D 79 CE 79 10 01 60 AD
DO AO B1 8D A9 8D
02
02 02 02 02 02
LDA BNE LDY LDA STA LDA STA LDA STA DEC BPL RTS
$0258 $C589 #$15 ($94),Y $0258 #$FF $028F $0278 $0279 $0279 $C59A
C59A C59D C59F C5A1 C5A4 C5A6 C5A8 C5AB
AE B5 30 BD DO A9 8D 60
79 02 E7 05 80 02 EE 00 8F 02
LDX LDA BMI LDA BNE LDA STA RTS
$0279 $E7,X $C5A6 $0280,X $C594 #$00 $028F
C5AC C5AE C5B1 C5B2 C5B5 C5B8 C5BA C5BC C4BE C5C1 C5C4 C5C7 C5C9
AO 00 8C 91 02 88 8C 53 02 AD 85 FE 85 80 A9 01 85 81 8D 93 02 20 75 D4 AD 93 02 DO 01 60
LDY STY DEY STY LDA STA LDA STA STA JSR LDA BNE RTS
#$00 $0291
C5CA C5CC
A9 07 8D 95 02
LDA #$07 STA $0295
C5CF
A9 00
LDA #$00
$0253 $FE85 $80 #$01 $81 $0293 $D475 $0293 $C5CA
197
record length record length get from directory
wildcard flag set? yes trk # already set? yes
18, directory track sector 1 read sector
number of directory entries (-1 )
ABACUS Software
Anatomy of the 1541
C5D1
20 F6 D4
JSR $D4F6
C5D4 C5D7 C5DA C5DD C5DF C5E1 C5E3 C5E6 C5ES
SD 20 CE AO B1 DO
93 ES 95 00 94 lS AD 91 DO 2F 20 3B
STA JSR DEC LDY LDA BNE LDA BNE JSR
$0293 $D4ES $0295 #$00 ($94),Y $C5FB $0291 $C617 $DE3B
C5EB C5ED C5FO C5F2 C5F5 C5FS C5FA
A5 SD A5 AE SD FO 60
Sl 91 02 94 92 02 92 02 1D
LDA STA LDA LDX STA BEQ RTS
$Sl $0291 $94 $0292 $0292 $C617
C5FB C5FD C600 C602
A2 EC DO FO
01 92 02 2D 13
LDX CPX BNE BEQ
#$01 $0292 $C62F $C617
C604 C607 C609 C60C C60E C611 C614 C617 C619
AD S5 S5 SO AD 90 S5 Sl 20 75 AD 94 20 CS AD FF SD 53
LDA STA LDA STA JSR LDA JSR LDA STA
$FES5 $SO $0290 $81 $D475 $0294 $D4CS #$FF $0253
C61C C61F
AD 95 02 30 OS
LDA $0295 BMI $C629
C621 C623
A9 20 20 C6 D1
LDA #$20 JSR $D1C6
02 D4 02
02 DE
FE 02 D4 02 D4 02
198
get char from buffer save as track # set buffer pointer decrement counter first byte from dir
get track and sector number sector number buffer pointer
buffer ptr to one?
lS, track # of BAM track number sector number read block set buffer pointer clear flag for file found all directory entries checked? inc buffer ptr by 32, next entry
ABACUS Software
Anatomy of the 1541
C626
4C D7 C5
JMP $C567
and continue
C629 C62C
20 4D D4 4C C4 C5
JSR $D44D JMP $C5C4
set buffer pointer read next block
C62F C631 C634
AS 94 8D 94 02 20 3B DE
LDA $94 STA $0294 JSR $DE3B
C637 C639 C63C
AS 81 8D 90 02 60
LDA $81 STA $0290 RTS
******************************
get track & sector no. from buffer save sector number test and initialize drive
C63D C63F C641 C643 C645 C647 C649 C64C C64F C651 C653 C655 C657 C659
AS DO A6 56 90 A9 8D 20 AO C9 FO C9 FO C9
68 28 7F 1C 22 FF 98 02 OE DO FF 02 OA 03 06 OF
LDA BNE LDX LSR BCC LDA STA JSR LDY CMP BEQ CMP BEQ CMP
$68 $C669 $7F $lC,X $C669 $FF $0298 $DOOE #$FF #$02 $C65F #$03 $C65F #$OF
C65B C65D C65F C661 C662 C664 C666 C669 C66B C66D
FO AO A6 98 95 DO 20 A6 B5 60
02 00 7F
BEQ LDY LDX TYA STA BNE JSR LDX LDA RTS
$C65F #$00 $7F
drive number
$FF,X $C669 $D042 $7F $FF,X
save error flag error? load BAM drive number transmit error code
FF 03 42 DO 7F FF
199
drive number disk changed? no, then done set error flag read dir track 20, 'read error'? yes 21, 'read error'? yes 74, 'drive not ready'? yes
ABACUS Software
Anatomy of the 1541
****************************** C66E C66F C672
48 20 A6 C6 20 88 C6
PHA JSR $C6A6 JSR $C688
C675 C676 C677
68 38 ED 4B 02
PLA SEC SBC $024B
C67A C67B C67D C67F C681 C683 C684 C685 C687
AA
TAX BEQ BCC LDA STA INY DEX BNE RTS
FO 90 A9 91 C8 CA DO 60
OA 08 AO 94 FA
$C687 $C687 #$AO ($94),Y
name of file in directory buffer get end of the name write filename in buffer compare len with max length
pad with shift spc
$C681
****************************** C688 98 TYA C689 OA ASL A C68A A8 TAY C68B B9 99 00 LDA $0099,Y C68E 85 94 STA $94 C690 B9 9A 00 LDA $009A C693 85 95 STA $95 C695 AO 00 LDY #$00 C697 BD 00 02 LDA $0200,x C69A C69C C69D
91 94 C8 FO 06
STA ($94),Y INY BEQ $C6A5
C69F C6AO C6A3 C6A5
E8 EC 76 02 90 F2 60
INX CPX $0276 BCC $C697 RTS
200
buffer number times 2 as pointer bffr ptr to $94/$95 transmit characters in buffer buffer already full?
-----~-----------
ABACUS Software
Anatomy of the 1541
****************************** C6A6 C6A8 C6AB C6AC C6AD
A9 00 8D 4B 02 8A 48 BD 00 02
C6BO C6B2 C6B4 C6B6 C6B8 C6BB C6BC C6BE C6C1 C6C3 C6C6 C6C8 C6CB C6CC C6CD
C9 FO C9 FO EE E8 A9 CD 90 EC 90 8E 68
2C 14 3D 10 4B 02 OF 4B 02 05 74 02 E5 76 02
AA
60
LDA #$00 STA $024B TXA PHA LDA $0200,X CMP BEQ CMP BEQ INC INX LDA CMP BCC CPX BCC STX PLA TAX RTS
#$2C $C6C8 #$3D $C6C8 $024B #$OF $024B $C6C8 $0274 $C6AD $0276
search for end of name in command preparation for len get characters out of buffer
,, , '='
inc len of name 15 greater? end of input line?
ptr to end of name
****************************** LDA $83 AS 83 C6CE 48 PHA C6DO C6D1 C6D3 C6D4
A5 82 48 20 DE C6
LDA $82 PHA JSR $C6DE
C6D7 C6D8 C6DA C6DB C6DD
68 85 82 68 85 83 60
PLA STA $82 PLA STA $83 RTS
secondary address and channel no. create file entry for directory get data back
****************************** LDA #$11 A9 11 C6DE STA $83 85 83 C6EO
201
17 secondary address
ABACUS Software
Anatomy of the 1541
C6E2
20 EB DO
JSR $DOEB
C6E5 C6E8 C6EB C6ED C6FO C6F2
20 E8 D4 AD 53 02 10 OA AD 8D 02 DO OA 20 06 C8
JSR LDA BPL LDA BNE JSR
$D4E8 $0253 $C6F7 $028D $C6FC $C806
C6F5 C6F6 C6F7 C6FA C6FC C6FF C701 C704 C707
18 60 AD FO CE DO CE 20 20
CLC RTS LDA BEQ DEC BNE DEC JSR JSR
$028D $C71B $028D $C70E $028D $C38F $C806
C70A C708
38 4C 8F C3
SEC JMP $C38F
C70E C710
A9 00 8D 73 02
LDA #$00 STA $0273
C713 C716 C719 C71A
8D 8D 02 20 B7 C7 38 60
STA $028D JSR $C7B7 SEC RTS
C71B C71D C71F C721 C724 C726 C728 C729 C72B C72E C730
A2 AO B1 8D FO A2 88 B1 8D EO FO
LDX LDY LDA STA BEQ LDX DEY LDA STA CPX BEQ
8D 1F 8D OD 8D 8F 06
02 02 02 C3 C8
18 1D 94 73 02 02 16 94 72 02 16 OA
#$18 #$1D ($94), Y $0273 $C728 #$16 ($94),Y $0272 #$16 $C73C
202
open channel for reading set buffer pointer not yet last entry? write 'blocks free. ,
change drive write 'blocks free. , change drive drive #. for header, hi-byte write header
number of blocks hi in buffer zero? number of blocks 10 in buffer
Anatomy of the 1541
ABACUS Software
C732 C734 C736 C737 C739 C73B C73C C73F C741 C742 C743 C745
C9 90 CA C9 90 CA 20 B1 48 OA 10 A9
OA 06 64 01 AC C7 94 05 3C
CMP BCC DEX CMP BCC DEX JSR LDA PHA ASL BPL LDA
#$OA $C73C
10
#$64 $C73C
100
$C7AC ($94),Y
erase buffer file type
A $C74A #$3C
bit 7 in carry bit 6 not set? ,= 2? get track and sector number s '? drive
Il1Jmr. l e
r
Anatomy of the 1541
ABACUS Software
DA01 DA03 DA06
A5 81 8D 6F 02 4C 99 C1
LDA $81 STA $026F JMP $C199
******************************
DA09 DAOC DAOF DA11 DA12 DA14
BC B9 AO 88 30 D9
7A 02 00 02 04
DA17 DA19 DA1C DAlE DA1F DA21
DO 8C AO 88 30 D9
DA24 DA26 DA29
DO F8 8C 4A 02 60
08 B2 FE F8 97 02 05 08 B6 FE
LDY LDA LDY DEY BMI CMP
$027A,X $0200,Y #$04
BNE STY LDY DEY BMI CMP
$DA11 $0297 #$05
$DA1C $FEB2,Y
$DA29 $FEB6,Y
BNE $DA1E STY $024A RTS
******************************
DA2A
20 39 CA
JSR $CA39
DA2D DA2F DA32 DA34
A9 20 FO 20
LDA JSR BEQ JSR
DA37 DA39 DA3A DA3B DA3D
A6 81 E8 8A DO 05 20 A3 D1
LDX $81 INX TXA BNE $DA42 JSR $D1A3
DA40 DA42
A9 02 20 C8 D4
LDA #$02 JSR $D4C8
80 A6 DD F6 95 DE
#$80 $DDA6 $DA 2A $DE95
272
sector
check file type and control mode pointer in cmd line get chars from line
control modes 'R' , 'w' , 'A' , 'M' save
file types 'D', 'S', 'P', 'U', 'L' save preparation for append open channel to read, get byte last byte? no get track and sector numbers sector number not $FF? close buffer, write block buffer pointer to 2
ABACUS Software
DA45 DA47 DA49 DA4B DA4D DA4F DA51 DA54
A6 A9 95 A9 05 A6 9D 60
82 01 F2 80 82 83 2B 02
Anatomy of the 1541
LDX LDA STA LDA ORA LDX STA RTS
$82 #$01 $F2,X #$80 $82 $83 $022B,X
****************************** DA55 A9 OC LDA #$OC DA57 8D 2A 02 STA $022A DA5A A9 00 LDA #$00 LDX $0274 DA5C AE 74 02 DA5F CA DEX DA60 FO OB BEQ $DA6D DA62 CA DEX BNE $DA86 DA63 DO 21 LDA $0201 DA65 AD 01 02 20 BD C3 JSR $C3BD DA68 BMI $DA86 DA6B 30 19 DA6D STA $E2 85 E2 INC $0277 DA6F EE 77 02 DA72 EE 78 02 INC $0278 INC $027A DA75 EE 7A 02 LDA #$80 DA78 A9 80 DA7A STA $E7 85 E7 DA7C A9 2A LDA #$2A DA7E 8D 00 02 STA $0200
DA81 DA84 DA86
8D 01 02 DO 18 20 E5 C1
STA $0201 BNE $DA9E JSR $C1E5
DA89 DA8B DA8E DA90 DA91 DA92
DO 20 AO 88 88 8C
BNE JSR LDY DEY DEY STY
05 DC C2 03 7A 02
$DA90 $C2DC #$03 $027A
273
channel number set flag for WRITE
channel # in table OPEN "$" command number 12
second character get drive number not a plain number?
set wildcard flag '* , as file name in command buffer unconditional jump test input line up to ' . , found? clear flags
pointer to drive # in command
ABACUS Software
Anatomy of the 1541
DA95 DA98 DA9B DA9E
20 20 20 20
DAA1 DAA4 DAA7
20 B7 C7 20 9D C4 20 9E EC
JSR $C7B7 JSR $C49D JSR $EC9E
DAAA
20 37 D1
JSR $D137
DAAD DAAF DAB2 DAB4
A6 9D A4 8D
82 3E 02 7F 8E 02
LDX STA LDA STA
$82 $023E $7F $028E
DAB7 DAB9 DABB DABD
09 95 A9 85
04 EC 00 A3
ORA STA LDA STA
#$04 $EC,X #$00 $A3
DABF
60
00 98 20 CA
C2 C3 C3 C3
JSR JSR JSR JSR
$C200 $C398 $C320 $C3CA
analyze line ascertain file type get drive number initialize drive 1'.f'..... necessary prepare disk title load directory create and prepare directory get byte from buffer channel number byte in output reg drive number save as last drive number PRG-flag reset pointer in input buffer
RTS
****************************** DACO A9 00 LDA #$00 DAC2 8D F9 02 STA $02F9 DAC5 A5 83 LDA $83 DAC7 DO 08 BNE $DAD4 DAC9 A9 00 LDA #$00 DACB DACE DAD1
8D 54 02 20 27 D2 4C DA D4
STA $0254 JSR $D227 JMP $D4DA
DAD4 DAD 6
C9 OF FO 14
CMP #$OF BEQ $DAEC
DAD8 DADE DADD
20 02 DB A5 83 C9 02
JSR $DB02 LDA $83 CMP #$02
274
CLOSE-routine secondary address not zero? secondary address 0, LOAD close channel close internal channels 17 & 18 15 "1 1 yes, close a~~ channels close file secondary address
ABACUS Software
DADF DAEI DAE4 DAE6 DAE9 DAEC DAEE DAFO DAF3 DAF5 DAF7 DAFA DAFC DAFF
Anatomy of the 1541
DO 03 4C 94 C1
BCC LDA BNE JMP
$DAD1 $026C $DAE9 $C194
4C A9 85 20 C6 10 AD DO 4C 4C
JMP LDA STA JSR DEC BPL LDA BNE JMP JMP
$C1AD #$OE $83 $DB02 $83 $DAFO $026C $DAFF $C194 $CIAD
90 t 0 1
A.D
f~' ) ....."
AD OE 83 02 83 F9 6C 03 94 AD
02
C1 DB 02 C1 Cl
****************************** LDX $83 A6 83 DB02 .Bll 2B 02 LDA $022B,X DB04 CMP #$FF DB07 C9 FF ~
DB09 DBOB
DO 01 60
BNE $DBOC RTS
DBOC DBOE DBIO DB13 DB15 DB17 DB19 DBIB
29 85 20 C9 FO C9 FO 20
AND STA JSR CMP BEQ CMP BEQ JSR
DBIE
BO 09
BCS $DB29
DB20 DB23
20 62 DB 20 A5 DB
JSR $DB62 JSR $DBA5
DB26 DB29
20 F4 EE 4C 27 D2
JSR $EEF4 JMP $D227
OF 82 25 D1 07 OF 04 11 07 D1
#$OF $82 $D125 #$07 $DB26 #$04 $DB2C $Dl07
275
less than 2? termination 14 secondary address close file next secondary addr
termination close file secondary address get channel number no channel assigned? no, then done isolate channel # check file type direct access? yes reI-file? yes channel for writing open no file for writing? write last block write entry in dir and block write BAM close channel
Anatomy of the 1541
ABACUS Software
DB2C
20 F1 DD
JSR $DDF1
DB2F DB32
20 1E CF 20 CB E1
JSR $CF1E JSR $E1CB
DB35 DB37 DB39 DB3B DB3D DB3F DB41 DB43 DB44 DB46 DB48
A6 86 E6 A9 85 85 A5 38 E9 85 20
D5 73 73 00 70 71 D6
$D5 $73 $73 #$00 $70 $71 $D6
OE 72 51 DF
LDX STX INC LDA STA STA LDA SEC SBC STA JSR
DB4B DB4D DB4F DB51 DB53 DB55 DB57 DB5A DB5C DB5F
A6 A5 95 A5 95 A9 20 FO 20 AC
82 70 B5 71 BB 40 A6 DD 03 A5 DB 27 D2
LDX LDA STA LDA STA LDA JSR BEQ JSR JMP
$82 $70 $B5,X $71 $BB,X #$40 $DDA6 $DB5F $DBA5 $D227
#$OE $72 $DF51
****************************** DB62 A6 82 LDX $82 DB64 B5 B5 LDA $B5,X DB66 15 BB ORA $BB,X DO OC DB68 BNE $DB76 DB6A 20 E8 D4 JSR $D4E8 DB6D CMP #$02 C9 02 DB6F DO 05 BNE $DB76 DB71 A9 OD LDA #$OD DB73 20 F1 CF JSR $CFF1 DB76 20 E8 D4 JSR $D4E8 DB79 C9 02 CMP #$02 DB7B DO OF BNE $DB8C 276
get buffer #, write block change buffer get last side-sector side-sector number
minus 14 for ptr calculate block number of file channel number record number 10 record number hi bit 6 set? no enter in dirctory close channel write last block channel number record number 10 record number hi not zero? set buffer pointer not 2 CR in buffer set buffer pointer now equal to 2? no
ABACUS Software
Anatomy of the 1541
DB7D DB80 DB82 DB84 DB86 DB88 DB8A DB8C DB8D DB8F DB90 DB92 DB95 DB98
20 A6 BS DO D6 D6 A9 38 E9 48 A9 20 20 68
IE CF 82 BS 02 BB BS 00
DB99 DB9C DB9F DBA2
20 20 20 4C
F1 C7 99 1E
01 00 C8 D4 F1 CF CF DO DS CF
JSR LDX LDA BNE DEC DEC LDA SEC SBC PHA LDA JSR JSR PLA
$CF1E $82 $BS,X $DB88 $BB,X $B5,X #$00 #$01 #$00 $04C8 $CFF1
JSR $CFF1 JSR $D0C7 JSR $DS99 JMP $CF1E
****************************** LDX $82 DBA5 A6 82 STX $0270 DBA7 8E 70 02 LDA $83 DBAA A5 83 PHA 48 DBAC LDA $0260,X BD 60 02 DBAD STA $81 DBBO 8S 81 LDA $0266,X DBB2 BD 66 02 STA $0294 DBBS 8D 94 02 LDA $EC,X DBB8 B5 EC AND #$01 DBBA 29 01 STA $7F DBBC 85 7F LDA $FE85 DBBE AD 85 FE STA $80 DBC1 85 80 JSR $DF93 20 93 DF OBC3 PHA 48 DBC6 STA $F9 DBC7 85 F9 JSR $D460 20 60 D4 DBC9 LDY #$00 AO 00 DBCC LDA $FEEO,X BD EO FE DBCE STA $87 DBD1 85 87
277
change buffer channel number record number 10 decrement blk # hi and block # 10 set pointer to end buffer ptr to zero write 0 in buffer second byte = pointer to end write in buffer write block to disk and verify change buffers directory entry channel number save secondary address save sector # in dir set pointer in dir
drive number 18, directory track set increment buffer # read dir block buffer address
ABACUS Software
94 02 86 86 20 43 25 01 04 44 86 8F 86
Anatomy of the 1541
DBD3 DBD6 DBD8 DBDA DBDC DBDE DBE1 DBE3 DBES DBE7 DBE9 DBEB DBEC DBEE DBFO DBF2 DBF4
AD 85 B1 29 FO 20 C9 FO B1 29 91 C8 B1 85 84 AO B1
DBF6 DBF7 DBF8
48 88 B1 86
PHA DEY LOA (:$86), Y
DBFA DBFC DBFE DBFF DCOl DC03
DO 85 68 85 A9 20
BNE STA PLA STA LOA JSR
DC06 DC07 DC09 DCOB DCOC DCOE DC OF DC11 DC13
48 A9 91 C8 91 68 A4 91 C8
DC14 DC16
B1 86 85 81
86 80 71 1B 86
OA 80 81 67 45 E6 00 86 86 71 86
LOA STA LOA AND BEQ JSR CMP BEQ LOA AND STA INY LOA STA STY LOY LOA
PHA LOA STA INY STA PLA LDY STA INY
$0294 $86 ($86), Y #$20 $DC21 $0125 #$04 $DC29 (:$86) ,Y #:$8F ($86), Y
buffer pointer
($86),Y $80 $71 #$lB ($86),Y
track number
$DC06 $80 $81 #$67 $E645 #$00 ($86),Y ($86) ,Y
file type file closed? yes check file type rel-file? yes clear bits 4,5, & 6 in file type
sectr # of the file for overwriting save track # for overwriting set? set track number sector number 67, 'illegal track or sector' erase track number and sector # of the substitute file
$71 ($86), Y set track & sec # of the new file
LDA ($86) ,Y STA $8l
278
ABACUS Software
Anatomy
DC18 DC19 DC1B DC1E
68 91 86 20 7D C8 4C 29 DC
PLA STA ($86),Y JSR $C870 JMP $OC29
DC21 OC23 OC25
B1 86 29 OF 09 80
LOA ($86),Y AND #$OF ORA #$80
DC27 DC29 OC2C OC2E DC30 DC32 OC33 DC35 DC37 OC38 DC39 DC3B DC40 DC41 DC43
91 AE AO B5 91 C8 B5 91 68
STA LOX LOY LOA STA INY LOA STA PLA TAX LOA JSR PLA STA JMP
86 70 02 1C B5 86 BB 86
AA
A9 20 68 85 4C
90 90 05 83 07 01
($86), Y $0270 #$lC $B5,X ($86), Y
erase old file get file type isolate bits 0-3 set bit 7 for closed file channel number block number 10 in directory entry and block number hi write buffer number
#$90 $0590
code for 'writing' write block
$83 $0107
secondary address open channel for writing
DC46 DC48
A9 01 20 E2 01
LOA #$01 JSR $01E2
OC4B DC4E DC51 DC52 OC53 OC55 OC57
20 AD 48 OA 05 95 20
JSR LOA PHA ASL ORA STA JSR
DC5A OC5C
A6 82 A5 80
7F EC 9B DO
1541
$BB,Y ($86), Y
******************************
B6 DC 4A 02
or the
$OCB6 $024A A $7F $EC,X $009B
LOX $82 LOA $80
279
read block, allocate buffer find channel and buffer for read set pointer file type save drive number read block in buffer channel number track
Anatomy of the 1541
ABACUS Software
05 81 44 02
DO A5 9D 68 C9 DO A4 B9 09 99
DC74 DC77 DC79
AD 58 02
95 C7 20 8E D2
LDA $0258 STA $C7,X JSR $D28E
DC7C DC7E DC81 DC83 DC85 DC88 DC8A DC8D De8F
10 4C A6 95 AC 84 AC 84 20
03 OF 82 CD 59 80 5A 81 D3
BPL JMP LDX STA LDY STY LDA STY JSR
$DC81 $D20F $82 $CD,X $0259 $80 $025A $81 $D6D3
DC92 DC95 DC98 DC9A DC9C DC9E DCAO DCA3 DCA6
20 20 A6 A9 95 A9 20 20 4C
73 99 82 02 C1 00 C8 53 3E
JSR JSR LDX LDA STA LDA JSR JSR JMP
$DE73 $D599 $82 #$02 $C1,X #$00 $D4C8 $E153 $DE3E
DCA9
20 56 D1
JSR $D156
DCAC DCAE DCB1
A6 82 9D 3E 02 A9 88
LDX $82 STA $023E,X LDA #$88
04 3F 83 2B 02 40 2B 02
D2 02 02 D6 DE D5
D4 E1 DE
BNE LDA STA PLA CMP BNE LDA LDA ORA STA
$DC65 $81 $0244,X
DC5E DC60 DC62 DC65 DC66 DC68 DC6A DC6C DC6F DC71
#$04 $DCA9 $83 $022B,Y #$40 $022B,Y
280
following track? sector as end pointer file type rei-file? no secondary address channel number set flag for READ and WRITE record length find buffer for side-sector found? 70, 'no channel' channel number trk for side-sector sec for side-sector transmit parameters to disk controller read block and verify channel number pointer for writing buffer ptr to zero find next record get track and sector numbers get byte from buffer channel number byte in output reg set flag for READ
ABACUS Software
DCB3 DCB5
95 F2 60
Anatomy of the 1541
STA $F2,X RTS
****************************** DCB6 A6 82 LDX $82 DCB8 LDA $A7,X B5 A7 DCBA OA ASL A DCBB A8 TAY DCBC LDA #$02 A9 02 DCBE STA $0099,y 99 99 00 DCC1 B5 AE LDA $AE,X ORA #$80 DCC3 09 80 DCC5 DCC7 DCC8 DCC9 DCCB DCCE DCDO DCD2 DCD4 DCD6 DCD9
95 OA A8 A9 99 A9 95 95 A9 9D 60
AE
02 99 00 00 B5 BB 00 44 02
STA ASL TA-' LDA STA LDA STA STA LDA STA RTS
#$02 $0099,Y #$00 $B5,X $BB,X #$00 $0244,X
DCDA
20 A9 Fl
JSR $FIA9
DCDD DCDF
A9 01 20 DF Dl
LDA #$01 JSR $DIDF
DCE2
20 DO D6
JSR $D6DO
DCE5 DCE8 DCEA DCED DCEE DCEF DCF1
20 A6 AD 48 OA 05 95
JSR LDX LDA PHA ASL ORA STA
7F EC
buffer pointer 10 set bit 7, buffer not allocated
$AE,X A
******************************
B6 DC 82 4A 02
reset pointer channel number buffer number times 2
buffer pointer 10 block number 10 block number hi end pointer construct a new block find free sector in BAM
$DCB6 $82 $024A
open channel and allocate buffer transmit param to disk controller reset pointer channel number file type
A $7F $EC,X
drive number save as flag
281
Anatomy of the 1541
ABACUS Software
OCF3 OCF4 OCF6 OCF8 OCFA DCFC
68 C9 FO A9 95 60
OCFO OCFF 0002
A4 83 B9 2B 02 29 3F
LOY $83 LOA $022B,Y ANO #$3F
0004 0006 0009 OOOC OOOE
09 40 99 2B 02 AD 58 02 95 C7 20 8E 02
ORA #$40
STA LOA STA JSR
$022B,Y $0258 $C7,X $028E
0011 0013 0016 0018
10 4C A6 95
BPL JMP LOX STA
$0016 $020F $82 $CO,X
001A 0010
20 C1 OE 20 1E Fl
JSR $OEC1 JSR $F11E
0020 0022 0025 0027 002A D02C OD2E
A5 80 A5 80 A6 B5 20
80 59 02 81 5A 02 82 CO 03 06
LOA STA LOA STA LOX LOA JSR
$80 $0259 $81 $025A $82 $CO,X $0603
0031 0033 0036 0038
A9 20 A9 20
00 E9 OE 00 80 00
LOA JSR LOA JSR
#$00 $OEE9 #$00 $0080
003B 0030
A9 11 20 80 00
04 05 01 F2
03 OF 02 82 CO
PLA CMP BEQ LOA STA RTS
#$04 $OCFO #$01 $F2,X
LOA #$11 JSR $0080
282
rei-file? yes set WRITE flag secondary address channel # in table clear the top two bits set bit 6 REAO and WRITE flag record length in table find buffer and allocate found? 70, 'no channel' channel number buffer number for side-sector erase buffer find free block in BAM track for 1st side-sector sector for side-sector channel number buffer number transmit param to disk controller buffer ptr to zero zero as track pointer in buffer 17 as end pointer in buffer
ABACUS Software
Anatomy of the 1541
DD40 DD42
A9 00 20 SD DD
LDA #$00 JSR $DDSD
DD45 DD48 DD4B
AD 5S 02 20 SD DD AS SO
LDA $0258 JSR $DD8D LDA $80
DD4D DD50 DD52 DD55 DD57 DD5A
20 A5 20 A9 20 20
JSR LDA JSR LDA JSR JSR
DD5D
A5 SO
LDA $80
DD5F DD62
20 SD DD A5 Sl
JSR $DD8D LDA $81
DD64 DD67 DD6A DD6D DD6F DD72 DD74 DD75 DD77 DD79 DD7B DD7E
20 20 20 A9 20 A6 38 A9 F5 95 20 20
8D 6C 99 02 CS S2
DDS1 DDS4 DDS7 DDSA
20 20 20 4C
SD Sl SD 10 E9 3E
DD DD DE DE
DD DE D5
$DDSD $81 $DD8D #$10 $DEE9 $DE3E
$DD8D $DE6C $D599 #$02 $D4C8 $S2
00 C7 C1 E2 E2 19 DE
JSR JSR JSR LDA JSR LDX SEC LDA SBC STA JSR JSR
5E 99 F4 98
JSR JSR JSR JMP
$DE5E $D599 $EEF4 $DC9S
D4
DE D5 EE DC
#$00 $C7,X $C1,X $E2E2 $DE19
****************************** DDSD DDSE
48 A6 82
PHA LDX $82
283
zero as side-sector number in buffer record length in buffer track number of this block in buffer sector number in buffer 16 buffer ptr to 16 get track and sector numbers track # of the first data block in buffer sector # of the first data block in buffer write block to disk and verify buffer pointer to 2 channel number record length pointer for writing erase buffer write link bytes in buffer write block to disk and verify write BAM and done write byte in side-sector block save byte channel number
Anatomy of the 1541
ABACUS Software
DD90
B5 CD
LDA $CD,X
DD92
4C FD CF
JMP $CFFD
****************************** DD95 BCC $DD9D 90 06 A6 82 LDX $82 DD97 DD99 15 EC ORA $EC,X DD9B DO 06 BNE $DDA3 A6 82 LDX $82 DD9D DD9F 49 FF EOR #$FF AND $EC,X DDA1 35 EC DDA3 STA $EC,X 95 EC DDA5 RTS 60 DDA6 DDA8 DDAA
A6 82 35 EC 60
LDX $82 AND $EC,X RTS
20 93 DF AA
BD 5B 02 29 FO C9 90 60
JSR TAX LDA AND CMP RTS
BD 2B 02
DDBE DDCO DDC2 DDC4 DDC5 DDC7
C9 DO A6 E8 EO 90
FF 08 71 10 FO
channel number clear flag
channel number test flag
$025B,X #$FO #$90
isolate cmd code code for writing?
LDA $022B,X CMP BNE LDX INX CPX BCC
channel number set flag
$DF93
****************************** DDB7 A2 00 LDX #$00 DDB9 STX $71 86 71 DDBB
manipulate flags
verify command code for writing get buffer number
****************************** DDAB DDAE DDAF DDB2 DDB4 DDB6
buffer # of the side-sector write byte in buffer
#$FF $DDCA $71 #$10 $DDB9 284
counter for secondary address get channel number from table file open? increment counter still less than 16?
ABACUS Software
DDC9
60
DDCA DDCC DDCE DDCF DDD2 DDD4 DDD6 DDD9 DDDB DDDD DDDF DDE1 DDE4 DDE6 DDE8 DDEB DDED DDEF DDFO
86 29 A8 B9 29 85 AE
B5 29 C5 DO B9 D5 DO B9 D5 DO 18 60
Anatomy of the 1541
RTS 71 3F EC 01 70 53 E2 01 70 E1 60 D8 DA 66 DD D3
00 02
02 02
STX AND TAY LDA AND STA LDX LDA AND CMP BNE LDA CMP BNE LDA CMP BNE CLC RTS
$71 #$3F $OOEC,Y #$01 $70 $0253 $E2,X #$01 $70 $DDC2 $0260,Y $D8,X $DDC2 $0266,Y $DD,X $DDC2
******************************
DDF1 DDF4 DDF6 DDF9 DDFC
20 9E DF 50 06 20 5E DE 20 99 D5 60
JSR BVC JSR JSR RTS
$DF9E $DDFC $DE5E $D599
20 AS 91 C8 AS 91 4C
2B DE 80 94 81 94 05 E1
JSR LDA STA INY LDA STA JMP
isolate drive #
isolate drive # same drive? no sector # in dir same as file? no pointer same? no
write a block of a rel-file get buffer number no rel-file? write block and verify
$DE2B $80 ($94),Y
write bytes for following track set buffer pointer track number in buffer
$81 ($94),Y $E105
sector number in buffer set rel-flag
******************************
DDFD DEOO DE02 DE04 DE05 DE07 DE09
isolate channel #
285
Anatomy of the 1541
ABACUS Software
****************************** DEOC DEOF DEll DE13 DE14 DE16 DE18
20 2B DE Bl 94 85 80 C8 B1 94 85 81 RTS
JSR LDA STA INY LDA STA
$DE2B (!$:94),Y $80 ($94),Y $81
20 A9 91 C8 A6 B5
2B DE 00 94 82 C1
AA
CA 8A 91 94 60
JSR LDA STA INY LDX LDA TAX DEX TXA STA RTS
following track sector #s buffer pointer following trk #
and sector #
$DE2B #$00 ($94),Y
following track for last block set buffer pointer zero as track number
$82 $Cl,X
channel number pointer in block
****************************** DE19 DE1C DElE DE20 DE21 DE23 DE25 DE26 DE27 DE28 DE2A
get and set get
minus 1 ($94),Y
as pointer in block
****************************** DE2B 20 93 DF JSR $DF93 DE2E OA ASL A DE2F AA TAX DE30 B5 9A LDA $9A,X DE32 STA $95 85 95 DE34 A9 00 LDA #$00 DE36 STA $94 85 94 DE38 AO 00 LDY #$00 DE3A RTS 60
buffer ptr to zero get buffer number times 2
****************************** DE3B 20 EB DO JSR $DOEB DE3E 20 93 DF JSR $DF93 DE41 STA $F9 85 F9 DE43 OA ASL A A8 TAY DE44
get trk and sector get channel number get buffer number save times 2
286
buffer pointer hi buffer pointer 10
ABACUS Software
Anatomy of the 1541
DE45 DE48 DE4A
B9 06 00 85 80 B9 07 00
LDA $0006,Y STA $80 LDA $0007,Y
DE4D DE4F
85 81 60
STA $81 RTS
****************************** DE.50 LDA #$90 A9 90 STA $024D DE52 8D 4D 02 DE55 DO 28 BNE $DE7F
get track and sector #s from disk controller
cmd code for write
#$80 $024D $DE7F #$90 $024D $DE8B
cmd code for read
A9 80 8D 4D 02 DO 1F
LDA #$·80 STA $024D BNE $DE8B
cmd code for read
DE6C DE6E DE71
A9 90 8D 4D 02 DO 02
LDA #$90 STA $024D BNE $DE75
cmd code for write
DE73 DE75 DE78 DE7A
A9 8D A6 B5
LDA STA LDX LDA
cmd code for read
DE7C DE7D DE7F
AA
DE57 DE59 DE5C DE5E DE60 DE63
A9 8D DO A9 8D DO
DE65 DE67 DE6A
DE82 DE85 DE86 DE88 DE8B
80 4D 02 21 90 4D 02 26
80 4D 02 82 CD
10 13 20 DO D6 20 93 DF AA
A5 7F 9D 5B 02 20 15 E1
LDA STA BNE LDA STA BNE
#$80 $024D $82 $CD,X
TAX BPL $DE92 JSR $D6DO JSR TAX LDA STA JSR
$DF93 $7F $025B,X $El15 287
cmd code for write
channel number side-sector buffer number buffer assigned? generate header for disk controller get buffer number drive number buffer number
Anatomy of the 1541
ABACUS Software
DE8E DE91 DE92
20 93 DF AA
4C 06 D5
JSR $DF93 TAX JMP $D506
****************************** DE95 DE97 DE9A DE9D DE9F DEA2 DEA4
A9 20 20 85 20 85 60
00 C8 D4 37 D1 80 37 D1 81
LDA JSR JSR STA JSR STA RTS
#$00 $D4C8 $D137 $80 $D137 $81
****************************** DEA5 48 PHA DEA6 A9 00 LDA #$00 DEA8 STA $6F 85 6F DEAA 85 71 STA $71 DEAC B9 EO FE LDA $FEEO,y DEAF STA $70 85 70 DFB1 BD EO FE LDA $FEEO,X DEB4 85 72 STA $72 DEB6 PLA 68 A8 DEB7 TAY DEB8 88 DEY DEB9 B1 6F LDA ($ 6F) , Y DEBB DEBD DEBE DECO
91 71 88 10 F9 60
STA ($71) , Y DEY BPL $DEB9 RTS
****************************** DEC1 A8 TAY DEC2 B9 EO FE LDA $FEEO,y DEC5 70 STA $70 85 DEC7 A9 00 LDA #$00 DEC9 85 6F STA $6F DECB A8 TAY DECC 91 6F STA ($ 6F) , Y
288
get buffer number write block get following track & sec from buffer buffer ptr to zero get byte save as track get byte as sector copy buffr contents
buffer addr Y, hi buffer addr X, hi
copy contents of buffer Y to buffer X
erase buffer Y buffer number get hi-address lo-address erase buffer
ABACUS Software
DECE DECF DEDl
C8 DO FB 60
Anatomy or the 1541
INY BNE $DECC RTS
****************************** DED2 A9 00 LDA #$00 DED4 20 DC DE JSR $DEDC DED? AO 02 LDY #$02 Bl 94 LDA ($94), Y DED9
DEDB
60
85 94 A6 82 B5 CD AA
BD EO FE 85 95 60
48 20 DC DE 48 8A OA AA
68 95 9A 68 95 99 60
byte 2 contains the side-sector #
$94 $82 $CD,X
set buffer ptr to side-sector pointer 10 channel number buffer number
STA LDX LDA TAX LDA STA RTS
$FEEO,X $95
buffer address hi set
$DEDC
buffer pointer for side-sector ptr in side-sector set buffer pointer
A
buffer number times 2
******************************
DEE9 DEEA DEED DEEE DEEF DEFO DEFl DEF2 DEF4 DEF5 DEF?
buffer ptr to zero
RTS
******************************
DEDC DEDE DEEO DEE2 DEE3 DEE6 DEE8
get side-sector #
PHA JSR PHA TXA ASL TAX PLA STA PLA STA RTS
buffer pointer hi $9A,X buffer pointer 10 $99,X
******************************
DEF8
20 66 DF
JSR $DF66
DEFB
30 OE
BMI $DFOB
289
get side-sector and buffer ptr is side-sector in buffer? no
ABACUS Software
13 82 CD 1B DF 66 DF
Anatomy or the 1541
DEFD DEFF DF01 DF03 DF06
50 A6 B5 20 20
BVC LDX LDA JSR JSR
$DF12 $82 $CD,X $DF1B $DF66
DF09 DFOB
10 07 20 CB E1
BPL $DF12 JSR $E1CB
DFOE DF11 DF12 DF14
2C CE FE 60 A5 D6 20 E9 DE
BIT $FECE RTS LDA $D6 JSR $DEE9
DF17 DF1A
2C CD DE 60
BIT $FECD RTS
ok channel number buffer number read side-sector and check if in buffer yes? get last side-sector set V bit side-sector end ptr set pointer in side-sector clear V bit
****************************** DF1B 85 F9 STA $F9 DF1D A9 80 LDA #$80 DF1F DO 04 BNE $DF25
read side-sector buffer number cmd code for read
****************************** DF21 STA $F9 85 F9 DF23 A9 90 LDA #$90 DF25 48 PHA DF26 LDA $EC,X B5 EC DF28 29 01 AND #$01 DF2A STA $7F 85 7F DF2C 68 PLA DF2D 05 7F ORA $7F
write side-sector buffer number cmd code for write
DF2F DF32 DF34 DF36 DF37 DF39 DF3B DF3D
8D B1 85 C8 B1 85 A5 20
4D 02 94 80 94 81 F9 D3 D6
STA LDA STA INY LDA STA LDA JSR
$024D ($94), Y $80 ($94) ,Y $81 $F9 $D6D3
290
isolate drive # command code plus drive number save track number sector number buffer number transmit param to disk controller
ABACUS Software
OF40 DF42
A6 F9 4C 93 05
Anatomy of the 1541
LOX $F9 JMP $0593
****************************** OF45 OF47 OF49
A6 82 B5 CD 4C EB 04
LOX $82 LOA $CO,X JMP $04EB
****************************** OF4C
A9 78
LDA #$78
OF4E OF51 OF52 OF54
20 5C OF CA 10 F8 AS 72
JSR $OF5C OEX BPL $OF4C LOA $72
OF56 OF57 OF5A
4A 20 5C OF A5 73
LSR A JSR $OF5C LOA $73
OF5C OF50 OF5F OF61 DF63 DF65
18 65 85 90 E6 60
CLC AOC STA BCC INC RTS
70 70 02 71
$70 $70 $OF65
set buffer pointer in side-sector channel number buffer number set buffer pointer calculate # of blks in a rel-file 120 block ptrs per side-sector add to $70/$71 side-sector number next side-sector? # of pointers in last block divided by 2 add to previous sum number of assigned side-sector blocks add
$71
****************************** DF66 DF69
20 D2 DE C5 D5
JSR $OE02 CMP $05
OF6B DF60 OF6F OF71 OF73 OF76
DO A4 B1 FO 2C 60
BNE LOY LOA BEQ BIT RTS
OE 06 94 04 CD FE
buffer number tranmit cmd to disk controller
$OF7B $06 ($94),Y $OF77 $FECO
291
verify side-sector in buffer get side-sector # = number of required block? no ptr in side-sector track number not yet allocated? clear bits
ABACUS Software
Anatomy of the 1541
DF77 DF7A
2C CF FE 60
BIT $FECF RTS
set N-bit
DF7B DF7D DF7F DF81 DF82 DF83 DF85 DF87 DF89 DF8B DF8E
A5 C9 BO OA A8 A9 85 B1 DO 2C 60
LDA CMP BCS ASL TAY LDA STA LDA BNE BIT RTS
side-sector number 6 or greater? yes
DF8F DF92
2C CE FE 60
D5 06 OA 04 94 94 04 DO FE
$D5 #$06 $DF8B A #$04 $94 ($94),Y $DF8F $FEDO
BIT $FECE RTS
****************************** A6 82 LDX $82 DF93 LDA $A7,X DF95 B5 A7 DF97 10 02 BPL $DF9B LDA $AE,X DF99 B5 AE DF9B DF9D
29 BF 60
DF9E DFAO DFA3 DFA5 DFA7 DFA8 DFA9 DFAB DFAE DFBO DFB2
A6 8E B5 10 8A 18 69 8D B5 85 29
DFB4 DFB6
24 70 60
82 57 02 A7 09 07 57 02 AE 70 1F
AND #$BF RTS LDX STX LDA BPL TXA CLC ADC STA LDA STA AND
track number set N and V bits set V bit get buffer number channel number buffer number allocated? buffer number from second table clear V bit
$82 $0257 $A7,X $DFBO
channel number save get buffer number buffer allocated?
#$07 $0257 $AE,X $70 #$lF
increment # by 7 and save buf # from table 2
BIT $70 RTS
292
clear the highest 3 bits
ABACUS Software
Anatomy or the 1541
DFB7 DFB9 DFBB DFBD
AD B5 30 B5
DFBF DFC1
C9 FF 60
CMP #$FF RTS
DFC2 DFC4 DFC6 DFC8 DFCA DFCC DFCD DFCF
A6 09 B4 10 95 60 95 60
LDX ORA LDY BPL STA RTS STA RTS
82 A7 02 AE
82 80 A7 03 A7 AE
LDX LDA BMI LDA
$82 $A7,X $DFBF $AE,X
$82 #$80 $A7,X $DFCD $A7,X $AE,X
****************************** 20 9D DD 80 A6 DD 41 82 B5 02 BB 82 C1 2E E8 D4 82 Cl
LDA JSR LDA JSR BNE LDX INC BNE INC LDX LDA BEQ JSR LDX CMP
channel number buffer number buffer free? buffer number from table 2 free?
#$20 $DD9D #$80 $DDA6 $E01D $82 $B5, X $DFE4 $BB,X $82 $C1,X $E018 $D4E8 $82 $C1,X
DFDO DFD2 DFD5 DFD7 DFDA DFDC DFDE DFEO DFE2 DFE4 DFE6 DFE8 DFEA DFED DFEF
A9 20 A9 20 DO A6 F6 DO F6 A6 B5 FO 20 A6 D5
DFF1 DFF3
90 03 20 3C EO
BCC $DFF6 JSR $E03C
DFF6 DFF8
A6 82 B5 Cl
LDX $82 LDA $C1,X 293
get next record in rel-file clear bit 5 test bit 7 set? channel number increment record # record number hi channel number write-pointer zero? set buffer pointer channel number buffer ptr less than write ptr? yes write block, read next block channel number write pointer
ABACUS Software
Anatomy of the 1541
DFFA
20 C8 D4
JSR $D4C8
DFFD DFFF E001 E003 E006
A1 85 A9 20 20
LDA STA LDA JSR JSFz
E009 EOOA
48 90 28
PHA BCC $E034
EOOC EOOE E011 E013 E014 E016 E018 E01A E01D E020 E022 E025 E027 E029
A9 20 DO 68 C9 FO A9 20 20 B5 99 A9 85 60
00 F6 D4 21
LDA JSR BNE PLA CMP BEQ LDA JSR JSR LDA STA LDA STA RTS
#$00 $D4F6 $E034
E02A E02D E02F E031 E033
20 A6 A9 95 60
35 EO 82 00 C1
JSR LDX LDA STA RTS
$E035 $82 #$00 $e1, X
E034 E035 E037 E039
68 A6 82 95 C1 4C 6E E1
99 85 20 9D DD 04 E3
02 12. 80 97 DD 2F D1 99 44 02 OD 85
($99) ,X $85 #$20 $DD9D $E304
#$02 $E02A #$80 $DD97 $D12F $99,X $0244,Y #$OD $85
PLA LDX $82 STA $C1, X JMP $E16E
****************************** E03C
20 D3 D1
JSR $D1D3
294
set buffer pointer = write ptr byte from buffer put in output reg clear bit 5 add record length to write ptr and save not yet in last block? get track number does block exist? pointer = 2 yes set bit 7 get byte from buffr buffer pointer as end pointer CR in output register
channel number write-ptr to zero
channel number set write pointer write block and read next block get drive number
ABACUS Software
Anatomy of the 1541
E03F
20 95 DE
JSR $DE95
E042 E045 E047 E04A E04D E04F E052 E055 E057 E05A
20 50 20 20 A9 20 20 DO 20 4C
9E 16 5E 1E 02 C8 AB 24 57 99
JSR BVC JSR JSR LDA JSR JSR BNE JSR JMP
$DF9E $E05D $DE5E $CF1E #$02 $D4C8 $DDAB $E078 $DE57 $D599
E05D E060 E063 E065 E068 E06B
20 20 DO 20 20 20
1E AB 06 57 99 95
JSR JSR BNE JSR JSR JSR
$CF1E $DDAB $E068 $DE57 $D599 $DE95
E06E E070 E072 E075 E078 E07B
A5 FO 20 20 20 60
80 09 1E CF 57 DE 1E CF
LDA BEQ JSR JSR JSR RTS
$80 $E07B $CF1E $DE57 $CF1E
DF DE CF D4 DD DE D5 CF DD DE D5 DE
******************************
E07C E07F E082 E083 E084 E086 E088 E08A E08B E08D E08F E092
20 05 E1 20 93 DF OA AA
A5 81 B4 C8 DO A4 B9 FO
85 99 99 09 82 C1 00 OA
JSR JSR ASL TAX LDA STA LDY INY BNE LDY LDA BEQ
$E105 $DF93 A $85 ($99,X) $99,X $E096 $82 $00C1,Y $E09E
295
get track and sector numbers get buffer number no rel-file? write block change buffers buffer pointer to 2 cmd code for write? no read block and verify change buffers cmd code for write? no read block and verify get track and sector numbers track no following track? change buffers read block change buffers write a byte in a record get buffer number times 2 data byte write in buffer buffer pointer increment not equal zero? channel number write-pointer equal zero?
ABACUS Software
Anatomy of the 1541
E094 E096 E097 E099
AO 02 98 AS 82 D9 C1 00
LDY #$02 TYA LDY $82 CMP $00C1,Y
E09C E09E EOAO
DO 05 A9 20 4C 97 DD
BNE $E043 LDA #$20 JMP $DD97
EOA3 EOA5 EOA7
F6 99 DO 03 20 3C EO
INC $99,X BNE $EOAA JSR $E03C
EOAA
60
RTS
****************************** EOAB EOAD EOBO EOB2 EOB4 EOB7 EOB9 EOBB
A9 20 DO AS 20 AS
EOBC EOBE EOC1 EOC3
A9 20 FO A9
EOC5 EOC8
8D 6C 02 20 F3 EO
STA $026C JSR $EOF3
EOCB EOCE EOD1 EOD3
20 AD FO 4C
JSR LDA BEQ JMP
EOD6
4C BC E6
Fa
AO A6 DD 27 85 7C EO F8 00
LDA JSR BNE LDA JSR LDA BEQ RTS
#$AO $DDA6 $EOD9 $85 $E07C $F8 $EOC8
20 A6 DD 05 51
LDA JSR BEQ LDA
#$20 $DDA6 $EOC8 #$51
60
53 E1 6C 02 03 C8 C1
$E153 $026C $EOD6 $C1C8
JMP $E6BC
296
buffer pointer to 2 channel number buffer pointer write pointer? no set bit 5 inc buffer pointer not zero? else write block, read next one write byte in rel-file test bits 6 & 7 set? data byte write in record end? yes
test bit 5 not set 51, 'overflow in record' set error flag fill remainder with zeros error flag set? no set error message error-free execution
ABACUS Software
Anatomy of the 1541
EOD9 EODB EODD EODF EOEl
29 DO AS FO 60
80 05 F8 DB
AND BNE LDA BEQ RTS
#$80 $EOE2 $F8 $EOBC
bit 7 set? yes
EOE2 EOE4 EOE5 EOE8 EOE9 EOEB EOED EOFO
AS 48 20 68 85 A9 20 4C
85
LDA PHA JSR PLA STA LDA JSR JMP
$85
data byte
$E31C
expand side-sector
$85 #$80 $DD9D $EOB2
clear bit 7 write byte in file
lC E3 85 80 9D DD B2 EO
****************************** LDA #$20 EOF3 A9 20 20 A6 DD JSR $DDA6 EOF5 BNE $E104 DO OA EOF8 LDA #$00 EOFA A9 00 STA $85 EOFC 85 85 $E07C JSR EOFE 20 7C EO $EOF3 JMP E10l 4C F3 EO
E104
end?
fill record with Os test bit 5 set? zero as data byte write in record until record full
RTS
60
******************************
write buffer number in table
E105 E107 E10A E10D E10F El12 El14
A9 20 20 09 AE 95 60
40 97 DD 9E DF 40 57 02 A7
LDA JSR JSR ORA LDX STA RTS
#$40 $DD97 $DF9E #$40 $0257 $A7,X
set bit 6 get buffer number set bit 6 channel number + 7 write in table
EllS El18 EllA EllD EllF
20 29 AE 95 60
9E DF BF 57 02 A7
JSR AND LDX STA RTS
$DF9E #$BF $0257 $A7,X
get buffer number clear bit 6 channel number + 7 write in table
297
ABACUS Software
Anatomy of the 1541
****************************** E120 E122 E125 E127
A9 20 DO 20
80 A6 DD 37 2F D1
LDA JSR BNE JSR
#$80 $DDA6 $E15E $D12F
E12A E12C E12F E131 E133 E135
B5 D9 FO F6 DO 20
99 44 02 22 99 06 3C EO
LDA CMP BEQ INC BNE JSR
$99,x $0244,Y $E135 $99,X $E13B $E03C
E138 E13B E13D E140 E142
20 A1 99 A9 99
2F D1 99 3E 02 89 F2 00
JSR LDA STA LDA STA
$D12F ($99,X) $023E,Y #$89 $00F2,Y
E145 E147 E14A E14C
B5 99 D9 44 02 FO 01 60
LDA $99,Y CMP $0244,Y BEQ $E14D RTS
E14D E14F E152
A9 81 99 F2 00 60
LDA #$81 STA $00F2,Y RTS
E153 E156
20 DO DF 20 2F D1
JSR $DFDO JSR $D12F
E159 E15B
A5 85 4C 3D E1
LDA $85 JMP $E13D
E15E E160 E162 E165 E167
A6 A9 9D A9 95
LDX LDA STA LDA STA
82 OD 3E 02 81 F2
$82 #$OD $023E,X #$81 $F2,X
298
get byte from reI-file test bit 7 set? get byte from buffer buffer pointer compare to end ptr equal? inc buffer ptr not zero? write block, read next one get byte from buf in output register set READ and WRITE flag buffer pointer compare to end ptr same?
set flag for end find next record get buffer and channel numbers data byte into output reg channel number CR into output reg set flag for end
ABACUS Software
Anatomy of the 1541
E169 E16B
A9 50 20 C8 CI
LDA #$50 JSR $C1C8
E16E E170 E172 E174 E176 E178 E17A E17C E17E E180 E182 E185 E187
A6 B5 85 C6 C9 DO A9 85 B5 85 20 A6 C5
82 C1 87 87 02 04 FF 87 C7 88 E8 D4 82 87
LDX LDA STA DEC CMP BNE LDA STA LDA STA JSR LDX CMP
$82 $C1, X $87 $87 #$02 $E17E #$FF $87 $C7,X $88 $D4E8 $82 $87
E189 E18B E18D E190 E193 E195 E197 E19A
90 FO 20 20 90 A6 9D 4C
19 17 1E B2 08 82 44 1E
BCC BEQ JSR JSR BCC LDX STA JMP
$E1A4 $E1A4 $CF1E $E1B2 $E19D $82 $0244,X $CF1E
E19D E1AO E1A2 E1A4 EIA7 EIA9 E1AC E1AE E1B1
20 A9 85 20 BO 20 A6 9D 60
1E FF 87 B2 03 E8 82 44
JSR LDA STA JSR BCS JSR LDX STA RTS
$CFIE #$FF $87 $EIB2 $E1AC $D4E8 $82 $0244,X
EIB2 EIB5 E1B7 E1B9
20 A4 B1 DO
2B DE 87 94 OD
JSR LDY LDA BNE
$DE2B $87 ($94),Y $EIC8
CF E1 02 CF CF E1 D4 02
299
50, 'record not present' channel number write-pointer save equal 2? no record length set buffer pointer channel number buffer pointer > write pointer? no change buffers channel number change buffers change :buffers
set buffer pointer channel number end pointer buffer ptr to zero byte from buffer not zero?
ABACUS Software
EIBB EIBC EIBE EICO EIC2 EIC4 EIC6 EIC7
88 CO 90 C6 DO C6 18 60
EIC8 EIC9 EICA
98 38 60
02 04 88 F3 88
Anatomy of the 1541
DEY CPY BCC DEC BNE DEC CLC RTS
#$02 $EIC4 $88 $EIB7 $88
TYA SEC RTS
****************************** EICB
20 D2 DE
EICE EIDO EID2 EID4 EID6
85 A9 85 AO DO
EID8 EID9 EIDA EIDC
88 88 30 26 Bl 94
DEY DEY BMI $E202 LDA ($94), Y
EIDE EIEO EIEl EIE2
FO F8 98 4A C5 D5
BEQ $EID8 TYA LSR A CMP $D5
EIE4 EIE6 EIE8 EIEA EIEC EIEF EIFl EIF3
FO 85 ' A6 BS 20 AO 84 Bl
D5 04 94 OA 04
09 D5 82 CD IB DF 00 94 94
JSR $DED2 STA LDA STA LDY BNE
BEQ STA LDX LDA JSR LDY STY LDA
$D5 #$04 $94 #$OA $EIDC
$EIEF $DS $82 $CD,X $DFIB #$00 $94 ($94),Y
300
get last side-sector get number of the side-sector save ptr to side-sectors
track # of the previous block not allocated? divide by 2 = number of the current block? yes else save all #s channel number buffer number read block buffer pointer track number
Anatomy of the 1541
ABACUS Software
OB
EIF5 EIF7 EIF8 EIFA EIFB EIFC EIFE EIFF
DO C8 Bl A8 88 84 98 4C
E202 E204
A9 67 20 45 E6
94 D6 E9 DE
BNE INY LDA TAY DEY STY TYA JMP
$E202
anothel. block?
($94),Y
sector #
$D6
save end pointer
$DEE9
set buffer pointer
#$67 JSR $E645
**********~*******************
C1
JSR LDA STA JSR BCC LDA JSR
$C2B3 $0201 $83 $DOEB $E219 #$70 $C1C8
9D DD 25 D1 05 64 C8 Cl
LDA JSR JSR BEQ LDA JSR
#$AO $DD9D $D125 $E228 #$ 64 $CIC8
EC 01 7F 02 02 B5 03 02 BB B2 89 F2 04 02
LDA AND STA LDA STA LDA STA LDA LDA STA LDA
$EC,X #$01 $7F $0202 $B5, X $0203 $BB,X $82 #$89 $F2,X $0204
E207 E20A E20D E20F E212 E214 E216
20 AD 85 20 90 A9 20
B3 01 83 EB 05 70 C8
E219 E21B E21E E221 E223 E22S
A9 20 20 FO A9 20
AO
E228 E22A E22C E22E E231 E233 E236 E238 E23A E23C E23E
BS 29 85 AD 95 AD 95 A6 A9 95 AD
C2 02 DO
301
=
end ptr
67, 'illegal track or sector' p-command, 'Record' verify lines secondary address find channel number found? 70,
'no block'
clear bits 6 & 7 check if !REL'-file yes 64, 'file type mismatch'
drive number record number 10 record number hi channel number READ and WRITE flag byte-pointer
ABACUS Software
10
Anatomy of the 1541
BEQ SEC SBC BEQ CMP
$E253
E241 E243 E244 E246 E248
FO 38 E9 FO D5
E24A E24C E24E
90 07 A9 51 8D 6C 02
BCC $E253 LDA #$51 STA $026C
E251 E253 E255
A9 00 85 D4 20 OE CE
LDA #$00 STA $D4 JSR $CEOE
E258
20 F8 DE
JSR $DEF8
E25B E25D E25F E262
50 A9 20 4C
08 80 97 DD 5E El
BVC LDA JSR JMP
$E265 #$80 $DD97 $E15E
E265 E268 E26A E26D E26F
20 A9 20 FO 4C
75 E2 80 A6 DD 03 5E El
JSR LDA JSR BEQ JMP
$E275 #$80 $DDA6 $E272 $E15E
E272
4C 94 Cl
JMP $C194
E275 E278 E27A E27D E27F E281 E282 E284 E286
20 A5 20 A6 B5 38 E5 BO 4C
JSR LDA JSR LDX LDA SEC SBC BCS JMP
01 OB C7
9C E2 D7 C8 D4 82 C7 D4 03 02 E2
#$01 $E253 $C7,X
$E29C $D7 $D4C8 $82 $C7,X $D4 $E289 $E202
302
zero?
compare with record length 51, 'overflow in record' calculate pointer in reI-file and read corresponding side-sector does block exist? set bit 7 and 50, 'record not present'
test bit 7 not set 50, 'record not present' done pointer in reI-file set buffer pointer channel number record length minus position positive? 67, 'illegal track or sector'
ABACUS Software
Anatomy or the 1541
E289 E28A
18 65 D7
E28C E28E E290 E291 E294
90 69 38 20 4C
E297 E299
A9 51 20 C8 Cl
LDA #$51 JSR $CIC8
E29C E29E E2AO E2A2 E2A4 E2A7 E2A9
AS 85 AS 85 20 DO 60
94 89 95 8A DO E2 01
LDA STA LDA STA JSR BNE RTS
$94 $89 $95 $8A $E2DO $E2AA
E2AA E2AD E2BO E2B2 E2B4
20 20 AS FO 20
Fl DD OC DE 80 OE D3 E2
JSR JSR LDA BEQ JSR
$DDFI $DEOC $80 $E2C2 $E2D3
E2B7 E2B9 E2BC E2BF E2C2 E2C4 E2C6 E2C8 E2C9
DO 20 4C 20 AO B1 85 C8 B1
06 IE CF DA D2 DA D2 00 89 80
BNE JSR JMP JSR LDY LDA STA INY LDA
$E2BF $CF1E $D2DA $D2DA #$00 ($89),Y $80
E2CB E2CD
85 81 4C AF DO
STA $81 JMP $DOAF
E2DO
20 3E DE
JSR $DE3E
03 01 09 EO 38 El
89
CLC ADC $D7 BCC ADC SEC JSR JMP
$E291 #$01
add pointer in data block no overflow plus 2
$E009 $E138
set pointer get byte from buf
($89),Y
303
51, 'overflow in record' buffer pointer 10 buffer pointer hi compare trk and sec not equal?
track no block following? compare track and sector numbers not equal? change buffers
track and sector of the next block read block
Anatomy of the 1541
ABACUS Software
E2D3 E2D5 E2D7 E2D9 E2DB E2DC E2DD E2DF E2E1
AO B1 C5 FO 60 C8 B1 C5 60
00 89 80 01 89 81
LDY LDA CIvIP BEQ RTS INY LDA CMP RTS
#$00 ($89),Y $80 $E2DC
track number compa.ce
($89),Y $81
sector number compare
***************k************** E2E2 E2E5 E2E7 E2E9 E2EB E2EC E2EE
20 AO A9 91 C8 DO 20
E2F1 E2F3 E2F4 E2F6
95 C1 A8 A9 FF 91 94
STA $C1,X TAY LDA #$FF STA ($94), Y
E2F8
20 04 E3
JSR $E304
90 F4
BCC BNE LDA STA RTS
E2FB E2FD E2FF E301 E303
2B DE 02 00 94 FB 04 E3
CO 04 A9 00 95 C1 60
JSR LDY LDA STA INY BNE JSR
$DE2B #$02 #$00 ($94), Y $E2E9 $E304
$E2F1 $E303 #$00 $C1,X
****************************** E304 E306 E308 E309 E30B E30C
A6 B5 38 FO 18 75
82 C1 OD C7
LDX LDA SEC BEQ CLC ADC
divide data blocks into records set buffer pointer erase buffer set pointer to next record
$FF as 1st character in record set pointer to next record done in this block? block full? write-pointer to 0
$82 $C1,X
set pointer to next record channel number write-pointer
$E318
equal zero?
$C7,X
add record length
304
ABACUS Software
E30E E310 E312 E314 E317
90 DO A9 2C 60
OB 06 02 CC FE
E318 E31A E31B
69 01 38 60
Anatomy of the 1541
BCC BNE LDA BIT RTS
$E31B $E318 #$02 $FECC
ADC #$01 SEC RTS
****************************** JSR $0103 20 03 01 E31C JSR $E1CB E31F 20 CB E1 E322 E325 E328 E32A E32C E32E E330 E332 E334 E336 E338
20 20 A5 85 A5 85 A9 85 A9 85 20
9C E2 7B CF 06 87 05 86 00 88 00 04 OE CE
JSR JSR LOA STA LOA STA LOA STA LOA STA JSR
$E29C $CF7B $06 $87 $05 $86 #$00 $88 #$00 $04 $CEOE
E33B E33E E340 E342 E343 E344 E345
20 A4 B6 CA 8A 18 65
40 EF 82 C7
JSR LDY LOX OEX TXA CLC ADC
$EF40 $82 $C7,Y
E347 E349 E34B
90 OC E6 06 E6 06
BCC $E355 INC $06 INC $06
E340 E34F
DO 06
BNE $E355 INC $D5
07
E6 05
smaller than 2561 equal 256?
add two
expand side-sector get drive number get last side-sector
side-sector number
calculate sidesector # and ptr # of free blocks channel number record length
plus pointer in data block
$07
305
increment ptr to end by 2 increment side-sector #
ABACUS Software
E351 E353 E355 E357 E358 E35A
A9 85 A5 18 69 20
E35D E35F E361 E363 E365
10 D6 87
Anatomy of the 1541
#$10 #D6 $87
02 E9 DE
LDA STA LDA CLC ADC JSR
A5 C9 90 A9 20
D5 06 05 52 C8 Cl
LDA CMP BCC LDA JSR
$D5 #$06 $E368 #$52 $CIC8
E368 E36A E36B E36D E36F E371 E372 E374 E376
A5 38 E5 BO E9 18 85 A5 E5
D6
LDA SEC SBC BCS SBC CLC STA LDA SBC
$D6
£378 E37A E37C
85 73 A2 00 86 70
STA $73 LDX #$00 STX $70
E37E E380 E381
86 71 AA
20 51 DF
STX $71 TAX JSR $DF51
E384 E386 E388 E38A E38B E38D E38F E392
A5 DO A6 CA DO E6 CD 90
LDA BNE LDX DEX BNE INC CMP BCC
87 03 OF 72 D5 86
71 07 70 02 88 73 02 09
#$02 $DEE9
$87 $E372 #$OF $72 $D5 $86
set pointer to 16
set buffer ptr for side-sector side-sector number less than 6? 52, 'file too large' end pointer minus last end ptr minus 16 side-sector number minus last side-sector number save erase sum for calculation calculate # of blocks in rei-file
$71 $E38F $70 $E38F $88 $0273 $E39D
306
block # of rel·-file greater than free blocks on disk?
Anatomy of the 1541
ABACUS Software
E394
00 CO
BNE $E363
E396 E399 E39B
AO 72 02 C5 70 90 C6
LOA $0272 CMP $70 BCC $E363
E390 E39F
A9 01 20 F6 04
LOA #$01 JSR $04F6
E3A2 E3A3 E3A5 E3A7 E3A9
18 69 A6 95 20
CLC AOC LOX STA JSR
E3AC E3AF E3B1
20 FO 00 A5 88 00 15
JSR $OOFO LOA $88 BNE $E3C8
E3B3 E3B6 E3B9
20 5E OE 20 IE CF 20 00 06
JSR $OE5E JSR $CFIE JSR $0600
E3BC
20 IE Fl
JSR $FIIE
E3BF
20 FO 00
JSR $OOFO
E3C2 E3C5
20 E2 E2 4C 04 E3
JSR $E2E2 JMP $E304
E3C8 E3CB
20 1E CF 20 00 06
JSR $CF1E JSR $0600
E3CE E301
20 E2 E2 20 19 DE
JSR $E2E2 JSR $DE19
E3D4 E3D7 E3DA E3DC E3DD
20 20 A5 48 A4
01 82 C1 IE Fl
5E DE OC DE 80 81
JSR JSR LDA PHA LDA
#$01 $82 $Cl,X $FIIE
52, 'file too large' 52, 'file too large' get byte from buffer plus 1 as write pointer find free block in BAM trk and sec in buf only one block needed? write block change buffers transmit param to disk controller find free block in BAM track and sector in buffer erase buffer
$DE5E $DEOC $80
change buffers transmit param to disk controller erase buffer zero byte and end ptr in buffer write block get trk and sector track
$81
and sector
307
ABACUS Software
Anatomy of the 1541
E3DF E3EO
48 20 3E DE
PHA JSR $DE3E
E3E3 E3E5 E3E6 E3E8 E3E9
AS 81 48 AS 80 48 20 45 DF
LDA $81 PHA LDA $80 PHA JSR $DF45
E3EC E3ED E3EF E3F2 E3F4 E3F7
AA
DO 20 A9 20 E6
TAX BNE JSR LDA JSR INC
E3F9 E3FA E3FD E3FE E401 E402 E404 E405 E407 E409 E40B E40D E40F
68 20 68 20 68 85 68 85 FO AS C5 DO 20
E412 E414 E416 E418
C5 90 FO 20
E41B E41C E41E E421 E423 E424
48 A9 20 A9 A8 91
OA 4E E4 10 E9 DE 86
80 OF 86 D5 A7 45 DF
PLA JSR PLA JSR PLA STA PLA STA BEQ LDA CMP BNE JSR
D6 AO BO 45 DF
CMP BCC BEQ JSR
8D DD 8D DD 81
00 DC DE 00 94
PHA LDA JSR LDA TAY STA
save get trk and sector from disk cont. save sector and track set buffer ptr for side-sector
$E3F9 $E44E #$10 $DEE9 $86
pointer not zero? write side-sector
$DD8D
track in side-sect
$DD8D
sector in side-sec
$81
get sector
$80 $E418 $86 $D5 $E3B6 $DF45
and track back no more blocks? side-sector number changed? yes set buffer ptr in side-sector end pointer smaller? same set buffer ptr in side-sector
$D6 $E3B6 $E3C8 $DF45
buffer ptr to 16 increment side-sector number
#$00 $DEDC #$00
buffer ptr to zero
($94),Y
o
308
as track number
ABACUS Software
E426 E427 E428 E429 E42B E42D E430 E433 E436
C8 68 38 E9 91 20 20 20 20
01 94 6C 99 F4 OE
E439 E43C E43F E441 E444 E446 E449 E44B
Anatomy or the 1541
DE D5 EE CE
INY PLA SEC SBC STA JSR JSR JSR JSR
#$01 ($94), Y $DE6C $D599 $EEF4 $CEOE
20 20 70 4C
1E CF F8 DE 03 75 E2
JSR .JSR BVS JMP
$CF1E $OEF8 $E444 $E275
A9 20 A9 20
80 97 DD 50 C8 C1
LDA JSR LDA JSR
#$80 $D097 #$50 $C1C8
end pointer
$DEC1 $82 $CD,X
erase buffer channel number buffer number
#$10
16 bytes of the side-sector copy in buffer
20 1E F1
JSR $F11E
E451 E454 E457 E45A E45B E45E E460 E462 E463 E464 E465
20 20 20 48 20 A6 B5 A8 68
A9 10
JSR JSR JSR PHA JSR LOX LDA TAY PLA TAX LDA
E467 E46A E46C
20 A5 DE A9 00 20 DC OE
JSR $OEA5 LOA #$00 JSR $OEDC
AA
50, 'record not present'
$CF1E $DDF1 $OF93
E44E
C1 DE 82 CD
set bit 7
write side-sector and allocate new find free block in BAM change buffers write block get buffer number
******************************
1E CF F1 DD 93 OF
minus one as sector write block and verify update BAM update ptr for rel-file change buffers right side-sector? no
309
buffer ptr to 0, old side-sector
ABACUS Software
02 94
Anatomy of the 1541
E46F E471 E473 E474 E476
AO B1 48 A9 20
E479 E47A E47B
68 18 69 01
PLA CLC ADC #$01
E47D E47F E480 E482
91 94 OA 69 04 85 89
STA ASL ADC STA
E484 E485 E486 E488
A8 38 E9 02 85 8A
TAY SEC SBC #$02 STA $8A
E48A E48C E48E E490 E491 E493 E495 E497 E499 E49A E49C E49D E49F E4A1 E4A3 E4A6 E4A9 E4AC E4AE
A5 85 91 C8 A5 85 91 AO 98 91 C8 A9 91 A9 20 20 20 A6 B5
LDA STA STA INY LDA STA STA LDY TYA STA INY LDA STA LDA JSR JSR JSR LDX LDA
E4BO
48
00 C8 D4
80 87 94 81 88 94 00 94 11 94 10 C8 D4 50 DE 99 D5 82 CD
LDY LDA PHA LDA JSR
#$02 ($94),Y #$00 $D4C8
($94),Y A #$04 $89-
$80 $87 ($94),Y
side-sector number buffer ptr to 0, new side-sector increment sidesector number and in buffer times 2 plus 4 equals ptr to track/sector minus 2 equals pointer to old side-sector track in buffer
$81 $88 ($94),Y #$00
sector
($94) ,Y
zero in buffer
#$11 ($94),Y #$10 $D4C8 $DE50 $D599 $82 $CD,X
17 # of bytes in block 16 buffer ptr to 16 write block and verify channel number buffer number of the side-sector
PHA 310
in buffer
Anatomy of the 1541
ABACUS Software
$DF9E $82 $CD,X
get buffer number channel number write in table
$0257 $A7,X #$00
channel number + 7 in table
$D4C8
buffer ptr to zero
#$00 $80 ($94), Y
track in buffer
81 94 DE E4
JSR LDX STA PLA LDX STA LDA JSR LDY LDA STA INY LDA STA JMP
$81 ($94) , Y $E4DE
sector in buffer
20 A6 20 A9 20 C6 C6
93 DF 82 IB DF 00 C8 D4 8A 8A
JSR LDX JSR LDA JSR DEC DEC
$DF93 $82 $DFIB #$00
get buffer number channel number read block
$D4C8
buffer ptr to zero
E4E2 E4E4 E4E6 E4E8 E4E9 E4EB E4ED E4FO E4F3
A4 AS 91 C8 AS 91 20 20 A4
89 87 94
LDY LDA STA INY LDA STA JSR JSR LDY
$89 $87 ($94),Y
track number in buffer
$88 ($94), Y $DE5E $D599 $8A
sector number in buffer write block and verify counter for side-sector blocks
E4F5 E4F7
CO 03 BO D8
CPY #$03 BCS $E4Dl
E4F9
4C IE CF
JMP $CFIE
E4B1 E4B4 E4B6 E4B8 E4B9 E4BC E4BE E4CO E4C3 E4C5 E4C7 E4C9 E4CA E4CC E4CE
20 A6 95 68 AE 95 A9 20 AO AS 91 C8 AS 91 4C
9E DF 82 CD
E4Dl E4D4 E4D6 E4D9 E4DB EFDE E4EO
57 02 A7 00 C8 D4 00 80 94
88 94 5E DE 99 D5 8A
$8A $8A
counter for side-sector blocks
311
greater than or equal to 3? change buffers
ABACUS Software
Anatomy of the 1541
******************************
table of error messages E4FC 00 00 , oK' E4FO AO 4F CB E500 20 21 22 23 24 27 error numbers of 'read error' E506 02 45 41 44 'Read' E50A 89 pointer to 'error' E50B 52 52 E50C 83 pointer to 'file' , too largE' E500 20 54 4F 4F 20 AC 4A 52 47 C5 E517 50 50 E518 8B 06 pointer to 'record' and 'not' / E51A 20 50 52 45 53 45 4E 04 presenT' E522 51 51 E523 CF 56 45 52 46 4C 4F 5 -, 20 'Overflow in' E52E 8B pointer to 'record' E52F 25 28 error numbers of 'write error' E531 8A 89 pointer to 'write' and 'error I E533 26 26 E534 8A pointer to "drite' E535 20 50 52 4E' 54 45 43 54 20 4F CE I protect oN' E540 29 29 E541 88 pointer to 'disk' I E542 20 49 85 id' E545 85 ptr to I mismatch' E546 30 31 32 33 34 error numbers for 'syntax error' E54B 03 59 4E 54 41 58 'Syntax' , error' E551 89 pointer to E552 60 60 E553 8A 03 84 ptrs to 'write' f 'file' & 'open' E556 63 63 E557 83 pointer to 'file' , existS' E558 20 45 58 49 53 54 D3 E55F 64 64 E560 83 pointer to 'file' 312
Anatomy of the 1541
ABACUS Software
E561 E566 E567 E568 E570
20 54 59 50 45 85 65 CE 4F 20 42 4C 4F 43 CB 66 67
E572 E57A E582 E589 E58A
C9 54 20 61 83
4C 4C 52 41 53 45 06 84
E58D 39 62 E590 83 06 87 E593 01 E594 83 E594 53 20 53 E59F E5AO E5AA E5AB E5AE E5AF E5BO E5B1 E5B6 E5B7 E5BF E5C4 E5C5 E5CA E5CB E5D5 E5D6 E5DB E5DC E5E1 E5E2
, type'
ptr to 'mismatch' 65 'No block' 'illegal track or sector' , 'Illegal 45 47 41 4C 20 'track or' 43 4B 20 4F 52 'sectoR' 43 54 4F D2 61 pointer to ' file' , 'not' & 'open' error #s for 'file not found' ptrs to 'file', 'not' & 'found' 01 pointer to 'file' 43 52 41 54 43 48 45 C4 's scratcheD' 70 43 48 41 4E 4E 45 CC 'No channeL' 71 'Dir' pointer to 'error' 72 pointer to 'disk' , fulL' 4C CC 73 , 'Cbm dos 20 44 4F 53 20 36 20 31 35 34 B1 'v2.6 1541' 74 'Drive' 56 45 pointer to 'not' , readY' 41 44 D9
70 CE 4F 20 71 C4 49 52 89 72 88 20 46 55 73 C3 42 4D 56 32 2E 74 C4 42 49 06 20 52 45 09 C5 52 52 4F D2 OA D7 52 49 54 C5 03 C6 49 4C C5
'ErroR' 'WritE' 'FilE'
313
Anatomy of the 1541
ABACUS Software
E5E6 E6E7 E5EB E5EC E5F4 E5F5 E5F8 E5F9 E5FE E5FF E603 E604
04 CF 05 CD 06 CE 07 C6 08 C4 OB D2
50 45 CE
'OpeN'
49 53 4D 41 54 43 C8
'MismatcH'
4F D4
'NoT'
4F 55 4E C4
'FounD'
49 53 CB
'DisK'
45 43 4F 52 C4
'RecorD'
******************************
B5 85 B5 85 68 29 FO
06 80 07 81 OF 08
PHA STX TXA ASL TAX LDA STA LDA STA PLA AND BEQ
E61D E61F E621 E623
C9 DO A9 DO
OF 06 74 08
CMP BNE LDA BNE
E625 E627 E629 E62A E62B E62C E62D E62E
A9 06 09 20
E60A E60B E60D E60E E60F E610 E612 E614 E616 E618 E619 E61B
48 86 F9 8A OA AA
AA
CA CA 8A 48 AD 2A 02
$F9 A
prepare error # and message save error code drive number times 2 as pointer
$06, X $80 $07,X $81 #$OF $E625 #$OF $E627 #$74 $E62D
LDA #$06 ORA #$20 TAX DEX DEX TXA PHA LDA $022A 314
get track and sector numbers get error code back isolate bits 0-3 $10, then 24, 'read error' 15? 74, 'drive not ready' 6 add $20 subtract two save error number # of the disk cmd
Anatomy of the 1541
ABACUS Software
C9 DO A9 8D 68 20
E63E E641
20 42 DO 4C 48 E6
JSR $D042 JMP $E648
E644 E645 E648 E64B E64D E650 E653
68 20 20 A9 8D 20 20
PLA JSR JSR LDA STA JSR JSR
E656 E658
A9 00 85 A3
LDA #$00 STA $A3
E65A E65C
A2 45 9A
LDX #$45 TXS
E65D E65F E661 E663 E665 E667 E668 E66A E66C E66E E670 E672
A5 29 85 C9 FO 78 AS DO AS DO A6 BD
84 OF 83 OF 31
E675 E677 E679 E67B
C9 FO 29 85
00 OF FF 2A 02 C7 E6
C7 BD 00 F9 2C DA
E6 C1 02 Cl D4
CMP BNE LDA STA PLA JSR
#$00 $E644 #$FF $022A
E631 E633 E635 E637 E63A E63B
$E6C7
$E6C7 $C1BD #$00 $02F9 $CI2C $D4DA
$84 #$OF $83 #$OF $E698
79 lC 7A 10 83 2B 02
LDA AND STA CMP BEQ SEI LDA BNE LDA BNE LDX LDA
FF IF OF 82
CMP BEQ AND STA
#$FF $E698 #$OF $82
$79 $E688 $7A $E680 $83 $022B,X
315
VALIDATE? no get error # back generate error message load BAM set error message set error message erase input buffer clear error flag turn LED off close channels 17 and 18 input-buffer pointer to zero initialize stack pointer secondary address 15? yes, cmd channel LISTEN active? yes TALK active? yes channel number channel to this second. addr open? no channel number
ABACUS Software
E67D
4C 8E E6
Anatomy of the 1541
JMP $E68E
******************************
E680
20 EB DO
JSR $DOEB
E683 E684 E685 E686
EA EA EA DO 06
NOP NOP NOP BNE $E68E
******************************
E688
20 07 Dl
JSR $0107
E68B E68C E68D E68E E691 E693 E695 E698
EA EA EA 20 C9 BO 20 4C
NOP NOP NOP JSR CMP BCS JSR JMP
25 Dl 04 03 27 D2 E7 EB
$0125 #$04 $E698 $D227 $EBE7
******************************
E69B E69C E69E E69F F6Al E6A3 E6A4 A6A6 E6A7 E6AA
AA A9 F8 EO FO 18 69 CA 4C D8
00 00 07 01 9F E6
TAX LDA SED CPX BEQ CLC ADC DEX JMP CLD
AA 4A 4A
LISTEN open channel for writing
verify file type file type REL? yes close channel convert hex to decimal (2 bytes)
#$00 #$00 $E6AA
convert hex to BCD
#$01 $E69F
******************************
E6AB E6AC E6AD
TALK open channel for reading
TAX LSR A LSR A
divide BCD number into two bytes shift hi-nibble down
316
Anatomy of the 1541
ABACUS Software
E6A.E E6AF E6BO E6B3 E6B4 E6B6 E6B8 E6BA E6BB
4A 4A 20 8A 29 09 91 C8 60
B4 E6 OF 30 A5
LSR LSR JSR TXA AND ORA STA INY RTS
A A $E6B4 #$OF #$30 ($A5),Y
****************************** E6BC E6BF E6C1 E6C3 E6C5
20 A9 AO 84 84
23 C1 00 00 80 81
JSR LDA LDY STY STY
$C123 #$00 #$00 $80 $81
****************************** LDY #$00 AO 00 E6C7 LDX #$D5 A2 D5 E6C9 STX $A5 86 A5 E6C8 LDX #$02 A2 02 E6CD STX $A6 86 A6 E6CF JSR $E6AB 20 AB E6 E6D1 E6D4 E6D6 ED68 E6D9
A9 2C 9A A5 C8 AD D5 02
LDA #$2C STA ($A5),Y INY LDA $02D5
E6DC E6DF E6EO E6E3 E6E5 E6E7 E6E8 E6EA
8D 8A 20 A9 91 C8 A5 20
STA TXA JSR LDA STA INY LDA JSR
E6ED
A9 2C
43 02 06 E7 2C A5 80 9B E6
$0243 $E706 #$2C ($A5),Y $80 $E69B
LDA #$2C 317
convert to ASCII clear top 4 bits add '0' write in buffer inc buffer pointer write 'ok' in buffer clear error flags error number 0 track 0 sector 0 error msg in buffer buffer pointer ptr $A5/$A6 to $2D5 error # to ASCII and in buffer ',' comma write in buffer inc buffer pointer first digit of the disk status in output register error # in acc error msg in buffer ',' comma write in buffer and inc buffer ptr track number to ASCII and in buffer , , , comma
ABACUS Software
Anatomy of the 1541
E6EF E6F1 E6F2 E6F4
91 AS C8 AS 81 20 9B E6
STA ($A5) , Y INY LDA $81 JSR $E69B
E6F7 E6F8 E6F9 E6FA E6FC E6FF E701 E703 E705
88 98 18 69 8D E6 A9 85 60
DEY TYA CLC ADC STA INC LDA STA RTS
D5 49 02 AS 88 F7
#$D5 $0249 $A5 #$88 $F7
****************************** TAX LDA PHA LDA PHA LDA STA
E706 E707 E709 E70A E70C E70D E70F
AS 48 AS 48 A9 85
E713 E715 E716 E718
85 87 8A A2 00 C1 86
STA $87 TXA LDX #$00 CMP ($86,X)
E71A E71C E71D
FO 21 48 20 75 E7
BEQ $E73D PHA JSR $E775
E720 E722 E725
90 05 20 75 E7 90 FB
BCC $E727 JSR $E775 BCC $E722
E727 E729
AS 87 C9 E6
LDA $87 CMP #$E6
AA
86 87 FC 86
write in buffer inc buffer pointer sector convert to ASCII and in buffer
end pointer inc buffer pointer set READ flag
write error message to buffer error code to X
$86 save ptr $86/$87 $87 #$FC #$E4
318
start of the error messages error # in acc compare with error # in table bit 7 into carry and clear not set? bit 7 into carry wait for character with bit 7 set
Anatomy of the 1541
ABACUS Software
Bee $E735
E72B
90 08
E720 E72F E731 E733 E735 E736 E739 E73A
00 AO e5 90 68 4e 68 4e
E730
20 67 E7
JSR $E767
E740
90 FB
Bee $E730
E742 E745 E748
20 54 E7 20 67 E7 90 F8
JSR $E754 JST $E767 Bee $E742
E74A E740 E74E E750 E751 E753
20 54 E7 68 85 87 68 85 86 60
JSR $E754 PLA STA $87 PLA STA $86 RTS
OA OA 86 04 18 E7 40 E7
BNE LOA eMP Bee PLA JMP PLA JMP
$E60A, check for end of table
$E739 #$OA $86 $E739 $E718
no, continue
$E74D
done
******************************
E754 E756
e9 20 BO OB
eMP #$20 BeS $E763
E758 E759 E75B E750 E75E E75F
AA
A9 20 91 A5 e8 8A 20 06 E7
TAX LOA #$20 STA ($A5),Y INY TXA JSR $E706
E762 E763 E765
60 91 A5 e8
RTS STA ($A5),Y INY
319
get a character, bit 7 in carry wait for character with bit 7 set and write in buffer get next character wait for character with bit 7 set put char in buffer get ptr $86/$87
get character and in buffer , , blank greater, then write in buffer save code blank write in buffer inc buffer pointer code in accumulator output associated text write char in buffr and increment ptr
ABACUS Software
E766
60
Anatomy of the 1541
RTS
******************************
E767 E769 E76B E76D E76F E770 E772 E774
E6 DO E6 A1 OA A1 29 60
86 02 87 86 86 7F
INC BNE INC LDA ASL LDA AND RTS
$86 $E76D $87 ($86,X) A ($86,X) #$7F
****************************** E775 20 6D E7 JSR $E76D E778 E6 86 INC $86 E77A DO 02 BNE $E77E E77C E6 87 INC $87 E77E 60 RTS
get a char of the error message increment pointer get character bit 7 into carry get character clear bit 7 increment pointer bit 7 into carry increment pointer
****************************** E77F 60 RTS ******************************
E780 E781 E7A1 E7A2
60 EA ... ... EA 60
RTS NOP NOP RTS
test for AUTO start is no longer present in current operating system
****************************** E7A3 A9 8D LDA #$8D E7A5 20 68 C2 JSR $C268
E7A8 E7AB E7AE E7AF E7B1 E7B4
20 58 F2 78 02 48 A9 01 8D 78 02 A9 FF AD
JSR LDA PHA LDA STA LDA
check for AUTO-start
'&' - command
$F258 $0278
check command line to end (RTS) number of filenames save
#$01 $0278 #$FF
a filename
320
ABACUS Software
Anatomy of the 1541
E7B6 E7B8 E7BB E7BE E7CO E7C2
85 20 AD DO A9 20
E7C5 E7C6
68 8D 78 02
PLA STA $0278
E7C9 E7CC E7CE E7D1 E7D3 E7D5
AD 85 AD 85 A9 20
80 02 80 85 02 81 03 77 D4
LDA STA LDA STA LDA JSR
$0280 $80 $0285 $81 #$03 $D477
E7D8 E7DA E7DC E7DF
A9 85 20 85
00 87 39 E8 88
LDA STA JSR STA
#$00 $87 $E839 $88
E7E1 E7E4 E7E7 E7E9 E7EC E7EE E7FO E7F2
20 20 85 20 A5 FO A5 48
4B E8 39 E8 89 4B E8 86 OA 88
JSR JSR STA JSR LDA BEQ LDA PHA
$E84B $E839 $89 $E84B $86 $E7FA $88
E7F3 E7F5 E7F6 E7F8 E7FA E7FD E7FF E802 E805
A5 48 A9 85 20 85 20 20 AO
89
LDA PHA LDA STA JSR STA JSR JSR LDY
$89
86 4F C4 80 02 05 39 C8 C1
00 86 39 E8 8A 4B E8 39 E8 00
STA JSR LDA BNE LDA JSR
$86 $C44F $0280 $E7C5 #$39 $C1C8
find file found? 39, 'file not found' get number of filenames back track and sector file type 'USR' buffer allocated, read 1st block erase checksum get byte from file save as start address 10 form checksum get byte from file as start address hi form checksum
save program start address #$00 $86 $E839 $8A $E84B $E839 #$00
321
get byte from file save as counter form checksum get byte from file
ABACUS Software
Anatomy of the 1541
E807
91 88
STA ($88),Y
E809 E80C E80E E80F E811 E813 E815 E817 E819 E81B E81E E820 E822 E824
20 A5 18 69 85 90 E6 C6 DO 20 A5 C5 FO 20
JSR LDA CLC ADC STA BCC INC DEC BNE JSR LDA CMP BEQ JSR
E827 E829
A9 50 20 45 E6
LDA #$50 JSR $E645
E82C E82E E830 £831 E833
A5 F8 DO A8 68 85 89 68
LDA $F8 BNE $E7D8 PLA STA $89 PLA
E834 E836 E839 E83C E83E E840
85 6C 20 A5 DO 20
STA JMP JSR LDA BNE JSR
E843 E845
A9 51 20 45 E6
LDA #$51 JSR $E645
E848 E84A
A5 85 60
LDA $85 RTS
4B E8 88 01 88 02 89 8A E7 35 CA 85 87 08 3E DE
88 88 00 35 CA F8 08 3E DE
$E84B $88 #$01 $88 $E817 $89 $8A $E802 $CA35 $85 $87 $E82C $DE3E
$88 ($0088) $CA35 $F8 $E848 $DE3E
****************************** E84B A8 CLC
322
save as program bytes form checksum
increment $88/$89 decrement pointer get next byte data byte equal to checksum? yes transmit param to disk controller 50, 'record not present' end? no, next data block get program start address back and execute program get byte from file end? no transmit param to disk controller 51, 'overflow in record' data byte generate checksum
Anatomy of the 1541
ABACUS Software
E84C E84E E850 E852
AOC $87 AOC #$00 STA $87 RTS
65 87 69 00 85 87 60
add carry
****************************** E853
AO 01 18
LOA $1801
E856 E858
A9 01 85 7C
LOA #$01 STA $7C
E85A
60
RTS
****************************** E85B E85C E85E
78 A9 00 85 7C
SEI LOA #$00 STA $7C
E860
85 79
STA $79
E862 E864 E866
85 7A A2 45 9A
STA $7A LOX #$45 TXS
E867 E869 E86B E860 E870
A9 85 85 20 20
80 F8 70 B7 E9 A5 E9
LOA STA STA JSR JSR
#$80 $F8 $70 $E9B7 $E9A5
E873 E876 E878 E87B E87E E880 E882 E884 E887
AD
00 10 00 00 57 04 F7 C9 3F
18
LOA ORA STA LOA BPL ANO BNE JSR CMP
$1800 #$10 $1800 $1800 $E807 #$04 $E87B $E9C9 #$3F
09 80 AD 10 29 DO 20 C9
18 18
E9
323
IRQ routine for serial bus read port A, clear IRQ flag set flag for 'ATN received' service the serial bus erase flag for 'ATN received' erase flag for LISTEN erase flag for TALK initialize stack pointer clear end clear EOI CLOCK OUT DATA OUT, hi
flag flag 10 bit '0' ,
set ATN acknowledge read IEEE port EOI? CLOCK IN? no get byte from bus unlisten?
ABACUS Software
Anatomy of the 1541
E889 E88B E88D
DO 06 A9 00 85 79
E88F E891 E893 E895 E897 E899 E89B E89D E89F E8A1 E8A3 E8A5
FO C9 DO A9 85 FO C5 DO A9 85 A9 85
71 5F 06 00 7A 67 78 OA 01 7A 00 79
BEQ CMP BNE LDA STA BEQ CMP BNE LDA STA LDA STA
$E902 #$5F $E89B #$00 $7A $E902 $78 $E8A9 #$01 $7A #$00 $79
E8A7 E8A9 E8AB E8AD E8AF E8B1 E8B3 E8B5 E8B7 E8B8 E8BA E8BC E8BE E8BF
FO C5 DO A9 85 A9 85 FO
29 77 OA 01 79 00 7A 1B
$E8D2 $77 $E8B7 #$01 $79 #$00 $7A $E8D2
29 C9 DO 8A 85
60 60 3F
BEQ CMP BNE LDA STA LDA STA BEQ TAX AND CMP BNE TXA STA
E8C1 E8C3 E8C5 E8C7 E8C9 E8CB E8CD E8CE E8D1
29 85 A5 29 C9 DO 58 20 78
OF 83 84 FO EO 35
AND STA LDA AND CMP BNE CLI JSR SEI
#$OF $83 $84 #$FO #$EO $E902
AA
84
CO DA
BNE $E891 LDA #$00 STA $79
#$60 #$60 $E8FD $84
no reset flag for LISTEN untalk? no reset flag for TALK TALK address? no set flag for TALK reset flag for LISTEN LISTEN address? no set flag for LISTEN reset flag for TALK
set bit 5 and 6 no byte is secondary address
$DACO
324
channel number CLOSE? CLOSE routine
Anatomy of the 1541
ABACUS Software
E8D2 E8D5
2C 00 18 30 AD
BIT $1800 BMI $E884
E8D7 E8D9 E8DB E8DE
A9 85 AD 29
00 7D 00 18 EF
LDA STA LDA AND
#$00 $7D $1800 #$EF
E8EO E8E3 E8E5 E8E7 E8EA
8D A5 FO 20 4C
00 18 79 06 2E EA E7 EB
STA LDA BEQ JSR JMP
$1800 $79 $E8ED $EA2E $EBE7
E8ED E8EF E8Fl
A5 7A FO 09 20 9C E9
E8F4 E8F7 E8FA E8FD
20 20 4C A9
E8FF
8D 00 18
STA $1800
E902 E905
2C 00 18 10 DO
BIT $1800 BPL $E8D7
E907
30 F9
BMI $E902
AE E9 09 E9 4E EA 10
LDA $7A BEQ $E8FA JSR $E99C JSR JSR JMP LDA
$E9AE $E909 $EA4E #$10
****************************** SEI 78 E909 JSR $DOEB DO EB 20 E90A E90D E90F E911 E913 E915
BO A6 B5 30 60
06 82 F2 01
BCS LDX LDA BMI RTS
$E915 $82 $F2,X $E916
325
test ATN active, then get next byte clear ATN flag clear ATN acknowledge LISTEN active? no receive data to delay loop TALK active? no DATA OUT, bit ' 1 ' , 10 CLOCK OUT hi send data to delay loop neither TALK nor LISTEN, ignore byte switch data lines to input test ATN ATN no longer active? wait until command mode ended send data open channel for reading channel active? channel number READ flag set? yes
ABACUS Software
E916 E919 E91C E91E E91F E922 E923 E925 E928 E92B E92D E92F E931 E933 E935 E937 E93A E93D E93F
20 20 29 08 20 28 FO 20 20 29 DO A6 B5 29 DO 20 20 29 DO
12 59 CO 01 F6 82 F2 08 14 59 CO 01 F6
E941 E944 E947 E949 E84B E94E E951 E954 E956 E958
20 20 29 FO 20 20 20 29 DO A9
59 CO 01 F6 AE 59 CO 01 F3 08
E95A E95C E95F E961
85 20 29 DO
E963 E965 E968 E969 E96C
A6 BD 6A 90 BO
Anatomy of the 1541
59 EA CO E9 01
JSR JSR AND PHP JSR PLP BEQ JSR JSR AND BNE LOX LOA AND BNE JSR JSR AND BNE
$E937 $EA59 $E9CO #$01 $E925 $82 $F2,x #$08 $E94B $EA59 $E9CO #$01 $E937
JSR JSR AND BEQ JSR JSR JSR AND BNE LOA
$EA59 $E9CO #$01 $E941 $E9AE $EA59 $E9CO #$01 $E94B #$08
98 CO E9 01 36
STA JSR AND BNE
$98 $E9CO #$01 $E999
82 3E 02
LDX LOA ROR STA BCS
$82 $023E,X A $023E,X $E973
B7 E9 EA E9
EA E9
EA E9 E9 EA E9
3E 02 05
$EA59 $E9CO #$01 $E9B7
326
test for ATN read IEEE port isolate data bit and save CLOCK OUT 10 check for ATN read IEEE port isolate data bit channel number no end? test for ATN read IEEE port isolate data bit output byte with EOI test for ATN read IEEE port isolate data bit CLOCK OUT hi test for ATN read IEEE port isolate data bit counter to 8 bits for serial transfer read IEEE port isolate data bit no activity on serial bus? channel number byte to output lowest bit in carry bit set
ABACUS Software
Anatomy of the 1541
E96E
20 A5 E9
JSR $E9A5
E971 E973
DO 03 20 9C E9
BNE $E976 JSR $E99C
E976 E979 E97B E97D
20 A5 DO 20
JSR LDA BNE JSR
E980
20 FB FE
JSR $FEFB
E983 E985 E987 E98A E98D E98F E991 E992 E99S E996
C6 DO 20 20 29 FO 58 20 78 4C
DEC BNE JSR JSR AND BEQ CLI JSR SEI JMP
E999
4C 4E EA
B7 E9 23 03 F3 FE
98 D5 59 EA CO E9 01 F6 AA D3 OF E9
$E9B7 $23 $E980 $FEF3
$98 $E95C $EAS9 $E9CO #$01 $E987
DATA OUT, output bit '0 ' unconditional jump DATA OUT, output bit ' 1 ' set CLOCK OUT 1540 mode? yes, skip delay delay for serial bus set DATA OUT and CLOCK OUT all bits output? no test for ATN read IEEE port isolate data bit
$D3AA
get next data byte
$E90F
and output
JMP $EA4E
to delay loop
****************************** E99C AD 00 18 LDA $1800 AND #$FD E99F 29 FD STA $1800 E9A1 8D 00 18 E9A4 RTS 60
DATA OUT 10
****************************** LDA $1800 E9A5 AD 00 18 ORA #$02 E9A8 09 02 STA $1800 8D 00 18 E9AA RTS E9AD 60
DATA OUT hi
****************************** LDA $1800 AD 00 18 E9AE ORA #$08 E9Bl 09 08 STA $1800 8D 00 18 E9B3
CLOCK OUT hi
327
output bit ' 1 '
output bit '0 '
set bit 3
ABACUS Software
E9B6
Anatomy of the 1541
60
RTS
****************************** E9B7 AD 00 18 LDA $1800 E9BA 29 F7 AND #$F7 E9BC 8D 00 18 STA $1800 E9BF 60 RTS
CLOCK OUT 10
****************************** E9CO AD 00 18 LDA $1800 E9C3 CD 00 18 CMP $1800 E9C6 DO F8 BNE $E9CO E9C8 60 RTS
read IEEE port read port wait for constants
******************************
get data byte from bus
E9C9 E9CB
A9 08 85 98
E9CD E9DO E9D3 E9D5 E9D7 E9DA E9DC E9DF E9E2 E9E5 E9E7 E9E9 E9EC E9EE
20 20 29 DO A9 4C 20 AD 29 DO 20 29 FO
E9FO
DO 19
20
59 CO 04 F6 9C 01 20 59 OD 40 09 CO 04 EF
LDA #$08 STA $98 EA E9 E9 FF EA 18 E9
JSR JSR AND BNE JSR LDA JMP JSR LDA AND BNE JSR AND BEQ
$EA59 $E9CO #$04 $E9CD $E99C #$01 $FF20 $EA59 $180D #$40 $E9F2 $E9CO #$04 $E9DF
BNE $EAOB
****************************** E9F2 E9F5
20 AS E9 A2 OA
JSR $E9A5 LDY #$OA
328
clear bit 3
bit counter for serial output test for ATN read IEEE port CLOCK IN? no, wait DATA OUT, bit I I' patch test for ATN timer run out? yes, EOI read IEEE port CLOCK IN? no, wait receive normal data byte accept byte with EOI DATA OUT bit '0 ' hi 10
ABACUS Software
Anatomy of the 1541
E9F7
CA
DEX
E9F8 E9FA E9FD EAOO EA03 EA05 EA07 EA09 EAOB EAOE EA10 EA11 EA13 EA15 EA16 EA17 EA18 EA1A EA1D EA20 EA22 EA24
DO 20 20 20 29 FO A9 85 AD 49 4A 29 DO EA EA EA 66 20 20 29 FO C6
EA26 EA28 EA2B
DO E3 20 AS E9 AS 85
BNE $EAOB JSR $E9AS LDA $85
EA2D
60
RTS
FD 9C 59 CO 04 F6 00 F8 00 01
E9 EA E9
18
02 F6
85 59 EA CO E9 04 F6 98
BNE JSR JSR JSR AND BEQ LDA STA LDA EOR LSR AND BNE NOP NOP NOP ROR JSR JSR AND BEQ DEC
delay loop, approx 50 micro sec. $E9F7 $E99C $EA59 $E9CO #$04 $E9FD #$00 $F8 $1800 #$01 A #$02 $EAOB
$85 $EA59 $E9CO #$04 $EA1A $98
****************************** EA2E EA2F
78 20 07 D1
SEI JSR $D107
EA32 EA34 EA36
BO 05 B5 F2 6A
BCS $EA39 LDA $F2,X ROR A
329
DATA OUT, bit '1'10 test for ATN read IEEE port CLOCK IN? no, wait set EOI flag IEEE port invert data byte and into carry CLOCK IN?
accept next bit test for ATN read IEEE port CLOCK IN? no decrement bit counter all bits received? DATA OUT bit '0 ' hi load data byte again
accept data from serial bus open channel for writing channel not active? WRITE flag into carry
ABACUS Software
OB 84 FO FO 03 4E EA
Anatomy of the 1541
$EA44 $84 #$FO #$FO $EA44 JMP $EA4E
BCS LDA AND CMF BEQ
set, accept byte secondary address
EA37 EA39 EA3B EA3D EA3F EA41
BO A5 29 C9 FO 4C
EA44
20 C9 E9
JSR $E9C9
EA47 EA48 EA4B
58 20 B7 CF 4C 2E EA
CLI JSR $CFB7 JMP $EA2E
and write in buffer to loop beginning
EA4E EA50 EA53
A9 00 8D 00 18 4C E7 EB
LDA #$00 STA $1800 JMP $EBE7
reset IEEE port to wait loop
EA56
4C 5B E8
JMP $E85B
****************************** $7D $EA63 $1800 $EA6B
OPEN command? yes else ignore, to wait loop get data byte from bus
to serial bus main loop test for ATN ATN active? no IEEE port ATN no longer active?
EA59 EA5B EA5D EA60
A5 7D FO 06 AD 00 18 10 09
LDA BEQ LDA BPL
EA62
60
RTS
EA63 EA66
AD
00 18 10 FA
LDA $1800 BPL $EA62
IEEE port ATN not active, then return
EA68
4C 5B E8
JMP $E85B
EA6B
4C D7 E8
JMP $E8D7
receive command byte clear ATN flag, serve serial bus
330
ABACUS Software
Anatomy of the 1541
****************************** EA6E
A2 00
LDX #$00
EA70 EA71
2C A5 6F
.BYTE $2C LDX $6F
EA73 EA74 EA75
9A BA A9 OS
TXS TSX LDA #$OS
EA77 EA7A
OD 00 1C 4C EA FE
ORA $lCOO JMP $FEEA
EA7D EA7E EA7F EAS1 EAS3 EAS4 EAS6 EAS9 EASB EASE EASF EA90 EA92 EA94 EA95 EA97 EA98 EA9A EA9C EA9E
9S lS 69 DO SS DO AD 29 8D 9S lS 69 DO 88 DO CA 10 EO DO FO
TYA CLC ADC BNE DEY BNE LDA AND STA TYA CLC ADC BNE DEY BNE DEX BPL CPX BNE BEQ
01 FC FS 00 1C F7 00 1C 01 FC F8 DB FC FO D4
flash LED for hardware defects, self-test blink once, zero page blink X+1 times for RAM/ROM error select LED bit in the port turn LED on, back to $EA7D
#$01 $EA7F $EA7E $lCOO #$F7 $lCOO #$01 $EA90
turn LED off
delay l_'JOp
$EA8F $EA75 #$FC $EASE $EA74
****************************** SEI 7S EAAO CLD DS EAA1 LDX #$FF EAA2 A2 FF STX $1803 EAA4 8E 03 18 331
wait for delay turn LED on again RESET routine
direction output
ABACUS Software
EAA7 EAA8 EAAA EAAC EAAD EAAF EABO EAB2 EAB3 EAB5
4C AO A2 8A 95 E8 DO 8A D5 DO
EAB7 EAB9 EABA EABC EABE EACO EAC2 EAC4 EAC6 EAC7 EAC9 EACB EACD EACF EAD1 EAD2 EAD4 EAD5 EAD7 EAD9 EADA EADC EADD EADF EAE1 EAE2 EAE4 EAE6 EAE8 EAEA
F6 C8 DO D5 DO 94 B5 DO E8 DO E6 86 A9 85 A8 A2 18 C6 71 C8 DO CA DO 69 AA C5 DO EO DO A9
10 FF 00 00 00 FA 00 B7 00 FB 00 AE 00 00 A8 E9 6F 76 00 75
20 76 75 FB F6 00 76 39 CO DF 01
Anatomy of the 1541
JMP LDY LDX TXA STA INX BNE TXA CMP BNE
$FF10 #$00 #$00
patch
$OO,X
erase zero page
INC INY BNE CMP BNE STY LDA BNE INX BNE INC STX LDA STA TAY LDX CLC DEC ADC INY BNE DEX BNE ADC TAX CMP BNE CPX BNE LDA
$OO,X
$EAAC $OO,X $EA6E
$EAB7 $OO,X $EA6E $OO,X $OO,X $EA6E
is byte erased? no, then to error display (flash)
error error
$EAB2 $6F $76 #$00 $75 #$20
test 32 pages
$76 ($75), Y $EAD7 $EAD5 #$00 $76 $EB1F #$CO $EAC9 #$01
332
test ROM
ROM error
Anatomy of the 1541
ABACUS Software
EAEC EAEE EAFO
85 76 E6 6F A2 07
STA $76 INC $6F LDX #$07
EAF2 EAF3 EAF4 EAF6 EAF8 EAF9 EAFB EAFD EAFE EBOO EB02 EB04 EB05 EB06 EB07 EB09 EBOB EBOD EBOF EBll EB13 EB15 EB17 EB1S EBIA EBIB EB1D EB1F
98 18 65 76 91 75 C8 DO F7 E6 76 CA DO F2 A2 07 C6 76 88 98 18 65 76 D1 75 DO 12 49 FF 91 75 51 75 91 75 DO 08 98 DO EA CA DO E5 FO 03 4C 71 EA
TYA CLC ADC $76 STA ($75) , Y INY BNE $EAF2 INC $76 DEX BNE $EAF2 LDX #$07 DEC $76 DEY TYA CLC ADC $76 CMP ($75) ,Y BNE $EB1F EOR #$FF STA ($75), Y EOR ($75), Y STA ($75), Y BNE $EB1F TYA BNE $EB04 DEX ENE $EB02 BEQ $EB22 JMP $EA71
EB22 EB24
A2 45 9A
EB25 EB28 EB2A EB2D
AD 29 8D A9
00 lC F7 00 lC 01
test RAM, beginning at page 7
LDX #$45 TXS LDA AND STA LDA
$lCOO #$F7 $lCOO #$01
333
RAM error
RAM error
continue test ok to error display initialize stack pointer turn LED off
ABACUS Software
Anatomy of the 1541
EB2F
8D OC 18
STA $180C
EB32 EB34
A9 82 8D OD 18
LDA #$82 STA $180D
EB37 EB3A EB3D
8D OE 18 AD 00 18 29 60
STA $180E LDA $1800 AND #$60
EB3F EB40 EB41
OA 2A 2A
ASL A ROL A ROL A
EB42 EB43
2A 09 48
ROL A ORA #$48
EB45
85 78
STA $78
EB47
49 60
EOR #$60
EB49
85 77
STA $77
EB4B EB40 EB4F EB51
A2 AO A9 95
LDX LOY LDA STA
EB53 EB54
E8 B9 EO FE
INX LOA $FEEO,y
EB57 EB59 EB5A EB5B EB5D EB5F EB61 EB63
95 E8 C8 CO DO A9 95 E8
STA INX INY CPY BNE LDA STA INX
EB64 EB66
A9 02 95 99
00 00 00 99
99 05 FO 00 99
#$00 #$00 #$00 $99,X
$99, X
CAl (ATN IN) trigger on pos edge interrupt allowed through ATN IN read port B isolate bits 5 (device #)
&
6
rotate to bit positions o & 1 add offset from 8 + $40 for TALK device number for TALK (send) erase bit 6, set bit 5 device number + $20 for LISTEN
low-byte of buffer address high byte of address from table save
#$05 $EB4F #$00 $99,X
LDA #$02 STA $99, X
334
ptr $A3/$A4 to $200, input buffer
Anatomy of the 1541
ABACUS Software
INX LDA #$D5 STA $99,X INX
EB68 EB69 E86B EB6D
E8 A9 D5 95 99 E8
EB6E EB70 EB72 EB74 EB76
A9 95 A9 A2 9D
02 99 FF 12 2B 02
LDA STA LDA LDX STA
#$02 $99,X #$FF #$12 $022B,X
EB79 EB7A EB7C EB7E EB80 EB82
CA 10 A2 95 95 95
FA 05 A7 AE CD
DEX BPL LDX STA STA STA
$EB76 #$05 $A7,X $AE,X $CD,X
EB84 EB85 EB87 EB89 EB8B EB8D EB8F EB91 EB93 EB95 EB97
CA 10 A9 85 A9 85 A9 85 85 A9 8D
F7 05 AB 06 AC FF AD B4 05 3B 02
DEX BPL LDA STA LDA STA LDA STA STA LDA STA
$EB7E #$05 $AB #$06 $AC #$FF $AD $B4 #$05 $023B
EB9A EB9C
A9 84 8D 3A 02
LDA #$84 STA $023A
EB9F
A9 OF
LDA #$OF
EBAI
8D 56 02
STA $0256
EBA4 EBA6 EBA8
A9 01 85 F6 A9 88
LDA #$01 STA $F6 LDA #$88 335
pointer $A5/$A6 to $2D5, buffer error msg message pointer
fill channel table with $FF ( "not allocated" )
erase buffer table erase side-sector table buffer assign buffer assign
5 to channel 4 6 to channel 5
channel 5 WRITE flag cleared channel 4 WRITE flag set initialize channel allocation reg bit '1 ' equals channel free WRITE flag
ABACUS Software
Anatomy of the 1541
EBAA EBAC EBAE
85 F7 A9 FO 8D 4F 02
STA $F7 LL. .. ,;::$EO STA $024F
EBBI
A9 FF
LDA #$FF
EBB3 EBB6 EBB8
8D 50 02 A9 01 85 lC
STA $0250 LDA #$01 STA $IC
EBBA EBBC EBBF
85 ID 20 63 CB 20 FA CE
STA $lD JSR $CB63 JSR $CEFA
EBC2
20 59 F2
JSR $F259
EBC5 EBC7 EBC9
A9 22 85 65 A9 EB
LDA #$22 STA $65 LDA #$EB
EBCB EBCD EBCF EBDI
85 A9 85 A9
STA LDA STA LDA
EBD3 EBD5
85 6A A9 73
STA $6A LDA #$73
EBD7
20 Cl E6
JSR $E6Cl
EBDA EBDC EBDF
A9 00 8D 02 18 A9 00
LDA #$00 STA $1800 LDA #$lA
EBEI EBE4
8D 02 18 20 80 E7
STA $1802 JSR $E780
EBE7 EBE8 EBEB EBED
58 AD 00 18 29 £5 8D 00 18
CLI LDA $1800 AND #$E5 STA $1800
66 OA 69 05
$66 #$OA $69 #$05
336
READ flag 5 buffers free initialize buffer allocation reg $24F/$250, 16 bit, l=buffer allocated set flags for WRITE protect set vector for UO initialize channel table initialization for disk controller pointer $65/$66 to $EB22 step width 10 for sector assignment 5 read attempts prepare power-up message 73, Icbm dos v2.6 1541' clear data register DATA OUT, CLOCK OUT and ATN A to output data dir port B check for auto-start reset serial po:::-t
ABACUS Software
EBFO EBF3 EBF5 EBF7 EBFA EBFC
AD FO A9 8D 85 20
55 02 OA 00 55 02 67 46 C1
Anatomy of the 1541
LDA BEQ LDA STA STA JSR
$0255 $EBFF #$00 $0255 $67 $C146
****************************** EBFF 58 CLI LDA $7C ECOO A5 7C EC02 EC04 EC07 EC08 ECOA ECOC ECOE EC10 EC12 EC14 EC17 EC19 EC1B EC1D EC1F EC22 EC23 EC26 EC28 EC29 EC2B EC2D EC2F EC31
FO 4C 58 A9 85 A9 85 85 A6 BD C9 FO 26 85 20
03 5B E8
EC34 EC36 EC38 EC39
10 05 29 01
OE 72 00 6F 70 72 2B 02 FF 10 3F 82 93 DF
AA
BD 5B 02 29 01 AA
F6 C6 10 AO B9
6F 72 E3 04 00 00
AA
F6 6F
BEQ JMP CLI LDA STA LDA STA STA LDX LDA CMP BEQ AND STA JSR TAX LDA AND TAX INC DEC BPL LDY LDA
$EC07 $E85B #$OE $72 #$00 $6F $70 $72 $022B,X #$FF $EC2B #$3F $82 $DF93
command flag set? no reset command flag analyze and execute command wait loop ATN signal discovered? no to IEEE routine 14 as secondary addr job counter secondary address channel assigned? no channel number get buffer number
$025B,X #$01
drive number
$6F,X $72 $EC12 #$04 $OOOO,Y
increment job cntr 10 address continue search buffer counter disk controller in action? no isolate drive #
BPL $EC3B AND #$01 TAX INC $6F,X
337
increment job cntr
ABACUS Software
Anatomy of the 1541
EC3B EC3C EC3E EC3F EC42 EC44 EC45 EC47 EC49 EC4B EC4D EC4F EC51
88 10 F3 78 AD 00 1C 29 F7 48 A5 7F 85 86 A9 00 85 7F A5 6F FO OB A5 1C
DEY BPL SEI LDA AND PHA LDA STA LDA STA LDA BEQ LDA
EC53 EC55
FO 03 20 13 D3
BEQ $EC58 JSR $D313
EC58 EC59 EC5B EC5C EC5E EC60 EC62
68 09 48 E6 A5 FO A5
EC64 EC66
FO 03 20 13 D3
EC69 EC6A EC6C EC6D EC6F EC71
68 09 00 48 A5 86 85 7F 68
PHA LDA $86 STA $7F PLA
EC72
AE 6C 02
LDX $026C
FO 21 00 lC EO 80 DO 03
BEQ LDA CPX BNE
EC75 EC77 EC7A EC'IC
AD
$EC31
next buffer
$lCOO #$F7
erase LED bit
$7F $86 #$00 $7F $6F $EC5C $lC
drive number drive 0 job for drive O? no write protect for drive O? no close all channels to drive 0
PLA 08
ORA #$08
7F 70 OB ID
PHA INC LDA BEQ LDA
$7F $70 $EC6D $lD
BEQ $EC69 JSR $D313
set LED bit increment drive # job for drive 1? no write protect for drive I? no close all channels to drive 1
PLA ORA #$00
get drive # back bit for LED
$EC98 $lCOO #$80 $EC81 338
interrupt counter for LED flash to zero?
ABACUS Software
Anatomy of the 1541
EC7E EC81
4C 8B EC AE 05 18
EC84 EC86 EC88 EC8B EC8E EC90
30 A2 8E CE 00 40
EC93 EC95 EC98 EC9B
A2 8E 80 4C
12
JMP $EC8B LOX $1805
05 18 6C 02 08 60 02
BMI LOX STX OEC BNE EOR
$EC98 #$AO $1805 $026C $EC98 $0260
10 6C 02 00 1C FF EB
LOX STX STA JMP
#$10 $026C $lCOO $EBFF
AO
****************************** EC9E A9 00 LOA #$00 ECAO 85 83 STA $83 ECA2 A9 01 LOA #$01 ECA4 20 E2 01 JSR $01E2
ECA7 ECA9
A9 00 20 C8 04
LDA #$00 JSR $04C8
ECAC ECAE ECBO ECB3 ECB6 ECB7 ECB9 ECBC ECBE ECCl ECC3 ECC6 ECC8 ECCB
A6 A9 90 20
LOX LOA STA JSR TAX LOA STA LOA JSR LOA JSR LOA JSR JSR
ECCE
AD 72 02
82 00 44 02 93 OF
AA
AS 90 A9 20 A9 20 A9 20 20
7F SB 01 F1 04 F1 01 Fl F1
02 CF CF CF CF
$82 #$00 $0244,X $OF93 $7F $02SB,X #$01 $CFF1 #$04 $CFF1 #$01 $CFF1 $CFF1
LOA $0272
339
clear timer interrupt set timer decrement counter not yet zero? invert condition bit for LEO reset counter turn LEO on/off back to wait loop LOAD "$" secondary address 0 find channel and buffer initialize buffer pointer channel number ptr to end = zero get buffer number drive number bring in table 1 write in buffer 4, start addr $0401 write in buffer 2 times 1 write in buffer as link address drive number
Anatomy of the 1541
ABACUS Software
ECD1
20 F1 CF
JSR $CFF1
ECD4 ECD6 ECD9 ECDC ECDF ECEO ECE1
A9 20 20 20 OA
D6 99
LDA JSR JSR JSR ASL TAX DEC
ECE3 ECE5 ECE7
D6 99 A9 00 20 F1 CF
DEC $99,X LDA #$00 JSR $CFF1
ECEA ECEC
A9 01 20 F1 CF
LDA #$01 JSR $CFF1
ECEF ECF2 ECF5 ECF7 ECFA ECFD EDOO ED03 ED06 ED08
20 F1 CF 20 CE C6 90 2C AD 72 02 20 F1 CF AD 73 02 20 F1 CF 20 59 ED A9 00 20 F1 CF
JSR JSR BCC LDA JSR LDA JSR JSR LDA JSR
$CFF1 $C6CE $ED23 $0272 $CFF1 $0273 $CFF1 $ED59 #$00 $CFF1
EDOB EDOD ED10 ED11 ED12 ED14 ED16 ED18 ED1A ED1D ED20 ED22
DO DD 20 93 DF OA
BNE JSR ASL TAX LDA STA LDA LDY STA STA LDA RTS
$ECEA $DF93 A
00 F1 CF 59 ED 93 DF
AA
AA
A9 95 A9 A4 8D 99 A5 60
00 99 88 82 54 02 F2 00 85
#$00 $CFF1 $ED59 $DF93 A $99, X
#$00 $99, X #$88 $82 $0254 $00F2,Y $85
340
write in buffer as line number line number hi in buffer dir entry in buffer get buffer number decrement buffer pointer
o as line end in buffer 2 times 1 as link address dir entry in buffer another entry? block number 10 in buffer block number hi in buffer dir entry in buffer zero as end marker in buffer buffer full? no get buffer number
buffer ptr to zero set READ flag channel number flag for channel data byte
ABACUS Software
Anatomy of the 1541
****************************** ED23 AD 72 02 LDA $0272 ED26 20 F1 CF JSR $CFF1 ED29 AD 73 02 LDA $0273 ED2C 20 Fl CF JSR $CFF1 ED2F 20 59 ED JSR $ED59 ED32 ED35 ED36 ED37 ED39 ED3B ED3D ED40
20 93 DF OA D6 D6 A9 20 20
99 99 00 F1 CF F1 CF
ED43 ED46 ED49 ED4A ED4B ED4E ED50 ED53 ED56
20 20 OA A8 B9 A6 9D DE 4C
F1 CF 93 DF
AA
99 82 44 44 OD
02 02 02 ED
JSR ASL TAX DEC DEC LDA JSR JSR
$DF93 A
JSR JSR ASL TAY LDA LDX STA DEC JMP
$CFF1 $DF93 A
$99,X $99,X #$00 $CFF1 $CFF1
$0099,Y $82 $0244,X $0244,X $EDOD
****************************~*
ED59 ED5B ED5E
AO 00 B9 B1 02 20 F1 CF
LDY #$00 LDA $02B1,Y JSR $CFF1
ED61 ED62 ED64 ED66
C8 CO IB DO F5 60
INY CPY #$lB BNE $ED5B RTS
****************************** ED67 ED6A ED6C
20 37 D1 FO 01 60
JSR $D137 BEQ $ED6D RTS 341
block number 10 write in buffer block number hi in buffer , in 'Blocks free. buffer get buffer number times 2 buffer ptr minus 2 three zeroes as program end get buffer number times 2 buffer pointer as end marker
transmit dir line char from buffer write in output buffer 27 characters?
get byte trom buffer get byte buffer ptr zero?
ABACUS Software
Anatomy of the 1541
ED6D ED6F ED71 ED74 ED76 ED78 ED7B ED7D
85 A4 B9 FO A9 99 A5 60
ED7E ED7F
48 20 EA EC
PHA JSR $ECEA
ED82 ED83
68 60
PLA RTS
85 82 44 02 08 80 F2 00 85
STA LDY LDA BEQ LDA STA LDA RTS
$85 $82 $0244,Y $ED7E #$80 $00F2,Y $85
****************************** ED84 JSR $C1D1 20 D1 C1 ED87 ED8A ED8C ED8F
20 A9 8D 20
42 DO 40 F9 02 B7 EE
ED92 ED94 ED97
A9 00 8D 92 02 20 AC C5
LDA #$00 STA $0292 JSR $C5AC
ED9A ED9C ED9E EDAO EDA3 EDA5
DO A9 85 AD 85 20
BNE LDA STA LDA STA JSR
EDA8 EDAA EDAD
A9 00 8D F9 02 20 FF EE
LDA #$00 STA $02F9 JSR $EEFF
EDBO
4C 94 C1
JMP $C194
3D 00 81 8E FE 80 E5 ED
JSR LDA STA JSR
$D042 #$40 $02F9 $EEB7
$EDD9 #$00 $81 $FE85 $80 $EDE5
342
save data byte channel number set end marker zero (LOAD $)? set READ flag data byte
create directory line in buffer
V command, 'collect' find drive number in input line load BAM create new BAM in buffer load directory, find 1st entry found? sector 0 18 track 18 for BAM mark dir blocks as allocated write BAM back to disk done, prepare disk status
ABACUS Software
Anatomy of the 1541
****************************** EDB3 INY C8 EDB4 LDA ($94),Y B1 94 ED86 48 PHA EDB7 C8 INY EDB8 LDA ($94) ,Y B1 94 EDBA 48 PHA EDBB AO 13 LDA #$13 94 OA 80
B1 FO 85 C8 B1 85
EDC8
20 E5 ED
JSR $EDE5
EDCB EDCC EDCE
68 85 81 68
PLA STA $81 PLA
EDCF EDD1
85 80 20 E5 ED
STA $80 JSR $EDE5
EDD4
20 04 C6
JSR $C604
EDD7 EDD9 EDDB EDDD
FO AO B1 30
BEQ LDY LDA BMI
EDDF
20 B6 C8
JSR $C8B6
EDE2
4C D4 ED
JMP $EDD4
94 81
C3 00 94 D4
LDA BEQ STA INY LDA STA
($94),Y $EDCB $80
EDBD EDBF EDC1 EDC3 EDC4 EDC6
($94),Y $81
save track and sector pointer to side-sector block no track following? track and sector of 1st side-sector block mark side-sector blocks as allocated get track and sector back
$ED9C #$00 ($94),Y $EDB3
****************************** EDE5
20 5F D5
JSR $D55F
EDE8
20 90 EF
JSR $EF90
343
mark blocks of file as allocated read next entry in directory end of directory? file type bit 7 set, file closed? file type to zero and write BAM allocate file blocks in BAM check track and sector numbers allocate blk in BAM
Anatomy of the 1541
ABACUS Software
75 00 C8 37 80 37 81 80 03 27
D4
EDEB EDEE EDFO EDF3 EDF6 EDF8 EDFB EDFD EDFF EE01
20 A9 20 20 85 20 85 A5 DO 4C
EE04 EE07 EEOA
20 90 EF 20 4D D4 4C EE ED
D4 D1 D1
D2
JSR LDA JSR JSR STA JSR STA LDA BNE JMP
buffer pointer zero get byte from buffr track get byte from buffr sector another block? yes close channel
JSR $EF90 JSR $D44D JMP $EDEE
allocate blk in BAM read next block continue
****************************** 20 12 C3 JSR $C312 EEOD LDA $E2 EE10 A5 E2 BPL $EE19 EE12 10 05 LDA #$33 EE14 A9 33 4C C8 C1 JMP $C1C8 EE16 kJD #$01 EE19 29 01 STA $7F EE1B 85 7F JSR $CIOO EEID 20 00 Cl EE20 A5 7F LDA $7F ASL A EE22 OA TAX EE23 AA LDY $027B EE24 AC 7B 02 EE27 CPY $0274 CC 74 02 EE2A EE2C EE2F EE31 EE34 EE36 EE39 EE3B EE3D EE40 EE43
FO B9 95 B9 95 20 A9 85 20 20 4C
1A 00 12 01 13 07 01 80 C6 05 56
02 02 D3 C8 FO EE
read next block
$D475 #$00 $D4C8 $D137 $80 $D137 $81 $80 $EE04 $D227
BEQ LDA STA LDA STA JSR LDA STA JSR JSR JMP
$EE46 $0200,Y $12,X $0201,Y $13,X $D307 #$01 $80 $C8C6 $FOO5 $EE56 344
N command, 'header' get drive number drive number not clear? 33,
'syntax error'
drive number turn LED on drive number times 2 comma position compare with end name format without ID first char of ID save second character close all channels track 1 format disk erase buffer continue as below
ABACUS Software
Anatomy of the 1541
EE46 EE49 EE4B EE4E
20 A6 BD CD
EE51 EE53
FO 03 4C 72 D5
BEQ $EE56 JMP $D572
EE56 EE59 EE5B EE5C EE5D EE5E
20 B7 EE AS F9 A8 OA AA AD
88 FE
JSR LDA TAY ASL TAX LD"\
EE61 EE63 EE66 EE68
95 AE A9 20
99 7A 02 IB 6E C6
STA LDX LDA JSR
$99,X $027A #$lB $C66E
EE6B EE6D EE6F EE72 EE75 EE76 EE77 EE78 EE7A EE7C EE7D EE7F EE81 EE82 EE83 EE85 EE87 EE88 EE8B
AO A6 AD 9D 8A OA
12 7F D5 FE 01 01
LDY LDX LDA STA TXA ASL TAX LDA STA INY LDA STA INY INY LDA STA INY LDA STA
#$12 $7F $FED5 $0101,X
42 DO 7F 01 01 D5 FE
AA
B5 91 C8 B5 91 C8 C8 A9 91 C8 AD 91
12 94 13 94 32 94 D5 FE 94
JSR LDX LDA CMP
$D042 $7F $0101,X $FED5
$EEB7 $F9
load BAM drive number 'A' , marker for 1541 format ok 73, 'cbm dos v2.6 1541' create BAM buffer number
A $FE88
$90, start of disk name buffer ptr to name 27 write filenames in buffer position 18 drive number 'A' , 1541 format
A
times 2
$12,X ($94),Y
ID, first character in buffer
$13,X ($94),Y
and second char in buffer
#$32 ($94),Y
'2 ' in buffer
$FED5 ($94),Y
'A' 1541 format in buffer
345
ABACUS Software
Anatomy of the 1541
EE8D EE8F EE91 EE94 EE96
AO 91 AD 85 20
EE99 EE9B EE9D
A9 01 85 81 20 93 EF
LDA #$01 STA $81 JSR $EF93
EEAO EEA3
20 FF EE 20 05 FO
JSR $EEFF JSR $£'005
EEA6 EEA8 EEAA EEAC EEAF EEB1 EEB4
AO A9 9A 20 C6 20 4C
LDY LDA STA JSR DEC JSR JMP
02 6D 85 FE 80 93 EF
01 FF 6D 64 D4 81 60 D4 94 C1
LDY STA LDA STA JSR
#$02 ($ 6D) , Y $FE85 $80 $EF93
#$01 #$FF ($ 6D) , Y $D464 $81 $D460 $C194
****************************** EEB7 20 D1 FO JSR $FOD1 EEBA AO 00 LDY #$00 EEBC A9 12 LDA #$12 EEBE STA ($ 6D) , Y 91 6D EECO C8 INY EEC1 98 TYA EEC2 STA ($ 6D) , Y 91 6D EEC4 C8 INY EEC5 C8 INY EEC6 INY C8 EEC7 A9 00 LDA #$00 EEC9 STA $6F 85 6F EECB STA $70 85 70 EECD EECF EEDO EED1
85 71 98 4A 4A
STA $71 TYA LSR A LSR A
and at position 2 18 track number mark block as allocated 1 sector number mark block as allocated write BAM pointer $6D/$6E to buffer, erase buffr trk following is 0 write BAM dec sector #, 0 read block prepare disk status create BAM 18 pointer to dir trk 1 pointer to dir sec
3 bytes = 24 bits for sectors byte position divided by 4 track number
346
ABACUS Software
EED2 EED5 EED7 EEDB EED9 EEDA EEDC EEDE EEEO EEE1 EEE3 EEE5 EEE7 EEEB EEE9 EEEB EEED EEEF EEF1
20 4B F2 91 6D CB AA
3B 26 26 26 CA DO B5 91 CB EB EO 90 CO 90 4C
6F 70 71 F6 6F 6D 03 F6 90 D6 75 DO
Anatomy of the 1541
JSR STA INY TAX SEC ROL ROL ROL DEX BNE LDA STA INY INX CPX BCC CPY BCC JMP
$F24B ($ 6D) , Y
get # of sectors and in BAM
$6F $70 $71
create bit model
$EED9 $6F,X ($ 6D) , Y #$03 $EEE3 #$90 $EEC7 $D075
****************************** EEF4 20 93 DF JSR $DF93 TAX EEF7 AA BD 5B 02 LDA $025B,X EEFB #$01 $7F $7F $0251,Y
EEFB EEFD EEFF EF01
29 01 85 7F A4 7F B9 51 02
AND STA LDY LDA
EF04 EF06
DO 01 60
BNE $EF07 RTS
EF07 EF09
A9 00 99 51 02
LDA #$00 STA $0251,Y
EFOC
20 3A EF
JSR $EF3A
EFOF EF11
A5 7F OA
LDA $7F ASL A
347
3 bytes the BAM in buffer
position 144? no, next track calculate # of free blocks write BAM if needed get buffer number command for disk controller isolate drive # BAM-changed flag set? yes
reset BAM-changed flag set buffer pointer for BAM drive number times 2
ABACUS Software
EF12 EF13 EF16 EF17 EF18 EFIA EFID EFIF EF20 EF22 EF24 EF25 EF26 EF28 EF2B EF2D EF2F
48 20 68 18 69 20 A5 48 A9 85 OA OA 85 20 E6 A5 CD
EF32 EF34 EF35 EF37
90 FO 68 85 80 4C 8A D5
A5 FO 01 A5 FO 80 01 80 6D 20 F2 80 80 D7 FE
Anatomy of the 1541
PHA JSR PLA CLC ADC JSR LDA PHA LDA STA ASL ASL STA JSR INC LDA CMP
$FOA5
verify BAM entry
#$01 $FOA5 $80
increment track # verify BAM entry track
#$01 $80 A A $6D $F220 $80 $80 $FED7
BCC $EF24 PLA STA $80 JMP $D58A
****************************** EF3A EF3D EF3E EF41 EF43 EF46 EF48 EF4A EF4C
20 OF Fl AA
20 A6 BD 85 A9 85 60
DF FO F9 EO FE 6E 00 6D
JSR TAX JSR LDX LDA STA LDA STA RTS
$FIOF $FODF $F9 $FEEO,X $6E #$00 $6D
****************************** EF4D EF4F EF52 EF55
A6 BD 8D BD
7F FA 02 72 02 FC 02
LDX LDA STA LDA
$7F $02FA,X $0272 $02FC,X
348
track 1 times 4 verify BAM increment track # and compare with max val + 1 = 36 ok, next track get track # back write BAM to disk set buffer pointer for BAM get 6 for drive 0 allocate buffer buffer number buffer adr, hi byte
10 byte pointer to $6D/$6E get # of free blocks for dir drive number # of blocks, 10 # of blocks, hi
Anatomy or the 1541
ABACUS Software
EF58 EF5B
8D 73 02 60
STA $0273 RTS
****************************** JSR $EFF1 EF5C 20 F1 EF JSR $EFCF EF5F 20 CF EF EF62 EF63
38 DO 22
SEC BNE $EF87
EF65 EF67
B1 6D 1D E9 EF
LDA ($ 6D) , Y ORA $EFE9
EF6A EF6C
91 6D 20 88 EF
STA ($ 6D) , Y JSR $EF88
EF6F EF71 EF72 EF74
A4 6F 18 B1 6D 69 01
LDY $6F CLC LDY ($ 6D) , Y ADC #$01
EF76 EF78 EF7A EF7D EF7F
91 A5 CD FO FE
EF82 EF84
DO 03 FE FC 02
BNE $EF87 INC $02FC,X
EF87
60
RTS
6D 80 85 FE 3B FA 02
STA LDA CMP BEQ INC
($ 6D) , Y $80 $FE85 $EFBA $02FA,X
****************************** EF88 EF8A EF8C EF8F
A6 7F A9 01 9D 51 02 60
LDX $7F LDA #$01 STA $0251,X RTS
349
in buffer for dir mark block as free set buffer pointer clear bit for sector in BAM block already free, then done bit pattern of BAM set bit X, marker for free set flag for BAM changed
increment # of free blocks per track track equal to 18? then skip inc # of free blocks in disk increment number of blocks hi set flag for 'BAM changed' drive number flag
=
1
Anatomy or the 1541
ABACUS Software
****************************** EF90 EF93
20 F1 EF 20 CF EF
JSR $EFF1 JSR $EFCF
EF96
FO 36
BEQ $EFCE
EF98 EF9A EF9D EF9F
B1 5D 91 20
LDA EOR STA JSR
EFA2 EFA4 EFA6 EFA7
A4 6F B1 6D 38 E9 01
LDA $6F LDA ($6D), Y SEC SBC #$01
EFA9 EFAB EFAD EFBO EFB2
91 AS CD FO BD
STA LDA CMP BEQ LDA
EFB5 EFB7
DO 03 DE FC '02
BNE $EFBA DEC $02FC,X
EFBA EFBD
DE FA 02 BD FC 02
DEC $02FA,X LDA $02FC,X
EFCO
DO OC
BNE $EFCE
EFC2 EFC5 EFC7 EFC9 EFCB EFCE
BD C9 BO A9 20 60
LDA CMP BCS LDA JSR RTS
6D E9 EF 6D 88 EF
6D 80 85 FE OB FA 02
FA 02 03 05 72 C7 E6
($ 6D) , Y $EFE9,X ($ 6D) , Y $EF88
($ 6D) , Y $80 $FE85 $EFBD $02FA,X
$02FA,X #$03 $EFCE #$72 $E6C7
350
mark block as allocated set buffer pointer clear bit for sector in BAM already allocated, then done clear bit for block set flag for BAM changed
decrement # of blocks per track track 18? number of free blocks 10 decrement number of free blocks number of free blocks hi more than 255 blocks free? free blocks 10 less than 3? 72,
'disk full'
Anatomy of the 1541
ABACUS Software
****************************** EFCF
20 11 FO
JSR $F011
EFD2 EFD3 EFDS EFD7 EFD8 EFD9 EFDA EFDB EFDD EFDE EFEO EFE2 EFE3 EFES
98 85 AS 4A 4A 4A 38 65 A8 AS 29
B1 6D 3D E9 EF
TYA STA LDA LSR LSR LSR SEC ADC TAY LDA AND TAX LDA AND
EFE8
60
RTS
6F 81
6F 81 07
AA
$6F $81 A A A
erase bit for sector in BAM entry find BAM field for this track sector divide by 8
$6F $81 #$07 ($6D),Y $EFE9,X
byte # in BAM entry sector number bit # in BAM entry byte in BAM clear bit for corresponding sector
****************************** 01 02 04 08 10 20 40 80 EFE9
powers of 2
******************************
write BAM after change
EFF1 EFF3
A9 FF 2C F9 02
LDA #$FF BIT $02F9
EFF6 EFF8 EFFA EFFC EFFE FOOl F004
FO 10 70 A9 8D 4C 60
BEQ BPL BVS LDA STA JMP RTS
OC OA 08 00 F9 02 8A DS
$F004 $F004 $F004 #$00 $02F9 $DS8A
****************************** JSR $EF3A 20 3A EF FOOS F008
AO 00
LDY #$00
351
flag for BAM changed set? no reset flag write block erase BAM buffer pointer $6D/$6E to BAM buffer
ABACUS Software
FOOA FOOB FOOD FOOE F010
Anatomy of the 1541
98 91 6D C8 DO FB 60
TYA STA ($6D) , Y INY BNE $FOOB RTS
erase BAM buffer
****************************** F011 F013 F014 F016 F017 F019 FOIB FOlD FOIF F022
A5 48 A5 48 A6 B5 FO A9 20 20
F025 F027 F028 F029 F02B F02C F02E F03l F033 F034 F036 F039 F03B F03E F040 F042 F045 F046 F047 F048 F04A F04C F04E
85 6F 8A OA 85 70 AA AS 80 DD 9D FO OB E8 86 70 DD 9D FO 03 20 5B A5 70 A6 7F 9D 9B OA OA 18 69 A1 85 6D A9 02 69 00
6F 70 7F FF 05 74 48 E6 OF Fl
02
02 FO 02
LDA PHA LDA PHA LDX LDA BEQ LDA JSR JSR
$6F $70 $7F $FF,X $F022 #$74 $E648 $FlOF
STA $6F TXA ASL A STA $70 TAX LDA $80 CMP $029D,X BEQ $F03E INX STX $70 CMP $029D,X BEQ $F03E JSR $F05B LDA $70 LDX $7F STA $029B,X ASL A ASL A CLC ADC #$Al STA $6D LDA #$02 ADC #$00
352
drive number drive zero? 'drive not ready' get buffer number for BAM
track
drive number times 4
Anatomy of the 1541
ABACUS Software
F050 F052 F054 F055 F057 F058 F05A
85 AO 58 85 68 85 60
6E 00 70 6F
STA LDY PLA STA PLA STA RTS
$6E #$00 $70 $6F
****************************** LDX $6F A6 6F F05B JSR $FODF F05D 20 DF FO LDA $7F A5 7F F060 TAX AA F062 ASL A OA F063 ORA $029B,X 1D 9B 02 F064 EOR #$01 01 49 F067 #$03 AND 29 03 F069 $70 STA 70 85 F06B JSR $FOA5 20 A5 FO F06D LDA $F9 A5 F9 F070 ASL A OA F072 TAX AA F073 LDA $80 A5 80 F074 A ASL OA F076 ASL A OA F077 STA $99,X F078 95 99 F07A F07C F07D F07E F07F F081 F084 F086 F088 F08A F08B F08C F08E F090
A5 OA OA A8 A1 99 A9 81 F6 C8 98 29 DO A6
70
99 A1 02 00 99 99 03 EF 70
LDA ASL ASL TAY LDA STA LDA STA INC INY TYA AND BNE LDX
drive number
buffer number track times 4 equals pointer in BAM field
$70 A A ($99,X) $02A1,X #$00 ($99,X) $99, X #$03 $F07F $70
353
zero in buffer inc buffer pointer
Anatomy of the 1541
ABACUS Software
F092 F094 F097 F09A F09C
A5 9D AD DO 4C
SO 9D 02 F9 02 03 SA D5
F09F FOAl FOA4
09 SO SD F9 02 60
ORA #$SO STA $02F9 RTS
FOA5 FOA6 FOA9 FOAB FOAC FOAE FOBl FOB3 FOB4 FOB5 FOB6 FOB7 FOBB FOBA FOBB FOBC FOBD FOBE FOC1 FOC3 FOC5 FOCS FOCA FOCB FOCC FOCE FODO
AS B9 FO 4S A9 99 A5 OA AA 6S OA OA 95
TAY LDA BEQ PHA LDA STA LDA ASL TAX PLA ASL ASL STA TYA ASL ASL TAY LDA STA LDA STA INC INY TYA AND BNE RTS
FODl FOD3 FOD4
A5 7F OA
9D 02 25 00 9D 02 F9
99
98
OA OA AB B9 Sl A9 99 F6 CS 9B 29 DO 60
AA
Al 02 99 00 Al 02 99 03 EE
LDA STA LDA BNE JMP
$SO $029D,X $02F9 $F09F $D5SA
track
'tlrite block set for BAM write
$029D,Y $FODO #$00 $029D,Y $F9 A
buffer number times 2
A A $99, X A A $02A1,Y ($99,X) #$00 $02Al,Y $99,X
write in buffer inc buffer pointer
#$03 $FOBE
LDA $7F ASL A TAX
drive number
354
ABACUS Software
FOD5 FOD7 FODA FODB FODE
A9 00 9D 9D 02 E8 9D 9D 02 60
Anatomy of the 1541
LDA #$00 STA $029D,X INX STA $029D,X RTS
****************************** FODF B5 A7 LDA $A7,X FOE1 CMP #$FF C9 FF FOE3 DO 25 BNE $F10A TXA FOE5 8A FOE6 48 PHA FOE7 20 8E D2 JSR $D28E FOEA AA TAX FOEB BPL $FOF2 10 05 FOED LDA #$70 A9 70 FOEF 20 C8 C1 JSR $C1C8 FOF2 STX $F9 86 F9 PLA FOF4 68 TAY FOF5 A8 TXA FOF6 8A ORA #$80 FOF7 09 80 STA $00A7,Y FOF9 99 A7 00 FOFC OA ASL A TAX FOFD AA FOFE LDA $FE85 AD 85 FE F101 STA $06,X 95 06 LDA #$00 F103 A9 00 F105 STA $07,X 95 07 F107 4C 86 D5 JMP $D586
F10A FlOC FlOE
29 OF 85 F9 60
AND #$OF STA $F9 RTS
******************************
F10F F111 Fl13 Fl15
A9 06 A6 7F DO 03 18
LDA #$06 LDX $7F BNE $Fl18 CLC
355
find free buffer found 70,
'no channel'
18, directory track save 0 as sector write block buffer number get buffer number for BAM drive number
ABACUS Software
Fl16 Fl18
69 07 60
Anatomy of the 1541
ADC #$07 RTS
****************************** Fl19 F11C F11D
20 OF F1 AA
60
JSR $F10F TAX RTS
****************************** F11E
20 3E DE
JSR $DE3E
F121 F123 F125 F127
A9 85 A9 OD
LDA STA LDA ORA
F12A F12D F12F F130
8D F9 02 A5 6F 48 20 11 FO
STA $02F9 LDA $6F PHA JSR $F011
F133 F134 F136
68 85 6F B1 6D
PLA STA $6F LDA ($ 6D) , Y
F138 F13A F13C F13F F141
DO A5 CD FO 90
BNE LDA CMF BEQ BCC
F143 F145 F147
E6 80 A5 80 CD D7 FE
INC $80 LDA $80 CMP $FED7
F14A
DO E1
BNE $F12D
F14C F14F F150
AE 85 FE CA 86 80
LDX $FE85 DEX STX $80
03 6F 01 F9 02
39 80 85 FE 19 1C
#$03 $6F #$01 $02F9
$F173 $80 $FE85 $F15A $F15F
356
gives 13 for drv 0 buffer # for BAM get buffer number
find and allocate free block get track and sector numbers counter set flag for BAM write save counter find BAM field for this track get counter back number of free blocks in track blocks still free? track 18, dir track? yes, 'disk full' smaller, then next lower track increment track # 36, highest track number plus one no, continue searching this trk 18, directory track decrement save as track #
Anatomy of the 1541
ABACUS Software
F152 F154 F156 F158
A9 85 C6 DO
00 81 6F D3
LDA STA DEC BNE
#$00 $81 $6F $F12D
F15A F15C F15F F161
A9 20 C6 DO
72 C8 C1 80 CA
LDA JSR DEC BNE
#$72 $C1C8 $80 $F12D
F163 F166 F167 F169 F16B F16D F16F
AE E8 86 A9 85 C6 DO
85 FE
LDX INX STX LDA STA DEC BNE
$FE85
F171
FO E7
BEQ $F15A
F173 F175 F176
AS 81 18 65 69
LDA $81 CLC ADC $69
F178 F17A F17C F17F F182 F185
85 AS 20 8D 8D C5
F187 F189 F18A F1BC
BO OC 38 AS 81 ED 4E 02
BCS $F195 SEC LDA $81 SBC $024E
F18F F191 F193
85 81 FO 02 C6 81
STA $81 BEQ $F195 DEC $81
80 00 81 6F BC
81 80 4B F2 4E 02 4D 02 81
STA LDA JSR STA STA CMP
$80 #$00 $81 $6F $F12D
begin with sect #0 decrement counter not yet zero, then continue 72, 'disk full' decrement track # not yet 0, continue in this track 18, directory track increment save as track # begin with sector 0 decrement counter not yet zero, then continue else 'disk full' sector number
$81 $80 $F24B $024E $024D $81
357
plus step width (10) as new number track number get max sector # and save greater than selected sector #? yes else sector number minus maximum sector number save as new sect # zero? else decrement sector # by 1
ABACUS Software
Anatomy of the 1541
F195
20 FA F1
JSR $F1FA
F198 F19A
FO 03 4C 90 EF
BEQ $F19D JMP $EF90
F19D F19F F1A1 F1A4 F1A6
A9 85 20 DO 4C
LDA STA JSR BNE JMP
00 81 FA F1 F4 F5 F1
#$00 $81 $F1FA $F19A $F1F5
****************************** F1A9 FlAB F1B1 F1B3 F1B4 F1B6 F1B8 F1BB F1BC F1BE FICO F1C2
A9 OD A5 48 49 85 AD 38 E5 85
01 F9 02 86
FO 07
LDA ORA LDA PHA LDA STA LDA SEC SBC STA BCC BEQ
F1C4
20 11 FO
JSR $F011
F1C7
B1 6D
LDA ($ 6D) , Y
F1C9 F1CB F1CE F1CF F1D1 F1D3 F1D5
DO AD 18 65 85 E6 CD
BNE LDA CLC ADC STA INC CMP
F1D8 F1DA
90 05 A9 67
01 86 85 FE 86 80
90 09
1B 85 FE 86 80 86 D7 FE
check BAM, find free sector not found? allocate block in BAM sector zero find free sector found? no, 'dir sector' find free sector and allocate
#$01 $02F9 $86 #$01 $86 $FE85
track counter
$86 $80 $FICB $F1CB
minus counter save as track # result no, 20, 'read error' , header block not found byte ready?
Anatomy of the 1541
ABACUS Software
LDA $lCOl
F3CB
AD 01 lC
F3CE F3DO F3Dl F3D3 F3D5
95 E8 EO DO 20
F3D8 F3DA F3DC
AO 04 A9 00 59 16 00
LDY #$04 LDA #$00 EOR $0016,Y
F3DF F3EO F3E2 F3E4
88 10 FA C9 00 DO 38
DEY BPL $F3DC CMP #$00 BNE $F41E
F3E6 F3E8 F3EA F3EC F3EE
A6 A4 95 A5 C9
3E 18 22 45 30
LDX LDA STA LDA CMP
$3E $18 $22,X $45 #$30
F3FO F3F2 F3F4 F3F5 F3F6 F3F9 F3FB F3FD F400 F402
FO A5 OA A8 B9 C5 DO B9 C5 DO
lE 3E
BEQ LDA ASL TAY LDA CMP BNE LDA CMP BNE
$F410 $3E A
F404
4C 23 F4
JMP $F423
F407
C6 4B
DEC $4B
F409 F40B
DO BO A9 02
BNE $F3BB LDA #$02
25 07 F3 97 F4
12 00 16 lE 13 00 17 17
STA INX CPX BNE JSR
$25,X #$07 $F3C8 $F497
$0012,Y $16 $F41B $0013,Y $17 $F41B
367
data byte from disk (block header) save 7 bytes continue reading decode GCR header bytes 4 bytes plus parity form checksum for header parity ok? 27, 'read error', parity error in block header drive number track # of header use as actual trk # command code code for 'preserve header'? preserve header drive number times 2 compare with 1D1 not equal? compare with 1D2 , then 29, 'disk id mismatch' decrement counter for attempts and try again else
ABACUS Software
F40D
20 69 F9
Anatomy of the 1541
JSR $F969
****************************** F410 F412 F414 F416 F418 F41A F41B
A5 85 A5 85 A9 2C A9
OB
LDA $16 STA $12 LDA $17 STA $13 LDA #$01 .BYTE $2C LDA #$OB
F41D F41E F420
2C A9 09 4C 69 F9
.BYTE $2C LDA #$09 JMP $F969
16 12 17 13 01
20, 'read error', block header not found preserve block header IDI and ID2 preserve ok 29, 'disk id mismatch' 27, 'read error' done
******************************
job optimization
F423 F425 F427 F429 F42A F42C
A9 85 AS 18 69 C5
last sector
F42E F430 F432
90 02 E5 43 85 4D
BCC $F432 SBC $43 STA $4D
F434 F436 F438 F43A
A2 86 A2 20
05 3F FF 93 F3
LDX STX LDX JSR
#$05 $3F #$FF $F393
F43D F43F F441 F443 F445 F447
10 85 29 C5 DO AO
44 44 01 3E 3C 00
BPL STA AND CMP BNE LDY
$F483 $44 #$01 $3E $F483 #$00
7F 4C 19 02 43
LDA STA LDA CLC ADC CMP
#$7F $4C $19 #$02 $43
368
plus 2 compare with max sector # smaller? else wrap around store as valid sector buffer number set buffer ptr for disk controller isolate drive # motor running? no
Anatomy or the 1541
ABACUS Software
F449 F44B F44D F44F F451 F453 F455 F457 F458 F45A F45C F45E F45F F461 F463 F465 F466 F468 F46A F46B F460 F46F F471 F473 F475 F477 F478 F47A
B1 C5 DO AS C9 FO AO 38 B1 E5 10 18 65 C4 BO 48 A5 FO 68 C9 90 C9 BO 85 A5
32 40 34 45 60 OC 01
F47C F47E F47F F481 F483 F485 F487 F488 F48A
DO 68 C9 90 C6 10 8A 10 4C
F48D F48F
86 3F 20 93 F3
32 40 03 43 4C 1E 45 14 09 14 OC 10 4C 3F
AA
69 03 85 31 05 06 FO 3F B3 03 9C F9
LOA CMP BNE LOA CMP BEQ LOY SEC LOA SBC BPL CLC AOC CMP BCS PHA LOA BEQ PLA CMP BCC CMP BCS STA LOA TAX AOC STA
($32),Y $40 $F483 $45 #$60 $F461 #$01
BNE PLA CMP BCC DEC BPL TXA BPL JMP
$F483
desired track same as last trk? no command code position head?
($32),Y $40 $F461 $43 $4C $F483 $45 $F47E #$09 $F483 #$OC $F483 $4C $3F #$03 $31
command code read? sector difference less than 9? more than 12 store buffer number plus 3 equals pointer in buffer
#$06 $F473 $3F $F43A
next buffer
$F480 $F99C
to job loop
STX $3F JSR $F393 369
buffer number get buffer number
ABACUS Software
Anatomy of the 1541
F492 F494
AS 45 4C CA F4
LOA $45 JMP $F4CA
F497 F499 F49A F49C F490 F49F F4A1 F4A3 F4A5 F4A7 F4A9
AS 48 AS 48 A9 85 A9 85 A9 85 20
30
$30
24 30 00 31 00 34 E6 F7
LOA PLA LOA PHA LOA STA LOA STA LOA STA JSR
F4AC F4AE F4BO F4B2 F4B4 F4B6 F4B8
AS 85 AS 85 AS 85 20
55 18 54 19 53 1A E6 F7
LOA STA LOA STA LOA STA JSR
$55 $18 $54 $19 $53 $lA $F7E6
F4BB F4BO F4BF F4C1 F4C3 F4C4 F4C6 F4C7 F4C9
AS 85 AS 85 68 85 68 85 60
52 17 53 16
LDA STA LDA STA PLA STA PLA STA RTS
$52 $17 $53 $16
31
31 30
save ptr $30/$31 $31 #$24 $30 #$00 $31 #$00 $34 $F7E6
C9 00 FO 03 4C 6E F5
ptr $30/$31 to $24
decode 5 GCR bytes into 4 normal bytes fourth byte track third byte sector second byte parity decode 5 GCR bytes into 4 normal bytes first byte 102 second byte 101
$31 get ptr $30/$31 $30
****************************** F4CA F4CC F4CE
command code continue checking
CMF #$00 BEQ $F401 JMP $F56E
370
test command code further cmd code for read? yes continue checking command code
Anatomy of the 1541
ABACUS Software
****************************** JSR $F50A 20 OA F5 F4Dl
$F4D4
read find data byte
sector beginning of block ready?
F4D4 F4D6 F4D7 F4DA F4DC F4DD F4DF F4El F4E3 F4E4 F4E7 F4EA F4EB F4ED
50 B8 AD 91 C8 DO AO 50 B8
01 lC 99 00 01 C8 DO F4 20 EO F8
BVC CLV LDA STA INY BNE LDY BVC CLV LDA STA INY BNE JSR
F4FO
AS 38
LDA $38
F4F2
C5 47
CMP $47
F4F4 F4F6
FO 05 A9 04
BEQ $F4FB LDA #$04
F4F8
4C 69 F9
JMP $F969
F4FB
20 E9 F5
JSR $F5E9
F4FE F500 F502
C5 3A FO 03 A9 05
CMP $3A BEQ $F505 LDA #$05
calculate parity of data block match? yes 23, 'read error', parity error in data block
F504 F505 F507
2C A9 01 4C 69 F9
.BYTE $2C LDA #$01 JMP $F969
ok prepare error msg
FE 01 lC 30 F5 BA FE
AD
$lCOI ($30),Y $F4D4 #$BA $F4E1
byte ready?
$lCOI $0100,Y
read bytes from $lBA to $lFF
$F4E1 $F8EO
******************************
F50A
20 10 F5
get data byte and write in buffer 256 times
JSR $F510 371
calculate data from group code data block marker r>ad equal 7, start of data block? yes 22, 'read error', data blk not found error termination
find start of data block read block header
ABACUS Software
F50D
4C 56 F5
Anatomy of the 1541
JMP $F556
****************************** F510 A5 3D LDA $3D F512 OA ASL A F513 AA TAX B5 12 LDA $12,X F514 STA $16 F516 85 16 F518 B5 13 LDA $13,x F51A STA $17 85 17 F51C AO 00 LDY #$00 F51E Bl 32 LDA ($32),Y F520 STA $18 85 18 F522 INY C8 F523 Bl 32 LDA ($32),Y F525 F527
85 19 A9 00
STA $19 LDA #$00
F529 F52B F52D F52F F531 F533
45 45 45 45 85 20
16 17 18 19 lA 34 F9
EOR EOR EOR EOR STA JSR
$16 $17 $18 $19 $lA $F934
F536 F538 F53B F53D F53F F540
A2 20 AO 50 B8
5A 56 F5 00 FE
#$5A $F556 #$00 $F35D
AD 01 lC
LDX JSR LDY BVC CLV LDA
F543
D9 24 00
CMP $0024,Y
F546
DO 06
BNE $F54E
F548 F549 F54B F54D
C8 CO 08 DO FO 60
INY CPY #$08 BNE $F53D RTS
$lCOI
372
wait for next SYNC read block header drive number IDI save ID2 save get track and sector numbers from buffer calculate parity for block header IDI ID2 track sector and save as parity convert block header to GCR code 90 attempts wait for SYNC byte ready? read data from block header compare with saved data not the same, try again 8 bytes read? no
Anatomy of the 1541
ABACUS Software
F54E F54F F551 F553
CA DO E7 A9 02 4C 69 F9
DEX BNE $F538 LDA #$02 JMP $F969
****************************** LDA #$DO A9 DO F556 STA $1805 8D 05 18 F558 LDA #$03 F55B A9 03 F55D F560
2C 05 18 10 F1
F562 F565 F567 F56A F56B F56D
2C 30 AD B8 AO 60
00 1C F6 10 1C 00
BIT $1805 BPL $F553 BIT BMI LDA CLV LDY RTS
$lCOO $FS5D $lC01
C9 10 FO 03 4C 91 F6
20, 'read error', block header not found wait for SYNC 208 start timer error code for SYNC not found time diff>20ms, then 21, 'read error' SYNC signal not yet found? read byte
#$00
****************************** F56E F570 F572
decrement C()t~ . ·r not yet zero?
eMP #$10 BEQ $F575 JMP $F691
****************************** F575
20 E9 F5
JSR $FSE9
FS7B F57A FS7D
8S 3A AD 00 1C 29 10
STA $3A LDA $lCOO AND #$10
FS7F FS81 F583
DO OS A9 08 4C 69 F9
BNE $FS86 LDA #$08 JMP $F969
373
test command code further cmd code for write yes continue checking command code write data block to disk calculate parity for buffer and save read port B isolate bit for 'write protect' not set, ok 26, on'
'write protect
ABACUS Software
SF F7 10 F5 09 FE
Anatomy of the 1541
F5S6 F5S9 F5SC F58E F590 F591
20 20 A2 50 BS CA
F592 F594 F596
00 FA A9 FF SO 03 lC
BNE $F5SE LOA #$FF STA $lC03
F599 F59C F59E
AO OC lC 29 iF 09 CO
LOA $lCOC ANO #$lF ORA #$CO
F5AO F5A3 F5A5 F5A7
SO A9 A2 SO
STA LOA LOX STA
F5AA F5AB F5AO F5AE F:lAF F5Bl F5B3
BS 50 B8 CA 00 AO B9
F5B6 F5BS F5B9 F5BC F5BO F5BF
50 BS 80 CS 00 Bl
F5Cl F5C3 F'5C4 F5C7 F5CS
50 FE B8 SO 01 lC CS 00 F5
OC lC FF 05 01 lC FE FA BB 00 01 FE 01 lC F4 30
JSR JSR LOX BVC CLV OEX
CLV BVC CLV OEX BNE LOY LOA BVC CLV STA INY BNE LOA
$F7SF $F510 #$09 $F5SE
calc. group code find block header byte ready? 9 bytes GAP after skipping block header
$lCOC #$FF #$05 $lCOl $F5AB $F5AB #$BB $0100,Y
port A (write/read head) to output change PCR to output, CB2 10 SYNC write SYNC to disk 5 times byte ready?
bytes $lBB to $lFF to disk
$F5B6 $lCOl $F5B3 ($30),Y
BVC $F5Cl CLV STA $lCOl INY BNE $F5BF 374
write to disk data buffer 256 bytes GCR code write to disk
----
---------------------------------
ABACUS Software
Anatomy of the 1541
FSCA FSCC FSCF
SO FE AD OC 1C 09 EO
BVC $FSCA LDA $lCOC ORA #$EO
FSD1 FSD4 FSD6
8D OC 1C A9 00 8D 03 1C
STA $lCOC LDA #$00 LDA $lC03
FSD9
20 F2 FS
JSR $FSF2
FSDC FSDE FSE1
A4 3F B9 00 00 49 30
LDY $3F LDA $OOOO,Y EOR #$30
FSE3 FSE6
99 00 00 4C B1 F3
STA $OOOO,y JMP $F3B1
****************************** FSE9 F5EB F5EC FSEE F5EF FSF1
A9 00 AS 51 30 C8 DO FB 60
LDA #$00 TAY EOR ($30),Y INY BNE $FSEC RTS
****************************** F5F2 F5F4 F5F6 F5F8 F5FA F5FC F5FE F600
A9 85 85 85 A5 85 A9 8S
F602 F604 F606
85 2F A9 BB 8S 34
00 2E 30 4F 31 4E 01 31
LDA STA STA STA LDA STA LDA STA
#$00 $2E $30 $4F $31 $4E #$01 $31
STA $2F LDA #$BB STA $34 375
byte ready? PCR to input again, CB2 hi port A (read/write head) to input convert GCR data to normal data buffer number convert cmd code 'write' to 'verify' and read block header calculate parity for data buffer generate parity
convert GCR data to normal data
initialize ptr
set pointer to buffer $lBB
ABACUS Software
Anatomy of the 1541
F608 F60A
85 36 20 E6 F7
STA $36 JSR $F7E6
F60D F60F
A5 52 85 38
LDA $52 STA $38
F611 F613 F615
A4 36 A5 53 91 2E
LDY $36 LDA $53 STA ($2E),Y
F617 F618 F61A F61C F61D F61F
C8 A5 91 C8 A5 91
INY LDA STA INY LDA STA
F621 F622 F624
C8 84 36 20 E6 F7
INY STY $36 JSR $F7E6
F627 F629 F62B F62D F62E F630 F632 F633
A4 36 A5 52 91 2E C8 A5 53 91 2E C8 FO OE
LLlY LDA STA INY LDA STA INY BEQ
$36 $52 ($2E),Y
1st decoded byte in buffer
$53 ($2E),Y
2nd decoded byte in buffer
$F643
F635 F637 F639 F63A F63C F63E F63F
A5 91 C8 A5 91 C8 84
LDA STA INY LDA STA INY STY
$54 ($2E),Y
no longer in overflow buffer? 3rd decoded byte in buffer
$55 ($2E),Y
4th decoded byte in buffer
F641
DO El
BNE $F624
F643
A5 54
LDA $54
54 2E 55 2E
54 2E 55 2E 36
convert 5 GCR bytes to 4 normal first byte save as data block marker 2nd byte save as first data byte
$54 ($2E),y
third byte as 2nd data byte
$55 ($2E),Y
fourth byte save as 3rd data byte
$36
376
store buffer ptr convert 5 GCR bytes to 4 normal bytes
inc buffer pointer and save still in overflow buffer $1BB to $lFF? 3rd decoded byte
ABACUS Software
Anatomy of the 1541
F645 F647 F648 F64A F64C F64D F64F
91 C8 A5 91 C8 84 20
30
F652 F654 F656 F658 F659 F65B F65D F65E F660 F662 F663 F665 F667 F668 F66A F66C F66E F670 F672 F674 F676 F678
A4 A5 91 C8 A5 91 C8 A5 91 C8 A5 91 C8 84 CO 90 A9 85 A5 85 AO B1
36 52 30
F67A
91 2E
STA ($2E),Y
F67C F67D F67F F681 F683 F685
88 DO B1 91 A2 BD
DEY BNE LDA STA LDX LDA
55 30 36 E6 F7
53 30 54 30 55 30 36 BB E1 45 2E 31 2F BA 30
F9 30 2E BB 00 01
STA INY LDA STA INY STY JSR LDY LDA STA INY LDA STA INY LDSTA INY LDA STA INY STY CPY BCC LDA STA LDA STA LDY LDA
($30),Y
in buffer
$55 ($30),Y
4th decoded byte in buffer
$36 $F7E6 $36 $52 ($30),Y
save buffer ptr convert 5 GCR bytes to 4 normal bytes load buffer ptr 1st decoded byte in buffer
$53 ($30),Y
2nd decoded byte in buffer
$54 ($30),Y
3rd decoded byte in buffer
$55 ($30),Y
4th decoded byte in buffer
$36 #$BB $F64F #$45 $2E $31 $2F #$BA ($30),Y
save buffer ptr all bytes decoded? not yet, continue 69 bytes
$F678 ($30),Y ($2E),Y #$BB $0100,X
377
copy the bytes in the lower part of the data buffer to the upper part
copy the bytes from the overflow buffer
Anatomy of the 1541
ABACUS Software
F688
91 30
STA ($30),Y
F68A F68B F68C F68E F690
C8 E8 DO F7 86 SO 60
INY INX BNE $F68S STX $SO RTS
****************************** F691
C9 20
CMP #$20
F693 F69S
FO 03 4C CA F6
BEQ $F698 JMP $F6CA
****************************** F698
20 E9 FS
JSR $FSE9
F69B F69D F6AO
8S 3A 20 8F F7 20 OA FS
STA $3A JSR $F78F JSR $FSOA
F6A3 F6AS F6A8 F6AA F6AB
AO B9 SO B8 4D
F6AE
DO 15
BNE $F6CS
F6BO F6Bl F6B3 F6BS F6B7 F6B8
C8 DO Bl SO B8 4D
INY BNE LDA BVC CLV EOR
BB 00 01 FE 01 lC
F2 30 FE 01 lC
LDY LDA BVC CLV EOR
#$BB $0100,Y $F6A8 $lCOI
$F6AS ($30),Y $F6BS $lCOI
378
to the lower part of the data buffer
clear GCR flag continue to test command code command code for 'verify'? yes continue checking command code compare written data with data on disk calculate parity for data buffer and save calculate GCR code find start of data block ptr to GCR buffer data from buffer byte ready? compare with data from disk not equal, then error data from buffer compare with data from disk
Anatomy of the 1541
ABACUS Software
F6BB
DO 08
BNE $F6C5
F6BD F6BE F6CO F6C2
C8 CO FD DO F1 4C 18 F4
INY CPY #$FD BNE $F6B3 JMP $F418
F6C5 F6C7
A9 07 4C 69 F9
LDA #$07 JMP $F969
******************************
F6CA F6CD
20 10 F5 4C 18 F4
JSR $F510 JMP $F418
******************************
LDA #$00 STA $57
F6DO F6D2
A9 00 85 57
F6D4 F6D6 F6D8 F6DA F6DC F6DD
85 A4 A5 29 4A 4A
F6DE F6DF F6EO
4A 4A AA
LSR A LSR A TAX
F6E1 F6E4 F6E5
BD 7F F7 OA OA
LDA $F77F,X ASL A ASL A
F6E6 F6E7 F6E9
OA 85 56 A5 52
ASL A STA $56 LDA $52
5A 34 52 FO
STA LDY LDA AND LSR LSR
$5A $34 $52 #$FO A A
not equal, then 25, 'write error'
error-free termination 25, 'write error' , no match command code for find sector read block header done convert 4 bytes ($52-$55) to 5 GCR bytes ($56-$5A) erase destination area first data byte isolate hi-nibble and rotate to lower nibble as index in GCR code table get GCR code shift bit pattern to pos 3-7 and save get first data byte
379
ABACUS Software
Anatomy of the 1541
F6EB
29 OF
AND #$OF
F6ED
AA
TAX
F6EE F6F1 F6F2
BD 7F F7 6A 66 57
LDA $F77F,X ROR A ROR $57
F6F4 F6F5 F6F7
6A 66 57 29 07
ROR A ROR $57 AND #$07
F6F9 F6FB F6FD F6FE F700
05 91 C8 AS 29
ORA STA INY LDA AND
F702 F703 F704
4A 4A 4A
LSR A LSR A LSR A
F705
4A
F706
AA
LSR A TAX
F707 F70A F70B
BD 7F F7 OA 05 57
LDA $F77F,X ASL A ORA $57
F70D F70F F711 F713
85 57 A5 53 29 OF AA
STA $57 LDA $53 AND #$OF TAX
F714 F717 F718
BD 7F F7 2A 2A
LDA $F77F,X ROL A ROL A
F719 F71A
2A 2A
ROL A ROL A
56 30 53 FO
$56 ($30),Y $53 #$FO
isolate lower nibble as index in GCR code table bring in 2nd destination byte and in lowest 3 bits second data byte in buffer increment buffer isolate upper nibble shift to upper nibble
380
as index in GCR code table get GCR code bring to proper pos in 2nd dest byte 3rd data byte lower nibble as index in GCR table get GCR code shift to required bit position
ABACUS Software
Anatomy of the 1541
F71B
85 58
STA $58
F71D F71E F720 F722 F724 F725 F727 F729 F72A F72B
2A 29 05 91 C8 AS 29 4A 4A 4A
ROL AND ORA STA INY LDA AND LSR LSR LSR
F72C F72D
AA
01 57 30 54 FO
and copy to dest byte
A #$01 $57 ($30),Y $54 #$FO A A A
LSR A TAX
4A 7F F7
$F77F,X
F72E F731 F732 F733 F735 F737 F738 F739 F73B F73D F73F F741
BD 18 6A 05 91 C8 6A 29 85 AS 29 AA
LDA CLC ROR ORA STA INY ROR AND STA LDA AND TAX
F742 F745 F746
BD 7F F7 OA OA
LDA $F77F,X ASL A ASL A
F747 F749 F74B F74D F74F F751 F752
29 05 85 AS 29 4A 4A
58 30 80 59 54 OF
7C 59 59 55 FO
AND ORA STA LDA AND LSR LSR
A $58 ($30),Y A #$80 $59 $54 #$OF
#$7C $59 $59 $55 #$FO A A
381
one bit left in 2nd dest byte in buffer inc buffer ptr 3rd data byte isolate hi-nibble shift to lower nibble as index in GCR code table get GCR code
in buffer inc buffer pointer copy to dest byte 3rd data byte lower nibble as index in GCR table get GCR code shift bits to proper pos copy to dest byte 4th data byte isolate hi-nibble shift to lower nibble
ABACUS Software
F753 F754 F755
LSR A LSR A TAX
4A 4A AA
F756 F759 F75A F75C F750 F75F F760 F762 F764 F766 F768 F769 F76B F760 F76F F771 F773
BO 6A 66 6A 66 6A 66 29 05 91 C8 00 A5 85 A5 29
F774 F777 F779 F77B F77C F77E
BO 05 91 C8 84 60
Anatomy of the 1541
7F F7 5A 5A 5A 03 59 30 04 2F 31 55 OF
AA
7F F7 5A 30 34
as index in GCR code table
LOA ROR ROR ROR ROR ROR ROR ANO ORA STA INY BNE LOA STA LOA ANO TAX
$F77F,X A $5A A $5A A $5A #$03 $59 ($30),Y
LOA ORA STA INY STY RTS
$F77F,X $5A ($30),Y
$F76F $2F $31 $55 #$OF
$34
shift bits
copy to dest byte in buffer inc buffer pointer
4th data byte isolate lwr nibble as index in GCR code table get GCR code in buffer inc buffer pointer and save
****************************** F77F OA OB 12 13 OE OF 16 17 F787 09 19 1A 1B 00 10 1E 15
GCR code table
******************************
convert 260 bytes to 325 bytes group code
F78F F791 F793 F795 F797
A9 85 85 85 A9
00 30 2E 36 BB
LOA STA STA STA LOA
#$00 $30 $2E $36 #$BB
382
initialize pointer
Anatomy of the 1541
ABACUS Software
F799 F79B
85 34 85 50
STA $34 STA $50
F79D F79F F7Al F7A3 F7A5
A5 85 A9 85 A5
LDA STA LDA STA LDA
F7A7
85 52
STA $52
F7A9 F7AB F7AD F7AF F7BO F7B2 F7B4 F7B5 F7B7 F7B9 F7BA F7BC
A4 Bl 85 C8 Bl 85 C8 Bl 85 C8 84 20
36 2E 53
LDY LDA STA INY LDA STA INY LDA STA INY STY JSR
$36 ($2E),Y $53
data block marker (7 ) bring in work storage load buffer ptr 1st data byte bring in work storg
($2E),Y $54
2nd data byte bring in work storg
($2E),Y $55
3rd data byte bring in work storg
$36 $F6DO
F7BF F7Cl F7C3 F7C5 F7C6 F7C8 F7CA F7CC F7CD F7CF F7Dl F7D2 F7D4 F7D6 F7D7 F7D9 F7DB
A4 Bl 85 C8 FO Bl 85 C8 Bl 85 C8 Bl 85 C8 DO A5 85
36 2E 52
LDY LDA STA INY BEQ LDA STA INY LDA STA INY LDA STA INY BNE LDA STA
$36 ($2E),Y $52
store buffer ptr convert 4 bytes to 5 bytes GCR code load buffer ptr first byte bring in work storg
$F7D9 ($2E),Y $53
2nd byte bring in work storg
($2E),Y $54
3rd byte bring in work storg
($2E),Y $55
4th byte bring in work storg
$F7BA $3A $53
convert bytes checksum in work storg
31 2F 01 31 47
2E 54 2E 55 36 DO F6
11 2E 53 2E 54 2E 55 El 3A 53
set pointer to buffer $lBB
$31 $2F #$01 $31 $47
383
ABACUS Software
Anatomy of the 1541
F7DD F7DF
A9 00 85 54
LDA #$00 STA $54
F7E1 F7E3
85 55 4C DO F6
STA $55 JMP $F6DO
****************************** F7E6 F7E8 F7EA F7EC F7ED F7EE F7EF F7Fl F7F3
A4 B1 29 4A 4A 4A 85 Bl 29
34 30 F8
56 30 07
LDY LDA AND LSR LSR LSR STA LDA AND
$34 ($30),Y #$F8 A A A $56 ($30),Y #$07
F7F5 F7F6 F7F7 F7F9 F7FA F7FC
OA OA 85 57 C8 DO 06 A5 4E
ASL ASL STA INY BNE LDA
A A $57
F7FE F800 F802 F804
85 A4 Bl 29
STA LDY LDA AND
$31 $4F ($30),Y #$CO
F806 F807
2A 2A
ROL A ROL A
F808 F809
2A 05 57
ROL A ORA $57
F80B
85 57
STA $57
F80D
Bl 30
LDA ($30),Y
31 4F 30 CO
2 zero bytes in work storage convert 4 bytes to 5 bytes GCR code convert 5 GCR bytes to 4 normal bytes get GCR byte isolate top 5 bits
and save get the lowest 3 bits of the 1st GCR byte shift 2 bits up and save inc buffer pointer
$F802 $4E
if zero then change buffers load 2nd GCR byte and isolate the top two bits bring in bit position 0-1
384
combine with the 2nd isolated GCR pattern and save load 2nd GCR byte
Anatomy of the 1541
ABACUS Software
AND #$3E LSR A
isolate bits 1-5 shift to bit pos 1-4 and save load 2nd GCR byte isolate bit 0
F80F F811
29 3E 4A
F812 F814 F816 F818 F819 F81A F81B F81C F81E F81F F821 F823 F824 F825
85 B1 29 OA OA OA OA 85 C8 B1 29 4A 4A 4A
F826 F827
4A 05 59
LSR A ORA $59
F829 F82B F82D F82F
85 59 B1 30 29 OF OA
STA LDA AND ASL
$59 ($30), Y #$OF A
F830 F832 F833 F835 F837 F838 F839 F83A F83C
85 C8 B1 29 18 2A 2A 29 05
5A
$5A ($30),Y #$80
load 4th GCR byte isolate bit 7
01 5A
STA INY LDA AND CLC ROL ROL AND ORA
load 3rd GCR byte isolate bits 0-3 shift to bit pot 1-4 and store
A A #$01 $5A
F83E F840 F842 F844
85 5A B1 30 29 7C 4A
STA LDA AND LSR
$5A ($30),Y #$7C A
58 30 01
59 30 FO
30 80
STA LDA AND ASL ASL ASL ASL STA INY LDA AND LSR LSR LSR
$58 ($30),Y #$01 A A A A $59 ($30),Y #$FO A A A
shift in bit pos 4 and save load 3rd GCR byte isolate bits 4-7 shift to bit pos 0-4 combine with previous bit and store
385
shift to bit pos 0 isolate bit 0 combine with previous part pattern and store load 4th GCR byte isolate bits 2-6
ABACUS Software
Anatomy of the 1541
F845
4A
LSR A
F846 F848 F84A F84C F84D
85 5B Bl 30 29 03 OA OA
STA LDA AND ASL ASL
$5B ($30),Y #$03 A A
F84E F84F F851 F852 F854
OA 85 5C C8 DO 06 A5 4E
ASL STA INY BNE LDA
A $5C
F856 F858 F85A F85C F85E F85F F860
85 A4 Bl 29 2A 2A 2A
STA LDY LDA AND ROL ROL ROL
$31 $4F ($30), Y #$EO A A A
F861 F862
2A 05 5C
ROL A ORA $5C
F864 F866 F868 F86A F86C F86D F86F
85 Bl 29 85 C8 84 A6
STA LDA AND STA INY STY LDX
F871
BD AO F8
LDA $F8AO,X
F874
A6 57
LDX $57
F876
ID CO F8
ORA $F8CO,X
F879
85 52
STA $52
31 4F 30 EO
5C 30 IF 5D 34 56
$F85A $4E
$5C ($30),Y #$lF $5D $34 $56
386
shift to bit pos 0-4 and store load 4th GCR byte isolate bits 0-1 shift to bit pos 2-4 and store increment pointer if zero, change buffers load 5th GCR byte isolate bits 5-7 bring in bit pos 0-2 combine with last pattern and store load 5th GCR byte isolate bits 0-4 and store store buffer ptr load first GCR pattern get binary code for hi nibble load 2nd GCR pattern combine with binary code for 10 nibble store as first result byte
Anatomy of the 1541
ABACUS Software
F87B
A6 58
LDX $58
F87D
BD AO F8
LDA $F8AO,X
F880
A6 59
LDX $59
F882
1D CO F8
ORA $F8CO,X
F885
85 53
STA $53
F887
A6 5A
LDX $5A
F889
BD AO F8
LDA $F8AO,X
F88C
A6 5B
LDX $5B
F88E
1D CO F8
ORA $F8CO,X
F891
85 54
STA $54
F893
A6 5C
LDX $5C
F895
BD AO F8
LDA $F8AO,X
F898
A6 5D
LDX $5D
F89A
1D CO F8
ORA $F8CO,X
F89D
85 55
STA $55
F89F
60
RTS
****************************** F8AO F8A8 F8BO F8B8
FF FF FF FF
FF 80 FF 90
FF 00 20 AO
FF 10 30 BO
FF FF FF FF
FF CO FO DO
FF 40 60 EO
FF 50 70 FF
387
load 3rd GCR pattern get binary code for hi nibble load 4th GCR pattern combine with binary code for 10 nibble store as 2nd result byte load 5th GCR pattern get binary code for hi nibble load 6th GCR pattern combine with binary code for 10 nibble store as 3rd result byte load 7th GCR pattern get binary code for hi nibble load 8th GCR pattern combine with binary code for 10 nibble store as 4th result byte conversion table GCR code to binary, hi byte $FF means invalid
Anatomy of the 1541
ABACUS Software
****************************** F8CO F8C8 F8DO F8D8
FF FF FF FF
FF 08 FF 09
FF 00 02 OA
FF 01 03 OB
FF FF FF FF
FF OC OF OD
FF 04 06 OE
FF 05 07 FF
****************************** LDA #$00 F8EO A9 00 F8E2 STA $34 85 34 F8E4 STA $2E 85 2E F8E6 STA $36 85 36 LDA #$01 F8E8 A9 01 F8EA STA $4E 85 4E BA 4F 31 2F E6 F7
A9 85 A5 85 20
F8F7 F8F9
A5 52 85 38
LDA $52 STA $38
F8FB F8FD F8FF F901 F902 F904 F906 F907 F909 F90B F90C F90E
A4 A5 91 C8 A5 91 C8 A5 91 C8 84 20
LDY LDA STA INY LDA STA INY LDA STA INY STY JSR
F911 F913 F915
A4 36 A5 52 91 2E
36 53 2E 54 2E 55 2E 36 E6 F7
LDA STA LDA STA JSR
#$BA $4F $31 $2F $F7E6
F8EC F8EE F8FO F8F2 F8F4
conversion table GCR code to binary, 10 byte $FF means invalid
decode 69 GCR bytes
pointer to overflow buffer $lBA
$36 $53 ($2E),Y
decode 5 GCR bytes to $52-$55 1st decoded byte as block header marker load buffer ptr 2nd decoded byte in data buffer
$54 ($2E) ,Y
3rd decoded byte in data buffer
$55 ($2E),Y
4th decoded byte in data buffer
$36 $F7E6
store buffer ptr decode 5 GCR bytes to $52-$55 load buffer ptr 1st decoded byte in data buffer
LDY $36 LDA $52 STA ($2E),Y
388
Anatomy of the 1541
ABACUS Software
F917 F918
C8 FO 11
F91A F91C F91E F91F F921 F923 F924 F926 F928 F929 F92B F92D F92F F931 F933
A5 91 C8 A5 91 C8 A5 91 C8 DO A5 85 A5 85 60
53 2E 54 2E 55 2E E1 53 3A 2F 31
INY BEQ $F92B LDA STA INY LDA STA INY LDA STA INY BNE LDA STA LDA STA RTS
$53 ($2E),Y
all bytes from overflow buffer decoded? 2nd decoded byte in data buffer
$54 ($2E),Y
3rd decoded byte in data buffer
$55 ($2E),Y
4th decoded byte in data buffer
$F90C $53 $3A $2F $31
****************************** 31 2F 00 31 24
F934 F936 F938 F93A F93C
A5 85 A9 85 A9
F93E F940
85 34 A5 39
F942 F944 F946 F948 F94A F94C F94E F950
85 A5 85 A5 85 A5 85 20
F953
A5 17
52 1A 53 19 54 18 55 DO F6
LDA STA LDA STA LDA
$31 $2F #$00 $31 #$24
STA $34 LDA $39 STA LDA STA LDA STA LDA STA JSR
$52 $lA $53 $19 $54 $18 $55 $F6DO
LDA $17
389
2nd data byte store as parity load buffer ptr convert block header to GCR code
ptr to buffer for GCR data constant for data header (8) in work storage parity in work storage sector in work storage track in work storage convert 4 bytes to 5 GCR bytes ID2
ABACUS Software
F955 F957 F959 F95B F95D F95F F961
85 A5 85 A9 85 85 20
F964 F966 F968
A5 2F 85 31 60
52 16 53 00 54 55 DO F6
Anatomy of the 1541
STA LDA STA LDA STA STA JSR
$52 $16 $53 #$00 $54 $55 $F6DO
in work storage ID1 in work storage 2 zero bytes in work storage convert 4 bytes to 5 GCR bytes
LDA $2F STA $31 RTS
****************************** F969 F96B
A4 3F 99 00 00
LDY $3F STA $OOOO,Y
F96E
A5 50
LDA $50
F970 F972
FO 03 20 F2 F5
BEQ $F975 JSR $F5F2
F975 F978 F97A F97B
20 8F F9 A6 49 9A 4C BE F2
JSR $F98F LDX $49 TXS JMP $F2BE
error entry disk controller buffer number error code in command register data still in GCR format? no decode GCR data again reset motor flags get stack ptr back to main loop disk controller
****************************** F97E A9 AO LDA #$AO F980 85 20 STA $20 F982 AD 00 1C LDA $lCOO F985 09 04 ORA #$04 F987 8D 00 1C STA $lCOO F98A A9 3C LDA #$3C F98C 85 48 STA $48 F98E 60 RTS
turn drive motor on
****************************** F98F A6 3E LDX $3E F991 A5 20 LDA $20
turn drv motor off motor flag drive status
390
turn drive motor on motor on drive status
60
Anatomy of the 1541
ABACUS Software
F993 F995 F997 F999 F99B
09 85 A9 85 60
10 20 FF 48
ORA STA LDA STA RTS
set bit 4
#$10 $20 #$FF $48
****************************** 07 1C 05 1C 00 1C 10 1E
LDA STA LDA AND CMP
$lC07 $lC05 $lCOO #$10 $lE
F99C F99F F9A2 F9A5 F9A7
AD 8D AD 29 C5
F9A9
85 1E
STA $lE
F9AB F9AD F9AF
FO 04 A9 01 85 1C
BEQ $F9B1 LDA #$01 STA $lC
F9B1
AD FE 02
LDA $02FE
F9B4 F9B6 F9BB F9BA F9BC F9BF F9C1 F9C3 F9C5 F9C8
FO C9 DO A9 8D FO 85 A9 8D 4C
15 02 07 00 FE 02 OA 4A 02 FE 02 2E FA
BEQ CMP BNE LDA STA BEQ STA LDA STA JMP
$F9CB #$02 $F9C1 #$00 $02FE $F9CB $4A #$02 $02FE $FA2E
****************************** LDX $3E A6 3E F9CB BMI $F9D6 30 07 F9CD LDA $20 A5 20 F9CF TAY A8 F9D1 CMP #$20 C9 20 F9D2 BNE $F9D9 DO 03 F9D4 391
job loop disk controller restart timer write protect? compare with last time store current condition unchanged? set flag for diskette change phase of the stepper motor head on track?
head is over track
move head one half track farther motor running? no bit 5 set? yes
ABACUS Software
F9D6
4C BE FA
Anatomy of the 1541
JMP $FABE
end of disk controller routine
******************************
F9D9 F9DB F9DD F9DE F9EO F9E2 F9E4 F9E6 F9E8 F9EB F9ED F9FO F9F2
C6 DO 98 10 29 85 29 FO AD 29 8D A9 85
F9F4 F9F6 F9F8 F9FA F9FB
A9 85 FO 98 29
F9FD F9FF
DO 03 4C BE FA
BNE $FA02 JMP $FABE
bit 6 set, head movement? yes end of the disk controller routine
FA02
6C 62 00
JMP ($0062)
move head
48 ID 04 7F 20 10 12 00 lC FB 00 lC FF 3E 00 20 DC 40
DEC BNE TYA BPL AND STA AND BEQ LDA AND STA LDA STA LDA STA BEQ TYA AND
$48 $F9FA
decrement counter still running?
$F9E4 #$7F $20 #$10 $F9FA $lCOO #$FB $lCOO #$FF $3E
bit 7 cleared? clear bit 7
#$00 $20 $F9D6 #$40
bit 4 set? no drive motor off set flag for motor off clear flag
****************************** FAOS
AS 4A
LDA #$4A
FA07 FA09
10 05 49 FF
BPL $FAOE EOR #$FF
FAOB FAOC FAOE FAI0 FA12
18 69 CS BO A9
step counter for head transport positive? negative, generate two's complement
CLC ADC CMP BCS LDA
200
01 64 OA 3B
#$01 $64 $FAIC #$3B
392
Anatomy of the 1541
ABACUS Software
FA14 FA16
85 62 A9 FA
STA $62 LDA #$FA
FA18 FAIA
85 63 DO 12
STA $63 BNE $FA2E
pointer $62/$63 to $FA3B
****************************** 5E 5E 61 5E 60 7B 62 FA
SBC SBC STA LDA STA LDA STA LDA
$5E $5E $61 $5E $60 #$7B $62 #$FA
FAIC FAIE FA20 FA22 FA24 FA26 FA28 FA2A
E5 E5 85 A5 85 A9 85 A9
FA2C FA2E
85 63 A5 4A
STA $63 LDA $4A
FA30 FA32 FA34
10 31 E6 4A AE 00 lC
BPL $FA63 INC $4A LDX $lCOO
FA37 FA38
CA 4C 69 FA
DEX JMP $FA69
calculate # of head steps -4 -4
pointer $62/$63 to $FA7B step counter for head transport
****************************** LDA $4A
FA3B
AS 4A
FA3D FA3F FA41 FA43
DO A9 85 A9
EF 4E 62 FA
BNE LDA STA LDA
$FA2E #$4E $62 #$FA
FA45 FA47 FA49 FA4B
85 A9 85 4C
63 05 60 BE FA
STA LDA STA JMP
$63 #$05 $60 $FABE
393
increment bits for stepper motor decrement move stepper motor short distance step counter for head transport not yet zero? pointer $62/$63 to $FA4E counter to 5
ABACUS Software
Anatomy of the 1541
****************************** FA4E C6 60 DEC $60 FASO DO 6C BNE $FABE FAS2 AS 20 LDA $20 FAS4 29 BF AND #$BF FAS6 FAS8 FASA FASC
8S A9 8S A9
FASE FA60
8S 63 4C BE FA
20 OS 62 FA
STA LDA STA LDA
$20 #$OS $62 #$FA
AE E8 8A 29 8S AD 29 OS 8D 4C
00 IC 03 4B 00 IC FC 4B 00 IC BE FA
LDX INX TXA AND STA LDA AND ORA STA JMP
$ICOO #$03 $4B $ICOO #$FC $4B $ICOO $FABE
****************************** FA7B FA7C FA7F FA81 FA84 FA86 FA88 FA8A FA8C FA8E
38 AD ES 8D C6 DO AS 8S A9 8S
07 IC SF OS IC 60 OC SE 60 97 62
clear bit 6, head transport ended
pointer $62/$63 to $FAOS
STA $63 JMP $FABE
****************************** FA63 C6 4A DEC $4A FA6S FA68 :CA69 FA6A FA6C FA6E FA71 FA73 FA7S FA78
load head decrement counter not yet zero?
SEC LDA SBC STA DEC BNE LDA STA STA STA
$IC07 $SF $ICOS $60 $FA94 $SE $60 #$ 97 $62
394
dec step cntr for head transport bits for step motor increment
serve stepper motor
prepare fast head movement timer minus 4 restart decrement counter not yet zero? 4 restart counter
ABACUS Software
Anatomy of the 1541
FA90
A9 FA
LDA #$FA
FA92 FA94
85 63 4C 2E FA
STA $63 JMP $FA2E
****************************** FA97 DEC $61 C6 61 FA99 DO F9 BNE $FA94 FA9B A9 A5 LDA #$A5 STA $62 FA9D 85 62 FA9F A9 FA LDA #$FA FAAI FAA3
85 63 DO EF
07 lC
$lC07
5F 05 lC 60 E2 4E 62 FA
LDA CLC ADC STA DEC BNE LDA STA LDA
63 05 60 OC lC FD
STA LDA STA LDA AND
$63 #$05 $60 $lCOC #$FD
AD 18 65 8D C6 DO A9 85 A9
FAB8 FABA FABC FABE FACI
85 A9 85 AD 29
FAC3 FAC6
8D OC lC 60
fast head movement decrement counter
pointer $62/$63 to $FAA5
STA $63 BNE $FA94
****************************** FAA5 FAA8 FAA9 FAAB FAAE FABO FAB2 FAB4 FAB6
pointer $62/$63 to $FA97
$5F $lC05 $60 $FA94 #$4E $62 #$FA
prepare slow head movement timer plus 2 restart decrement counter not yet zero? pointer $62/$63 to $FA4E counter to 5 clear bit 1, CA2 10, disable SO (Byte Ready)
STA $lCOC RTS
****************************** LDA $51 FAC7 A5 51 BPL $FAF5 10 2A FAC9
395
formatting track number fomatting already in progress?
ABACUS Software
Anatomy of the 1541
FACB FACD
A6 3D A9 60
LDX $3D LDA #$60
FACF FAD 1 FAD3 FAD5
95 A9 95 85
STA LDA STA STA
FAD7 FAD9
A9 A4 85 4A
LDA #$A4 STA $4A
FADB FADE
AD 00 1C 29 FC
LDA $lCOO AND #$FC
FAEO FAE3 FAE5 FAE8 FAEA
8D A9 8D A9 8D
STA LDA STA LDA STA
FAED
A9 OF
LDA #$OF
FAEF FAF2
8D 22 06 4C 9C F9
STA $0622 JMP $F99C
back in job loop
FAF5 FAF7 FAF9 FAFB FAFD
AO D1 FO 91 4C
00 32 OS 32 9C F9
LDY CMP BEQ STA JMP
#$00 ($32),Y $FBOO ($32),Y $F99C
still same track? yes store new track to job loop
FBOO FB03 FB05 FB07 FB09
AD 29 DO A9 4C
00 1C 10 05 08 D3 FD
LDA AND BNE LDA JMP
$lCOO #$10 $FBOC #$08 $FDD3
FBOC
20 A3 FD
20 01 22 51
00 1C OA 20 06 AO 21 06
$20,X #$01 $22,X $51
$lCOO #$OA $0620 #$40 $0621
JSR $FDA3
396
drive number flag for head transport set set dest track running track # for format -92 (46 tracks out) step counter for head transport stepper motor phase on whole track 10 error counter $621/$622 = 4000 initialize track capacity 4000 < capacity < 2*4000 bytes
write protect? no 26, on'
'write protect
erase track, write SYNC 10240 times
ABACUS Software
Anatomy of the 1541
FBOF
20 C3 FD
JSR $FDC3
FB12 FB14 FB17
A9 55 8D 01 1C 20 C3 FD
LDA #$55 STA $lCOI JSR $FDC3
FBIA FB1D FB20 FB22
20 20 A9 OD
FB25 FB28
8D OB 18 A9 62
FB2A FB2D FB2F FB32 FB35 FB37 FB39 FB3C FB3E FB41
8D A9 8D 8D AO A2 2C 30 2C 10
FB43
AD 04 18
LDA $1804
FB46 FB49
2C 00 lC 10 11
BIT $lCOO BPL $FB5C
FB4B
AD OD 18
LDA $180D
FB4E FB4F
OA 10 F5
ASL A BPL $FB46
FB51 FB52 FB54
E8 DO EF C8
INX BNE $FB43 INY
FB55 FB57
DO EC A9 02
BNE $FB43 LDA #$02
00 FE 56 F5 40 OB 18
06 00 07 05 00 00 00 FB 00 FB
18 18 18 lC lC
JSR JSR LDA ORA
$FEOO $F556 #$40 $180B
STA $180B LDA #$62 STA LDA STA STA LDY LDX BIT BMI BIT BPL
$1806 #$00 $1807 $1805 #$00 #$00 $lCOO $FB39 $lCOO $FB3E
397
write SYNC ($621/$622) times $55, no SYNC to write head and ($621/$622) times to disk switch to read wait for SYNC timer 1 free running 98 clock cycles, about 0.1 ms
start timer counter to zero SYNC found? no, wait SYNC found? wait until SYNC range done reset interrupt flag timer SYNC found? SYNC range not done ($55)? interrupt flag register timer flag to bit 7 timer not run out yet? increment counter increment hi-byte of counter overflow, error
ABACUS Software
Anatomy of the 1541
FB59 FB5C
4C D3 FD 86 71
FB5E FB60 FB62 FB64
84 A2 AO AD
72 00 00 04 18
STY LDX LDY LDA
$72 #$00 #$00 $1804
FB67 FB6A FB6C FB6F FB70
2C 30 AD OA 10
00 lC 11 OD 18
BIT BMI LDA ASL BPL
$ICOO $FB7D $180D A $FB67
FB72 FB73 FB75 FB76 FB78 FB7A FB7D FB7E FB7F
E8 DO C8 DO A9 4C 38 8A E5
FB81 FB82 FB84
AA
85 70 98
TAX STA $70 TYA
FB85 FB87 FB88 FB8A
E5 72 A8 85 71 10 OB
SBC $72 TAY STA $71 BPL $FB97
FB8C FB8E FB8F FB90
49 FF A8 8A 49 FF
EOR #$FF TAY TXA EOR #$FF
FB92 FB93 FB94
AA
TAX INX BNE $FB97
F5 EF EC 02 D3 FD 71
E8 DO 01
JMP $FDD3 STX $71
INX BNE INY BNE LDA JMP SEC TXA SBC
formatting error counter = duration of $55 range store counter to 0 again reset timer 1 interrupt flag SYNC found? yes interrupt flag reg timer flag to bit 7 no, wait until timer run out
$FB64
increment counter
$FB64 #$02 $FDD3
overflow, error formatting error
$71
difference between counter ($ 55) and value for SYNC range
398
bring to $70/$71 difference positive?
calculate abs. val of difference
ABACUS Software
Anatomy of the 1541
FB96 FB97 FB98 FB9A
C8 98 DO 04 EO 04
INY TYA BNE $FB9E CPX #$04
FB9C FB9E FBAO FBA2 FBA3 FBA5 F8A8
90 06 26 18 A5 6D 8D
$FBB6 $70 $71
70 21 06 21 06
BCC ASL ROL CLC LDA ADC STA
FBAB FBAD FBBO FBB3
A5 6D 8D 4C
71 22 06 22 06 OC FB
LDA ADC STA JMP
$71 $0622 $0622 $FBOC
FBB6 FBB8 FBBA FBBB FBBE FBCO FBC2 FBC3 FBC4 FBC6 FBC7 FBC9 FBCB FBCE FBCF FBDO FBD3 FBD4
A2 AO B8 AD 10 50 B8 E8 DO C8 DO A9 4C 8A OA 8D 98 2A
00 00
#$00 #$00
counter to zero
$lCOO $FBCE $FBBB
SYNC? no byte ready?
F5
LDX LDY CLV LDA BPL BVC CLV INX BNE INY BNE LDA JMP TXA ASL STA TYA ROL
$FBBB
increment counter
$FBBB #$03 $FDD3
overflow, error formatting error
FBD5 FBD8 FBDA FBDD
8D A9 2D 8D
24 06 BF OB 18 OB 18
18 70 71
00 lC OE 59
F2 03 D3 FD 25 06
STA LDA AND STA
$70 $0621 $0621
difference less than 4 * 0.1 ms? yes double difference
add to output value 4000
repeat until diff < 4 * 0.1 ms
A $0625
double counter
A
and to $624/$625 as track capacity
$0624 #$BF $180B $180B
399
turn timer off
ABACUS Software
Anatomy of the 1541
FBEO FBE2 FBE5
A9 66 8D 26 06 A6 43
LDA #$66 STA $0626 LDX $43
FBE7 FBE9 FBEA FBEB FBEE FBFO FBFl FBF2 FBF3
AO 98 18 6D 90 C8 C8 CA DO
LDY TYA CLC ADC BCC INY INY DEX BNE
FBF5
49 FF
EOR #$FF
FBF7 FBF8 FBFA FBFB FBFE FCOO FC03 FC04 FC05 FC07 FC08 FCOA FCOB FCOE FCI0 FC12 FC15 FC16 FC17 FC19 FCIA FCIC FCIE FCIF FC21
calculate # of all bytes in spaces between blocks
38 69 18 6D BO CE
SEC ADC CLC ADC BCS DEC TAX TYA EOR SEC ADC CLC ADC BPL LDA JMP TAY TXA LDX SEC SBC BCS DEY BMI INX
result in A/X
00 26 06 01
F5
00 25 06 03 24 06
AA
98 49 38 69 18 6D 10 A9 4C A8 8A A2 38 E5 BO 88 30 E8
FF 00 24 06 05 04 D3 FD 00 43 03 03
102 number of sectors in this track
#$00 $0626 $FBFl
$FBEA
#$00 $0625 $FC03 $0624 #$FF #$00 $0624 $FC15 #$04 $FDD3
4 formatting error
#$00 $43 $FC21 $FC24
400
total divided by # of sectors ($43 )
----------------~-------------.----------------------
Anatomy or the 1541
ABACUS Software
FC22 FC24
DO F5 8E 26 06
BNE $FC19 STX $0626
FC27 FC29 FC2B FC2D FC30 FC31 FC33 FC36 FC38 FC3B FC3D FC3F
EO BO A9 4C 18 65 8D A9 8D AO A6 A5
04 05 05 D3 FD
CPX BCS LDA JMP CLC ADC STA LDA STA LDY LDX LDA
#$04 $FC30 #$05 $FDD3
FC41 FC44 FC45 FC46 FC49 FC4C FC4D FC4F FC52 FC53 FC55 FC58 FC59 FC5B FC5E FC5F FC61 FC64 FC65 FC68 FC69 FC6B FC6E FC71 FC74
99 C8 C8 AD 99 C8 A5 99 C8 B5 99 C8 B5 99 C8 A9 99 C8 99 C8 A9 59 59 59 59
00 03
STA INY INY LDA STA INY LDA STA INY LDA STA INY LDA STA INY LDA STA INY STA INY LDA EOR EOR EOR EOR
$0300,Y
counter for sectors counter 10 drive number constant 8, marker for header start in buffer
$0628 $0300,Y
sector number in buffer
$51 $0300,Y
track number in buffer
$13,X $0300,Y
ID 2 in buffer
$12,X $0300,Y
ID 1 in buffer
#$OF $0300,Y
15 in buffer
$0300,Y
15 in buffer
43 27 06 00 28 06 00 3D 39
28 06 00 03 51 00 03 13 00 03 12 00 03 OF 00 03 00 03 00 FA FB FC FD
02 02 02 02
$43 $0627 #$00 $0628 #$00 $3D $39
#$00 $02FA,Y $02FB,Y $02FC,Y $02FD,Y 401
compare # of bytes per gap with minimum value ok 5 format error rem of division plus # of sectors save
generate checksum
ABACUS Software
F9 02 28 06 28 06 43
Anatomy of the 1541
FC77 FC7A FC7D FC80
99 EE AD C5
FC82
90 BB
BCC $FC3F
FC84 FC85 FC86 FC87 FC88 FC8B FC8C FC8E FC90 FC92
98 48 E8 8A 9D E8 DO A9 85 20
FA 03 31 30 FE
TYA PHA INX TXA STA INX BNE LDA STA JSR
FC95 FC96 FC97 FC98 FC9B FC9E FCAO FCA2
68 A8 88 20 20 A9 85 20
E5 FD F5 FD 05 31 E9 F5
PLA TAY DEY JSR JSR LDA STA JSR
FCA5 FCA7
85 3A 20 8F F7
STA $3A JSR $F78F
FCAA FCAC FCAE
A9 00 85 32 20 OE FE
LDA #$00 STA $32 JSR $FEOE
FCB1 FCB3 FCB6 FCB8 FCBA FCBB FCBC
A9 8D A2 50 B8 CA DO
LDA STA LDX BVC CLV DEX BNE
00 05
FF 01 1C 05 FE FA
STA INC LDA CMF
$02F9,Y $0628 $0628 $43
$0500,X $FC88 #$03 $31 $FE30
$FDE5 $FDF5 #$05 $31 $F5E9
#$FF $lC01 #$05 $FCB8 $FCB8
402
and write in buffer increment counter counter compare with # of sectors smaller, then continue
generate data block buffer ptr to $300 convert blk header data to GCR code
copy buffer data copy data in buffer buffer ptr to $500 calculate parity for data buffer and save convert data block to GCR code erase track, write SYNC 10240 times SYNC to write head write SYNC 5 times byte ready?
Anatomy of the 1541
ABACUS Software
FCBE FCCO FCC2 FCC4 FCC5 FCC8 FCCB FCCC FCCO FCCF FC01 FC03 FC04
A2 A4 50 B8 B9 80 C8 CA 00 A2 50 B8 A9
OA 32 FE
FC06 FC09 FCOA FCOC FCOE FCEO FCE2 FCE3 FCE6 FCE7 FCE9 FCEB FCEO FCEE
80 CA DO A9 A2 50 B8 80 CA DO A2 50 B8 BO
01 1C
FCF1 FCF4 FCF5 FCF7 FCF9 FCFB FCFC
80 E8 DO AO 50 B8 B1
FCFE FOOl F002
80 01 1C C8 DO F5
00 03 01 1C F3 09 FE 55
F5 FF 05 FE 01 1C F7 BB FE 00 01 01 1C F4 00 FE 30
LOX LOY BVC CLV LOA STA INY OEX BNE LOX BVC CLV LOA
#$OA $32 $FCC2
10 times buffer pointer byte ready?
$0300,Y $lC01
blk header GCR code write 10 bytes written?
$FCC2 #$09 $FC01
9 times byte ready?
STA OEX BNE LOA LOX BVC CLV STA OEX BNE LOX BVC CLV LOA
$lC01
$55, GAP between block header and data block write
$FC01 #$FF #$05 $FCEO
9 times? SYNC 5 times byte ready?
$lC01
to write head
$FCEO #$BB $FCEB
byte ready?
STA INX BNE LOY BVC CLV LOA
$lC01
area $lBB to $lFF, 69 bytes GCR code write
$FCEB #$00 $FCF9
byte ready?
#$55
$0100,X
($30),Y
STA $lC01 INY BNE $FCF9 403
plus 256 bytes GCR code = 325 bytes write to disk
ABACUS Software
Anatomy of the 1541
FD04 FD06 FD09
A9 55 AE 26 06 50 FE
LDA #$55 LDX $0626 BVC $FD09
FDOB FDOC FDOF FD10 FD12
B8 8D 01 1C CA DO F7 A5 32
CLV STA $lC01 DEX BNE $FD09 LDA $32
FD14 FD15 FD17 FD19 FD1C FD1E FD20 FD21 FD23 FD24 FD27 FD29 FD2C FD2E FD30 FD32 FD34
18 69 85 CE DO 50 B8 50 B8 20 A9 8D A9 85 A9 85 A5
CLC ADC STA DEC BNE BVC CLV BVC CLV JSR LDA STA LDA STA LDA STA LDA
FD36 FD39 FD3C
8D 28 06 20 56 F5 A2 OA
STA $0628 JSR $F556 LDX #$OA
FD3E FD40 FD42 FD43 FD46
AO 50 B8 AD D1
LDY BVC CLV LDA CMP
FD48 FD4A
DO OE C8
OA 32 28 06 93 FE FE 00 FE C8 23 06 00 30 03 31 43
00 FE 01 1C 30
$55 ($626) times GAP between data block and next block header write ptr to block header GCR code
#$OA $32 $0628 $FCB1 $FD1E
plus 10
$FD21
byte ready?
$FEOO #$C8 $0623 #$00 $30 #$03 $31 $43
switch to reading 200 attempts
#$00 $FD40 $lC01 ($30),Y
BNE $FD58 INY
404
decrement sector # write next sector byte ready?
buffer ptr to $300 # of sectors per track wait for SYNC 10 data block header GCR code byte ready? read byte compare with data in buffer not equal, error
Anatomy of the 1541
ABACUS Software
FD4B FD4C FD4E FD4F FD51
CA DO F2 18 A5 30 69 OA
DEX BNE $FD40 CLC LDA $30 ADC #$OA
FD53 FD55
85 30 4C 62 FD
STA $30 JMP $FD62
FD58 FD5B FD5D FD5F
CE DO A9 4C
FD62 FD65
inc ptr by 10 to next block header
$0623 $FD2C #$06 $FDD3
dec attempt counter not yet zero? 6 format error
20 56 F5 AO BB
JSR $F556 LDY #$BB
FD67 FD69 FD6A FD6D
50 FE B8 AD 01 lC D9 00 01
BVC $FD67 CLV LDA $lCOI CMP $0100,Y
wait for SYNC ptr to first 69 GCR bytes byte ready?
FD70 FD72 FD73 FD75 FD77 FD79 FD7A FD7D
DO C8 DO A2 50 B8 AD D9
FD80
DO D6
BNE $FD58
FD82 FD83 FD84 FD86 FD89 FD8B FD8D
C8 CA DO CE DO E6 A5
INY DEX BNE DEC BNE INC LDA
23 06 CF 06 D3 FD
E6 F2 FC FE 01 lC 00 05
Fl 28 06 AE 51 51
DEC BNE LDA JMP
BNE INY BNE LDX BVC CLV LDA CMP
$FD58 $FD67 #$FC $FD77 $lCOI $0500,Y
read byte compare with buffer contents not equal, error next byte byte ready? read byte compare with next 256 GCR bytes not equal, then error next byte
$FD77 $0628 $FD39 $51 $51
405
dec sector counter not yet zero? increment track #
Anatomy or the 1541
ABACUS Software
FD8F
C9 24
CMP #$24
FD91
BO 03
BCS $FD96
FD93
4C 9C F9
JMP
$F99C
FD96 FD98 FD9A FD9C
A9 85 A9 85
LDA STA LDA STA
#$FF $51 #$00 $50
FD9E FDAO
A9 01 4C 69 F9
FF 51 00 50
LDA #$01 JMP $F969
****************************** FDA3 FDA6
AD
OC 1C 29 1F
LDA $lCOC AND #$lF
FDA8 FDAA FDAD FDAF
09 8D A9 8D
CO OC 1C FF 03 1C
ORA STA LDA STA
#$CO $lCOC #$FF $lC03
FDB2 FDB5 FDB7 FDB9 FDBB FDBC FDBD FDBF FDCO FDC2
8D A2 AO 50 B8 88 DO CA DO 60
01 1C 28 00 FE
STA LDX LDY BVC CLV DEY BNE DEX BNE RTS
$lC01 #$28 #$00 $FDB9
FA F7
AE 21 06
AC 22 06 50 FE B8
track number to $FF clear flag for GCR data ok write SYNC 10240 times, erase track switch PCR to writing, CB2 10
port A (read/write head) to output write SYNC to disk 40 byte ready?
$FD89 $FD89
****************************** FDC3 FDC6 FDC9 FDCB
compare with 36, highest track#+l greater, then formatting done continue
LDX $0621 LDY $0622 BVC $FDC9 CLV
406
read/write ($621/$622) times byte ready?
-------------------------~----------------------
ABACUS Software
FDCC FDCD FDCF FDDO FDD2
CA DO FA 88 10 F7 60
Anatomy of the 1541
DEX BNE $FDC9 DEY BPL $FDC9 RTS
****************************** FDD3 FDD6 FDD8
CE 20 06 FO 03 4C 9C F9
DEC $0620 BEQ $FDDB JMP $F99C
FDDB FDDD
AO FF 84 Sl
LDY #$FF STY $Sl
FDDF FDEO
C8 84 SO
INY STY $SO
FDE2
4C 69 F9
JMP $F969
****************************** FDES B9 00 03 LDA $0300,y FDE8 99 4S 03 STA $034S,Y FDEB DEY 88 FDEC FDEE FDF1 FDF4
DO F7 AD 00 03 8D 45 03 60
attempt counter for formatting dec # of attempts zero, then error continue flag for end of formatting flag for erasing GCR data error termination
copy buffer contents
BNE $FDES LDA $0300 STA $0345 RTS
****************************** FDFS FDF7 FDFA
AO 44 B9 BB 01 91 30
LDY #$44 LDA $OlBB,Y STA ($30),Y
FDFC FDFD FDFF
88 10 F8 60
DEY BPL $FDF7 RTS
407
copy data from overflow buffer $lBB to $lFF write in buffer $30/$31
ABACUS Software
Anatomy of the 1541
****************************** FEOO AD OC 1C LDA $lCOC FE03 09 EO ORA #$EO FE05 FE08 FEOA FEOD
8D OC 1C A9 00 8D 03 1C 60
STA $lCOC LDA #$00 STA $lC03 RTS
****************************** FEOE FEll FE13
AD
OC 1C 29 1F 09 co
LDA $lCOC AND #$lF ORA #$CO
FE15 FE18 FE1A
8D OC 1C A9 FF 8D 03 1C
STA $lCOC LDA #$FF STA $lC03
FE1D FE1F
A9 55 8D 01 1C
LDA #$55 STA $lC01
FE22 FE24 FE26 FE28 FE29 FE2A FE2C FE2D FE2F
A2 AO 50 B8 88 DO CA DO 60
LDX LDY BVC CLV DEY BNE DEX BNE RTS
28 00 FE FA F7
A9 85 85 85 A9 85 A5
00 30 2E 36 BB 34 31
LDA STA STA STA LDA STA LDA
switch PCR to reading, CB2 hi port A to input write $55 10240 times switch PCR to writing, CB2 10 port A to output (write head) %01010101, not SYNC to port A (write head)
#$28 #$00 $FE26
byte ready
$FE26
10240 times
$FE26
****************************** FE30 FE32 FE34 FE36 FE38 FE3A FE3C
switch to reading
#$00 $30 $2E $36 #$BB $34 $31
408
convert header in buffr 0 to GCR code
clear byte counter
Anatomy of the 1541
ABACUS Software
2F 01 31 36 2E 52
STA LOA STA LOY LOA STA INY LOA STA INY LOA STA INY LDA STA INY BEQ STY JSR
$2F #$01 $31 $36 ($2E),Y $52
byte counter
($2E),Y $53
second data byte
($2E),Y $54
third data byte
($2E),Y $55
fourth data byte
FE3E FE40 FE42 FE44 FE46 FE48 FE4A FE4B FE4D FE4F FE50 FE52 FE54 FE55 FE57 FE59 FE5A FE5C FE5E
85 A9 85 A4 B1 85 C8 B1 85 C8 B1 85 C8 B1 85 C8 FO 84 02
FE61
4C 44 FE
JMP $FE44
FE64
4C DO F6
JMP $F6DO
2E 53 2E 54 2E 55 08 36 00 F6
$FE64 $36 $F6DO
****************************** PHA 48 FE67 TXA 8A FE68 PHA 48 FE69 TYA FE6A 98 PHA FE6B 48 LOA $1800 AD 00 18 FE6C
02 03 53 E8 00 1C
FE6F FE71 FE73 FE76
29 FO 20 AO
FE79 FE7A
OA 10 03
AND BEQ JSR LOA
#$02 $FE76 $E853 $lCOO
ASL A BPL $FE7F
409
first data byte
done? convert 4 bytes to 5 GCR bytes continue convert 4 bytes to 5 GCR bytes interrupt routine save registers int from serial bus (ATN in)? no serve serial bus interrupt from timer 1? no
ABACUS Software
Anatomy of the 1541
FE7C
20 BO F2
JSR $F2BO
FE7F FE80 FE81 FE82 FE83 FE84
68 A8 68
PLA TAY PLA TAX PLA RTI
AA
68 40
IRQ routine for disk controller restore registers
******************************
FE85 12 FE86 04 FE87 04 FE88 90
constants for disk format 18, track for BAM and directory start of BAM at position 4 4 bytes in BAM for each track $90 = 144, end of BAM, start diskname
******************************
table of command words
FE89 56 49 44 4D 42 55
'v' ,
' I ' ,
'B' ,
'u'
FE8F 50 26 43 52 53 4E ******************************
'P' ,
' & ' ,
'S' ,
'N'
'D' ,
'M' ,
'C' ,
'R' ,
lo-bytes of command addresses
FE95 84 05 C1 F8 1B 5C FE9F 07 A3 FO 88 23 OD ******************************
hi-bytes of command addresses
FEA1 ED DO C8 CA CC CB FEA7 E2 E7 C8 CA C8 EE ****************************** FEAD 51 DD 1C 9E IC
410
bytes for syntax check
Anatomy of the 1541
ABACUS Software
****************************** FEB2 52 57 41 4D
file control methods 'R' , 'w' , 'A' ,
'M'
****************************** FEB6 44 53 50 55 4C
file types 'D' , 'S' , 'P' , 'L'
****************************** FEBB 44 53 50 55 52
names of file types 1st letters 'D' , 'S' , 'P' , 'U' , 'R' 2nd letters 'E' , 'E' , 'R' , , S ' , 'E' 3rd letters 'L' , 'Q' , 'G' , 'R' , 'L'
FECO 45 45 52 53 45 FEC5 4C 51 47 52 4C
'U' ,
****************************** FECA 08 00 00 ****************************** FE CD 3F 7F BF FF ****************************** FED1 11 12 13 15 ****************************** FED5 4A FED6 04 FED7 24 FED8 1F 19 12
****************************** FE DB 01 FF FF 01 00
411
masks for bit cmd # of sectors per track 17, 18, 19, 21
contants for disk format 'A' marker for 1541 format 4 track numbers 36, highest track number + 1 31, 25, 18 tracks with change of number of sectors control bytes for head position
ABACUS Software
Anatomy of the 1541
****************************** FEEO 03 04 05 06 07 07 ****************************** FEE6 3E
addresses of buffers high bytes checksum for ROM $EOOO-$FFFF
****************************** JMP ($0065) FEE7 6C 65 00
from ur command $EB22, to rest w/o RAM/ROM test
******************************
patch for diagnostic routine turn LED on port to output back to diagnostic routine
FEEA FEED FEFO
8D 00 1C 8D 02 1C 4C 7D EA
STA $lCOO STA $lC02 JMP $EA7D
****************************** FEF3 FEF4 FEF6
8A A2 05 CA
TXA LDX #$05 DEX
FEF7 FEF9 FEFA
DO FD AA
BNE $FEF6 TAX RTS
60
****************************** FEFB FE FE
20 AE E9 4C 9C E9
JSR $E9AE JMP $E99C
****************************** FF01 FF04 FF06 FF08 FF09
AD C9 FO 38 E9
02 02 2D 05 2B
LDA CMP BEQ SEC SBC
$0202 #$2D $FFOD #$2B 412
delay loop for serial bus in 1541 mode about 40 microseconds
patch for data output to serial bus CLOCK OUT hi DATA OUT 10 U9 vector, switch 1540/1541 char after "U9" '_'?
yes, then 1540 mode
'+'?
Anatomy of the 1541
ABACUS Software
FFOB
DO DA
BNE $FEE7
FFOD
85 23
STA $23
FFOF
60
RTS
****************************** 03 18 02 00 18 lA
FFI0 FF13 FF15 FF18
8E A9 8D A9
FFIA FFID
8D 02 18 4C A7 EA
STX LDA STA LDA
$1803 #$02 $1800 #$lA
STA $1802 JMP $EAA7
****************************** FF20 FF23 FF25 FF27 FF29 FF2C
AD 29 DO A9 8D 4C
00 18 01 F9 01 05 18 DF E9
LDA AND BNE LDA STA JMP
$1800 #$01 $FF20 #$01 $1805 $E9DF
indirect jump via ($ 65) 0=1541 mode, else 1540 mode patch for reset routine, from $EAA4 port A to output DATA OUT hi port B DATA OUT, CLOCK OUT & ATN A to output data dir port B back to initialization patch for LISTEN to serial bus, from $E9DC wait for DATA IN 10 load timer back to LISTEN routine
****************************** FF2F AA ... FFE1 ... AA ****************************** FFE2 52 53 52 AA ****************************** $C8C6 FFE6 C6 C8 $F98F FFE8 8F F9
413
format routine turn drv motor off
ABACUS Software
Anatomy of the 1541
****************************** USER vectors FFEA 5F CD UA, U1, $CD5F FFEC 97 CD UB, U2, $CD97 FFEE 00 05 UC, U3, $0500 FFFO 03 05 UD, U4, $0503 FFF2 06 05 UE, U5, $0506 FFF4 09 05 UF, U6, $0509 FFF6 OC 05 UG, U7, $050C FFF8 OF 05 UH, U8, $050F FFFA 01 FF UI, U9, $FF01 (NMI vector not used) ************************** FFFC OA EA FFFE 67 FE
414
hardware vectors $EAAO RESET and UJ (U: ) vector $FE67 IRQ vector
ABACUS Software
Anatomy or the 1541
Chapter 4: Programs and Tips for Using the 1541 Disk Drive
4.1 4.1.1
Utility Programs Displaying all File Parameters
Not all of the information about a file can be gathered from the directory. Perhaps you need to know the starting address of a program on the diskette. This starting address is located in the program file itself and not in the directory entry. These and other file parameters can be easily found and displayed by the following program. The number and kind of file parameters are naturally dependent on the file type. A relative file, for instance, has no starting address. The following table presents the parameters displayed by this program. FILE TYPE
PARAMETER DEL
SEQ
PRG
USR
REL
File closed? File protected Allocated blocks Record length Side-sector blocks Data blocks Records Starting address
X X X
X X X
X X X
X X X
X X X X X X X
Free blocks, disk Allocated blocks, disk
X X
X X
X X
X X X
415
X X
ABACUS Software
Anatomy of the 1541
This program is documented in detail so that the serious programmer can get a good overview of the file parameters. In addition, the variables used by the program are explained.
Variables used in the program: Numerical Variables T S FL TY FT LB HB BL RL DT DS SA BF BA BS RC
Track of the actual block of the file entry in the directory Sector of the actual block of the file entry in the directory Flag, set if the file name read from the diskette does not agree with the searched-for file File type of the given file (byte 0 of the entry) nibble of the file type (bits 0-3), contains the actual file type Low byte of the starting address High byte of the starting address Number of allocated blocks in the file Record length of a relative file Track of the first data block of a program file, which contains the starting address Sector of the first data block of a program file Starting address of a program file Number of free blocks on a disk N umber of allocated blocks on a disk Number of side-sector blocks in a relative file Number of records in a relative file
String Variables Name of the file to search for Contains the actual filename from the directory File type Indicates whether the file is closed or not (contains "YES" or "NO") PR$ Indicates whether the file is protected or not (contains "YES" or "NO") RE$ contains CHR$(18), REVERSE ON RA$ contains CHR$(146), REVERSE OFF
F$ FF$ FT$ CL$
416
ABACUS S(lftware
Anatomy of
~he
1541
Program Documentation: Set the color code of the screen Program heacling Asks if the names should be listed out. Sets flag FL to 1 and executes the routine at 280-490. 250 - 270 Input the filename. Asks for new input if the filename if greater than 16 characters. 280 - 490 Reads the file name from the directory and either displays it (FL= 1) or compares it to the desired filename. 500 - 530 Reads byte 0 (file type) of the file entry of the desired file and stores it in TY. Also, the right half-byte is stored in FT. 540 - 590 Checks the file type and saves the text in FT$, and checks for invalid file type. 600 - 610 Checks bit 7 of the file type byte (file closed?) and saves the result in CL$. 620 - 630 Checks bit 6 of the file type byte (file protected?) and saves the result in PR$. 640 - 690 Reads the number of allocated blocks in the file from bytes 28 and 29 of the file entry and saves it in BL. 700 - 730 If it is relative file, the record length is read from byte 21 and saved in RL 740 - 880 If it is a program file, the starting address of the file is taken from the first data block and stored in SA. 890 - 980 Free blocks on the disk are calculated by reading the first byte of the track-marked BAM section and added to BF. The allocated blocks are calculated by BA = 664 - BF 990 -1020 Here the number of side-sector blocks (BS) of a relative file is calculated with the help of the record length (RL) and the number of allocated blocks in the file (RC). 1040-1230 Here the data can be sent to the screen or the printer as one chooses. The file parameters are shown in REVERSE. 1240-1280 The parameters of another file can be output. 110
120 - 200 210 - 230
The program is written for a CBM 64. In spite of this, it can be run without major changes on a VIC 20. Only line 110, where the color of the screen is set, need be changed for the VIC 20.
417
ABACUS Software
Anatomy of the 1541
100 CLR 110 POKE 53280,2:POKE53281,2:PRINTCHR$(158); CHR$(147); 120 PRINT TAB(6);"===========================" 130 PRINT TAB(6);"DISPLAY ALL FILE PARAMETERS" 140 PRINT TAB(6);"===========================" 150 PRINT:PRINT 160 PRINT"WITH THIS PROGRAM, ALL PARAMETERS OF A" 170 PRINT"FILE CAN BE OUTPUT TO THE SCREEN OR TO" 180 PRINT"A PRINTER AT YOUR OPTION." 200 PRINT:PRINT 210 PRINT"LIST FILENAMES (YIN)?" 220 GETX$:IFX$"Y"ANDX$"N"THEN220 230 IF X$="Y"THENFL=1:GOSUB280 240 FL=O 250 INPUT"NAME OF THE FILE: ";F$ 260 IFLEN(F$)4THENPRINT"INVALID FILE TYPE!":GOT0200 600 IFTYAND128THENCL$="YES":GOT0620 610 CL$="NO" 620 IFTYAND64THENPR$="YES":GOT0640 630 PR$="NO" 640 PRINT#15,"B-P";2;X*32+30 650 GET#2,X$:IFX$=""THENX$=CHR$(0) 660 LB=ASC(X$) 670 GET#2,X$:IFX$=""THENX$=CHR$(0) 680 HB=ASC(X$) *256 690 BL=LB+HB 700 IFFT4THEN740 710 PRINT#15,"B-P";2;X*32+23 720 GET#2,X$:IFX$=""THENX$=CHR$(0) 730 RL=ASC (X$) 740 IFFT2THEN890 750 PRINT#15,"B-P";2;X*32+3 760 GET#2,X$:IFX$=""THENX$=CHR$(0) 770 DT=ASC(X$) 780 GET#2,X$:IFX$=""THENX$=CHR$(0) 790 DS=ASC(X$) 8000PEN3,8,3,"#" 810 PRINT#15,"B-R";3;0;DT;DS 820 PRINT#15,"B-P";3;2 830 GET#3,X$:IFX$=""THENX$=CHR$(0) 840 LB=ASC(X$) 850 GET#3,X$:IFX$=""THENX$=CHR$(0) 860 HB=ASC(X$) *256 870 SA=LB+HB 880 CLOSE3 419
ABACUS Software
Anatomy of the 1541
890 PRINT#15,"B-R";2;0;18;0 900 BF=O 910 FORI=4T0140STEP4 920 IFI=72THEN960 930 PRINT#15,"B-P";2;I 940 GET#2,X$:IFX$=""THENX$=CHR$(O) 950 BF=ASC(X$)+BF 960 NEXT 980 BA=664-BF 990 IFFT4THEN1040 1010 BS=BL/121:IFBSINT(BS)THENBS=INT(BS+1) 1020 RC=INT«(BL-BS)*254)/RL) 1040 PRINTCHR$(147);"SCREEN OR PRINTER (Sip)?" 1050 GETX$:IFX$"S"ANDX$"P"THEN1050 1060 RE$=CHR$(18) :RA$=CHR$(146) 1070 IFX$="S"THENOPEN1,3:PRINT#1,CHR$(147) 1080 IFX$="P"THENOPEN1,4 1090 PRINT#l,"FILE PARAMETERS ";RE$;F$;RO$ 1100 PRINT#l,"------------------------------------" 1110 PRINT#l, "FILE TYPE: ";RE$;FT$;RA$: PRINT#l 1120 PRINT#l,"FILE CLOSED: ";RE$;CL$;RA$: PRINT#l 1130 PRINT#l, "FILE PROTECTED: ";RE$;PR$;RA$: PRINT#l 1140 PRINT#l,"ALLOCATED BLOCKS: ";RE$;BL;RA$: PRINT#l 1150 IFFT4THEN1200 1160 PRINT#1,"RECORD LENGTH: ";RE$;RL;RA$: PRINT#1 1170 PRINT#l,"SIDE-SECTOR BLOCKS: ";RE$;BS;RA$: PRINT#l 1180 PRINT#l,"DATA BLOCKS: ";RE$;BL-BS;RA$: PRINT#l 1190 PRINT#l,"RECORDS: ";RE$;RC;RA$: PRINT#1 1200 IFFT=2THENPRINT#1,"START ADDRESS: ";RE$;SA;RA$:PRINT#l 1210 PRINT#1,"FREE BLOCKS (DISK): ";RE$;BF;RA$: PRINT#l
420
ABACUS Software
Anatomy of the 1541
1220 PRINT#l,"ALLOCATED BLOCKS (D) :"iRE$iBAiRA$: PRINT#l 1230 CLOSE1 1240 PRINT"MORE (YIN)?" 1250 CLOSE2:CLOSE15 1260 GETX$:IFX$"Y"ANDX$"N"THEN1260 1270 IFX$="Y"THEN100
421
Anatomy or the 1541
ABACUS Software
4.1.2
Scratch-protect Files - File Protect
As already mentioned, it is possible to protect files on the VIC-1541 diskette and save this information in the directory. A file's type is contained in byte 0 of the file entry. Bit 6 denotes a protected file. If this bit is set to 1, the file can no longer be deleted with the SCRATCH command. But because the DOS has no command to set this bit, an alternative way must be used to protect a file. With the following program, you can:
• • • •
display all files on the disk protect files un protect files erase files
This program can delete protected files as well as unprotected files. If you wish to delete a protected file, you must confirm it. This program is also documented with a variable usage and descriptions so that you can use these techniques in your own programs. This utility program was written for the CBM 64. This version can also be run on the VIC 20. Only line 100 which sets the screen color on the CBM 64 need be changed or ignored. If you value perfect video output, lines 110-230 can also be changed to accommodate the VIC 20's smaller screen size.
List of Variables: DF
Flag, set in the routine "read/search file" if the desired filename is found FL Set if the routine "read/search file" is only to be used for listing files FT Variable for storing the filetype T Track of the current block of the file entry S Sector of the current block of the file entry IT Track, in which the file entry block of the file is found SS Sector, in which the file entry block of the desired file is found FF$ Last filename read from the directory F$ Filename to search for 422
ABACUS Software
Anatomy of the 1541
Program Documentation: 100 110 - 230 240 - 260 270 280 - 350 310 320 350 360 - 600 390 400 410 - 450 460 - 480 490 - 500 510 520 - 550 560 570 - 600 610 - 850 640 650 660 - 700 710 - 730 740 - 750 760 770 - 800 810 820 - 850 860 -1170 890 900 910 - 950 960 - 980 990 1000-1030 1040-1060 1070
Set the screen color Program header and option menu Read the menu choice and call the appropriate subroutine Back to the option menu Subprogram "list all files" Erase screen Set flag FL to list files in the subroutine "read/search file" Reset the flag and jump back Subroutine "protect file" Call subroutine "input filename" Call the subroutine "read/search file" Test if the file is found Read file type and store in FT Test if the file is already protected Protect file (bit 6 to 1) Transfer the file type to the buffer and write the block to disk Close the channel Message "File protected" and jump back Subroutine "unprotect file" Call subroutine "input filename" Call subroutine "read/search file" Test if file is found Read file type and store in FT Test if the file is already unprotected Unprotect the file (bit 6 to 0) Transfer the file type to the buffer and write the block to the disk Close the file End the subroutine Subroutine "erase a file" Call the subroutine "input filename" Call the subroutine "read/search file" Test if the file is found Read the file type and save in FT Test if the file is protected Indicate that the file is protected, with the possibility to erase it anyway Ask if the file should really be erased Bit 6 set back, if protected 423
ABACUS Software
1080-1110 1120 1130 1140-1170 1190-1560 1220 1230-1240 1250-1320
1330 1340-1350 1360-1390 1400-1530 1540-1560
Anatomy of the 1541
Transfer the file type to the buffer and write the block to the disk Initialize the diskette Erase the file End the subroutine Subroutine "read/search file" Open the command and data channels Read directory and set buffer pointer Test if the disk contains a write protect. For this purpose, the directory is written back to the disk unchanged (line 1250). If the disk has a write protect tab on it, the error message 26, WRITE PROTECT ON will occur. Initial values for the track and sector variables are set Read the file entry block and position the buffer pointer to the fIrst byte Read the address of the next file entry block Loop to read filenames. The names are then either listed on the screen or compared to the desired filename, based on the value of flag FL If the variable T (track) contains zero, no more file entry blocks follow and the subroutine ends.
424
ABACUS Software
Anatomy of the 1541
100 POKE 53280,2:POKE53281,2:PRINTCHR$(158); CHR$(147); 110 PRINTTAB(8) ; "=======================" 120 PRINTTAB(8);"ERASE AND PROTECT FILES" 130 PRINTTAB(8);"=======================" 140 PRINT:PRINT 150 PRINT"WITH THIS PROGRAM, FILES CAN BE" 160 PRINT"PROTECTED, ERASED, AND UNPROTECTED" 180 PRINT:PRINT 190 PRINTTAB(6); -1- LIST ALL FILES":PRINT 200 PRINTTAB(6); -2- PROTECT A FILE":PRINT 210 PRINTTAB(6); -3- UNPROTECT A FILE":PRINT 220 PRINTTAB(6); -4- ERASE A FILE":PRINT 230 PRINTTAB(6); -5- END THE PROGRAM":PRINT 240 GETX$:IFX$=" ORVAL(X$)24THENS%(T)=18: IFT>30THENS%(T)=17 550 NEXT 560 FORI=OT07:Z(I)=2I:NEXT:RETURN 570 IFRTHENPRINT#1,"U1 2 O"T;S:SYSIN:RETURN 580 PRINT#l,"B-P 2 0":SYSOUT:PRINT#1,"U2 2 O"T;S:RETURN 590 CLOSE2:PRINT"PLEASE INSERT "A$(R)" DISKETTE." 600 PRINT"AND PRESS RETURN":PRINT:POKE198,0 610 GETA$:IFA$CHR$(13)THEN610 620 PRINT#l,"IO" 6300PEN2,8,2,"#":RETURN 640 FOR I = 828 TO 873 : REM READ MACH LANG PROG 650 READ X : POKE I,X : S=S+X : NEXT 660 DATA 162, 2, 32,198,255,160, 0, 32,207,255, 145,250 670 DATA 200,208,248,230,251, 32,204,255, 96,198, 1,162 680 DATA 2, 32,201,255,160, 0,177,250, 32,210, 255,200 690 DATA 208,248,230,251, 32,204,255,230, 1, 96 700 IF S7312 THEN PRINT "ERROR IN DATA! !":END 710 IN=828:0UT=849:RETURN
431
ABACUS Software
4.1.4
Anatomy of the 1541
Copying Individual Files to another Diskette
The following program permits you to copy individual files from one diskette to another. The files can be programs (PRG), sequential files (SEQ) or user files (USR). Relative files cannot be copied with this program; these can be copied with a BASIC program that reads all data records into a string array and then writes them back again to a new file. In the first pass, the program reads the complete file into the memory of the Commodore 64. Then the destination diskette is inserted and the file opened with the same name. Next the complete file is written on the second disk. The computer has 49 Kbytes for data storage; you can handle up to 196 blocks on the diskette. For reasons of speed, the reading and writing of the data is performed by a machine language program, which is stored in DATA statements. The program is suited for copying sequential files as already mentioned, as well as programs of all kinds; the start address (of a machine language program) is not relevant.
432
ABACUS Software
Anatomy of the 1541
100 REM FILE COPIER PROGRAM C64 110 REM 120 POKE 56,12 : CLR 130 GOSUB 1000 140 INPUT"FILENAME "iN$ 150 PRINT"FILE TYPE "i 160 GETT$:IFT$"S"ANDT$"P"AUDT$"U"THEN160 170 PRINTT$:PRINT 180 PRINT"PLEASE INSERT ORIGINAL DISK" 190 PRINT"AND PRESS A KEY":PRINT 200 GETA$:IFA$=""THEN200 210 OPEN 2,8,2,N$+","+T$ 220 POKE 3,0:POKE 4,12:SYS 866 230 CLOSE 2 240 PRINT"PLEASE INSERT DESTINATION DISK" 250 PRINT"AND PRESS A KEY":PRINT 260 GETA$:IFA$=""THEN260 270 OPEN 2,8,2,N$+","+T$+",W" 280 POKE3,0:POKE4,12:SYS828 290 CLOSE 2:END 1000 FOR I = 828 TO 898 1010 READ X : POKE I,X : S=S+X : NEXT 1020 DATA 162, 2, 32,201,255,198, 1,160, 0, 56, 165, 3 1030 DATA 229, 5,165, 4,229, 6,176, 13,177, 3, 32,210 1040 DATA 255,230, 3,208,236,230, 4,208,232,230, 1, 76 1050 DATA 204,255,162, 2, 32,198,255,160, 0, 32, 207,255 1060 DATA 145, 3,230, 3,208, 2,230, 4, 36,144, 80,241 1070 DATA 165, 3,133, 5,165, 4,133, 6, 76,204, 255 1080 IF S 8634 THEN PRINT "ERROR IN DATA! !":END 1090 RETURN
433
Anatomy of the 1541
ABACUS Software
4.1.5 Reading the Directory from within a Program Sometimes applications programs store user data in a file under a desired name. If you want to use this file again, but you cannot remember the file name, then you have a problem. If this happens, you must exit the program, search for the name in the directory, reload the program and start again. To avoid this, you can include a directory listing routine in your program. If you forget the filename, you can display the directory with a function key, for example, without the need to leave the program. Here is a sample of such a routine: 100 PRINTCHR$(147) i 1100PEN15,8,15,"IO":OPEN2,8,2,"#" 120 T=18:S=1 130 PRINT#15,"B-R"i2iOiT;S 140 PRINT#15,"B-P";2iO 150 GET#2,X$:IFX$=""THENX$=CHR$(0) 160 T=ASC(X$) 170 GET#2,X$:IFX$=""THENX$=CHR$(0) 180 S=ASC(X$) 190 FORX=OT07 200 PRINT#15,"B-P"i2;X*32+5 210 FF$="" 220 FORY=OT015 230 GET#2,X$:IFX$=""THENX$=CHR$(0) 240 IFASC(X$)=160THEN270 250 FF$=FF$+X$ 260 NEXTY 270 IFA=OTHENA=l:PRINTFF$i :GOT0290 280 A=0:PRINTTAB(20) iFF$ 290 NEXTX 300 IFTOTHEN130 310 CLOSE1:CLOSE2 320 PRINT"RETURN FOR MORE" 330 INPUTX$ 340 END:REM IF SUBROUTINE, THEN RETURN HERE
In order to select the filename, the directory is printed on the screen. Should this program be used as a subroutine (called with GOSUB) line 340 must contain RETURN instead of END. We used this routine in the utility programs in sections 4.1.1 and 4.1.2. 434
ABACUS Software
Anatomy of the 1541
4.1.6 Searching for "Hidden" Files Many of our readers are familiar with this situation: Some program or even the entire diskette is "shot to pieces." This can have serious consequences. The work of days or weeks can be destroyed by a wrong command. What error conditions can occur? Often it happens that diskettes are formatted without IDs. This causes all of the files on the disk to be erased. Erased is really the wrong term. Only the first block of the directory is actually erased (track 18, sector 1). The blocks originally allocated by the files are still present. Another example: You overwrote a file with the @-sign. Here it can occur that the disk drive does not execute the corresponding routine properly. The error that usually occurs is that when trying to load one program, another appears instead. The reason is the following: Instead of the starting block of the new program, the starting block of some other program is entered in the directory. The "lost" program is stilI on the diskette, only the first block is unknown. The following program returns all of the data blocks on the disk which could be the starting block of a file. If a program is lost, you can determine its starting block by comparing these blocks with the actual starting blocks. This starting block must then be placed in the directory entry with the disk monitor. NOTE: The following program outputs the blocks in decimal, but the disk monitor works in hexadecimal. With a completely erased disk you must restore the entire file entry in the directory. Since the number of blocks allocated to the file is not known, a 0 appears in the directory. It is advisable to load the reconstructed prograrr once and then save it on another disk.
435
Anatomy of the 1541
ABACUS Software
1 PRINT CHR$(147) "SeaL'ching for Hidden Files" 5 DIMBL(35,20) 6 PRINT"PLEASE INSERT THE DISKETTE AND PRESS RETURN" 7 INPUTX$ 10 OPEN 1,8,15,"10" 20 OPEN 2,8,2,"#" 40 REM READ SECTORS FOR 1=1 TO 4 52 53 READ T1,T2,Sl 54 DATA 1,17,20 55 DATA 18,24,18 56 DATA 25,30,17 57 DATA 31,35,16 60 FOR T=T1 TO T2 65 IF T=18 THEN 140 68 PRINT"track ";t; 70 FOR S=O TO Sl 75 PRINT"sector ";s;"{cursor up}" 80 PRINT#1,"U1";2;0;T;S 85 PRINT#1,"B-P";2;0 90 GET#2,B1$:GET#2,B2$ 100 IF B1$="" THEN B1$=CHR$ (0) 110 IF B2$="" THEN B2$=CHR$(0) 115 TR=ASC(B1$) :SC=ASC(B2$) 120 IF BL(T,S)2 THEN BL(T,S)=3 125 IF TR=O OR TR>35 OR SC>20 THEN BL(T,S)=1:GOT0130 126 BL(TR,SC)=2 130 NEXT S 135 PRINT"{2 cursor ups}" 140 NEXT T 150 :NEXT I 155 CLOSE1:CLOSE2 160 FOR T=l TO 35 170 FOR S=O TO 20 180 IF BL(T,S)=3 THEN PRINT"TRK:";T;" SEC:";S:FI=FI+1 190 NEXT S 195 :NEXT T 200 PRINT"FILES:"FI
436
ABACUS Software
Anatomy
or the
1541
After starting this program the first two bytes of each block ( diskette are read. These two bytes contain the address of the next blo::k the corresponding program. This takes about two minutes. Then the program prints all blocks which could themselves be a data block and to which no other data blocks point. Only these can be the first data blocks of a file. If there are relative files on the disk, however, blocks may be printed which are not the first data blocks of any file. We are not perfect either and there have been situations when this program has helped us a great deal. We hope that it can save you hours and days of work as well.
437
ABACUS Software
Anatomy of the 1541
4.1.7 Changing the Disk Name and the ID The name of the disk and the ill are set when the disk is formatted. Without some help, this name cannot be changed without reformatting the disk. But since both of these data are stored on track 18, sector 0, we can change both of them in a roundabout way. The following program allows you to change the name and ill of the diskette without changing anything else or losing any other data. After starting, the program requires you to insert the appropriate disk and press RETURN. Once this is done, the disk name is displayed. This can be changed if you answer the following question with "Y". The same applies for the ill. Here is the listing: 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 285 290 300
REM ======================= REM CHANGE DISK NAME AND ID REM ======================= PRINT CHR$(147); PRINT"INSERT DISK AND PRESS RETURN" GETX$:IF X$CHR$(13) THEN 150 OPEN 15,8,15 OPEN 2,8,2,"'" PRINT'15,"U1";2;0;18;0 PRINT'15,"B-P";2;144 DN$="" FOR 1=0 TO 15 GET,2,X$ DN$=DN$+X$ NEXT PRINT"NAME: ";DN$ PRINT"CHANGE (YIN)?" GET X$:IF X$"Y" AND X$"N" THEN 270 IF X$="N n THEN 340 F1=1 INPUT "NEW NAME: n;DN$ IF DN$="" OR LEN(DN$»16 THEN PRINT CHR$(145); :GOT0290 310 FOR 1=1 TO 16-LEN(DN$) 320 DN$=DN$+CHR$(160)
438
ABACUS Software
330 340 350 360 370 380 390 400 405 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580
Anatomy of the 1541
NEXT PRINT#15,"B-P";2;162 GET#2,X$:ID$=X$ GET#2,X$:ID$=ID$+X$ PRINT "ID: ";ID$ PRINT"CHANGE (YiN)?" GET X$:IF X$"Y" AND X$"N" THEN 390 IF X$="N" THEN 430 F2=1 ";ID$ INPUT "NEW ID: IF LEN(ID$)2 THEN PRINT CHR$(145);: GOTO 410 IF F1=0 THEN 480 PRINT#15,"B-P";2;144 FOR 1=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT IF F2=0 THEN 520 PRINT#15,"B-P";2;162 PRINT#2,LEFT$(ID$,1); PRINT#2,RIGHT$(ID$,1); IF F1=0 AND F2=0 THEN 570 PRINT#15,"U2";2;0;18;0 PRINT#15,"IO" INPUT#15,E1$,E2$,E3$,E4$ PRINT E1$"-"E2$"-"E3$"-"E4$ CLOSE 2:CLOSE 15 END
The most important lines and their function: Read track 18, sector 0 into the buffer Position the buffer pointer to the disk name Read the name byte-by-byte and build it in DN$ Set flag Fl (new name) Input the new name; check to see that it is not longer than 16 characters 310-330 Pad disk name with SHIff SPACE (160) 340-360 Position to ID and read into ID$ Set flag F2 (new ID) 405 180 190 200-240 285 290-300
439
Anatomy of the 1541
ABACUS Software
410-420 430-470 480-510 520-540 560-580
Input new ID; check if length is 2 bytes Write new name if changed (F1=1) Write new ID if changed (F2=1) Write block back Output the error channel and end program
440
ABACUS Software
Anatomy of the 1541
':;!.1.8 Software Write Protect With this program you can protect your disketes from accidental erasure. This protection can also be removed, of course. If the software protection is enabled, no more programs can be saved on the diskette. The program listing: 100 110 120 13() 140 150 160 170 180 190 200 210 220 230 240 250 260
REM ============================ REM WRITE PROTECT REM ============================ A$=CHR$(233) PRINT CHR$(147); PRINT"WRITE PROTECT ENABLE OR DISABLE (E/D)?" GET X$:IF X$"E" AND X$"D" THEN 160 IF X$="D" THEN A$="A" PRINT"INSERT DISK AND PRESS RETURN" GET X$:IF X$CHR$(13) THEN 190 OPEN 15,8,15 PRINT#15,"IO" OPEN 2,8,2,"#" PRINT#15, "M-W"CHR$(l)CHR$ (l)CHR$ (1)CHR$(65) PRINT#15,"U1 2 0 18 0" PRINT#15,"B-P 2 2" PRINT#2,A$;
270 PRINT#15,"U2 2 0 18 0"
280 CLOSE 2 290 PRINT#15,"IO":CLOSE 15
This program tricks the DOS. The actual protection consists of writing the byte CHR$(233) in the second byte of sector 0 in track 18. This is normally the format id of the disk. But this alone is not sufficient, so we must dig a little deeper into our bag of tricks in order to be able to remove this protection again. Once the protection is enabled, no more write accesses to the disk are possible. But we can also no longer set the byte back to its original value. Here we trick the DOS by changing the format id not on the disk, but first on the buffer in which it is contained. The most important line of this program is line 230.
441
ABACUS Software
Anatomy of the 1541
4.1.9 Invisible Directory With this program you can amaze the '64 owners in your circle of acquaintances. You produce diskettes whose directories are no longer visible. After LOAD"$",8 and LIST, only READY appears! This can also be reversed, of course. The program listing: 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 360 370 380 390 400
REM ========================= REM INVISIBLE DIRECTORY REM ========================= PRINT CHR$(147); PRINT "INSERT DISK AND PRESS RETURN" GET X$:IF X$CHR$(13) THEN 150 PRINT "INVISIBLE OR VISIBLE (I/V)?" GET X$:IF X$"I" AND X$"V" THEN 170 OPEN 15,8,15:0PEN 2,8,2,"#" IF X$="I" THEN 390 REM *** DIRECTORY VISIBLE *** PRINT#15,"U1";2;Oi18;0 PRINT#15,"B-P";2;144 GET#2,X$ IF X$=CHR$(20) THEN 270 PRINT"DIRECTORY IS VISIBLE ... " GO TO 630 PRINT#15,"B-P";2;200:DN$="" FOR 1=1 TO 16 GET#2,X$ DN$=DN$+X$ NEXT PRINT#15,"B-P";2;144 FOR 1=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT PRINT#15,"U2";2;0;18;0 PRINT#15,"IO" GOTO 630 REM *** DIRECTORY INVISIBLE *** PRINT#15,"U1";2;0;18;0
442
ABACUS Software
410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640
Anatomy of the 1541
PRINT#15,"B-P";2;144:DN$="" FOR I=1 TO 16 GET#2,X$ DN$=DN$+X$ NEXT IF LEFT$(DN$,1)CHR$(20) THEN 490 PRINT"DIRECTORY IS INVISIBLE ... " GOTO 630 PRINT#15,"B-P";2;200 FOR I=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT DN$=CHR$(20)+CHR$(20)+CHR$(20) FOR I=1 TO 13 DN$=DN$+CHR$(O) NEXT PRINT#15,"B-P";2;144 FOR I=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT PRINT#15,"U2";2;0;18;0 PRINT#15,"IO" CLOSE 2:CLOSE 15 END
Because this program is somewhat more complicated than the previous one, we will make only the following comment: The directory is made invisible by overwriting the disk name with the following characters: Three CHR$(20)s and Thirteen CHR$(O)s In order to be able to restore the name later, it is stored in an unused area of block 18/0. This unused area is from position 200 to 215.
443
ABACUS Software
Anatomy of the 1541
4.2 The Utility Programs on the TEST/DEMO Disk There are many 1541 owners who know little about the programs contained on the TestlDemo disk. The main reason is that these programs are largely undocumented. The following descriptions of these programs should help you:
4.2.1
DOS 5.1
The DOS 5.1 simplifies the operation of the VIC-1541 DOS. It can run on the VIC-20 or Commodore 64. To load DOS 5.1 on the VIC-20, give the commands
LOAD"VIC-20 WEDGE",8
RUN
This is the loader for DOS 5.1 for the VIC 20. If you want to use it on the Commodore 64, give the commands:
LOAD"C-64 WEDGE",8
RUN
This loads DOS 5.1 into the CBM 64. What does this DOS 5.1 offer? It allows you to send convenient commands to the 1541 disk drive. If, for example, you want to display the directory on the screen, you use the DOS 5.1 command @$ or >$. This does not erase the program in memory.
445
ABACUS Software
Anatomy of the 1541
The individual commands of the OOS 5.1 Command
Function
@$or>$ @Vor>V @C: ... or>C: ... "fIle or /fIle @or> @N: ... or>N: ... @lor>1 @R: ... or>R: .. . @S: ... or>S: .. . @#nor>#n
Display the directory Same function as "V ALIDATE" Copy files (COPY) Load program Read and display error message Format a diskette Intitialize the disk Rename a file (RENAME) Erase a file (SCRATCH) Change disk device to n
4.2.2
COPY/ALL
With the program COPY/ALL, files can be copied between disk drives with different addresses. A drive must be changed from device address 8 with the program DISK ADDR CHANGE before this can occur. After starting the program, the message: disk copy all
jim butterfield
from unit? 8
appears on the screen. Here you give the device address of the disk drive from which you wish to get the files. If this address is 8, just press RETURN. After this you give the corresponding drive number of this unit (always 0 for single drives). In this manner you also give the device address of the destination drive. Once this has occurred, the program asks want to new the output disk ?n
You are being asked if the destination diskette should be formatted. You answer with "y" (yes) or "n" (no). Then you can choose the files you want to copy with the wildcard (*). If all files are supposed to be copied, just give the asterisk. 446
ABACUS Software
Anatomy of the 1541
Now the program gives the message
hold down 'y' or 'n' key to select The program displays the files on the original disk, which you can select with the "y" key (yes) or "n" (no). The files by which you pressed "y" will be copied. If, during the copying process, asterisks (***) appear behind the files, it means that an error has occurred. If there is not enough room on the destination disk, "*** output disk full" and "do you have a new one" appears. The remaining files can be put on another formatted diskette. To do this, answer "y" when ready. At the the conclusion of the copying process, the number of free blocks on the destination disk is displayed.
4.2.3
DISK ADDR CHANGE
This program allows you to change the device address of a disk drive. After starting the program, tum off all drives except for the one you wish to change. Now enter the old and new device addresses. After this, the address is changed and the other drive can be turned back on. The following drives can be changed with this program:
1541 2031 2040 4040 4040 8050 8050 8250
DOS V2.6 DOS V2.6 DOS Vl.1 DOS V2.1 DOS V2.7 DOS V2.5 DOS V2.7 DOS V2.7
447
ABACUS Software
4.2.4
Anatomy of the 1541
DIR
This is a small utility program with the following options: d - display the directory on the screen > - With this character, a disk command can be given in shortened form (for example, >N:TEST,KN to format a diskette) q - exit the program s - display the error channel These possibilities are also found in DOS 5.1, along with other commands.
4.2.5
VIEW BAM
With this utility program you can view the usage of diskette blocks on the screen. This table displays the sectors in columns and the tracks in rows. Crosses indicate free blocks and reverse crosses indicate allocated blocks. "n/a" means that these blocks do not exist on the track. After outputting the table, the diskette name and the number of free blocks are displayed.
4.2.6
CHECK DISK
The utility program CHECK DISK tests every block on the diskette by writing to and reading from it. The current block and the total number of tested blocks is displayed on the screen. WARNING! THIS PROGRAM DESTROYS (FORMATS) THE DISKETTE!
448
ABACUS Software
4.2.7
Anatomy of the 1541
DISPLAY T&S
If you are interested in the construction of the individual blocks of the disk and want to display these on the screen, this utility program will help you. After starting the program you give the desired track and sector. The contents of this block will then be sent to the printer or screen. The DISK-MONITOR contained in this book is easier to use, because it allows you to change blocks and save them again.
4.2.8
PERFORMANCE TEST
This program makes it possible to test the mechanics of the VIC-1541 disk drive. To accomplish this, all the access commands are executed in the following order: 1. The disk is formatted 2. A file is opened for reading 3. Data are written to this file 4. The file is closed again 5. This file is opened for reading 6. The data are read 7. The file is closed again 8. The file is erased 9. Track 35 is written 10. Track 1 is written 11. Track 35 is read 12. Track 1 is read After each access of the disk the error channel is displayed. In this manner, it can be established which access of the disk is not executed properly. When using this program, use only diskettes containing no important data because the entire diskette is erased during the testing.
449
ABACUS Software
Anatomy of the 1541
4.3
BASIC Extensions and Programs for the 1541
4.3.1
Input strings of desired length from the disk
Reading data from the disk with the INPUT# statement has one major disadvantage--only data items having fewer than 88 characters can be read. This is because the input buffer of the computer is limited. In addition, not all characters can be read with the INPUT# statement. If a record contains a comma or colon, BASIC views it as a separating character and the remainder of the input is assigned to the next variable. If the INPUT# statement has only one variable, the remainder is ignored and the next INPUT# statement continues reading past the next carriage return (CHR$(13)). The alternative is to read the input with a GET# statement but this results in much slower input. To avoid these disadvantages, we can use a small machine language routine. We will change the INPUT# statement so that we can specify the number of characters to be read. To distinguish it from the normal INPUT# statement, we name the command INPUT*. The syntax looks like this:
INPUT* Ifn, len, var Lfn is the logical file number of the previously OPENed file, len is the number of characters to be read, and var is the string variable into which the characters are to be read. A program excerpt might look like this: 100 110
OPEN 2,8,2, "FILE" INPUT* 2,100,A$
This reads a string of 100 characters from the opened file into A$. This procedure is especially suited for relative files, because a complete record can be read with one command after positioning the record pointer. The partitioning of a record into fields can be accomplished with the MID$ function. An elegant method of creating records is described in the next section.
451
ABACUS Software
Anatomy of the 1541
With this procedure it is no longer necessary to end a record with a carriage return. You can especially make use of the maximum record length with relative flles: 100 OPEN 1,8,15 110 OPEN 2,8,2, "REL-FILE,L, "+CHR$ (20) 120 PRINT#l, "P"+CHR$(2)+CHR$(0)+ CHR$(l)+CHR$(l) 130 PRINT#2, "12345678901234567890"; 140 PRINT#l, "P"+CHR$(2)+CHR$(0)+ CHR$(l)+CHR$(l) 150 INPUT* 2,20,A$ 160 PRINT A$ 12345678901234567890
Here is the assembler listing for the machine language program as well as a loader program in BASIC for the Commodore 64 and VIC 20. The program resides in the cassette buffer. 110:
033C ; INPUT* LFN,LEN,A$
150: 160: 170: 180: 190:
033C 033C 033C 033C 033C
210: 220: 380: 390: 400: 410: 420: 430: 440: 450: 460 : 470:
033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C
INPUT STAR BASVEC CHRGET CHRGOT
$85 $AC $308 $73 CHRGET + 6
; C64 VERSION CHKIN BASIN CHKCOM INTER EXECOLD INPUTOLD FINDVAR STRRES FRESTR GETBYT
452
=
$E11E $E112 $AEFD $A7AE $A7E7 $ABBF $B08B $B475 $B6A3 $B79E
Anatomy of the 1541
ABACUS Software
VIC 20 VERSION 240: 250: 260: 270: 280: 290: 300: 310: 320: 330:
$EIIB $EI0F $CEFD $C7AE $C7E7 $CBBF $D08B
CHKIN BASIN CHKCOM INTER EXECOLD INPUTOLD FINDVAR STRRES FRESTR GETBYT
033C 033C 033C 033C 033C 033C 033C 033C 033C 033C
;
$D475
$D6A3 $D79E
COMMON LABELS $49 $FFCC $61
VARADR CLRCH PARA
490: 500: 510:
033C 033C 033C
530: 540: 550: 560: 570: 580:
033C 033C 033E 0340 0343 0346
A9 AO 8D 8C 60
47 INIT 03 08 03 09 03
*= LDA LDY STA STY RTS
828 #TEST BASVEC BASVEC+l
600: 610: 620: 630: 640:
0347 034A 034C 034E 0351
20 C9 FO 20 4C
73 00 TEST 85 06 79 00 E7 A7
JSR CMP BEQ JSR JMP
650: 660:
0354 20 73 00 FOUND 0357 C9 AC
670: 680: 680: 690:
0359 035B 035E 0361
CHRGET #INPUT FOUND CHRGOT EXECOLD ; TO THE OLD ROUTINE CHRGET ; NEW #STAR INPUT ROUTINE OKSTAR INPUTOLD INTER GETBYT-3 ; GET FILE NUMBER
FO 20 4C 20
06 BF AB AE A7 9B B7 OKS TAR
453
JSR CMP BEQ JSR JMP JSR
ABACUS Software
700: 710: 720:
Anatomy of the 1541
0364 20 1E E1 0367 20 FD AE 036A 20 9E B7
730: 730:
036D 8A 036E 48
740: 750:
036F 20 FD AE 0372 20 8B BO
760: 760: 770: 780:
0375 0377 0379 037C
790:
037D 20 75 B4
800: 810: 820: 830: 840: 850: 860: 870: 880: 890: 900: 910: 910:
0380 0382 0385 0387 0388 038A 038B 038E 0390 0391 0393 0395 0398
JSR JSR JSR TXA PHA
85 49 84 4A 20 A3 B6 68
AO B9 91 88 10 C8 20 91 C8 C4 DO 20 4C
02 61 00 STORE 49 F8 12 E1 FETCH 62 61 F6 CC FF AE A7
454
CHKIN CHKCOM GETBYT
;
LENGTH
STORE JSR CHKCOM JSR FINDVAR SEARCH FOR VARIABLE STA VARADR STY VARADR+1 JSR FRESTR PLA LENGTH JSR STRRES RESERVE PLACE FOR STRING LDY #2 LDA PARA,Y STA (VARADR) ,Y DEY BPL STORE INY y=o JSR BASIN STA (PARA +1), Y INY CPY PARA BNE FETCH JSR CLRCH JMP INTER iTO INTERPRETER LOOP
Anatomy of the 1541
ABACUS Softwa re
Here are the BASIC programs for entering the machine language program for the INPUT* statement. INPUT* , 64 Version 100 FOR I = 828 TO 922 S=S+ X: NEXT 110 READ X : POKE I,X 3, 9, 3,140 , 8, , 3,141 0, 71,16 120 DATA 169, 96, 32 0, 76, 6, 32,12 1, 0,201 ,133, 240, 130 DATA 115, 231,1 67 6, 32,19 1,171 , 0,201 ,172, 240, 140 DATA 32,11 5, 76,17 4 , 150 DATA 167, 32,15 5,183 , 32, 30,22 5, 32,25 3,174 32,15 8 160 DATA 183,1 38, 72, 32,25 3,174 , 32,13 9,176 ,133, 73,13 2 2, 170 DATA 74, 32,16 3,182 ,104, 32,11 7,180 ,160, 185, 97 0,145 , 73,13 6, 16,24 8,200 , 32, 18,22 5, 180 DATA 145, 98 190 DATA 200,1 96, 97,20 8,246 , 32,20 4,255 , 76, 174,1 67 200 IF S 11096 THEN PRINT "ERROR IN DAT A!!" END 210 SYS 828 : PRINT "OK." INPUT* , VIC 20 Version 100 FOR I = 828 TO 922 S=S+X : NEXT 110 READ X : POKE I, X 3, 9, 3,140 , 8, 3,141 , 120 DATA 169, 71,16 0, 96, 32 0, 76, 6, 32,12 1, 0,201 ,133, 240, 115, DATA 130 231,1 99 6, 32,19 1,203 , 0,201 ,172, 240, 32,11 5, DATA 140 76,17 4 455
ABACUS Softwa re
Anatomy of the 1541
150 DATA 199, 32,15 5,215 , 32, 27,22 5, 32,25 3,206 , 32,15 8 160 DATA 215,1 38, 72, 32,25 3,206 , 32,13 9,208 ,133, 73,13 2 170 DATA 74, 32,16 3,214 ,104, 32,11 7,212 ,160, 2, 185, 97 180 DATA 0,145 , 73,13 6, 16,24 8,200 , 32, 15,22 5, 145, 98 190 DATA 200,1 96, 97,20 8,246 , 32,20 4,255 , 76, 174,1 99 200 IF S 11442 THEN PRINT "ERROR IN DATA ' '" END 210 SYS 828 : PRINT "OK."
4.3.2 Easy Prepa ration of Data Records If you have worked with relative files before, you know that a definit e record length must be established. This record is usually divide d into several fields which likewise begin at a definite position within the record , and have a set length.
If you create a new record, a separate INPUT statement is genera used for each field. Before the complete record can be written, it must lly assembled properly. Each field must be checked for proper length. If be longer than then the planne d length of the corresponding data field, it is the remainder must be truncated to the proper length. Here are two new BASIC commands that are excellently suited to this task. These new commands are written in machine language and are initialized with a SYS command. You can then use them as any other BASIC commands. The first comm and has the name !STR$ and serves to create a string with the length of the data record. A$ = !STR$(lOO,If If)
creates a string with 100 blanks and puts it in the variable A$.
456
ABACUS Software
Anatomy of the 1541
The next command places our data field within the previously created string. For example, if you want to assign the variable N$ containing the last name as a field of 25 characters at position 1 in the string A$, our new command looks like this:
MID$ (A$,1,25) = N$ Here the MID$ command is used as a so-called pseudo-variable on the left side of the assignment statement. What happens here is as follows: The variable N$ replaces the first 25 characters of A$. If the variable N$ is longer than 25 characters, only the first 25 characters are replaced and the rest are disregarded. If N$ is shorter than 25 characters, only as many characters are replaced as N$ contains. The original characters in A$ remain (blanks, in our case). That is exactly as we wanted. Now we can program the following:
200 210 220 230 240 250 260 270 280 290 300 310 320 330
INPUT "LAST NAME INPUT "FIRST NAME INPUT "STREET INPUT "CITY INPUT "STATE INPUT "ZIP CODE A$ = !STR$ (92, " MID$ (A$,1,25) = MID$ (A$,26,20) = MID$ (A$,46,20) = MID$ (A$, 66,15) = MID$ (A$,81,2) = MID$ (A$,83,9) = PRINT#2, A$
; ; ; ; ; ;
") L$ F$ S$ C$ T$ Z$
457
L$ F$ S$ C$ T$ Z$
ABACUS Software
Anatomy of the 1541
Here is the machine language program for the Commodore 64 135: 140: 150: 160: 170: 180: 190: 200: 205: 210: 220: 226: 229: 230: 231: 232: 233: 234: 235: 236 : 237: 238: 240: 241: 242: 243: 245: 248: 248: 248: 248: 248: 250: 250: 250: 251: 251: 251: 251:
C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C802 C804 C807 C80A C800 C80F C811 C814 C816 C818 C81B
*= CHKOPEN CHKCLOSE CHKCOM FRMEVL CHKSTR FRESTR YFAC CHRGET CHRGOT GETBYT INTEGER OESCRPT STRAOR ADR2 ADR1 LEN1 LEN2 NUMBER START TYPFLAG STRCODE ILLQUAN SYNTAX POSCOOE VECTOR TEMP A9 AO 8D 8C 4C A9 85 20 C9 FO 20 4C
00 C8 OA OB 6B 00 00 73 21 06 79 80
03 03 C8 TESTIN 00 00 AE 458
LOA LOY STA STY JMP LOA STA JSR CMP BEQ JSR JMP
$C800 $AEFA $AEF7 $AEFO $A09E $A08F $B6A3 $B3A2 $73 CHRGET+6 $B79B $B1AA $64 $62 $FB $FB+2 3 4 5 6 13 $C4 $B248 $AF08 $B9 $30A LEN1 #TESTIN VECTOR VECTOR+1 MIOSTR #0 TYPFLAG CHRGET #"!" TEST2 CHRGOT $AE80
~---
----------------~-
--
Anatomy of the 1541
ABACUS Software
252: 252: 252: 253:
C81E C821 C823 C825
20 C9 FO 4C
JSR CMP BEQ JMP
73 00 TEST2 C4 03 08 AF ; ;
CHRGET #STRCODE STRING SYNTAX
STRING$ FUNCTION
900: 900:
C828 20 73 00 STRING C82B 20 FA AE
JSR JSR
CHRGET CHKOPEN
910: 920: 920:
C82E 20 9E B7 C831 8A C832 48
JSR TXA PHA
GETBYT+3
930: 940: 950: 960:
C833 C836 C839 C83B
FD AE 9E AD OD OC
JSR JSR BIT BMI
970: 980:
C83D 20 AA B1 C840 A5 64
JSR LDA
990: 1000 :
C842 DO 24 C844 A5 65
BNE LDA
1010 : 1020:
C846 4C 52 C8 C849 20 82 B7 STR
JMP JSR
1030 :
C84C FO 1A
BEQ
1040 : 1050 :
C84E AO 00 C850 B1 22
LDY LDA
1060 : 1070 :
C852 85 03 C854 68
1080 : 1090 : 1100 :
20 20 24 30
STA PLA
STR2
STORE LENGTH CHKCOM FRMEVL TYPFLAG STR STRING INTEGER ;HIGH DESCRPT BYTE ;>255 ILL DESCRPT+1 ; LOW BYTE,LENGTH STR2 $B782 SETSTR TYPFLAG TO NUMERIC ILL LENGTH 0 #0 ($22) ,Y FIRST CHAR TEMP LENGTH
C855 20 7D B4
JSR
$B47D
C858 A8 C859 FO 07
TAY BEQ
STR3
459
;OPEN PAREN
FRESTR
ABACUS Software
Anatomy of the 1541
1110: 1120: 1120:
C85B A5 03 C85D 88 C85E 91 62
LDA DEY STA
1130: 1140:
C860 DO FB C862 20 CA B4 STR3
BNE JSR
1150: 1160:
C865 4C F7 AE C868 4C 48 B2 ILL
IN JMP JMP
LOOP
TEMP (STRADR) ,Y CREATE STRING LOOP $B4CA i BRING STRING DESCRIPTOR STACK CHKCLOSE ILLQUAN
MID$(STRINGVAR,POS,LEN) = STRING EXP MID$(STRINGVAR,POS) STRING EXP 200: 210:
C86B C86B
MIDCODE EXECUT
240: 250: 255: 260 : 270: 280: 290: 325: 330: 355: 360: 370: 372: 375: 378:
C86B C86B C86B C86B C86B C86B C86B C86B C86B 0003 0004 0005 0007 0007 0007
EXECOLD VARNAM VARADR DESCRPT TESTSTR GETVAR SETSTR TEST GETBYT
400: 410: 420: 430: 440: 450:
C86B C86D C86F C872 C875 C876
LENGTH POSITION VARSTR COMP POINT2 A9 AO 8D 8C 60 20
76 MIDSTR C8 08 03 09 03 73 00 MID TEST
460
*= *= *= *=
LDA LDY STA STY RTS JSR
$CA $308 iVECTOR FOR STATEMENT EXECUTE $A7E7 $45 $49 $64 $AD8F $B08B $AA52 $AEFF $B79E 3 *+1 *+1 *+2 $B2 $50 #MIDTEST EXECUT EXECUT+1 CHRGET
--------
------------
ABACUS Software
Anatomy of the 1541
460:
C879 C9 CA
CMP
470:
C87B FO 06
BEQ
480: 490:
C87D 20 79 00 C880 4C E7 A7
JSR JMP
500:
C883 20 73 00 MID
JSR
505:
C886 20 FA AE
JSR
510:
C889 20 8B BO
JSR
520: 530: 535: 535: 540: 545: 545: 545:
C88C C88E C890 C892 C894 C897 C899 C89B
64 65 49 4A A3 B6 00 64
STA STY STA STY JSR LDY LDA PHA
545: 550:
C89C FO 2E C89E 20 52 AA
BEQ JSR
560: 560: 560:
C8A1 AO 01 C8A3 B1 49 C8A5 85 05
LDY LDA STA
570: 570: 570: 600: 610:
C8A7 C8A8 C8AA C8AC C8AF
C8 B1 85 20 20
49 06 FD AE 9E B7
INY LDA STA JSR JSR
620: 630: 650: 650: 660:
C8B2 C8B3 C8B5 CSB6 C8B8
8A FO 17 CA 86 04 20 79 00
TXA BEQ DEX STX JSR
85 84 85 84 20 AO B1 48
461
#MIDCODE iCODE FOR MID$ ,• ?. MID YES CHRGOT EXECOLD EXECUTE NORMAL STATEMENT CHRGET iNEXT CHAR CHKOPEN iOPEN PAREN GETVAR iGET VAR DESCRPT DESCRPT+1 VARADR VARADR+1 FRESTR #0 (DESCRPT) , Y LENGTH ILL SETSTR iPUT STRING IN RAM #1 (VARADR),Y VARSTR iVAR ADDR (VARADR),Y VARSTR+1 CHKCOM GETBYT iGET POS ILL POSITION CHRGOT
ABACUS Software
Anatomy of the 1541
660:
C8BB C9 29
CMF
665: 665:
C8BD DO 04 C8BF A9 FF
BNE LDA
665: 670: 670:
C8C1 DO OC C8C3 20 FD AE NEXT C8C6 20 9E B7
BNE JSR JSR
680: 690: 700: 710: 715: 715: 715: 717: 717: 717: 720:
C8C9 C8CA C8CC C8CF C8D1 C8D2 C8D3 C8D5 C8D7 C8D9 C8DB
730: 770: 780:
C8DE A9 B2 C8EO 20 FF AE C8E3 20 9E AD
LDA JSR JSR
790: 800: 800: 800: 800: 800: 800: 810: 810: 820:
C8E6 C8E9 C8EB C8ED C8EF C8FO C8F2 C8F4 C8F5 C8F7
20 AO B1 85 88 B1 85 88 B1 FO
A3 B6 02 64 51
JSR LDY LDA STA DEY LDA STA DEY LDA BEQ
840: 850: 860: 870: 880:
C8F9 C8FB C8FD C8FF C901
C5 BO 85 A5 18
03 02 03 05
8A DO 4C 85 68 38 E5 C5 BO 85 20
03 48 B2 ILL STORE 03 04 03 02 03 F7 AE OK
64 50 64 D3
TXA BNE JMP
STA PLA SEC SBC CMF BCS STA JSR
CMP BCS STA LDA CLC
OK1
462
#")" iEND OF EXPRESSION? NEXT #$FF ; MAX LENGTH STORE CHKCOM ;GET GETBYT LEN *+5 ILLQUAN LENGTH POSITION LENGTH OK LENGTH CHKCLOSE ; CLOSE PAREN #COMP TEST FRMEVL iGET EXP FRESTR #2 (DESCRPT) , Y POINT2+1 (DESCRPT) , Y POINT2 (DESCRPT),Y ;0 ILL THEN ERROR LENGTH OK1 LENGTH VARSTR
ABACUS Software
Anatomy of the 1541
880: 910: 910: 920: 940: 950: 950:
C902 C904 C906 C908 C90A C90C C90D
50
ADC STA BCC INC LDY DEY LDA
960:
C90F 91 05
STA
970: 970 : 980:
C911 CO 00 C913 DO F7 C915 4C AE A7
CPY BNE
65 85 90 E6 A4 88 B1
04 05 02 06 03 LOOP
JMP
POSITION VARSTR *+4 VARSTR+1 LENGTH (POINT1) , Y TRANSFER CHARS FROM STRING (VARSTR),Y;EXP TO VAR #0 LOOP $A7AE ;TO INTERPRETER LOOP
For those who have no monitor or assembler for the Commodore 64, we have written a loader program in BASIC.
100 FOR I = 51200 TO 51479 110 READ X : POKE T,X : S=S+X : NEXT 120 DATA 169, 13,1.60,200,141, 10, 3,140, 11, 3, 76,107 130 DATA 200,169, 0,133, 13, 32,115, 0,201, 33, 240, 6 140 DATA 32,121, 0, 76,141,174, 32,115, 0,201, 196,240 150 DATA 3, 76, 8,175, 32,115, 0, 32,250,174, 32,158 160 DATA 183,138,72,32,253,174,32,158,173,36, 13, 48 170 DATA 12, 32,170,177,165,100,208, 36,165,101, 76, 82 180 DATA 200, 32,130,183,240, 26,160, 0,177, 34, 133, 3 190 DATA 104, 32,125,180,168,240, 7,165, 3,136, 145, 98 200 DATA 208,251, 32,202,180, 76,247,174, 76, 72, 178,169
463
ABACUS Software
Anatomy of the 1541
210 DATA 118,160,200,141, 8, 3,140, 9, 3, 96, 32,115 220 DATA 0,201,202,240, 6, 32,121, 0, 76,231, 167, 32 230 DATA 115, 0, 32,250,174, 32,139,176,133,100, 132,101 240 DATA 133, 73,132, 74, 32,163,182,160, 0,177, 100, 72 250 DATA 240, 46, 32, 82,170,160, 1,177, 73,133, 5,200 260 DATA 177, 73,133, 6, 32,253,174, 32,158,183, 138,240 270 DATA 23,202,134, 4, 32,121, 0,201, 41,208, 4,169 280 DATA 255,208, 12, 32,253,174, 32,158,183,138, 208, 3 290 DATA 76, 72,178,133, 3,104, 56,229, 4,197, 3,176 300 DATA 2,133, 3, 32,247,174,169,178, 32,255, 174, 32 310 DATA 158,173, 32,163,182,160, 2,177,100,133, 81,136 320 DATA 177,100,133, 80,136,177,100,240,211,197, 3,176 330 DATA 2,133, 3,165, 5, 24,101, 4,133, 5, 144, 2 340 DATA 230, 6,164, 3,136,177, 80,145, 5,192, 0,208 350 DATA 247, 76,174,167 360 IF S 31128 THEN PRINT "ERROR IN DATA!!" END 370 SYS 51200 : PRINT "OK."
464
ABACUS Software
4.3.3
Anatomy of the 1541
Spooling - Printing Directly from the Disk
If you have a printer connected to your computer in addition to the disk drive, you can use a special characteristic of the the serial bus.
It is possible to send files directly from disk to the printer, without having to transfer it byte by byte with the computer. For example, if you have text saved as a sequential file, and you want to print it on the printer, the following program allows you to do so:
100 110 120 130 140 150
OPEN 1,4 : REM PRINTER OPEN 2,8,2, "O:TEST" : REM TEXT FILE GET#2, A$ : IF ST = 64 THEN 140 PRINT#l, A$; : GOTO 120 CLOSE 1 : CLOSE 2 END
Characters are sent from the disk to the printer until the end of file is recognized. Then the two files are closed and the program ended. The following is done when spooling: First both files are opened again. A command to receive data (Listen) is sent to the printer, while the disk drive receives the command to send data (Talk). Data are sent automatically from the disk to the printer until the end of the file is reached. During this time, the computer can be used without interferring with the transfer of data. Only the use of peripheral devices is not possible during this time. In practice, this is done with a small machine language program. When you want to start printing, you call the program and give the name of the file which you want to send.
SYS 828, "TEXT" OPENs the file TEXT on the diskette and sends it to the printer. As soon as the transfer is begun, the computer responds with READY again and you can use it, as long as no attempt is made to access the serial bus. You can prove that the computer is no longer needed for transfer by pulling out the bus cable to the disk, so that the diskette is connected only to the printer. When the spooling is done, the disk file is still open (the red LED is still lit). 465
Anatomy of the 1541
ABACUS Software
You can CLOSE the file and tum the printer off and then back on, and give the SYS command without a filename (the cable to the disk must be attached, of course). SYS 828
You can stop a transfer in progress with the same command. The machine language program in the form of a loader program for the Commodore 64 and the VIC 20 is found at the end. Here are some hints for use: We have successfully used the printer spooling with a Commodore 64 and a VIC 20 with a printer such as the the VIC 1525. Attempts using an Epson printer with a VIC interface as well as the VIC 1526 did not succeed. The serial bus, in contrast with the parallel IEEE bus, appears to be capable of spooling only with limitations. This is why it is necessary to turn the printer off after spooling, because it still blocks the bus. We would be happy if you would inform us of your experience with other printers.
;
1541 - 64 SPOOL
110: 130: 140: 142: 144: 160: 170: 175: 180:
033C 033C 033C 033C 033C 033C 033C 033C 033C
CHRGOT LISTEN ATNRES CLOCK DATA CLOSE CLALL SETFIL GETNAME
$79 $FFB1 $EDBE $EE85 $EE97 $FFC3 $FFE7 $FFBA $E254
190: 200: 202: 204: 230: 240:
033C 033C 033C 033C 033C 033C
OPEN CHKIN UNTALK UNLISTEN FNLEN INDEV
$FFCO $FFC6 $FFAB $FFAE $B7 $99
260:
033C
NMBFLS
$98
466
;ATN HI ;CLOCK HI ;DATA HI
;GET FILENAME
; INPUT DEVICE ;# OF FILES
------------
----------------
ABACUS Software
Anatomy of the 1541
280:
033C
ERROR
300: 310:
033C 033C 20 79 00
*= JSR
828 CHRGOT
320:
033F FO 33
BEQ
OFF
330: 340: 350: 360: 370: 380: 390: 400: 410:
0341 0344 0347 0349 034B 034D 034F 0351 0354
20 20 A6 FO A9 A2 AO 20 20
E7 54 B7 38 02 08 02 BA CO
JSR JSR LDX BEQ LDA LDX LDY JSR JSR
411: 412: 413: 420: 430: 432: 434: 436: 510: 510: 530: 540: 550: 560: 570: 580: 620: 630: 640 :
0357 0359 035C 035F 0361 0364 0367 036A 036D 036F 0371 0373 0374 0376 0378 037B 037E 0380 0383
A9 20 20 A2 20 20 20 20 A9 85 85 60 A9 85 20 20 A9 4C 4C
04 B1 BE 02 C6 BE 85 97 00 99 98
CLALL GETNAME FNLEN SYNTAX #2 #8 #2 SETFIL OPEN iOPEN FILE #4 LISTEN iPRINTER ATNRES #2 CHKIN iFLOPPY ATNRES CLOCK DATA #0 INDEV NMBFLS
01 98 AE AB 02 C3 08
$AF08
FF E2
FF FF FF ED FF ED EE EE
OFF FF FF FF AF SYNTAX
467
iSYNTAX ERROR iMORE CHARACTERS iSPOOLING DONE
LDA JSR JSR LDX JSR JSR JSR JSR LDA STA STA RTS LDA #1 STA NMBFLS JSR UNLISTEN JSR UNTALK LDA #2 JMP CLOSE JMP ERROR
Anatomy of the 1541
ABACUS Software
Here is the BASIC loader program for the Commodore 64. 100 FOR I = 828 TO 901 110 READ X : POKE I,X : S=S+X : NEXT 120 DATA 32,121, 0,240,51,32,231,255,32,84, 226,166 130 DATA 183,240, 56,169, 2,162, 8,160, 2, 32, 186,255 140 DATA 32,192,255,169, 4, 32,177,255, 32,190, 237,162 150 DATA 2, 32,198,255, 32,190,237, 32,133,238, 32,151 160 DATA 238,169, 0,133,153,133,152, 96,169, 1, 133,152 170 DATA 32,174,255, 32,171,255,169, 2, 76,195, 255, 76 180 DATA 8,175 190 IF S 9598 THEN PRINT "ERROR IN DATA! !":END 200 PRINT "OK" Use the following loader program for the VIC 20. 100 FOR I = 828 to 901 110 READ X : POKE I,X : S=S+X : NEXT 120 DATA 32,121, 0,240, 51, 32,231,255, 32,81, 226,166 130 DATA 183,240, 56,169, 2,162, 8,160, 2,32, 186,255 140 DATA 32,192,255,169, 4, 32,177,255, 32,197, 238,162 150 DATA 2, 32,198,255, 32,197,238, 32,132,239, 32,160 160 DATA 228,169, 0,133,153,133,152, 96,169, 1, 133,152 170 DATA 32,174,255, 32,171,255,169, 2, 76,195, 255, 76 180 DATA 8,207 190 IF S9642 THEN PRINT "ERROR IN DATA! !":END 200 PRINT "OK"
468
ABACUS Software
Anatomy of the 1541
4.4 Overlay Technique and Chaining Machine Language Programs A proven programming technique involves the creation of a menu program which then loads and executes other programs based on the user's choice. There are two variations: preserving or clearing the old variables in the chained program. It is possible to pass the old variables if the calling program is as large or larger than the chained program. If one program is chained from another program, the pointer to the end of the previous program remains intact, and the new program loads over the old. In this example, we would get the following result:
100 REM PROGRAM 1 110 REM THIS PROGRAM IS LARGER THAN THE SECOND 120 A = 1000 130 LOAD "PROGRAM 2",8 100 REM PROGRAM 2 110 PRINT A 1000
If the chained program is larger than the original program, part of the variables are overwritten and contain meaningless values. Moreover, when the variables that the program destroyed are assigned new values, part of the program is also destroyed. There are two characteristics of passing variables from the previous program that should be noted--for strings and for functions. Any string variables that are defined as constants enclosed in quotes in the fIrst program will have a problem. The string variable pointer points to the actual text in the program. If, for example, a string is defined in the first program with the following assignment
100 A$ = "TEXT"
469
ABACUS Software
Anatomy of the 1541
the variable pointer points to the actual text within line number 100. When chaining, the next program does not change this pointer. New text is now at the original location, so the variable has unpredictable contents. We can easily work around this, however. We need only ensure that the text is copied from the program into string storage where text variables are normally stored. You can do this as follows:
100 A$ = "TEXT" + "" By concatenating an empty string, you force the contents of the variable to be copied to the string storage area. Similar considerations apply to function definitions, because here also the pointer points to the definition within the program. Here you must define the function again in the second program, for example:
100 DEF FN A(X) = 0.5 * EXP (-X*X) If you want to chain a program, you can continue to use the old variables provided the second program is not longer than the first. If the chained program is longer, and we do not want to preserve the old variables, there is a trick we can use. We need only set the end-of-program pointer to the end of the new program immediately after loading. This can be done with a pair of POKE commands:
POKE 45, PEEK(174) : POKE 46, PEEK (175) : CLR The CLR command is absolutely necessary. This line should be the first line in the chained program. This allows us to chain a large program without transfer of variables. Another, not so elegant, method involves writing the load command in the keyboard buffer so the program will automatically be loaded in the direct mode. To do this, we write the LOAD and RUN commands on the screen and fill the keyboard buffer with "HOME" and carriage returns. An END statement must come after this in the program. The operating system then gets the contents of the keyboard buffer in the direct mode and reads the LOAD and RUN commands that control the loading and execution of the program. Because this occurs in the direct mode, the end address of the program is automatically set, the variables are erased and the program is started with the RUN. The disadvantage of this method is that since the LOAD command must appear on the video screen, a.1'}y display will be destroyed. In practice it looks like this:
470
ABACUS Software
Anatomy of the 1541
1000 PRINT CHR$ (147) "LOAD " CHR$ (34) "PROGRAM 2" CHR$(34)",8" 1010 PRINT : PRINT : PRINT : PRINT 1020 PRINT "RUN" 1030 POKE 631,19 POKE 632,13 POKE 633,13 1040 POKE 634,13 POKE 635,13 POKE 636,13 1050 POKE 198,6 END You can see that this procedure is more complicated than the previous one; it is only mentioned for the sake of completeness. With the first procedure, only the LOAD command need be programmed in line 1000:
1000 LOAD "PROGRAM 2",8 There is another technique for chaining machine language programs. If a machine language program is to be used from a BASIC program, it must usually be loaded at the beginning of the BASIC program. You must take note of two things: First of all, you must make sure that the machine language program loads to a specific place in memory. If you load a program without additional parameters, the control system treats it as a BASIC program and loads it at the starting address of the BASIC RAM, generally at 2049 (Commodore 64). Machine language programs can only be run, however, when they are loaded at the address for which they were written. This absolute loading can be accomplished by adding the secondary address I:
LOAD "MACH-PRG" ,8,1 But remember that when loading a program from within another program, BASIC attempts to RUN the program from the beginning. This leads to an endless loop when loading machine language programs, because the operating system thinks that a new BASIC program has been chained:
100 LOAD "MACH-PRG" ,8,1 Here we can make use of the fact that the variables are preserved when chaining. If we program the following, we have reached our goal:
471
ABACUS Software
Anatomy of the 1541
100 IF A=O THEN A=l : LOAD "MACH-PRG" ,8,1 110 ... When the program is started with RUN, A has the value zero and the assignment after the THEN is executed, A contains the value 1 and the machine language program is then LOADed. When the program begins again after LOADing the program MACH-PRG, A has the value 1 so the next line is executed. The procedure is similar if you have several machine language programs to load.
100 IF A=O THEN A=l : LOAD" PROG 1" ,8,1 110 IF A=l THEN A=2 : LOAD" PROG 2" ,8,1 120 IF A=2 THEN A=3 : LOAD "PROG 3" ,8,1 130 .... The first time through, PROG 1 will be loaded, the next time, PROG 2, and so on. Once all the programs are loaded, execution continues with line 130.
472
ABACUS Software
4.5
Anatomy of the 1541
Merge - Appending BASIC Programs
Certainly you have thought about the possibility of combining two separate BASIC programs into one. This is not possible without some work because loading the second program would overwrite the first. With the knowledge of how BASIC programs are stored in memory and on the diskette, we can develop a simple procedure to accomplish this task. BASIC programs are stored in memory as follows:
NLNH LLLH XXYYZZ
00
pointer to the next program line, 10 hi line number, 10 hi ..... tokenized BASIC statements end-of-Iine marker
At the end of the program are two additional zero bytes: 00 00 for a total of 3 zero bytes Programs are also saved in this format. Where the program starts and ends lies in two pointers in page zero:
PRINT PEEK(43) + 256
* PEEK(44)
gives the start of BASIC, 2049 for the Commodore 64,
PRINT PEEK(45) + 256
* PEEK(46)
points to the byte behind the three zero bytes. Because a program is always loaded at the start of the BASIC storage area, contained in the pointer at 43/44, one can cause a second program to load at the end of the first. In practice, we must proceed as follows: First we load the fIrst program into memory.
LOAD "PROGRAM 1",8 Now get the value of the ending address of the program.
A = PEEK(45) + 256 * PEEK(46)
473
ABACUS Software
Anatomy of the 1541
This value is decremented by two so that the two zero bytes at the end of the program will be overwritten later.
A=A-2 Now, note the original value of the start of BASIC.
PRINT PEEK(43), PEEK(44) Next, set the start of BASIC to this value.
POKE 43,(A AND 255): POKE 44, A / 256 Now, LOAD the second program.
LOAD "PROGRAM 2",8 If you set the start of BASIC back to the original value, 1 and 8 for the Commodore 64 (as shown above with the PRINT commands), you have the complete program in memory and can view it with LIST or save it with SAVE.
POKE 43,1: POKE 44,8 The following should be noted when using this method: The appended program may contain only line numbers which are greater than the largest line number of the first program. Otherwise these line numbers can never be accessed with OOTO or OOSUB and the proper program order cannot be guaranteed. This procedure is especially well suited for constructing a subroutine library for often-used routines, so they need not be typed in each time. It will work out best if you reserve specific line numbers for the subroutines, such as 20000- 25000, 25000-30000, and so on. If you want to merge several programs in this manner, you must first load the program with smallest line numbers, and then the program with the next highest numbers, etc.
474
ABACUS Software
Anatomy of the 1541
4.6 Disk Monitor for the Commodore 64 and VIC 20 In this section we present a very useful tool for working with your disk drive, allowing you to load, display, modify, and save desired blocks on the diskette. For reasons of speed, the program is written entirely in machine language. The following commands are supported:
* * * * * * *
Read a block from the disk Write a block to the disk Display a block on the screen Edit a block on the screen Send disk commands Display disk error messages Return to BASIC
The program announces its execution (automatically by the BASIC load program) with
DISK-MONITOR Vl.O >
and waits for your input. If you enter '@', the error message from the disk will be displayed, for example
00, OK,OO,OO If you want to send a command to the disk, enter an '@' followed by the command.
You can initialize a diskette with >@I
You can send complete disk commands in this manner, commands that you would otherwise send with
OPEN 15,8,15 PRINT# 15,"command" CLOSE 15
475
ABACUS Software
Anatomy of the 1541
For example, you can erase files, format disks, and so on. The most important function of the disk monitor is the direct access of any block on the diskette. For this you use the commands Rand W. R stands for READ and reads a desired block, W stands for WRITE and writes a block to the disk. You need only specify the track and sector you want to read. These must be given in hexadecimal, exactly as the output is given on the screen. If, for example, you want to read track 18, sector 1 (the first directory block), enter the following command: >R 1201
Each input must be given as a two-digit hex number, separated from each other with a blank. In order to display the block, use the command M. We receive the following output: DISK-MONITOR >M >:00 12 04 82 >: 08 46 49 4B >:10 53 52 43 >: 18 00 00 00 >:20 00 00 82 >:28 4F 54 2E >:30 AO AO AO >:38 00 00 00 >: 40 00 00 82 >: 48 4F 54 2E >:50 AO AO AO >:58 00 00 00 >:60 00 00 P2 >:68 2E 53 52 >: 70 AO AO AO >:78 00 00 00 >:80 00 00 82 >:88 2E 4F 42 >:90 AO AO AO >:98 00 00 00 >:AO 00 00 82 >:A8 50 2E 53
V1.0 11 20 AO 00 13 53 AO 00 13 53 AO 00 13 43 AO 00 13 4A AO 00 10 52
01 41 AO 00 00 52 AO 00 03 52 AO 00 09 AO AO 00 08 AO AO 00 00 43
47 49 00 00 48 43 00 00 56 43 00 00 4D AO 00 00 4D AO 00 00 53 AO
52 44 00 15 50 AO 00 05 50 AO 00 09 45 AO 00 06 45 AO 00 01 57 AO
41 2E 00 00 4C AO 00 00 4C AO 00 00 4D AO 00 00 4D AO 00 00 41 AO
476
· . . . . GRA
FIK AID. SRC
·....... · . . . . HPL
OT.SRC
·....... · . . . . VPL
OT.SRC
·....... · ..•• MEM
.SRC
·....... · .... MEM .OBJ
·.... ... · .... SWA P.SRC
ABACUS Software
>:BO >:B8 >:cO >:C8 >:DO >:D8 >:EO >:E8 >:FO >:F8
AO 00 00 52 AO 00 00 53 AO 00
AO 00 00 49 AO 00 00 53 AO 00
AO 00 82 58 AO 00 82 2E AO 00
Anatomy of the 1541
AO 00 10 2E AO 00 13 54 AO 00
AO 00 01 53 AO 00 OC 45 AO 00
00 00 4D 52 00 00 47 53 00 00
00 04 41 43 00 00 41 54 00 01
00 00 54 AO 00 00 55 AO 00 00
· ... . . . . · .... MAT RIX.SRC
·....... · .... GAU SS.TEST
·.. .....
Let's take a closer look at the output. The first hex number after the colon gives the address of the following 8 bytes in the block, 00 indicates the first byte in the block (the numbering goes from 00 to FF (0-255». 8 bytes follow the address (4 on the VIC 20). In the right half are the corresponding ASCII characters. If the code is not printable ($00 to $lF and $80 to $9F), a period is printed. When you give the command M, as above, the entire block is displayed. Because the block does not fit on the screen completely, it is possible to display only part of it. You can give an address range that you would like to display. If you only want to see the first half, enter:
>M007F The second half with:
>M80FF With the VIC 20, you can view quarters of the block. If you now wish to change some data, you simply move the cursor to the corresponding place, overwrite the appropriate byte, and press RETURN. The new value is now stored and the right half is updated with the proper ASCII character. To write the modified block back to the diskette, you use the command W. Here also you must give the track and sector numbers in hexadecimal.
>W 12 01 writes the block back to track 18, sector 1, from where we had read the block previously.
477
ABACUS Software
Anatomy of the 1541
If you want to get back to BASIC, enter X and the computer will respond with READY .. If you then want to use the disk monitor again, you need not reload it. Just type SYS 49152 for the C64 or SYS 6690 for the VIC 20. A warning: Be sure to make a copy of any diskette that you work with in this way. Should you make an error when editing or writing a block, you can destroy important information on the disk so that it can no longer be used in the normal manner. You should make it a rule to work only with a copy. Here you find an assembler listing of the program. After this are the BASIC loader programs for the Commodore 64 and VIC 20. ; ;
disk monitor vic 20 / cbm 64
190: 200:
COOO COOO
PROMPT NCMDS
210: 220: 230: 240: 250: 260: 270: 280: 290: 300: 310: 320: 330: 340: 350: 360: 370: 380: 390: 400:
COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO
INPUT TALK SECTALK IEEE IN UNTALK LISTEN SECLIST IEEEOUT UNLIST WRITE OPEN CLOSE SETPAR SETNAM CHKIN CKOUT CLRCH CR QUOTE QUOTFLG
478
,.>,.
6 NUMBER OF COMMANDS $FFCF $FFB4 $FF96 $FFA5 $FFAB $FFB1 $FF93 $FFA8 $FFAE $FFD2 $FFCO $FFC3 $FFBA $FFBD $FFC6 $FFC9 $FFCC 13 $22 $D4
ABACUS Software
Anatomy of the 1541
410:
0200
420: 430: 440: 450: 460: 470: 480:
0201 0202 0203 0204 0205 0205 0205
SAVX WRAP BAD FROM TO STATUS SA
490:
0205
FA
500:
0205
FNADR
510:
0205
FNLEN
520: 610:
0205 COOO
TMPC COUNT
620 :
COOO
READY
630: 640: 650: 660: 670: 680: 690: 700: 710: 710: 710: 720:
COOO C002 C005 C008 C009 COOB COOD COOF C011 C014 C016 C019
730: 740: 750:
C01C C9 3E COlE FO F9 C020 C9 20
760: 770:
C022 FO F5 C024 A2 05
*=
A2 BD 20 E8 EO DO A2 A9 20 A9 8D 20
INIT 00 85 C2 MSGOUT D2 FF 12 F5 OD START 3E EB CO 00 01 02 33 C1 ST1
SO
479
$200 BASIC INPUT BUFFER .BYT 0 .BYT 0 .BYT 0 .BYT 0 .BYT 0 $90 $B9 SECONDARY ADDRESS $BA DEVICE # $BB FILENAME ADR $B7 ;LEN OF FILENAME $97 ;# OF BYTES 8 PER LINE $E37B ; $E467 FOR VIC LDX #0 LDA MESSAGE, X JSR WRITE INX CPX #ASCDMP-MESSAGE BNE MSGOUT LDX #CR LDA #PROMPT JSR WRTWHR LDA #0 STA WRAP JSR RDOC ; READ INPUT LINE CMP #PROMPT BEQ ST1 CMP #" " ; READ OVER BLANK BEQ ST1 LDX #NCMDS-1 COMPARE WITH COMMAND TABLE
Anatomy of the 1541
ABACUS Software
780: 790: 800:
C026 DD 6A CO Sl C029 DO OC C02B 8E 00 02
CMP BNE STX
840: 850:
C02E BD 70 CO C031 48
LDA PHA
860: 870: 880: 890: 900:
C032 C035 C036 C037 C038
910:
C03A 4C OD CO
LDA PHA RTS DEX BPL
BD 76 CO 48 60 S2 CA 10 EC
960: 970: 980:
C03D 85 97 C03F 20 62 CO C042 B9 EO C2
990: 1000: 1000: 1000: 1010: 1020: 1030:
C045 C048 C049 C04B C04E C050 C052
1060: 1070:
C053 20 FE CO C056 90 03
1080:
C058 99 EO C2
1090: 1100: 1110: 1120: 1130: 1140: 1150: 1160:
C05B C05C C05E C05F C062 C064 C065 C067
20 C8 DO EE C6 DO 60
C8 C6 60 20 A9 2C A9 4C
DC CO 03 01 02 97 ED
97 62 CO 20 OD D2 FF
JMP
CMDS,X S2 SAVX ;# OF CMDS IN TABLE ADRH,X ; JUMP ADDR TO STACK ADRL,X
;LOOP OF ALL CMDS
Sl START
SUBROUTINE TO DISPLAY THE DISK CONTENTS STA TMPC DM JSR SPACE DM1 LDA BUFFER,Y ;GET BYTE FROM BUFFER JSR WROB INY BNE DM2 INC WRAP DM2 DEC TMPC BNE DM1 RTS READ BYTES AND WRITE TO MEMORY BYT JSR RDOB BCC BY3 BLANK? STA BUFFER,Y WRITE BYTE IN BUFFER INY BY3 DEC TMPC RTS JSR SPACE SPAC2 SPACE LDA #" BYT $2C LDA #CR CRLF JMP WRITE II
480
ABACUS Software
Anatomy of the 1541
1190:
C06A 3A
1200:
C06B 57
1210:
C06C 52
1220:
C06D 4D
1230:
C06E 40
1240: 1250: 1260: 1270: 1280: 1290 : 1300: 1310: 1320: 1330: 1340: 1350: 1360: 1370: 1380: 1370: 1370: 1370: 1370: 1370: 1380:
C06F C070 C071 C072 C073 C074 C075 C076 C077 C078 C079 C07A C07B C07C C07E C081 C082 C085 C088 C08A C08C
58 CO C1 C1 CO C1 E3 CO 90 90 7B 3E 7A AO 8C 88 8C 20 C9 FO 20
04 02 CF FF OD 17 FE CO
1390: 1400: 1410: 1410: 1410: 1420:
C08F C091 C094 C097 C099 C09B
90 8D 20 C9 FO 20
12 03 02 CF FF OD 08 FE CO
1430:
C09E 90 03
00 03 02
COMMAND AND ADDRESS TABLE CMDS .ASC ' . , ;EDIT MEM CONTENTS .ASC 'w' ;WRITE BLOCK .ASC 'R' ; READ BLOCK ;DISLPAY .ASC 'M' BYTES .ASC '@ , ;DISK COMMAND .ASC 'x' ;EXIT ADRH .BYT >ALTM-1 .BYT >DIRECT-1 .BYT >DIRECT-1 .BYT >DSPLYM-1 .BYT >DISK-1 .BYT >READY-1 .BYT