The_Anatomy_of_the_1541_Disk_Drive_Jun84 The Anatomy Of 1541 Disk Drive Jun84
The_Anatomy_of_the_1541_Disk_Drive_Jun84 The_Anatomy_of_the_1541_Disk_Drive_Jun84
User Manual: The_Anatomy_of_the_1541_Disk_Drive_Jun84
Open the PDF directly: View PDF .
Page Count: 336
Download | |
Open PDF In Browser | View PDF |
THE ANATOMY OF THE 1541 DISK DRIVE A Complete Guide to Using The Commodore Disk Drive Authors: Lothar Eng1isch Norbert Szczepanowski Edited by: Greg Dykema Arnie Lee ABACUS SOFTWARE P.O. BOX 7211 GRAND RAPIDS, MI 49510 Second English printing, June 1984 Printed in U.S.A Copyright (C)1983 Data Becker GrngH Merowingerstr. 30 4000 Dusseldorf W. Germany Copyright (C)1984 Abacus Software 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, photocopying, recording, or otherwise, without the prior written permission of ABACUS Software, Inc. ISBN 0-916439-01-1 PREFACE The VIC-154l disk drive represents a very efficient external storage medium for the Commodore user. It is an affordable peripheral. In order to get the most from your 1541, you need the appropriate information. In months of long, detailed work, Lothar Englisch and Norbert Szczepanowski have discovered many secrets of the 1541. This book progresses from simple storage techniques, to direct access commands , to program chaining techniques. Beginners will welcome the nUmerous sample programs that are fully explained in clear text. Machine language programmers will particularly like the detailed documentation listing of the Disk Operating System (005). This book contains many useful and ready-to-run programs that need only be typed in. Some of these programs are: routines for extending BASIC, helpful routines such as spooling, efficient address management, a complete household budget planner and an easy-to-use DOS monitor to manipulate individual sectors. Have fun with this book and your VIC1541 disk drive. TABLE OF CONTENTS Chapter 1: programming the VIC-1541 •••••••••••••••••••••••• 1 1.1 Getting Started •••••••••••••••••••••••••••••••••••••••• l 1.1.1 The Disk Operating System ••••••••••••••••••••••• l 1.1.2 The TEST/DEMO Diskette •••••••••••••••••••••••••• 2 1.1.3 Formatting New Diskettes •••••••••••••••••••••••• 2 1.1.4 Some Facts about a 1541 Diskette •••••••••••••••• 3 1.2 Storing Programs on Diskette ••••••••••••••••••••••••••• 4 1.2.1 SAVE - Storing BASIC Programs ••••••••••••••••••• 4 1.2.2 LOAD - Loading BASIC Programs ••••••••••••••••••• 4 1.2.3 VERIFY - Checking Stored prograros ••••••••••••••• 5 1.2.4 SAVE "@: ..... Replacing Prograros ••••••••••••••••• 5 1.2.5 Loading Machine Language Programs ••••••••••••••• 6 1.2.6 Storing Machine Language Programs ••••••••••••••• 7 1.3 Disk System Commands •••••••••••••••••••••••••••••••••• l0 1.3.1 Transmitting Commands to the Disk Drive •••••••• 10 1.3.2 NEW - Formatting Diskettes ••••••••••••••••••••• 11 1.3.3 Reading the Error Channel •••••••••••••••••••••• 12 1.3.4 LOAD "$",8 Loading the Directory •••••••••••••• 13 1.3.5 SCRATCH - Deleting Files ••••••••••••••••••••••• 14 1.3.6 RENAME - Renaming Files •••••••••••••••••••••••• 15 1.3.7 COpy - Copying Files ••••••••••••••••••••••••••• 16 1.3.8 INITIALIZE - Intitializing the Diskette •••••••• 16 1.3.9 VALIDATE - "Cleaning up· the Diskette •••••••••• 17 1.3.10 ? * - The Wildcards ••••••••••••••••••••••••••• 18 1.4 Sequential Data Storage ••••••••••••••••••••••••••••••• 20 1.4.1 The principle •••••••••••••••••••••••••••••••••• 20 1.4.2 OPENing a Sequential File •••••••••••••••••••••• 21 1.4.3 Transferring Data between Disk and Computer •••• 24 1.4.4 Adding Data to Sequential Files •••••••••••••••• 27 1.4.5 CLOSEing a sequential File ••••••••••••••••••••• 28 1.4.6 Redirecting the Screen Output ••••••••••••••• ·••• 29 1.4.7 Sequential Files as Tables in the Computer ••••• 30 1.4.8 Searching Tables ••••••••••••••••••••••••••• ~ ••• 32 1.4.9 Simple sorting of Tables ••••••••••••••••••••••• 35 1.4.10 Mailing List Management with Sequential Data Storage •••••••••••••••••••••••••••••••• 38 1.4.11 Uses for Sequential Storage •••••••••••••••••••• 45 1.5 Relative Data Storage ••••••••••••••••••••••••••••••••• 46 1.5.1 The Principle •••••••••••••••••••••••••••••••••• 46 1.5.2 The Advantage over Sequential Storage •••••••••• 47 1.5.3 OPENing a Relative File •••••••••••••••••••••••• 47 1.5.4 Preparing the Data for Relative Storage •••••••• 50 1.5.5 Transferring Data •••••••••••••••••••••••••••••• 52 1.5.6 CLOSEing a Relative File ••••••••••••••••••••••• 55 1.5.7 Searching Records with the Binary Method ••••••• 55 1.5.8 Searching Records with a Separate Index File ••• 58 1.5.9 Changing Records ••••••••••••••••••••••••••••••• 61 1.5.10 Expanding a Relative File •••••••••••••••••••••• 62 1.5.11 Home Accounting with Relative Data Storage ••••• 64 1.6 Disk Error Messages and their Causes •••••••••••••••••• 72 1.7 Overview of Commands with a Comparison of BASIC 2.0 - BASIC 4.0 - OOS 5.1 •••••••••••••••••••• 77 Chapter 2: Advanced Programming ••••••••••••••••••••••••••• 82 2.1 The Direct Access of any Block of the Diskette •••••••• 82 2.2 The Di rect 2.2.1 The 2.2.2 The 2.2.3 The 2.2.4 The 2.2.5 The 2.2.6 The Access Commands ••••••••••••••••.••••••••••• 86 Block-Read Command ••••••••••••••••••••••••• 86 Block-Pointer Command •••••••••••••••••••••• 87 Block-Write Command •••••••••••••••••••••••• 88 Block-Allocate Command ••••••••••••••••••••• 89 Block-Free Command ••••••••••••••••••••••••• 90 Block-Execute Command •••••••••••••••••••••• 91 2.3 Uses of Di rect Access ••••••.•••••••••••••••••••••••••• 92 2.4 Accessing the DOS - The Memory Commands ••••••••••••••• 94 2.4.1 The Memory-Read Command •••••••••••••••••••••••• 94 2.4.2 The Memory-Write Command ••••••••••••••••••••••• 95 2.4.3 The Memory-Execute Command ••••••••••••••••••••• 96 2.4.4 The User Commands •••••••••••••••••••••••••••••• 97 Chapter 3: Technical Information •••••••••••••••••••••••••• 99 3.1 The Construction the VIC-154l ••••••••••••••.•••••••••• 99 3.1.1 Block Diagram of the Disk Drive •••••••••••••••• 99 3.1.2 DOS Memory Map - ROM, RAM, 1/0 •••••••••••••••• 100 3.2 Operation of the DOS - An Overview •••••••••.••••••••• l04 3.3 The Structure of the Diskette •••••••••••••••••••••••• 106 3.3.1 The BAM of the VIC 1541 ••••••••••••••••••••••• 106 3.3.2 The Directory ••••••••••••••••••••••••••••••••• l07 3.3.3 The Directory Format •••••••••••••••••••••••••• l09 3.4 The Organization of Relative Files ••••••••••••••••••• 114 3.5 OOS 2.6 Rom Listings ••••••••••••••••••••••••••••••••• 118 Chapter 4: Programs and Tips For utilization of the VIC-154l ••••••••••••••••••••••••.••••••• 269 4.1 Utility Programs ••••••••••••••••••••••••••••••••••••• 269 4.1.1 Displaying all File Parameters •••••••••••••••• 269 4.1.2 Scratch-protect Files - File Protect ••.••••••• 273 4.1.3 Backup Program - Copying a Diskette ••••••••••• 278 4.1.4 Copying Individual Files to another Diskette •• 280 4.1.5 Reading the Directory from within a program ••• 281 4.2 The Utility Programs on the TEST/DEMO Disk, •••••••••• 283 4.2 .1 008 5.1 •••.•••••••••••••••••••••••••.••••••••• 283 4.2.2 COPY/ALL •••••••••••••••••••••••••••••••••••••• 284 4.2.3 DISK ADDR CHANGE •••••••••••••••••••••••••••••• 284 4.2.4 DIR ••••.•••••••••••••.•••••••••••••••••••••••• 2fS 4.2.5 VIEW BAM •••••••••••••••••••••••••••••••••••••• 285 4.2.6 CHECK D1 SK •••••••••••••••••••••••••••••••••••• 285 4.2.7 DISPLAY T&S ••••••••••••••••••••••••••••••••••• 286 4.2.8 PERFORMANCE TEST •••••••••••••••••••••••••••••• 286 4.3 BASIC-Expansion and Programs for Easy Use of the 1541 •••••••••••••••••••••••••• 287 4.3.1 Input strings of desired Length from the Disk.287 4.3.2 Easy preparation of Data Records •••••••••••••• 290 4.3.3 Spooling - Printing Directly from the Disk •••• 295 4.4 OVerlay Technique and Chaining Machine Language Programs ••••••••••••••••••••• 299 4.5 Merge - Appending BASIC Programs ••••••••••••••••••••• 302 4.6 Disk-Monitor for Commodore 64 and VIC 20 ••••••••••••• 304 Chapter 5: The Larger CBM Disks •••••••••••••••••••••••••• 317 5.1 IEEE-Bus and Serial Bus •••••••••••••••••••••••••••••• 317 5.2 Comparison of all CBM Disk Drives •••••••••••••••••••• 319 Anatomy of the 1541 Disk Drive Chapter 1: programming the VIC-154l 1.1 Getting Started There it sits, your new Commodore VIC-154l 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-l54l. 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, when you understand the "basics". The beginner probably uses the disk drive mainly to store programs. perhaps he has not realized that there are many other ways to use the disk drive. 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 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 drive, it sends commands to the disk drive along the heavy black cable that connects the drive to the computer. The commands sent by the Commodore 64 or VIC-20 are understood at the disk drive by a by a built in program called the Disk Operating System (DOS). The DOS is a lengthy program contained on ROM in the disk drive and carries out the activities of the disk drive as commanded by the Commodore 64 or VIC-20. The version of DOS contained in the VIC-154l carries the designation CBM DOS V2.6. The Commodore 64 and VIC-20 contain a version of BASIC called COMMODORE BASIC 2.0. Other versions of BASIC (e.g. BASIC 4.0 found of the Commodore 8032) have more advanced disk commands which the VIC-l54l can also understand. In order to use these advanced disk commands, you have to sil11ulate them using BASIC 2.0. At the end of the chapter is a listing of the BASIC 2.0 1 Anatomy .of the 1541 Disk Drive commands with corresponding commands of the easier BASIC 4.0, as found on the larger Commodore computers. 1.1.2 The TEST/DEMO Diskette The VIC-l54l disk drive is packaged with a diskette called TEST/DEMO. Some of the programs contained on it cannot he used without adequate knowledge of the way the disk drive works. For now, lay this diskette aside. The TEST/DEMO diskette is described in detail later. 1.1.3 Formatting New Diskettes Brand new diskettes must be prepared before using them to store data. Preparing them is called formatting. what does formatting mean? Each disk drive mechanism has its own special characteristics. A diskette is divided into tracks and information is written along each track (similar to the grooves of a phonographic record). The number of tracks per diskette is varies from one manufacturer to another. Each track is divided into sectors, whose number can also vary. During formatting empty sectors are written to the diskette. A sector is written to each track and sector location and each sector receives its own "address". This allows the DOS to identify its position on the diskette. A sector is also given a code so that the DOS can recognize if this diskette was formatted by this type of disk drive. The code for the VIC-154l disk drive is 2A. The remainder of the sector (called a block) is used to store data and accommodates exactly 256 characters. The final purpose of formatting is to construct the directory for the diskette. The directory is a "table of contents· of the files stored on the diskette. There is also a special data block (called the bit availability map or BAM) which indicates if a given block on the diskette is already in use or available for use. The directory and BAM are kept on track 18 of the diskette. 2 Anatomy of the 1541 Disk Drive 1.1.4 Some Pacts about a 1541 Diskette Diskette: 35 17 to 21 (depending on track) 256 683 644 (the directory occupies the remainder) 144 per diskette Number of Tracks: Sectors per Track: Bytes per block: Total number of blocks: Number of free blocks Entries in the directory: 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) 3 Anatomy of the 1541 Disk Drive 1.2 Storing Programs on Diskette The most common use of the disk drive is for storage of programs. storing programs with a disk drive is considerably easier than with a cassette recorder. The greatest advantage of the disk drive is the speed of 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-154l disk drive An additional advantage is that a diskette can store more programs than the cassette. To load a program, you can consult the directory to view the selection of programs. Even though the cassette drive allows you to store more than one program on a tape, searching for that program is very time consuming. Before trying any of the following examples in this chapter, you should remember that the diskette must be previously formatted as explained in section 1.3.2 in order to be able to save programs onto it. 1.2.1 SAVE - Storing BASIC Programs Perhaps you previously owned a datasette on which you stored programs. In this case the commands to save programs onto diskette should be familiar to you. The SAVE command for the disk drive is essentially 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 command SAVE. Normally the drive is preset to respond to this device number. Now write a small BASIC program and save it with the command: type in a the NEW command so the program in the computer's memory is erased. In the following section you will learn how the program can be retrieved. 1.2.2 LOAD - Loading BASIC Programs AS with the SAVE command, this command is similar to the LOAD command for the datasette with the addition of the device number. NOW load in the previously saved program with: 4 Anatomy of the 1541 Disk Drive You can check the program by using the LIST command. Any previous program in memory has now been replaced by the program "TEST". It is possible to load a program into the memory without replacing the previous program in memory. Combining two program in memory is called "merging" An example of merging is presented in a later section. 1.2.3 VERIFY - Checking Stored Programs When you have saved a program on disk with the SAVE command, it is often desirable to make sure that the program was written error-free. You can do this by using the VERIFY command. It has the following format: Earlier you saved a program with SAVE -TEST-,8. This program should still be in memory. Using VERIFY, the program 1n memory is checked against the program stored on diskette. If both programs are identical, the computer responds with OK. To try this out, type a few BASIC lines and then give the following commands: SAVE ·TEST2-,8 VERIFY ·TEST2·,8 Your computer will respond with OK if it is performing correctly. 1.2.4 SAVE·@: ••• • - Replacing Programs If you try to save your small TEST program on the disk again, the computer will respond with a FILE EXISTS error and will not complete the SAVE. The operating system of ehe VIC-154l disk drive does not allow two programs to be saved under the same name. This is logical because the computer would not be able to distinguish between two programs with the same name. However you may want to update a program on diskette that was previously saved. There are three ways to accomplish this: 1. Save the program under a different name 2. First erase the old program from the disk and save tte new one under the old name 5 Anatomy of the 1541 Disk Drive 3. Use the addition @: in front of the file name in the SAVE command This is used as follows: SAVE-@:TEST-,8 If you forget to use the characters @: in front of the filename, and try to save a program whose name is already contained on the diskette, you get the FILE EXISTS error. If you are ieplacing a program on a diskette then the DOS carries this out as follows: 1. A free block is designated as the first block of the program 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. All of the 1.2.5 blocks of the old copy are marked as free. Loading Machine Language Programs Machine language programs are handled a little differently from BASIC programs. A machine language program is transferred to the computer by using a secondary address of 1. When secondary address 1 is used, the program is loaded "absolutely", that is, loaded into memory beginning at the address specified in the first two bytes of the disk file. An example: loads the machIne language program at an absolute address. For example, the program may he set up to load at the decimal address 49152, and is started by the command: SYS 49152. Should you load a machine language program without the secondary address, you will most likely 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. Roth 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 a machine language program. In this case it must be loaded with the command LOAD ·program-,8,1. It cannot be 6 Anatomy of the 1541 Disk Drive started with RUN however! address of this program. You must first find the execution In a later section is a program that lists all the file parameters of a program. One of the parameters is a load address. This load address is usually the initial execution address of the program and can be called with the command 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,"programname,S,R" GET#l,X$:IF X$='"' THEN X$=CHR$(O) LB=ASC(X$) GET#l,X$:IF X$="n THEN X$=CHR$(O) HB=ASC(X$) CLOSE 1 AD=HB*256+LB PRINT"LOAD ADDRESS:":AD The program shows the load address of "programname". Here the program file is opened as a sequential data file. The starting address is stored as the first two bytes of the file and read using the GET command 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 program is unclear, handling sequential files clarified in the next sections. 1.2.6 Storing Machine Language Programs Machine language programs are usually written with an assembler or a machine language monitor and saved using this program. Machine language programs can also be written from BASIC with the individual bytes of the program written in decimal values in DATA statements. A machine language program written in BASIC with the help of DATA statements follows: 10 20 30 40 50 60 80 90 SA=starting address EA=ending address FOR I=SA TO EA READ X POKE I,PEEK(X) NEXT I DATA •••••••••••••••••••••••••••••••••••• DATA •••••••••••••••••••••••••••••••••••• In this example, the decimal value of the starting address is placed in line 10 and the ending address fn line 20. The decimal values of the individual bytes of the machine language program are typed into the DATA statements of the 7 Anatomy of the 1541 Disk Drive program, separated by commas. Naturally, you can save any machine language program that you find in this book in the form of a BASIC program. This is, however, a tedious and complicated process. A more elegant and time-saving method is to store the machine language program in true form. This way, you can immediately execute the program after LOADing without requiring any complicated conversion. The following program will save such a program that already in memory: 10 20 30 40 50 60 70 80 90 is SA=starting address EA=ending address OPEN 1,8,1,"programname" HB=INT(SA/256):LB=SA-HB*256 PRINT#l,CHR$(LB);CHR$(HB); FOR I=SA TO EA PRINT#l,CHR$(PEEK(I»; NEXT I CLOSE 1 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 machine language program: 10 SA=starting address 20 EA=ending address 30 OPEN 1,8,1,"programname" 40 HB=INT(SA/256):LB=SA-HB*256 50 PRINT#l,CHR$(LB);CHR$(HB); 60 FOR I=SA TO EA 70 READ X 80 PRINT#I,CHR$(X); 90 NEXT I 100 CLOSE 1 110 DATA •••••••••••••••••••.••••.• 120 DATA •••••••••••••••••••••••••• Here the addresses and DATA statements are filled in also. The above program writes a machine language program to diskette which can later be loaded with the command LOAD ·programname-,8,1. Then the program can be executed with the command: SYS (starting address). Machine language programs can also be loaded and executed from a BASIC program. Such a program might have this form: 10 IF A=O THEN A=l:LOAD"programname" ,8,1 20 SYS (starting address) The IF command in line 10 is puzzling at first. It must be present because after performing a LOAD from within a program, the BASIC interpreter begins executing again at the 8 Anatomy of the 1541 Disk Drive first line of the new BASIC program. Because the machine language program doesn't usually overlay the BASIC program in memory, the original BASIC program remains intact and is therefore is re-executed. If you use the routine: 10 LOAD"programname",8,1 20 SYS (starting address) the program continues to LOAD "programname" again, and the SYS command is never executed. If the variable A is present, the program branches to line 20 at the end of the first command on line 10. This loader can be placed on the diskette together with the machine language program. To execute the machine language program, you need only give the commands: LOAD-loader-,8 RUN This has the advantage that the starting address of the machine language program need not be known, because it is included in the SYS of the loader. 9 Anatomy of the 1541 Disk Drive 1.3 Disk System Commands As already mentioned, the VIC-I54l 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 processor and control system. The Disk Operating System (DOS) 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 builtin 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: - opening the channel - data transfer - close the channel (OPEN) (PRINT) (CLOSE) In the OPEN command you specify a logical file number (arbitrary between 1 and 127), a 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 Ifn,8,I5,·command· or OPEN Ifn,8,I5:PRINT'Ifn,·commandThe number 8 is the device number of the disk drive and the number 15 is the secondary address or channel number. The parameter lfn is the logical file number which is used in subsequent commands (PRINT#, INPUT#, GET#). It can be a number in the range 1-127. The ·command w can either follow the OPEN statement directly, or can be transferred with a PRINT# command following the o~ening. Any number of system commands can be transmitted untll the channel is closed, but must be referenced by the logical file number used in the OPEN command. 10 Anatomy of the 1541 Disk Drive 1.3.2 NEW - Formatting Diskettes The command to format a diskette is called NEW and can, as every other command, be abbreviated to its first letter (N). As already mentioned, the command can follow an OPEN command or be ~iven in a PRINT# command. The NEW command has the followIng format: NEW:diskname,id The parameter diskname may contain up to 16 characters and is stored in the header of the diskette directory. The parameter ID (identification) consists of two arbitrary characters, so that the DOS can recognize if a different diskette 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: The command can be abbreviated to: OPEN 1,8,15,-N:ABCDISK.KLYou need only use the command once - when you first use a brand new diskette. Formatting takes about 80 seconds. Formatting 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 PRINTtl,-N:ABCDISK,KL- to open the channel 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 formatting: CLOSE 1 Now the command channel is closed. The number 1 is again the logical file number of the corresponding OPEN command. 11 Anatomy of the 1541 Disk Drive 1.3.3 Reading the Error Channel When the Commodore 64 or VIC-20 is incorrectly programmed, it responds with an error message. Disk commands are carried out and verified by the processor of the disk drive. Therefore the computer cannot directly display error messages that are detected by the disk drive. Errors are indicated by the flashing red LED on the disk drive. In order to determine which error has occurred, the computer must read the error from channel 15. Therefore 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 Field Field Field 1: 2: 3: 4: Error number Description of the error (string) Track number Sector number The track and sector information may 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 errc'r cha.nnel: OPEN 1,8,15 (if not already done) INPUT'l,EN,DE$,TR,SE CLOSE 1 The INPUT' statement must be entered from within a program. It is not proper to issue an INPUT# statement from command mode. 10 20 30 40 OPEN 1,8,15 INPUT#l,EN,DE$,TR,SE PRINT EN;DE$;TR;SE CLOSE 1 (to display the error) To understand the operation of this program, first create the following error: OPEN l,8,I5,-NEW ABCDISK,TlCLOSE 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 the program to read the error channel and type RUN. The error will appear on the screen: 34 SYNTAX ERROR 0 0 The 34 is the number of the error, which is explained later. The track and sector fields are 0 because this information 12 Anatomy of the 1541 Disk Drive is not relevant to this error. If you read the error channel occurred, the message: o OK 0 when an error had not 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 caus~s 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. The directory is loaded by typing: LOAD -$-,8 and can be viewed with the LIST command. Try LOADing the directory of the TEST/DEMO 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 follows should be shown on the screen o 13 5 4 I 4 11 4 4 6 4 14 9 5 13 "1541test/demo " zx 2a prg "how part two" prg "vic-20 wedge" prg "c-64 wedge" prg "dos 5.1" prg prg "copy/all" "disk addr change" prg prg "dir" "view bam" prg prg "cheek disk" "display t&s" prg "performance test" prg prg "sequential file" "random file" prg "how to use" 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 the directory is of the diskette in drive O. Other disk drives such as the 4040, contain two disk drives - drive 0 or drive 1. On the 1541 the drive 13 Anatomy of the 1541 Disk 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. Next are the individual file names, their lengths in blocks in the first column and the file type in the last column. This diskette contains three different file types: PRG These are PROGRAM files, written in either BASIC or machine language SEQ sequential data files, explained later REL This is another form 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 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). If you own a printer, this directory can be printed as you would print a program listing. Use the following commands: OPEN 1,4 CMD 1 LIST PRINT#l CLOSE 1 open the printer the printer is now linked to the screen the directory will be printed send a RETURN to the printer dIose the printer again It is assumed that the directory is already loaded with the LOAD·S·,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 Sometimes an unneeded file must be removed from the diskette. The SCRATCH 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 he careful before using the SCRATCH command. 14 Anatomy of the 1541 Disk Drive To delete a file, the following format should be used: PRINT'lfn.·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 following commands are used: with the name TEST, the OPEN 1.8.l5.·S:TEST· CLOSE 1 If channel 15 is already open, only the PRINT# command is required: PRINTtl.·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. 1.3.6 RENAME - Renaming Files You can also change the name of a file on the diskette. The command RENAME is provided for this purpose. It has tte 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.l5,·R:PEST=TEST· CLOSE 1 or 15 Anatomy of the 1541 Disk Drive OPEN 1,8,15 PRINTfl,-R:PEST=TESTCLOSE I Note that you cannot rename a file until it is CLOSEd. 1.3.7 COpy - Copying Files 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.OI for example) with this command. The COpy command has the format: COPY:newfile=oldfilel,oldfile2, ••• So, the named data records can be combined as follows: OPEN 1,8,15,·C:EXP.Ol=EXP.Ol,EXP.02,BXP.03CLOSE I 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. The COpy command is seldom 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 TEST/DEMO diskette. We have also thought 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 The DOS requires a BAM (Block Allocation Map) to be present on each disk. The BAM 1S a layout of the usage of the blocks on each diskette. It marks each block on the diskette 16 Anatomy of the 1541 Disk Drive 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 RAM. Therefore, each diskette should be given a unique id when you format it. It is a good practice to give each diskette a different id. You can force the disk drive to read the BAM of a new diskette by issuing the INITIALIZE command. This command has the following format: PRINT,lfn,"INITIALIZE" or shortened to PRINTt1fn,"I" Example: OPEN 1,8,15,"1" CLOSE 1 If you change diskettes and also change data records, then we strongly recommend that you use the INITIALIZE command after changing the diskettes, to be safe. 1.3.9 VALIDATE - "Cleaning Up" the Diskette The command VALIDATE frees all allocated blocks that are not assigned to normally CLOSEd files. For example, i f you OPIN a file, and transfer data to that file, but forget to CLOSE the file, the VALIDATE command can be used to free the data blocks that were written to. If you use the direct access commands, be sure to allocate them (using the BLOCK-ALLOCATE command) or the VALIDATE command will free them again. The command has an additional function: If a file is deleted using the SCRATCH command, the file type in the first byte of the file entry is set to O. It no longer appears in the directory. If you now change this byte back to its old file type with the DOS monitor (described later) or other direct access commands, VALIDATE will restore the file. If it has not been overwritten, it will be the same as before the SCRATCH command. The command has the following format: PRINTt1fn,·VALIDATE" or the shorter form PRINTt1fn,·V" 17 Anatomy of the 1541 Disk Drive An example: OPEN 1,8,15,-VCLOSE 1 If you have a diskette such that the sum of the file lengtt!s plus the number of free blocks does not equal the total number available (664), use the VALIDATE command to restore it. Another example: If you want to store a program or data record that uses more than the number of free blocks, the DOS will give the error DISK FULL. If the disk had shown some blocks free before, the number is now zero. The VALIDATE command will restore the original free blocks. 1.3.10 ? * - The Wildcards There are two wildcard characters - the asterisk (*) and the characters of the first file on the disk that begins with the characters which precede the asterisk. An example: 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: loads only the directory of the files that begin with the letter "All. 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: 18 Anatomy of the 1541 Disk Drive *=S *=p *=R *=U selects selects selects selects only sequential files program files . relative files user-files For example, the command: LOAD ·$*=P·,8 causes only the directory entries of programs 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: OPEN l,8,15,·S:*=S· CLOSE 1 With the question mark, certain characters of a file name can be declared "not relevant". To illustrate the function of the question mark, here are two examples of shortened file names and their effects: A????? ????TEST - refers to a six-letter filename of whict first character is A - 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: ????* TEST.??* TEST-??Ol*=S - refers to all file names that have four characters before a period - refers to all file names having at least 7 characters, of which the first five are TEST. - refers to all sequential files whose names have at least nine characters, the first five heing TEST- and the eighth and ninth being 01 19 Anatomy of the 1541 Disk Drive 1.4 Sequential Data Storage A disk drive need not be used exclusively for storing programs. If you have written a program that manages a large quantity of data, you need a fast way of organizing it. Sequential data storage is not the fastest, but it is the easiest method of managing data. This method is comparable to sequential storage on a cassette, which can be maintained in a program as such: 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 diskette) new file on an external medium (cassette, 5. Exit the program The maximum number of data items that the program can handle depends on the size of the computer's memory, because a single data item cannot be changed or erased directly on the cassette or diskette. To that end, the entire set of data items must be read in, changed, and then rewritten again. Reading and rewriting the data occurs remarkably faster on a disk drive than on cassette. It is worth mentioning that programs which work with sequential data on cassettes can be easily modified to work with disk. Only the corresponding OPEN commands need be changed. 1.4.1 The Principle A sequential data file consists of several data records that are further divided into fields. The following is a name and address file and illustrates the principle of sequential data storage. Individual names and addresses comprise the data records of this file. A record consists of several fields (last name, first name, etc.). The structure of the file looks something like this: Field 1 : Field 2 : Field 3 : Field 1 : Field 2 : Field 3 : Data record 1 Data record 2 FILE 20 Anato~y of the 1541 Disk Drive Only two records are shown above. 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: LAST NAME FIRST NAME TELEPHONE EXTENSION FIELD 1 FIELD 2 FIELD 3 Let's look at a section of this previously written file (the character + symbolizes a RETURN): position: 1111111111222222222233333333334444444 1234567890123456789012345678901234567890123456 Data: SMITH+JOHN+236+LONG+TIM+121+HARRIS+SAM+654+ ••• You can see that the fields are of different lengths and are all separated by a RETURN character. This RETURN character is automatically written after the data field by a PRINT# statement, provided the PRINT# statement is not followed by a semicolon (which suppresses the RETURN character). These data items are assigned to the variables with an INPUT# statement. After that, another INPUT# must follow in order to read the next field, and so on. The following sections explain the fundamentals of writing programs using sequential data storage. 1.4.2 Opening a Sequential Data File To create a sequential data file, you must first OPEN the file. When opening a file to be written to, the following is carried out: 1. The diskette is checked to-see if an existing file has 21 Anatomy of the 1541 Disk Drive the same name. If so, the error message FILE EXISTS is given by the DOS. 2. The file entry in the directory 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. 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 be used (reading or writing). The format of the OPEN command looks like this: OPEN Ifn.8,sa,-filename.filetype.modeWhen the logical file number is between 1 and 127, a PRINTi statement sends a RETURN character to the file after each variable. If the logical file number is greater than 127 (128-255), the PRINT* statement sends an additional linefeed after each RETURN. This is necessary for printers, for example, that do not provide an automatic line-feed after a RETURN character. The secondary address (sa) can bE> a value between 2 and 14. The secondary address indicates the channel over which the computer is to transfer data to and from the disk drive. Secondary addresses 0 and 1 are reserved by the DOS for saving and loading programs. Secondary address 15 is designated as the command and error channel. Should several files be open at once, they must all use different secondary addresses, as only one file can use a channel. If, however, a file is opened with the secondary 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 time. When utilizing relative data files, the DOS requires 2 channels per file. Therefore, the following maximum combinations are possible: or - 1 relative and 1 sequential file - 3 sequential files When specifying the filename to be written to (in the OPEN command), you must be sure that the fi Ie name does not already exist on the diskette. If a file that already exists is to be to opened for writing, an at sign followed by a colon (@:) must be placed in front of the file name (same as in the SAVE command). For example: 22 Anatomy of the 1541 Disk Drive OPEN 1.8,2.-@:ADDRESSES.S.W- 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. It is not a data file 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 - Write a file (WRITE - section 1.4.3) R - Read a file (READ - section 1.4.4) A - Add to a sequential file (APPEND - section 1.4.4) M - read a file that has not been closed ("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.-SEOU.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 *SEO 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! While a file is open, the command/error channel 15 may be opened, but when channel 15 is closed, all other channels are closed as well. You must take note of this. Now some examples of the OPEN command: OPEN 1,8,2,"SEOU.TEST,S,R" - open a sequential file for reading - open a user file for writing - open a program file for reading OPEN 2,8,3,"SEOU.TEST,l],W" OPEN 3,8,4,"TEST,P,R" 23 AnatOItty of the 1541 Disk Drive OPEN 4,8,5,"SEOU.TEST,S,A" - open a sequential file for appending data - open the unclosed customer file for reading 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 PRINTiF 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 CLOSEd again. PRINT# cen 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,WYou should notice that lit. It signals the fact write to the file named name and address record the red LED on the disk drive was that a file was OPENed. You can now TEST. Here is how we would write a consisting of 4 fields: PRINT# 1, "SAM" PRINT#I,"HARRIS" PRINT#l,"2001 MAIN STREET" PRINT# 1, "ANYTOWN" Now these data items have been written to the file so we can 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 directly, a small program must be written: 10 OPEN 1,8,2,"TEST,S,R" 20 INPUT#I,FNS 30 INPUT#!, LN$ 40 INPUT#I,ST$ 50 INPUT#! ,CTS 60 CLOSE 1 ";FN$ 70 PRINT"FIRST NAME: 80 PRINT"LAST NAME: ";LNS 90 PRINT"STREET: ";STS 100 PRINT"CITY: " lCT$ The program is simple to explain: Line 10 The file TEST is opened for reading 24 Anatomy of the 1541 Disk Drive 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 as written earlier, on the screen: FIRST NAME: LAST NAME: STREET: CITY: SAM HAFRIS 2001 MAIN STREET ANYTOWN Four INPUTi 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: 10 20 30 40 50 60 70 80 90 OPEN 1,8,2,"TEST,S,F" FOR 1=1 TO 4 INPUTU,D$(I) NEXT I CLOSE 1 PRINT"FIRST NAME: ", D$ (1) ", D$ (2) PFINT"LAST NAME: ",D$(3) PRINT"STREET: ",D$(4) PRINT"CITY: Here, instead of four separate string variables, an array with index 1-4 is used. It should be noted that in BASIC 2.0, if an index higher than 10 is used, the array must be dimensioned with a DIM statement. Should we want to read in 20 fields, the statement DIM 0$(20) must be given 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: INPUT FN$.LN$.TE wi th this statement, as: three variables must be entered, NICHOLAS,MULLER,7465 The read data can be printed on the screen with: PRINT FN$.LN$.TE 25 such Anatomy of the 1541 Disk Drive In this manner, sequential data can be written and later read back in again. The only difference is that the string variables containing the data to be written must be separated by commas enclosed in quotes. For example, if you wish to write the previous variables to a file, the PRINT# statement command must changed as follows: Numeric variables need only be separated with a comma from the other variables. To read the data, use the command: INPUTll,FV$,LN$,TE Because the maximum number of characters read by an INPUT# statement may not exceed 88, this method of reading is only marginally useful. If a field in a record is more than 88 characters long, a different statement must be used. This is the GETI statement, which r.ads each individual character, one at a time. Suppose you want to read a record of which a field is 100 characters long. This record can be placed in a string variable with the following routine: 10 20 30 40 50 60 70 80 OPEN 1,8, •••••••••••••• D$= .... FOR 1=1 TO 100 GETll,X$ D$=D$+X$ NEXT I GETIl,X$ CLOSE 1 At the end of this program, the string variable D$ will contain the 100 characters of the data field. After opening a sequential data file, the DOS establishes a pointer that always points to next character to be read. We assume that the data was written with a PRINTI statement without a trailing semicolon, so that a RETURN was written at the end of the data item. After reading the first 100 characters, the pointer points to this RETURN. The next GET. in line 70 is necessary to read the RETURN found at the end of the field. Then the next GET' statement can read the next field and not the RETURN. In the above example, we used data records with a constant length of 100 characters. According to the rules of sequeptial access, the length of data records need not be constant. Since the INPUT. statement can only read a maximum of 88 characters, we will use the GET' statement to recognize the RETURN as the end of a field. Such a routine looks like this: lOOP EN 1, 8 , .••••••••••••••••••••• 20 S$='''' 30 GET#l,X$ 40 IF X$=CHRS(13) THEN 80 26 Anatomy of the 1541 Disk Drive 50 60 70 80 90 S$=S$+X$ IF ST<>64 THEN 30 CLOSE l:END PRINT S$ 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,"l. DATA RECORD" CLOSE 1 Now you have a sequential data file containing one data record. This file can be expanded with tw.o more records as follows: OPEN 1,8,2,"TEST2,S,A ft PRINT#1,"2. DATA RECORD" PRINT#1,"3. DATA RECORD" CLOSE 1 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 1=1 TO 3 INPUTU,DR$ PRINT DR$ NEXT I CLOSE 1 After the program starts, printed on the screen. the data records 27 is read and Anatomy of the 1541 Disk Drive You can see that the append A mode makes it quick and easy to expand a sequential data fileS. 1.4.5 Closing a Sequential File OPENed data files can be closed with the CLOSE command. This command has the format: CLOSE lfn The parameter Ifn is the that was used in the OPEN need to be closed a CLOSE one. When the last file is goes out. logical file number of the file statement. Should several files statement must be given for each closed, the red LED on the drive As you already know, data is sent to the disk drive over a channel. This channel uses storage 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. This could be a problem if the DOS did not allow read access to a file. For this reason, the DOS offers the M mode. A file that is marked 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 (original file) to a correctly closed file (destination file) : 100 110 120 130 140 150 160 170 180 190 INPUT"ORIGINAL FILE NAME";S$ INPUT"DESTINATION FILE NAME";D$ OPEN 1,8,2,S$+",S,M" OPEN 2,8,3,D$+",S,W" INPUT#I,X$ PRINT#2,X$ IF ST<>64 THEN 140 CLOSE I:CLOSE 2 OPEN l,8,15,"S:"+S$ CLOSE 1 At the completion of the program, the unneeded original file 28 Anatomy of the 1541 Disk Drive is deleted 1.4.6 (scratched). Redirecting the Screen Output Any output appearing on the video screen (PRINT, LIST, etc) can be redirected to a sequential data file. This is acconplished 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 program listing, for instance, as a sequential file on diskette, use the following commands: OPEN 1,8,2,"TEST.LIST,U,W" CMD 1 LIST CLOSE 1 The command CLOSB 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. 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 ST<>64 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 which is set to 64 at the end. 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 GETU,X$ PRINT#2,X$ IF ST<>64 THEN 30 CLOSE 1 29 Anatomy of the 1541 Disk Drive Here it assumed that the printer is connected as device address 4. 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. The following diagram shows an example of a table: Field 1 Field 2 Field 3 Record 1 Record 2 Record 3 Record 4 Record 5 Record 6 ~-----------------------------------------~ ~ DSIl,l) ~ 0$11,2) ~ 0$(1,3) ~ ~-----------------------------------------~ " 0$ ( 2 ,1) " 0$ ( 2 ,2) ~ 0$ (1 ,3) " ~-----------------------------------------~ ~ 0$(3,1) ~ 0$(3,2) ~ 0$(3,3) ~ ~-----------------------------------------~ ~ 0$(4,1) ~ 0$(4,2) ~ 0$14,3) ~ ~-----------------------------------------~ " oS I 5 , 11 ~ DS ( 5 ,2) " oS ( 5,3) " ~-----------------------------------------~ " D$16,1) " D$(6,2) " D$16,3) ~ ~-----------------------------------------~ This table is a file composed of six records which have three fields each. The variable 0$ 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 200 .210 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 ";Y;": ": INPUT X$ PRINTU,X$ NEXT Y NEXT X CLOSE 1 Two nested loops are used here, whose variables are numbered wi th the record and field. Enter six data records. When the program is done, these records will be contained on the 30 Anatomy of the 1541 Disk Drive diskette with the filename of TABFILE. 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.SEO,S,R" DIM 0$(6,3) FOR X=l TO 6 FOR Y=l TO 3 iNPUTtl,D$(X,Y) NEXT Y NEXT X CLOSE 1 This program places data into the table. You can check this with a 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 0$(1,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 question 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: 160 170 180 190 200 210 220 230 240 PRINT"------------------" 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 desired record to input the new table element. 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! 31 Anatomy of the 1541 Disk Drive 100 110 120 130 140 150 160 OPEN 1,8,2,"@:TABFILE,S,W" FOR X=1 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 @: in line 10 is necessary in order to overwrite the existing file. Accessing data through the use of the table is very fast. The access time is independent of the size of the table. 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 data, sequential storage is no longer feasible. 1.4.B 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 OPEN 1,B,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$ 32 Anatomy of the 1541 Disk Drive 200 210 220 230 240 PRINT"MORE INPUT (yiN)?" GETX$:IF X$="II OR X$<>'Y' AND X$<>"N" THEN 200 IF X$="N" THEN 240 GOTO llO CLOSE 1 Program Documentation: Line 100 The sequential file "TELEDAT" is opened for writing Line 110 The screen is cleared Lines 120-150 The four fields are entered from the keyboard Lines 160-lBO If the data are not correct, they can entered again 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 who~e list, looking for the desired name. Once found, it gives you the complete record which contained that name. The following routine accomplishes this: 100 110 120 130 140 150 160 170 IBO 190 OPEN l,B,2,"TELEDAT,S,R" DIM D$(100,4):X=1 INPUT*l,D$(X,l),D$(X,2),D$(X,3),D$(X,4) IF ST<>64 THEN X=X+l:GOTO 120 CLOSE 1 PRINT CHR$(147) PRINT"DESIRED NAME: n:N$ FOR 1=1 TO X ID D$(I,l)=N$ THEN 210 NEXT I 33 Anatomy of the 1541 Disk Drive 200 210 220 230 240 250 260 270 280 290 300 310 PRINT"NAME NOT FOUNDI":GOTO 280 PRINT"NAME FOUND:" PRINT"------~----" PRINT"LAST NAME: PRINT"FIRST NAME: PRINT"AREA CODE: PRINT"NUMBER: "lD$(I,l) "lD$(I,2) "10$(1,3) "lD$(I,4) PRINT"-~---------" PRINT"MORE (YIN)?" GETX$:IF X$="" OR X$<>"Y" AND X$<>"N" THEN 290 IF X$="Y" THEN 150 PRINT"PROGRAM DONE":END program Documentation Line 100 The sequential file uTELEDAT" 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 checking name. If branches 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 searches the table of records, the name fields against the desired the position is found, the program to the output routine 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 .desired field other than the name. You might want to search for an area code, fOr instance. The first program stops the search when the first matching data record is found. This is not always 34 Anatomy of the 1541 Disk Drive 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 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 OPEN 1,8,2,"TELEOAT,S,R" DIM D$(100,4) :X=l INPUT#1,D$(X,1),0$(X,2),0$(X,3),0$(X,4) IFST<>64 THEN X=X+l:GOTO 120 CLOSE 1 PRINT CHR$(147) PRINT"AREA CODE TO SEARCH FOR: ",AC$ FOR 1=1 TO X IF D$(I,3)=AC$ THEN 210 NEXT I PRINT"ENO OF OATA!":GOTO 270 PRINT"----------------n PRINT"LAST NAME: ",0$ (1,1) PRINT"FIRST NAME: ",0$(1,2) PRINT" AREA COOE: ",0$ (1,3) PRINT"NUMBER: ",0$(1,4) PRINT"----------------" PRINT"MORE (Y/N)?U GETX$:IF X$="" OR X$<>"Y" AND X$<>"N" THEN ;280 IF X$="Y" THEN 190 PRINT"SEARCH OONE!":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 ENO 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. 1.4.9 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 consuming task, which the programmer has tried to shorten ty using better sorting methods. Sorting is certainly a time consuming task 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. 35 Anatomy of the 1541 Disk Drive 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 ce 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 below. TA(I) > TA(X)? No 1(----0( X No ~------< I > max? max? Yes END 36 Yes TA(O)=TA(I) TA(I)=TA(X) TA( X) =TA( 0) Anatomy of the 1541 Disk Drive 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. In order to run this program, a table must be built. 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 1=1 TO 12 INPUT TA$(!) 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 1=1 X=I+l IF TAS(I) < TA$(X) THEN 180 TA$(O)=TA$(I):TAS(I)=TA$(X):TA$(X)=TA$(O) X=X+l IF X <= 12 THEN 160 1=1+1 IF I <> 12 THEN 150 FOR 1=1 TO 12 PRINT TAS(12) NEXT I The table is sorted and displayed on the screen. If, instead of a one dimensional table, you want to sort a two dimensional table such as our telephone file, exchange the fields by changing lines 160-170 as below: 160 IF DS(I,l) < D$(X,l) THEN 180 170 DS(O,l)=D$(I,l):D$(I,l)=DS(X,l): D$(X,l)=DS(O,l) 171 D$(0,2)=D$(I,2):DS(I,2)=D$(X,2): D$(X,2)=D$(O,2) 172 D$(0,3)=DS(I,3):D$(I,3)=DS(X,3): D$ (X, 3 ) =DS ( 0 ,3) 173 D$(0,4)=D$(I,4):D$(I,4)=D$(X,4): DS(X,4)=D$(0,4) 37 Anatomy of the 1541 Disk Drive It is very time consuming to sort a greater amount of data with this method. If you have a large amount of data to be sorted, we recommend that you use the very fast machine language sort routine from our book Commodore 64 Tips & Tricks. 1.4.10 MAILING LIST MANAGEMENT with Sequential Data Storage At the end of this section, is a mailing list management program that every user will hopefully find easy to use. At the same time, this program provides insight into the operation of many data processing techniques. A mailing list record of following fields: - this program consists of the NAME 1 NAME 2 STREET CITY, STATE ZIP CODE TELEPHONE NUMBER NOTES The use of the fields 'NAME I' and 'NAME 2' are up to the user. For instance, 'NAME I' can be the first name and 'NAME 2' the last name, or 'NAME I' the company name and "to the attention oL •• " in 'NAME 2'. The field 'NOTES' can be used for grouping the addresses (family, business, friends, etc.). The program offers the following Main Menu options: -1-2-3-4-5-6-0- LOAD DATA SAVE DATA INPUT DATA EDIT DATA SELECT/PRINT DATA DELETE DATA END PROGRAM -1- LOAD DATA Use this function to enter the name of the mailing list file that is to be maintained. If the file exists on the diskette, it is loaded and ready to be used. The number of records in the file is displayed. If an error is encountered while loading, or if the file does not exist, the message DISK ERROR! is displayed. At the conclusion of this function, the Main Menu reappears. 38 Anatomy of the 1541 Disk Drive -2- SAVE DATA Use this function to write an updated or expanded copy of the mailing list to the diskette. If the file name already exists, then the file is overwritten. The mailing list should be saved often while using the program in case a power outage should erase the computer's memory. After saving, the file can be used further, without having to reload it in.again. -3- INPUT DATA Use this function to add records to the mailing list: 1. When no data has been previously loaded. First a file name for the mailing list is entered. Enter a file name which does not already exist on the diskette or the old file is overwritten. All records that are inputted are new to the mailing list. 2. When data has been previously loaded. All records that are inputted are added to the existing mailing list. After entering an mailing list entry, the message CORRECT (Y/N)? is displayed. Here you may correct the data. If the entry is not correct, press the N key. If the entry is correct, press Y. Now the message MORE INPUT (Y/N)? is displayed. If you want to enter another mailing list entry, press Y. If you press N, the Main Menu appears again. -4- EDIT DATA Use this function to change existing mailing list records. Both Name 1 and Name 2 must be entered. If both nawes are not known, the other can be found with the SELECT/PRINT DATA routine. After entering the names, the mailing list is searched for matching names. When they are found, the complete address is displayed with the fields numbered. Now you must enter the number of the field which you want to change. The new contents are requested. The record is once again displayed in its updated form. If no more changes to this record are required, press 9. The program asks if another record is to be changed. This question is to be answered by pressing Y or N. 39 Anatomy of the 1541 Disk Drive -5- SELECT/PRINT DATA Use this function to search for certain records and print or display them. You must first specify if the selected records are to be printed on the screen (S) or the printer (P). If you have selected the printer, you must again choose if the data is to be printed with all fields on normal paper (P), or if fields 1-5 are to be printed on mailing labels (M). The address labels must be in a single column and measure 89mm x 36mm. In order to select the data, enter search criteria. For fields which are not relevant, simply press RETURN. If, for example, you want to find all addresses in Grand Rapids, press RETURN for the first three fields and type GRAND RAPIDS, MI for the fourth, and press RETURN for the next three. An example: NAME 1 NAME 2 STREET CITY, STATE ZIP CODE TELEPHONE NUMBER NOTES MFAMILY All family merobers whose name 1 begins with 'M' will be displayed. You can see how versatile this search is. Try it out yourself. -6- DELETE DATA Use this function to delete records. After entering the first and second names of the record, the record is reed and the remaining fields are displayed. Then you are asked to confirm that the record is to be deleted. If you press Y, the record is deleted. -0- END PROGRAM Use this function to leave the prograro. Before the program is ended, you are reminded that you can restart the program without losing data by typing GOTO 110. This is important if you forget to save the data before ending the program. 40 Anatomy of the 1541 Disk Drive Here is 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 330 340 350 360 370 380 390 400 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 POKE 53280,5:POKE53281,2:PRINTCHR$(158),:DIMD$(100,7) GOSUB2030 PRINT"SELECT THE DESIRED FUNCTION:" PRINT"----------------------------":PRINT PRINT" -1- LOAD DATA" PRINT" -2- SAVE DATA" PRINT" -3- INPUT DATA" PRINT" -4- EDIT DATA" PRINT" -5- SELECT/PRINT DATA" PRINT" -6- DELETE DATA":PRINT PRINT" -0- END PROGRAM" PRINT PRINT" CHOICE (0-6)?" GETX$:IFX$<"0"ORX$>"6"THEN230 IF X$<>"0"THEN340 PRINT:PRINT" ARE YOU SURE (Y/N)?" GETX$:IFX$<>"N"ANDX$<>"Y"THEN260 IFX$="N"THENI10 GOSUB2030 PRINT"THE PROGRAM CAN BE RESTARTED WITH PRINT" 'GOTO 110'" PRINT" WITHOUT LOSS OF DATA" END ONVAL(X$)GOSUB360,540,680,880,1190,1770 GOTO 110 REM ********* REM LOAD DATA REM ********* GOSUB 2030 INPUT"NAME THE FILE :",FN$ OPEN 15,8,15 OPENl,8,2,FN$+",S,R" INPUTiI5,FE:IF FE=O THEN 460 PRINT"DISK ERROR!" GOTO 510 X=l INPUTil,D$(X,l) ,D$(X,2) ,D$(X,3) ,D$(X,4) ,DS(X,5) ,D$(X,6), D$(X,7) IF ST<>64 THEN X=X+l:GOT0470 PRINT"FILE IS LOADED AND CONTAINS",X,"RECORDS." PRINT CLOSE:CLOSE15 PRINT"RETURN FOR MORE" INPUTX$:RETURN REM ********* REM SAVE DATA REM ********* IF X>O THEN 590 GOSUB2230:RETURN GOSUB 2030 OPEN 1,8,2,"@:"+FN$+",S,W" FORI=lTOX PRINT#1,D$(I,1)","D$(I,2)","D$(I,3), 41 Anatomy of the 1541 Disk Drive 630 PRINT#1,D$(I,4)","D$(I,5)","D$(I,6)","D$(I,7) 640 NEXT 650 PRINT"DATA IS SAVED":CLOSE1:RETURN 660 PRINT"RETURN FOR MORE" 670 INPUTX$:RETURN 680 REM ********** 690 REM INPUT DATA 700 REM ********** 710 IFX>OTHEN730 720 GOSUB2030:INPUT"FILENAME ",FN$ 730 X=X+l 740 GOSUB2030 750 PRINT"INPUT DATA:" 760 PRINT"-----------":PRINT 770 I=X:GOSUB2110 780 FORI=lT07:PRINTCHR$(145),:NEXT 790 FORI=lT07:PRINTTAB(12);:INPUTD$(X,I):NEXT 800 PRINT:PRINT"CORRECT (YIN)?" 810 GETX$:IFX$<>"N"ANDX$<>"Y"THEN810 820 IFX$=" y"THEN840 830 GOTO 740 840 PRINT"MORE INPUT (YIN)?" 850 GETX$ :IFX$O"N"ANDX.$O"Y"THEN850 860 IFX$="Y"THEN730 870 RETURN 880 RE.M ********* 890 REM EDIT DATA 900 REM ********* 910 IF X>OTHEN930 920 GOSUB2230:RETURN 930 GOSUB2030 940 INPUT"NAME 1: ",Nl$ 950 INPUT"NAME 2: ",N2$ 960 FORI=lTOX 970 IF D$(I,1)=N1$ANDD$(I,2)=N2$THEN1010 980 NEXTI 990 PRINT-NAME NOT FOUND!" 1000 PRINT"RETURN FOR MORE":INPUTX$:RETURN 1010 GOSUB2030 .1020 PRINT"-l- NAME 1 :";0$(1,1) :";D$(I,2) 1030 PRINT"-2- NAME 2 1040 PRINT"-3- STREET :"; 0$ (1,3) 1050 PRINT"-4- CITY, STATE :",D$(I,4) :";0$(1,5) 1060 PRINT"-5- ZIP CODE :"; 0$ (1,6) 1070 PRINT"-6- TELEPHONE :";D$(I,7) 1080 PRINT D -7- NOTES 1090 PRINT"NO. OF FIELD TO CHANGE: ":PRINT"(9=NO CHANGES)" 1100 GETX$ :IFVAL(X$) <10RVAL(X$) > 7 AN DVA L( X$) o9THENll00 1110 IFVAL(X$)=9THEN1150 1120 Y=VAL(X$) 1130 INPUT"NEW CONTENTS",D$(I,Y) :PRINT 1140 GOTO 1010 1150 PRINT"MORE CHANGES (YIN)?" 1160 GETX$ :IFX$<>"y"ANDX$<>"N"THEN1160 42 Anatomy of the 1541 Disk Drive 1170 1180 1190 1200 1210 1220 1230 1240 1250 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 1630 1640 1650 1660 1670 1680 1690 1700 IFX$="Y"THEN880 RETURN REM ***************** REM SELECT/PRINT DATA REM ***************** IF X>OTHENI240 GOSUB2230:RETURN GOSUB2030:PRINT"OUTPUT TO PRINTER (P) OR SCREEN (S)?" GETX$:IFX$<>"S"ANDX$<>"P"THENI250 O$=X$:IFO$="S"THENI300 PRINT:PRINT"PAPER (P) OR MAILING LABELS (M)?" GETX$:IFX$<>"P"ANDX$<>"M"THENI280 D$=X$ GOSUB2030 PRINT"ENTER THE SEARCH DATA:" PRINT"PRESS RETURN BY IRRELEVANT FIELDS." PRINT"----------------------------------":PRINT I=O:GOSUB2110 . FORI=IT07:PRINTCHR$(l45): :S$(I)="":NEXT FORI=IT07:PRINTTAB(12)::INPUTS$(I):NEXT IFO$="S"ORD$="M"THENI450 GOSUB2030:PRINT"PRINTER READY (Y)?" GETX$:IFX$<>"Y"THENI390 OPEN 1,4 PRINTlI 1, "NAME 1": SPC( 8) : "NAME 2": SPC( 8) : "STREET": SPC(lO) : PRINT1I1,"CITY, STATE";SPC(4):"ZIP CODE TELEPHONE NOTES" FORI=IT079:PRINTlIl,"="::NEXT:PRINT#1 CLOSEI FORI=ITOX FORY=IT07 IFS$(Y)=LEFT$(D$(I,Y),LEN(S$(Y»)THENZ=Z+I:GOTOI480 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 PRINTil,D$(I,1);SPC(14-LEN(D$(I,1»): PRINTlIl,D$(I,2):SPC(14-LEN(D$(I,2»): PRINTi1,D$(I,3);SPC(16-LEN(D$(I,3»); PRINTlIl,D$(I,4):SPC(15-LEN(D$(I,4»); PRINT#I,D$(I,5);SPC(8-LEN(D$(I,5»): PRINTlIl,O$(I,6);SPC(12-LEN(D$(I,6»); PRINTil,O$(I,7) PRINTi1:CLOSEI RETURN OPEN2,4 PRINTlI 2 FORJ=IT05:PRINTlI2,O$(I,J) lNEXT PRINT#2:PRINT1I2~PRINT1I2 Anatomy of the 1541 Disk Drive 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 2030 2040 2050 2060 2070 2080 2090 2100 2110 2120 2130 2140 2150 2160 2170 2180 2190 2200 2220 2230 2240 2250 2260 CLOSE2 RETURN GOSUB2030:GOSUB2110 PRINT:PRINT"MORE (Y)?" GETX$: IFX$<>" y"THEN17 50 RETURN REM *********** REM DELETE DATA REM *********** IFX>OTHEN1820 GOSUB2230:RETURN GOSUB2030 INPUT"NAME 1 : ";N1$ INPUT"NAME 2 : ";N2$ FORI=lTOX IFO$(I,1)=Nl$ANOO$(I,2)=N2$THEN1900 NEXTI PRINT"NAME NOT FOUND!":PRINT PRINT"RETURN FOR MORER:INPUTX$:RETURN GOSUB2030:GOSUB2110 PRINT:PRINT"OELETE RECORD (yiN)?" GETX$:IFX$<>"Y"ANOX$<>"N"THEN1920 IFX$=RN"THENRETURN FORY=ITOX-l FORJ=lT06 D$(Y,J)=D$(Y+l,J) NEXTJ,Y FORJ=lT06:0$(X,J)="":NEXTJ X=X-l PRINT"RECORD IS DELETED!" PRINT"RETURN FOR MORE" INPUTX$:RETURN REM *************** REM PROGRAM HEADING REM *************** PRINTCHR$ ( 14 7) ; PRINTTAB(8);"=======================" PRINTTAB(8);"M A I LIN G LIS T PRINTTAB(8);"=======================" RETURN REM ************ REM PRINT RECORD REM ************ ";D$(I,1) PRINT"NAME 1 ";0$(1,2) PRINT"NAME 2 PRINT"STREET ";0$(1,3) PRINT"CITY, STATE ";0$(1,4) PRINT"ZIP CODE ";D$(I,5) PRINT"TELEPHONE ";0$(1,6) ";0$(1,7) PRINT"NOTES RETURN REM ******** REM NO DATA! REM ******** GOSUB2030 Anatomy of the 1541 Disk Drive 2270 PRINT"NO DATA IN MEMORY1":PRINT 2280 PRINT"RETURN FOR MORE" 2290 INPUTX$:RETURN 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 defini te length. It makes sense to make u~e of th is advantage, where the 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, which offer other advantages. 45 Anatomy of the 1541 Disk Drive 1.5 Relative Data Storage Relative data storage and its programming is not described in the VIC-1541 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 the 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, you don't have to read an entire file into the computer, only the desired records. Managing 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. Writing a record: 1. 2. 3. 4. The The The The file is opened. file is positioned on the record to be written. record is written. file is closed. Reading a record: 1. 2. 3. 4. The The The The file is opened. file is positioned over the record to be read. record is read. file is closed. 46 Anatomy of the 1541 Disk Drive 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. 1.5.3 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 Ifn,da.channel. -fi lename,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 one and 254. Thus each record of a relative file is limited to a maximum of 254 characters. If the record length is smaller than 88, the record can be read with an INPUT# statement. For this, it is necessary 47 Anatomy of the 1541 Disk Drive that the PRINT# statement transfers the record with a tr.ailing RETURN. A PRINT# statement sends a RETURN when it is not ended 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 l,8,2,"FILE.REL,L,"+CHR$(8l) 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 opened at a time. If you want to files, you must always close the second. One sequential file may be relative file. one relative file can be work with two relative first before opening the opened in addition to one When a relative file is opened fpr the first time, the DOS as many "null" or unused records that can fit in a single 254 byte block. It creates these "null" records by writing a record with a CHR$(255) at the beginning of each record. This is called formatting a relative file. cre~tes If you want to expand a relative file beyond the initial number of records that the DOS formatted, then you can reference the last record number that you want to write (by positioning to that record number) and the DOS automatically formats the"records between the current end of file and the new last record number by writing records containing CHR$(255). Formatiing takes time to complete. If you try to read a record whose number greater than that of the last record, the DOS returns the error RECORD NOT PRESENT. However, if you write a record which is greater than the highest current record, all records less than the new record number are also written with CHR$(255). Subsequently accessing these record does not result in an error. If you want to avoid long delays as relative records are formatted (as the file is expanded), then you should reference the last record number immediately after opening the file. The formatting of the null records takes place at that time instead of at a more inconvenient time. To position the DOS for a specific relative record you mUf't send a position command over the command channel (15), as shown here: PRINTllfn,-P-+CHR$(channel)+CHR$(low)+CHR$(higA)+CHR$(bytel 48 Anatomy of the 1541 Disk Drive If you are positioning to a record which is beyond the current end of file, the DOS presents the message RECORD NOT PRESENT appears to the disk error channel. If this record is to be written, then you can ignore the message. The following PRINTi statement is carried out in spite of the error message. The parameters low and high in the P command designate the record number. The maximum value that can be given with one byte is 255, but a relative file contains up to 65535 records. Therefore, the record number must be transmitted in two bytes. These two bytes are calculated with the following formula: HB=INT(RN/256) LB=RN-HB*256 HB LB RN High Byte (parameter high) Low Byte (parameter low) Record Number The last parameter (byte) serves to position to a specific location within the given record. An example: PRINTI2,-P-+CHR$(2)+CHR$(10)+CHR$(I)+CHR$(5) Here the file is positioned to the fifth byte of the 266th record. This 266 is coded as a low byte of 10 and a high byte of 1 (high byte * 256 + low 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 RETURN (CHR$(13» is taken as the character location. The corresponding BASIC program to establish a file of 100 80-character records looks like this: 100 110 120 130 140 150 160 170 RN=100 HB=INT(RN/256) LB=RN-HB* 256 OPENl,8,2,"FILE.REL,L,"+CHR$(80) OPEN2,8,15 PRINTi2,"P"+CHR$(2)+CHR$(LB)+CHR$(HB)+CHR$(1) PRINT#1,CHR$(255) CLOSE l:CLOSE 15 Freeing 100 records takes some time. The creation of this file takes about ten minutes. Notice that of the 80 characters ina record, only 79 can be used to hold data, because transferring data with a PRINTi command adds a trailing RETURN. 49 Anatomy of the 1541 Disk Drive 1.5.4 Preparing Data for Relative Storage As already mentioned, you cannot change the record length of a relative file. If a record consists of several fields, these fields must be combined. 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 manage an inventory using relative storage techniques. To that end, the following fields are necessary: PART NUMBER DESCRIPTION QUANTITY COST PRICE 4 15 5 6 6 CHARACTERS CHARACTERS CHARACTERS CHARACTERS CHARACTERS Record length 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 150 160 RN=200:REM NUMBER OF INVENTORY ITEMS RL=36 :REM RECORD LENGTH OPEN 1,8,2,"INVEN,L,"+CHR$(36) OPEN 2,8,15 PRINT#2,"P"+CHR$(2)+CHR$(200)+CHR$(0)+CHR$(1) PRINT#1,CHR$(255) CLOSE l:CLOSE 2 Now the file is created and all records are written. Let's suppose that the inventory is present as a sequential file. It consists of 200 records, the fields of which are ordered one after the other. These fields must be written to the relative file. This is not simple, however, because many of the descriptions are not the full fifteen characters in length, for example. The structure of the relative file looks as follows: 111111111122222222223333333 Position : 123456789012345678901234567890123456 Field Contents : PN$-DE$------------Q$---C$----P$---1 2 3 1/8 in. sheet No. 10 screw Valve A3A4 1344 11.40 20.30 1231 4.00 7.00 1243 11.45 16.40 200 1/2 in. tubing 2321 3.35 4.10 The fields will be read from the sequential file into the following variables: 50 Anatomy of the 1541 Disk Drive Part number Description Ouantity Cost Price PN$ DES 0$ C$ p$ The following command chains these fields together: RC$ = PN$ + DE$ + 0$ + C$ + P$ The record variable Re$ does not have the deSired structure. The reason is that the quantity immediately follows the description. Because the quantity must begin at position 20 and the description is not always fifteen characters, we have a problem. In order to read the records from the relative file, the structure must be observed. Therefore, all fields that are shorter than the planned length must be padded with blanks. Taking this into account, the chaining goes like this: BL$=n RC$=PN$+LEFT$(BL$,4-LEN(PN$» RC$=RC$+DE$+LEFT$(BL$,15-LEN(DE$» RC$=RC$+O$+LEFT$(BL$,5-LEN(OS» RC$=RC$+C$+LEFT$(BL$,6-LEN(C$» RC$=RC$+P$+LEFT$(BL$,6-LEN(P$» 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. T Let's go through an example: Suppose the first part number is 8. The string, LEN(PN$), is then one. The maximum field (4) minus the actual length (1) is 3. must therefore be padded with three blanks, length of this length of this The string PN$ LEFT$(BL$,3). Each record of the old sequential file must be prepared in this manner before it can be transferred to the relative file. Naturally, the above is true for all input values to be used in a relative 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. 51 Anatomy of the 1541 Dis.k Drive 1.5.5 Transferring 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 be written or read, the file must be positioned to that record. This is accomplished with the P command. This example program illustrates what we have discussed: 100 105 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 BL$=" OPEN 1,8,2, "TEST .REL, L, "+CHR$ (41) OPEN 2,8,15 PRINT#2,"P"+CHR$(2)+CHR$(100)+CHR$(0)+CHR$(1) PRINT#1,CHR$(255) PRINT CHR$(147) PRINT"INPUT RECORD:" PRINT"-------------" INPUT"RECORD NUMBER (1-100) : "lRN IF RN lOO THEN PRINTCHR$(145)1:GOT0160 INPUT"FIELD 1 (MAX.lO CHAR.) : "lFl$ IF LEN(Fl$»lO THEN PRINTCHR$(145)nGOT0190 INPUT"FIELD 2 (MAX. 5 CHAR.) : "lF2$ IF LEN(F2$»S THEN PRINTCHR$(14S)::GOT0210 INPUT"FIELD 3 (MAX.lO CHAR.): "lF3$ IF LEN(F3$»10 THEN PRINTCHR$(145)1:GOT0230 INPUT"FIELD 4 (MAX.15 CHAR.) : "lF4$ IF LEN(F4$»15 THEN PRINTCHR$(145)::GOT0250 PRINT"COHRECT (YIN)?" GETX$:IF X$<>"Y' AND X$<>"N" THEN 280 IF X$="N" THEN 140 RC$=Fl$+LEFT$(BL$,lO-LEN(Fl$» RC$=RC$+F2$+LEFT$(BL$,5-LEN(F2$» RC$=RC$+F3$+LEFT$(BL$,10-LEN(F3$» RC$=RC$+F4$+LEFT$(BL$,15-LEN(F4$» PRINT#2,"P"+CHR$(2)+CHR$(RN)+CHR$(0)+CHR$(1) PRINT# 1, RC$ PRINT"MORE INPUT (YIN)?" GETX$:IF X$<>"Y" AND X$<>"N" THEN 370 IF X$="Y" THEN 140 CLOSE l:CLOSE 2:END The following line-oriented documentation explains operation of the program: 100 105 110 120 130 140 the 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. The screen is erased. 52 Anatomy of the 1541 Disk Drive 150-260 270-290 300-330 340 350 360-380 390 The record no. and fields 1-4 are entered and checked for correct length. The entered data can be corrected. The record is prepared. The head is positioned over the first byte of the record. The record is written to the disk. New data can be entered. The program ends. Now write some records with this program, but don't forget to save in case you need it later. Certainly, it also necessary to read and change e~isting 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 OPEN 1,8,2,"TEST.REL,L,"+CHR$(4l) OPEN 2,8,15 PRINT CHR$(147) INPUT"RECORD NUMBER :";RN PRINT# 2, "P"+CHRS (2) +CHR$ (RN) +CHR$ (0) +CHR$ (1) INPUT# 1 ,RC$ IF ASC(RC$)<>255 THEN PRINT"RECORD NOT FOUND!": GOT0250 170 PRINT RC$ 250 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 establishment 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 MIDS. 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$=MIDS(RC$,l,lO) PRINT Fl$ Now the variable Fl$ contains the first field, as written by the first program. The division of records into individual fields is accomplished by building on the previous program. Add or change the following lines: 170 180 190 200 FlS=MID$(RC$,l,lO) F2$=MID$(RCS,11,5) F3$=MID$(RC$,16,10) F4$=MID$(RC$,26,15) 53 Anatomy of the 1541 Disk Drive 210 220 230 240 250 260 270 280 PRINT"FIELD 1: H Fl$ PRINT"FIELD 2: " F2$ PRINT"FIELD 3: " F3$ PRINT"FIELD 4: " F4$ PRINT"MORE (YIN) " GETX$:IF X$<>"yn AND X$<>"N" THEN 260 IF X$"'''Y" THEN 115 CLOSE l:CLOSE 2 Here the record is separated into the individual fields and the fields are displayed. It is important for the MID$ function that the exact positions of the fields within the record be maintained. The first parameter within the parentheses is the string variable containing the record. The second parameter is the position at which the number of characters represented by the parameter will be taken out. Further work may done with the selected fields inside the program. So far, we have read the records with the INPUTi statement. If the record is longer than 88 characters, it can no longer be read with the INPUT# statement. The way to get around the limited INPUT# statement is with the GET# statement. The bytes of a record are read one at a time with this command and assembled into a single string. Suppose you have a relative file with l28-character records. Now you want to read the tenth record of this file and place it in the variable RC$. The example of the following routine illustrates reading this with GET#: 100 110 120 130 140 150 160 170 OPEN 1,8,2, "TEST .GET ,L, "+CHR$ (128) OPEN 2,8,15 PRINT#2,"P"+CHR$(2)+CHR$(10)+CHR$(0)+CHR$(1) RC$"'"" FOR 1"'1 TO 128 GET#! ,X$ RC$"'RC$+X$ NEXT I After running this routine, the record is contained in the variable RC$. If this record had been written with a PRI'NT# 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 l27-character record of the previous example, you want to read positions 40-60 into a 54 Anatomy of the 1541 Disk Drive field, the head must be positioned over the 40th charact~r and the next 21 bytes read. The following routine clarifies this: 100 110 120 130 140 150 160 170 OPEN 1,8,2,"TEST.GET,L,"+CHR$(128) OPEN 2,8,15 PRINTI2,"P"+CHR$(2)+CHR$(10)+CHR$(0)+CHR$(40) F$="" FOR 1=1 TO 21 GETll,X$ F$=F$+X$ 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 140170 reads the following 21 bytes (bytes 40-60 of the record) into F$. 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 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 if you want to search for a specific name in a relative and the record number is not known. It is possible to each record and compare each for the desired name. But is very time consuming if the file has many records. what file read this 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 ZYPHER might be contained in the last relative record of 55 Anatomy of the 1541 Disk Drive 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, then the records must 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 turn halfway into the first section of the book, and so on. You go through it systematically. 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 ascending order: Record number 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 relative file, sorted in Contents 1985 1999 2005 2230 2465 2897 3490 3539 4123 5000 5210 6450 6500 6550 6999 out of 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 equal to the target value, and if not, whether it is larger or smaller. In this case, it (3539) is 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 and results in record 6 whose contents is 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. 56 Ana~amy of the 1541 Disk Drive 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 file with necessary number of comparisons (searches) and N is the records in the file. In a sorted relative data 1000 records, no more than ten comparisons will be 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 170 OPENl,8,2,"BINARY.REL,L,"+CHR$(5) FORI=l T015 READ RC$ PRINTU ,RC$ NEXT I CLOSE l:CLOSE 2:END DATA 1985,1999,2005,2230,2465,2897,3490,3539 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 210 220 230 240 250 260 270 280 290 300 310 320 OPENl,8, 2, "BINARY .REL, L, "+CHR$ (5) OPEN2,8,15 PRINTCHR$(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 1=2"1 X=I/2 INPUT"RECORD TO FIND (* TO END): ";SR$ IF SR$="*" THEN 320 IF M I THEN PRINT"END OF FILE EXCEEDED!" GOTO 230 CLOSE l:CLOSE 2 57 Anatomy Of the 1541 Disk Drive 330 340 350 360 END PRINT"RECORD FOUND!" PRINT"CONTENTS : ":RCS GOTO 140 Program Documentation: 100 110 120 140 150-190 210-220 230 240 250-260 2.70 280-310 320-330 340-360 The relative file "BINARY.REL" is opened. The command channel is opened. The screen is erased. The number of records is assigned to the variable N. If the maximum number of records does not represent a power of two, the next higher power of two is formed. The file will be expanqed, but no records are lost. The exponent of this power of two is used as the index. X is the value of 1/2. 1/2 indicates the exact middI'e of the (expanded) file. After that, the variable M receives the value of 1-1. The record to be found is read. To end the program, enter a '*'. If M lOO THEN PRINTCHR$(145);:GOT0200 PRINT"---------------------------" PRINT*2, "P"+CHR$ (2) +CHR$ (RN)+CHR$ (0 )+CHR$ (1) INPUTU,RC$ IF ASC(RC$)<>255 THEN 270 PRINT "RECORD NOT WRITTEN" GOTO 630 REM ====================== REM PREPARE RECORD REM ====================== F$(l)=MID$(RC$,l,lO) F$(2)=MID$(RC$,11,5) F$(3)=MID$(RC$,16,10) F$(4)=MID$(RC$,26,15) 61 Anatomy of the 1541 Disk Drive 340 350 360 370 380 390 400 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640 650 660 670 680 690 REM ====================== REM DISPLAY FIELDS REM ====================== PRINT CHR$(147) FOR 1=1 TO 4 PRINT"FIELD";I;": ";F$(I) NEXT I PRINT"-------------------------" REM ====================== REM CHANGE FIELDS REM ====================== PRINT"CHANGE WHICH FIELD (l-4)?" GETX$:IFX$<"l" OR X$>"4" THEN 460 INPUT"NEW CONTENTS: ";F$(VAL(X$» PRINT"RECORD IS CHANGED" PRINT"MORE CHANGES IN THIS RECORD (YIN)?" GETX$:IF X$<>"Y" AND X$<>"N" THEN 500 IF X$="Y" THEN 340 REM ==================== REM CHAIN FIELDS REM ==================== RC$=F$(l)+LEFT$(BL$,lO-LEN(F$(l») RC$=RC$+F$(2)+LEFT$(BL$,5-LEN(F$(2») RC$=RC$+F$(3)+LEFT$(BL$,10-LEN(F$(3») RC$=RC$+F$(4)+LEFT$(BL$,15-LEN(F$(4») REM ========================= REM WRITE RECORD BACK REM ========================= PRINT#! ,RC$ REM ==================== REM END PROGRAM? REM ==================== PRINT"MORE CHANGES TO FILE (YIN)?" GETX$:IF X$<>"Y" AND X$<>"N" THEN 670 IF X$="Y" THEN 160 CLOSE l:CLOSE 2:END After this program is RUN you can change any desired record. This record must have been written with the program in section 1.5.5. This editing program does not check the new field data for correct length. The important commands in this program have already explained in the corresponding sections. b~en 1.5.10 Expanding a Relative File Every relative file has a user-determined number of records that ranges from 1 to 65538. This number is the record with the highest record number and is written to the file with a 62 Anatomy o£ the 1541 Disk Drive value of CHR$(255). Writing this last record also formats all records in the file that precede this record number with CHR$(255). You can expand the size of a relative file at a later tiroe. For example, consider a relative file that is initially created with three records. After the file is OPENed, you position the file at record number 3 and write the record with CHR$(255). Here's an example of how you might do this: 10 20 30 40 OPEN 1,8,2, "RELFILE, L, "+CHR$ (50) OPEN 15,8,15 PRINTU5, "P"+CHR$ (2) +CHR$ (3)+CHR$ (O)+CHR$ (1) PRINTil,CHR$(255) When statement 40 is performed, not only is record 3 written, but records 1 and 2 are also formatted by the DOS. Subsequently, if you position and write a 90th record, the DOS formats records 4 through 89 (see lines 150 and 160 below). Each time the file is expanded, the DOS formats records between the current high record number and the new high record number. 150 PRINTi15,"P"+ CHR$(2)+CHR$(90)+CHRS(0)+CHR$(1) 160 PRINTil,CHR$(255) 500 PRINTi15,"P"+CHR$(2)+CHR$(175)+CHR$(0)+CHR$(1) 510 PRINTil,CHR$(255) An existing relative file can be expanded at any time, provided there is sufficient room on the disk. To do so, the new last record is written with CHR$(255). At the same time, all records between the old and new end of file are also formatted. When writing a record to a relative file whose record number is higher than the current high record number, a DOS error is not returned. If there is room on the diskette for the new records (current high record number through the new high record number) the file is simply expanded. If there is a lack of space on the diskette for the new records, the DOS error FILE TOO LARGE is returned. When reading a record from a relative file whose record number is higher than the current high record number, the DOS error RECORD NOT PRESENT is returned to the error channel.- 63 Anatomy of the 1541 Disk Drive 1.5.11· Home Accounting with Relative ·Data Storage A complete example of problem solving using relative files offers you a good insight into the organization of relative file processing. It can be used by most readers of this book. Few examples of relative file usage have been explained elsewhere, so here is such a program. In this application, individual accounts are numbered. This account number is used as a key to the corresponding records. This provides that each account contain a clear text description. The first field of each record is this account name. Twenty characters are allowed for the name. since information is needed for each month, twelve fields are necessary for each record. These summary fields are each ten characters long. The account summaries are stored as strings which are converted to numbers with .the help of the VAL function. The record consists of 141 characters (twenty for the name, 12*10 for the month summaries and one for RETURI'/) • The layout of the records follows: Length position Account name January summary February summary 20 10 10 1-20 21-30 31-40 November summary December summary 10 10 121-130 131-140 Field The maximum number of accounts per year is set to twenty. Therefore, a year's file consists of twenty records of 141 bytes each. We also specified the functions that this program is to perform. * Create accounts * Post to accounts * Display summary by Account * Display account names * Display Monthly summary 64 Anatomy of the 1541 Disk Drive * Display Year-end summary Create accounts: This function creates the file for a year. It asks for the number and names of the accounts. The records are then written with the account name and the summary fields are set to zero. Should a data file already exist with the sane name, the old file is deleted. Post to accounts: This function asks for the account number to be posted and whether the posting is an income or expense. For example, the category "SALARY" is an income account and the category "RENT" is an expense account. After this, the current contents of the account are displayed. When you post the appropriate amount, which is always positive. If you are making a correction entry, use a negative amount. Now the updated contents are displayed. new entry. You may then make a Producing account summary: After entering the account number, the summary of the twelve months and the year's total are displayed for that account. Display account names: Each account is determined by its number. Should you forget a number, this function lists all accounts by name and corresponding number. Display monthly summary: Here the income or expenses of all accounts are displayed. The monthly balance of all accounts is also displayed. Display year-end summary: This function shows the summary of all accounts and the year-end balance. This display takes some time, since all monthly fields of each record must be read and totaled. It accesses the entire file. Here's the program listing: 65 Anatomy of the 1541 Disk Drive 100 POKE 53280,2:POKE5328l,2:PRINTCHR$(158):: BL$=" ":DIMS(12) 110 GOSUB 2050 120 INPUT"CURRENT YEAR: ":Y$ 130 IF Y$<"1984"ORY$>"1999"THENPRINTCHR$(145);:GOT0120 140 GOSUB 2050 150 PRINT"SELECT A FUNCTION: 160 PRINT"------------------":PRINT 170 PRINT" -1- CREATE ACCOUNTS" 180 PRINT" -2- POST TO ACCOUNTS" 190 PRINT" -3- ACCOUNT SUMMARY" 200 PRINT" -4- DISPLAY ACCOUNT NAMES" 210 PRINT" -5- MONTHLY SUMMARY" 220 PRINT" -6- YEAR SUMMARY":PRINT 230 PRINT" -0- END PROGRAM" 240 GETX$:IFX$<"0"ORX$>"9"THEN240 250 IFX$<>"0"THEN270 260 END 270 ONVAL(X$)GOSUB 290,560,920,1160,1370,1720 280 GOTO 140 290 REM ================-======= 300 REM CREATE ACCOUNTS 310 REM ======================== 320 GOSUB 2050 330 PRINT"CAUTION! ANY PREVIOUS FILE FOR THIS YEAR" 340 PRINT"WILL BE ERASED!":PRINT 350 PRINT"CONTINUE(Y/N)?" 360 GETX$:IFX$<>"Y"ANDX$<>"N"THEN360 370 IFX$="Y"THEN390 380 CLOSEl:CLOSE2:RETURN 390 OPEN2,8,15,"S:ACCOUNTS"+Y$ 400 OPEN1,8,2,"ACCOUNTS"+Y$+",L,"+CHR$(141) 410 GOSUB 2050 420 INPUT"HOW MANY ACCOUNTS (1-20): .. :AN 430 PRINT 440 IFAN<10RAN>20THENPRINTCHR$(145)::GOT0420 450 FORI=ITOAN 460 PRINT"NAME OF ACCOUNT NO.":I;": to; 470 INPUTAN$ 480 IFLEN(AN$»20THENPRINTCHRS(145);:GOT0420 490 RC$=AN$+LEFT$(BL$,20-LEN(AN$» 500 FORX=lT012 510 RC$=RC$+STR$(0)+LEFT$(BL$,8) 520 NEXTX 530 PRINTH,RCS 540 NEXT I 550 CLOSE I:CLOSE 2:RETURN 560 REM ============= 570 REM POSTING 580 REM ============= 590 GOSUB2050 600 INPUT"ACCOUNT NmIBER" :AN 610 IFAN<10RAN>20THENPRINTCHR$(145)::GOT0600 620 GOSUB2140 630 PRINT"----------------------------" 66 Anatomy of the 1541 Disk Drive 640 PRINT"NO."lAN1" - "lAN$ 650 PRINT"------------------------" 660 PRINT"INCOME OR EXPENSE (I/E)?" 670 PRINT"------------------------" 680 GETX$:IFX$<>"I"ANDX$<>"E"THEN680 690 INPUT"MONTH (1-12) : "1M 700 IFM<10RM>12THENPRINTCHR$(145)1:GOT0690 710 PRINT"----------------------------" 720 PRINT"OLD CONTENTS : "lS(M) 730 PRINT"----------------------------" 740 INPUT"POSTING AMOUNT: ";PA 750 PRINT"----------------------------" 760 IFX$="I"THENS(M)=S(M)+PA:GOT0780 770 S(M)=S(M)-PA 780 PRINT"NEW CONTENTS : "lS(M) 790 PRINT"----------------------------" 800 RC$=AN$+LEFT$(BL$,20-LEN(ANS» 810 FORI=lT012 820 S$=STRS(S(I» 830 RC$=RC$+S$+LEFT$(BL$,10-LEN(S$» 840 NEXT! 850 PRINH 2," P"+CHR$ (2) +CHR$ (AN) +CHR$ (0) +CHR$ (1) 860 PRINT#l,RC$ 870 CLOSEl:CLOSE2 880 PRINT"FURTHER POSTING (Y/N)?" 890 GETX$:IFX$<>"Y"ANDX$<>"N"THEN890 900 IFX$<>"Y"THENGOSUB2050:GOT0600 910 RETURN 920 REM =================== 930 REM ACCOUNT SUMMARY 940 REM =================== 950 GOSUB2050 960 INPUT"ACCOUNT NUMBER: ";AN 970 IFAN<10RAN>20THENPRINTCHR$(145);:GOT0960 980 GOSUB2140 990 GOSUB2050:PRINTCHR$(145);CHR$(145)1 1000 PRINT"-------------------------" 1010 PRINT"NO.";AN;" - "lAN$ 1020 PRINT"-------------------------" 1030 PRINT"MONTH TOTAL" 1040 PRINT"-------------------------" 1050 TL=O 1060 FORI=lT012 1070 PRINTI;TAB(8)lS(I) 1080 TL=TL+S(I) 1090 NEXT I 1100 PRINT"-------------------------" 1110 PRINT"TOTAL";TAB(8) ;TL 1120 PRINTTAB(9);"=======" 1130 PRINT"RETURN FOR MORE" 1140 INPUTX$ 1150 CLOSE1:CLOSE2:RETURN 1160 REM ===================== 1170 REM DISPLAY ACCOUNT NAMES 1180 REM ===================== 67 Anatomy of the 1541 Disk Drive 1190 1200 1210 1220 1230 1240 1250 1260 1270 1280 1290 1300 1320 1330 1340 1350 1360 1370 1380 1390 1400 1410 l420 1430 1440 1450 1460 1470 1480 1490 1500 1510 1520 1530 1540 1550 1560 1570 1580 1590 1600 1610 16 20 1630 1640 1650 1660 1670 1680 1690 1700 1710 1720 1730 1740 GOSUB2050 OPEN1,8,2,"ACCOUNTS"+Y$+",L,"+CHR$(141) OPEN2,8,15 1=1 PRINT* 2," P"+CHR$ (2) +CHR$ (I) +CHR$ (0) +CHR$ (1) RC$="" FORX=IT020 GETU ,X$ RC$=RC$+X$ NEXTX INPUT*2,X IFX=50THENI340 PRINTI:" - ":RC$ I=I+l:GOTOI230 PRINT"RETURN FOR MORE" INPUTX$ CLOSEl:CLOSE2:RETURN REM =============== REM MONTH SUMMARY REM =============== GOSUB2050 INPUT"MONTH : ":M GOSUB2050 PRINT"---------------------------------" PRINT"NO. NAME CONTENTS· PRINT"---------------------------------" OPENl, 8,2, ,. ACCOUNTS"+Y$+" , L, "+CHR$ ( 141) OPEN2,8,15 TL=O FORAN=IT020 AN$="":S$="" PRINT#2,"P"+CHR$(2)+CHR$(AN)+CHR$(0)+CHR$(I) FORI=IT020 GET*I,X$ AN$=AN$+X$ NEXTI INPUT#2,F IFF<>50THENI590 GOT01670 PRINT#2,"P"+CHR$(2)+CHR$(AN)+CHR$(0)+CHR$(20+(M-l)*10) FORI=ITOI0 GETU,X$ S$=S$+X$ NEXT I TL=TL+VAL(S$) PRINT AN:TAB(6):AN$:TAB(26):S$ NEXT AN PRINT"---------------------------------" PRINT"TOTAL BALANCE":TAB(26):STR$(TL) PRINTTAB(26):"=======" PRINT"RETURN FOR MORE": INPUTX$:CLOSE1:CLOSE2:RETURN REM ============== REM YEAR SUMMARY REM ============== 68 Anatomy of the 1541 Disk Drive 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 2030 2040 2050 2060 2070 2080 2090 2100 2110 2120 2130 2140 2150 2160 2170 2180 2190 2200 2210 2220 2230 2240 2250 2260 2270 2280 2290 GOSUB2050 OPENl,8,2,"ACCOUNTS"+Y$+",L,"+CHR$(141) OPEN2,8,15 PRINT .. ------------------------------------ .. PRINT"NO. NAME YEAR BALANCE" PRINT .. ------------------------------------ .. TL:O FOR AN:IT020 PRINT,2,"P"+CHR$(2)+CHR$(AN)+CHR$(0)+CHR$(1) RC$= .... FORI=lT0140 GETU,X$ RC$=RC$+X$ NEXTI INPUT'2,F:IFF=50THEN1980 AN$=LEFT$(RC$,20) YB=O FORI:ITOI0 YB:YB+VAL(MID$(RC$,20+(I-l)*10,10» NEXTI TL=TL+YB PRINTAN,TAB(6),AN$,TAB(26);YB NEXTAN PRINT .. ---------------------------- .. CLOSEl:CLOSE2 PRINT"TOTAL BALANCE";TAB(26),TL PRINTTAB(26),"::=:===" PRINT"RETURN FOR MORE" INPUTX$ RETURN REM =========:========= REM PROGRAM HEADING REM =================== PRINTCHR$(147), PRINTTAB(4);"============================" PRINTTAB(4);"H 0 MEA C C 0 U N TIN G" PRINTTAB(4);"============================" PRINT:PRINT RETURN REM ================ REM READ ACCOUNT REM ================ OPENl,8,2,"ACCOUNTS"+Y$+",L,"+CHR$(141) OPEN2,8,15 PRINT'2,"P"+CHR$(2)+CHR$(AN)+CHR$(O)+CHR$(l) RC$= .... FORI=lT0140 GET'l,X$ RC$=RC$+X$ NEXT I INPUT'2,F IFF<>50THEN2300 PRINT"YEAR FILE OR ACCOUNT NOT FOUND!":PRINT PRINT"RETURN FOR MORE":INPUTX$ CLOSEl:CLOSE2:RETURN 69 Anatomy of the 1541 Disk Drive 2300 2310 2320 2330 2340 2350 2360 AN$=LEFT$(RC$,20) TL=O FORI=lT012 S(I)=VAL(MID$(RC$,20+(I-l)*10,10» TL=TL+S( I) NEXT I RETURN Program Documentation: Initialization: 100 llO-l30 140-280 Screen and character color set: blank character string defined: variable for account summaries dimensioned. Program heading displayed and current year read. Program functions displayed and choice read: corresponding subprogram called. Establish Accounts: 390-400 480 500-540 530 Any existing files of this year are erased and the new file is opened. Account name is placed in positions 1-20 of the record RC$. Month summaries are set to zero and placed in the record as string variables. The record is transferred with a trailing RETURN. posting: 590 800 810-840 850-860 The routine "Read Account" is called. This routine places the month summaries of the account in the variables S(l) to S(12). Account name is placed in the record. Account summary is placed in the record. Record is transferred. Account summary: 980 Desired account is read and the month summaries' are placed in variables S(l) to S(12). 1050-1090 Month summaries are displayed and the total (TL) is added up. 1110 Total displayed. Display Account Names: 1220 1230 Account number is initialized. The head is positioned over the corresponding 70 Anatomy of the 1541 Disk Drive record. 1240-1280 Account name is read out of the record in RCS. 1290-1300 If RECORD NOT PRESENT is sent over the error channel (error 50), the routine is broken off. 1320 Account number and name are displayed. Month Summary: Loop to read all accounts. position head over record. Read account name. Determine if account existsl stop if all twenty accounts have been defined. 1590 position over summary field of the desired month. 1600-1630 Read the month summary. Add month summary to total. 1640 Account number, account name and month summary are 1650 displayed. 1680 Total balance displayed. 1490-1660 1510 1520-1550 1560-1580 Year Summary: 1820-1970 1830 1850-1880 1890 1900 1920-1940 1950 1960 2000 Loop to read all accounts position head over record. Complete record read into RC$. Test if RECORD NOT PRESENT. Get account name from record. Read month summary, convert to numerical form and add to year summary (YS). Year summary (YS) is added to total (TL). Account number, account name and year summary displayed. Total balance (month balance) displayed. Read Account: 2190 2210-2240 2250-2260 2300 2320-2350 position over record given in AN. Read record into RCS. Test if RECORD NOT PRESENT. Account name read from record. Month summaries read from record, converted to numerical form and placed into the table S(l) to S(12) • 71 Anatomy of the 1541 Disk Drive 1.6 Disk Error Messages and their Causes If you cause an error while ,,?orking with the disk drive, the drive signals this by blinking the red LED. The LED blinks until you read the error channel of the disk drive or until you send a new command. First we want to see how to read the error message from the disk drive. In order to do this, the error/command channel must be opened with the secondary address 15: 100 OPEN 15,8,15 110 INPUT#15,A,B$,C,D 120 PRINT A,B$,C,D If no error has occurred, the following is displayed: o OK o o The first number is the error number, in this case zero, which. means no error has occurred. Next follows the error message (variable B$). The variables C and D contain the track and sector numbers, respectively, in which the error occurred, which is dependent on the type of error (mainly associated with hardware errors and block-oriented commands) • This routine accomplishes the same function: 100 OPEN15,8,15 110 GET#15,A$:PRINTA$;:IFST<>64THENl10 00, OK,OO,OO Here characters are read from the error channel until the end is recognized (status = 64). This gives the error message exactly as the BASIC 4.0 command PRINT DS$ When using BASIC 4.0, variables DS$ and DS are reserved variables which contain the complete error message and error number. Each access of these variables gives the error status of the last disk operation. Unfortunately, the Commodore 64 does not use BASIC 4.0, so these variables are meaningless in Commodore 64 BASIC (BASIC 2.0). Next follows the list of error messages that the DOS can recognize: 00. OK.OO.OO This message occurs when the last disk operation was error free or if no command or data was sent after the last error message. 72 Anatomy of the 1541 Disk Drive 01.FILBS SCRATCHBD.XX.OO This is the message after a SCRATCH command. The number XX denotes the number of filed that were erased. Since this is not really an error message, the LED does not blink. 20.READ BRROR.TT.SS This error means that the 'header' of a block was not found. It is usually the result of a defective diskette. TT and SS designate the track and sector in which the error occurred. Remedy: change defective diskette. 21.RBAD ERROR.TT,SS This is also a read error. The SYNC (synchronous) marker of a block was not found. The cause may be an unformatted disk, or no disk in the drive. This error can also be caused by a misaligned read/write head. Remedy: Either insert a diskette, format the disk, or have the read/write head aligned. 22,READ ERROR.TT.SS This error message means that a checksum error has occurred in the header of a data blocK, which can be caused by the incorrect writing of a block. 23.READ ERROR.TT.SS The error implies that a data block was read into the DOS buffer, but a checksum error occurred. One or more data bytes are incorrect. Remedy: Save as many files as possible onto another diskette. 24.RBAD ERROR.TT.SS This error also results from ~ checKsum error in the data block or in the preceding data header. Incorrect bytes have been read. Remedy: same as error 23. 25.WRITE ERROR.TT.SS This error is actually a VERIFY ERROR. After writing every block the data is read again checked against the data in the buffer. This error is produced if the data are not identical. Remedy: Repeat the command that caused the error. If this doesn't work, the corresponding block must be locked out from further use with the block-allocate command. 26.WRITE PROTECT ON.TT.SS An attempt was made to write to a disK with a write protect tab on it. Remedy: Remove write protect tab. 27,RBAD ERROR.TT.SS A checksum error occurred in the header of a data block. Remedy: Repeat command or rescue block. 73 Anatomy of the 1541 Disk Drive 28,WRITE ERROR,TT,SS After writing a data block, the SYNC characters of the next data block were not found. Remedy: Format disk again, or exchange it. 29,DISK ID MISMATCH,TT,SS The ID (two character disk identification) in the DOS memory does not agree with the ID on the diskette. The diskette was either not initialized or there is an error in the header of a data block. Remedy: Initialize diskette. 30,SYNTAX ERROR,OO,OO A command was sent over the command channel that the DOS could not understand. Remedy: Check and correct command. 31,SYNTAX ERROR,OO,OO A command was not recognized by the DOS, for example, the BACKUP command (Duplicate) on the 1541. Remedy: Do not use the command. 32,SYNTAX ERROR,OO,OO The command sent over the command channel was longer than 40 characters. Remedy: Shorten command. 33,SYNTAX ERROR,OO,OO A wildcard ('*' or '?') was used command. Remedy: Remove wildcard. in an OPEN or SAVE 34,SYNTAX ERROR,OO,OO The DOS cannot find the filename in a command. This may be because a colon was forgotten after the command word. Remedy: Check and correct command. 39,FILE NOT FOUND,OO,OO User program of type 'USR' was not found for automatic execution. Remedy: Check filename. 50,RECORD NOT PRESENT,OO,OO A record was addressed in a relative data file that has not yet been written. When writing a record this is not really an error. You can avoid this error message if you write the highest record number of the file with CHR$(255) when initializing it. This error will no longer occur upon later access. 51,OVERFLOW IN RECORD,OO,OO The number of characters sent when writing a record in a relative file was greater than the record length. The excess characters are ignored. 52,FILE TOO LARGE,OO,OO The record number of a relative file is too big: diskette does not have enough capacity. Remedy: another diskette or reduce the record number. 74 the Use Anatomy of the 1541 Disk Drive 60,WRITE FILE OPEN,OO,OO An attempt was made to OPEN a file that had not previously been CLOSEd after writing. Remedy: Use mode 'M' in the OPEN command to read the file. 6I,FILE NOT OPEN,OO,OO A file was accessed that had not been OPENed. Remedy: Open the file or check the filename. 62,FILE NOT ~UND,OO,OO An attempt was made tp load a program or open a file that does not exist on the diskette. Remedy: Check the filename. 63,FILE EXISTS,OO,OO An attempt was made to establish a new file with the name of a file already on the diskette. Remedy: Use a different filename or @: (to replace the old file). 64,FILE TYPE MISMATCH,OO,OO The file type use in the OPEN command does not agree with the file type in the directory. Remedy: Correct file type. 65,NO BLOCK,TT,SS This error message is given in association with the BLOCKALLOCATE command when the specified block is no longer free. In this case, the DOS automatically searches for a free block with a higher sector and/or track number and gives these values as the track and sector number in the error message. If no block with a greater number is free, two zeroes will be given. 66,ILLEGAL TRACK OR SECTOR,TT,SS If you attempt to use a block with the block commands that does not exist, this error is returned. 61,ILLEGAL TRACK OR SECTOR,TT,SS The track-sector combination of a file produces a nonexistent track or sector. 10,NO CHANNEL,OO,OO An attempt was made to open more files than channels available or a direct access channel is already reserved. 11,DIR ERROR,TT,SS The number of free blocks in "the DOS storage does not agree with the BAM. Usually this means the disk has not • been initialized. 12,DISK FULL,OO,OO Fewer than three blocks are free on the diskette or t~e maximum number of directory entries have been used (144 on the VIC 1541). 15 Anatomy of the 1541 Disk Drive 73,CBM DOS V.26 1541.00,00 The message is the power-up message of the VIC 1541. As an error message, it appears when an attempt is made to write to a disk that was not formatted with the same DOS version, for example, the forerunner of the CBM 4040, the CBM 2040 (DOS version 1.0). 74.DRIVE NOT READY,OO,OO When one attempts to use the disk without a diskette in the drive, this error message is returned. 75,FORMAT SPEED ERROR.OO,OO This error message occurs only on the CBM 8250. It indicates a deviation from the normal revolutions per minute while formatting. 76 Anatomy of the 1541 Disk Drive 1.7 Overview of Commands with a Comparison of BASIC 2.0 BASIC 4.0 - DOS 5.1 BASIC 2.0 BASIC 4.0 (abbrev) OPEN - Mode 'A' APPEND ( aP) BACKUP ( bA) CATALOG (CA) COLLECT (coL) CONCAT (conC) COpy (coP) DCLOSE (dC) DLOAD (dL) DOPEN (dO) DS$ , DS DSAVE (dS) HEADER ( hE) I( initialize) RECORD (reC) RENAME ( reN) SCRATCH (sC) LOAD"$",B & LIST V(alidate) C(opy) CLOSE LOAD" ••• ",B OPEN .... ,8, ..... OPEN 1,B,15 SAVE" ••• " ,B N(ew) I(nitialize) P R(ename) S(cratch) ... ... DOS 5.1 @$ or >$ @V or >V @C: •• or >C: •• ©file or /file @ or > @N: •• or >N: •• @I or >1 @R: •• or >R: •• @S: •• or >S: •• This table lists the different versions of BASIC. The DOS 5.1 is found on the TEST/DEMO disk and will be described in section 4.2.1. The essential difference between BASIC 2.0 and BASIC 4.0 is that with BASIC 2.0, each command is executed by the disk control system (DOS) and must be sent over channel 15. The disk commands of BASIC 4.0 manage this channel themselves (with the exception of INITIALIZE). For example, the command HEADER DO,"DISKl",IHJ generates the same sequence of commands necessary in BASIC 2.0, namely: OPEN l,B,15,"N:DISKl,HJ" CLOSE 1 Here are are the specifics of the BASIC 4.0 commands: Note the following parameters: Ifn dn da logical file number drive number - drive 0 (DO) or drive 1 (Dl) with a double drive, or DO for a single drive device address of the disk drive (U4 to U31) Information in parentheses is optional. The standard parameters DO and UB will be used (meaning Drive 0 and Unit B) • 77 Anatomy of the 1541 Disk Drive APPEND: T'i1iSCommand allows data to be added to a sequential file, which is accomplished in BASIC 2.0 with the OPEN-command mode A. This command has the following format: APPEND#lfn,"filenamen(,Ddn,Uda) For example, should the sequential file "SEQU.l" be on drive 0, the following statements are necessary to add a data record to it: 100 APPEND#l,"SEQU.l",DO 110 PRINT#! ,X$ 120 CLOSE 1 BACKUP: With this command, a complete diskette can be copied. The BACKUP command can only be used with a dual disk drive (such as the 4040), however. Notice the format of this command: BACKUP Ddn TO Ddn(,Uda) It is important that either DO to Dl or Dl to DO be given. An example: The diskette in drive 1 is supposed to be copied onto the disk in drive O. To this end, give the following command: BACKUP Dl TO DO CATALOG: The CATALOG command of BASIC 4.0 has the advantage that the program in the computer's memory is not erased, as is true in BASIC 2.0. The format of the command: CATALOG (Ddn,Uda) If no drive number is given for a double drive, the contents of both drives are given. With a single drive, CATALOG DO is assumed. An example: CATALOG DO The contents of the disk in drive 0 will be displayed. COLLECT: This command corresponds with the VALIDATE command of BASIC 2.0. The syntax of this command looks like this: COLLECT (Ddn) 78 Anatomy of the 1541 Disk Drive CONCAT: CON'CAT concatenates sequential files, in which one file to be made from the data of two files. The format: CON CAT (Ddn,)"filel" TO (Ddn,)"file2" is (ON Udal Suppose you want to combine the data of the files "SEOU.2" in drive 0 and "SEOU.l" in Dl. To accomplish this, issue the following command: CON CAT DO,"SEOU.2" TO Dl,"SEOU.l" COPY: with this command files can be copied from one drive to the other (except relative files). The command is useless with a single drive. The syntax looks like this: COpy (Ddn,)("filel") TO (Ddn,)("file2") To copy all files (for example, from drive 0 to drive 1), use the following command: COPY DO TO Dl DCLOSE: The command DCLOSE has the same function as the simple CLOSE command, with the following exceptions: DCLOSE closes all files closes file number 1 DCLOSE#l DCLOSE# 1 ON U9 closes the logical file #l on device address 9 closes all files on device address 8 DCLOSE U8 The command has the following syntax: DC LOSE (#lfn) (ON Udal DLOAD: The command DLOAD has the advantage that the standard device address 8 used. The format: DLOAD "program" (, Ddn) ( , Uda) For instance, if you want to load the program "PRG.2" from drive 0 or from a single drive, give the following command: DLOAD "PRG.2" Drive 0 (DO) is the default value. 79 Anatomy of the 1541 Disk Drive OOPEN: T1iTS command of BASIC 4.0 is very comprehensive. The following format verifies this: DOPEN#lfn,"file H ( ,Ddn) (,Uda) (,fileparameter) The peculiarity of this method of opening is the file parameter. There are two file parameters, that have the following function: : 'L'-parameter : 'W'-parameter : Mode of operation YES NO NO YES NO NO A relative file is opened. A sequential file is opened for writing. A file is opened for reading(REL,SEO,PRG,USR): In addition to the 'L' parameter the record length must be given (such as LBO). A DOPEN command of this type looks like this: DOPEN#1,"FILE.REL",DO,L80 Here a relative file is opened with a record length of 80 bytes. The declaration of the file parameter is only necessary once, at the establishment of the file. All later openings of the file can occur without the parameter declaration. DS$ Ii OS: After a disk error, the complete error message can be displayed with PRINT DS$ or just the error number with PRINT DS. of course, the error can be read within a program and the appropriate branch made. For example: 100 IF DS = 26 THEN GOTO ••• DSAVE: A program can be saved on disk following format is to be noted: with this command. Tte DSAVE (Ddn,)"programname"(,Uda) BEADER: x-dISk is formatted with the HEADER command in BASIC 4.0. It corresponds to the NEW command in BASIC 2.0. The syntax of the command: 80 Anatomy of the 1541 Disk Drive or HEADER "diskname",DO,Iid(U,da) HEADER Ddn,"diskname" ,lid Here there are two possibilities to designate the drive. The id is the diskette identification. If it is not given, the disk is presumed to be formatted and is merely given a new name and all files are erased. RECORD: This command corresponds to the position command of BASIC 2.0 (DOS 2.6). The read/write head can be positioned over a record in a relative file, without the need to send the position over channel 15. The syntax of this command illustrates how easy this positioning is: RECORD#lfn,rn(,bp) The logical file number is obtained from the opened relative file. 'rn' is the record number (1-65535) and 'bp' is the position within this record (1-254). An example: You want to position the head over the twelfth byte of the 128th record of a relative file opened with the logical file number 2. The following commaniC accomplishes this: RECORD#2,128,12 RENAME: This RENAME is similar to the RENAME of BASIC 2.0. The format of this command: RENAME (Ddn,)" old name" TO "new name" ( , Uda ) SCRATCH: This method of erasing files is essentially easier because files can be erased with one command. The format of this command: SCRATCH (Ddn,)"file"(,Uda) After entering a SCRATCH command the message "ARE YOU SURE?" which allows the command to be stopped. If the file is really supposed to be erased, answer 'y' else 'N'. After erasing the file, the message "FILES SCRATCHED" appears on the screen. 81 Anatomy of the 1541 Disk Drive Chapter 2: Advanced Disk Programming 2.1 Direct Access of any Block of the Diskette When handling files and programs on the cribed in Chapter 1, we didn't have to with the organization on the diskette, operating system (DOS) took care of these diskette, as desconcern ourselves because the disk details for us. But the DOS offers the capability of accessing each individual block on the diskette. This gives us a lot of flexibility - ranging from manipulation of individual files to creating completely new data structures. In order to access a block directly, a channel is OPENed to a data buffer within the 1541 disk drive. It is over this channel that data is transmitted. The data buffer serves as an intermediate storage place for the data that is read from the diskette or written to the diskette. In order to inform the DOS that we want to work with direct access commands, we use a special filename in the OPEN command: OPEN 1,8,2,-'Using this command, logical file number 1 on device 8 (the disk drive), is associated with a direct access file. Channel 2 serves to transmit data to and from the disk drive. The channel number (secondary address in the OPEN command) may be 2 through 14. Channels 0 and 1 are reserved for LOAD and SAVE and channel 15 is the command channel. The choice of a secondary address is arbitrary. You may not use the same secondary address simultaneously, since the DOS, upon encountering the second OPEN command with the same secondary address, closes the previous file using this channel number. This also occurs when working with sequential or relative files. This form of the OPEN command causes the DOS to search for a free data buffer and assign it to that channel. By using a GET# statement immediately after the OPEN we can find the buffer number that the DOS assigns: 100 OPEN 1,8,2,"#" 110 GET#!, A$ 120 PRINT ASC(AS+CHR$(O» RUN 3 In this case, buffer three was assigned. The buffer numbers range from 0 to 4. Each buffer can hold 256 characters of data. The buffers are located in the following memory 82 Anatomy of the 1541 Disk Drive locations in the VIC 1541: Buffer number o 1 2 3 4 Memory location $300-$3FF, 768-1023 $400-$4FF, 1024-1279 $500-$5FF, 1280-1535 $600-$6FF, 1536-1791 $700-$7FF, 1792-2047 Buffer 4 is normally unavailable, because the BAM is stored there. If we work with sequential or relative files at the same time, buffer 3 is also unavailable, because it is used for the directory. If we want to associate a specific data buffer for direct access, we can assign it with the OPEN command. This associates buffer 3 ($600-$6FF) with channel number 2, assuming it is still free. Unless you have a pressing reason to use a specific buffer, you should leave the choice of the buffer up to the DOS, because the choice of a definite buffer increases the possibility that it will not be available. After opening a channel, you should check the error channel. 130 OPEN 15,8,15 140 GETtIS, A$ : PRINT A$: : IF ST<>64 THEN 140 If the buffer is already in use, you will receive the error message 70,NO CHANNEL,OO,OO If no other files are open, you can open up to 4 channels for direct access. The following example illustrates this: 10 20 30 40 50 60 70 100 110 120 130 OPEN 1,8,15,"10" : 1=2 : REM ERROR CHANNEL OPEN 2,8,2, "t" GOSUB 100 OPEN 3,8,3, "i" GOSUB 100 OPEN 4,8,4, "i" GOSUB 100 OPEN 5,8,5, nt" GOSUB 100 OPEN 6,8,6, 't" GOSUB 100 END GETtI,A$:PRINT ASC(A$+CHR$(O» 1=1+1 : REM BUFFER NUMBER GETil,A$ : PRINT A$: : IF ST<>64 THEN 120 RETURN When RUN, the above program produces the following output: 3 83 Anatomy of the 1541 Disk Drive 00, OK,OO,OO 2 00, OK,OO,OO 1 00, OK,OO,OO a 00, OK,OO,OO 199 70.NO CHANNEL,OO.OO As you see, attempting to open a fifth channel for direct access fai Is. Transmitting data to and from the buffer usually takes place using the GET#, INPUT# and PRINT# statements. If a buffer contains pure text (alphanumeric data) which is not longer than 88 characters and is separated using CR (Carriage Return, CHR$(13», it can be read using INPUT#. However, if the buffer contains control characters or the text is separated using commas or colons, the INPUT# statement fails. Then we must use the GET# statement, which retrieves only one character at a time. GET# does not ailow null values (CHR$(O» to be read. In this case, GE1# receives an empty string and you must check for this condition as below: 100 GET'2, A$ : IF A$ + •• THEN A$ = CHR$(O) A simpler alternative to the GET# statement is to use the statement INPUT*, as is described in section 4.3.1. Here you can declare how many characters are to be read into a string. It also handles null values (CHR$(O». You can read almost the entire buffer (255 characters are possible) with one command. In the next section, all commands used for direct access are described in detail. Keep the following points in mind when using direct access commands. When using direct access commands, you must explicitly cause the blocks on the diskette to be read or written. The direct access commands are transmitted over command channel 15. The data that is read from or written to a buffer are transmitted over a separate channel that is associated with that buffer. Both channel 15 and the separate channel must be OPENed before transmission can begin. 1) A PRINT# statement to command channel 15, sends a direct access command to the DOS. 2) A PRINT# statement to channels 2 thru 14 sends data to a buffer. 3) An INPUT# or GET# statement to command channel 15 re- 84 Anatomy of the 1541 Disk Drive turns any error messages detected by the DOS. 4) An INPUT. or GET. statement to channels 2 thru 14, reads the data from the buffer. If you are ready to work wi th the block commands and want to display individual blocks on the screen or change them, you can use the DOS monitor in section 4.6, which provides a simple and easy way of doing so. 85 Anatomy of the 1541 Disk Drive 2.2 The Direct Access Commands 2.2.1 The Block-Read Command B-R The block-read command instructs the 1541 to read a block from the diskette into a buffer of a previously opened direct access file. The block-read command is sent over the command channel (secondary address 15) to the disk drive. The block-read command can be shortened to B-R. Because this command does not read the first byte of the block, you can substitute the command Ul to read a block. The command has the following syntax: Ul channel number drive track sector You must give the channel number that you used when OPENing the direct access file. Next follows the drive number, which is always zero for the VIC 1541, and then the track and sector numbers of the block you want to read. 10 OPEN 1,8,15 20 OPEN 2,8,2, "#" 30 PRINT#l, ·Ul 2 0 18 0" This reads the contents of track 18 sector 0 into the buffer belonging to channel 2. Now you can read the data from this buffer with GET#2. 40 GET# 2, A$, B$ 50 PRINT ASC(AS), ASC(B$) 18 1 Now we have read and displayed the first two bytes in the buffer. Sector 0 of track 18 contains a pointer to the first directory block (track and sector) and the BAM for the diskette. In the demo program DISPLAY T&S on the TEST/DEMO diskette (section 4.2.7) this command is used in order to read the BAM from the disk and to graphically display each record on the disk. We can read all 256 bytes of the block from the buffer with the GET# statement; in our example we will read the diskette name and ID from position 144. The blocks which comprise a file are chained to each other. The first two bytes of each file block contains a pointer to the track and sector of the following block. Using this information, you can piece together the usage of disk space for a file. A track pointer of zero indicates the last 86 Anatomy of the 1541 Disk Drive block of the file and the pointer which usually contains the sector number now contains the number of bytes of the last block which are part of this file. The first sector of a file can be read with our program in section 4.1.1. The following small program displays all of the remaining tracks and sectors that are part of the file. 100 110 120 130 140 150 160 170 180 OPEN 1,8,15 OPEN 2,8,2, ''It'' INPUT "TRACK AND SECTOR ·,T,S PRINT#l,"Ul 2 O",T,S GETlt2, T$, S$ T = ASC(T$+CHR$(O»: S = ASC(S$+CHR$(O» IF T=O THEN CLOSE 2 : CLOSE 1 : END PRINT "TRACK",T,"SECTOR",S GOTO 130 Enter 18 and 0 as track and sector to follow the blocks for the BAM and directory. 2.2.2 The Block-Pointer Command B-P The diskette name is located starting at position 144 of track 18, sector O. using the above example, we have to read the first 143 bytes of the buffer in order to be positioned at the diskette name. But the DOS has an easier way to do this. To access any desired byte of a buffer, you can use the block-pointer command. using the block-pointer command the DOS moves to an exact position within the buffer. The block-pointer command can be shortened to B-P. The syntax is the following: B-P channelnumber position Now we can read the diskette name directly: 100 110 120 130 140 150 160 170 OPEN 1,8,15 OPEN 2,8,2, ·It'' PRINTltl,"Ul 2 0 18 0" PRINTlIl,"B-P 2 144" FOR I = 1 TO 16 : REM MAXIMUM LENGTH GET#2, A$ : IF A$=CHR$(160) THEN 170 PRINT A$, : NEXT CLOSE 2 : CLOSE 1 Here we first read the block, set the buffer pointer to position 144 and then read and print the diskette name which has a maximum length of 16 characters. A shifted space (CHR$(160» indicates the end of the diskette name. The bytes in the buffer are numbered 0 through 255, the first byte having the number O. The buffer pointer is auto87 Anatomy of the 1541 Disk Drive matically set to zero by reading a block with vI. You can, for example, read byte number 2 after reading the name. You do this by setting the buffer pointer to this value. PRINT#l, "B-P 2 2" 2.2.3 The Block-Write Command B-W The block-write command allows us to write the contents of a buffer to a desired block on the diskette. with this, you can write the block one has sent to the buffer within the disk drive. It is possible to read a block into the buffer with the block-read command, change some bytes, and then write the block back. The block-write command can be shortened to B-W. Because this B-W command writes the contents of the buffer pointer, one usually uses the U2 command which always sets the buffer pointer to 1. The syntax of the command is analogous to the B-R command: V2 channelnumber drive track sector 100 110 120 130 140 OPEN 1,8,15 OPEN 2,8,2, "#" PRINT#2, "TEST DATA" PRINT'l, "U2 2 0 1 0" CLOSE 2 : CLOSE 1 Here the text "TEST DATA" will be written to the buffer associated to channel 2 and then written to track 1 sector 0 of the diskette. The V2 command does not change the contents of the buffer. Here's an example of using the block-write command to change the diskette name that we read in the last section. For this we must fill the new name with 16 characters ending with a shifted spaces CHR$(160), so that we can write it to the disk. We will again use the block-pointer command to set the buffer pointer directly to the desired position within the buffer. 100 110 120 130 140 150 160 170 180 190 OPEN 1,8,15 OPEN 2,8,2, "I" PRINTl1,"Ul 2 0 18 0" PRINT,l,"B-P 2 144" A$="NEW FILE NAME" IF LEN(A$)<16 THEN A$=A$+CHR$(160) PRINT#2,A$; PRINTl1,"U2 2 0 18 0" CLOSE 2 PRINTI1,"IO" : CLOSE 1 88 GOTO 150 Anatomy of the 1541 Disk Drive First we read track IB sector 0 into the buffer, set the buffer pointer to the position of the diskette name and write a new 16 character name to the buffer. Note that the diskette name is changed in the buffer only. But in line 170, the buffer contents are written to the same block which changes the name permanently on the diskette. Next channel 2 is closed. Finally the diskette is initialized so the BAM and name in the DOS memory are updated. Get the directory with LOAD"$",B LIST on the screen to verify that the diskette name has changed. 2.2.4 The Block-Allocate Command B-A The block-allocate command has the task of indicating in the BAM (block availability map) is a particular diskette block is being used. The block allocate command can be shortened to B-A. For program, sequential or relative files, as diskette blocks are used, the BAM is updated to note that the block is no longer available. But blocks written using the direct access commands are not automatically allocated. When blocks used in this manner are not allocated, the possibility exists that they will be overwritten when other files are used. The block-allocate command can be used to prevent this overwriting. The block-allocate command has the following syntax: B-A drive track sector With this the corresponding block in the BAM is marked as allocated and is protected from being overwritten by other files. If the block was already allocated, the error channel returns error message 65,'NO BLOCK'. lOO 110 120 130 140 OP EN 1, B , 15 INPUT "TRACK, SECTOR ":T,S PRINT#l, "B-A O":T:S INPUT#l, A$,B$,C$,D$ PRINT A$","B$","C$","D$ Using this program you can input a track and sector number of a block that you want to allocate. If the block is still free, it was allocated and the message 00, 01(,00,00 is returned. If that block is already allocated, the message 65,NO BLOCK,TT.SS is returned. In this case TT and SS contain the next higher numbered free block on the diskette. This tells you that the requested block is allocated but the block at TT,SS is still available. If error message 65 returns zeroes as the track and sector numbers, it means 89 Anatomy of the 1541 Disk Drive that no block with a higher track and/or sector number is available. The following program automatically allocates the next free sector: 100 110 120 130 140 150 160 170 180 190 OPEN 1,8,15 INPUT "TRACK, SECTOR ";T,S PRINT.l, "B-A O";T;S INPUTll, A$,B$,TT,SS IF A$ = "00" THEN 190 IF A$<>"6S" THEN PRINT A$","B$","TT","SS IF TT=O THEN PRINT "NO MORE FREE BLOCKS" IF TT=18 THEN TT=19 : SS=O T=TT : S=SS : GOTO 120 PRINT "TRACK" TT "SECTOR" SS "ALLOCATED." END END The test for track 18 in line 180 prevents a block in the directory from being allocated. An additional error message in connection with the B-A command is interesting. If one attempts to allocate a block that does not exist, for example, track 20 sector 21, one received the error message 66,ILLEGAL TRACK OR SECTOR,20,21 Marking a block as allocated in the BAM prevents it from being overwritten by other files. The block will be recognized as allocated until the command VALIDATE (COLLECT in BASIC 4.0) is issued. The VALIDATE command rebuilds a new BAM by rechaining the blocks of individual files and marking each block as belonging to a a new BAM. Unclosed files, marked in the directory with * are deleted. All blocks allocated with the B-A command and those not belonging to a properly closed file are freed. So, if you allocate blocks that do not belong to a file that appears in the directorl, you should not use the VALIDATE command, or the blocks will be freed, thus destroying your file. 2.2.5 The Block-Free Command B-F The block-free command performs the opposite function of the block-allocate command. It marks a block as not allocated (free) in the BAM. The block-free command can be shortened to B-F.The syntax is analogous to the block-allocate command: B-F drive track sector 100 OPEN 1,8,15 110 PRINTll, "B-F 0 20 9" Here the block in track 20 sector 9 is freed in the BAM. If this block is already free, no error occurs. 90 Anatomy of the 1541 Disk Drive Allocating and freeing blocks has an effect only on the blocks used by program, sequential or relative file by the DOS. The block-write and block-read commands do not check the BAl4 before overwriting blocks. With these commands you can write to blocks marked as allocated in the BAM. If, for example, you have a disk containing only direct access files, it is in principle unnecessary to allocate written blocks because no other files will be written on the diskette. In this case, you can use the directory blocks in track 18 and have 672 blocks available on the VIC 1541 diskette. 2.2.6 The Block-Execute Command B-E The block-execute command allows a block to be read from diskette into a buffer and then the contents of the buffer to be executed as a machine language program. You can cen write routines that the DOS is supposed to execute with the B-W or U2 command to a sector and later load it into a buffer with the block-execute program where it will be executed as a machine language program. Naturally, this presupposes knowledge of the internal workings of the DOS. If you want to use the B-E command, you usually give the buffer number in the OPEN command, in case the machine language program is not relocatable and is written for a specific buffer. The block-execute command has the following syntax: B-E channelnurnber drive track sector 100 OPEN 1,8,15 110 OPEN 2,8,2, "#3" 120 PRINT#l, "B-E 2 0 17 12" Here buffer 3 ($600-$6FF) is assigned to channel 2. The contents of track 17 sector 12 is loaded into this buffer and there the machine language program is executed. The block-execute command is a combination of the block-read and memory-execute commands. Examples of the design of machine language programs to execute in the DOS are found in section 2.4 by the memory commands. 91 Anatomy of the 1541 Disk Drive 2.3 Uses of direct access What do the direct access commands permit us to do? Here is a sample of their use: By manipulating individual sectors you can make changes to the BAM sector (Track 18, Sector 0) such as changing the diskette name or 10. You can make changes to the DIRECTORY (beginning at Track 18, sector 1). Each file entry in the directory has unused space. You can use the unused space to store additional information. You can change file names in the directory by using direct access commands. You can follow the "chaining" of the blocks in a file to determine if the file is intact. You can CLOSE an unclosed file by setting bit 7 of the file type indicator in the directory. For example, you can change the file type indicator from $02 to $82. Normally these files are indicated in the directory with an asterisk: after the above change the asterisk will disappear. Each file entry also contains a "lock" which disallows deletion (SCRATCH command). If you set bit 6 of the file type then the file is said to be locked and not available for deletion. These entries have the < symbol after the type designation in the directory listing. Using this bit of knowledge, you can protect important programs on your diskette from accidental erasure. More information on this topic is found in section 4.1. If you are interested in making such changes, you may want to read an entire sector and display it on the screen, change it, and write it back again. Such a program called the DISK MONITOR is described in section 4.6. Before you begin with such experiments, however, you should make a copy of your diskette. A directory or BAM error can result in the loss of the entire diskette contents. Have you ever accidentally scratched a program or file from a diskette? As long as you haven't written any other programs or data to the diskette, you can recover this scratched file. Scratching a file simply sets the file type to 0 in the directory and frees the allocated blocks. You need only search the directory entries for the file and restore the file type: $81 for SEQ, $82 for PRG, $83 for USR, and $84 for REL. After restoring the file type, you should use the VALIDATE command to reallocate the blocks again (for example: OPEN 1,8,15:PRINT#1,"VO"). 92 Anatomy of the 1541 Disk Drive other uses of direct access can provide the means for creating new data structures that the DOS normally does not recognize. You can undertake the management of the new file yourself, and use the direct access commands for reading and writing. Such a data structure is the ISAM file. ISAM is an abbreviation for Indexed Sequential Access Method. With an ISAM file, you can directly access each record, similar to the relative file. However, access is not by the record number, however, but by a key or index. This index is a field within the record. If, for example, a record consists of 5 fields, last name, first name, street, city/state and zip code, last name can be defined as the access key. To to read the record Muller, the command is simply' read record "Muller"'. We need not concern ourselves with record number or other ordering criteria and can select which record we want to read, change, write or erase with clear text. In such an ISAM file system, the index is usually saved separately, together with the information where the data record can be found on the disk. Such an ISAM file management with very powerful additions as described here, is found along with other features in the program development system MASTER 64, also available for the Commodore 64 from Abacus Software. 93 Anatomy of the 1541 Disk Drive 2.4 Accessing the DOS - The Memory Commands In section 2.2.6 we saw a way to load a program into DOS memory and execute it. With the memory commands, we can access each byte of the DOS and execute programs in RAM and ROM. For instance, we can access the work space of the DOS and read the number of free blocks on the disk or get the disk name from the BAM buffer. By writing into the DOS RAM we can change constants such as the device number of the drive or the number of read attempts for a block until an error message results. Furthermore, we can execute routines inside the DOS memory. These can be DOS ROM routines or your own, that are stored in a buffer and executes there. Of course this presumes knowledge of 6502 machine language and of the method of operation of the DOS. We hope this book is be helpful for the latter. Now follows a description of the commands and examples of their use. 2.4.1 The Memory-Read Command M-R Using this command, you can access each byte of the DOS. The memory-read command can be shortened to M-R. The memory-read command is transmitted over the command channel. The byte read is then returned over the command channel where it can be retrieved with GET#. The syntax of the command looks like this: M-R CHR$(LO) CHR$(HI) LO and HI signify the low and high bytes of the address in the DOS that should be read. The following program asks for an address and reads the contents of the address out of the DOS. 100 110 120 130 140 150 160 INPUT"ADDRESS ";A HI = INT (A!256) LO = A-256*HI OPEN 1,8,15 PRINT#I, "M-R";CHR$(LO);CHR$(HI) GET#!,AS PRINT ASC(A$+CHR$(O» For instance, if we want to know the number of free blocks on a diskette, we don't have to re~d the entire directory, rather we can read the appropria~ ~ bytes directly from the DOS storage. This may be necessary i~ files are to be established by a program and you don't know if there is enough space on the disk. 100 OPEN 1,8,15,"10" 110 PRINTll, "M-R" CHR$(250) CHR$(2) 120 GET#!, A$ : IF A$='''' THEN A$=CHR$ (0) 94 Anatomy of the 1541 Disk Drive 130 140 150 160 PRINT#l, "M-R" CHR$(252) CHR$(2) GET#l, B$ : IF B$="· THEN B$=CHR$(O) PRINT ASC(A$) + 256 * ASC(B$) "BLOCKS FREE" CLOSE 1 With this syntax, an M-R command must be given for each byte that is to be read. As you can gather from the DOS listing and through checking and verifying, one can read more than one byte at a time with a M-R command. You need only give the number of bytes to be read as the third parameter: M-R CHR$(LO) CHR$(HI) CHR$(NUMBER) We can use this to read the name of a diskette from the BAM buffer storage. Before this can be done, the diskette must be initialized so that the current diskette name is stored in the buffer at address $700, out of which we will read the name of the disk with the M-R command. 100 110 120 130 OPEN 1,8,15, "10" PRINT#l, "M-R" CHR$(144) CHR$(7) CHR$(16) INPUT#l, A$ PRINT AS This is a simple way to read the name of the diskette (16 characters padded with shifted spaces (CHR$(160)). With this you can check if the correct diskette is in the drive. The disk buffer can also be read using this method. It also allows parts of the DOS to be manipulated by copying the contents of the ROM to a buffer where it can be changed and executed. This is explained in the next two sections. 2.4.2 The Memory-Write Command M-W The complement command of memory-read is the command to write data in the DOS storage memory-write or M-W. writing is allowed only to DOS RAM - page zero, stack, and buffers. It is possible to send several bytes with one command. The syntax look like this: M-W CHR$(LO) CHR$(HI) CHR$(NUMBER) CHR$(DATAl) CHR$(DATA2) The number of bytes as specified by NUMBER can be transmitted, theoretically 255, but because the input buffer holds only 40 characters, the number of bytes is limited to 34. A possible use of this command is to change the address number (see program 'DISK ADDRESS CHANGE', section 4.2.3). The address is stored in two memory locations in page zero. The device number plus $20 (32 decimal) is stored in address $77 (119 decimal) for LISTEN, for receiving data from the computer. The address immediately following contains the 95 Anatomy of the 1541 Disk Drive device number plus $40 (64 decimai) for TALK, for sending data to the computer. Because the addresses are saved separately. It is possible to use different send and receive addresses. In the following example, the receive address is set to 9 and the send address to 10. 100 OPEN 1,8,15 110 PRINTt1, "M-W· CHR$(119) CHR$(O) CHR$(2) CHR$(9+32) CHR$(10+64) 120 CLOSE 1 140 OPEN 1,9,15 150 OPEN 2,10,15 160 PRINTtl,"IO" 170 INPUT#2,A$,B$,C$,D$ 180 PRINT A$",UB$","C$","D$ 00, OK,OO,OO Programs cannot be loaded this way because the DOS will try to load the program using the same address that the filename was sent under. Changing the device number is necessary if you want to use more than one disk drive with a single computer. To this end, change the device address of the second drive to 9. This software change remains in effect only until a reset (for example, turning the drive off). If the change needs to be permanent, you can change the with DIP switches or cut the circuit board jumper inside the drive. Because many parameters of the DOS are in RAM, you can make extensive changes to the function of the DOS, such as the step size, with which the number of sectors per track is determined (address $69 (105 decimal), normally contains 10). We can also specify the number of attempted reads until an error results (address $6A (106 decimal), contains 5). More addresses of parameters can be found in section 3.1.2. 2.4.3 The Memory-Execute Command M-E Using this command you can call up and execute machine language programs in the DOS memory. The memory-execute command can be shortened to M-E. The programs must end with RTS (Return from Subroutine, $60). The syntax of the command: M-E CHR$(LO) CHR$(HI) Again, LO and HI are the low and address of the machine language call up routines in the DOS ROM written to a buffer with M-W 96 high bytes of the starting routine. It is possible to as well as our own routines and there executed. As an Anatomy of the 1541 Disk Drive example, you can call up a routine that creates an error message. For example, address $EFC9 is the entry point for message 72, 'DISK FULL'. The, example looks like this: 100 110 120 130 OPEN 1,8,15 PRINT#l,"M-E" CHR$(20l) CHR$(239) INPUT#l,A$,B$,C$,D$ PRINT A$ .," B$ ",. C$ .," D$ In line 110, the address $EFC9 is divided into a low byte of $C9 (201) and high byte of $EF (239) and sent as the parameters of the M-E command. Then the error channel is read and the message displayed. 72.DISK FULL,OO,OO If you want to run your own programs in the 1541 drive, the program should be w·ritten to a buffer and .there called with M-E. Should this program be used more often, the contents of the buffer can be written to a block on the diskette. It can then be executed with the B-E command, which loads the contents of the block in the buffer and then automatically starts the routine. As a suggestion for your own program in DOS, you can display the directory in a different form, with additional parameters, similar to the program in section 4.1.1. In addition, you could count the number of files on the disk and display that. using such a routine you can get a much clearer understanding of how the directory is created in the DOS listing. If you are clear on the matter of the new directory format, you are ready to take the additionel parameters from the directory entries and assemble them in the desired format. 2.4.4 The User Commands U Using the USER commands there are two possible ways of executing programs in the drive. The user commands have the following syntax: UX X can be a letter from A to J or a digit from 1 to 9 or 'I' (which takes the place of 10). When a command is called, a jump is made to the following addresses in DOS: UA UB UC Ul U2 U3 U4 UE U5 u6 U7 un UF UG $CD5F $DC97 $0500 $0503 $0506 $0509 $050C substitute for 'Block-Read' substitute for 'Block-Write' 97 Anatomy of the 1541 Disk Drive UH UI UJ U8 U9 U: $050F $FFOI $EAAO reset You are already acquainted with the commands Ul and U2 (also UA and UB)1 they serve as substitutes for BLOCK-READ and BLOCK-WRITE. The commands U3 to U8 (UC to UH) jump to addresses within buffer 2 (address $500 (1280) - see section 2.1). If you want to use several commands, a jump table to individual routines can be placed therel if only one user command (U3) is used, the program can begin directly at $500. The user command UJ jumps to the reset vectorl drive is then reset. 100 110 120 130 the disk OPEN 1,8,15 PRINT#I,"UJ" FOR 1=1 TO 1000 : NEXT GET#I,A$ : PRINT A$ : IF ST<>64 THEN 130 73,CBM DOS V2.6 1541,00,00 Line 120 waits for the reset to take place. Then the initialization message is retrieved in line 130. By using the user commands, parameters can be passed to the routines. The complete command string is put in the input buffer at $200 (512). possible parameters are addresses, command codes, and filenames. This way, the user commands can be utilized to expand the commands of the disk or to realize a new data structure. Whole user commands can replace the M-E command with its corresponding addresses 1 the user-call is shorter and clearer. 98 Anatomy of the 1541 Disk Drive Chapter 3: Technical Information 3.1 The Construction of the VIC 1541 3.1.1 Block Diagram of the Disk Drive - 1''03 ! Q .) I(" iL N < o-; C- :> :> N N Ltl II) !' 0 ~ . 0:: '::lO:}OW . )(S-':O ' til 0. al til 0 al < ~ Q Q .... < ~ < 0-; :> [: ) :t H v\ \j 0 N Q III IC '-- til 0 Q:l ) IIQ Jli :£ < z < ....- til til Eo< ~ "'" a:}l.lM-peag § .IO:}OW 6uldda:}s ' H K :}:>a:}o.Id '" -a:}l.IM " 0:: H :::> Il< U 99 r--N N Ltl IC ....... f1 p r- - I U IlQ H t-l < 0-; 0:: IlQ til - Anatomy of the 1541 Disk Drive 3.1.2 DOS Memory Map - ROM, RAM, I/O Memory map of the VIC 1541 disk drive 65535 $FFFF 16K Control system $eooo 49152 7183 $lCOF VIA Disk Control 7168 $lCOO 6159 $180F VIA serial bus 6144 $1800 2047 $07FF 2 K RAM o $0000 100 Anatomy of the 1541 Disk Drive Layout of the I/O Ports (VIA 6522) VIA 6522 1, Port for Serial Bus S1800 S1801 S1802 S1803 Port B Port A Direction of Port B Direction of Port A S1805 Timer PB PB PB PB PB PB CB DATA IN DATA OUT CLOCK IN CLOCK OUT ATN A Device address ATN IN 0: 1: 2: 3: 4: 5,6: 2: VIA 6522 2, Port for Motor and Read/Write Head Control SlCOO SlCOl SlC02 SlC03 Port B, control port Port A, data to and from read/write head Direction of Port A Direction of Port B PB PB PB PB PB STP I STP 0 MTR ACT WPS 0: 1: 2: 3: 4: PB 7 : CA 1: CA 2: step motor for head movement drive motor LED on drive Write Protect Switch SYNC Byte ready SOE 101 Anatomy of the 1541 Disk Drive The Layout of the Important Memory Locations o 10 12 14 18 20 22 32 48 57 $00 $01 $02 $03 $04 $06-$07 $08-$09 $OA-$OB SOC-SOD $OE-$OF $12-$l3 $14-$15 $16-$17 $20-$21 $30-$31 $39 58 61 63 67 $3A $3D $3F $43 71 $47 1 2 3 4 6 8 73 74 81 105 106 111 119 120 121 122 124 125 127 128 129 l30 131 132 l33 l39 148 153 155 157 159 161 163 165 $49 $4A $51 $69 $6A $6F-$70 $77 $78 $79 $7A $7C $7D $7F $80 $81 $82 $83 $84 $85 S8B-$8D $94-$95 $99-$9A $9B-$9C $9D-$9E $9F-$AO $A1-$A2 $A3-$A4 $A5-$A6 Command code for buffer 0 Command code for buffer 1 Command code for buffer 2 Command code for buffer 3 Command code for buffer 4 Track and sector for buffer 0 Track and sector for buffer 1 Track and sector for buffer 2 Track and sector for buffer 3 Track and sector for buffer 4 ID for drive 0 ID for drive 1 ID Flag for head transport Buffer pointer for disk controller Constant 8, mark for beginning of data block header Parity for data buffer Drive number for disk controller Buffer number for disk controller Number of sectors per track for formatting Constant 7, mark for beginning of data block header Stack pointer step counter for head transport Actual track number for formatting Step size for sector division (10) Number of read attempts (5) Pointer to address for M & B commands Device number + $20 for listen Device number + $40 for talk Flag for listen (1/0) Flag for talk (1/0) Flag for ATN from serial bus receiving Flag for EOI from serial bus Drive number Track number Sector number Channel number Secondary address Secondary address Data byte Work storage for division Actual buffer pointer Address of buffer 0 S300 Address of buffer 1 $400 Address of buffer 2 $500 Address of buffer 4 $600 Address of buffer 5 $700 Pointer to input buffer $200 Pointer to buffer for error message $2D5 102 Anatomy of the 1541 Disk Drive 181 187 193 199 212 213 214 215 231 249 256-325 512-552 586 600 601 602 628 632 663 640-644 645-649 725-761 762/764 768-1023 1024-1279 1280-1535 1536-1791 1792-2047 $B5-$BA $BB-$CO $Cl-$C6 $C7-$CC $D4 $D5 $D6 $D7 $E7 $F9 $100-$145 $200-$228 $24A $258 $259 $25A $274 $278 $297 $280-$284 $285-$289 $2D5-$2F9 $2FA/$2FC $300-$3FF $400-$4FF $500-$5FF $600-$6FF $700-$7FF ** ** Record 10, block 10 Record hi, block hi Write pointer for reI. file Record length for reI. files Pointer in record for reI. file Side sector number Pointer to data block in side sector Pointer to record in reI. file File type Buffer number Stack Buffer for command string File type Record length Track side-sector Sector side-sector Length of input line Number of file names File control method Track of a file Sector of a file Buffer for error message Number of free blocks Buffer 0 Buffer 1 Buffer 2 Buffer 3 Buffer 4 103 Anatomy of the 3.2 15~1 Disk Drive Operation of the DOS - An Overview The VIC-1541 is an intelligent disk drive with its own microprocessor and control system (Disk Operation System, DOS). This means that no memory space or processing time is taken from the computer. The comput1!!r needs only transm it commands to the disk drive, which it then executes on its own. The disk performs three tasks simultaneOUSly: Firstly, it manages data traffic to and from the computer. secondly, it interprets the commands and performs the management of files and the associated communications channels and block buffer. Thirdly, i t handles the hardware-oriented related functions of the disk drive - formatting, reading and writing, etc. These tasks are carried out simultaneously by the 6502 microprocessor in the VIC 1541. This is possible with the help of the interrupt technique. Only in this way can three tasks be executed simultaneously. Most of the DOS is concerned with interpreting and executing the transmitted commands. The reception of data and commands from the computer is controlled by interrupts. If the computer wants to talk to a peripheral device, it sends a pulse along the ATN line (ATteNtion, see section 5.11. This generates an interrupt at the disk drive. The DOS stops its current task and notices that the computer wants to send data. The DOS then finishes the original task. After that, the DOS will accept further data and commands from the the computer. If the command is finished, the DOS stays in a wait loop until new commands arrive from the disk. The execution of a command at this level is limited to the logical processing of the command, the management of the communications channel to and from the computer and the preparation and retrieval of data to be written or read, respectively. The tasks of a disk controller, formatting diskettes and writing and reading individual blocks, must , also be performed by the processor. These tasks are again interrupt controlled. Regular programs in the disk are interrupted every 14 milliseconds by a built-in timer, and control branches to a program that fulfills the tasks of a disk controller. Communications between the two independent programs is handled through a common area of memory, in which the main program places codes for the disk controller program. If the interrupt program is active, it looks at the memory locations to determine which activities are demanded, such as formatting a diskette. if this is the case, the drive and head motors are set in motion. At the end of the interrupt routine, the main program examines the memory locations to determine if the task was carried out by the disk controller, or if it 104 Anatomy of the 1541 Disk Drive must wait yet. In this way, the main program is informed in case of an error, such as a read error or if a write protect tab is present. The main program can then react appropriately and display the error message, for example. In the large CBM disks, two 6504 microprocessors are used as a disk controller. Communication again occurs over a common area of memory. An overview of the storage layout of the DOS such as the I/O primitives for managing the diskette and serial bus can be found in the previous section. This overview of the work of the DOS is naturally just a rough outline. If you want more exact information, refer to the DOS listing of the VIC 1541 in section 3.5, in which the complete 16K control system is documented. 105 Anatomy 'of the 1541 Disk Drive 3.3 The Structure of the VIC 1541 Diskette The diskette of the 1541 is divided into 35 tracks. Each track contains from 17 to 21 sectors. The total number of sectors is 683. Because the directory occupies track 18, 664 data are available for use, each containing 256 bytes. The tracks are layed out as follows: NUMBER OF SECTORS : TRACK :------------------------------: 21 19 18 17 :lT017 :18 TO 24 :25 TO 30 :31 TO 35 •. The varying number of sectors per track is necessitated by the shortening of the tracks from the midpoint on. 3.3.1 The BAM of the VIC 1541 BAM is an abbreviation for Block Availability Map. The BAM indicates whether a block on the diskette is free or allocated to a file. After every manipulation of blocks (saving, deleting, etc.) the BAM is updated. When the BAM indicates that a file to be saved requires more blocks than are available, an error message is given. When a file is OEPNed, the BAM in the DOS storage is updated, and is rewritten to disk when the file is CLOSEd. Commands that have a write or delete function read the BAM, update it, and rewrite it to the diskette. The BAM is organized as follows on track 18 sector 0: : Track 18, sector 0 : BYTE : CONTENTS : MEANING 0,1 ($OO-$Ol) $12,$01 2 ($02) $41 ($03) 3 4-143 ($04-$8F) * 1 = block $00 free; 0 Track and sector of the 1st· : block of the directory ASCII character 'A' ; indicates 1541 format Zero flag for future use Bit map of free and allocated blocks * = block allocated The bit map of the blocks is organized so that 4 bytes 106 Anatomy of the 1541 Disk Drive represent the sectors on a track. As can be inferred from the following table, the first of the 4 bytes contain the number of free blocks in the track. The other 3 bytes (24 bits) indicate which blocks are free and which are allocated in this track. Structure of the BAM entry of a track: : BYTE o : CONTENTS Number of available blocks in this track Bit map of sectors 0-7 Bit map of sectors 8-15 Bit map of sectors 16-23 1 2 3 4 bytes of a track designation in the BAM: : Track 18, sector 0, bytes 4-7 (track 1) : : 00001010 ($OA) 00000000 00000011 11111111 : ($00) ($03) ($FF) : 10 free : blocks o = allocated 1 = free Using a simple program, you can read the first byte of each track entry in the bit map, add them up and find the total number of free blocks on the diskette. 3.3.2 The Directory The directory is the table of contents of the diskette. It contains the following information: - disk name disk 10 DOS version number filenames file types blocks per file free blocks This directory is loaded into memory with the command LOAD -$-.8. A program previously in memory will be destroyed! It can be displayed on the screen with the LIST command. The directory occupies all of track 18 on the disk. The file entries follow the directory header. Each block accommodates 107 Anatomy of the 1541 Disk Drive a maximum of 8 file entries. Because the BAM and the header occupy one block, 18 blocks are left for file entries. A total of 144 files may reside on one diskette (18 blocks with 8 entries each). Format of the directory header: : Track 18, sector 0 : BYTE, : CONTENTS : MEANING 144-161 ($90-$A1) 162,163 ($A2-$A3) ($A4) 164 165,166 ($A5-$A6) $AO $32,$41 167-170 ($A7-$AA) 171-255 ($AB-$FF) $AO $00 Disk name (padded with shifted spaces) Disk 10 marker Shifted Space ASCII characters "2A " (format) Shifted Space not used, filled with 0 : * Bytes 180 to 191 have the contents "BLOCKS FREE" on : many diskettes The Diskette Name: The name of the diskette can be a maximum of 16 characters in length and is established when the diskette is formatted. If fewer then 16 characters are given, the rest is filled with shifted spaces ($AO). The following BASIC routine reaos the name and saves it in the string variable DN$: 100 OPEN 15,8,15,"10" 110 120 130 140 150 160 170 180 190 200 210 REM COMMAND CHANNEL 15 AND DISK INITIALIZED OPEN 2,8,2,"#" REM DATA CHANNEL 2 OPENED PRINTjl15, "B-R":2; 0; 18; 0 REM TRACK 18, SECTOR 0 READ AND PLACED IN CHANNEL 2 PRINT#15,"B-P";2;144 REM BUFFER-POINTER TO BYTE 144 DN$="" REM STRING DN$ IS ERASED REM LOOP TO READ THE 16 BYTES OF THE NAME FOR 1=1 TO 16 :.:GET# 2 ,X$ REM READ A BYTE ::IF ASC(X$)=160 THEN 200 REM IGNORE SHIFT SPACE : :DN$=DN$+X$ REM BYTE ADDED TO DN$ NEXT I CLOSE 2:CLOSE 15 REM CLOSE CHANNELS After running the routine, the string DNS contains the disk name. 108 Anatomy of the 1541 Disk Drive Diskette ID: The diskette ID is two characters in length and is specified when formatting the diskette. The DOS uses this ID to detect if a diskette in the drive has been replaced. If so, then the DOS performs an INITIALIZE. Initializing a diskette loads the BAM into memory in the drive. This way, the actual BAM is always in memory, provided the ID given when formatting is always different. Should this not be the case, a diskette must be initialized explicitly by using the INITIALIZE command. 3.3.3 The Directory Format Blocks 1 through 19 on track 18 contain the file entries. The first two bytes of a block point to the next directory block with file entries. If no more directory blocks follow, these bytes contain SOD and SFF, respectively. : Track 18, sector 1 : Byte : Contents 0,1 (SOO,SOl) 2-31 34-63 66-95 98-127 130-159 lfi2-191 194-223 226-255 (S02-S1F) (S22-S3F) (S42-S5F) (S62-S7F) (S82-S9F) (SA2-SBF) (SC2-SDF) (SE2-SFF) Track and sector number of the next directory block Entry of 1st file Entry of 2nd file Entry of 3rd file Entry of 4th file Entry of 5th file Entry of 6th file Entry of 7th file Entry of 8th file Format of a Directory Entry: Each file entry consists of 30 bytes, the functions of which are described below: 109 Anatomy of the 1541 Disk Drive : CONTENTS : BYTE o 1,2 (SOO) (SOl,S02) 3-18 19,20 (S03-S12) (S13,S14) 21 (SIS) 22-25 26,27 (S16-S19 ) (SlA-SIB) 28,29 (SIC-SID) File type Track and sector number of the first data block Filename (padded with "SHIFT SPACE" Only used for relative files (track and sector of the first side-sector block) Only used for relative files (record length) Not used Track and sector number of the new file when overwritten with the @: Number of blocks in the file (low byte, high byte) Fi1e Type Marker: Byte 0 of the file entry denotes the file type. Bits 0-2 are used to indicate the 5 file types •. Bit 7 indicates if the file has been CLOSEd properly. Closing a file sets bit 7. An unclosed file is denoted with an asterisk in front of the file type in the directory listing. If, for example, a sequential file "TEST" is opened and the directory is listed, this file will be represented like this: 12 "TEST" *SEO If the file is CLOSEd again, the asterisk does not appear in future directory listings. If this file remains unclosed and later opened, the error message "WRITE FILE OPEN" will appear. The File Type: In order to understand the function of byte 0 in the file entry, the file type, a table of all file types follows: : File type : Bit mask opened HEX : 7654 3210 : Bit mask closed HEX : 7654 3210 -------------------------------------------------------DELeted SEOuential ProGram USeR RELative 0000 0000 0000 0000 0000 0000 0001 0010 0011 0100 SOO SOl S02 S03 $04 1000 1000 1000 1000 1000 0000 0001 0010 0011 0100 S80 $81 S82 S83 $84 perhaps you have noticed that bits 3-6 have no function. Rut we verified with help from the DOS listing, bit 6 has a 110 Anatomy of the 1541 Disk Drive function: BIT 6 OF THE FILE TYPE DENOTES A PROTECTED FILE! If you set this bit to I, the corresponding file can no longer be deleted. This is designated in the directory listing with a < next to the file type. Because setting this bit requires some complicated commands, you will find a program in chapter 4 of this book with which you can protect, unprotect, and delete files. Track and sector of the first Data Block Bytes 1 and 2 of the file entry point to the first data block of the file. The first byte contains the track and the second the sector number where the file begins. The first data block, in turn contains a pointer to the second block of the file (also contained in the first two bytes of the block). The last data block of the file is indicated by a first-byte value of $00. The second byte contains the number of bytes used in this last sector. This concatenation can be explained with the help of the Dl'S MONITOR, contained in this book: > :BO > :B8 >:CO > :C8 > :00 >: D8 ):EO ): E8 >:FO >: F8 AD 00 00 2F AD 00 00 4B 48 00 AD 00 00 53 AD 00 00 20 41 00 AD 00 81 30 AD 00 82 41 4E 00 AD AD 00 00 00 00 13 09 54 31 AD AD AD AD 00 00 00 00 10 00 44 44 44 52 47 45 00 00 00 00 00 DB 31 AD 00 06 49 20 00 04 00 00 32 AD 00 00 53 43 00 00 ·•.••• ....... T12 /SOI ·•••.. ....... DIS K ADDR C BANGE ••• This is an extract from the directory (track 18, sector 1) of the TEST/DEMO diskette. You can follow the organization of the file DISK ADDR CHANGE. The entry of this file begins at byte $E2 and ends with byte $FF. This is a PRG file, which can be recognized by the file type $82 in byte $E2. This file comprises 4 blocks on the disk. This is evident from bytes $FE and $FF. Bytes SE3 and SE4 of the entry address the first data block of the file {SID, SOD, corresponding to track 16, sector OJ. Let's look at a section of this block: >:00 >:08 ):10 >:18 ):20 >: 28 10 97 32 93 49 45 OA 01 04 OF 35 39 34 36 00 39 04 6E 13 11 11 11 56 45 20 41 53 53 20 43 04 38 OD 11 44 48 64 2C 99 44 44 41 00 31 22 52 52 4E 111 • •••.• $ • .59468,1 2.9 ••.• " • ••••• DR IVE ADDR ESS CHAN Anatomy of the 1541 Disk Drive >:30 >:38 >:40 >:48 47 41 99 4F 45 4D 22 46 20 22 11 46 50 00 54 20 52 59 55 41 4F 04 52 4C 47 6F 4E 4C 52 00 20 20 GE PROGR AM".Y./. ••• TURN OFF ALL 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 commands are converted to one byte codes called tokens. This is why only the text can be recognized in the right hand translation of the hexadecimal codes. The first two bytes of this data block indicate the second data block ($10 and $OA, track 16, sector 10) from with this section follows: >:00 >:08 >:10 >:18 > :20 >:28 >:30 >:38 >:40 >:48 10 00 8F 52 45 36 48 44 B4 20 14 80 20 49 00 30 41 52 00 53 34 20 46 56 39 30 4E 45 99 45 30 33 49 45 05 3A 47 53 22 4C 00 30 4E 20 AA 20 45 53 11 45 ID 30 44 54 00 8F 20 00 54 43 05 3A 20 59 8D 20 41 68 48 54 AO 20 44 50 20 43 44 05 45 45 • .40 ••• •• 300: • FIND D DRIVE TYP E.9. 600: • C HANGE AD DRESS.(. •••• THE SELECTE The program is continued in this block. Bytes $00 and $01 point to the third data block of the file ($10, $14, track 16, sector 20): >:00 >:08 >:10 >:18 >:20 >:28 >:30 >:38 >:40 >:48 10 06 35 31 32 36 43 4D 3A 31 08 54 34 31 30 00 B2 54 20 2E 31 01 20 39 33 45 32 B2 32 32 30 8B A7 3A 31 06 32 35 30 00 30 20 20 20 20 5E 36 30 34 67 30 43 4D 8F 56 01 20 3Ao 30 06 00 B2 54 3A 32 8B A7 20 20 68 23 32 B2 20 2E 20 20 8F 56 01 •• 1000.# .T .. C 2 54 MT 119: .: 2031 V2. 6.E ••• C 226 MT 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 contiguously. 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 number 20. The DOS begins again with the first block if the calculated block oversteps the highest blOCk. Because track 16 contains 21 blocks, the last data block is block number 8. The first two bytes of this third hlock address it: > > > > 00 08 10 18 00 20 01 31 F8 34 8B 30 SA 34 20 30 42 30 53 30 B2 00 54 00 31 14 20 45 20 07 A7 07 A7 A3 20 B8 112 • ZB 1 440 ••• •• ST 1000.E. Anatomy of the 1541 Disk Drive >:20 >:28 >: 30 >:38 >:40 >:48 01 52 C7 31 43 C7 98 22 28 35 B2 28 31 C7 31 2C C6 30 35 28 36 5A 28 29 2C 31 29 43 5A 29 22 37 3A 24 43 00 4D 32 Al 3A 24 66 2D 29 23 SA AA 07 •. 15,"MR" (172) (16) : # 15,ZC$:Z C F(ZC$ G(O».&. Here the end of the program is marked by the value $00 in byte $00. Byte $01 gives the number of bytes in this last block that belong to the program. ($F8 corresponds to 248 bytes). Now we can find out the size of the program: 3 blocks with 254 bytes each = 762 bytes last block = 248 bytes Size of the program llOO bytes The Filename: The filename is contained in bytes 3-18 of the file entry. It consists of a maximum of 16 characters. Should the name be shorter than 16 characters, the rest of the name is padded with shifted spaces (SAO). Track and Sector of the new File for "Overwriting-: If a file is overwritten by using the @:, the new file is first completely saved. No filename entry is made in the directory for this file because the file already exists under this same name. Instead the address of the first block of the new file is placed in bytes 26 and 27 of the filename entry. If the new program is removed, the old one is deleted, which merely designates the blocks allocated to the file as free in the BAM. Now the address of the first data block of the new file is placed into the filename entry in bytes I and 2 is used and the file is "overwritten". Number of Blocks in the File: The length of a file is given in bytes 28 and 29 of its file entry. A file consists of at least one block and as many as 664 blocks. The first byte is the low byte, and the second is the high byte. If, for example, you discovered the file length $IF,SOO with the DISK MONITOR, the file consists of 31 blocks. 113 Anatomy of the 1541 Disk Drive 3.4 The Organization of Relative Piles Relative files differ from sequential files in that each data record can be accessed directly by a record number. The 1541 OOS takes care of most of the tasks required to support relative records. Let's take a closer look at the organization of a relative file. First OPEN a relative file with a record length of 100: OPEN 2,8,2, "REL-FILE,L,"+CHR$(lOO) Now write data record number 70: OPEN 1,8,15 PRINTU,"P"+CHR$(2)+CHR$(70)+CHR$(0)+CHR$(1) PRINT*2,DDATA FOR RECORD 70" CLOSE 2 : CLOSE 1 The directory entry then looks like this: >:00 84 >:08 20 46 49 >:10 AO AO AO >:18 00 00 00 11 4C AO 00 00 45 AO 00 52 AO 11 00 45 4C ••• REL AO AO -FILE OA 64 10 00 •• $ ........ The first byte $84 denotes a relative file. The next two bytes denote the first track and sector of the data ($11, $00: track 17 sector 0): exactly as with a sequential file. As usual, the name of the file follows (16 characters, padded with shifted spaces, $AO). Following are two fields not used with sequential files. The first field is a two byte pointer to the track and sector of the first sidesector block. A side-sector contains the pointers to each data record and is described more in detail later ($11, $OAI track 17, sector 10). The second field is a byte w-hich contains the record length, a value between 1 and 254, in our case $64 (100). The convenience of being able to access each record individually requires a definite length for each record thet must be defined when establishing a relative file. The rest of the fields in the directory entry have the usual significance; the last two bytes contain the number of blocks in the file (10 and hi byte, $10 and $00 (29». What does such a side-sector block look like and what is its function? The side-sector blocks contain the track and sector pointers to the individual data records. For example, if we want to read the 70th record in the relative file, the DOS consults the side-sector block to determine which track and sector contains the record and then read this record directly. As 114 Anatomy of the 1541 Disk Drive a resul t, you can read the 70th record of the file without having to read the entire file. Now let's take a look at the exact construction of a side-sector block. This s ide-sectc'r block is from our previous file. >:00 >:08 >: 10 >:18 >:20 >:28 >:30 >:38 >:40 >:48 >:50 etc. 00 47 00 00 00 00 11 00 11 11 02 11 11 04 11 11 06 11 11 08 11 10 08 10 10 04 10 00 00 00 00 00 00 64 00 OB OD OF 11 13 12 OE 00 00 11 OA 00 00 00 00 11 01 11 03 11 05 11 07 11 09 10 06 10 02 00 00 00 00 00 00 11 OC 11 OE 11 10 11 12 11 14 10 10 10 OC 00 00 00 00 •••• ·.G.$ ....... ....... ···....... ....... ··....... ....... ·........ ....... ··....... ....... 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 blocksl 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 ~8 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, 115 Anatomy of the 1541 Disk Drive 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: >:00 >:08 >:10 >:18 >:20 >:28 >:30 >:38 >:40 >:48 >:50 >:58 >:60 > :68 >:70 >:78 >:80 >:88 >:90 >:98 >:AO >:A8 >:BO >:B8 >:CO >:C8 > :00 >:08 9:EO >: E8 > :FO > :F8 00 00 00 00 00 00 20 46 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 F3 00 00 00 00 00 46 52 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 4E 44 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 52 20 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 44 20 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00 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 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 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 ORO 70 •• If we get a block number greater than 120 from the calculation, the pointer can no longer be found on the first side-sector block, rather in the next side-sector blocks. In this case, you divide the block number by 120, the quotient being the number of the side-sector block. The remainder gives the location of the pointer within this block. Fer instance, to find record number 425, divide by 120 and get a quotient 3, remainder 65. Therefore, you must read sidesector block 3 and get the pointer to the 65th data block. Between 2 and 4 block accesses are necessary to access a record of a relative data file. When creating or expanding a relative file, the following takes place: First, a directory entry is created for the relative file, 116 Anatomy of the 1541 Disk Drive containing the record length. Two channels are reserved for the relative file,one for the data, the other for the sidesectors. 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 set so that the contents can be accessed. If not, the record is created. All records preceding this record number that 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 mey 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). 117 Anatomy of the 1541 Disk Drive 3.5 DOS 2.6 ROM LISTINGS ****************************** 78 CIOO SEI CIOI A9 F7 LDA II$F7 2D 00 IC ANO $ICOO CI03 CI06 48 PHA CI07 AS 7F LOA $7F CI09 FO 05 BEO $CllO CIOB 68 PLA CIOC 09 00 ORA #$00 BNE $C1l3 ClOE DO 03 ClIO 68 PLA 09 08 ORA #$08 Clli C1l3 STA $lCOO 8D 00 IC C1l6 58 CLI 60 C1l7 RTS ****************************** C1l8 78 SEI C119 A9 08 LDA #$08 CllB 00 00 IC ORA $ICOO STA $ICOO CllE 8D 00 IC 58 CLI C12I CI22 60 RTS ****************************** A9 00 Cl23 LDA #$00 STA $026C Cl25 80 6C 02 Cl28 8D 60 02 STA $026D Cl2B 60 RTS ****************************** Cl2C 78 SEI 8A TXA Cl20 48 PHA Cl2E LDA #$50 Cl2F A9 50 Cl31 8D 6C 02 STA $026C Cl34 A2 00 LDX #$00 BD CA FE LOA SFECA,X Cl36 8D 6D 02 STA $0260 Cl39 Cl3C 00 00 IC ORA SICOO STA SICOO Cl3F 80 00 IC 68 PLA Cl42 TAX CI43 AA Cl44 58 CLI RTS C145 60 ****************************** Cl46 Cl48 Cl4B A9 00 80 F9 02 AD 8E 02 LOA #SOO STA S02F9 LOA S028E turn LEO on erase LED bit drive number O? not drive 0, turn LED off turn LED on turn LED on LED on erase error flags save X register 8 turn LEO on get x register back interpret command from computer last drive number 118 Anatomy of the 1541 Disk Drive Cl4E C150 C153 C155 C157 C159 C15B C15D C160 85 20 A5 10 29 C9 FO 4C 20 7F BC E6 84 09 OF OF 03 B4 D7 B3 C2 STA JSR LDA BPL AND CMP BEQ JMP JSR $7F $E6BC $84 $C160 #$OF #$OF $C160 $07B4 $C2B3 C163 C165 C168 C16A C16D C170 C172 C173 Cl75 Cl77 C17A C17D Cl7F C181 C184 C187 C18A Cl8C Cl8F C191 Bl 80 A2 BO CD FO CA 10 A9 4C 8E EO 90 20 AE BO 85 BO 85 6C A3 75 02 OB 89 FE 75 02 08 LDA STA LDX LDA CMP BEQ OEX BPL LDA JMP STX CPX BCC JSR LDX LDA STA LOA STA JMP ($A3),Y $0275 #$OB $FE89,x $0275 $C17A F5 31 C8 2A 09 03 EE 2A 95 6F Al 70 6F Cl 02 Cl 02 FE FE 00 drive number prepare 'ok l message secondary address $CI6A #S31 $CIC8 $022A #$09 $C184 $ClEE $022A $FE95,X $6F $FEAl,X $70 ($006F) ****************************** C194 C196 C199 C19C Cl9E CIAO CIAI CIA3 CIA5 CIA7 ClAA ClAD CIAF CIB2 CIB3 CIB5 CIB7 CIBA A9 80 AO DO AO 98 84 84 84 20 20 A5 80 AA A9 95 20 4C 00 F9 02 6C 02 2A 00 80 81 A3 C7 E6 23 Cl 7F 8E 02 00 FF BD CI DA 04 LOA STA LDA BNE LOY TYA STY STY STY JSR JSR LOA STA TAX LOA STA JSR JMO #$00 $02F9 $026C $CIC8 #$00 15, command channel yes to OPEN command determine line length and erase flags get first character and store 11 commands compare to first character found? not found 31, 'syntax error' number of command words command nUlllber < 9? test for 'R' , IS' , and command number jump address 10 'N' jump address hi jump to command prepare error message after executing command flag set? yes, then set error message error number 0 track number 0 sector number 0 $80 $81 $A3 $E6C7 $C123 $7F $028E prepare 'ok' message erase error flag drive number save as last drive number #$00 $FF,X $CIBO $D40A erase input buffer close internal channel ****************************** CIBO AO 28 LOY #$28 CIBF A9 00 LOA #$00 119 erase input buffer erase 41 characters Anatomy of the 1541 Disk Drive CICI CIC4 CIC5 CIC7 99 00 02 88 10 FA 60 STA $0200,Y DEY BPL $CICl RTS ****************************** CIC8 CICA CICC CICE AO 84 84 4C 00 80 81 45 E6 LDY STY STY JMP #$00 $80 $81 $£645 4C 68 C3 give error message (track & sector) track = 0 sector = 0 error number ace, generate error message ****************************** CIDl A2 00 LDX #$00 CID3 8E 7A 02 STX $027A CID6 A9 3A LDA #$3A CID8 20 68 C2 JSR $C268 CIDB FO 05 BEO $CIE2 88 CIDD DEY 88 CIDE DEY CIDF STY $027A 8C 7A 02 C1E2 $200 to $228 JMP $C368 check input line .. pointer to drive number : test line to I : no colon found? I or to end point to drive number (before colon) get drive # and turn LED on ****************************** AO 00 LDY #$00 C1£5 CIE7 A2 00 LDX #SOO CIE9 A9 3A LDA #S3A ClEB JMP $C268 4C 68 C2 check input line pointer to input buffer counter for commas ****************************** 20 E5 Cl CIEE JSR $CIE5 CIFI DO 05 BNE $CIF8 LDA #S34 CIF3 A9 34 CIF5 4C C8 Cl JMP SCIC8 88 CIF8 DEY 88 CIF9 DEY CIFA 8C 7A 02 STY S027A CIFD 8A TXA DO F3 BNE $CIF3 C!FE C200 A9 3D LDA #S3D C202 20 68 C2 JSR $C268 C205 8A TXA FO 02 C206 BEO SC20A C208 A9 40 LDA #S40 C20A 09 21 ORA #S21 C20C 8D 8B 02 STA S028B C20F INX E8 C210 8E 77 02 STX $0277 8E 78 02 STX $0278 C213 C216 AD 8A 02 LDA $028A C219 FO OD BEO SC228 C2lB A9 80 LOA #$80 C2lD OD 8B 02 ORA $028B C220 8D 8B 02 STA $028B check input line test line to 1: ' or end colon found? 120 I: t test line to colon or to end 34, , syntax error' set pointer to colon position of the drive no. comma before the colon yes, then 'syntax error' '=' check input to '=' comma found? no bit 6 and set bit 0 and 5 flag for syntax check wildcard found? no set bit 7 Anatomy of the 1541 Disk Drive C223 C225 C228 C229 C22B C22E C231 C234 C236 C239 C23A C23D C23E C24A C243 C245 C248 C24A C24C C24E C251 C254 C257 C25A C25D C25F C260 C263 C265 A9 8D 98 FO 9D AD 8D 00 8A 02 29 7A 02 77 02 79 02 A9 8D 20 68 C2 E8 8E 78 02 CA AD 8A 02 FO 02 A9 08 EC 77 02 FO 02 09 04 09 03 4D 8B 02 8D 8B 02 AD 8B 02 AE 2A 02 3D AS FE DO 01 60 8D 6C 02 A9 30 4C C8 Cl LDA STA TYA BEO STA LDA STA LDA JSR INX STX DEX LDA REO LDA CPX BEO ORA ORA EOR STA LDA LDX AND BNE RTS STA LDA JMP #$00 $028A $C254 $027A,X $0277 $0279 #S8D $C268 $0278 $028A $C245 #$08 $0277 $C24C #$04 #$03 $028B $028B $028B $022A $FEA5,X $C260 S026C #$30 $CIC8 8D CC BO Bl C8 CD FO C9 FO C9 DO EE C9 DO 98 9D AD 29 FO A9 95 8D E8 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 BEO CMP BEO CMP BNE INC CMP BNE TYA STA LDA AND BEO LDA STA STA INX number of commas before '=' shift CR check line to end increment comma counter store # of commas wildcard found? no set bit 3 comma after '=' ? no set bit 2 set bits 0 and 1 as flag for syntax check syntax flag command number combine with check byte set error flag 30, 'syntax error' ****************************** C268 C26B C26E C270 C272 C273 C276 C278 C27A C27C C27E C280 C283 C285 C287 C288 C28B C28E C290 C292 C294 C296 C299 reset wildcard flag '=' found? no S0275 $0274 $C29E (SA3) ,Y search characters in input buffer save character already done? yes get char from buffer $0275 $C2AO #S2A $C280 #$ 3F SC283 S028A #S2C $C26B compared with char found $027B,X $028A #S7F $C299 #$80 $E7,X $028A note comm", position wildcard flag ,* , '? ' set , , wildcard flag , 121 no wildcard note flag and save as wildcard flag inc comma counter Anatomy of the 1541 Disk Drive C29A C29C C29E C2AO C2A3 C2A6 C2A9 C2AB C2AD C2AF C2Bl C2B2 EO 90 AO AD 9D AD 29 FO A9 95 98 60 04 CD 00 74 02 7B 02 8A 02 7F 04 80 E7 CPX BCC LDY LDA STA LDA AND BEO LDA STA TYA RTS #$04 SC26B #SOO $0274 S027B,X $028A #S7F $C2Bl #S80 $E7,X ****************************** C2B3 A4 A3 LDY SA3 FO 14 C2B5 BEO SC2CB DEY C2B7 88 C2B8 FO 10 BEO SC2CA C2BA B9 00 02 LDA S0200,Y C2BD CMP #SOD C9 OD C2BF FO OA BEO $C2CB C2Cl 88 DEY C2C2 B9 00 02 LDA S0200, Y C2C5 C9 OD CMP #SOD C2C7 FO 02 BEO SC2CB C2C9 C8 INY C8 INY C2CA STY S0274 C2CB 8C 74 02 C2CE CO 2A CPY #S2A C2DO AO FF LDY #$FF C2D2 BCC SC2DC 90 08 8C 2A 02 C2D4 STY S022A C2D7 A9 32 LDA #S32 JMP SClC8 C2D9 4C C8 Cl ****************************** C2DC LDY #SOO AO 00 C20E 98 TYA C20F 85 A3 STA SA3 C2El 8D 58 02 STA S0258 C2E4 8D 4A 02 STA S024A C2E7 8D 96 02 STA S0296 C2EA 85 D3 STA SD3 C2EC 8D 79 02 STA $0279 C2P.F STA $0277 8D 77 02 C2F2 8D 78 02 STA $0278 C2F5 8D 8A 02 STA $028A C2F8 80 6C 02 STA $026C C2FB A2 05 LDX #$05 C2FD 9D 79 02 STA S0279,X C300 95 D7 STA $D7,X C302 95 DC STA SDC,X C304 95 El STA SEl,X C306 95 E6 STA $E6,X 122 4 commas already? no, continue set flag for line end wildcard flag no wildcard set flag check line length ptr to command input buffer zero? one? pointer to input buffer 'CR' yes, line end preceding character 'CR' yes pointer to old value again same line length compare with 42 characters smaller, ok 32, 'syntax error' line too long erase flag for input command pointer to input buffer 10 record length file type comma counter wildcard flag error flag flags for line analysis directory sectors buffer pointer drive number wildcard flag Anatomy of the 1541 Disk Drive C308 C30B C30E C30F C311 9D 7F 02 9D 84 02 CA DO EC 60 STA $027F,X STA $0284,X DEX BNE $C2~'D RTS ****************************** C312 C315 C318 C31A C31D C320 C323 C325 C327 C32A C32D C32F C332 C333 C335 C336 C339 C33B AD 8D A9 8D 8D AC A2 86 BD 20 A6 9D 98 95 E8 EC 90 60 78 77 01 78 79 8E 00 D3 7A 3C D3 7A 02 02 02 02 02 02 C3 02 E2 78 02 EA LDA STA LDA STA STA LDY LDX STX LDA JSR LDX STA TYA STA INX CPX BCC RTS $0278 $0277 i$Ol $0278 $0279 $028E i$OO $D3 $027A,X $C33C $D3 $027A AA AO A9 DD FO DD DO E8 98 29 A8 8A 60 00 3A 01 02 OC 00 02 16 C352 C355 C356 C357 C359 C35B C35D C35F C361 C362 C364 C366 BD E8 E8 C9 FO C9 FO DO 98 09 29 DO 00 02 01 30 F2 31 EE EB 80 81 E7 TAX LDY LDA CMP BEO CMP BNE INX TYA AND TAY TXA RTS LDA INX INX CMP BEO CMP BEO BNE TYA ORA AND BNE preserve drive number number of commas save number of drive numbers last drive number position of the colon get drive no. before colon save exact position $E2,X drive number in table $0278 $C325 got all drive numbers? no, continue ****************************** C33C C33D C33F C341 C344 C346 C349 C34B C34C C34D C34F C350 C351 track number sector number search for drive number note position #$00 i$3A $0201,X $C352 $0200,X $C361 colon behind it? yes colon here? no #$01 drive number $0200,X get drive number 1:1 '0 I? i$30 $C34D i$31 $C34D $C34C yes 111 ? yes no, use last drive number last drive number set bit 7, uncertain drive # erase remaining bits #$80 #$81 $C34F ****************************** 123 get drive number Anatomy of the 1541 Disk Drive C368 C36A C36D C370 C372 C375 C377 C378 C37B C37D C380 C38l C383 C386 C388 C38A C38C A9 8D AC Bl 20 10 C8 CC BO AC 88 DO CE A9 29 85 4C 00 RB 02 7A 02 A3 BD C3 11 74 02 06 74 02 ED 8B 02 00 01 7F 00 Cl LDA STA LDY LDA JSR BPL INY CPY BCS LDY DEY BNE DEC LDA AND STA JMP #$00 $028B $027A ($A3},Y $C3BD $C388 $0274 $C383 $0274 $C370 $0288 #$00 #$01 $7F SClOO search line for drive no. drive number turn LED on ****************************** C38F C391 C393 C395 C397 A5 49 29 85 60 7F 01 01 7F LDA EOR AND STA RTS $7F #$01 #$01 $7F ****************************** C398 AD 00 LDY #$00 C39A AD 77 02 LDA $0277 C39D CD 78 02 CMP $0278 C3AO FO 16 BEO SC3B8 C3A2 CE 78 02 DEC $0278 C3AS AC 78 02 LDY $0278 C3A8 B9 7A 02 LDA S027A,Y C3AB C3AC C3AE A8 Bl A3 AO 04 TAY LDA (SA3) ,Y LDY #$04 C3BO C3B3 C3S5 C3B6 C3B8 C3B9 C3BC D9 FO 88 DO 98 8D 60 CMP REO DEY RNE TYA STA RTS BB FE 03 F8 96 02 SFEBB,Y SC3B8 C9 FO C9 FO 09 29 60 30 06 31 02 80 81 C~1P BEO CMP BEO ORA AND RTS reverse drive number drive number switch bit 0 establish file type '=1 found? no get pointer set pointer to character behind '=1 pointer to buffer compare with marker for file type lSI, • pI I I U· I 'R' agreement SC3BO $0296 note file type (1-4) ****************************** C3BD C3BF C3C1 C3C3 C3C5 C3C7 C3C9 erase syntax flag position in command line get chars from command buffer get drive number certain number? increment pointer line end? yes #$ 30 SC3C7 #S31 SC3C7 #S80 #S81 check drive number '0 ' ' l' no zero or one, then set bit 7 124 Anatomy of the 1541 Disk Drive ****************************** C3CA C3CC C3CE C3Dl C3D2 C3D5 C3D6 C3D8 C3D9 C3DB C3DD C3DE C3EO C3E2 C3E4 C3E6 C3E8 C3E9 C3EB C3ED C3EE' C3FO C3Fl C3F4 C3F5 C3F7 C3FA C3FB C3FC C3FE C400 C402 C404 C407 C409 C40C C40E C411 C413 C416 C419 C41B C41D C420 A9 85 8D 48 AE 68 05 48 A9 85 CA 30 B5 10 06 06 4A 90 06 DO 68 AA BD 48 29 8D 68 OA 10 A5 29 85 AD FO 20 FO 20 A9 8D 20 FO A9 20 20 00 6F 8D 02 C423 C426 C427 C42A C42B C42D C42F C432 C434 20 08 20 28 FO A9 8D FO 20 3D C6 78 02 6F 01 6F OF E2 04 6F 6F EA 6F E6 3F C4 03 8C 02 3E E2 01 7~' 8C 28 3D 12 8F 00 8C 3D IE 74 C8 8F 02 C6 C3 02 C6 Cl C3 8F C3 OC 00 ac 02 05 3D C6 verify drive number LDA STA STA PHA LDX PLA ORA PHA LDA STA DEX BMI LDA BPL ASL ASL LSR BCC ASL BNE PLA TAX LDA PHA AND STA PLA ASL BPL LDA AND STA LDA BEO JSR BEO JSR LDA STA JSR BEO LDA JSR JSR #$00 $6F $028D A SC43C $E2 #SOl S7F S028C SC434 $C63D $C420 $C38E' #$00 $028C $C63D SC439 #$74 SClC8 SC38F initialze drive error? switch to other drive JSR PHP JSR PLP BEO LDA STA BEO JSR $C63D initialize drive $C38F switch to other drive $C439 #$00 $028C $C439 $C63D no error? $0278 number of drive numbers $6F #$01 $6F $C3EF SE2,X $C3E8 $6F $6F A $C3D5 $6F $C3D5 SC43F,X get syntax flag #$03 S028C isolate drive number init ial ize drive no error? 74, 'drive not ready' number of drives initialize drive 125 Anatomy of the 1541 Disk Drive C437 C439 C43C C43D DO E2 4C 00 Cl 2A 4C 00 C4 BNE JMP ROL JMP error? Turn LED on drive # from carry after bit a $C41B $CI00 A $C400 ****************************** C440 00 80 41 01 01 01 01 81 C448 81 81 81 42 42 42 42 flags for drive check ****************************** search for file in directory initialize drive C44F C452 C454 C457 C45A C45C C45F C461 20 A9 80 20 DO CE 10 60 CA 00 92 AC 19 BC 01 JSR LOA STA JSR BNE DEC BPL RTS $C3CA #$00 $0292 $C5AC $C475 $028C $C462 C462 C464 C467 C46A C46D A9 80 20 20 4C 01 80 8F 00 52 LOA STA JSR JSR JMP #$01 $0280 $C38F $CI00 $C452 C470 C473 C475 C47B C47B C470 20 Fa 20 AD FO 60 17 C6 10 08 C4 BF 02 01 JSR BEO JSR LOA BEO RTS $C617 $C4B5 $C408 $02BF $C47E C47E C481 C483 C485 C488 C48A AD 30 10 AD FO 60 53 02 ED F'O 8F 02 02 LOA BMI BPL LOA BEO RTS $0253 $C470 $C475 $028F $C45C C48B C48E C490 20 04 C6 FO lA DO 28 JSR $C604 BEO $C4AA BNE $C4BA C492 C494 C497 C49A C490 C49F C4A2 C4A5 C4A7 C4AA C4AD C4AF A9 BD 20 20 A9 80 20 DO 80 AD DO CE LOA STA JSR JSR LOA STA JSR BNE STA LOA BNE DEC 01 80 8F 00 00 92 AC 13 8F 8F 28 8C C3 02 C5 02 02 C3 Cl C4 02 C3 Cl 02 C5 02 02 02 pointer read first directory block entry present? drive number clear? no change drive Turn LED on and search search next file in directory not found? verify directory entry more files? fi Ie not found? yes search next directory block not found? #$01 $0280 $C38F $CI00 #$00 $0292 $C5AC $C4BA $028F $028F $C4D7 $028C change drive turn LED on read directory block found? 126 Anatomy of the 1541 Disk Drive C4B2 C4B4 10 DE 60 C4B5 C4B8 C4BA C4BD C4CO C4C2 C4C5 C4C7 20 FO 20 AE 10 AD FO DO 17 FO D8 53 07 8F EE DE C4C9 C4CC C4CE C4DO C4D2 C4D5 C4D7 AD FO B5 29 CD 00 60 C4D8 C4DA C4DO C4DE C4El C4E4 C4E6 A2 8E E8 8E 20 FO 60 C4E7 C4EA C4EC C4EE C4FO C4F1 C4F3 C4F5 C4F7 C4F9 C4FC C4FE C50I C502 C505 C507 20 DO A5 55 4A 90 29 FO A9 CD FO ElO AA 20 C50A C500 C50F C511 C513 C5I5 C517 C519 C51B C51C BPL $C492 RTS C6 JSR BEO JSR LOX BPL LDA BEO BNE $C617 $C4AA $C4D8 $0253 $C4C9 $028F $C4B5 $C4D7 96 02 09 E7 07 96 02 DE LOA BEO LOA AND CMP BNE RTS $0296 $C467 $E7,X #$07 $0296 $C4B5 same as desired file type? no FF 53 02 LOX STX INX STX JSR BEQ RTS #$FF S0253 flag for data found C4 02 02 8A 02 89 C5 06 next entry in directory not found? check entry file found? yes no, then done file type S028A $C589 SC4EC set pointer to data $C594 SC4E6 S7F $E2,X A $C4FE #S40 $C4E7 #$02 $028C $C4E7 $027A,X pointer to next file end, then done drive number A6 C6 03 4C 10 C5 JSR BNE LOA EOR LSR BCC AND BEQ LOA CMP BEO LDA TAX JSR LOY JMP $C6A6 #$03 SC510 get length of filename BO 00 02 01 94 ~'O OA C9 3F' 00 02 Bl 94 C9 AO FO CC E8 C8 LDA CMP BEQ CMP BNE LOA CMP BEQ INX INY $0200,X (S94),Y $C51E1 #$3F $C4E7 ($94),Y #SAO $C4E7 get chars out of command line same character in directory? yes 94 C5 FA 7F E2 DB 40 FO 02 8C 02 E9 7A 02 AD 127 search both drives? yes I? ' no shift blank, end of name? yes increment pointer Anatomy of the 1541 Disk Drive C51D C520 C522 C525 C527 C529 EC BO BD C9 FO DO 76 02 09 00 02 2A OC DF CPX BCS LDA CMP BEQ BNE $0276 $C52B $0200,X #$2A SC535 $C50A end of the name in the command? yes next character C52B C52D C52F C531 C533 C535 C538 C53B C53D C53F C542 C545 C547 C549 C54B C54D C54F C550 C55l C553 C555 C556 C558 C55A C55C C55E C560 C562 C564 C566 C568C56A C56C C56E C570 C572 C574 C577 C578 C57A C57D C580 C582 C584 C586 -C589 CS8B C58E CO BO Bl C9 DO AE 8E B5 29 8D AD 95 AS 95 13 06 94 AO B2 79 02 53 02 CPY BCS LDA CMP BNE LDX STX LDA AND STA LDA 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 LDA BNE LDY LDA STA LDA STA LDA #S13 $C535 ($94), Y #SAO SC4E7 $0279 S0253 SE7,x #$80 $028A $0294 SDD,X S81 SD8,X #SOO (S94), Y 19 reached end of name E7 80 8A 02 94 02 DD 81 D8 AD 00 Bl 94 C8 48 29 40 85 6F 68 29 DF 30 02 09 20 29 27 05 6F 85 6F A9 80 35 E7 05 6F 95 E7 B5 E2 29 80 05 7F 95 E2 Bl 94 9D 80 02 C8 Bl 94 9D 85 02 AD 58 02 DO 07 AO 15 B1 94 8D 58 02 A9 FF 8D 8F 02 AD 78 02 • *. yes, file found continue search shift blank, end of name not found sector number of the directory enter in table file type *$ 40 $6F isolate scratch-protect bit ( 6) and save #$DF $C55C #$20 #$ 27 $6F $6F #$80 erase bit 7 $E7 , X $6F , X SE7 , X $E2 , X isolate flag for wildcard set bit 5 erase bits 3 and 4 get bit 6 again write in table #$80 $7F SE2,X drive number ($94) I Y $0280 , X ($94) I Y S0285,X $0258 $C589 #$15 ($94), Y $0258 #SFI<' $028F S0278 128 first track of file get sector from directory record length record length get from directory Anatomy of the 1541 Disk Drive C591 CS94 CS97 CS99 SD 79 02 CE 79 02 10 01 60 STA $0279 DEC $0279 BPL $CS9A RTS CS9A CS9D CS9F CSAl CSA4 CSA6 CSAS CSAB AE BS 30 BD DO A9 So 60 79 02 E7 OS SO 02 EE 00 SF 02 LDX LDA BMI LDA BNE LOA STA RTS $0279 $E7,X $CSA6 $ 02S0,X $CS94 #$00 $02SF CSAC CSAE CSBl CSB2 CSBS CSBS C5BA C5BC C4BE C5C1 C5C4 C5C7 C5C9 AO SC SS SC An S5 A9 SS SD 20 AD DO 60 00 91 02 LOY STY DEY STY LDA STA LDA STA STA JSR LDA BNE RTS #$00 $0291 C5CA CSCC CSCF CSDI C5D4 CSD7 C5DA CSDO CSOF CSEI CSE3 CSE6 CSE8 CSEB CSED CSFO C5F2 C5F5 C5FS CSFA A9 SD A9 20 So 20 CE AO Bl DO AO DO 20 AS SD AS AE SD FO 60 07 95 00 F6 93 ES 9S 00 94 18 91 2F 3B 81 91 94 92 92 10 C5FB C5FD C600 C602 A2 EC DO FO 01 92 02 2D 13 C604 AD S5 FE S3 SS SO 01 Sl 93 75 93 01 02 FE 02 D4 02 02 D4 02 D4 02 02 DE 02 02 02 $02S3 $FES5 $SO #$01 $Sl $0293 $D475 $0293 $CSCA wildcard flag set? yes track number already set yes IS, directory track sector 1 read sector LDA STA LDA JSR STA JSR DEC LDY LDA BNE LOA BNE JSR LDA STA LDA LDX STA BEO RTS #$07 $0295 #$00 $D4r'6 $0293 $D4ES $029S #$00 ($94),Y $CSFB $0291 $C617 $DE3B $Sl $0291 $94 $0292 $0292 $C617 LDX CPX BNE BEO #$01 $0292 $C62F $C617 number of directory entries (-1) get pointer from buffer save as track number set buffer pointer decrement counter first byte from directory get track and sector number sector number buffer pointer buffer pointer to one? LDA $FESS IS, track number of BAM 129 Anatomy of the 1541 Oisk Orive C607 C609 C60C C60E C611 C614 C617 C619 C61C C61F C621 C623 C626 85 AO 85 20 AO 20 AO 80 AO 30 A9 20 4C 80 90 81 75 94 C8 FF 53 95 08 20 C6 07 C629 C62C 20 40 04 4C C4 C5 JSR $0440 JMP $C5C4 set buffer pointer read next block C62F C631 C634 C637 C639 C63C A5 80 20 AS 80 60 LOA STA JSR LOA STA RTS get track & sector no. from buffe 02 04 02 04 02 02 01 C5 94 94 02 3B OE 81 90 02 STA LOA STA JSR LOA JSR LOA STA LOA BMI LOA JSR JMP $80 $0290 $81 $0475 $0294 $04C8 #$FF $0253 $0295 $C629 #$20 $01C6 $C567 track number sector number read block set buffer pointer erase-file found flag all directory entries checked? inc buffer ptr by 32, next entry and continue $94 $0294 $OE3B $81 $0290 save sector number ****************************** C630 LOA $68 A5 68 C63F 00 28 BNE $C669 C64l LOX $7F A6 7F C643 56 lC LSR $lC,X C645 90 22 BCC $C669 C647 A9 FF LOA $FF C649 80 98 02 STA $0298 C64C JSR $OOOE 20 OE 00 C64F AO FF LOY #$FF C651 CMP #$02 C9 02 C653 BEQ $C65F FO OA CMP #$03 C655 C9 03 C657 FO 06 BEQ $C65F C659 C9 OF CMP #$OF C65B BEQ $C65F FO 02 C650 AO 00 LOY #$00 C65F A6 7F LOX $7F C661 98 TYA C662 95 FF STA $FF,X C664 00 03 BNE $C669 C666 20 42 DO JSR $0042 C669 A6 7F LOX $7F C66B LOA $FF.X B5 FF C660 60 RTS ****************************** C66E 48 PHA C66F 20 A6 C6 JSR $C6A6 C672 20 88 C6 JSR $C688 C675 68 PLA 130 test and initialize drive drive number disk changed? no, then done set error flag read directory track 20, 'read error'? yes 21, 'read error'? yes 74, 'drive not ready' ? yes drive number save error flag error? load BAM drive number transmit error code name of file in directory buffer get end of the name write filename in buffer Anatomy of the 1541 oisk Orive C676 C677 C67A C67B C670 C67F C68l C683 C684 C685 C687 38 EO AA FO 90 A9 91 C8 CA 00 60 4B 02 SEC SBC $024B compare len with max length TAX OA 08 AO 94 FA BEQ BCC LOA STA INY OEX BNE RTS $C687 $C687 lI$AO ($94),Y $C68l ****************************** C688 98 TYA OA C689 ASL A C68A A8 TAY B9 99 00 LOA $0099,Y C68B 85 94 STA $94 C68E C690 B9 9A 00 LOA $009A C693 85 95 STA $95 C695 AO 00 LOY #$00 BO 00 02 LOA $0200,X C697 C69A 91 94 STA ($94),Y C69C C8 INY C690 FO 06 BEQ $C6A5 INX C69F E8 C6AO EC 76 02 CPX $0276 C6A3 90 F2 BCC $C697 60 C6A5 RTS ****************************** C6A6 C6A8 C6AB C6AC C6AO C6BO C6B2 C6B4 C6B6 C6B8 C6BB C6BC C6BE C6Cl C6C3 C6C6 C6C8 C6CB C6CC C6CO A9 80 8A 48 BO C9 FO C9 FO EE E8 A9 CO 90 EC 90 8E 68 00 4B 02 pad with 'Shift blank' buffer number times 2 as pointer buffer pointer after $94/$95 transmit characters in buffer buffer already full? search for end of name in command LOA #$00 STA $024B TXA 00 02 2C 14 30 10 4B 02 OF 4B 02 05 74 02 E5 76 02 PHA LOA CMP BEQ CMP BEQ INC INX LOA CMP BCC CPX BCC STX PLA AA TAX 60 RTS $0200,X #$2C $C6C8 #$30 $C6C8 $024B get , , characters out of buffer #$OF $024B $C6C8 $0274 $C6AO $0276 15 , '=' increment length of name greater? end of input line? pointer to end of name ****************************** C6CE LOA $83 A5 83 C600 48 PHA 131 secondary address and channel no. Anatomy of the 1541 Disk Drive C601 C603 C604 C607 C608 C60A C60B C600 AS 48 20 68 85 68 85 60 82 DE C6 82 83 LOA PHA JSR PLA STA PLA STA RTS $82 $C60E create file entry for directory $82 get data back $83 ****************************** C60E LOA #$11 A9 11 C6EO 85 83 STA $83 C6E2 20 EB DO JSR $OOEB C6E5 JSR $04E8 20 E8 04 C6E8 LOA $0253 AO 53 02 10 OA BPL $C6F7 C6EB LOA $0280 C6EO AD 80 02 BNE $C6FC C6FO DO OA 20 06 C8 JSR $C806 C6F2 C6F5 18 CLC C6F6 60 RTS LOA $0280 C6F7 AD 80 02 C6FA FO IF BEO $C7lB C6FC DEC $0280 CE 80 02 C6FF ENE $C70E DO 00 C701 DEC $028D CE 80 02 JSR $C38F C704 20 8F C3 C707 JSR $C806 20 06 C8 C70A 38 SEC C708 4C 8F C3 JMP $C38F C70E C7l0 C713 C7l6 C7l9 C7lA A9 80 80 20 38 60 00 73 02 80 02 B7 C7 LOA STA STA JSR SEC RTS #$00 $0273 $0280 $C7B7 C71B C7l0 C71F C721 C724 C726 C728 C729 C72B C72E C730 C732 C734 C736 C737 C739 C73B A2 18 AO 10 Bl 94 80 73 02 FO 02 A2 16 88 Bl 94 80 72 02 EO 16 FO OA C9 OA 90 06 CA C9 64 90 01 CA LOX LOY LOA STA BEO LOX DEY LDA STA CPX BEO CMP BCC DEX CMP BCe OEX #$18 #$10 ($94), Y $0273 $C728 11$16 17 secondary address open channel to read set buffer pointer not yet last entry? write 'blocks free. , change drive write 'blocks free. , change drive drive no. for header, hi-byte write header ($94), Y S0272 #$16 $C73C II$OA $C73C IIS64 SC73C number of blocks hi in buffer zero? number of blocks 10 in buffer 10 100 132 Anatomy of the 1541 Disk Orive C73C C73F C741 C742 C743 C745 C747 C74A C74B C740 C74E C751 C754 C755 C758 C75B C75C C75F C762 C763 C764 C766 C768 C76B 6760 C770 C771 C773 C775 C778 C779 C77A C77C C77E C780 C783 C784 C786 C788 C78B C780 C7BF C791 C793 C795 C798 C799 C89B C790 C79F C7A2 C7A5 C7A7 C7AA C7AB 20 Bl 48 OA 10 A9 90 68 29 A8 B9 90 CA B9 90 CA B9 90 CA CA 80 A9 90 A9 90 CA AO Bl 90 CA 88 CO BO A9 90 E8 EO BO BO C9 FO C9 00 A9 90 E8 EO BO A9 30 90 10 20 38 60 AC C7 94 05 3C B2 02 OF C5 FE Bl 02 CO ~'E Bl 02 BB FE Bl 02 05 2A 82 02 AO Bl 02 12 94 Bl 02 03 F5 22 Bl 02 20 OB Bl 02 22 04 AO FO 22 Bl 02 20 OA 7F Bl 02 Bl 02 Fl B5 C4 JSR LDA PHA ASL BPL LOA STA PLA ANO TAY LOA STA OEX LOA STA OEX LOA .STA OEX OEX BCS LOA STA LOA STA OEX LOY LOA STA OEX OEY CPY BCS LOA STA INX CPX BCS LOA CMP BEQ CMP BNE LOA STA INX CPX BCS LOA ANO STA BPL JSR SEC RTS ($94), Y erase buffer file type A $C74A #$3C $02B2,X bit 7 in carry bit 6 not set? ,< ' for protected file write behind file type #$OF $FEC5,Y $02Bl,X isolate bits 0-3 as file type marker 3rd letter of the file type in buffer $FECO,y $02Bl,X 2nd letter of file type in buffer $FEBB,Y $02Bl,X 1st letter of file type in buffer $C76B #$2A $02B2,X #$AO $02Bl,X file not closed? before file type in buffer pad with 'shift blank' in buffer i$12 ($94) ,Y $02Bl,X filenames write in buffer i$03 $C773 i$22 $02Bl,X write before fi Ie type $CnC i$20 $C793 $02Bl,X #$22 $C793 i$AO $C783 #$22 $02Bl,X i$20 $C7A7 #$7F $02Bl,X $02Bl,X $C798 $C4B5 133 ,* , '=' character from buffer '='? 'shift blank' at end of name fill through '=' bit 7 erase in the remaining chars search for next directory entry Anatomy of the 1541 Disk Drive ****************************** LDY #$lB C7AC AO IB LDA #$20 C7AE A9 20 STA $02BO,Y C7BO 99 BO 02 88 DEY C7B3 DO FA BNE $C7BO C7B4 C7B6 60 RTS erase directory buffer ****************************** C7B7 20 19 Fl JSR SF1l9 C7BA 20 DF FO JSR $FODF 20 AC C7 C7BD JSR SC7Ae C7CO A9 FF LDA #SFF C7C2 85 6F STA $6F LDX $7F A6 7fo' C7C4 8E 72 02 STX $0272 C7C6 A9 00 LDA #$00 C7C9 C7CB 8D 73 02 STA S0273 LDX $F9 C7CE A6 F9 LOA $FEEO,X BD EO ~'E C7DO C7D3 85 95 STA $95 AD 88 FE C7D5 LDA $FE88 C7D8 85 94 STA $94 C7DA AO 16 LOY #S16 Bl 94 LOA ($94),Y C7DC C7DE C9 AO CMP #$AO C7EO DO OB BNE $C7EO C7E2 A9 31 LOA #$31 ,BYTE $2C C7E4 2C C7E5 Bl 94 LOA ($94),Y C7E7 C9 AO CMP #$AO C7E9 DO 02 BNE $C7EO C7EB A9 20 LDA #$20 C7ED 99 B3 02 STA $02B3 C7FO 88 OEY C7Fl 10 F2 BPL $C7E5 C7F3 A9 12 LDA #$12 C7F5 80 Bl 02 STA $02Bl C7F8 A9 22 LOA #$22 C7FA SD B2 02 STA $02B2 C7FD 8D C3 02 STA $02C3 C800 A9 20 LDA #$20 8D C4 02 C802 STA $02C4 C805 60 RTS create header with disk name initialize if needed read disk name erase buffer ****************************** $C7AC #$OB $Ca17,Y $02Bl,Y create last line erase buffer 12 characters 'blocks free.' write in buffer $C80B $EF40 number of free blocks in front C806 C809 caOB C80E CBll C8l2 CB14 20 AO B9 99 88 10 4C AC C7 OB 17 C8 Bl 02 F7 4D EF JSR LOY LOA STA DEY BPL JMP 134 , , blank write in buffer drive number as block no, 10 in buffer block number 10 buffer number hi-byte of the buffer address $90, position of disk name save pad buffer with 'shift blank' , l' character from buffer compare with 'shift blank' , , blank in buffer 'RVS ON' in buffer write before and after disk name , , blank behind i t Anatomy of the ****************************** C8l7 42 4C 4F 43 4B 53 20 46 C8lF 52 45 45 2E *********~******************** C823 C826 C829 C82C C82E C830 C833 C835 C838 C83A C83C C83E C840 C842 C845 C847 C849 C84B C840 C84E C850 C852 C855 C858 C85A C85C C85E C861 C863 C866 C868 C86B C860 0870 C872 C874 C876 C878 C87A 20 20 20 A9 85 20 30' 20 90 AO B1 29 00 20 AO Bl 98 20 CA 00 86 90 30 B7 33 00 94 40 2B B6 13 94 C3 C3 C3 C4 00 C8 FO OA 85 C8 B1 85 20 AE A9 35 00 BD 85 BD 85 20 E6 20 10 AS 85 A9 AO 4C 80 94 81 70 53 20 E7 00 80 80 85 81 70 86 8B C3 86 80 01 00 A3 C8 02 02 02 C8 C4 Cl JSR JSR JSR LOA STA JSR BMI JSR BCC LOY LOA ANO BNE JSR LOY LOA BEQ STA INY LOA STA JSR LOX LDA ANO BNE LOA STA LOA STA JSR INC JSR BPL LOA STA LOA LOY JMP $C398 $C320 $C3CA #$00 $86 $C490 $C872 $ODB7 $C860 #$00 ($94),Y 1$40 $C860 $C8B6 11$13 ($94),Y $C855 $80 ($94),Y $81 $C870 $0253 11$20 $E7,X $C86B $0280,X $80 $0285,X $81 $C870 $86 $C48B $C835 $86 $80 *$01 #$00 $CIA3 ****************************** C870 20 SF EF JSR $EF5F C880 20 75 D4 JSR $0475 C883 20 19 Fl JSR $F119 C886 B5 A7 LOA $A7,X C888 C9 FF CMP #$FF CB8A FO 08 BEQ $C894 C88C AO F9 02 LOA $02F9 09 40 C88F ORA #$40 C891 80 F9 02 STA $02F9 135 15~1 Oisk Orive 'blocks f' 'ree.' S command 'scratch' ascertain file type get drive number initialize drive if needed counter for erased files search for file in directory not found? is file open yes file type scratch protect yes erase file and note in directory track no. of the first side-sector none present? note track number and sector number erase side-sector file number bit 5 set? yes, file not closed get track and sector erase file increment number of erased files search for next file if present, erase number of erased files save as 'track' 1 as disk status o as 'sector' message 'files scratched' erase file free block in BAM get buffer number in BAM Anatomy of the 1541 Disk Drive C894 C896 C899 C89C C89E C8A1 C8A3 C8A5 C8A7 C8AA A9 00 C8AD C8BO C8B3 20 5F EF 20 4D 04 4C 94 C8 20 20 85 20 85 A5 DO 20 4C C8 56 80 56 81 80 06 F4 27 04 01 D1 EE D2 #$00 $04C8 $D156 $80 $D156 $81 $80 $C8AO $EEF4 $0227 track number not equal to zero write BAM close channel JSR $EF5F JSR $D440 JMP $C894 free block in BAM read next block and continue LOA JSR JSR STA JSR STA LOA RNE JSR JMP buffer pointer to zero get track get sector ****************************** C8B6 AO 00 LDY #$00 98 C8B8 TYA C8B9 STA ($94) ,Y 91 94 C8BR 20 5E DE JSR $DE5E C8SE JMP $0599 4C 99 05 erase directory entry set file type to zero write block and check **k*************************** C8C1 A9 31 LDA #$31 C8C3 4C C8 C1 JMP $C1C8 O-command ****************************** A9 4C C8C6 LOA #$4C C8C8 80 00 06 STA $0600 C8CB A9 C7 LOA #$C7 C8CD 8D 01 06 STA $0601 C8DO A9 FA LOA #$FA C802 8D 02 06 STA $0602 C8D5 A9 03 LOA #$03 C807 20 03 D6 JSR $0603 LOA $7F C80A AS 7F C80C 09 EO ORA #$EO C80E 85 03 STA $03 LOA $03 C8EO AS 03 C8E2 30 FC BMI $C8EO C8E4 C9 02 CMP #$02 90 07 BCC $C8EF C8E6 C8ES A9 03 LOA #$03 C8EA A2 00 LOX #$00 4C OA E6 C8EC JMP $E60A 60 C8EF RTS format diskette JMP-command ****************************** C8FO A9 EO LOA #$EO C8F2 8D 4F 02 STA $024F C8F5 20 01 FO JSR $F001 C8FS 20 19 Fl JSR SF1l9 C8FB A9 FF LOA #$FF C8FD 95 A7 STA $A7,X C8FF A9 OF LOA #$OF C-command 136 ' backup' 31, 'syntax error' JMP $FAC7 in $600 to $602 set track and sector number drive number command code for formatting transmit wait until formatting done smaller than two, then ok 21, , read error' 'copy' get buffer number of BAM Anatomy of the 1541 Disk Drive C90l C904 C907 C909 8D 20 DO 4C 56 02 E5 Cl 03 Cl C8 C90C C90F C9l2 C915 C917 C919 C91C C9H' C921 C923 C925 20 20 AD 29 DO AE BO C9 DO F8 20 8B 55 OF 7A 00 2A 05 A9 30 4C C8 Cl C3 02 C928 C92B C920 C92F C932 C934 C937 C93A C93D C940 C942 C944 C946 C948 C94B C94E C951 AD 29 DO 4C A9 80 80 80 80 8B 09 F4 52 00 58 8C 80 81 E3 01 7F 01 91 7B 7A 02 C952 C955 C958 C95A C95C C95E C960 C962 C964 C966 C968 C96A C96C C96E C971 C973 C976 C979 C97C C97E 20 AD C9 90 A5 C5 DO AS C5 DO AS C5 DO 20 A9 80 20 20 FO C9 4F 78 03 45 E2 E3 3F DD OE 39 08 09 33 CC 01 79 FA 25 04 02 C4 02 A4 29 85 09 80 AD 8D 60 02 02 Cl C9 02 02 02 02 02 02 02 CA 02 C9 Dl STA JSR BNE JMP $0256 $ClE5 $C90C $C8Cl JSR JSR LOA AND BNE LOX LOA CMP BNE LOA JMP $ClF8 SC320 S028B #$55 SC928 S027A S0200,X #S2A SC928 #S30 SClC8 LOA AND BNE JMP LOA STA STA STA STA LDA AND STA ORA STA LOA STA RTS S028B #$D9 SC923 $C952 #$00 $0258 $028C S0280 $0281 $E3 #$01 $7F #SOI $0291 S027B S027A JSR LOA CMP BCC LDA CMP BNE LOA CMP BNE LDA CMP BNE JSR LOA STA JSR JSR REO CMP $C44F S0278 #$03 $C9Al SE2 SE3 SC9Al $OD SOE SC9Al SD8 S09 SC9Al SCACC #S01 $0279 check input line 31, 'syntax errorcheck input test drive number flag for syntax check character of the command ,* , 30, 'syntax error' syntax flag 30, 'syntax error l number of drives track number in directory drive number search for file in directolY number of filenames in command smaller than three? yes first drive number second drive number not on same drive? directory block of the 1st file same dir block as second file? no directory sector of first file same dir sector as second file? no is file present SC9~'A S0125 SC982 #$02 get data type reI-file? prg-file 137 Anatomy of the 1541 Disk Drive C980 C982 C984 C987 C989 C9SB C9SE C991 C993 C996 C999 C99B C99E DO A9 20 A9 85 AD SD A9 8D 20 A2 20 4C $C987 #$64 $CIC8 #$12 $83 $023C $023D #$fo'F $023C $DA2A #$02 $C9B9 SC194 copy file done C9Al C9A4 20 A7 C9 4C 94 Cl JSR SC9A7 JMP SC194 copy file done C9A7 C9AA C9AC C9AE C9BO C9B3 C9B6 C9B9 C9BC C9BF C9Cl C9C3 E7 E2 01 7f 86 E4 77 79 FA 11 83 EB 25 03 53 OS F8 DS CA C9C9 C9CB C9CE C9DO C9D2 20 A4 29 85 20 20 AE 8E 20 A9 85 20 20 DO 20 A9 85 4C JSR LDA AND STA JSR JSR LOX STX JSR LDA STA JSR JSR BNE JSR LDA STA JMP SCAE7 SE2 #SOl $7f $0486 S06E4 $0277 $0279 $C9FA #Sl1 S83 $OOEB $0125 $C9CE $CA53 #$OS $fS SC9D8 C9D5 C9D8 C90B C9DO C9EO C9E2 C9E5 C9E7 C9EA C9EO C9EE C9Fl C9F3 C9F5 C9F7 20 20 A9 20 FO 20 FO 20 AE E8 EC 90 A9 85 4C 9B 35 80 A6 F3 25 03 9B 79 CF CA JSR JSR LOA JSR BEO JSR BEO JSR LOX INX CPX BCC LDA STA JMP $CF9B $CA35 #$80 SODA6 $C9D5 $0125 $C9EA $CF9B $0279 C9FA C9FO C9FF AE 79 02 B5 E2 29 01 C9C6 05 64 C8 12 S3 3C 3D ff 3C 2A 02 B9 94 Cl 02 02 02 DA C9 Cl D4 D6 02 02 C9 DO Dl CA C9 OD 01 CF 02 7S 02 C6 12 83 02 DB BNE LDA JSR LDA STA LDA STA LDA STA JSR LDX JSR JMP no 64, 'file type mismatch' IS secondary address prepare append drive no. of first file drive number enter file in directory 17 get data type no reI-file? write byte in buffer and get byte test bit 7 not set? check file type reI-file? get data byte in buffer $027S $C9B9 #$12 $83 $DB02 18 close channel LOX $0279 LDA $E2,X ANO #$01 drive number 138 Anatomy of the 1541 Disk Drive CAOI CA03 CA06 CA08 CAOA CAOC CAOF CAl2 CAl4 CAl7 CAIA CAlC CAIE CA2l CA23 CA26 CA29 CA2B CA2E CA30 CA3l CA32 CA35 CA37 CA39 CA3C CA3E CA40 CA42 CA44 CA46 CM8 CA4B CA40 CA4F CA52 85 AO 85 B5 85 20 AE B5 20 AE B5 29 8D A9 80 20 AO 20 FO C8 98 4C A9 85 20 85 A6 85 29 85 00 20 FO A9 20 60 CA53 CA56 CA59 CA5B CA5C CASE CA5F CA61 CA63 CA66 CA69 CA6C CA6F CA71 CA73 CA75 CA77 CA79 20 20 AS 48 AS 48 A9 85 20 20 20 20 A5 85 AS 85 A9 85 7F 85 80 08 81 75 79 DO C8 79 E7 07 4A 00 58 AO 01 25 01 C8 11 83 9B 85 82 F2 08 F8 OA 25 05 80 97 FE 04 02 04 02 02 02 09 01 04 03 Dl 00 03 01 CB El 06 05 12 83 07 03 CB 9C 06 87 05 86 00 88 01 01 EI E2 STA LOA STA LOA STA JSR LOX LOA JSR LOX LOA ANO STA LOA STA JSR LOY JSR BEO INY TYA $7F $FE85 $80 SD8,X $81 $0475 S0279 SDO,X S04C8 S0279 $E7,X #$07 S024A #$00 $0258 $09AO #SOI $0125 $CA31 save 18, directory track save directory sector J~1P $04C8 #$11 $83 $039B $85 $82 $F2,X #$08 $F8 $CA52 $0125 $CA52 #$80 $D097 set buffer pointer 17 LOA STA JSR STA LOX LOA ANO STA BNE JSR BEO LOA JSR RTS JSR JSR LOA PHA LOA PHA LOA STA JSR JSR JSR JSR LOA STA LOA STA LOA STA read block pointer in block set buffer pointer file type isolate and save get parameters for reI-file get file type reI-file? open channel and get byte channel number isolate end marker not set? get data type reI-file? set bit 7 $0103 $EICB $06 set drive number $05 #$12 $83 $0107 $0103 $EICB $E29C $06 $87 $05 $86 #$00 $88 18 open write channel set drive number 139 Anatomy of the 1541 Disk Drive CA7B CA7D CA7F CA80 CA82 CA83 CA8S 85 85 68 85 68 85 4C D4 D7 D5 D6 3B E3 STA STA PLA STA PLA STA JMP $D4 $D7 $D5 $D6 $E33B ****************************** CA88 CA8R CA8D CA8F CA91 CA93 CA9S CA97 CA99 CA9C CA9F' CAAI CAA3 CAA5 CAA7 CAA9 CAAC CAAF CABI CAB2 CAB4 CAB7 CABA CARB CABE CACO CAC3 CAC6 CAC9 20 A5 29 85 C5 FO 09 85 20 20 A5 29 85 A5 85 20 20 A5 18 69 20 20 A8 AE A9 20 20 20 4C 20 E3 01 E3 F.2 02 80 E2 4F E7 E3 01 7F D9 81 57 99 DE C3 C4 CA DE DS 03 C8 D4 93 Dr' 7A 10 6E 5E 99 94 02 C6 DE D5 Cl JSR LDA AND STA CMP BEO ORA STA JSR JSR LDA AND STA LDA STA JSR JSR LDA CLC ADC JSR JSR TAY LDX LDA JSR JSR JSR JMP $C320 $E3 #$01 $E3 $E2 $CA97 #$80 $E2 $C44F' $CAE7 $E3 #$01 $7F $09 $81 $OES7 $0599 $DE 2nd drive number compare with 1st drive number same? search for file in directory does name exist? drive number sector number read block from directory ok? pointer to directory entry #$03 $D4C8 $DF93 pointer plus 3 to file name set buffer pointer get buffer number S027A #$10 $C66E $DE5E $D599 $C194 16 characters write name in buffer write block to directory ok? done, prepare disk status ****************************** CACC CACE CADO CAD3 CAD6 CAD? CADA CADC CADF CAEl CAE3 CAE6 AS 29 8D AE CA EC 90 BD DO A9 4C 60 E8 07 4A 02 78 02 CAE7 CAEA 20 CC CA 80 80 02 77 02 OA 80 02 FS 62 C8 Cl LDA AND STA LDX DEX CPX BCC LOA BNE LOA JMP RTS R-command, 'rename' get drive no. from command line $E8 #$07 $024A S0278 check i f file present file type save $0277 $CAE6 $0280,X $CAD6 #$62 $ClC8 JSR $CACC LDA $0280,X 140 track number not zero? 62, I file not found I does file exist with old n, me? track number of new file Anatomy of the 1541 Disk Drive CAED CAEF CAFl CAF4 CAF5 CAF7 FO A9 4C CA 10 60 05 63 C8 Cl F3 BEO LDA JMP DEX BPL RTS SCAF4 #$63 $ClC8 file erased? 63, 'fi Ie exists' SCAEA ****************************** CAF8 CAFB CAFD CAFF CB02 CB04 CB07 CB09 CBOR CROE CBIO CB12 CB15 CBl7 CB19 CBIR CBID AD C9 DO AD 85 AD 85 AO AD C9 FO 20 C9 FO C9 DO 6C 01 2D 4C 03 6F 04 70 00 02 52 OE 58 57 37 45 2E 6F 02 02 02 02 F2 00 LDA CMP BNE LDA STA LDA STA LDY LDA CMP BEQ JSR CMP BEO CMP BNE JMP S0201 #S2D $CB4B $0203 $6F $0204 $70 #$00 S0202 #S52 SCB20 $F258 #S57 $CB50 #S45 $CB4B (S006F) ****************************** 6F 85 74 02 06 1A 05 02 '-' address in $6F/S70 3rd character from buffer ' R' to memory read ( RTS) 'w' to memory write ' E' memory-execute 'Memory-Read' M-R, read byte CB20 CB22 CB24 CB27 CB29 CB2B CB2E CB2F CB31 CB32 CB33 CB35 CB37 CB3A CB3C CB3E CB40 CB42 Bl 85 AD C9 90 AE CA FO 8A 18 65 E6 8D A5 85 A5 85 4C 6F 6F 49 02 6F A5 70 A6 43 D4 LDA STA LDA CMP RCC LDX DEX BEO TXA CLC ADC INC STA LDA STA LDA STA JMP CB45 CB48 20 EB DO 4C 3A D4 J~IP JSR SDDEB $D43A open read channel byte out CB4B CB4D A9 31 4C C8 C1 LDA #$31 JMP $C1C8 31, 'syntax error' 14 ($6F),Y S85 $0274 #S06 $CR45 S0205 M-command, 'memory' 2nd character from buffer SCR45 only one byte? number of bytes $6F $6F $0249 $6F $A5 S70 SA6 SD443 plus start address end pointer buffer pointer for error mEssage set to start address for ' r1-R' byte out ****************************** CB50 CB53 B9 06 02 91 6F length of command line less than 6? yes number LDA S0206,Y STA (S6F), Y 141 M-W, 'memory-write' read character and save Anatomy of the 1541 Disk Drive CB55 CBS6 CBS9 CBSB C8 CC OS 02 90 FS 60 INY CPY $0205 BCC $CBSO RTS number of characters all characters? ****************************** CBSC CBSF CB61 CB63 CR6S CB67 CB69 CR6B AC CO DO A9 85 A9 85 60 01 02 30 09 EA 6R FF 6C CB6C CR6F 20 72 CB 4C 94 Cl JSR $CB72 JMP $C194 CB72 CB73 CB74 CB76 CB77 CB78 CB7A C87C CB70 Cll7F CB81 88 98 29 OA A8 Bl 85 C8 Bl 85 6C OEY TYA AND ASL TAY LOA STA INY LOA STA JMP OF 6B 75 6B 76 75 00 LOY CPY BNE LOA STA LOA STA RTS $0201 #$30 $CB6C #$EA $6B #$FF $6C U-command, second char '0 ' no 'user' ptr to table of user-addresses $FFEA done, prepare error message #$OF A number times 2 ($6B), Y $75 as pointer in table address at $75/$76 ($6B),Y $76 ($0075) execute function $028E $7F $83 open direct access channel, , #' last drive number drive number channel number $C630 check drive and initialize $83 $0274 length of filename OD 01 E2 01 Fl CB LOA STA LOA PHA JSR PLA STA LOX DEX BNE LOA ,]SR JMP 70 C8 Cl 01 7C CC 85 02 05 EF 00 6F 70 LOA JMP LOY JSR LOX CPX BCS LDA STA STA #$70 $CIC8 #$01 $CC7C $0285 #$05 $CBAO lI$OO S6!" S70 ****************************** CB84 CB87 CB89 CB8B CB8C CB8F CB90 CB92 CB95 CB96 CB98 CB9A CB90 AO 85 AS 48 20 68 85 AE CA 00 A9 20 4C 8E 02 CBAO CBA2 CBAS CBA7 CBAA CBAD CBAF CBBI CBB3 CBBS A9 4C AO 20 AE EO BO A9 85 85 7F 83 30 C6 83 74 02 $CBAS #$01 $01E2 $CBFl greater than one? layout buffer and channel set flags, done 70, 'no channel' get buffer number buffer number bigger than 5? 70, 'no channel' 142 Anatomy of the 1541 Disk Drive CBB7 CBB8 CBBA CBBC CBBO CBBF CBCl CBC4 CBC6 CBC8 CBCB CBCO CBCF CB02 CBD5 CB07 CBOA CBOO CBOF CBE2 CBE4 CBE7 CBE9 CBEA CBEC CBEE CBn CBF3 CBF6 CBF8 CBFB CBFO CBFF CC02 CC04 CC07 CCOA CCOD CCOE CCOF CCll CC13 CC15 CC18 38 26 26 CA 10 A5 20 DO A5 20 DO A5 00 8D A5 00 8D A9 20 A6 AD 95 AA AS 95 9D A6 BD 09 9D A4 A9 99 A9 99 89 99 01'1 AA A9 95 A9 99 4C 6F 70 F9 6F 4F OA 70 50 D3 6F 4F 4F 70 50 50 00 E2 82 85 A7 7F 00 5B 83 28 40 2B 82 FF 44 89 F2 A7 3E 02 02 02 02 02 02 Dl 02 02 02 02 02 00 00 02 01 99 OE EC 00 94 Cl SEC ROL ROL OEX BPL LOA AND BNE LOA AND BNE LOA ORA STA LDA ORA STA LOA JSR LDX LOA STA TAX LOA STA STA LOX LOA ORA STJ>. LOY LOA STA LOA STA LOA STA ASL TAX LOA STA LOA STA JMP $6F $70 $CBB8 $6F $024F $CBAO $70 $0250 $CBAO $6F $024F $024F $70 $0250 $0250 lIS 00 $01E2 $82 $0285 $A7,X search channel channel number buffer number $7F $OO,X $025B,X $83 $022B,X #$40 $022B,X $82 lI$FF $0244,Y #$89 $OOF2,Y $00A7,Y $023E,Y drive number A times 2 #$01 $99,X t$OE $OOEC,Y $C194 ****************************** CClB AD 00 LOY #$00 CClO AO 00 LOX #$00 CClF A9 20 LOA #$20 CC2l 20 68 C2 JSR $C268 CC24 DO OA BNE $CC30 CC26 A9 31 LOA #$31 CC28 4C C8 Cl JMP $CIC8 143 secondary address set READ and WRITE flags channel number end pointer set READ and WRITE flags buffer number buffer pointer to one flag for direct access done B-command, 'Block' '-' search for minus sign found? 31, 'syntax error' Anatomy of the 1541 Dis~ Drive CC2B CC2D A9 30 4C C8 Cl LDA *$30 JMP $C1C8 CC30 CC3l CC33 CC35 CC38 CC3B CC3D CC3E CC40 CC42 CC43 CC45 CC48 CC46 CC4E CC4F CC50 CC53 CC55 CC58 CC5A 8A DO A2 B9 DO FO CA 10 30 8A 09 8D 20 AD OA TXA BNE LDX LDA CMP BEQ OEX BPL BMI TXA ORA STA JSR LDA ASL F8 05 00 02 5D CC 05 F8 E4 80 2A 02 6F CC 2A 02 AA BO 85 BD 85 6C 30, 'syntax error' $CC2B #$05 $0200,Y $CC5D,X $CC42 char from buffer compare with 'AFRWEP' found? $CC38 $CC26 compare with all characters not found, error *$80 $022A $CC6F $022A command number, set bit 7 get parameters A TAX 64 CC 70 63 CC 6F 6F 00 LDA STA LOA STA JMP comma, then error $CC64,X $70 $CC63,X $6F ($006F) number times 2 as index address of command hi address 10 jump to command ****************************** CC5D 41 46 52 57 45 50 names of the various block cmds 'AFRWEP' ****************************** CC63 03 CD F5 CC CC65 CC67 56 CD 73 CD CC69 CC6B A3 CD BO CD CC60 addresses of block commands $CD03, B-A $CCF5, B-F $CD56, B-R $CD73, B-W $CDA3, B-E $CDBO, B-P ****************************** get parameters for block command I CC6F CC71 CC73 CC75 CC78 CC7A CC7C CC7F CC8l CC83 CC85 CC87 CC89 CC8B CC8C CCBF CC9l AO A2 A9 20 DO AO B9 C9 FO C9 FO C9 DO C8 CC 90 60 00 00 3A 68 C2 02 03 00 02 20 08 lD 04 2C 07 74 02 EB LOY LDX LDA JSR BNE LDY LOA CMP BEO CMP BEQ CMP BNE INY CPY BCC RTS 41$00 *$00 *$3A $C268 $CC7C *$03 $0200,Y i$20 $CC8B #$10 $CC8B #$2C $CC92 $0274 $CC7C I:' test line to colon found? no, begin at 4th character search for separating char , , blank cursor right ',I comma line end? 144 Anatomy of the 1541 Disk Drive CC92 CC95 CC98 CC9B CC9D CC9F CCAI CCA3 CCA5 CCA7 CCA9 CCAB CCAE CCBO CCB2 CCB4 CCB6 CCB8 CCB9 CCBB CCBD CCBF CCCI CCC2 CCC4 CCC5 CCC7 CCCA CCCD CCCE CCDO CCDI CCD3 CCD5 CCD7 CCD8 CCDA CCDD CCDF CCEO CCE2 CCE4 CCE5 CCE8 CCEA CCED CCEE CCFl 20 EE AC EO 90 BO A9 85 85 85 A2 B9 C9 BO C9 90 29 48 A5 85 A4 85 68 85 C8 CC 90 8C 18 A9 E8 EO BO B4 88 30 7D 90 18 E6 DO 48 AE A5 9D 68 9D 60 Al 77 79 04 EC 8A 00 6F 70 72 FF 00 40 18 30 14 OF CC 02 02 02 70 71 6F 70 6F 74 02 El 79 02 00 03 OF 6F F6 F2 CC F8 72 F3 77 02 72 80 02 85 02 JSR INC LOY CPX BCC BCS LDA STA STA STA LOX LDA CMP BCS CMP BCC AND PHA LDA STA LDA STA PLA STA INY CPY BCC STY CLC LDA INX CPX BCS LDY DEY BMI ADC BCC CLC INC BNE PHA LDX LDA STA PLA STA RTS $CCAI $0277 $0279 *$04 $CC8B $CC2B *$00 $6F $70 $72 *$FF $0200,Y *$40 $CCCA #$30 $CCCA #$OF $70 $71 $6F $70 compare with maximum number 30, 'syntax error' erase storage area for decimal *s get characters from input buffer no digits? '0 ' no digits? convert ASCII digits to hex and save move digits one further $6F note read number increment pointer in input buffer line end reached no save pointer $0274 $CCAB $0279 #$00 lI$03 $CCE4 $6F,X convert hex digits to one byte $CCDO $CCF2,X $CCD7 add decimal value $72 $CCD7 $0277 $72 $0280,X counter for parameters $0285,X 10-byte ****************************** CCF2 preserve next parameter increment parameter counter 01 OA 64 ****************************** CCF5 20 F5 CD JSR $CDF5 CCF8 20 SF EF JSR $EF5F 145 hi-byte decimal values 1, 10, 100 B-F command, 'Block-Free' get track, sector and drive no. free block Anatomy of the 1541 Disk Drive CCFB 4C 94 Cl done, prepare error message JMP $C194 ****************************** LDA 11$01 CCFE A9 01 80 F9 02 STA $02F9 COOO ****************************** 20 F5 CD JSR $CDF5 C003 A5 81 LDA $81 C006 PHA 48 C008 C009 20 FA Fl JSR $FlFA FO OB BEQ $CDl9 CDOC COOE PLA 68 COOF C5 81 CMP $81 BNE $CD2C COll 00 19 COl3 20 90 EF JSR $EF90 4C 94 Cl JMP $C194 C016 COl9 COlA COIC COlE C020 C022 CD25 CD27 CD2A C02C CD2E CD31 CD33 68 A9 85 E6 A5 CD BO 20 FO A9 20 A9 20 00 81 80 80 07 OA FA EE 65 45 65 C8 FE Fl E6 Cl PLA LDA STA INC LDA CMP BCS JSR BEQ LDA JSR LDA JSR 11$00 $81 $80 $80 $FED7 $CD31 $FIFA SCOlA 11$65 $E645 11$65 $CIC8 B-A command, 'Block-Allocate' get track, sector and drive no. sector save find block in BAM block allocated? desired sector = next free sector? no allocate block in BAM done sector 0 next track track number 36, last track number + 1 >=, then 'no block' find free block in next track not found, check next track 65, 'no block' next free block 65,'no block' no more free blocks ****************************** JSR $CDF2 CD36 20 F2 CD 4C 60 D4 JMP $D460 CD39 open channel, set parameters read block from disk ****************************** CD3C JSR $D12F 20 2F 01 CD3F Al 99 LDA ($99,X) RTS 60 CD41 get byte from buffer set pointer to buffer get byte ****************************** CD42 JSR $C036 20 36 CD CD45 A9 00 LOA 11$00 CD47 20 C8 D4 JSR $04C8 JSR $CD3C CD4A 20 3C CD 99 44 02 STA $0244,Y CD4D A9 89 LDA $89 CD50 99 F2 00 STA $00F2,Y CD52 60 RTS CD55 read block from disk open channel, read block set buffer pointer to zero get a byte from the buffer ****************************** CD56 20 42 CO JSR $C042 20 EC D3 JSR $D3EC CD59 CD5C 4C 94 Cl JMP $C194 B-R command, 'Block-Read' read block from disk prepare byte from buffer prepare error message 146 set read and write flag Anatomy of the 1541 Disk Drive ****************************** 20 6F CC JSR $CC6F CD5F 20 42 CD JSR $CD42 CD62 B9 44 02 LDA $0244,Y CD65 99 3E 02 STA $023E,Y CD68 CD6B A9 FF LDA #$FF CD6D 99 44 02 STA $0244,Y CD70 4C 94 Cl JMP $C194 Ul command, sub. for 'Block-Read' get parameters of the command read block from disk end pointer save as data byte ****************************** CD73 20 F2 CD JSR $CDF2 CD76 20 E8 D4 JSR $D4E8 CD79 A8 TAY CD7A 88 DEY CD7B C9 02 CMP #$02 CD7D BO 02 BCS $CD81 CD7F LDY #$01 AO 01 CD81 A9 00 LDA #$00 CD83 20 C8 D4 JSR $D4C8 CD86 98 TYA CD87 20 Fl CF JSR $CFFI CD8A 8A TXA CD8B 48 PHA 20 64 D4 JSR $D464 CD8C CD8F 68 PLA CD90 AA TAX CD91 20 EE D3 JSR $D3EE CD94 4C 94 Cl JMP $C194 R-W command, 'Block-Write' open channel set bUffer pointer ****************************** CD97 20 6F CC JSR $CC6F CD9A 20 F2 CD JSR $Cm'2 20 64 D4 JSR $D464 CD9D CDAO 4C 94 Cl JMP $C194 U2, sub for 'Block-Write' get command parameters open channel and write block to disk done ****************************** 20 58 F2 CDA3 JSR $F258 CDM 20 36 CD JSR $CD36 CDA9 A9 00 LDA #$00 CDAB 85 6F STA $6F CDAD LDX $F9 A6 F9 CDAF BD EO FE LDA $FEEO,X STA $70 CDB2 85 70 CDB4 20 BA CD JSR $CDBA CDB7 4C 94 Cl JMP $C194 CDBA 6C 6F 00 JMP ($006F) 'B-E' command, 'Block-Execute' (RTS) open channel and read block ****************************** CDBD 20 D2 CD ,ISR $CDD2 CDCO A5 F9 LDA $F9 CDC2 OA ASL A CDC3 AA TAX AD 86 02 CDC4 LDA $0286 CDC7 95 99 STA $99,X 'B-P' command, 'Block-Pointer' open channel, get buffer number buffer number 147 end pointer to $FF done, prepare error message buffer pointer 10 less than 2? no buffer pointer to zero write byte in buffer write block to disk get byte from buffer done, error message address low buffer number buffer address high execute routine done jump to routine * 2 as index pointer value save as buffer pointer Anatomy of the 1541 Disk Drive CDC9 CDCC CDCF 20 2F Dl 20 EE D3 4C 94 Cl prepare a byte in buffer for output done JSR SD12F JSR SD3EE JMP SC194 ****************************** CDD2 CDD4 CDD6 CDD9 CODA CDDB CDDC CDDE CDEO CDE2 A6 E6 BD A8 88 88 CO 90 A9 4C D3 D3 85 02 CDE5 CDE7 CDEA COEC COEF COFI 85 20 BO 20 85 60 83 EB DO F4 93 OF F9 OC 05 70 C8 Cl open channel LOX INC LOA TAY DEY DEY CPY BCC LDA JMP $D3 S03 S0285,X #$OC $COE5 #$70 $ClC8 buffer number smaller than 14? yes STA JSR BCS JSR STA RTS $83 $OOEB SCOEO $OF93 $F9 secondary address open channel already allocated,70 'no channel buffer number set buffer number 70, 'no channel' ****************************** 20 02 CO JSR $C002 COF2 LOX $D3 A6 03 COF5 BO 85 02 LOA $028S,X COF7 COFA 29 01 AND #$01 85 7F STA $7F COFC BO 87 02 LOA $0287,X COFE CEOI 85 81 STA $81 BO 86 02 LOA $0286,X CE03 85 80 STA S80 CE06 CE08 20 SF 05 JSR $055F CEOB 4C 00 Cl JMP SCI00 ****************************** .]SR $CE2C CEDE 20 2C CE CEll 20 6E CE JSR SCE6E CE14 A5 90 LDA S90 85 D7 STA S07 CE16 20 71 CE JSR SCE7l CE18 E6 07 INC $07 CEIB E6 D7 CEIO INC SD7 A5 8B LDA $8B CEIF CE2l 85 D5 STA $D5 A5 90 CE23 LOA S90 OA ASL A CE25 CLC CE26 18 CE27 69 10 AOC #SlO CE29 85 D6 STA $06 60 CE2B RTS check buffer no. and open channe channel number buffer address drive number sector track track and sector ok? turn LED on set pointer for reI-file record number * record length divide by 254 remainder = pointer in data bloc) data pointer divide by 120 = side-sector # data ptr + 2 (track/sector ptr!) result of division equals side-sector number remainder times 2 plus 16 =ptr in side-sector to data ****************************** CE2C 20 D9 CE JSR SCE09 erase work storage 148 bloc~ Anatomy of the 1541 Disk Drive CE2F CE31 CE33 CE35 CE37 CE39 CE3B CE30 CE3F CE41 CE43 CE44 CE46 CE48 CE4A CE4C CE4E CE50 CE52 CE54 CE57 CE5A CE5C CE5E CE60 CE61 CE63 CE65 CE67 CE69 CE6B CE6D 85 Ali B5 85 B5 85 00 A5 FO A5 38 E9 85 BO C6 B5 85 46 90 20 20 A5 00 A5 18 65 85 90 E6 DO E6 60 92 82 B5 90 BB 91 04 90 OB 90 01 90 02 91 C7 6F 6F 03 ED CE E5 CE 6F F2 04 8B 8B 06 8C 02 80 STA LOX LOA STA LOA STA BNE LOA BEO LDA SEC SBC STA BCS DEC LDA STA LSR BCC JSR JSR LOA BNE LOA CLC ASC STA BCC INC BNE INC RTS $92 $82 $B5,X $90 $BB,X $91 $CE41 $90 $CE4C $90 channel number record number 10 record number hi record number not zero? #$01 $90 SCE4C $91 $C7,X $6F $6F $CE57 $CEED $CEE5 $6F $CE50 $04 then subtract one record length record number * record length shift reg ister left $8B $8B $CE6D $8C $DE6D $80 result in $8B/$8C/$8D ****************************** CE6E CE70 A9 FE 2C LDA #$FE .BYTE $2C ****************************** CE7l CE73 CE75 CE77 CE79 CE7A CE7C CE7E CE7F CE8l CE82 CE84 CE87 CE89 CE8B CE80 CE8E A9 85 A2 B5 48 85 95 68 95 CA DO 20 A2 85 95 E8 78 6F 03 8F 8A 8F 8A F3 D9 CE 00 90 8F EO 04 LOA STA LOX LOA PHA LDA STA PLA STA OEX BNE JSF LOX LOA STA INX CPX #$78 S6F #$03 $8F,X divide by 254, calculate block # 254 divide by 120, calculate side-sector number divisor $8A,X $8F,X S8A,X SCE77 $CE09 #$00 $90,X S8F,X erase work storage #$04 149 Anatomy of the 1541 Disk Drive CE90 CE92 CE94 CE96 CE98 CE9A CE9C CE9D CE9F CEAO CEA3 CEA6 CEM CEAB CEAD CEBO CEB2 CEB3 CEB5 CEB7 CEB9 CEBB CEBD CEBF CEC1 CEC3 CEC5 CEC7 CEC8 CECA CECC CECE CEDO CED2 CED4 CED8 90 A9 85 24 30 06 08 46 28 20 20 20 24 30 20 AS 18 65 85 90 E6 DO E6 AS 05 DO AS 38 E5 90 E6 DO E6 DO 85 60 F7 00 92 6F 09 8F 8F E6 ED E5 6F 03 E2 8F 90 90 06 91 02 92 92 91 C2 90 6F OC 8B 06 8C 02 90 CE CE CE CE BCC LDA STA BIT BMI ASL PHP LSR PLP JSR JSR JSR BIT BMI JSR LDA CLC ADC STA BCC INC BNE INC LDA ORA BNE LDA SEC SBC BCC INC BNE INC BNE STA RTS $CE89 #$00 $92 $6F $CEA3 $8F $8F $CEE6 $CEED $CEE5 $6F $CEBO $CEE2 $8F shift register 1 left add register 0 to register 1 shift register 1 left left-shift reg ister 1 twice $90 $90 $CEBF $91 $CEBF $92 $92 $91 $CE87 $90 $6F $CED8 $8B $CED6 $8C $CED6 $90 quotient in $8B/$8C/$8 D remainder in $90 ****************************** CED9 A9 00 LDA #$00 85 8B CEDB STA $8B CEDD 85 8C STA $8C CEDF 85 8D STA $8D CEEl 60 RTS erase work storage ****************************** CEE2 20 E5 CE JSR $CEE5 left-shift 3-byte register twice ****************************** CEE5 18 CLC CEE6 29 90 ROL $90 CEE8 26 91 ROL $91 CEEA 26 92 ROL $92 CEEC 60 RTS left-shift 3-byte register once ****************************** 150 Anatomy of the 1541 Disk Drive CEED CEEE CEFO CEF2 CEF4 CEF6 CEF7 CEF9 18 A2 B5 75 95 E8 DO 60 CEFA CEFC CEFD CEFF 0'00 CF02 Cr'04 CF06 Cr'08 A2 8A 95 E8 EO DO A9 95 60 CF09 O'OB CFOD AO A6 B9 96 C5 FO 88 30 AA 4C 60 cno CF12 Cl"l4 CFl6 CF'l7 CF19 CFIA CFlD CFIE 0'21 CF24 CF26 CF29 CF2C CF2E 0'31 0'33 CF34 CF36 CF37 CF39 cnc CF3E CF40 CF43 CF45 CF47 CF4A 0'4C CF4F 0'51 CF54 FD 8E 93 8E F7 00 FA 04 F8 06 FA 04 82 FA 00 FA 82 07 El OD CF 20 09 CF 20 B7 OF DO 46 20 D3 D1 20 8E D2 30 48 20 C2 OF A5 80 48 A5 81 48 A9 01 20 F6 D4 85 81 A9 00 20 F6 D4 85 80 FO IF 20 25 D1 FO Os 20 AB DD D(I 06 20 8C CF 4C 50 n' CLC LOX LOA ADC STA INX BNE FTS LDX TXA STA INX CPX BNE LDA STA RTS #$FD $8E,X $93,X $8E,X register $90/$91/$92 add to register $8B/$SC/$8D $CEFO #$00 $FA,X #$04 $CEFC #$06 $FA,X LDY LDX LDA STX CMP BEO DEY BMI TAX JMP RTS #$04 $82 $OOFA,Y $FA,Y $82 $CFlD JSF JSR BNE JSF JSR BMI JSR LOA PHA LDA PHA LDA JSF STA LDA JSR STA BEO JSR BEO JSR BNE JSR JMP $CF09 SDFB7 SCF6C $D1D3 $D28E $CF76 $OFC2 $80 set drive number $81 sector channel number channel number $CE~'A $CFOD track #$01 $D4F6 $81 #$00 SD4F6 $80 $CF66 $D125 $CF57 $DDAR get byte 1 from buffer sector get byte 0 from buffer track check file type reI-file? $C~'57 $CF8C SCF5D 151 Anatomy of the 1541 Disk Drive CFS7 CF5A CF5D CP5E CF60 CF63 20 20 68 85 68 85 4C CF66 CF67 CF69 CF6A CP6C CF6P CF72 CF73 68 85 68 85 20 20 AA 4C CP76 cns A9 70 4C C8 Cl LDA #$70 JMP $ClCS CF7B Cl"7E CF8l CF83 CF86 Cl"88 CF8B 20 20 DO 20 30 20 60 JSR JSR BNE JSR C~'61 8C CF 57 DE 81 80 6F CF 81 80 8C CF 93 DF 99 D5 09 B7 08 8E EE C2 CF' DF D2 DF JSR JSR PLA STA PLA STA JMP PLA STA PLA STA JSR JSR TAX JMP $CF8C $DE57 $81 get sector $SO $CP6F and track number $81 get back sector $80 $CF8C $DF93 and track number $D599 and verify 70, $CF09 $DFB7 $CF8B $D28E B~II $CF76 JSR $DFC2 RTS ****************************** CF8C CF8E CF90 CF92 CF94 CF96 CF98 CF9A A6 B5 49 95 B5 49 95 60 82 A7 80 A7 AE 80 AE LDX LDA EOR STA LDA EOR STA RTS $82 $A7,X #$80 $A7,X $AE,X #$80 $AE,X A2 86 20 20 20 90 A9 20 AS C9 PO DO C~'B7 A5 84 29 8F CFB9 12 83 07 00 25 05 20 9D 83 OF' 23 08 Dl Cl D1 DD LDX STX JSR JSR JSR BCC LDA JSR LDA CMP BEO BNE change buffer channel number rotate bit 7 in table ****************************** CF9B CE'9D CF9F' CFA2 CFA5 CF'AB CFAA CFAC CF'AP CF'BI n'B3 CFB5 'no channel' #$12 $83 $D107 $C100 $D125 $CF'AF #$20 $DD9D $83 #$OF' $Cf'D8 $CF'BF' write data byte in buffer channel 18 open write channel turn LED on check file type no reI-file change buffer secondary address IS? yes no LDA $84 AND #$8P secondary address 152 Anatomy of the 1541 Disk Orive CFBB CFBO CFBF CFC2 CFC4 CFC6 C9 BO 20 BO AS 4C CFC9 CFCB 00 03 4C AB EO CFCE CFDO CFD3 CF05 AS 20 A4 4C 85 Fl CF 82 EE 03 LOA JSR LDY JMP $85 $CFF1 $82 $D3EE CFD8 CFDA O'DF CFE1 CFE3 CFE5 CFE8 CFEA CFEC A9 85 20 C9 FO AS 20 A5 FO 60 04 82 E8 D4 2A 05 85 Fl CF F8 01 LDA STA JSR CMP BEO LDA JSR LOA BEO RTS #$04 $82 $D4E8 #$2A $CFE8 $85 channel 4 corresponding input buffer set buffer pointer 40 buffer end? $C~'F1 write data byte in buffer end flag set? yes CFED CFFO EE 55 02 60 C~'DC OF 19 25 01 05 85 90 01 CMP BCS JSR BCS LOA JMP #$OF $CFD8 $0125 $CFC9 $85 $0190 greater than 15? then input buffer check file type reI-file or direct access? data byte write in buffer BNE $CFCE JMP $EOAB direct access file? write data byte in reI-file write data byte in buffer channel number prepare next byte for output $F8 $CFEO INC $0255 RTS set command flag ****************************** CFFl CFF2 CFF5 0'F7 CFF8 CFFA CFFD O'FE CFFF DODO D002 D004 48 20 10 68 A9 4C OA 93 OF 06 61 C8 C1 AA 68 81 99 1"6 99 60 PHA JSR BPL PLA LDA JMP ASL TAX PLA STA INC RTS $DF93 $CFFD #$61 $C1C8 A ($99,X) $99,X ****************************** D005 D008 DOOB 20 D1 C1 20 42 DO 4C 94 C1 JSR $C1Dl JSR $0042 JMP $C194 ****************************** DOOE DOll D012 D014 D016 D019 20 OF Fl A8 86 A7 EO 1"1" 48 20 8E 02 JSR TAY LDX CPX PHA JSR SFIOF SA7,Y #SFF $D28E 153 write data byte in buffer save data byte get huffer number associated buffer? 61, ' file not open' buffer number times 2 as index data byte write in buffer increment buffer pointer I-command, Initialize find drive number load BAM prepare disk status Anatomy of the 1541 Disk Drive DOIC DOID D02l D024 D025 D026 DO 27 D029 D02C D02D D02F 0031 D033 D035 D038 D03A D03D D03F AA A9 20 68 A8 8A 09 99 8A 29 85 A2 86 AE 86 20 A9 4C 70 48 E6 80 A7 00 OF F9 00 81 85 FE 80 D3 D6 BO 8C D5 TAX LDA JSR PLA TAY TXA ORA STA TXA AND STA LDA STX LDX STX JSR LDA JMP lI$70 $E648 70, 'no channel' H80 $OOA7,Y lISOF SF9 lISOO S81 SFE85 $80 $D6D3 #$BO sector 0 18 track 18 transmit param to disk controll command code 'read block header transmit to disk controller $D58C ****************************** D042 20 Dl Fa JSR $FODI D045 20 13 D3 JSR $D313 D048 JSR $DOOE 20 OE DO D04B LDX $7F A6 7F D04D A9 00 LDA lISOO D04F 9D 51 02 STA S025l,X D052 8A TXA D053 OA ASL A D054 AA TAX D055 AS 16 LDA S16 D057 95 12 STA $12,X D059 LDA $17 A4 17 D05B 95 13 STA S13 ,X D05D JSR $D586 20 86 D5 D060 AS F9 LDA $F9 D062 OA ASL A D063 AA ;TAX D064 A9 02 LDA #$02 D066 95 99 STA $99,X D068 Al 99 LDA ($99,X) D06A A6 7F LDX S7F D06C 9D 01 01 STA SOlOl,X D06F A9 00 LDA #$00 95 lC D07l STA $lC,X D073 95 FF STA $FF,X ****************************** D075 D078 D07A D07C D07D D07E 0080 D082 20 3A EF AO 04 A9 00 AA 18 71 6D 90 01 E8 JSR LDY LOA TAX CLC ADC BCC INX $EF3A lI$04 #SOO (S6D),Y $D083 load BAM read block drive number reset flag for 'BAM changed' save ID buffer number buffer pointer to $200 get character from buffer drive number flag for write protect flag for read error calculate blocks free buffer address to $6D/$6E begin at position 4 add no. of free blocks per track X as hi-byte 154 Anatomy of the 1541 Disk Drive D083 D084 D085 D086 D087 D089 D08B D08D D08F D090 D091 D093 D096 D097 D09A C8 C8 C8 C8 CO FO CO DO 48 8A A6 9D 68 9D 60 48 F8 90 EE 7F FC 02 FA 02 INY INY INY INY CPY BEO CPY BNE PHA TXA LDX STA PLA STA RTS plus 4 #$48 $D083 #$90 $D07D $7F $02FC ,X $02FA,X track 18? then skip last track number? no lo-byte hi-byte drive number hi-byte to $2FC lo-byte to $2FA ****************************** D09B D09E DOAI DOM DOA7 DOA9 DOAC DOAE 20 20 20 20 85 20 85 60 DO C3 99 37 80 37 81 DOAF DOR2 DOR4 DOB6 DOB7 DOBA DOBD DOCO 20 A5 DO 60 20 20 20 4C 9B DO 80 01 IE DO C3 IE D6 DO D5 Dl Dl CF D6 DO CF JSR JSR JSR JSR STA JSR STA RTS $D6DO $DOC3 $D599 $D137 $80 $D137 $81 parameters to disk controller read block ok? get byte from buffer track next byte from buffer sector JSR LDA BNE RTS JSR JSR JSR JMP $D09B $80 $DOB7 track $CFlE $D6DO $DOC3 $CFIE change buffer parameters to disk controller read block change buffer ****************************** DOC3 DOC5 A9 80 DO 02 LDA #$80 BNE $DOC9 ****************************** DOC7 DOC9 DOCC DOCF DODO DOD3 DOD4 DOD5 DOD6 DOD7 DOD9 DODB DaDE DOEO DOE2 A9 8D 20 AA 20 SA 48 aA AA A9 95 20 C9 BO F6 90 4D 02 93 DF 06 D5 00 99 25 Dl 04 06 B5 LDA STA JSR TAX JSR TXA PHA ASL TAX LDA STA JSR CMP BCS INC read block code for tread' #$90 $024D $DF93 write block code for 'write' save get buffer number $D506 get track/sector, read/write blk A buffer pointer times 2 #$00 $99,X $D125 #$04 SDOES SB5,X pointer in buffer to zero get file type reI-file or direct access? yes 155 Anatomy of the 1541 Disk Drive DOE4 DOE6 DOE8 DOE9 DOEA DO 02 F6 BB 68 AA 60 BNE $DOE8 INC $BB,X PLA TAX RTS increment block counter ****************************** DOEB A5 83 LOA $83 DOED C9 13 CMP #$13 DOEF 90 02 BCC $DOF3 DOFI 29 OF AND #$OF DOF3 C9 OF CMP #$OF DOF5 DO 02 BNE $DOF9 DOF7 A9 10 LOA #$10 DOF9 AA TAX DO FA 38 SEC DOFB BD 2B 02 LOA $022B,X DOFE 30 06 BMI $0106 DI00 29 OF AND #$OF DI02 85 82 STA $82 DI04 AA TAX 0105 18 CLC DI06 60 RTS open channel for reading secondary address 19 smaller? ****************************** 0107 A4 83 LDA $83 DI09 C9 13 CMP #$13 DI0B 90 02 BCC $DI0F 0100 29 OF AND #$OF DI0F AA TAX DllO BO 2B 02 LDA $022B,X DID A8 TAY OA D1l4 ASL A 90 OA BCC $D121 D1l5 D1l7 30 OA BMI S0123 98 TYA D1l9 DllA 29 OF AND #SOF DllC 85 82 STA S82 AA DllE TAX 18 DllF CLC D120 60 RTS open channel for writing secondary address 19 smaller? D121 0123 0124 30 F6 38 60 BMI $D119 SEC RTS A6 B5 4A 29 C9 60 82 EC 07 04 LOX LDA LSR AND OIP RTS flag for ok channel number flag for ok flag for channel allocated ***.*.** •• i**.** •• ************ 0125 0127 D129 D12A D12C Ol2E 16 check for file type 'REL' S82 $EC,X A #$07 #$04 'REL'? ***************.************** 156 get buffer and channel numbers Anatomy of the 1541 Disk Drive 012F 0132 0133 0134 0136 20 93 OF OA AA A4 82 60 JSR $OF93 ASL A TAX LOY $82 RTS get buffer number ****************************** 0137 013A 0130 013F 0141 0142 0144 0147 0149 014B 0140 014E 0150 0151 0153 0155 20 B9 FO Al 48 B5 09 00 A9 95 68 F6 60 Al F6 60 2F 01 44 02 12 99 99 44 02 04 FF 99 99 99 99 JSR LOA BEO LOA PHA LOA CMP BNE LOA STA PLA INC RTS LOA INC RTS $012F $0244,Y $0151 ($99,X) $99,X $0244,Y $014D i$FF $99,X ($99,X) S99,y get character from buffer increment buffer pointer 20 00 85 B9 FO A9 99 A5 60 37 01 36 85 44 02 08 80 F2 00 85 JSR BNE STA LOA BEQ LOA STA LOA RTS S0137 $0191 $85 $0244,Y S016A i$80 $00F2,Y $85 016A 0160 016F 0172 0175 0177 0179 Ol7B Ol7E 0180 0183 0186 0189 018C 018F 0191 20 A9 20 20 C9 FO 85 20 85 20 20 20 20 20 A5 60 IE 00 C8 37 00 19 80 37 81 IE 03 00 C3 IE 85 JSR LOA JSR JSR CHP BEQ STA JSR STA JSR JSR JSR JSR JSR LOA RTS $CFlE #$00 $04C8 $0137 #$00 $0192 $80 S0137 $81 $CFlE $DI03 $0600 $00C3 SCFIE S85 0192 0195 0197 20 37 Dl A4 82 99 44 02 01 CF 01 06 00 CF buffer pointer equal end pOinter? no $99,X ****************************** 04 01 get byte from buffer buffer pointer to -1 data byte increment buffer pointer 0156 0159 015B 0150 0160 0162 0164 0167 0169 CF get a byte from buffer get buffer and channel number end pointer get byte and read next block get byte from buffer not last character? save data byte end pointer yes REAO-flag data byte change buffer and read next block set buffer pointer to zero get first byte from buffer track number zero yes, then last block save last track number get next byte save as following track change buffer and read next block save drive number param to disk controller transmit read command change buffer and read block get data byte JSR $D137 LOY $82 STA S0244,Y 157 get next byte from buffer save as end pointer Anatomy of the 1541 oisk Drive LOA $85 D19A AS 85 019C 60 RTS ****************************** 20 F1 CF JSR $CFFI 0190 DIAO FO 01 BEQ $D1A3 D1A2 60 RTS get data byte back DIA3 DIA6 DIA9 DIAB OIAE DIBO DlB3 DIB5 DIB8 OIBB DIBE DlCl DlC3 get drive number find free block in BAM 20 20 A9 20 AS 20 AS 20 20 20 20 A9 4C D3 IE 00 C8 80 Fl 81 Fl C7 IE 00 02 C8 D1 Fl 04 CF CF 00 CF 06 D4 JSR JSR LDA JSR LDA JSR LDA JSR JSR JSR JSR LOA JMP $DI03 $FllE #$00 $D4C8 S80 SCFFl S81 SCFFI SDOC7 SCFlE S0600 #$02 SD4C8 buffer pointer to zero track number as first byte sector number as second byte write block change buffer param to disk controller buffer pointer to 2 ****************************** DIC6 85 6F STA $6F DICB 20 EB 04 JSR $04EB DlCB 18 CLC DICC 65 6F ADC $6F DICE 95 99 STA $99,X DIDO 85 94 STA $94 DlD2 60 RTS ****************************** DID3 DID6 DID7 DIDA DIDC DIDE 20 AA BD 29 85 60 93 DF 58 02 01 7F JSR TAX LDA AND STA RTS 3B BO 01 18 08 85 20 20 85 A6 28 90 09 90 29 6F 27 02 7F D3 82 83 02 80 2B 02 3F and increment $025B,X #SOl $7F isolate drive number and save SEC BCS SOlE3 CLC PHP STA JSR JSR STA LOX PLP BCC ORA STA ANO get buffer pointer get drive number get drive number ****************************** DIE2 DIE3 DIE4 DIE6 DIE9 DIEC DIEE DIFO DIFI DIF3 DIF5 DIFB increment buffer pointer $DF93 ****************************** DlDF OlEO byte in buffer and write blocl byte in buffer buffer full? $6F $0227 SD37F S82 $83 SOIF5 #SBO $022B,X #S3F 158 find write channel and buffer flag for writing find read channel and buffer flag for reading save bu ffer number close channel allocate free channel channel number secondary address read channel? flag for writing set Anatomy of the 1541 Disk Orive OIFA OlFB OlFD 0200 0203 0206 0208 020A 0200 020F 0212 0214 0217 021A 021C 021E 0221 0223 0226 A8 A9 99 99 99 C6 30 20 10 20 A9 4C 99 C6 30 20 30 99 60 FF A7 AE CO 6F lC 8E 08 5A 70 C8 A7 6F 08 8E EC AE 00 00 00 02 02 Cl 00 02 00 TAY LOA STA STA STA OEC BMI JSR BPL JSR LOA J~IP STA OEC BMI JSR BMI STA RTS #SFF $00A7,Y $OOAE,Y $OOCO,Y $6F $0226 $028E $0217 $025A *$70 $CIC8 $00A7,Y $6F $0226 $028E $020F $OOAE,Y ****************************** 0227 0229 022B 0220 AS 83 C9 OF 00 01 60 LOA $83 CMP *$OF BNE $022E RTS 022E 0230 0233 0235 0237 0239 D23B 0230 0240 0242 0244 0246 D249 024B 0240 024E D250 0251 0253 D256 0259 A6 BO C9 FO 29 85 A9 90 A6 A9 95 20 A6 A9 CA 30 OA 00 00 80 60 LOX LOA CMP BEO ANO STA LOA STA LDX LOA STA JSR LOX LOA OEX BMI ASL BNE ORA STA RTS 83 2B 02 FF 22 3F 82 FF 2B 02 82 00 F2 5A 02 82 01 03 FA 56 02 56 02 $83 $022B,X #$FF $0259 #$3F $82 #$FF $022B ,X $82 #$00 $F2,X $D25A $82 #$01 $0253 A $0240 $0256 $0256 A6 B5 C9 FO 48 A9 82 A7 FF 09 FF LOX LDA CMP BEO PHA LDA write in associated table decrement buffer number done already? find buffer found? erase flags in table 70, 'no channel' buffer number in table buffer number already done? find buffer not found? buffer number in table close channel secondary address IS? no else done already channel number not associated? then done channel number erase association in table erase REAO and WRITE flag free buffer channel number set bit 0 shift to correct position free in allocation register ****************************** 025A 025C 025E 0260 D262 D263 default value $82 $A7,X #$FF $D26B free buffer channel number buffer number not associated? #$FF 159 Anatomy of the 1541 Disk Drive 0265 0267 0268 026B 026D 026F 0271 0273 0274 0276 0278 D279 027C D27E 0280 D282 0284 0285 0287 D289 D28A D28D 95 68 20 A6 B5 C9 FO 48 A9 95 68 20 A6 B5 C9 FO 48 A9 95 68 20 60 A7 F3 D2 82 AE FF 09 FF AE F3 D2 82 CD FF 09 FF CD F3 D2 STA PLA JSR LDX LOA CMP BEO PHA LDA STA PLA JSR LDX LDA CMP BEO PHA LDA STA PLA JSR RTS $A7,x erase buffer association $D2~'3 erase buffer allocation channel number $82 $AE,X #$FF $D27C A2 89 3D FO CA 07 4F 02 E9 EF 04 LDX LDA AND BEO DEX iste associated in second table? no #$FF $AE,X erase association $D2F3 $82 $CD,X #$FF $D28D erase buffer in allocation reg. channel number associated in 3rd table? no #$FF $CD,X erase association $D2F3 erase buffer in allocation reg ****************************** D28E 98 TYA 028F 48 PHA 0290 AO 01 LDY #$01 0292 20 BA D2 JSR $D2BA 10 DC BPL $D2A3 D295 0297 DEY 88 D298 20 BA D2 JSR $D2BA 029B 10 06 BPL $D2A3 D29D 20 39 D3 JSR $0339 D2AO AA TAX D2A1 30 13 BMI $D2B6 D2A3 LDA $OO,X B5 00 D2A5 30 FC BMI $D2A3 D2A7 LDA $7F AS 7F D2A9 95 00 STA $OO,X D2AB 9D 5B 02 STA $025B,X D2AE 8A TXA D2AF OA ASL A D2BO A8 TAY D2B1 A9 02 LDA #$02 D2B3 99 99 00 STA S0099,y D2B6 68 PLA D2B7 TAY A8 D2B8 8A TXA D2B9 60 RTS D2BA D2BC D2BF D2C2 D2C4 re~, #$07 $024F,Y $EFE9 ,Y $D2C8 160 find buffer erase bit Anatomy of the 1541 oisk Drive 02C5 02C7 10 F5 60 BPL $D2BC RTS 02C8 02CB 02CE 0201 0202 0203 0205 0206 0208 0209 020A 020C 020E 02EO 02El 02E2 02E4 02E5 02E7 02E9 02EB 02EO 02EE 02FO 02F2 02F3 02F5 02F6 02F7 02F9 02FC 02FF 0300 0302 0303 0304 0306 B9 50 99 8A 88 30 18 69 LOA EOR STA TXA OEY BMI CLC AOC TAX RTS LOX LOA BMI TXA CLC AOC TAX LOA BPL CMP BEQ PHA LOA STA PLA ANO TAY INY LOX ROR ROR OEY BNE CLC OEX BPL RTS 4F 02 E9 EF 4F 02 03 08 AA 60 A6 B5 30 8A 18 69 AA B5 10 C9 FO 48 A9 95 68 29 A8 C8 A2 6E 6E 88 00 18 CA 10 60 82 A7 09 07 A7 FO j,'F EC FF A7 OF 10 50 02 4F' 02 01 F3 $024F,Y $EFE9,X $024F,Y buffer number $0208 *$08 buffer number $82 $A7,X $02E9 #$07 $A7,X $0209 #$FF $0209 *$FF $A7,X #$OF buffer number #$10 $0250 $024F 16 rotate 16-bit allocation reg. S0303 erase bit for buffer $02F9 ****************************** 0307 0309 030B 030E 0310 0312 A9 85 20 C6 00 60 OE 83 27 02 83 F9 LOA STA JSR OEC BNE RTS #$OE $83 $0227 $83 $030B ****************************** 0313 0315 0317 0319 D31C A9 85 A6 BO C9 OE 83 83 2B 02 FF LOA STA LOX LOA CMP rotate bit #$OE $83 $83 S022B,X #$FF 161 close all channels 14 secondary address close channel next secondary address close channels of other drives 14 secondary address association table channel associated? Anatomy of the 1541 Disk Drive D31E D320 D322 D324 D327 D328 D32B D32D D32F D331 D334 D336 D338 FO 29 85 20 AA BD 29 C5 DO 20 C6 10 60 14 3F 82 93 DF 5B 02 01 7F 03 27 D2 83 DF BEO AND STA JSR TAX LDA AND CMP BNE JSR DEC BPL RTS $D334 #$3F $82 $DF93 no channel number get buffer number $025B,X #$01 $7F $D334 $D227 $83 $D317 ****************************** D339 D33B D33C D33E D340 0342 0344 D346 D348 D349 D34A D34e D34D D34F D351 D353 D355 D356 D358 D35A D35C D35E D360 D362 D363 0365 D367 0369 036B 0360 036F 0371 A5 48 AO B6 B5 10 C9 DO 8A 18 69 AA B5 10 C9 DO C8 CO 90 A2 DO 86 29 AA B5 30 C9 90 A6 EO 90 BO 6F 0373 D375 0377 D37A 037B 0370 037E A4 6F 00 FA A7 04 FF 16 07 A7 04 FF 09 05 E4 n~ lC 6F 3F 00 FC 02 08 6F 07 07 E2 A9 FF 99 A7 00 68 85 6F 8A 60 LDA PHA LDY LDX LDA BPL CMP BNE TXA CLC ADC TAX LDA BPL CMP BNE INY CPY BCC LDX BNE STX ANO TAX LOA BMI CMP Bee LOX epx Bce BeS LOY LOA STA PLA STA TXA RTS $6F #$00 $FA,Y $A7,X $D348 #$FF $D35E #$07 $A7,X $D355 #SFF $D35E #$05 SD33E #SFF $D37A $6F #$3F SOD ,X $0363 #$02 $0373 S6F #$07 S0348 $0355 S6F #SFF $00A7,Y SoF 162 drive number isolate equal to actual drive number no close channel next channel Anatomy of the 1541 Disk Drive ****************************** 037F AD 00 LOY #$00 0381 A9 01 LOA #$01 0383 BIT $0256 2C 56 02 D386 DO 09 BNE $0391 0388 C8 INY 0389 OA ASL A 038A DO F7 BNE $0383 D38C A9 70 LOA #$70 038E 4C C8 C1 JMP $ClC8 0391 0393 0396 0399 039A 49 FF 20 56 02 80 56 02 98 60 EOR #$FF AND $0256 STA $0256 TYA RTS find channel and allocate set bit 0 channel free? rotate bit to left all channels checked? 70, 'no channel' rotate bit model erase bit allocate channel ****************************** 039B 20 EB DO JSR $OOEB JSR $ClOO 039E 20 00 Cl 03Al 20 AA 03 JSR $03AA LOX $82 03A4 A6 82 BO 3E 02 03A6 LOA $023E,X 03A9 60 RTS get byte for output open channel for reading turn LED on get byte in output register channel number get byte 03AA 03AC 03AF 03Bl A6 20 DO 4C 82 25 Dl 03 20 El LOX JSR BNE JMP $82 $0125 $03B4 $E120 channel number check file type no reI-file? get byte from reI-file 03B4 03B6 03B8 03BA 03BC 03BE 03CO 03C3 03C5 03C7 D3C9 03CB A5 C9 FO B5 29 DO 20 C9 00 A9 95 4C 83 OF 5A F2 08 13 25 01 07 07 89 F2 OE 03 LOA CMP BEO LOA AND ENE JSR CMP BNE LOA STA JMP $83 #$01" $0414 $F2,X #$08 $0303 $0125 #$07 $03CE #$89 $F2,X $030E secondary address 15 yes, r:ead error channel 03CE 0300 0302 A9 00 95 F2 60 LOA #$00 STA $F2,X RTS 0303 0305 0307 030A 030C 030E 03EI A5 FO 20 C9 90 20 B5 LOA BEO JSR CMP BCC JSR LDA 83 32 25 01 04 22 2F Dl 99 end flag set? no check file type direct access file? no set REAO and WRITE flag erase READ and WRITE flag $83 $0409 $0125 #$04 $0400 $012F $99,X secondary address zero, LOAD? check file type reI-file or direct access? no get buffer and channel number buffer pointer 163 Anatomy of the 1541 Disk Drive D3E3 D3E6 03E8 03EA 03EC 03EE 03FO 03F3 03F5 03FA 03FC 03FF D9 DO A9 95 F6 Al 99 B5 09 DO A9 99 60 0400 D403 0405 0408 20 56 Dl A6 82 9D 3E 02 60 0409 D40C 040E 0411 AO FO 20 4C 0414 0417 D419 D4lB D41D D41F 0421 0423 0425 D428 042A 042D 042F 0431 0433 0436 0438 043A 043C 043F 0441 0443 D445 D447 D449 D44C 03~'8 44 04 00 99 99 99 3E 99 44 05 81 F2 02 02 02 00 CMP BNE LOA STA INC LOA STA LOA CMP BNE LOA STA RTS $0244,Y SD3EC #$00 S99,X S99,X (S99,X) S023E,y S99,X S0244,y SD3FF #S8l SOOF2,Y buffer pointer to zero increment buffer pointer get byte from buffer into output register buffer pointer equal end pointer? no set flags JSR $0156 LDX $82 STA $023E,X RTS get byte from buffer channel number byte in output register 54 02 F2 67 EO 03 04 LOA BEO JSR JMP $0254 $0400 $E067 SD403 flag for directory? no create directory line 20 C9 DO AS C9 DO A9 85 20 A9 20 C6 A9 00 E8 04 D4 18 95 02 12 OD 85 23 Cl 00 Cl E6 AS 80 12 JSR CMP BNE LDA CMP BNE LDA STA JSR LOA JSR OEC LOA BNE SD4E8 #$D4 SD433 S95 #S02 SD433 #$00 S85 $C123 #$00 $E6Cl $A5 #S80 $0445 set buffer pointer 20 85 00 A9 20 A9 95 A9 85 AS 80 60 37 01 85 09 04 C8 D4 02 9A 88 F7 85 43 02 JSR STA BNE LOA JSR LDA STA LOA STA LOA STA RTS $D137 $85 $0443 #SD4 SD4C8 #$02 S9A,X #S88 SF7 S85 S0243 CR in output register erase error flags create 'ok l message set buffer pointer back set REAO flag get byte from buffer into output register set buf ptr in front of error ptr hi-address set READ flag data byte into output register ****************************** D440 0450 equal end pointer? no 20 93 OF OA JSR SOF93 ASL A 164 read next block get buffer number times 2 Anatomy of the 1541 Disk orive 0451 0452 0454 0456 0458 045A 045C 045F AA A9 95 Al FO 06 4C 60 00 99 99 05 99 56 01 TAX LOA STA LOA BEO OEC JMP RTS *$00 $99,X ($99,X) $045F $99,x $0156 ****************************** 0460 0462 A9 80 00 02 LDA *$80 BNE $0466 buffer pointer to zero get first byte from buffer no block following? buffer pointer to -1 read next block read block command code for reading ****************************** 0464 A9 90 LOA #$90 0466 05 7F ORA $7F STA $0240 0468 80 40 02 046B A5 F9 LOA $F9 0460 20 03 06 JSR $0603 0470 LOX $F9 A6 F9 JMP $0593 0472 4C 93 05 write block command code for writing drive number save code ****************************** 0475 LOA *$01 A9 01 0477 STA $024A 80 4A 02 047A A9 11 LOA #$11 047C STA $83 85 83 047E 20 46 OC JSR $OC46 0481 A9 02 LOA #$02 JMP $D4C8 0483 4C C8 04 allocate buffer and read block ****************************** allocate new block 18 secondary address allocate new block D486 0488 048A A9 12 85 83 4C DA DC LDA #$12 STA $83 JMP $DCDA ****************************** D480 0490 0492 0494 D496 0497 0499 049B 049E 049F 04A1 D4A3 04A6 04A8 04AB 04AO 04BO 04B3 20 3B A9 01 85 6F A5 69 48 A9 03 85 69 20 20 68 85 69 A9 00 20 C8 A5 80 20 F1 A5 81 20 Fl 20 C7 20 99 DE Fl 04 CF CF 00 05 JSR LOA STA LOA PHA LOA STA JSR PLA STA LOA JSR LOA JSR LDA JSR JSR JSR $OE3B #$01 $6F $69 param to disk controller execute command file type to sequential 17 secondary address allocate buffer and read block buffer pointer to 2 write directory block get track and sector number a block save step width 10 for block allocation *$03 $69 $F12D find free block in BAM $69 #$00 $D4C8 $80 $CFF1 $81 $CFFl $00C7 $D599 get step width back buffer pointer to zero track number in buffer sector number in buffer wri te block to disk and verify 165 Anatomy of the 1541 Oisk Orive 04B6 04B8 D4BB D4BE D4CO 04C3 D4C5 A9 20 20 00 20 A9 4C 00 C8 FI FB FI FF FI 04 CF CF CF LOA JSR JSR BNE JSR LOA JMP HOO $04C8 $CFFI $D4BB $CFFI *$FF $CFFI buffer pointer to zero fill buffer with zeroes zero as following track $FF as number of bytes ****************************** 04CB 85 6F STA $6F D4CA 20 93 OF JSR $OF93 04CO OA ASL A 04CE AA TAX 04CF B5 9A LOA $9A,X 04Dl 85 95 STA $95 04D3 A5 6F LDA $6F 0405 95 99 STA $99,X D4D7 85 94 STA $94 04D9 60 RTS set buffer pointer save pointer get buffer number times 2 ****************************** D4DA A9 11 LOA #$11 04DC 85 83 STA $83 20 27 02 D40E JSR $0227 A9 12 04El LOA #$12 04E3 85 83 STA $83 04E5 4C 27 02 JMP $0227 close internal channel 17 ****************************** set buffer pointer get buffer number 04E8 04EB 04EC 04ED 04EF 04Fl 04F3 D4F5 20 OA AA B5 85 B5 85 60 93 OF 9A 95 99 94 JSR ASL TAX LDA STA LOA STA RTS $OF93 A $9A,X $95 $99,X $94 85 20 AA BO 85 AO Bl 60 71 93 OF EO FE 72 00 71 STA JSR TAX LOA STA LOY LDA RTS BO 29 00 A8 86 8A 5B 02 01 40 02 F9 LOA ANO ORA PHA STX TXA close channel 18 close channel buffer pointer 10 $71 $OF93 $FEEO,X $72 #$00 ($7l),Y ****************************** 0506 0509 D50B 050E 050F D511 buffer pointer 10, new value buffer pointer hi ****************************** 04F6 D4F8 04FB 04FC 04FF 0501 0503 0505 buffer pointer hi $025B,X #$01 $0240 $F9 166 get byte from buffer pointer 10 get buffer number hi-byte buffer address pointer hi get byte from buffer check track and sector numbers command code for disk controller drive number plus command code save buffer number Anatomy of the 1541 Disk Drive 0512 D513 OS14 0516 OS19 DSIB oSlo D520 0522 D523 D524 D525 D527 D529 D52B D52C D520 D52E D530 D533 D535 D538 D53A D53D D53F D540 D543 D546 D548 054A 0540 D54F OA AA BS 80 BS FO CD BO 07 40 02 06 20 07 FE 28 AA 68 48 29 C9 DO 68 48 4A BO AD 90 AD FO CO DO 8A 20 CD FO BO 20 A9 4C FO 90 4F 05 01 01 03 02 01 05 D5 FE 33 4B 40 02 30 52 66 45 F2 02 05 E6 ASL TAX LOA STA LOA BEO CMP BCS TAX PLA PHA AND CMP BNE PLA PHA LSR BCS LOA BCC LOA BEO CMP BNE TXA JSR CMP BEO BCS JSR LDA ,TMP A times 2 $ 07 ,X $0240 $06,X $oS4A $FE07 $oS4A sector save track 66, , illegal track or sector' 36, highest track number + 1 66, , illegal track or sector' command code lI$FO #$90 $DS7A code for writing? no A $OS35 $0101 $OS38 $0102 $053F $FED5 $0572 IAI, format marker 73, 'cbm dos v2.6 1541' track number get maximum sector number compare with sector number equal, then error smaller? get track and sector number $F24B $0240 $D54A $057A $0552 #S66 $E645 66, 'illegal track or sector' ****************************** D552 D554 0555 D5S6 0558 OSSA 055C 055E A5 OA AA B5 85 B5 85 60 F9 055F D561 0563 D566 0568 056R OS60 056F 0571 A5 FO Co BO 20 C5 FO 90 60 0572 0575 20 52 D5 A9 73 06 80 07 81 80 EA 07 FE E5 4B F2 81 OE DC LOA ASL TAX LOA STA LOA STA RTS $F9 A LOA BEO CMP BCS JSR CMP BEO BCC RTS $80 $0540 $FED7 $054D $F24B $81 S054D $054D S06,X $80 $07,X $81 get track and sector number buffer number *2 as index track sector track zero, then error 36, maximum track number + 1 66, 'illegal track or sector' get maximum sector number sector error JSR S0552 LDA #$73 get track and sector numbet 167 Anatomy of the 1541 Disk Drive D577 4C 45 E6 JMP $E645 D57A D57C D57D D580 D582 D585 A6 68 8D 95 9D 60 LDX PLA STA STA STA RTS F9 4D 02 00 5B 02 73, 'cbm dos v2.6 1541' $F9 buffer number $024D $OO,X $025B,X command code for disk controller in command register and write in table ****************************** A9 80 LDA #$80 D586 D588 DO 02 BNE $D58C read block code for read ****************************** write block code for write drive number buffer number D58A D58C D58E D590 D593 D596 A9 05 A6 8D AD 20 90 7F F9 4D 02 4D 02 OE D5 LDA ORA LDX STA LDA JSR #$90 $7F $F9 $024D $024D $D50E command code check track and sector ****************************** D599 20 A6 D5 JSR $D5A6 D59C BO FB BCS $D599 48 D59E PHA A9 00 D59F LDA #$00 D5Al 8D 98 02 STA $0298 68 D5A4 PLA 60 D5A5 RTS verify execution verify execution wait for end D5A6 D5A8 D5AA D5AC D5AE D5BO D5B2 D5B4 D586 D5B8 D5BA DSBD D5BF D5C2 D5C3 B5 30 C9 90 C9 Fa C9 Fa C9 DO 2C 30 4C 18 60 cmd code (bit 7) still in reg? yes D5C4 D5C5 38 60 SEC RTS D5C6 D5C7 D5C8 D5CA 05CB 98 48 TYA PHA LOA $71" PHA LDA $025B,X 00 1A 02 14 08 08 08 04 OF OC 98 02 03 3F D6 7F 48 BO 58 02 AS LDA BMI CMP BCC CMF BEO CMP BEO CMF BNE BIT BMI JMP CLC RTS $OO,X SD5C4 #$02 $D5C2 #$08 $D5BA #$OB $D5BA #SOF $D5C6 $0298 $DSC2 SD63F erase error flag error-free execution 8 write protect 11 ID mismatch 15 create error message execution ended execution not yet ended 168 drive number Anatomy of the 1541 Disk Drive D5CE D5DO D5D2 D5D3 D5D6 D5D9 D5DC D5DE D5EO D5E3 D5E6 D5E8 D5E9 D5EB D5ED D5EF D5Fl D5F4 D5F6 D5F8 D5FA D5FD D600 D603 D606 D607 D60A D60D D6l0 D6l3 D616 D6l9 D6lB D6lD D620 D623 D625 D628 062B D62D 062F 0631 D633 0635 D636 D638 063A D63C 063F 0641 D644 0645 D648 D64A 064B 29 85 A8 B9 8D 20 C9 BO 4C BD 29 48 C9 DO A5 09 9D 24 70 A9 8D 8D AC AD 38 F9 8D B9 20 EE 20 C9 90 AC B9 DO AO 20 B5 C9 90 24 10 68 C9 DO 05 90 85 20 68 2C 30 48 A9 01 7F CA 6D A6 02 03 6D 5B FO 90 07 7F B8 5B 6A 39 00 99 9A 99 9A FE 02 D6 D6 02 02 02 02 02 02 DB 9A DB 76 99 FE 02 FE D6 02 A6 D6 02 08 99 02 DB FE DB 9A 02 76 D6 00 02 2B 6A OF 90 05 7F 5B 02 00 OA E6 98 02 23 CO AND STA TAY LDA STA JSR CMP BCS JMP LDA AND PHA CMP BNE LDA ORA STA BIT BVS LDA STA STA LDY LDA SEC SBC STA LDA JSR INC JSR CMP BCC LOY LOA BNE LDA JSR LDA CMP BCC BIT BPL PLA CMP BNE ORA STA LDA JSF PLA BIT BMI PHA LOA #$01 $7F drive number $FECA,Y $026D $D6A6 #$02 $D5E3 $D66D $025B,X #$FO bit roodel for drive read attempt not ok? done command code isolate #$90 $D5F4 $7F #$B8 $025B,X $6A $D63l #$00 S0299 S029A $0299 S029A code for write no drive number $FEDB,Y $029A $FEDB,Y $D676 $0299 $D6A6 #$02 $D625 $0299 $FEDB,Y $0600 $029A $D676 $OO,X #$02 $D65C S6A SD644 constants for read atteropts #S90 SD63F S7F S025B,X SOO,X SE60A cntr for searches next to track counter position head next to track increment counter read ateropt return message smaller than 2, ok? load counter get constants not yet zero (table end )? position head return message ok? command code for writing? no drive number command code in table return message set error message $0298 $D66D #SCO command code for head positioning 169 Anatomy of the 1541 Disk Orive 0640 064F 0651 0653 0655 0658 065A 065C 0650 065F 0661 0663 0666 0669 066B 0660 066E 0670 0671 0672 0674 0675 05 95 B5 30 20 C9 BO 68 C9 00 05 90 20 C9 BO 68 85 68 A8 B5 18 60 7F 00 00 FC A6 06 02 09 0676 0678 067A 067C 067E 0681 0682 0684 0686 C9 FO 30 AO 20 38 E9 00 FO 00 18 OC 01 93 D6 0688 068A 0680 068E 0690 0692 AO 20 18 69 00 60 FF 93 06 0693 0694 0695 0697 069A 069D 069F 06A1 06A4 06A5 48 98 99 09 FO A9 99 68 60 D6A6 06A8 D6AA D6AB A5 6A 29 3F A8 AD 60 02 A4 90 OC 7F 5B 02 A6 D6 02 02 7F 00 01 F6 OA 01 F6 7F F'E 02 FE 02 FB 00 FE 02 ORA STA LOA BM! JSR CMP RCS PLA CMP RNE ORA STA JSR CMP BCS PLA STA PLA TAY LOA CLC RTS CMP BEO BM! LOY JSR SEC SBC BNE BEO LOY JSR CLC AOC BNE RTS PHA TYA LOY STA CMP REO LOA STA PLA RTS $7F $OO,X $OO,X S0651 $06A6 #$02 $0635 drive number in command registe~ #$90 $066D $7F $025B,X $06A6 #$02 $063F command code for writing no drive number in table attempt execution again return message error? $7F get drive number back $OO,X error code end-of-execution flag wait for execution attempt command execution agair return message incorrect? #$00 $0692 $0688 #$01 S0693 transmit data for head position #$01 S067C $0692 #SFF S0693 transmit data for head position #SOl SD688 S7F $02FE,Y $02FE,Y $069A #$00 $02FE,Y LOA $6A ANO #S3F TAY LOA $026D drive number wait for r-eturn message from disk contr-011er maximum number of repetitions bit for LED 170 Anatomy of the 1541 Disk Drive D6AE D6Bl D6B4 D6B7 D6B9 D6BB D6BD D6BF D6Cl D6C2 D6C4 D6C5 D6C8 D6CB D6CE D6CF 4D 8D BD 95 B5 30 C9 90 88 DO 48 AD OD 8D 68 60 ODIC ODIC 5B 02 00 00 FC 02 03 E7 6D 02 ODIC ODIC EOR STA LDA STA LDA BMI CMP BCC DEY BNE PHA LDA ORA STA PLA RTS $lCOO $lCOO $025B,X $OO,X $OO,X $D6B9 #$02 $D6C4 $D6AB $026D $lCOO $lCOO command transmit to disk controller and return message wait ok? yes decrement counter attempt again LED off ****************************** 20 93 DF JSR $DF93 D6DO ASL A D6D3 OA A8 TAY D6D4 A5 80 LDA $80 D6D5 99 06 00 STA $0006,Y D6D7 A5 81 LDA $81 D6DA 99 07 00 STA $0007,Y D6DC D6DF A5 7F LDA $7F D6El OA ASL D6E2 TAX AA 60 RTS D6E3 transmit param to disk controller get buffer number ****************************** $83 enter file in directory secondary address $82 channel number $81 sector number $80 track number save D6E4 D6E6 D6E7 D6E9 D6EA D6EC D6ED D6EF D6FO D6F2 D6F4 D6F7 D6FA D6FB D6FD D6FF D701 D703 D706 D707 D709 D70B D70E D711 A5 48 A5 48 A5 48 A5 48 A9 85 20 AD 48 A4 29 85 A6 5D 4A 90 A2 8E 20 FO 83 82 81 80 11 83 3B DE 4A 02 E2 01 7F F9 5B 02 OC 01 92 02 AC C5 lD LDA PHA LDA PHA LDA PHA LDA PHA LDA STA JSR LDA PHA LDA AND STA LDX EOR LSR Bce LDX STX JSR BEO #$11 $83 $DE3B $024A $E2 #$01 $7F $F9 $025B,X A $D715 #$01 $0292 $C5AC $D730 171 track number transmit sector number transmit drive number times 2 secondary address 17 get track and sector number file type save drive number set buffer number equal drive number? pointer in directory load dir and find first entry not found? Anatomy of the 1541 Disk Drive 0713 00 28 BNE $0730 found? 0715 0718 071A 07lC D7lE 0720 0723 AO FO C5 FO 85 20 4C 91 02 OC 81 IF 81 60 04 30 07 LOA BEO CMP BEO STA JSR JMP $0291 $0726 $81 $0730 $81 S0460 $0730 sector number in directory equal zero equal sector number? yes save sector number read block 0726 0728 072B D72E 0730 0733 0735 0738 073A 0730 0740 0743 0744 0747 0749 074B 0740 0750 0751 0754 0757 0758 075B 075E 0761 0762 0765 0766 0768 076B 076D 076F 0771 D772 0774 0776 0779 077B 0770 077F 0782 0784 0785 0788 078A A9 80 20 DO 20 A5 80 01 LOA STA JSR BNE JSR LOA STA LOA STA LOA JSR PLA STA CMP BNE ORA JSR PLA STA JSR PLA STA JSR JSR TAY LOA TAX LOA JSR LOY LOA STA INY CPY BCC LDA CMP BNE LDY LOA STA INY LDA STA INY lI$Ol $0292 $C617 $0730 $0480 $81 $0291 lIS02 $0292 $0292 $04C8 A9 80 AD 20 68 80 C9 00 09 20 68 80 20 68 80 20 20 92 02 17 00 80 81 91 02 92 92 C8 C6 04 02 02 02 04 4A 02 04 02 80 Fl CF 80 02 FI CF 85 02 Fl CF 93 OF AS AO AA A9 20 AO A9 91 C8 CO 90 AO C9 00 AO AD 91 C8 AD 91 C8 7A 02 10 6E C6 10 00 94 IB F9 4A 02 04 13 10 59 02 94 5A 02 94 pointer to one find next entry in directory found? write directory block sector number pointer to 2 set buffer pointer $024A #$04 $0740 #$80 $CFFI file type reI-file? no set bit 7 and write in buffer $0280 $CFFI following track in buffer $0285 $CFFI $OF93 following sector in buffer get buffer number $027A pointer to dr i ve numbe r #$10 $C66E #$10 #$00 (S94),Y 16, length of filename write filename in buffer #$lB position 27 already? no file type reI-file no $076F $024A #$04 $0790 #$10 $0259 ($94) ,Y S025A (S94) , Y 172 fill with zeroes at pos 16 track and sector the side-sectors in dir entry Anatomy of the 1541 Disk Drive D78B D78E D790 D793 D794 D796 D797 D798 D79A D79D D79F D7A2 D7A5 D7A7 D7AA D7AD D7AF D7Bl D7B3 AD 91 20 68 85 AA 68 85 AD 85 9D AD 85 9D AD 85 A5 85 60 58 02 94 64 D4 82 83 91 D8 60 92 DD 66 4A E7 7F E2 02 02 02 02 02 LOA STA JSR PLA STA TAX PLA STA LDA STA STA LDA STA STA LDA STA LDA STA RTS $0258 (S94) ,Y $D464 record length in directory write block $82 channel number $83 $0291 $D8 $0260,X $0292 SDD $0266,X $024A $E7 $7F SE2 secondary address ****************************** D7B4 A5 83 LDA S83 D7B6 8D 4C 02 STA S024C D7B9 20 B3 C2 JSR SC283 D7BC 8E 2A 02 STX S022A D7BF AE 00 02 LDX S0200 D7C2 AD 4C 02 LDA S024C D7C5 DO 2C BNE SD7F3 D7C7 EO 2A CPX ltS2A D7C9 DO 28 fiNE $D7n D7CB A5 7E LDA S7E D7CD FO 4D BEO $08lC 07CF 85 80 STA $80 D7Dl AD 6E 02 LDA S026E D7D4 85 7F STA S7F 07D6 85 E2 STA $E2 D7D8 A9 02 LDA #$02 D7DA 85 E7 STA $E7 D7DC AD 6F 02 LDA S026F D7DF 85 81 STA S8l D7El 20 00 Cl JSR $CIOO D7E4 JSR SDC46 20 46 DC D7E7 A9 04 LDA #$04 D7B9 05 7F ORA S7F D7EB A6 82 LDX S82 D7ED 99 EC 00 STA $OOEC,Y D7FO 4C 94 Cl JMP $C194 D7F3 D7F5 D7F7 D7FA D7FC EO DO AD DO 4C 24 IE 4C 02 03 55 DA D7FF 20 Dl Cl CPX BNE LDA BNE JMP file type drive number OPEN command, secondary adr secondary address get line length, erase flags first character from buffer secondary address not equal 0 (LOAD)? '* , last track number track number last drive number drive number set data type to program last sector number sector turn LBD on allocate buffer, read block file type drive number channel number set flag done '$ , no secondary address not equal to zero? OPEN S *$ 24 $0815 S024C SD7FF $OA55 JSR SCIDI analyze line to end 173 <> 15 Anatomy of the 1541 Disk Drive 0802 0809 080B 080E 0810 0812 AD 85 A9 85 20 AS 09 4C 0815 D817 0819 EO 23 DO 12 4C 84 CB CPX #$23 BNE $082R JMP $CB84 08lC 08lE D821 0823 0825 0828 082B 082E 0830 0832 D834 D835 0837 0839 A9 80 A9 85 80 20 20 DO A2 FO 8A FO A9 4C LOA STA LOA STA STA JSR JSR BNE LOX BEO TXA REO LOA JMP 083C D830 083f' 0840 0843 0845 0848 0849 084C D84F D852 0855 0857 D85A D85D D860 0861 0864 D866 0869 086A 0860 086F 087l 0873 D876 0879 88 FO 88 8C A9 20 E8 8E 20 20 20 A2 8E 8E 8E E8 EC BO 20 Ell EC BO CO FO 20 AE 86 0805 0807 85 FE 80 00 81 46 DC 7F 02 EB 07 02 96 00 7F 8E 42 E5 04 00 OC 02 02 DO Cl 05 30 C8 Cl 01 7A 02 80 68 C2 78 12 CA 9D 00 58 97 4A 02 C3 C3 C4 02 02 02 77 02 10 09 DA 77 02 07 04 3E 09 DA 4C 02 83 LOA STA LOA STA JSR LOA ORA J~lP DEY BEO OEY STY LOA JSR INX STX JSR JSR JSR LDX STX STX STX INX CPX BCS JSR INX CPX BCS CPY REO JSR LOX STX $FE85 $80 #$00 $81 $OC46 $7F #$02 $07EB 18, directory track track sector 0 allocate buffer, read block drive number continue as above '# ' open direct access file #$02 $0296 #$00 $7F $028E $0042 $CIE5 $0834 #$00 $0840 file type program drive 0 load BAM analyze line colon found? comma found? no $083C #$30 $C1C8 30, 'syntax error' $0840 $027A #$80 $C268 pointer to drive number shift CR analyze line to end $0278 $C312 $C3CA $C49D #$00 $0258 $0297 $024A comma counter get drive number check drive number find file entry in directory default values record length $0277 $0876 $DA09 comma before equal sign? no get file type and control mode $0277 $0876 *$04 S08Bl $OA09 $024C $83 additional comma? no file type get file type and control method secondary address 174 Anatomy of the 1541 Disk Drive D87B D87D D87F D882 D884 D887 D88A D88C D88E D891 D894 D896 D898 D89A D89D DBAO D8A2 DBA4 DBA7 DBAA DBAC DBAE EO BO BE A9 8D AD DO A9 8D AD DO AS 29 80 AD DO A9 BD AD C9 FO 4C 02 12 97 40 F9 4A IB 02 4A 4A 11 E7 07 4A 80 05 01 4A 97 01 18 40 DBBI D8B4 D8B7 DBBA DBBD DBBF DBCl D8C4 BC B9 BD AD DO A9 BD DO 7A 00 5B 80 B7 01 97 BO D8C6 DBC8 D8CA D8CR DB CD D8CF D8Dl D8D3 D8D6 AS 29 AA DO A9 24 FO 20 4C E7 80 D8D9 D8DC D8DE D8El D8E4 D8E6 D8E8 D8E9 D8EB DBED DBFO D8F2 A9 DO 4C AD C9 FO 8A DO A9 4C A9 4C 80 02 03 E3 D9 00 02 40 00 02 02 02 02 02 02 02 02 02 D9 02 02 02 02 02 14 20 E7 06 B6 C8 E3 D9 05 63 C8 CI 33 CB CI CPX BCS STX LDA STA LDA BNE LDA STA LDA BNE LDA AND STA LDA BNE LDA STA LDA CMP BEO JMP #$02 $DB91 $0297 #$40 $02F9 $024A $D8A7 #$02 $024A $024A $D8A7 $E7 #$07 $024A $02BO $DBA7 #$01 $024A $0297 #$01 $D8C6 $0940 LDY LDA STA LDA RNE LOA STA BNE $027A,X $0200,Y $025B $02BO $DB76 #$01 $0297 $DR76 pointer behind second comma get value record length track number LOA AND TAX BNE LDA BIT BEO JSR JMP $E7 #$80 file type isolate wildcard flag $D8El #$20 $E7 $D8D9 $C8B6 $D9E3 wildcard in name LOA BNE JMP LDA CMP BEO TXA BNE LDA JMP LDA JMP $0280 $D8El $D9E3 $0200 #$40 $D8FS greater than 2? yes o or 1 (LOAD or SAVE) file type not deleted PRG -as file type get file type and command line track number not equal zero? file type sequential control method 'w' yes 'w' as control method was file closed? yes byte 0 in buffer and write block track number of the first block already existing first character from input buffer I@ I? yes $DBFO #$63 $CICB #$33 $CIC8 wildcard set? 63, 'file exists' 33, 'syntax error' 175 Anatomy of the 1541 oisk Orive ****************************** 08F5 AS E7 LOA $E7 08F7 29 07 ANO *$07 08F9 CO 4A' 02 CMP $024A 08FC DO 67 BNE $0965 08FE C9 04 CMP 1t$04 0900 FO 63 BEO $0965 0902 20 OA DC JSR $OCDA AS 82 0905 LOA $82 0907 8D 70 02 STA $0270 D90A A9 11 LDA *$11 20 EB DO D90C JSR $DOEB AD 94 02 D911 LDA $0294 0914 20 C8 04 JSR $04C8 0917 AO 00 LOY *$00 0919 Bl 94 LDA ($94),Y 09lB 09 20 ORA *$20 0910 91 94 STA (S94),Y 091F AD 1A LOY lI$lA 0921 AS 80 LOA $80 0923 91 94 STA ($94) ,Y 092S C8 INY 0926 A5 81 LOA $81 0928 STA ($94), Y 91 94 092A AE 70 02 LOX S0270 0920 AS 08 LDA $08 092F STA $0260,X 90 60 02 0932 AS 00 LOA $00 0934 90 66 02 STA S0266,X 0937 20 3B OE JSR $DE3B 093A 20 64 04 JSR $D464 0930 4C EF 09 JMP $D9EF 0940 0943 0945 0947 094A 094D 094F 0951 0953 0955 0957 0959 D95C 095E 0960 D963 D965 D967 D96A D96C D96F D972 AO 00 A9 4C AD C9 FO A9 24 FO A9 4C AS 29 CD FO A9 4C AO 8C AE EO 80 OS 62 C8 97 03 OB 20 E7 05 60 C8 E7 07 4A 05 64 C8 00 79 97 02 02 Cl 02 C1 02 Cl 02 02 LOA BNE LOA JMP LOA CMP BEO LOA HIT BEO LOA JMP LDA AND C~IP BEO LOA JMP LOY STY LDX CPX $0280 S094A *$62 $ClC8 $0297 #$03 $D9SC #$20 $E7 S09SC #$60 i$ClC8 SE7 #$07 $024A $096A i$64 SClC8 #SOO $0279 S0297 #$02 open a file with overwriting file type isolate file type different? reI-file? 64, , file type mismatch' save channel number open read channel set buffer pointer for directory file type set bit S, open file track and sector for open with at-sign channel number pointer to directory block get track and sector number write block prepare trk, sector, and drive II first track number file not erased? 62, , file not found' control mode 'M' yes,then no test of unclosed fill bit S test in file type not set, ok 60, 'write file open', isolate file type 64, 'file type mismatch' control mode IAI, append 176 Anatomy of the 1541 Disk Drive D974 D976 D978 D97A D97C D97E D980 D982 D983 D985 D987 D98A D98D D98E D990 D993 D996 D998 D99A D99D DO C9 FO Bl 29 91 A5 48 A9 85 20 20 68 85 20 AD C9 DO 20 4C D9AO D9A2 D9A4 D9A7 D9A8 D9AA D9AD D9AE D9BO D9B3 D9B6 D9B7 D9B9 D9BC D9BE D9CO D9C3 D9C6 D9C9 D9CB D9CE D9DO D9D3 D9D5 D9D8 D9DA D9DD D9DF D9E2 AO Bl 8D C8 Bl 8D C8 Bl AE 8D 8A FO CD FO A9 20 AE BD 85 BD 85 20 A4 AE B5 99 B5 99 60 D9E3 D9E5 D9F7 D9E9 A5 29 85 20 lA 04 EB 94 4F 94 83 11 83 3B DE 64 D4 83 AO 97 02 55 2A 94 D9 02 DA Cl 13 94 59 02 94 5A 02 94 58 02 58 02 OA 58 05 50 C8 79 80 80 85 81 46 82 79 D8 60 DD 66 02 C1 02 02 02 DC 02 02 02 E2 01 7F DA DC BNE CMP BEQ LDA AND STA LDA PHA LDA STA JSR JSR PLA STA JSR LDA CMP BNE JSR JMP LDA LDA STA INY LDA STA INY LDA LDX STA TXA BEO CMP BEQ LDA JSR LDX LDA STA LDA STA JSR LDY LDX LDA STA LDA STA RTS LDA AND STA JSR $D990 #$04 $D965 ($94), Y #$4F ($94), Y $83 .$11 $83 $DE3B $D464 no reI-file? channel 17 get track and sector number write block $83 SD9AO $0297 #$02 $D9EF $DA2A $C194 get channel • back control Illode done .$13 ($94), Y $0259 track ($94),Y $025A (S94), Y $0258 $0258 SD9C3 .$0258 $D9C3 #$50 $CIC8 $0279 $0280,X $80 $0285,X $81 $DC46 $82 $0279 $D8,X $0260,Y $DD,X $0266,Y $E2 #$01 $7E' SDCDA record length last record len 50, 'record not present' track sector drive # 177 Anatomy of the 1541 Disk Drive D9EC D9EF D9Fl D9F3 D9F5 D9F8 D9FA D9FC D9FE DAOI DA03 DA06 20 A5 C9 BO 20 A5 85 A5 8D A5 8D 4C E4 83 02 11 3E 80 7E 7F 6E 81 6F 99 D6 DE 02 02 Cl JSR LDA CMP BCS JSR LDA STA LDA STA LDA STA JMP $D6E4 $83 #$02 $DA06 $DE3E $80 $7E $7F $026E $81 $026F $C199 channel # ****************************** DA09 DAOC DAOF DAll DA12 DA14 DAl7 DA19 DAlC DAlE DAIF DA2l DA24 DA26 DA29 BC B9 AO 88 30 D9 DO BC AO 88 30 D9 DO 8C 60 7A 02 00 02 04 08 B2 FE F8 97 02 05 08 86 FE F8 4A 02 LDY $027A,X LDA $0200,Y LDY #$04 DEY BMI $DAIC 01P $FEB2,Y BNE $DAll STY $0297 LDY #$05 DEY BMI $DA29 CMP $FEB6,Y BNE $DAlE STY $024A RTS ****************************** DA2A DA2D DA2F DA32 DA34 DA37 DA39 DA3A DA3B DA3D DA40 DA42 DA45 DM7 OA49 OMB OA40 OMF DA5l OA54 20 A9 20 FO 20 A6 E8 8A DO 20 A9 20 A6 A9 95 A9 05 A6 90 60 39 CA 80 A6 DO F6 95 OE 81 05 A3 01 02 C8 D4 82 01 F2 80 82 83 2B 02 JSR LOA JSR BEQ JSR LDX INX TXA BNE JSR LDA JSR LDX LOA STA LDA ORA LOX STA RTS $CA39 #$80 $DDA6 $DA 2A SDE95 S8l A9 OC 80 2A 02 control modes • R I, I WI, 'AI, $0A42 $DIA3 #$02 $D4C8 $82 #$01 $F2,X #S80 $82 $83 S022B,X LOA #SOC STA $022A 178 I ~ save file types ID' ,'S' ,'pi ,lUI ,'L I save preparation for Append open channel to read, get byte last byte? no get track and sector number sector number ****************************** DA55 OA57 check file type and control mOl pointer in command line get characters from line not $FF? close buffer, write block buffer pointer to 2 channel number set flag for WRITE channel number in table OPEN U$" command number 12 Anatomy of the 1541 Disk Drive DA5A DA5C DA5F DA60 DA62 DM3 DM5 DA68 DMB DA6D DA6F DA72 DA75 DA78 DA7A DA7C DA7E DAB 1 DA84 DA86 DAB9 DA8B DA8E DA90 DA91 DA92 DA95 DA98 DA9B DA9E DAAl DAA4 DAA7 DAAA DAAD DAM' DAB2 DAB4 DAB7 DAB9 DABB DABD DABF A9 AE CA FO CA DO AD 20 30 85 EE EE EE A9 85 A9 BD BD DO 20 DO 20 AO 88 88 BC 20 20 20 20 20 20 20 20 A6 9D A4 8D 09 95 A9 85 60 00 74 02 OB 21 01 BD 19 E2 77 78 7A 80 E7 2A 00 01 lB E5 05 DC 03 7A 00 98 20 CA B7 9D 9E 37 82 3E 7F 8E 04 EC 00 A3 02 C3 02 02 02 02 02 Cl C2 02 C2 C3 C3 C3 C7 C4 EC Dl 02 02 LDA LDX DEX BEO DEX BNE LDA JSR BMI STA INC INC INC LDA STA LDA STA STA BNE JSR BNE JSR LDY DEY DEY STY JSR JSR JSR JSR JSR JSR JSR JSR LDX STA LDA STA ORA STA LDA STA RTS *$00 $0274 $DA6D $DAB6 $0201 $C3BD SDAB6 SE2 $0277 $0278 $027A *$80 $E7 *$2A $0200 $0201 $DA9E $ClE5 $DA90 $C2DC #$03 second character get drive number not a plain number? set wildcard flag ,* , as file name in command buffer absolute jump test input line to ':' found? erase flags pointer to drive no. in command analyze 1 ine ascertain file type get drive number initialize drive if necessary prepare disk title load directory create and prepare directory get byte from buffer channel number byte in output register drive number save as last drive number $027A $C200 $C398 $C320 $C3CA $C7B7 SC49D $EC9E $D137 S82 $023E S7F $028E *$04 $EC,X #SOO $A3 PRG-flag set pointer back in input buffer ****************************** DACO DAC2 DAC5 DAC7 DAC9 DACB DACE DADI A9 00 8D F9 02 A5 83 DO OB A9 00 BD 54 02 20 27 D2 4C DA D4 LDA STA LDA BNE LDA STA JSR JMP DAD4 C9 OF CMP #$OF *$00 $02F9 SB3 $DAD4 #$00 $0254 $D227 $D4DA CLOSE-routine secondary address not zero? secondary address 0, LOAD close channel close internal channels 17 & 18 15 179 Anatomy of the 1541 Disk Drive DAD6 DADS DADB DADD DADF DAEI DAE4 DAE6 FO 20 AS C9 90 AD DO 4C 14 02 DB 83 02 FO 6C 02 03 94 Cl BEO JSR LDA CMP BCC LDA BNE JMP $DAEC $DB02 $83 #$02 $DADI $026C $DAE9 $C194 DAE9 DAEC -DAEE DAFO DAF3 DAF5 DAF7 DAFA DAFC DAFF 4C A9 85 20 C6 10 AD DO 4C 4C AD OE 83 02 83 F9 6C 03 94 AD JMP LDA STA JSR DEC BPL LDA BNE JMP JMP $C1AD #$OE $83 $DB02 $83 $DAFO $026C $DAFF $C194 $CIAD CI DB 02 C1 C1 yes, close all channels close file secondary address smaller than 2? termination 14 secondary address close file next secondary address termination ****************************** DB02 DB04 DB07 DB09 DBOB A6 BD C9 DO 60 83 2B 02 FF 01 DBOC DBOE DB10 DBl3 DB15 DB17 DB19 DBIB DBIE DB20 DB23 DB26 DB29 29 85 20 C9 FO C9 FO 20 BO 20 20 20 4C OF 82 25 D1 07 OF 04 DB2C DB2F DB32 DB35 DB37 D839 DB3B DB3D DB3F DB41 DB43 DB44 CB46 DB48 20 20 20 A6 86 E6 A9 85 85 A5 38 E9 85 20 11 07 09 62 A5 F4 27 D1 DB DB EE D2 FI DD IE CF CB El D5 73 73 00 70 71 D6 OE 72 51 DF LDX LDA CMP BNE RTS $83 $022B,X #$FF $DBOC close file secondary address get channel number no channel associated? no, then done isolate channel number AND #$OF STA $82 JSR $D125 CMP #$07 BEO $DB26 CMP #$04 BEO $DB2C JSR $D107 BCS $DB29 JSR $DB62 JSR $DBA5 JSR $EEF4 JMP $D227 JSR JSR .TSR LDX STX INC LDA STA $DDFI $CF1E $EICB $D5 $73 $73 #$00 $70 LDA SEC SBC STA JSR $D6 check data type direct access? yes reI-file? yes channel for writing open no file for writing? write last block wri te en try in d ir and block write BAM close channel get buffer number, write block change buffer get last side-sector side-sector number #$OE $72 $ DF51 minus 14 for pointer calculate block number of file 180 Anatomy of the 1541 Disk Drive DB4B DB4D DB4F DB51 DB53 DB55 DB 57 DB5A DB5C DB5F A6 AS 95 A5 95 A9 20 FO 20 AC B2 70 B5 71 BB 40 A6 DD 03 A5 DB 27 D2 LDX LDA STA LDA STA LDA JSR BEO JSR JMP $B2 $70 $B5,X $71 $BB,X #$40 $DDA6 $DB5F $DBAS $D227 channel number record number 10 record number hi bit 6 set? no enter in dirctory close channel **** •. ************************* DB62 DB64 DB66 DB68 DB6A DB6D DB6F DB71 DB73 DB76 DB79 DB7B DB7D DB80 DB82 DBB4 DB86 DBB8 DBBA DBBe DB8D DBBF DB90 DB92 DB95 DB98 DB99 DB9C DB9F OBA2 A6 B5 15 DO 20 C9 DO A9 20 20 C9 DO 20 A6 B5 DO D6 D6 A9 38 E9 4B A9 20 20 68 20 20 20 4C B2 B5 BB OC EB D4 02 05 OD Fl CF E8 D4 02 OF lE CF 82 B5 02 BB B5 00 01 00 C8 D4 F'l CF Fl C7 99 IE CF DO D5 CF LDX LDA ORA BNE JSR C~lP BNE LDA JSR JSR CMP BNE JSR LDX LDA BNE DEC DEC LDA SEC SBC PHA LDA JSR JSR PLA JSR JSR JSR JMP S82 $B5,X $BB,X $DB76 SD4E8 #S02 $DB76 #SOD SCFFI $D4EB #$02 $DB8C $CF'l E $82 $B5,X SDB88 $BB,X SB5,X #$00 not 2 CR in buffer set buffer pointer now equal to 2? no change buffer channel numberrecord number 10 decrement block number hi and block number 10 #$01 set pointer to end #SOO S04C8 $CFFI buffer pointer- to zero write zero in buffer second byte = pointer to end write in buffer write block to disk and verify change buffer $CFFI SDOC7 $D599 $CF'lE ****************************** DBA5 DBA7 DBAA DBAC DBAD DBBO DBB2 DBB5 DBB8 OBBA DBBC 82 8E 70 02 A5 83 48 BD 60 02 85 81 BD 66 02 8D 94 02 B5 EC 29 01 85 7F A6 LDX STX LDA PHA LDA STA LOA STA LOA AND STA write last block channel number record number 10 record number hi not zero? set buffer pointer $82 $0270 $83 $0260,X $81 $0266,X $0294 $ EC,X #SOl $ 7 ~~ 181 directory entry channel number save secondary address save sector number in directory set pointer in directory drive number Anatomy of the 1541 Disk Drive DBBE DBCl DBC3 DBC6 DBC7 DBC9 DBCC DBCE DBDI DBD3 DRD6 DBDB DBDA DBDC DBDE DBEI DBE3 DBE5 DBE7 DBE9 DBEB DBEC DBEE DBFO DBF2 DBF4 DBF6 DBF7 DBF8 DBFA DBFC DBFE D8FF DCOI DC03 DC06 DC07 DC09 DCOB DCOC DCOE DCOF DCll DCl3 DC14 DC16 DC18 DC19 DClB DClE AD 85 20 48 85 20 91 C8 Bl 85 68 91 20 4C 86 DC2l DC23 DC25 DC27 Bl 29 09 91 AO BD 85 AD 85 Bl 29 FO 20 C9 FO Bl 29 91 C8 Bl 85 84 AO Bl 48 88 Bl DO 85 68 85 A9 20 48 A9 91 C8 91 68 85 FE 80 93 DF $FE8S $80 $DF93 86 7D C8 29 DC LDA STA JSR PHA STA JSR LDY LDA STA LDA STA LDA AND BEQ JSR CMP BEQ LDA AND STA INY LDA STA STY LDY LDA PHA DEY LDA BNE STA PLA STA LDA JSR PHA LDA STA INY STA PLA LDY STA INY LDA STA PLA STA JSR JMP ($86),Y $C87D $DC29 erase all files 86 OF 80 86 LDA AND ORA STA ($86),Y #$OF #$80 ($86) , Y get fi Ie type isolate bits 0-3 set bit 7 for closed file F9 60 D4 00 EO ~'E 87 94 02 86 86 20 43 25 Dl 04 44 86 8F 86 86 80 71 IB 86 86 OA 80 81 67 45 E6 00 86 86 A4 71 86 81 18, directory track set increment buffer number $F9 $D460 #$00 $FEEO,X S87 $0294 $86 (S86), Y #$20 $DC21 $D125 #$04 $DC29 ($86),Y #$8F ($86) , Y ($86),Y $80 $71 #$lB ($86),Y read directory block buffer address buffer pointer file type file closed? yes check file type reI-file? yes erase bits 4,5, and 6 in file type track number sector # of the file for overwriting ( $86) , Y $DC06 $80 track # for overwriting set? set track number $81 #$67 SE645 sector number 67, , illegal track or sector' #$00 ($86),Y ($86) , Y erase track number and sector number of the substitute file $71 ($86),Y set track & sec # of the new fil, ($86) , Y $81 182 Anatomy of the 1541 Disk Drive DC29 OC2C OC2E OC30 OC32 OC33 OC35 OC37 OC38 DC39 OC3B OC40 DC41 DC43 AE AO B5 91 C8 B5 91 68 70 02 lC B5 86 BB 86 AA A9 20 68 85 4C 90 90 05 83 07 01 LDX LOY LDA STA INY LDA STA PLA TAX LDA JSR PLA STA JMP $0270 lI$lC $B5,X ($86) ,Y channel number $BB,Y ($86),Y and block number hi write buffer number lI$90 $0590 code for 'writing' write block $83 $0107 secondary address open channel for writing ****************************** OC46 A9 01 LOA lI$Ol OC48 20 E2 01 JSR $ 01 E2 OC4B 20 B6 DC JSR $DCB6 DC4E AD 4A 02 LOA $024A DC51 48 PHA OC52 OA ASL A 05 7F DCS3 ORA $7F OCS5 95 EC STA $EC,X DC57 20 9B DO JSR $D09B DC5A A6 82 LDX $82 DC5C A5 80 LDA $80 DO 05 OC5E BNE $DC65 DC60 A5 81 LOA $81 9D 44 02 DC62 STA $0244,X OC6S 68 PLA DC66 C9 04 CMP lI$04 DC68 DO 3F BNE $DCA9 DC6A A4 83 LDA $83 B9 2B 02 DC6C LDA $022B,Y DC6F 09 40 ORA #$40 DC71 99 2B 02 STA $022B,Y DC74 AD 58 02 LDA $0258 DC77 95 C7 STA $C7,X DC79 20 8E D2 JSR $D28E DC7C 10 03 BPL $DC81 DC7E 4C OF D2 JMP $D20F DC8l DC83 DC85 DC88 DC8A DC8D DC8F DC92 DC95 DC98 DC9A DC9C A6 95 AC 84 AC 84 20 20 20 A6 A9 95 82 CD 59 80 5A 81 D3 73 99 82 02 Cl 02 02 D6 DE D5 LDX STA LDY STY LDA STY JSR JSR JSR LDX LDA STA $82 $CD,X $0259 $80 $025A $81 $D6D3 $DE73 $D599 $82 lI$02 $Cl,X block number 10 in directory entry read block, layout buffer find channel and buffer for read set pointer file type save drive number read block in buffer channel number track following track? sector as end pointer file type rel-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 track for side-sector sector for side-sector transmit parameters to disk cont. read block and verify channel number pointer for writing 183 Anatomy of the 1541 Disk Drive DC9E DCAO DCA3 DCA6 A9 20 20 4C 00 C8 D4 53 E1 3E DE LDA JSR JSR JMP #$00 $D4C8 $E153 $DE3E DCA9 DCAC DCAE DCBl DCB3 DCB5 20 A6 9D A9 95 60 56 Dl 82 3E 02 88 F2 JSR LDX STA LDA STA RTS $D156 $82 $023E,X #$88 $F2,X buffer pointer to zero find next record get track and sector number ****************************** DCB6 DCB8 DCBA DCBB DCBC DCBE DCC1 DCC3 DCC5 DCC7 DCC8 DCC9 DCCB DCCE DCDO DCD2 DCD4 DCD6 DCD9 A6 B5 OA A8 A9 99 B5 09 95 OA A8 A9 99 A9 95 95 A9 9D 60 82 A7 02 99 00 AE 80 AE 02 99 00 00 B5 BB 00 44 02 LDX LDA ASL TAY LDA STA LDA ORA STA ASL TAY LDA STA LDA STA STA LDA STA RTS $82 $A7,X A lI$02 $0099,y $AE,X #$80 SAE,X A #$02 S0099,Y #$00 $B5,X $BB,X #$ 00 $0244,X ****************************** DCDA DCDD DCDF DCE2 DCE5 DCE8 DCEA DCED DCEE DCEF DCn DCn DCF4 DCF6 DCF8 DCFA DCFC 20 A9 20 20 20 A6 AD 48 OA 05 95 68 C9 FO A9 95 60 A9 01 DF DO B6 82 4A DCFD DeFF DD02 A4 83 Fl Dl D6 DC 02 7 r' EC 04 05 01 F2 89 28 02 29 3f' JSR LDA JSR JSR JSR LDX LDA PHA ASL ORA STA PLA CMP BEO LDA STA RTS get byte from buffer channel number byte in output register set flag for READ reset pointer channel number buffer number times 2 buffer pointer 10 set bit 7 buffer pointer 10 block number 10 block number hi end pointer construct a new block find free sector in BAM $FIA9 #$01 $DIDF $D6DO $DCB6 $82 $024A open channel transm i t param to disk controller reset pointer channel number file type A $7F $EC,X drive number save as flag #$04 $DCFD #$01 $F'2,X reI-file? yes set WRITE flag LDY $83 LDA S022B,Y AND #$1F 184 secondary address channel number in table erase the top two bits Anatomy of the 1541 Disk Drive DD04 DD06 DD09 DDOC DDOE DDll DD13 09 99 AD 95 20 10 4C 40 2B 5S C7 SE 03 OF DD16 DD18 DDIA DDID DD20 DD22 DD25 DD27 DD2A DD2C DD2E DD31 DD33 DD36 DD38 DD3B DD3D DD40 DD42 DD45 DD48 DD4B DD4D DD50 DD52 DD55 DD57 DD5A DD5D DD5F DD62 DD64 DD67 DD6A DD6D DD6F DD72 DD74 DD75 DD77 DD79 DD7B DD7E DD81 DD84 DDS7 DD8A A6 95 20 20 AS 8D A5 SD A6 B5 20 A9 20 A9 20 A9 20 A9 20 AD 20 A5 20 A5 20 A9 20 20 AS 20 AS 20 20 20 A9 20 A6 3S A9 F5 95 20 20 20 20 20 4C 82 CD 02 02 D2 D2 Cl DE IE 80 59 81 5A 82 CD D3 00 E9 00 8D Fl 02 02 D6 DE DD 11 8D 00 8D 58 8D SO 8D 81 SD 10 E9 3E SO 8D 81 SD 6C 99 02 CS 82 00 C7 Cl E2 19 SE 99 F4 98 DD DD 02 DO DD DD DE DE DO DD DE D5 D4 E2 DE DE D5 EE DC ORA STA LDA STA JSR BPL JMP #$40 $022B,Y $0258 $C7,X $D28E $DD16 $D20F set bit 6 READ and WRITE flag record length in table find buffer found? 70, 'no channel' LDX STA JSR JSR LDA STA LDA STA LDX LDA JSR LDA JSR LDA JSR LDA JSR LDA JSR LDA JSR LDA JSR LDA JSR LDA JSR JSR LDA JSR LDA JSR JSR JSR LDA JSR LDX SEC LDA SBC STA JSR JSR JSR JSR JSR JMP $S2 $CD,X $DECI $FllE $80 $0259 $81 $025A $82 $CD,X $D6D3 #$00 $DEE9 #$00 $DDSD #$11 $DD8D #$00 $DDBD $0258 $DD8D $SO $DD8D $81 $DD8D #$10 $DEE9 SDE3E SSO SDD8D S81 SDDSD SDE6C $D599 #S02 $D4C8 SS2 channel number buffer number for side-sector erase buffer find free block in BAM track for side-sector sector for side-sector channel number buffer number transmit param to disk controller buffer pointer to zero 17 as end pointer in buffer zero as side-sector number in bt'ffer record length in buffer track number of this block in buffer sector number in buffer 16 buffer pointer to 16 get track and sector number track # of the first data block in buffer sector # of the first data block in buffer write block to disk and check buffer pointer to 2 channel number #$00 $C7,X SCl,X $E2E2 $DE19 SDESE SD599 SEEF4 $DC98 record length pointer for writing erase buffer write link bytes in buffer write block to disk and check write BArI and done 185 Anatomy of the 1541 Disk Drive ****************************** DDBD DDBE DD90 DD92 4B A6 82 B5 CD 4C FD CF PHA LDX $82 LDA $CD,X JMP SO'FD write byte in side-sector block save byte channel number buffer # of the side-sector write byte in buffer ****************************** DD95 90 06 Bec $DD9D DD9? A6 82 LOX $82 DD99 15 EC ORA $EC,X BNE $DDA3 DD9B DO 06 DD9D A6 82 LDX S82 49 FF EOR #$FF DD9F DDAI 35 EC AND SEC,X DDA3 95 EC STA $EC,X DDA5 60 RTS DDA6 A6 82 LDX $82 DDA8 35 EC AND $EC,X DDAA RTS 60 manipulate flags ****************************** $DF93 check command code for writing get buffer number $025B,X #$FO #$90 isolate command code code for writing? DDAB DDAE DDAF DDB2 DDB4 DDB6 20 AA BD 29 C9 60 93 OF 5B 02 FO 90 JSR TAX LDA AND CMP RTS channel number set flag channel number erase flag channel number test flag ****************************** DDB? DDB9 DDBB DDBE DDCO DDC2 DDC4 DOCS DDC7 DDC9 A2 86 BD C9 DO 00 71 2B 02 FF 08 A6 71 88 EO 10 90 FO 60 LOX STX LOA CMP BNE LOX INX CPX Bce RTS #$00 571 S022R,X #$FF $ODCA $71 DDCA DDce DDCE DDCF DDD2 DDD4 DDD6 DDD9 DDDR DDDD DDDF DDEl DDE4 DDE6 86 29 A8 B9 29 85 AE B5 29 C5 DO 89 05 DO STX AND TAY LDA AND STA LDX LDA AND CMP BNE LDA CMP BNE $71 #$3F 71 3F EC 00 01 70 53 02 E2 01 70 81 60 02 DB DA counter for secondary address get channel number from table file open? increment counter smaller than l6? #$10 $DDB9 isolate channel number $OOEC,Y #$ 01 S70 $0253 $E2,x #$01 $70 $DDC2 $0260,Y SD8,X $DDC2 186 isolate drive number isolate drive number same drive? no sector number in directory same as file? nO Anatomy of the 1541 Disk Drive DDE8 DDEB ODED DDEF DDFO B9 66 02 D5 DD DO D3 18 60 LDA $0266,Y CMP $DD,X BNE $DDC2 CLC RTS pointer same? no *.**************************** DDFI JSR $D~'9E 20 9E DF DDF4 50 06 BVC $DDFC 20 5E DE JSR $DE5E DDF6 20 99 D5 JSR $D599 DDF9 DDFC 60 RTS write a block of a reI-file get buffer number no reI-file? write block and verify ****************************** 20 2B DE DDFD JSR $DE2B DEOO AS 80 LDA $80 91 94 STA (S94),Y DE02 DE04 INY C8 AS 81 LDA $81 DE05 91 94 STA ($94),Y DE07 4C 05 El JMP $ElO5 DE09 write bytes for following track set buffer pointer track number in buffer ****************************** DEOC 20 2B DE JSR $DE2B Bl 94 DEOF LDA ($94),Y STA $80 DEll 85 80 DEl3 C8 INY DE14 Bl 94 LDA ($94),Y 85 81 DE16 STA $81 DE18 RTS get following track and sector set buffer pointer following track number ****************************** DE19 20 2B DE JSR SDE2B DEIC A9 00 LDA #$00 DElE 91 94 STA ($94),Y DE20 C8 INY DE21 A6 82 LDX $82 DE23 B5 Cl LDA $Cl,X DE25 AA TAX DE26 CA DEX DE27 TXA 8A STA ($94),Y 91 94 DE28 DE2A 60 RTS following track for last block set buffer pointer zero as track number ****************************** DE2B 20 93 DF JSR $DF93 OA ASL A DE2E TAX DE2F AA DE30 LDA $9A,X B5 9A DE32 85 95 STA $95 A9 00 LDA #$00 DE34 85"94 STA $94 DE36 AO 00 LDY #$00 DE38 DE3A 60 RTS 187 sector number in buffer set reI-flag and get sector number channel number pointer in block minus I as pointer in block buffer pointer to zero get buffer number times 2 buffer pointer hi buffer pointer 10 * Anatomy of the 1541 Disk Drive ****************************** JSR $OOEB 20 EB DO OE3B JSR $OF93 OE3E 20 93 OF 85 F9 STA $F9 OE41 OE43 OA ASL A OE44 A8 TAY B9 06 00 OE45 LOA $0006.Y 85 80 STA $80 OE48 OE4A B9 07 00 LOA $0007.Y STA $81 OE40 85 81 RTS OE4F 60 ****************************** A9 90 LOA #$90 OE50 8D 4D 02 STA $024D DE52 BNE $OE7F DO 28 DE55 80 4D 02 21 90 40 02 26 get track and sector # from disk controlle command code for writing command code for reading DE57 OE59 DE5C DE5E OE60 OE63 A9 8D DO A9 80 DO OE65 DE67 DE6A A9 80 80 4D 02 DO IF LOA #$80 STA $024D BNE $OE8B command code for reading DE6C DE6E DE71 A9 90 80 4D 02 DO 02 LDA #$90 STA $0240 BNE $OE75 command code for writing DE73 DE75 OE78 DE7A DE7C DE7D OE7F DEB2 DEBS OEB6 DEB8 DE8B DEBE DE91 DE92 A9 80 8D 4D 02 A6 82 B5 CD LOA STA LOX LOA TAX BPL JSR JSR TAX LOA STA JSR JSR TAX JMP #$80 $0240 $82 $CO.X command code for reading $OE92 $0600 $OF93 buffer associated? generate header for disk cont. get buffer number $7F $025B.X $E1l5 $OF93 drive number $D506 wri te block AA 10 13 20 00 06 20 93 OF AA AS 90 20 20 7F 5B 02 15 E1 93 OF AA 4C 06 05 LDA STA BNE LOA STA BNE get track and sector get channel number get buffer number save times 2 #$80 $024D $OE7/:O' #$90 $024D $OE8B command code for writing channel number side-sector buffer number ****************************** LOA #$00 OE95 A9 00 20 C8 04 JSR $04C8 OE97 OE9A JSR $D137 20 37 01 85·80 STA $80 DE90 20 37 01 JSR $0137 OE9F OEA2 85 81 STA $81 188 buffer number get buffer number get following track & sector fron buffer buffer pointer to zero get byte save as track get byte as sector Anatomy of the 1541 Disk Drive DEM 60 RTS ****************************** 4B PHA DEA5 DEA6 LDA #$00 A9 00 85 6F DEAB STA $6F DEM 85 71 STA $71 DEAC B9 EO FE LDA $FEEO,y DEAF B5 70 STA $70 DFBI BD EO FE LDA $FEEO,X STA $72 DEB4 85 72 PLA DEB6 68 DEB7 AB TAY 88 DEBB DEY LDA ($6F),Y DEB9 Bl 6F DEBB 91 71 STA ($71l,Y DEBD 88 DEY DEBE 10 F9 BPL $DEB9 RTS DECO 60 copy buffer contents ****************************** erase buffer Y buffer number get hi-address DECI DEC2 DEC5 DEC7 DEC9 DECB DECC DECE DEC~' DEDI A8 89 85 A9 85 AS 91 C8 DO 60 EO FE 70 00 6F 6F FB TAY LDA STA LDA STA TAY STA INY BNE RTS $FEEO,y $70 #$00 $6F ($6F), Y A9 20 AO Bl 60 00 DC DE 02 94 LDA JSR LDY LDA RTS #$00 SDEDC #$02 (S94),Y ****************************** DEDC DEDE DEEO DEE2 DEE3 DEE6 DEE8 85 94 A6 82 B5 CD AA BD EO FE 85 95 60 STA LDX LDA TAX LDA STA RTS 48 20 DC DE 48 SA OA AA copy contents of buffer Y to buffer X lo-address erase buffer get side-sector number buffer pointer to zero byte 2 contains the side-sector # $94 $82 $CD,X set buffer ptr to side-sector pointer 10 channel number buffer number $FEEO,X S95 buffer address hi set ******************~*********** DEE9 DEEA DEED DEEE DEEF DEFO buffer address X, hi $DECC ****************************** DED2 DED4 DED7 DED9 DEDB buffer address Y, hi PHA JSR $DEDC PHA TXA ASL A TAX buffer pointer for side-sector pointer in side-sector set buffer pointer buffer number times 2 189 Anatomy of the 1541 oisk Orive OEFI OEF2 OEF4 OEF5 OEF7 68 95 9A 68 95 99 60 PLA STA $9A,X PLA STA $99,X RTS buffer pointer hi buffer pointer 10 ****************************** 20 66 OF JSR $OF66 OEF8 8MI $OFOB 30 OE OEFB BVC $DF12 50 13 OEFO OEFF A6 82 LOX $82 LOA $CO,X OFOI B5 CO 20 18 OF JSR $DFIB OF03 20 66 OF JSR $DF66 OF06 10 07 BPL $DF12 0F'09 OFOB 20 CB El JSR $EICB BIT $FECE OFOE 2C CE FE OFll 60 RTS OF'12 A5 06 LOA $06 JSR $OEE9 OF14 20 E9 OE BIT $FECD OF17 2C CO OE RTS OFIA 60 get side-sector and buffer ptr is side-sector in buffer no ok channel number buffer number read side-sector and check if in buffer yes? get last side-sector set V bit ****************************** STA $F9 OFIB 85 F9 A9 80 OFIO LDA *$80 OFIF BNE $OF25 00 04 read side-sector buffer number command code for reading ****************************** write side-sector buffer number command code for writing DF21 DF23 DF25 OF26 OF28 DF2A Or'2C OF2D DF2F DF32 OF34 DF36 DF37 DF39 DF3B OF30 OF40 OF42 85 A9 48 B5 29 85 68 05 8D F9 90 EC 01 7F 7F 40 02 Bl 94 85 80 C8 Bl 94 85 81 A5 F9 20 D3 D6 A6 F9 4C 93 05 STA LOA PHA LOA ANO STA PLA ORA STA LOA STA INY LOA STA LOA JSR LOX JMP $F9 #$90 $EC,X #$01 $7F side-sector end pointer set pointer in side-sector erase V bit isolate drive number $7F $0240 ($94),Y $80 command code plus drive number save track number ($94), Y $81 $F9 $0603 $F9 $0593 sector number buffer number transmit param to disk controller buffer number tranmit cmd to disk controller ****************************** 01"45 A6 82 LOX $82 Df'47 B5 CD LOA $CD,X 4C E8 04 JMP $D4EB OF49 set buffer pointer in side-sector channel number buffer number set buffer pointer ****************************** calculate block # of a reI-file 120 block ptrs per side-sector DF4C A9 78 LDA #$78 190 Anatomy of the 1541 Disk Drive OF4E OFSl DFS2 DFS4 OFS6 OFS7 DF5A DF5C OF50 DF5F DF61 DF63 DF65 20 CA 10 AS 4A 20 AS 18 6S 8S 90 E6 60 SC DF F8 72 SC DF 73 70 70 02 71 JSR DEX BPL LDA LSI< JSR LDA CLC AOC STA BCC INC RTS add to $70/$71 side-sector number next side-sector? pointer value in last block divided by 2 add to previous sum number of the side-sector block $DFSC $DNC $72 A $OFSC $73 $70 $70 $DF65 $71 add ****************************** OF66 DF69 DF6B DF6D DF6F DF71 DF73 OF76 OF77 DF7A 20 D2 DE CS OS DO OE A4 D6 Bl 94 FO 04 2C CO FE 60 2C CF FE 60 JSR CMP BNE LOY LDA BEQ BIT I write pointer? no change buffer channel number change buffer change buffer set buffer pointer channel number end pointer buffer pointer to ze.ro byte from buffer not zero? Anatomy of the 1541 Disk Drive E1C7 60 RTS E1C8 E1C9 E1CA 98 38 60 TYA SEC RTS ****************************** E1CB E1CE E1DO E1D2 EID4 EID6 20 85 A9 85 D2 DE D5 0-4 94 AD OA DO 04 JSR STA LDA STA LDY BNE EID8 EID9 EIDA EIDC EIDE EIEO E1El E1E2 E1E4 E1E6 E1E8 ElEA E1EC E1EF E1Fl EIF3 E1F5 E1F7 E1F8 EIFA E1FB EIFC E1FE E1FF 88 88 30 Bl FO 98 4A C5 FO 85 A6 B5 20 AO 84 Bl DO C8 Bl 1'18 88 84 98 4C DEY DEY BMI LDA BEO TYA LSR CMP BEO STA LDX LDA JSR LDY STY LDA BNE INY LDA TAY DEY STY TYA JMP E202 E204 A9 67 20 45 E6 26 94 F8 D5 09 D5 82 CD IB DF 00 94 94 OB 94 D6 E9 DE $DED2 $D5 #$04 $94 *SOA $EIDC pointer to side-sectors $E202 (S94),Y $EID8 20 AD 85 20 90 1'19 20 divide by 2 number of the actual block? yes else save all numbers channel number buffer number read block ($94),Y sector number $D6 save end pointer $DEE9 set buffer pointer #$67 JSR $E645 Cl JSR LDA STA JSR BCC LDA JSR $C2B3 $0201 $83 SDOEB $E2l9 #$70 $C1C8 E2l9 E21B E21E E22l 1'19 AD 20 9D DD 20 25 Dl FO 05 LDA JSR JSR REO #$AO $DD9D $D125 $E228 B3 01 83 EB 05 70 C8 C2 02 DO track # of the previous block A $D5 SEIEF $D5 S82 $CD,X $DFIB #$00 $94 ($94) ,Y $E202 = buffer pointer track number another block? = end pointer 67, , illegal track or sector' ****************************** E207 E20A E20D E20F E2l2 E2l4 E2l6 get last side-sector get number of the side-sector save P-command, 'Record' verify lines secondary address find channel number found? 70, 'no block' erase bits 6 & 7 verify if 'REL'-file yes 191 Anatomy of the 1541 Disk Drive E223 E225 A9 64 20 C8 Cl LDA #$64 JSR $CIC8 E228 E22A E22C E22E E231 E233 E236 E238 E23A E23C E23E E241 E243 E244 E246 E248 E24A E24C E24E E251 E253 E255 E258 E25B E25D E25F E262 B5 29 85 AD 95 AD 95 A6 A9 95 AD FO 38 E9 FO D5 90 A9 8D A9 85 20 20 50 A9 20 4C DD El LDA AND STA LDA STA LDA STA LDA LDA STA LDA BEO SEC SBC BEO CMP BCC LDA STA LDA STA JSR JSR BVC LDA JSR JMP #$01 $E253 $C7,X $E253 #$51 $02liC #$00 $D4 $CEOE $DEF8 $E265 #$80 $DD97 $E15E E265 E268 E26A E26D E26F E272 20 75 E2 A9 80 20 A6 DD FO 03 4C 5E El 4C 94 Cl JSR LDA JSR BEO JMP JMP $E275 #$80 $DDM $E272 $E15E $C194 test bit 7 not set 50, 'record not present' done E275 E278 E27A E270 E27F E281 E282 E284 E286 20 A5 20 M B5 38 E5 BO 4C JSR LDA JSR LDX LDA SEC SBC BCS JMP $E29C $D7 $D4C8 $82 $C7,X pointer in reI-file set buffer pointer channel number record length $D4 $E289 $E202 minus position positive? 67, , illegal track or sector' E289 E28A E28C E28E E290 E291 E294 18 65 90 69 38 20 4C $D7 $E291 #$01 add pointer in data blocK no overflow plus 2 $E009 $E138 set pointer get byte froIl' buffer EC 01 7F 02 02 B5 03 02 BB B2 89 F2 04 02 10 01 08 C7 07 51 6C 00 D4 OE F8 08 80 97 5E 02 CE DE 9C E2 07 C8 D4 82 C7 D4 03 02 E2 07 03 01 09 EO 38 E1 CLC ADC BCC ADC SEC JSR JMP 64, , file type mismatch' $EC,X #$01 $7F $0202 $B5,X $0203 $BB,X $82 #$89 $F2,X $0204 $E253 drive number record number 10 record number hi channel number READ and WRITE flag byte-pointer zero? compare wi th record length 51, 'overflow in record' calculate pointer in reI-file and read appropriate side-sector does blocK exist? set bit 7 and 50, , record not present' 198 Anatomy of the 1541 Disk Drive LDA #$51 JSR $CIC8 E297 E299 A9 51 20 C8 Cl E29C E29E E2AO E2A2 E2M E2A7 E2A9 A5 85 A5 85 20 DO 60 94 89 95 8A DO E2 01 LDA STA LDA STA JSR BNE RTS $94 $89 $95 $8A $E2DO SE2AA E2M E2AD E2BO E2B2 E2B4 E2B7 E2B9 E2BC E2BF E2C2 E2C4 E2C6 E2C8 E2C9 E2CB E2CD 20 20 A5 FO 20 DO 20 4C 20 AO Bl 85 C8 Bl 85 4C Fl OC 80 OE D3 06 IE DA DA 00 89 80 JSR JSR LDA BEQ JSR BNE JSR JMP JSR LOY LOA STA INY LOA STA JMP $DDFI $DEOC $80 $E2C2 $E2D3 $E2BF $CFIE $D20A $D20A #$00 ($89), Y $80 E2DO E2D3 E2D5 E2D7 B2D9 E2DB E2DC B2DD E20F E2El 20 AO Bl C5 FO 60 C8 Bl C5 60 3E DE 00 89 80 01 JSR LOY LOA CMP BEQ RTS INY LDA $OE3E #$00 ($89),Y $80 $E2DC DD DE E2 CF D2 02 89 81 AF DO 89 81 C~lP 51, 'overflow in record' buffer pointer 10 buffer pointer hi compare track and sector not equal? ($89),Y $81 $DOAF ($89) ,Y $81 20 AO A9 91 C8 DO 20 95 A8 A9 91 20 90 DO track and sector of the next block read block track number compare sector number compare RTS ****************************** E2E2 E2E5 E2E7 E2E9 E2EB E2EC E2EE E2Fl E2F3 E2F4 E2f'6 E2F8 E2FB E2FD track no block following? compare track and sector number not equal? change buffer 2B DE 02 00 94 FB 04 E3 Cl FF 94 04 E3 F4 04 JSR LDY LDA STA INY BNE JSR STA TAY LDA STA JSR BCC BNE $DE2B #$02 #$00 ($94) ,Y $E2E9 $E304 $Cl,X subdivide records in data block set buffer pointer erase buffer set pointer to next record #$FF ($94) ,Y $E304 $ E2F1 $E303 199 SFF as 1st character in record set pointer to next record done in this block? block full? Anatomy of the 1541 Disk Drive E2r'F E301 E303 A9 00 95 Cl 60 LDA #SOO STA $Cl,X RTS write pointer to zero ****************************** E304 A6 82 LDX $82 E306 B5 Cl LDA $Cl,X 38 E308 SEC FO OD E309 BEO $E318 E30B 18 CLC E30C 75 C7 ADC $C7,X E30E 90 OB BCC $E31B BNE $E318 E310 DO 06 E312 A9 02 LDA #$02 E314 2C CC FE BIT $F'ECC 60 E317 RTS E318 E31A E31B 69 01 38 60 ADC #$01 SEC RTS set pointer to next record channel number write pointer equal zero? add record length smaller than 256? equal 256? add two ****************************** E31C 20 D3 Dl JSR SDID3 JSR SEICB E31F 20 CB El E322 JSR $E29C 20 9C E2 E325 20 7B CF JSR $CF7B E328 AS D6 LDA SD6 E32A 85 87 STA $87 E32C A5 D5 LDA $D5 E32E 85 86 STA $86 E330 A9 00 LDA #$00 E332 85 88 STA $88 E334 A9 00 LDA #$00 E336 STA $D4 85 D4 E338 20 OE CE JSR $CEOE E33B 20 40 EF JSR $EF4D E33E A4 82 LDY $82 E340 B6 C7 LDX $C7,Y E342 CA DEX E343 8A TXA E344 18 CLC E345 65 07 ADC $07 E347 90 DC FlCC $E355 E349 E6 06 INC SD6 E34B INC $06 E6 06 DO 06 BNE $E355 E34D E34F E6 05 INC $D5 E351 A9 10 LDA #$10 E353 85 06 STA #06 E355 AS 87 LOA $87 E357 18 CLC E358 69 02 ADC #$02 F,35A 20 E9 DE JSR $DEE9 E35D AS D5 LOA $D5 E35F C9 06 CMP #$06 200 expand side-sector get drive number get last side-sector side-sector number calculate side-sector no. and pt number of free blocks channel number record length plus pointer in data hlock increment ptr to end by 2 increment side-sector number set pointer to 16 set buffer ptr for side-sector side-sector number Anatomy of the 1541 Disk Drive E361 E363 E365 E368 E36A E368 E36D E36F E371 E372 E374 E376 E378 E37A E37C E37E E380 E381 E384 E386 E388 E38A E388 E38D E38F E392 E394 E396 E399 E39B E390 E39F E3A2 E3A3 E3A5 E3A7 E3A9 E3AC E3AF E38l E383 E3B6 E389 E3BC E3BF E3C2 E3C5 90 A9 20 A5 38 E5 80 E9 18 85 A5 E5 85 A2 86 86 20 A5 DO A6 CA DO E6 CD 90 DO AD C5 90 A9 20 18 69 A6 95 20 20 A5 00 20 20 20 20 20 20 4C 51 DF 71 07 70 E3C8 E3CB E3CE E30l E304 E3D7 E3DA 20 20 20 20 20 20 A5 IE DO E2 19 5E OC 80 05 52 C8 Cl 06 87 03 OF 72 D5 86 73 00 70 71 AA 02 88 73 02 09 CD 72 02 70 C6 01 F6 D4 01 82 Cl IE FD 88 15 5E IE DCi' IE FD E2 D4 Fl DO DE CF D6 Fl DD E2 E3 CF D6 E2 DE DE DE 8CC LOA JSR LOA SEC S8C 8CS SBC CLC STA LDA SBC STA LDX STX STX TAX JSR LDA BNE LDX DEX BNE INC CMP BCC BNE LDA CMP 8CC LDA JSR CLC ADC LDX STA JSR JSR LDA BNE JSR JSR JSR JSR JSR JSR JMP $E368 *$52 SCIC8 $D6 smaller than 6? S87 $E372 HOF minus last end pointer JSR JSR JSR JSR JSR JSR LOA $CF1E $D6DO $E2E2 SDE19 $DE5E $OEOC $80 52, ' file too large' end pointer minus 16 $72 SD5 $86 S73 #SOO S70 $71 side-sector number minus last side-sector number save erase sum for calculation $OF5I S71 $E38F $70 calculate block # of reI-file $E38F $88 S0273 $E39D SE363 S0272 $70 $E363 #$01 $D4F6 block number of reI-file greater than free blocks on disk? 52, 'file too large' 52, 'file too large' get byte from buffer #$01 582 $Cl,X $FllE $ODFD $88 $E3C8 $DE5E $CFlE $06DO $FllE $DDFD $E2E2 $E3D4 plus 1 as write pointer find free block in BAM track and sector in buffer only one block needed? write block change buffer transmit param to disk controller find free block in BAM track and sector in buffer erase buffer change huffer transmit par-am to disk controller erase buffer zero byte and end ptr in buffer write block get track and sector track 201 Anatomy of the 1541 Disk Drive E3DC E3DD E3DF E3EO E3E3 E3E5 E3E6 E3E8 E3E9 E3EC E3ED E3EF E3F2 E3F4 E3F7 E3F9 E3FA E3FD EWE E401 E402 E404 E405 E407 E409 E40B E40D E40F E412 E414 E416 E418 E413 E41C E41E E421 E423 E424 E426 E427 E428 E429 E42B E42D E430 E433 E436 E439 E43C E43F E441 48 48 20 A5 48 A5 48 20 AA DO 20 A9 20 E6 68 20 68 20 68 85 68 85 FO A5 C5 00 20 C5 90 FO 20 48 A9 20 A9 A8 91 C8 68 38 E9 91 20 20 20 20 20 20 70 4C E444 E446 E449 A9 BO 20 97 DO A9 50 A4 81 3E DE 81 80 45 OF OA 4E E4 10 E9 OE 86 80 DD 80 00 81 80 OF 86 05 A7 45 DF D6 AO BO 45 OF 00 DC DE 00 94 01 94 6C 99 F4 OE IE F8 03 75 DE D5 EE CE CF OE E2 PHA LDA PHA JSR LOA PHA LOA PHA JSR TAX BNE JSR LOA JSR INC PLA JSR PLA JSR PLA STA PLA STA BEO LDA CMP BNE JSR CMP BCC BEO JSR PHA LDA JSR LDA TAY STA INY PLA SEC SEC STA JSR JSR JSR JSR JSR JSR BVS JMP $DE3E $81 and sector save get track and sector from disk controller $80 save track and sector $DF45 set buffer ptr for side-sector $E3F9 $E44E #$10 $OEE9 $86 pointer not zero? write side-sector $0080 track in side sector $008D sector in side-sector $81 sector $80 $E418 $86 $D5 $E3B6 $0F45 $06 $E336 $E3C8 $DF45 and get 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 #$00 $DEDC #$00 buffer pointer to zero ($94), Y zero as track number S81 buffer pointer to 16 increment side-sector number end pointer #$01 ($94), Y $DE6C $0599 $EEF4 $CEOE $CFIE $OEFB $E444 $E275 LOA i$80 JSR $0097 LDA #$50 minus one as sector write block and verify update BAM update pointer for reI-file change buffer right side-sector? no set bit 7 202 Anatomy of the 1541 Disk Drive E44B 20 C8 Cl JSR $CIC8 50, 'record not present' ****************************** E44E E451 E454 E457 E45A E45B E45E E460 E462 E463 E464 E465 E467 E46A E46C E46F E471 E473 E474 E476 E479 E47A E47B E470 E47F E480 E482 E484 E485 E486 E488 E48A E48C E48E E490 E491 E493 E495 E497 E499 E49A E49C E49D E49F E4A1 E4A3 E4A6 E4A9 E4AC E4AE E4BO 20 20 20 20 48 20 A6 B5 A8 68 AA A9 20 A9 20 AO Bl 48 A9 20 68 18 69 91 OA 69 85 A8 38 E9 85 AS 85 91 C8 AS 85 91 AO 98 91 C8 A9 91 A9 20 20 20 A6 B5 48 IE IE Fl 93 Fl CF DD DF Cl DE 82 CO 10 A5 OE 00 DC DE 02 94 00 C8 04 01 94 04 89 02 SA 80 87 94 81 88 94 00 94 II 94 10 C8 D4 50 DE 99 05 82 CD JSR JSR JSR JSR PHA JSR LDX LOA TAY PLA TAX LOA JSR LOA JSR LDY LOA PHA LDA JSR PLA CLC AOC STA ASL ADC STA TAY SEC SBC STA LOA STA STA INY LOA STA STA LOY TYA STA INY LDA STA LDA JSR JSR JSR LDX LDA PHA $FllE $CFIE $DDFI $DF93 write side-sector and allocate new one find free block in BAM change buffer write block get buffer number $DECl $82 $CO,X erase buffer channel number buffer number *$10 $OEA5 *$00 $OEDC *$02 ($94) , Y 16 bytes of the side-sector copy in buffer #$00 $04C8 buffer ptr to 0, old side-sector side-sector number buffer ptr to 0, new side-sector *$01 ($94) , Y A #$04 $89 increment side-sector numbE'r and in buffer times 2 plus 4 #$02 $8A $80 $87 ($94) , Y minus 2 same pointer to old side-sector track $81 $88 ($94) , Y *$00 sector ($94) , Y zero in buffer #$11 ($94) , Y #$10 $D4C8 $DE50 $D599 $82 $CD,X number of bytes in block 16 buffer pointer to 16 write block and verify channel number buffer number of the side-~'ector 203 in buffer in buffer 17 Anatomy of the 1541 DiskOrive E4Bl E4B4 E4B6 E4B8 E4B9 E4BC E4BE E4CO E4C3 E4CS E4C7 E4C9 E4CA E4CC E4CE 20 A6 95 68 AE 95 A9 20 AO AS 91 C8 AS 91 4C E4Dl E404 E406 E409 E40B EFDE E4EO E4E2 E4E4 E4E6 E4E8 E4E9 E4EB E4ED E4FO E4F3 E4f'5 E4F7 E4F9 20 A6 20 A9 20 C6 C6 A4 AS 91 C8 AS 91 20 20 A4 CO SO 4C 9E OF 82 CO 57 02 A7 00 C8 04 00 80 94 81 94 OE E4 93 OF 82 IB OF 00 C8 04 8A 8A 89 87 94 88 94 5E DE 99 D5 8A 03 08 IE CF JSR LOX STA PLA LOX STA LOA JSR LOY LOA STA INY LOA STA JMP JSR LOX JSR LDA JSR OEC DEC LOY LOA STA INY LOA STA JSR JSR LOY Cpy BCS JMP $OF9E $82 $CO,X get buffer number channel number write in table $0257 $A7,X i$OO $04C8 #$00 $80 ($94), Y channel number + 7 in table $81 ($94), Y $E40E sector in buffer $OF93 $82 $OFIB #$00 $04C8 $8A $8A $89 $87 ($94), y get buffer number channel number read block $88 ($94), Y $OE5E $0599 $8A #$03 $E401 $CFIE sector number in buffer write block and verify counter for side-sector blocks ****************************** E4FC 00 E4FO AO 4F CB E500 20 21 22 23 24 27 E506 02 45 41 44 E50A 89 E50B 52 E50C 83 E500 20 54 4F 4F 20 AC 4A 52 47 E517 50 E518 8B 06 E51A 20 50 52 45 53 45 4E 04 E522 51 E523 CF 56 45 52 46 4C 4F 57 20 E52E 8B E52F 25 28 E531 8A 89 E533 26 E534 8A 204 buffer pointer to zero track in buffer buffer pointer to zero counter for side-sector blocks track number in buffer greater than or equal to 3? change buffer table of error messages 00 , oK' error numbers of ' read error' 'Read' pointer to (error52 pointer to 'file' , too largE' C5 50 pointer to 'record , and 'not , presenT' 51 'Overflow in' pointer to 'record' error numbers of ' write error' pointer to 'write' and 'error 26 pointer to 'write' , , Anatomy of the 1541 Disk Drive E535 E540 E541 E542 E545 E546 E54B E551 E552 E553 E556 E557 E558 E55F E560 E561 E566 E567 E568 E570 E572 E57A E582 E589 E58A E58D E590 E593 E594 E594 E59F E5AO E5AA E5AB E5AE E5AF E5BO E5Bl E5B6 E587 E5BF E5C4 E5C5 E5CA E5CB E5D5 E5D6 E5DB E5DC E5El E5E2 E5E6 E6E7 E5EB E5EC 20 29 88 20 85 30 D3 89 60 8A 63 83 20 64 83 20 85 65 CE 66 C9 54 20 61 83 39 83 01 83 53 70 CE 71 C4 89 72 88 20 73 C3 56 74 C4 06 20 09 C5 OA D7 03 C6 04 CF 05 CD , 50 52 4F 54 45 43 54 20 4F CE protect oN' 29 pointer to 'disk' , id' 49 85 , mismatch' pointer to error numbers for 'syntax error' 31 32 33 34 'Syntax' 59 4E 54 41 58 , error' pointer to 60 ptrs to 'write', 'file' & 'open' 03 84 63 pointer to 'file' , existS' 45 58 49 53 54 D3 64 pointer to 'file' , type' 54 59 50 45 pointer to 'mismatch' 65 'No block' 4F 20 42 4C 4F 43 CB 'illegal track or sector' 67 , 'Illegal 4C 4C 45 47 41 4C 20 'track or' 52 41 43 4B 20 4F 52 'sectoR' 53 45 43 54 4F D2 61 pointer to I fi Ie I , 1 not' & 'open' 06 84 error nos. for 'file not found' 62 ptrs to 'file', 'not' & 'found' 06 87 01 pointer to 'f i 1e' 20 53 43 52 41 54 43 48 45 C4 ' s scratcheD' 70 4F 20 43 48 41 4E 4E 45 CC 'No channeL' 71 'Dirt 49 52 pointer to 'error' 72 pointer to 'disk' , fulL' 46 55 4C CC 73 , 'Cbm dos 42 4D 20 44 4F 53 20 32 2E 36 20 31 35 34 Bl 'v2.6 1541' 74 'Drive' 42 49 56 45 pointer to 'not' , readY' 52 45 41 44 D9 52 52 4F D2 'ErroR' 52 49 54 C5 '''lritE' 49 4C C5 'FilE' 50 45 CE 'OpeN' 49 53 4D 41 54 43 C8 'MismatcH' 205 Anatomy of the 1541 Disk Drive E5F4 E5F5 E5F8 E5F9 E5FE E5FF E603 E604 06 CE 07 C6 08 C4 OB D2 4F D4 'NoT' 4F 55 4E C4 'FounD' 49 53 CB ' DisK' 45 43 4F 52 C4 'RecorD' ****************************** E60A 48 PHA E60B 86 F9 STX $F9 E600 8A TXA E60E OA ASL A E60F AA TAX E610 B5 06 LOA $06,X E612 85 80 STA $80 E614 B5 07 LOA $07,X E616 85 81 STA $81 E618 68 PLA E619 29 OF ANO #$OF E61B FO 08 BEO $E625 E610 C9 OF CMP jI$OF E61F 00 06 BNE $E627 E621 A9 74 LOA #$74 E623 00 08 BNE $E620 E625 A9 06 LOA #$06 E627 09 20 ORA #$20 E629 AA TAX E62A CA DEX E62B CA OEX E62C 8A TXA E620 48 PHA E62E AD 2A 02 LOA $022A E631 C9 00 CMP #$00 E633 00 OF BNE $E644 E635 A9 FF LOA #$FF E637 80 2A 02 STA $022A E63A 68 PLA E63B 20 C7 E6 JSR $E6C7 E63E 20 42 00 JSR $0042 £641 4C 48 E6 JMP $£648 E644 E645 E648 £64B E64D E650 E653 E656 E658 E65A £65C £65D 68 20 20 A9 80 20 20 A9 85 A2 9A A5 C7 BO 00 F9 2C OA 00 A3 45 84 E6 C1 02 C1 04 PLA JSR JSR LOA STA JSR JSR LOA STA LOX TXS LOA $£6C7 $ClBD #$00 $02F9 $C12C $04DA #$00 $A3 #$45 prepare error number and messagl save error code drive number times 2 as pointer get track and sector number get error code back isolate bits 0-3 zero, then 24, , read error' 15? 74, 'drive not ready' 6 add $20 subtract two save error number number of the disk command OPEN or VALIDATE? no get error number back generate error message load BAM set error message set error message erase input buffer erase error flag turn LED off close channels 17 and 18 input buffer pointer to zero initialize stack pointer secondary address S84 206 Anatomy of the 1541 Disk Drive E65F E661 E663 E665 E667 E668 E66A E66C E66E E670 E672 E675 E677 E679 E67B E67D 29 85 C9 FO 78 A5 DO A5 DO A6 BD C9 FO 29 85 4C OF 83 OF 31 79 lC 7A 10 83 2B 02 FF IF OF 82 8E E6 AND STA CMP BEQ SEI LDA BNE LDA BNE LDX LDA CMP BEO AND STA JMP #$OF $83 #$OF $E698 IS? yes, command channel $79 $E688 $7A $E680 $83 S022B,X #$FF $E698 #$OF $82 $E68E ****************************** E680 E683 E686 20 EB DO 20 4E EA DO 06 JSR SDOEB JSR $EA4E BNE $E68E ****************************** E688 E68B E68E E691 E693 E695 E698 20 20 20 C9 BO 20 4C 07 4E 25 04 03 27 E7 Dl EA Dl D2 EB JSR JSR JSR CMP BCS JSR JMP $DI07 $EA4E $D125 #S04 $E698 $D227 $EBE7 ****************************** E69B E69C E69E E69F F6Al E6A3 E6A4 A6A6 E6A7 E6AA AA A9 00 F8 EO 00 FO 07 18 69 01 CA 4C 9F F,6 D8 TAX LDA SED CPX BEQ CLC ADC DEX JMP CLD AA 4A 4A 4A 4A 20 SA 29 09 91 C8 B4 E6 OF 30 AS TAX LSR LSR LSR LSR JSR TXA AND ORA STA INY addr no channel number TALK open channel for reading accept byte LISTEN open channel for writing accept byte verify file type file type REL? yes close channel convert hex to decimal (2 bytes) #SOO #SOO SE6AA convert hex to BCD #S01 SE69F ****************************** E6AB E6AC E6AD E6AE E6AF E680 E6B3 E6B4 E6B6 E6B8 E6BA LISTEN act i ve? yes TALK active? yes channel number open channel to this second. A A A A $E6B4 divide BCD number into two bytes shift hi-nibble down convert to ASCI I #$OF #$30 ($A5),Y 207 erase top 4 bits add '0 ' write in buffer increment buffer pointer Anatomy of the 1541 Disk Drive E6BB 60 RTS ****************************** E6BC 20 23 Cl JSR SC123 E6BF A9 00 LDA IISOO AO 00 E6C1 LDY IISOO 84 80 STY S80 E6C3 84 81 STY S81 E6C5 write 'ok' in buffer erase error flag error number 0 ****************************** E6C7 AO 00 LOY IISOO A2 D5 LDX IISD5 E6C9 86 A5 E6C8 STX SA5 A2 02 LDX IIS02 E6CD E6CF 86 A6 STX SA6 20 AB E6 E6Dl JSR SE6AB A9 2C LDA jlS2C E6D4 STlI (S1I5),Y 9A A5 E6D6 ED6B C8 INY E6D9 AD D5 02 LDlI S02D5 8D 43 02 E6DC STA S0243 E60F 8A TXA 20 06 E7 E6EO JSR SE706 A9 2C E6E3 LOA IIS2C E6E5 STA (S1I5),Y 91 A5 C8 INY E6E7 A5 80 LDA S80 E6EB E6EA 20 98 E6 JSR SE69B A9 2C LDA 1I$2C E6ED E6EF STA (SA5),Y 91 A5 E6Fl C8 INY E6F2 A5 Bl LDA $81 20 9B E6 JSR SE69B E6F4 88 OEY E6F7 E6FB 9B TYA E6F9 IB CLC E6FA 69 D5 AOC lI$05 STA $0249 E6FC 8D 49 02 E6FF INC $1I5 E6 AS E701 A9 88 LDA #S88 E703 85 F7 STA $F7 E705 60 RTS error message in buffer buffer pointer ****************************** E706 All TAX E707 A5 86 LOA $86 E709 48 PHA E70A AS 87 LOA $87 PHA E70C 48 A9 FC LOA #$FC E70D E70F 85 86 STA lIS E4 E713 85 87 STA $87 E7l5 8A TXA E716 A2 00 LOX #$00 E718 Cl 86 CMP ($86,X) write error message to buffer error code to X 208 track 0 sector 0 pointer $A5/S1I6 TO $205 error * to .,. comma lISCII and in buffer write in buffer increment buffer pointer first digit of the disk status in output register error number in accumulator error message in buffer I,' comma write in buffer and increment buffer pointer track number to ASCII and in buffer • " comma wri te in buffer increment buffer pointer sector convert to ASCII and in buffer end pointer set READ flag preserve pointer $86/$87 start of the error messages error number in accumulator compare with error no in table Anatomy of the 1541 Disk Drive E7lA E7lC E71D E720 E722 E725 E727 E729 E72B E72D E72F E731 E733 E735 E736 E739 E73A FO 48 20 90 20 90 A5 C9 90 DO AO C5 90 68 4C 68 4C 21 E73D E740 E742 E745 E748 E74A E74D E74E E750 E751 E753 20 90 20 20 90 20 68 85 68 85 60 67 FB 54 67 F8 54 75 E7 05 75 E7 FB 87 E6 08 OA OA 86 04 18 E7 4D E7 E7 E7 E7 E7 87 86 BEO PHA JSR BCC JSR BCC LDA CMP BCC BNE LDA CMP BCC PLA JMP PLA JMP JSR BCC JSR JST BCC JSR PLA STA PLA STA RTS $E73D $E775 $E727 $E775 $E722 $87 #SE6 $E735 $E739 #SOA $86 $E739 bit 7 into carry and erase not set? bit 7 into carry wait for character with bit 7 set $E7l8 no, continue $E74D done $E767 $E73D $E754 $E767 $E742 $E754 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 character in buffer $E60A, check to end of table $87 get pointer $86/$87 back $86 ****************************** E754 E756 E758 E759 E75B E75D E75E E75F E762 E763 E765 E766 C9 20 SO OB AA A9 20 91 A5 C8 8A 20 06 E7 60 91 A5 C8 60 CMP #$20 BCS $E763 TAX LDA STA INY TXA JSR RTS STA INY RTS #$20 ($AS),Y SE706 ($A5),Y ****************************** E767 E769 E76B E76D E76F E770 E772 E774 E6 DO E6 Al OA Al 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 ****************************** 209 get character and in buffer • • blank greater, then write in buffer save code blank write in buffer increment buffer pointer code in accumulator output previous text write character in buffer and increment pointer get a char of the error message increment pointer get character bit 7 into carry get character erase bit 7 increment pointer Anatomy of the 1541 Disk Drive E77S E778 E77A E77C E77E 20 E6 DO E6 60 6D E7 86 02 87 JSR INC BNE INC RTS bit 7 into carry SE76D S86 $E77E S87 increment pointer ****************************** E77F 60 RTS ****************************** E780 E783 E784 E786 E788 E789 E78B E78D E78E E791 E793 E795 E798 E79B E79D E7AO AD AA 29 Fa 8A 29 FO 58 AD 29 FO EE EE A9 80 4C 00 18 04 F7 01 F2 00 05 F9 78 74 2A 00 A8 18 02 02 02 E7 LDA TAX AND BEO TXA AND BEO CLI LDA AND BNE INC INC LDA STA JMP S1800 check for AUTO-start read IEEE port #$04 $E77F isolate 'CLOCK IN' bit not set, then done #$01 SE77F isolate 'DATA IN' bit not set, then done $1800 #$05 SE78E S0278 $0274 #S2A $0200 SE7A8 load IEEE port test 'DATA IN' and 'CLOCK IN' wait until both set file name character in the input line '* , as filename write in buffer ****************************** E7A3 E7A5 E7A8 E7AB E7AE E7AF E7Bl E7B4 E7B6 E7B8 E7BB E7BE 1':7CO E7C2 E7C5 E7C6 E7C9 E7CC E7CE E7D1 E703 E705 E708 E7DA E7DC E70F E7E1 A9 20 20 AD 48 A9 80 A9 8S 20 AD DO A9 20 68 80 AD 85 AO 85 A9 20 A9 85 20 85 20 8D 68 C2 58 F2 78 02 01 78 FF 86 4F 80 05 39 C8 78 80 80 85 81 03 77 00 87 39 88 4B 02 C4 02 C1 02 02 02 D4 E8 E8 LDA JSR JSR LOA PHA LDA STA LOA STA JSR LOA BNE LOA JSR PLA STA LDA STA LDA STA LOA JSR LOA STA JSR STA JSR #S8D SC268 $F2S8 S0278 '& ' - command check command line to end (RTS) number of file names save #$01 S0278 iSFF S86 SC44F $0280 SE7C5 #$39 SClC8 file name find file found? 39, ' file not found' get number of file names back S0278 S0280 S80 $0285 S81 #$03 $D477 #$00 $87 $E839 $88 S884B track and sector file type 'USR' buffer allocated, read 1st bloc erase checksum get byte from file save as start address 10 form checksum 210 Anatomy of the 1541 Disk Drive E7E4 E7E7 E7E9 E7EC E7EE E7FO E7F2 E7F3 E7F5 E7F6 E7F8 E7FA E7FD E7FF E802 E805 E807 E809 E80C E80E E80F E811 E813 E8l5 E8l7 E819 E8lB E8lE E820 E822 E824 E827 E829 E82C E82E E830 E831 E833 E834 E836 E839 E83C E83E E840 E843 E845 E848 E84A 20 85 20 A5 FO A5 48 A5 48 A9 85 20 85 20 20 AO 91 20 A5 18 69 85 90 E6 C6 DO 20 A5 C5 FO 20 A9 20 A5 DO 68 85 68 85 6C 20 A5 DO 20 A9 20 A5 60 39 E8 89 4B E8 86 OA 88 89 00 86 39 8A 4B 39 00 88 4B 88 E8 E8 E8 E8 01 88 02 89 8A E7 35 CA 85 87 08 3E DE 50 45 E6 F8 A8 89 88 88 35 F8 08 3E 51 45 85 00 CA DE E6 JSR STA JSR LOA BEO LOA PHA LDA PHA LOA STA JSR STA JSR JSR LOY STA JSR LDA CLC AOC STA BCC INC OEC BNE JSR LDA CMP BEO JSR LOA JSR LOA BNE PLA STA PLA STA JMP JSR LOA BNE JSR LDA JSR LDA RTS $E839 $89 $E84B $86 $E7FA $88 get byte from file as start address hi form checksum save program start address $89 #$00 $86 $E839 $8A $E84B $E839 #$00 ($88),y $E84B $88 UOI $88 $E8l7 $89 $8A $E802 $CA35 $85 $87 $E82C $OE3E #$50 $E645 $F8 $E7D8 get byte from file save as counter form checksum get byte from file save as program bytes form checksum increment $88/$89 decrement pointer get next byte data byte equal to checksuro? yes transmit param to disk controller 50, 'record not present' end? no, next data block $89 get program start address back $88 ($0088) $CA35 $F8 $E848 $DE3E #$51 $E645 $85 ****************************** E84B A8 CLC E84C 65 87 ADC $87 E84E 69 00 ADC #$00 E850. 85 87 STA $87 60 E852 RTS 211 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 Disk Drive ****************************** E853 E856 E858 E85A AD 01 18 A9 01 85 7C 60 LDA $1801 LDA #$01 STA $7C RTS set flag for 'ATN received' ****************************** E85B E85C E85E E860 E862 E864 E866 E867 E869 E86B E86D E870 E873 E876 E878 E87B E87E E880 E882 E884 E887 E889 E88B E88D E88F E891 E893 E895 E897 E899 E89B E89D E89F E8A1 E8A3 E8A5 E8A7 E8A9 E8AB E8AD E8AF EBB1 EBB3 EBB5 E8B7 E8B8 EBBA 78 A9 85 85 85 A2 9A A9 85 85 20 20 AD 09 8D AD 10 29 DO 20 C9 DO A9 85 FO C9 DO A9 85 FO C5 DO A9 85 A9 85 FO C5 DO A9 85 00 7C 79 7A 45 80 F8 7D B7 A5 00 10 00 00 57 04 F7 C9 3F 06 00 79 71 5F 06 00 7A 67 78 OA 01 7A 00 79 29 77 OA 01 79 A9 00 85 7A FO IB AA 29 60 C9 60 E9 E9 18 18 18 E9 SEI LDA STA STA STA LDX TXS LDA STA STA JSR JSR LDA ORA STA LDA BPL AND BNE JSR CMP BNE LDA STA BEO CMP BNE LDA STA BEO CMP BNE LDA STA LDA STA BEO CMP BNE LDA STA LDA STA BEO TAX AND CMP IRO routine for serial bus read port A, erase IRO flag #$00 $7C $79 $7A #$ 45 servicing the serial bus erase flag for • ATN received' erase flag for LISTEN erase flag for TALK ini tiali ze stack pointer #$80 $F8 $7D $E9B7 $E9A5 $1800 jI$10 $1800 $1800 $E8D7 #$ 04 $E87B $E9C9 #$3F $E891 jI$OO $79 $E902 #$5F $E89B #$00 $7A $E902 $78 $E8A9 #$01 $7A jI$OO $79 $E8D2 $77 $E8B7 jI$Ol $79 #$ 00 $7A $E8D2 erase end erase EOI CLOCK OUT DATA OUT, flag flag 10 bit ' 0 I , hi switch data lines to input read IEEE port EO!? CLOCK IN? no get byte from bus un1isten? 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 #$60 #$60 set bit 5 and 6 212 Anatomy of the 1541 Disk Drive E8BC E8BE E8BF E8Cl E8C3 E8C5 E8C7 E8C9 E8CB E8CD E8CE E8Dl E8D2 E8D5 E8D7 E8D9 E8DB E8DE E8EO E8E3 E8E5 E8E7 E8EA DO 8A 85 29 85 AS 29 C9 DO 58 20 78 2C 30 A9 85 AD 29 8D AS FO 20 4C ESED E8EF ESFl ESF4 ESF7 E8FA ESFD ESFF E902 E905 E907 AS FO 20 20 20 4C A9 SD 2C 10 30 3F 84 OF 83 84 FO EO 35 CO DA 00 AD 00 7D 00 EF 00 79 06 2E E7 7A 09 9C AE 09 4E 10 00 00 DO F9 18 18 18 EA EB E9 E9 E9 EA IS 18 BNE TXA STA AND STA LDA AND CMP BNE CLI JSR SEI BIT BMI LDA STA LDA AND STA LDA BEQ JSR JMP LDA BEQ JSR JSR JSR JMP LDA STA BIT BPL BMI $E8FD no $84 #$OF $83 $84 #$FO #$EO $E902 byte is secondary address $DACO CLOSE routine channel number CLOSE? $1800 $E884 #$00 $7D $1800 #$EF $1800 $79 $E8ED $EA2E $EBE7 set EOI IEEE port switch data lines to output LISTEN active? no receive data to delay loop $7A TALK active? no DATA OUT, bit 11· , 10 CLOCK OUT hi send data to delay loop either TALK or LISTEN,ignore byte switch data lines to input $ES~'A $E99C $E9AE $E909 $EME #$10 $lSOO $1800 $ESD7 $E902 wait for handshake *******************.********** 7S E909 SEI E90A 20 EB DO JSR $DOEB E90D BO 06 BCS $E9l5 A6 S2 LOX $82 E90F E911 B5 F2 LOA $F2,X E913 30 01 BMI $E916 60 RTS E915 E916 JSR $EA59 20 59 EA E919 20 CO E9 JSR $E9CO 29 01 AND *$01 E91C 08 PHP E91E E91F 20 B7 E9 JSR $E9B7 E922 28 PLP E923 FO 12 BEQ $E937 E925 20 59 EA JSR $EA59 E928 20 CO E9 JSR $E9CO E92B 29 01 AND #$01 E92D 00 F6 BNE $E925 213 send data open channel for read channel active channel number set READ flag? yes check EOI read IEEE port isolate data bit and save CLOCK OUT 10 check EOI read IEEE port isolate data bit Anatomy of the 1541 E92F E931 E933 E935 E937 E93A E93D E93F E941 E944 E947 E949 E84B E94E E951 E954 E956 E958 E9SA E95C E95F E961 E963 E965 E968 E969 E96C E96E E971 E973 E976 E979 E97B E97D E980 E983 E985 E987 E98A E98D E98F E991 £992 E995 E996 A6 82 B5 29 DO 20 20 29 DO 20 20 29 FO 20 20 20 29 DO A9 8S 20 29 DO A6 BO 6A 9D BO 20 DO 20 20 AS DO 20 20 C6 DO 20 20 29 FO 58 20 78 4C E999 4C 4E EA F2 08 14 59 CO 01 F6 59 CO 01 F6 AE 59 CO 01 F3 08 98 CO 01 36 82 3E 3E OS AS 03 9C B7 23 03 F3 FB 98 D5 59 CO 01 F6 EA E9 EA E9 E9 EA E9 E9 02 02 E9 E9 E9 FE FE EA E9 AA D3 OF E9 Dis~ Drive LDX LDA AND BNE JSR JSR AND BNE JSR JSR AND BEO JSR JSR JSR AND BNE LDA STA JSR AND BNE LDX LDA ROR STA BCS JSR BNE JSR JSR LDA BNE JSR JSR DEC BNE JSR JSR AND BEO CLI JSR SEI $82 $F2,X #$08 $E94B $EA59 $E9CO #$01 $E937 $EA59 $E9CO #$01 $E941 $E9AE $EA59 $E9CO #$01 $E94B #$08 $98 $E9CO #$01 $E999 $82 $023E,X A $023E,X $E973 $E9A5 $E976 $E99C $E9B7 $23 $E980 $FEF3 $FEFB S98 $E95C $EA59 $E9CO #$01 $E987 $D3AA get next data byte J~lP $E90F and output JMP $EA4E channel number check EOI read IEEE port isolate data bit check EOI read IEEE port isolate data bit CLOCK OUT hi check EOI read IEEE port isolate data bit counter to 8 bits for serial transmission read IEEE port isolate data bit lowest bit in carry set bit DATA OUT, output bit ' 0' absolute jump DATA OUT, output bit ' I' set CLOCK OUT delay for serial bus set DATA OUT and CLOCK OUT all bits output? no check EOI read IEEE port isolate data bit to delay loop ****************************** E99C AD 00 18 LDA $1800 E99F 29 FD AND #$FD E9A1 8D 00 18 STA $1800 E9A4 60 RTS output bit 'I' ****************************** DATA OUT hi 214 DATA OUT 10 Anatomy of the 1541 Disk Drive E9A5 E9A8 E9AA E9AD AD 00 18 09 02 80 00 18 60 LOA $1800 ORA #$02 STA $1800 RTS output bit '0 ' ****************************** E9AE E9B1 E9B3 E9B6 AD 00 18 09 08 80 00 18 60 LOA $1800 ORA #$08 STA $1800 RTS set bit 3 ****************************** E9B7 E9BA E9BC E9BF AD 00 18 29 F7 80 00 18 60 LOA $1800 AND #$F7 STA $1800 RTS AD 00 18 CD 00 18 DO F8 60 CLOCK OUT 10 erase bit 3 ****************************** E9CO E9C3 E9C6 E9C8 CLOCK OUT hi LOA $1800 CMP $1800 BNE $E9CO RTS read IEEE port read port wait for constants ****************************** E9C9 E9CB E9CD E9DO E9D3 E9D5 E9D7 E9DA E9DC E9DF E9E2 E9E5 E9E7 E9E9 E9EC E9EE E9FO E9F2 E9F5 E9F7 E9FB E9FA E9FD EAOO EA03 EA05 EA07 EA09 EAOB EAOE EAI0 A9 85 20 20 29 DO 20 A9 80 20 AD 29 DO 20 29 FO DO 20 A2 CA DO 20 20 20 29 FO A9 85 AD 49 4A 08 98 59 CO 04 F6 9C 01 05 59 00 40 09 CO 04 EF 19 A5 OA FD 9C 59 CO 04 F6 00 F8 00 01 EA E9 E9 18 EA 18 E9 E9 E9 EA E9 18 LOA STA JSR JSR AND BNE JSR LOA STA JSR LOA AND BNE JSR AND BEQ BNE JSR LOY DEX BNE JSR JSR JSR AND BEO LOA STA LOA EaR LSR #$08 $98 $EA59 $E9CO #$04 $E9CD $E99C #$01 $1805 $EA59 $1800 #$40 $E9F2 $E9CO #$04 $E9DF $EAOB $E9A5 #$OA bit counter for serial output check EOI read IEEE port CLOCK IN? no, wait DATA OUT, bit ' I' set timer check EOI timer run down? yes, EOI read IEEE port CLOCK IN? no, wait DATA OUT bit '0' hi 10 delay loop, approx 50 micro sec. $E9F7 $E99C $EA59 $E9CO #$04 $E9FD #$00 $F8 $1800 #$01 A DATA OUT, bit '1' , 10 check EOI read IEEE CLOCK IN? no, wait set Eor flag IEEE port invert data byte 215 Anatomy of the 1541 Disk Drive EAll EA13 EA15 EA16 EAl7 EA18 EAIA EAID EA20 EA22 EA24 EA26 EA28 EA2B EA2D 29 DO EA EA EA 66 20 20 29 FO C6 DO 20 A5 60 02 F6 85 59 EA CO E9 04 F6 98 E3 A5 E9 85 AND BNE NOP NOP NOP ROR JSR JSR AND BEQ OEC BNE JSR LOA RTS #$02 $EAOB CLOCK IN? $85 $EA59 $E9CO #$04 $EAIA $98 $EAOB $E9A5 $85 prepare next bit check EOI read IEEE port CLOCK IN? no decrement bit counter all bits output? DATA OUT, bit ' 0 1 , hi load data byte again ****************************** 78 20 BO B5 6A BO A5 29 C9 FO 4C EA44 EA47 EA48 EMB 20 C9 E9 58 20 B7 CF 4C 2E EA JSR $E9C9 CLI JSR $CFB7 JMP $EA2E EA4E EA50 EA53 A9 00 80 00 18 4C E7 EB LOA #$00 STA $1800 JMP $EBE7 reset IEEE port to wait loop EA56 4C 5B E8 JMP $EB58 to serial bus main loop 07 01 05 F2 DB 84 FO FO 03 4E EA SEI JSR RCS LOA ROR BCS LOA ANO CMP BEO JMP accept data from serial bus EA2E EA2F EA32 EA34 EA36 EA37 EA39 EA3B EA30 EA3F EMI $0107 $EA39 $F2,X A $EM4 $84 #$FO #$FO $EM4 $EME open channel for writing channel not active? WRITE flag not set? secondary address OPEN command? yes to wait loop get data byte from bus and write in buffer to loop beginning ****************************** EA59 EA5B EA5D EA60 A5 FO AD 10 7D 06 00 18 09 EA62 60 RTS EA63 EA66 EA68 AD 00 18 10 FA 4C D7 E8 LDA $1800 BPL $EA62 JMP $E807 LOA BEO LOA BPL $70 $EA63 $lROO $EA6B EOI received? yes IEEE port IEEE port set EOI, serve serial bus ****************************** EA6E EA70 A2 00 2C LOX #$00 .BYTE $2C 216 blink LED for hardware defects blink once, zero page Anatomy of the 1541 Disk Drive EA7l EA73 EA74 EA75 EA77 EA7A EA7D EA7E EA7F EA81 EA83 EA84 EA86 EAB9 EABB EA8E EABF EA90 EA92 EA94 EA95 EA97 EA98 EA9A EA9C EA9E A5 9A BA A9 OD 4C 98 18 69 DO 88 DO AD 29 8D 9B IB 69 DO B8 DO CA 10 EO DO FO 6F 08 00 lC EA FE 01 FC F8 00 Ie F7 00 lC 01 FC FB DB FC FO D4 LDX TXS TSX LDA ORA JMP TYA CLC ADC ENE DEY BNE LDA AND STA TYA CLC ADC BNE DEY BNE DEX BPL CPX BNE BEO $6F blink X+l times for RAM/ROM err #$08 $lCOO $FEEA select LED bit in the port turn LED on, back to $EA7D #$01 $EA7F $EA7E $lCOO #$F7 $lCOO turn LED off #$01 $EA90 delay loop $EABF $EA75 #$FC $EA8E $EA74 wait for delay turn LED on again ****************************** EAAO EAAI EAA2 EAA4 EAA7 EAA8 EAAA EAAC EAAD EAAF EABO EAB2 EAB3 EAB5 EAB7 EAB9 EABA EABC EABE EACO EAC2 EAC4 EAC6 EAC7 EAC9 EACB EACD 78 D8 A2 BE E8 AO A2 BA 95 E8 DO 8A D5 DO F6 C8 DO D5 DO 94 B5 DO EB DO E6 86 A9 FF 03 IB 00 00 00 FA 00 B7 00 FB 00 AE 00 00 AB E9 6I" 76 00 SEl CLD LDX STX lNX LDY LDX TXA STA INX BNE TXA CMP BNE INC INY BNE CMP BNE STY LDA BNE lNX BNE INC STX LDA #$FF SlB03 RESET routine port A to output #SOO #SOO $OO,X erase zero page $EAAC $OO,X $EA6E $OO,X is byte erased? no, then to error display (blink) SEAB7 $OO,X $EA6E $OO,x $OO,X $EA6E error error $EAB2 $6F $76 #$00 217 Anatomy of the 1541 Disk Drive EACF EADI EAD2 EAD4 EAD5 EAD7 EAD9 EADA EADC EADD EADF EAEI EAE2 EAE4 EAE6 EAE8 EAEA EAEe EAEE EAFO EAF2 EAF3 EAF4 EAF6 EAF8 EAF9 EAFB EAFD EAFE EBOO EB02 EB04 EB05 EB06 EB07 EB09 EBOB EBOD EBOF EBll EBl3 EB15 EB17 EB18 EB1A EBlB EBID EB1F 85 A8 A2 18 C6 71 C8 DO CA DO 69 AA C5 DO EO DO A9 85 E6 A2 98 18 65 91 C8 DO E6 CA DO A2 C6 88 98 18 65 Dl DO 49 91 51 91 DO 98 DO CA DO FO 4C EB22 EB24 EB25 EB28 EB2A EB2D A2 9A AD 29 8D A9 75 20 76 75 FB F6 00 76 39 CO DF 01 76 6F 07 76 75 F7 76 F2 07 76 76 75 12 FF 75 75 75 08 EA E5 03 71 EA 45 00 lC F7 00 lC 01 STA TAY LDX CLC DEC ADC INY BNE DEX BNE ADC TAX CMP BNE CPX BNE LDA STA INC LDX TYA CLC ADC STA INY BNE INC DEX BNE LDX DEC DEY TYA CLC ADC CMP BNE EOR STA EOR STA BNE TYA BNE DEX BNE BEO JMP LDX TXS LDA AND STA LDA $75 #$20 test 32 pages $76 ($75) ,Y $EAD7 $EAD5 #$00 test ROM $76 $EBIF ROM error #$CO $EAC9 #$01 $76 $6F' #$07 test RAM, beginning at page 7 $76 ($75) ,Y $EAF2 $76 $EAF2 #$07 $76 $76 ($75),Y $EBIF #$FF ($75),Y ($75),Y ($75) ,y $EB1F RAM error RAM error $EB04 $EB02 $EB22 $EA7l continue test ok to error display #$45 initialize stack pointer $ICOO #$F7 turn LED off $lCOO #$01 218 Anatomy of the 1541 Disk Drive EB2F EB32 EB34 EB37 EB3A EB3D EB3F EB40 EB41 EB42 EB43 EB45 EB47 EB49 EB4B EB4D EB4F EB51 EB53 EB54 EB57 EB59 EB5A EB5B EB50 EB5F EB61 EB63 EB64 EB66 EB68 EB69 E86B EB6D EB6E EB70 EB72 EB74 EB76 EB79 EB7A EB7C EB7E EB80 EB82 EB84 EBB5 EB87 EB89 EBBB EB8D EB8F EB91 EB93 EB95 8D A9 8D 8D AO 29 OA 2A 2A 2A 09 85 49 85 A2 AO A9 95 E8 B9 95 E8 C8 CO DO A9 95 E8 A9 95 E8 A9 95 E8 A9 95 A9 A2 9D CA 10 A2 95 95 95 CA 10 A9 85 A9 85 A9 85 85 A9 OC 82 OD OE 00 60 18 18 18 18 4B 78 60 77 00 00 00 99 EO FE 99 05 FO 00 99 02 99 D5 99 02 99 FF 12 2B 02 FA 05 A7 AE CD F7 05 AB 06 AC F'F AD B4 05 STA LOA STA STA LDA AND ASL ROL ROL ROL ORA STA EOR STA LOX LDY LDA STA INX LDA STA INX INY CPY BNE LDA STA INX LDA STA INX LDA STA INX LDA STA LDA LDX STA DEX BPL LDX STA STA STA DEX BPL LOA STA LDA STA LDA STA STA LDA S180C #S82 S180D S180E S1800 #S60 A A CAl (ATN IN) trigger on pas edge A rotate to bit positions 0 & 1 interrupt possible through ATN IN read port B isolate bits 5 & 6 (device #) A #S48 S78 #S60 S77 #SOO #SOO #SOO S99,x add offset from 8 + S40 for TALK device number for TALK (send) erase bit 6, set bit 5 device number + S20 for LISTEN low-byte of buffer address $F'EEO, Y $99,x high byte of address from table save #S05 SEB4F' #$00 S99,X ptr SA3/$A4 to S200, input buffer #S02 S99,X #$D5 S99,X #S02 $99,X #SFF #S12 $022B,X SEB76 #$05 SA7,X SAE,X $CD,X pointer SA5/SA6 to S2D5, error message pointer fill channel table with SFF erase buffer table erase side-sector table SEB7E #$05 SAB #S06 SAC #SFF SAD SB4 #S05 buffer 5 associate with channel 4 buffer 6 associate with channel 5 219 Anatomy of the 1541 Disk Drive EB97 EB9A EB9C EB9F EBAI EBA4 EBA6 EBA8 EBAA EBAC EBAE EBBI EBB3 EBB6 EBB8 EBBA EBBC EBBF EBC2 EBC5 EBC7 EBC9 EBCB EBCD EBCF EBOI EBD3 EB05 EB07 EBDA EBDC EBOF EBEI EBE4 EBE7 EBES EBEB ERED EBFO EBF3 EBF5 EBF7 EBFA EBFC SO A9 SO A9 80 A9 85 A9 85 A9 80 A9 80 A9 85 85 20 20 20 A9 85 A9 85 A9 85 A9 85 A9 20 A9 8D A9 8D 20 58 AO 29 SO AO FO A9 80 85 20 3B 84 3A OF 56 01 F6 88 F7 FO 4F FF 50 01 lC 10 63 FA 59 22 65 EB 66 OA 69 05 6A 73 Cl lA 02 00 00 80 02 00 E5 00 55 OA 00 55 67 46 18 02 02 02 02 CB CE F2 E6 18 18 E7 18 02 02 Cl STA LDA STA LOA STA LOA STA LOA STA LOA STA LOA STA LOA STA STA JSR JSR JSR LOA STA LOA STA LOA STA LOA STA LDA JSR LOA STA LOA STA JSR CLI LDA AND STA LOA BEO LDA STA STA JSR $023B *$S4 $023A *$OF $0256 *$01 $F6 *$S8 SF7 *$EO $024F *$FF $0250 *$01 SIC S10 SCB63 $CEFA $F259 *$22 $65 #$EB $66 *$OA $69 H05 $6A #$73 $E6Cl #$lA $1802 #$00 $1800 $E7S0 channel 5 WRITE flag erased channel 4 WRITE flag set initialize channel allocation bit '1 ' equals channel free WRITE flag REAO flag 5 buffers free initialize buffer allocation reg $24F/$250, 16 bit flags for WRITE protect set vector for UO initialize channel table intialization for disk controller pointer $65/$66 to $EB22 step width 10 for sector assignment 5 read attempts prepare power-up message 73, 'cbm dos v2.6 1541' bit 1, 3 & 4 to exit data direction of port B erase data register check for auto-start $lS00 #$E5 $1800 $0255 $EBFF *$00 $0255 $67 $C146 reset serial port command flag set? no reset command flag analyze and execute command ****************************** EBFF ECOO EC02 EC04 EC07 EC08 ECOA ECOC ECOE 58 A5 FO 4C 58 A9 85 A9 85 7C 03 58 E8 OE 72 00 6F CLI LDA REO JMP CLI LOA STA LDA STA re~ wait loop $7C $EC07 SE85B ATN signal discovered? no to IEEE routine #$OE $72 #$00 $6F 14 as secondary address job counter 220 Anatomy of the 1541 Disk Drive EClO EC12 EC14 EC17 EC19 EClB EClD EClF EC22 EC23 EC26 EC28 EC29 EC2B EC2D EC2F EC3l EC34 EC36 EC38 EC39 EC3B EC3C EC3E EC3F EC42 EC44 EC45 EC47 EC49 EC4B EC40 EC4F EC51 EC53 EC55 EC58 EC59 EC5B EC5C EC5E EC60 EC62 EC64 EC66 EC69 EC6A EC6C EC6D EC6F EC71 EC72 EC75 ECn EC7A 85 A6 BD C9 FO 26 85 20 AA BD 29 70 72 2B 02 FF 10 3F 82 93 OF 5B 02 01 AA F6 C6 10 AO B9 10 29 AA F6 88 10 78 AD 29 48 A5 85 A9 85 A5 FO AS FO 20 68 09 48 E6 AS FO AS FO 20 68 09 48 A5 6F 72 E3 04 00 00 05 01 6F F3 00 1C F7 7F 86 00 7F 6F OB lC 03 13 D3 08 7F 70 DB ID 03 13 D3 00 86 85 7F 68 AE Fa AD EO 6C 02 21 00 lC 80 STA LOX LOA CMP BEO AND STA JSR TAX LOA AND TAX INC DEC BPL LOY LDA BPL AND TAX INC DEY BPL SEI LDA AND PHA LOA STA LDA STA LOA BEO LOA BEO JSR PLA ORA PHA INC LDA BEO LDA BEO JSR PLA ORA PHA LDA STA PLA LDX BEO LDA CPX $70 $72 $022B,X #$FF $EC2B #S3F $82 SDF93 secondary address channel associated? no channel number get buffer number $025B,X #$01 drive number $6F,X $72 $EC12 #$04 $OOOO,y SEC3B #$01 increment job counter 10 address continue search buffer counter disk controller in action? no isolate drive number $6F ,X increment job counter $EC31 next buffer $ICOO #$P? erase LED bit $7F $86 #$00 $7F S6F $EC5C SIC $EC58 $0313 drive 0 job for drive O? no write protect for drive O? no close all channels to drive 0 #$08 set LED bit $7F $70 $EC6D $10 SEC69 S0313 increment drive number job for drive I? no write protect for drive I? no close all channels to drive 1 drive number #$00 S86 $7F get drive number back bit for LED interrupt counter to zero? $026C $EC98 $lCOa #S80 221 Anatomy of the 1541 Disk Drive EC7C EC7E EC81 EC84 EC86 EC88 EC8B ECBE EC90 EC93 EC95 EC98 EC9B DO 4C AE 30 A2 8E CE DO 4D A2 8E 8D 4C 03 8B 05 12 AO 05 6C 08 6D 10 6C 00 FF EC 18 18 02 02 02 lC EB BNE JMP LDX BMI LDX STX DEC BNE EOR LDX STX STA JMP $EC81 $EC8B $1805 $EC98 #$AO $1805 $026C $EC98 $026D #$10 $026C $lCOO $EBFF erase timer interrupt set timer decrement counter not yet zero? reset counter turn LED on/off back to wait loop ****************************** EC9E A9 00 LDA #$00 ECAD 85 83 STA $83 A9 01 ECA2 LDA #$01 ECA4 20 E2 Dl JSR $DIE2 ECA7 A9 00 LDA #$00 ECA9 20 C8 D4 JSR $D4C8 ECAC A6 82 LDX $82 ECAE A9 00 LDA #$00 ECBO 9D 44 02 STA $0244,X ECB3 20 93 DF JSR $DF93 ECB6 AA TAX ECB7 AS 7F LDA $7F ECB9 9D 5B 02 STA $025B,X ECBC A9 01 LDA #$01 ECBE 20 Fl CF JSR $CFFI ECCI A9 04 LDA #$04 ECC3 20 Fl CF JSR $CFFI ECC6 A9 01 LDA #$01 ECC8 20 Fl CF JSR $CFFI ECCB 20 Fl CF JSR $CFFI ECCE AD 72 02 LDA $0272 ECDI 20 Fl CF JSR $CFFI ECD4 A9 00 LDA #$ 00 ECD6 20 Fl CF JSR $CFFI ECD9 20 59 ED JSR $ED59 ECDC 20 93 DF JSR $DF93 ECDF OA ASL A ECEO AA TAX ECEI D6 99 DEC $99,X ECE3 D6 99 DEC $99,X ECE5 A9 00 LDA #$00 ECE7 JSR $CFFl 20 1:'1 CF ECEA A9 01 LDA #$01 ECEC 20 Fl CF JSR $CFFl ECEF 20 Fl CF JSR $CFFI ECF2 20 CE C6 JSR $C6CE ECF5 90 2C BCC $ED23 ECF7 AD 72 02 LDA $0272 ECFA 20 Fl CF JSR $CFFI ECFD AD 73 02 LDA $0273 222 LOAD 11$11 secondary address 0 find channel and buffer initialize buffer pointer channel number pointer to end = zero get buffer number drive number bring in table 1 write in buffer 4, start address $0401 write in buffer 2 times 1 write in buffer as link address drive number write in buffer as line number line number hi in buffer directory entry in buffer get buffer number decrement buffer pointer 0 as line end in buffer 2 times 1 as link address directory entry in buffer another entry? block number 10 in buffer block number hi Anatomy of the 1541 Disk Drive EDOO Eo03 ED06 E008 EOOB EOOO EOIO EOll E012 E014 E016 E018 EOIA EOIO E020 E022 20 20 A9 20 00 20 OA Fl 59 00 Fl 00 93 CF EO CF OF AA A9 95 A9 A4 80 99 A5 60 00 99 88 82 54 02 F2 00 85 JSR JSR LOA JSR BNE JSR ASL TAX LOA STA LOA LOY STA STA LOA RTS $CFFI $E059 #$00 $CFFl $ECEA $OF93 A in buffer directory entry in buffer zero as end marker in buffer buffer full? no get buffer number #$00 $99,X #$88 $82 $0254 $00F2,Y $85 ***********.****************** E023 AO 72 02 LOA $0272 20 Fl CF E026 JSR $CFFI E029 AD 73 02 LOA $0273 E02C 20 Fl CF JSR $CFFI E02F 20 59 ED JSR $E059 E032 20 93 OF JSR $OF93 E035 OA ASL A E036 AA TAX E037 06 99 DEC $99,X E039 06 99 DEC $99,X E03B A9 00 LOA #$00 20 Fl CF JSR $CFFI E030 E040 20 Fl CF JSR $en'l E043 20 Fl C~' JSR $CFFI E046 JSR $OF93 20 93 OF E049 OA ASL A E04A A8 TAY E04B B9 99 02 LOA $0099,Y E04E A6 82 LOX $82 E050 90 44 02 STA $0244,X OE 44 02 E053 DEC $0244,X E056 JMP $EOOO 4C 00 EO ****************************** E059 AO 00 LOY #$00 E05B B9 Bl 02 LOA $02Bl,Y E05E 20 Fl CF JSR $CFFI E06l C8 INY E062 CO IB CPY #$lB E064 00 F5 BNE $E05B E066 60 RTS ****************************** E067 20 37 01 JSR $0137 E06A FO 01 BEO $E060 60 E06C RTS 223 buffer pointer to zero set REAO flag channel number flag for channel data byte block number 10 write in buffer block number hi in buffer I Blocks free. I in buffer get buffer number buffer pointer minus 2 three zeroes as program end get buffer number times 2 buffer pointer as end marker transmit directory line character from buffer write in output buffer 27 characters? get byte from buffer get byte buffer pointer zero? Anatomy of the 1541 Disk Drive E06D E06F E071 E074 E076 E078 E07B E07D 85 A4 B9 FO A9 99 AS 60 85 82 44 02 08 80 F2 00 85 E07E E07F E082 E083 48 20 EA EC 68 60 STA LOY LOA BEO LOA STA LOA RTS $85 $82 $0244,Y $E07E #$80 $00F2,Y $85 PHA JSR $ECEA PLA RTS save data byte channel number set end marker zero (LOAD S)? set REAO flag data byte create directory line in buffer ****************************** E084 20 01 C1 JSR $C101 E087 20 42 DO JSR $0042 E08A A9 40 LOA #$40 80 F9 02 STA $02F9 EOBC E08F 20 B7 EE JSR $EEB7 E092 A9 00 LOA #$00 E094 80 92 02 STA $0292 20 AC C5 JSR $CSAC E097 E09A 00 3D BNE $E009 A9 00 LOA #$00 E09C E09E 85 81 STA $B1 EOAO AO 8E FE LOA SFE85 B5 80 STA $80 EOA3 EOAS 20 E5 EO JSR SEOE5 LOA #SOO EDAB A9 00 EOAA 80 F9 02 STA $02F9 20 FF EE JSR SEEFF EOAO EOBO 4C 94 C1 JMP $C194 ****************************** EOB3 C8 INY EOB4 B1 94 LOA (S94),Y PHA EOB6 48 EOB7 C8 INY EOB8 Bl 94 LOA (S94),Y EOBA 48 PHA EOBB AO 13 LOA #$13 Bl 94 LDA (S94),Y EOBO EOBF FO OA BEO SEDCB EOC1 85 80 STA S80 C8 INY EOC3 EDC4 B1 94 LOA ($94),Y EOC6 85 81 STA $81 20 E5 EO EOC8 JSR SEOE5 EOCB 68 PLA EOCC 85 81 STA $81 EOCE 68 PLA EOCF 85 80 STA $80 EOD1 20 ES ED JSR $EDE5 EOD4 20 04 C6 JSR $C604 224 V command, • collect • find drive number in input line load BAM create new BAM in buffer load directory, find 1st flag found? sector 0 18 track 18 for BAM mark dir blocks as allocated write BAM back to disk done, prepare disk status 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 mark blocks of file as allocated read next entry in directory Anatomy of the 1541 oisk Drive E007 E009 EOOB EOOO EOOF EOE2 FO AO Bl 30 20 4C C3 00 94 04 B6 C8 04 EO BEO LOY LOA BMI JSR JMP $E09C #$00 ($94) , Y SEOB3 SC8B6 SE004 ****************************** EOE5 EOE8 EOEB EOEE EOFO EOF3 EOF6 EOF8 EOFB EDFD EDFF EEOl 20 20 20 A9 20 20 85 20 85 A5 DO 4C 5F 90 75 00 C8 37 80 37 81 80 03 27 05 EF 04 EE04 EE07 EEOA 20 90 EF 20 4D 04 4C EE EO 04 01 Dl 02 JSR JSR JSR LOA JSR JSR STA JSR STA LOA BNE JMP S055F SEF90 $0475 #$00 S04C8 $0137 S80 $D137 $81 $80 SEE04 $0227 20 A5 10 A9 4C 29 85 20 A5 OA AA AC CC FO B9 95 B9 95 20 A9 85 20 20 4C 12 C3 E2 05 33 C8 Cl 01 7F 00 Cl 7F 7B 74 lA 00 12 01 13 07 01 80 C6 05 56 JSR SEF90 JSR S044D JI1P $EDEE $C312 $E2 SEE19 #$ 33 $C1C8 #$01 $7F SCIOO $7F A C8 FO EE EE46 EE49 EE4B EE4E 20 A6 BO CO 42 00 7F 01 01 05 FE JSR LDX LOA CMP $0042 $7F $OlOl,X SFE05 02 02 03 allocate file blocks in BAM check track and sector number allocate block in BAM read next block allocate block in BAM read next block continue JSR LDA BPL LDA JI1P ANO STA JSR LOA ASL TAX LOY CPY BEO LOA STA LDA STA JSR LOA STA JSR JSR JMP 02 02 file type bit 7 set, file closed? file type to zero and write BAM buffer pointer zero get byte from buffer track get byte from buffer sector another block? yes close channel ****************************** EEOD EEIO EE12 EE14 EE16 EE19 EEIB EEID EE20 EE22 EE23 EE24 EE27 EE2A EE2C EE2F EE31 EE34 EE36 EE39 EE3B EE30 EE40 EE43 end of directory? N command, 'header' get drive number drive number not clear? 33, 'syntax error' drive number turn LED on drive number times 2 $027B $0274 $EE46 $0200,Y $12,X S0201,Y $13,X $0307 #$01 $80 $C8C6 $F005 SEE56 225 comma position compare with end name format without 1D first character of 1D save second character close all channels track 1 format disk erase buffer continue as below load BAM drive number 'A' , marker for 1541 format Anatomy of the 1541 Disk Orive EE51 EE53 FO 03 4C 72 05 BEO SEE56 JMP S0572 ok 73, 'cbm dos v2.6 1541' EE56 EE59 EE5B EE5C EESD EE5E EE61 EE63 EE66 EE6B EE6B EE6D EE6F EE72 EE75 EE76 EE77 EE7B EE7A EE7C EE70 EE7F EE81 EE82 EE83 EE85 EE87 EE8B EE8B EE8D EE8F EE91 EE94 EE96 EE99 EE9B EE90 EEAO EEA3 EEA6 EEAB EEAA EEAC EEAF EEBI EEB4 20 B7 EE A5 F9 JSR LOA TAY ASL TAX LOA STA LOX LOA JSR LDY LOX LOA STA TXA ASL TAX LOA STA INY LOA STA INY INY LOA STA INY LDA STA LDY STA LOA STA JSR LOA STA JSR JSR JSR LOY LOA STA JSR OEC JSR JMP create BAM buffer number AS OA AA AD 95 AE A9 20 AO A6 AO 90 8A OA AA B5 91 C8 B5 91 C8 C8 A9 91 C8 AO 91 AO 91 AO 85 20 A9 85 20 20 20 AO A9 9A 20 C6 20 4C 88 99 7A 1B 6E 12 7F D5 01 FE 02 C6 FE 01 12 94 13 94 32 94 D5 94 02 6D 85 BO 93 01 Bl 93 FF 05 01 FF 6D 64 81 60 94 F'E FE EF EF BE FO D4 04 Cl SEEB7 SF9 A SFE88 S99,X S027A #SlB SC6f;E 1IS12 S7F SFE05 S0101,X S90, start of disk name buffer pointer to name A times 2 S12,X (S94),Y ID, first character in buffer S13 ,X (S94) ,Y and second character in buffer #S32 (S94) ,Y '2' in buffer SFE05 (S94), Y 1IS02 (S60) ,Y SFE85 $80 SEF93 #SOI S81 SEF93 'A' 1541 format in buffer $EE~'F SF005 #SOI #SFF (S6D),Y S0464 S81 $0460 SC194 ****************************** EEB7 20 01 FO JSR SFOOI EEBA AO 00 LOY #SOO EEBC A9 12 LOA #S12 EEBE 91 60 STA (S60),Y 226 27 write filenames in buffer position 18 drive number 'A'r 1541 format and at position 2 18 track number mark block as allocated 1 sector number mark block as allocated wri te BAM pointer S60/$6E to buffer, erase buffer track following is zero write BAM decrement sector number, 0 read block prepare disk status create BAM 18 pointer to directory track Anatomy of the 1541 Disk Drive EECO EECl EEC2 EEC4 EEC5 EEC6 EEC7 EEC9 EECB EECD EECF EEDO EEDl EED2 EED5 EED7 EED8 EED9 EEDA EEDC EEDE EEEO EEEl EEE3 EEE5 EEE7 EEE8 EEE9 EEEB EEED EEEF EEFI C8 98 91 C8 C8 C8 A9 85 85 85 98 4A 4A 20 91 C8 6D 00 6F 70 71 4B F2 6D 6F 70 71 F6 6F 6D 03 F6 90 D6 75 DO SEC ROL ROL ROL DEX BNE LDA STA INY INX CPX BCC CPY BCC JMP S6F S70 S71 1\9 00 99 20 AS OA 48 20 68 18 69 20 3 bytes = 24 bits for sectors byte position divided by 4 = track number get number of sectors and in BAM create bit model SEED9 S6F,X (S6D),Y 3 bytes the BAM in huffer #S03 SEEE3 #S90 SEEC7 S[)075 position 144? no, next track calculate number of free blocks ****************************** EEF4 20 93 DF JSR SDf'93 EEF7 TAX AA BD 5B 02 LDA S025B,X EEF8 29 01 EEFB AND #$01 85 7F STA S7F EEFD 114 7F LDY S7F EEFF EFOI B9 51 02 LDA $025I,Y EF04 DO 01 BNE SEF07 60 EF06 RTS EF07 EF09 EFOC EFOF EFll EF12 EF13 EF16 EFl7 EF18 EFIA 1 pointer to directory sector TAX AA 38 26 26 26 CA DO B5 91 C8 E8 EO 90 CO 90 4C INY TYA STA (S6D),Y INY INY INY LDA #$00 STA S6F STA S70 STA S71 TYA LSR A LSR A JSR SF24B STA(S6D),Y INY 51 02 3A EF 7F A5 FO 01 AS FO LDA STA JSR LDA ASL PHA JSR PLA CLC ADC JSR #$00 S025l,Y SEF3A S7F write BAM if needed get buffer number command for disk controller isolate drive number BAM-changed flag set? yes A reset BAM-changed flag set buffer pointer for BAM drive number times 2 SFOA5 verify BAM entry #SOl $FOA5 increment track number verify BAM entry 227 Anatomy of the 1541 Disk Drive EFID EFIF EF20 EF22 EF24 EF25 EF26 EF28 EF2B EF20 EF2F EF32 EF34 EF35 EF37 AS 48 A9 85 OA OA 85 20 E6 AS CD 90 68 85 4C 80 01 80 6D 20 F2 80 80 07 FE FO 80 SA DS LDA PHA LDA STA ASL ASL STA JSR INC LOA CMP BCC PLA STA JMP S80 track #SOl S80 A A S6D SF220 S80 S80 SFED7 SEF24 and compare with max val + 1 ok, next track S80 S058A get track number back write BAI' to disk track 1 times 4 verify BAM increment track number ****************************** EF3A 20 OF FI JSR SFIOF EF30 AA TAX EF3E 20 DF FO JSR SFODF EF41 A6 F9 LDX SF9 BO EO FE EF43 LOA $FEEO,X EF46 STA S6B 85 6E EF48 A9 00 LDA #SOO EF4A 85 60 STA $6D EF4C 60 RTS ****************************** EF4D EF4F EF52 EFS5 EF58 EF5B A6 7F BD 8D BD 8D 60 FA 72 FC 73 02 02 02 02 LDX LDA STA LDA STA RTS S7F S02FA,X S0272 S02FC,X S0273 ****************************** EF5C EF5F EF62 EF63 EF65 EFG7 EF6A EF6C EF6F EF71 EF72 EF74 EF76 EF78 EF7A EF7D EF7F EF82 EF84 20 20 38 DO Bl 10 91 20 M 18 Bl 69 91 AS CD FO Fl EF CF EF 22 6D £9 EF 6D 88 EF 6F 6D 01 60 80 85 FE 313 ~"E FA 02 DO 03 FE FC 02 JSR JSR SEC BNE LDA ORA STA JSR LOY CLC LDY AOC STA LOA CMP BEO INC BNE INC SEFFI SEFCF SEFS7 ($60), Y SEFE9 (S60) ,Y SEFS8 S6F (S60),Y #SOI (S60),Y SSO SFE8S SEFBA S02FA,X SEF87 S02PC,X 228 set buffer pointer for BAM get 6 for drive 0 allocate buffer buffer nUJllber buffer address, hi byte 10 byte pointer to S60/S6E get # of free blocks for dir drive number number of blocks, 10 number of blocks, hi in buffer for directory mark block as free set buffer pointer erase bit for sector in BAM block already free, then done bit model of BAM set bit X, marker for free set flag for BAM changed increment # of free blocks/track track equal to 18? then skip inc # of free blocks in disk increment number of blocks hi Anatomy of the 1541 Oisk Orive EF87 60 FTS ****************************** EF88 A6 7F LOX $7F EF8A A9 01 LOA #$01 EF8C 90 51 02 STA $0251,X EF8F 60 RTS set flag for 'BAM changed' dri ve number ****************************** EF90 20 F1 EF JSR $EFFI EF93 20 CF EF JSR $EFCF EF96 FO 36 BEO $EFCE EF98 Bl 60 LOA ($60) ,Y 50 E9 EF EOR $EFE9,X EF9A EF90 STA (S60) ,Y 91 60 EF9F 20 88 EF JSR SEF8S EFA2 M 6F LOA $6F EFM Bl 60 LOA (S60),Y EFA6 38 SEC EFA7 E9 01 SBC #$01 EFA9 91 6D STA (S60),Y EFAB A5 80 LDA S80 EFAD CD 85 FE CMP SFE85 FO OB EFBO BEO $EFBO EFB2 BD FA 02 LDA $02FA,X EFR5 DO 03 BNE SEFBA EFB7 DE FC 02 DEC $02FC,X EFBA DE FA 02 DEC S02FA,X EFBD BD FC 02 LOA S02FC,X EFCO DO OC FINE SEFCE EFC2 BD FA 02 LDA $02FA,X EFC5 C9 03 CMP #S03 EFC7 BO 05 BCS SEFCE EFC9 A9 72 LDA #$72 EFCB 20 C7 E6 JSR $E6C7 EFCE 60 RTS mark block as allocated set buffer pointer erase bit for sector in BAM already allocated, then done **********~******************* erase bit for sector :n BAM entry find BAM field for this track EFCF EFD2 EFD3 EFD5 EFD7 EFD8 EFD9 EFDA EFDB EFDD EFDE EFEO EFE2 EFE3 EFE5 EFE8 20 98 85 A5 4A 4A 4A 38 65 A8 A5 29 11 FO 6F 81 6F 81 07 AA B1 60 30 E9 EF 60 JSR TYA STA LDA LSR LSR LSR SEC ADC TAY LDA AND TAX LDA AND RTS SFOll $6F $81 A A A flag = 1 erase bit for block set flag for BAM changed decrement 1I 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 smaller than 37 72, 'disk full' sector divide by 8 S6F byte number in BAM entry sector number $81 #S07 (SfiD) ,Y SEFE9,X 229 bit number in BAM entry byte in BAM erase bit for corresponding sector Anatomy of the 1541 Disk Drive ****************************** EFE9 01 02 04 08 10 20 40 80 powers of 2 ****************************** EFFI A9 FF LOA #$FF EFF3 2C F9 02 BIT $02F9 EFF6 FO OC BEO $F004 EFF8 10 OA BPL $F004 EFFA 70 08 BVS $F004 EFFC A9 00 LOA #$00 EFFE 80 F9 02 STA $02F'9 FOOl 4C 8A 05 JMP $DS8A FOO4 60 RTS write BAM after change ****************************** FOOS 20 3A EF JSR $EF3A FOO8 AO 00 LOY #$00 FOOA 98 TYA FOOB 91 6D STA (S6f),Y FOOD C8 INY FOOE DO FB BNE SFOOB FOIO 60 RTS reset flag write block erase BAM buffer pointer $6D/S6E to BAM buffer erase BAM buffer ** •• *******.*******.*******.*. Fall F013 F014 F016 F017 FOl9 FOIB FOlD FOIF F022 F025 F027 F028 F029 F02B F02C F02E F031 F033 F034 F036 F039 F03B F03E F040 F042 F045 F046 F047 F048 F04A AS 48 AS 48 A6 B5 FO A9 20 20 85 8A OA 85 AA A5 DD FO EB 86 6F 70 7F FF as 74 48 E6 OF FI 6F 70 80 9D 02 OB 70 00 9D 02 FO 20 AS A6 90 OA OA 18 69 85 03 5R FO 70 7F 9B 02 Al 6D LOA PHA LDA PHA LDX LDA BEO LDA JSR JSR STA TXA ASL STA TAX LOA CMP BEO INX STX CMP BEO JSR LOA LDX STA ASL ASL CLC ADC STA $6F S70 $7F $FF,X $F022 #$74 $E648 $FIOF $6F drive number drive zero? 'drive not ready' get buffer number for BAM A $70 S80 S0290,X $F03E $70 S029D,X SF03E SFOSB S70 $7F S029B,X A A #$Al S6D 230 track drive number times 4 Anatomy of the 1541 Oisk Orive F04C F04E F050 F052 F054 F055 F057 F058 F05A A9 69 85 AO 58 85 68 85 60 02 00 6E 00 70 6F LOA AOC STA LOY PLA STA PLA STA RTS 1IS02 #SOO S6E #SOO S70 S6F ****************************** F05B F050 F060 F062 F063 F064 F067 F069 F06B F060 F070 F072 F073 F074 F076 F077 F078 F07A F07C F070 F07E F07F F08l F084 F086 F088 F08A F08B F08C F08E F090 F092 F094 F097 F09A F09C A6 20 A5 AA OA 10 49 29 85 20 AS OA AA AS OA OA 95 AS OA OA A8 Al 99 A9 81 99 Al 02 00 99 F6 99 C8 98 29 03 00 EF' A6 70 A5 80 90 90 02 AO F9 02 DO 03 4C 8A 05 LOX JSR LOA TAX ASL ORA EOR ANO STA JSR LOA ASL TAX LOA ASL ASL STA LOA ASL ASL TAY LOA STA LOA STA INC INY TYA ANO BNE LOX LOA STA LDA BNE JMP F09F FOAl FOM 09 80 80 F9 02 60 ORA #S80 STA S02F9 RTS FOA5 FOA6 FOA9 A8 B9 90 02 E'O 25 TAY LDA S0290,y BEO SFOOO 6F Of FO 7F 9B 02 01 03 70 A5 FO F9 80 99 70 S6F SFOOF S7F dri ve number A $029B,X #SOI #S03 S70 SFOA5 SF9 A S80 A A S99,X S70 A A buffer number track times 4 equal pointer in BAM field (S99,X) S02Al,X #SOO (S99,X) S99,X #S03 SF07F S70 S80 S0290,X S02F9 SF'09F S058A 231 zero in buffer increment buffer pointer track write block Anatomy of the 1541 Disk Drive FOAB FOAC FOAE FOBl FOB3 FOB4 FOBS FOB6 FOB7 FOBB FOBA FOBB FORC FOBD FOBE FOCI FOC3 FOC5 FOCB FOCA FOCB FOCC FOCE FODO 48 A9 00 99 9D 02 AS F9 OA FODI FOD3 FOD4 FOD5 FOD7 FODA FODS FODE AS OA AA A9 9D E8 9D 60 FODF FOEI FOE3 FOES FOE6 FOE7 FOEA FOEB FOED FOEF (,"01"2 FOF4 1"01"5 FOF6 FOF7 FOF9 FOFC FOFD FOFE 1"101 FI03 B5 C9 DO 8A 48 20 AA 10 A9 20 AA 68 OA OA 95 98 OA OA AB B9 81 A9 99 F6 C8 9B 29 DO 60 99 Al 02 99 00 Al 02 99 03 EE 7F 00 9D 02 9D 02 A7 FF 25 HE D2 05 70 C8 Cl fl6 1"9 68 A8 8A 09 80 99 A7 00 OA AA AD 85 FE 95 06 A9 00 PHA LDA STA LDA ASL TAX PLA ASL ASL STA TYA ASL ASL TAY LDA STA LDA STA INC INY TYA AND BNE RTS #$00 $029D,Y $F9 A buffer number times 2 A A $99,x A A $02AI,Y ($99,X) #$00 $02AI,Y $99,X write in buffer increment buffer pointer #$03 $FOBE LDA ASL TAX LDA STA INX STA RTS $7F A LDA CMP ENE TXA PtTA JSR TAX BPL LDA JSR STX PLA TAY TXA ORA STA ASL TAX LDA STA LDA SA7,X #$1"1" SFIOA drive number #$00 $029D,X $029D,X $D28E SFOF2 #$70 SCIC8 SF9 70, • no channel' #S80 $00A7,Y A SFE85 S06,x #$00 18, directory track save 0 232 Anatomy of the 1541 Disk Drive Fl05 FI07 95 07 4C 86 D5 STA S07,X JMP $D586 as sector write hlock FIOA FlOC FlOE 29 OF 85 F9 60 AND #$OF STA $F9 RTS buffer number ****************************** FIOF Flll FIl3 F1l5 FIlii Fll8 A9 A6 DO 18 69 60 06 7F 03 07 LDA LDX BNE CLC ADC RTS drive number #$07 gives 13 for drive 0 ****************************** F1l9 FllC FllD 20 OF Fl AA 60 JSR SFIOF TAX RTS ****************************** FllE Fl21 F123 Fl25 F127 F12A F12D F12F F130 Fl33 F134 F136 F138 Fl3A Fl3C F13F F141 F143 F145 F147 Fl4A F14C F14F F150 F152 F154 F156 F158 F15A F15C F15F F161 F163 F166 20 A9 85 A9 OD 8D A5 48 20 68 85 3E DE 03 6F 01 F9 02 F9 02 6F 11 FO 6F Bl 6D DO A5 CD FO 90 E6 A5 CD DO AE CA 86 A9 85 C6 DO A9 20 C6 DO AE E8 39 80 85 FE 19 lC 80 80 D7 FE El 85 FE 80 00 81 6F D3 72 C8 Cl 80 CA 85 FE JSR LDA STA LDA ORA STA LDA PHA JSR PLA STA LDA BNE LDA CMP REO BCC INC LDA CMP BNE LDX DEX STX LDA STA DEC BNE LDA JSR DEC BNE LDX INX get buffer number for RAM #$06 $7F SF1l8 SDE3E 41$03 S6F #SOI S02F9 S02f'9 S6F buffer number for BAM get buffer number find and allocate free block get track and sector number counter save counter SFOll find BAM field for this track S6F (S6D),Y Sf'173 S80 SFE85 SF15A SF15F S80 S80 SFED? SF12D SFE85 get counter back number of free blocks in track blocks still free? track 18, directory track? yes, 'disk full' smaller, then next lower track increment track number S80 #SOO S81 S6F SF12D #S72 SCIC8 S80 SF12D SFE85 36, highest track number plus one no, continue searching thi~ track 18, directory track decrement save as track number begin with sector number zero decrement counter not yet zero, then continue 72, 'disk full' decrement track number not yet 0, continue in this track 18, directory track increment 233 Anatomy of the 1541 Disk Drive FI67 FI69 F16B F160 Fl6F F171 86 A9 85 C6 DO FO 80 00 81 6F BC E7 STX LDA STA DEC BNE BEO Fl73 Fl75 Fl76 F178 Fl7A Fl7C Fl7F Fl82 Fl8S Fl87 Fl1l9 F18A FIBC FIBF FI9! Fl93 Fl9S Fl98 F19A Fl9D Fl9F FIAI A5 18 65 85 A5 20 8D 80 CS BO 38 AS ED 85 FO C6 20 FO 4C A9 85 20 DO 4C 81 LDA $81 CLC ADC $69 STA $81 LDA $80 JSR SF24B STA $024E STA S024D CMP S8l BCS SF195 SEC LDA S8l SBC S024E STA $81 BEO SF195 DEC S81 JSR SFIFA BEO SFI , then 29, 'disk id mismatch' decrement counter for attempts and try again else 20, 'read error' ****************************** F410 F412 F414 F416 F41S F41A F41B F41D F41E F420 compare with ID1 LDA $16 STA $12 LDA $17 STA $13 LDA #$01 .BYTE $2C LDA #$OB .BYTE $2C LDA #$09 JMP $F969 preserve block header 1D1 and 1D2 preserve ok 29, 'disk id mismatch' 27, 'write error' done ****************************** F423 F425 F427 F429 F42A F42C F42E 1'430 F432 F434 F436 F438 F43A F43D F43F' F'441 F443 A9 85 A5 IS 69 C5 90 E5 R5 A2 86 A2 20 10 85 29 CS 7F 4C 19 02 43 02 43 4D 05 3F FF 93 F3 44 44 01 3E LDA STA LDA CLC ADC OlP BCC SEC STA LDX STX LDX JSR BPL STA AND CMP #$7F $4C $19 #$02 S43 $F432 $43 S4D #S05 S3F #$F'F SF393 SF483 S44 #$01 S3E set buffer ptr for disk control. 240 Anatomy of the 1541 Oisk Orive F445 F447 F449 F44B F440 F44F F451 F453 F455 1"457 F458 F45A F45C F45E F45F F461 F463 F465 F466 F468 F46A F46B F460 F46F F471 F473 F475 F477 F478 F47A F47C F47E F47F F481 F483 F485 F487 F488 F48A 00 AO 81 C5 00 AS C9 FO AO 38 Bl E5 10 i8 65 C4 BO 48 A5 FO 68 C9 90 C9 BO 85 A5 AA 69 85 DO 68 C9 90 C6 10 8A 10 4C 3C 00 32 40 34 45 60 OC 01 03 9C 10'9 BNE LDY LOA CMP BNE LDA CMP BEO LOY SEC LOA SBC BPL CLC AOC CMP RCS PHA LOA BEO PLA CMP BCC CMP BCS STA LOA TAX AOC STA BNE PLA CNP BCC DEC BPL TXA BPL JMP F480 F48F F492 F'494 86 20 A5 4C 3F' 93 F3 45 CA F4 F497 F499 F49A F49C F490 F49F F4Al F'4A3 F4A5 F4A7 A5 48 A5 48 A9 85 A9 85 A9 85 30 32 40 03 43 4C IE 45 14 09 14 OC 10 4C 3F 03 31 05 06 FO 3[< B3 31 24 30 00 31 00 34 $F483 #$00 ($ 32) • Y $40 $,,'483 $45 #$60 $F461 #SOI command code ($ 32) • Y S40 SF461 S43 S4C SF483 S45 SF47E #S09 SF483 #SOC $F483 54C 53F #$03 531 SF483 #$06 SF473 53F 5F43A $F48D 5F99C to job loop STX JSP LOA JNP $3F' 5F393 $45 $F4CA get buffer- numbercommand code continue checking LOA PLA LOA PHA LOA STA LDA STA LDA STA $30 save pointer $30/$31 $31 #$ 24 530 #$00 $31 #$00 $34 pointer $30/$31 to $ 24 241 Anatomy of the 1541 Disk Drive F4A9 F4AC F4AE F4BO F4B2 F4B4 F4B6 F4B8 F4EB F4BO F4BF F4CI F4C3 F4C4 F4C6 F4C7 F4C9 20 AS 85 AS 85 AS 85 20 AS 85 A5 85 68 85 68 85 60 E6 F7 55 18 54 19 53 IA E6 F7 52 17 53 16 31 30 JSR LOA STA LOA STA LOA STA JSR LDA STA LOA STA PLA STA PLA STA RTS $F7E6 $55 $18 $54 $19 $53 $IA $F7E6 S52 $17 $53 S16 $31 get pointer S30/S31 back $30 ****************************** F4CA C9 00 CMP #SOO F4CC FO 03 BEO $F401 F4CE 4C 6E F5 JMP SF56E F401 F404 F406 F407 F40A F4DC F40D F4DF F4El F4E3 F4E4 F4E7 F4EA F4EB F4EO F4FO F4F2 F4F4 F4F6 F4F8 20 50 B8 AO 91 C8 00 AO 50 B8 AO 99 C8 00 20 A5 C5 FO A9 4C F4FB F4FE F500 F502 F504 F505 F507 20 C5 FO A9 2C A9 4C OA F5 FE 01 lC 30 F5 BA FE 01 lC 00 01 F4 EO F8 38 47 05 04 69 F9 E9 F5 3A 03 05 01 69 F9 JSR BVC CLV LOA STA INY BNE LOY BVC CLV LOA STA INY ENE JSR LDA CMP BEO LOA JMP command code for 'read'? yes continue checking command code $F50A $F404 find beginning of data block byte ready? SICOl ($30) ,Y get data byte and write in buffer 256 times SF404 #SBA $F4EI byte ready? $lCOl SOIOO,Y read bytes from SIBA to $IFF $F4EI SFIlEO S38 $47 $F4FB #$04 $F969 equal 7, beginning of data bloc yes 22, 'read error' error termination JSR $F5E9 CMP $3A BEO $F505 LOA #$05 .BYTE S2C LOA #SOl JMP SF969 calculate parity of data block agreement? yes 23, 'read error' ok prepare error message ****************************** F50A 20 10 ~'5 JSR SF510 F500 4C 56 F5 JMP $F556 242 find start of data block read block header wait for SYNC Anatomy of the 1541 oisk Orive ****************************** F510 A5 30 LOA S30 ASL A F512 OA TAX F513 AA F514 B5 12 LOA S12,X F516 85 16 STA S16 B5 13 LOA S13,X F51S F51A 85 17 STA $17 F51C AD 00 LOY #SOO LOA (S32),Y F51E Bl 32 F520 85 18 STA S18 INY F522 C8 LOA (S32),Y F523 Bl 32 F525 85 19 STA S19 F527 A9 00 LOA *SOO F529 45 16 EOR $16 45 17 F52B EOR S17 F520· 45 18 EOR S18 EOR $19 F52F 45 19 F531 85 lA STA SlA F533 20 34 F9 JSR SF934 F536 A2 5A LOX #S5A F53S 20 56 F5 JSR SF556 LOY tt$OO F53B AO 00 F530 50 FE BVC SF'350 F53F B8 CLV F540 AO 01 lC LOA SlCOl 09 24 00 F543 CMP S0024,Y F546 BNE SF54E 00 06 F548 INY C8 F549 CO 08 CPY #S08 F54B 00 FO BNE SF530 F540 RTS 60 read block header drive number F54E F54F F551 F553 decrement counter not yet zero? CA 00 E7 A9 02 4C 69 F9 OEX BNE SF538 LOA #S02 JMP SF969 WI save 102 save get track and sector number from buffer calculate parity for block header and save 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 20, 'read error' ****************************** F556 A9 00 LOA #800 F558 80 05 18 STA S1805 F55B LOA #S03 A9 03 BIT S1805 F550 2C 05 18 F560 10 Fl BPL SF553 F562 2C 00 lC BIT SlCaO F565 30 F6 B~H SF550 F567 AO 10 lC LOA SlCOl F56A B8 CLV F56B AO 00 LOY #SOO F560 60 RTS ****************************** F56E C9 10 CMP #$10 243 wait for SYNC 208 start timer error code timer run down, then 'read error' SYNC signal not yet found? read byte command code for 'write' Anatomy of the 1541 Disk Drive 1"570 1"572 1"0 03 4C 91 1"6 BEO $1"575 JMP $1"691 yes continue checking command code ****************************** 20 E9 ~'5 JSR $F5E9 1"575 F57B STA $3A 85 3A F57A LDA $lCOO AD 00 lC F57D AND #$10 29 10 1"571" BNE $1"586 DO 05 1"581 LDA #$08 A9 08 F583 4C 69 1"9 JMP $1"969 F586 1"589 F58C F58E F590 1"591 1"592 1"594 F596 F599 F59C F59E F5AO F5A3 F5A5 F5A7 F5M F5AB F5AO F5AE F5AF F5Bl F5B3 F5B6 F5B8 F5B9 F5BC F'5BO F5BF F5Cl F5C3 F5C4 F'5C7 F5C8 F5CA 1"5CC F5CF 1"5Dl F5D4 F5D6 f'5D9 F5DC F50E 20 20 A2 50 B8 CA DO A9 8D AD 29 09 8D A9 A2 80 B8 50 B8 CA DO AO B9 50 B8 80 C8 DO B1 50 138 8D C8 DO 50 AD 09 8D A9 80 20 A4 81" 1"7 10 1"5 09 FE FA FF 03 OC IF CO OC 1"1" 05 01 1C 1C 1C 1C FE FA BB 00 01 FE 01 lC 1"4 30 FE 01 lC 1"5 FE OC EO DC 00 03 1"2 lC lC lC 1"5 3F 89 00 00 JSR JSR LOX BVC CLV DEX BNE LDA STA LDA AND ORA STA LDA LOX STA CLV BVC CLV DEX BNE LOY LOA BVC CLV STA INY BNE LDA BVC CLV STA INY BNE BVC LDA ORA STA LOA LOA JSR LDY LDA $F7AF $1"510 #S09 $F58E write data block to disk calculate parity for buffer and save read port B isolate bit for 'wri te protect' not set, ok 26, 'write protect' find block header byte ready? $F58E #SFF $lC03 SlCOC #$lF #$CO port A (write/read head) to to output change PCR to output ~lCOC #$1"1" #$05 SlC01 write $FF to disk 5 times SF5AB as SYNC characters SF5AB #SBB S0100,y $F5B6 bytes SlBB to SlFF to disk SlC01 $F5B3 (S30) , Y $F5C1 write data buffer (256 bytes) S lCOl SF5BF' SF5CA $lCOC #SEO $lCOC #SOO $lC03 Sf'5F2 S3F SOOOO,y 244 byte ready? PCR to input again port A (read/write head) to inpl Anatomy of the 1541 Disk Drive F5El F5E3 F5E6 49 30 99 00 00 4C Bl F3 EOR #$30 STA $OOOO,y JMP $F3Bl ****************************** F5E9 A9 00 LDA #$00 F5EB A8 TAY F5EC 51 30 EOR ($30) ,Y F5EE C8 INY F5EF DO FB BNE $F5EC F5Fl 60 RTS F5F2 F5F4 F5F6 F5F8 F5FA F5FC F5FE F600 F602 F604 F606 F608 F60A F60D F60F F611 F613 F615 F617 F618 F61A F61C F61D F61F F6.21 F622 F624 F627 F629 F62B F62D F62E F630 F632 F633 F635 F637 F639 F63A F63C F63E F63F F641 A9 85 85 85 AS 85 A9 85 85 A9 85 85 20 AS 85 A4 AS 91 C8 AS 91 C8 AS 91 C8 84 20 A4 AS 91 C8 AS 91 CB FO AS 91 C8 AS 91 C8 84 DO 00 2E 30 4F 31 4E 01 31 2F BB 34 36 E6 F7 52 38 36 53 2E 54 2E 55 2E 36 E6 F7 36 52 2E 53 2E OE 54 2E 55 2E 36 El LDA STA STA STA LDA STA LDA STA STA LDA STA STA JSF LDA STA LDY LDA STA INY LDA STA INY LDA STA INY STY JSF LDY LDA STA INY LDA STA INY BEO LDA STA INY LDA STA INY STY BNE #$00 $2E $30 $4F $31 S4E #SOI $31 $2F #$BB S34 $36 $F7E6 $52 $38 $36 $53 (S2E), Y $ 54 ($2E), Y $55 (S2E) ,Y $36 $F7E6 $36 $52 C$2E), Y $53 ($2E) ,Y $F643 S 54 (S2E) ,Y $55 (S2E) , Y $36 $F624 245 convert command code 'write' to 'verify' calculate parity for data I'uffer AnatOlllY of the 1541 Disk Drive F643 F645 F647 F648 F64A F64C F64D F64F F652 F654 F656 F658 F659 F65B F650 F65E F660 F662 F663 F665 F667 F668 F66.A F66C F66E FPO F672 F674 F'676 F678 F67A F67C F67D F67F F681 F683 F685 F688 F68A F68B F68C F68E F690 A5 91 C8 A5 91 C8 84 20 A4 A5 91 C8 A5 91 C8 A5 91 C8 A5 91 C8 84 CO 90 A9 85 A5 85 AO Bl 91 88 DO Bl 91 A2 BD 91 C8 E8 DO 86 60 54 30 55 30 36 E6 F7 36 52 30 53 30 54 30 55 30 36 BB El 45 2E 31 2F BA 30 2E F9 30 2E BB 00 01 30 F7 50 LDA STA INY LDA STA INY STY JSR LDY LOA STA INY LOA STA INY LDA STA INY LDA STA INY STY CPY BCC LDA STA LDA STA LOY LDA STA DEY BNE LDA STA LDX LDA STA INY INX BNE STX RTS $54 (S30),Y $55 (S30), Y S36 SF7E6 536 S52 (S30), Y S53 (530) ,Y 554 (530) ,Y 555 (530),Y $36 #SBB SF64F #S45 $2E S31 S2F iSBA ($30) ,Y ($2E) ,Y SF678 ($30),Y (S2E),Y lISBB $0100,X (S 30) ,Y $F685 $50 ****************************** F691 F693 F695 C9 20 FO 03 4C CA F6 CMP #$ 20 BE(l $F698 JMP SF6CA command code for 'verify'? yes continue checking command code F698 F69R F69D F6AO F6A3 F6A5 20 E9 F5 85 20 20 AO B9 JSR STA JSR JSR LDY LOA calculate parity for data buffer and save 3A 8F F7 OA f'5 BR 00 01 $F5E9 $3A $F78F $F50A #$BB $0100,Y 246 find start of data block data from buffer Anatomy of the 1541 Disk Drive FE F6A8 F6AA F6AB F6AE F6BO F6Bl F6B3 F6B5 F6B7 F6B8 F6BB F6BD F6BE F6CO F6C2 50 B8 4D DO CB DO Bl 50 B8 4D DO C8 CO DO 4C F6C5 F6C7 A9 07 4C 69 F9 01 lC 15 F2 30 FE 01 Ie 08 FD Fl 18 F4 BVC CLV EOR BNE INY BNE LDA BVC CLV EOR BNE INY CPY BNE JMP SF6A8 byte ready? SlCOl $F6C5 compare with data from disk not equal, then eJ:'ror $F6A5 ($30) , Y SF6B5 data from buffer SlCOl $F6C5 compare with data fJ:'om disk not equal, then error #SFD $F6B3 $F4l8 erJ:'oJ:' free termination LDA #$07 JMP $F969 25, 'write error' ****************************** F6CA F6CD 20 10 F5 4e 18 F4 J:'ead block header done JSR $F5l0 JMP $F4l8 ****************************** F6DO F6D2 F6D4 F6D6 F6D8 F6DA F6DC F6DD F6DE F6DF F6EO F6El F6E4 F6E5 F6E6 F6E7 F6E9 F6EB F6ED F6EE F6Fl F6F2 F6F4 F6F5 F6F7 F6F9 F6FB F6FD F6FE F700 F702 A9 00 85 57 85 5A A4 34 A5 52 29 FO 4A 4A 4A 4A AA BD 7F F7 OA OA OA 85 56 A5 52 29 OF AA BD 7F F7 6A 66 57 6A 66 57 29 07 05 56 91 30 C8 A5 53 29 FO 4A LDA STA STA LDY LDA AND LSR LSR LSR LSR TAX LDA ASL ASL ASL STA LDA AND TAX LDA ROR ROR ROR ROR AND ORA STA INY LDA AND LSR #$00 $57 $5A $34 $52 #$FO A A A A isolate hi-nibble and J:'otate to lower nibble as index in table $F77F,X A A A $56 $52 #$OF $F77F,X A $57 A $57 #$07 $56 ($30), Y $53 #$FO A times 8 isolate lower nibble as index in table in buffer increment buffer isolate upper nibble 247 Anatomy of the 1541 Disk Drive F703 F704 F705 F706 F707 F70A F70B F70D F70F F711 F7l3 F714 F7l7 F7l8 F7l9 F71A F7lB F7lD F7lE F720 F722 F724 F725 F727 F729 F72A F72B F72C F72D F72E F731 F732 F733 F735 F737 F738 F739 F73B F73D F73F F741 F742 F745 F746 F747 F749 F74B F74D F74F F751 F752 F753 F754 F755 F756 4A 4A 4A AA BD OA 05 85 A5 29 AA BD 2A 2A 2A 2A 85 2A 29 05 91 C8 A5 29 4A 4A 4A 4A AA BD 18 6A 05 91 C8 6A 29 85 A5 29 AA BD OA OA 29 05 85 A5 29 4A 4A 4A 4A AA 7F F7 57 57 53 OF 7F F7 58 01 57 30 54 FO 7F F7 58 30 80 59 54 OF 7F F7 7C 59 59 55 FO BD 7F' F7 LSR LSR LSR TAX LOA ASL ORA STA LOA AND TAX LDA ROL ROL ROL ROL STA ROL AND ORA STA INY LDA AND LSR LSR LSR LSR TAX LDA CLC ROR ORA STA INY ROR AND STA LDA AND TAX LDA ASL ASL AND ORA STA LDA AND LSR LSR LSR LSR TAX LDA A A A shift to upper nibble as index in table $F77F,X A $57 $57 $53 #$OF SF77F,X A A A A $58 A #$01 S57 (S30) ,Y $54 #$FO A A A A lower nibble as index in buffer increment buffer isolate hi-nibble SF77F,X A $ 58 ($30) ,Y A *S80 $59 $54 #$OF in buffer increment buffer pointer lower nibble as index $F77F,X A A #$7C $59 S59 $55 #$FO A A A A isolate hi-nibble shift to lower nibble as index in table $F77F',X 248 Anatomy of the 1541 Disk Drive F759 F75A F75C F75D F75F F760 F762 F764 F766 F768 F769 F76B F76D F76F F771 F773 F774 F777 F779 F77B F77C F77E 6A 66 6A 66 6A 66 29 05 91 C8 DO A5 85 A5 29 AA BO 05 91 C8 84 60 5A 5A 5A 03 59 30 04 2F 31 55 OF 7F F7 5A 30 34 ROR ROR ROR ROR ROR ROR AND ORA STA INY B:NE LOA STA LDA AND TAX LDA ORA STA INY STY RTS A $5A A $5A A $5A i$03 $59 ($30) ,Y $F76F $2F $31 $55 i$OF in buffer increll1ent buffer pOinter lower nibble as index $F77F ,X $5A ($30) ,Y $34 ****************************** F77F OA DB 12 13 OE OF 16 17 F787 09 19 1A 1B 00 10 IE 15 ****************************** F78F A9 00 LOA *$00 F791 85 30 STA $30 F793 85 2E STA $2E F795 85 36 STA $36 F797 A9 BB LDA i$BB F799 85 34 STA $34 F79B 85 50 STA $50 F790 A5 31 LOA $31 F79F 85 2F STA $2F F7A1 A9 01 LOA iS01 F7A3 85 31 STA $31 F7A5 A5 47 LOA $47 F7A7 85 52 STA $52 F7A9 A4 36 LOY $36 F7AB B1 2E LOA ($2E).,Y F7AO 85 53 STA $53 F7AF C8 INY F7BO B1 2E LOA ($2E),Y F7B2 85 54 STA $54 F7B4 C8 INY F7B5 B1 2E LOA ($2E), Y 85 55 STA $55 F7B7 F7B9 C8 INY 84 36 F7BA STY $36 F7BC 20 00 F6 JSR $F600 F7BF A4 36 LOY $36 F7C1 LDA ($2E) ,Y B1 2E 249 in buffer increment buffer pointer and save Anatomy of the 1541 Disk Drive F7C3 F7C5 F7C6 F7C8 F7CA F7CC F7CD F7CF F7D1 F7D2 F7D4 F7D6 F7D7 F7D9 F7DB F7DD F7DF F7E1 F7E3 85 C8 FO B1 85 C8 B1 85 C8 B1 85 C8 DO A5 85 A9 85 85 4C F7E6 F7E8 F7EA F7EC F7ED F7EE F7EF F7F1 F7F3 F7F5 F7F6 F7F7 F7F9 F7FA F7FC F7FE F800 F802 F804 F806 F807 F808 F809 F80B F80D F80F F811 F812 F814 F816 FS18 F819 F8lA F8lB F8lC A4 B1 29 4A 4A 4A 85 B1 29 OA OA 85 C8 DO A5 85 A4 B1 29 2A 2A 2A 05 85 B1 29 4A 85 B1 29 OA OA OA OA 85 52 11 2E 53 2E 54 2E 55 E1 3A 53 00 54 55 DO F6 34 30 F8 56 30 07 57 06 4E 31 4F 30 CO 57 57 30 3E 58 30 01 59 STA INY BEO LDA STA INY LDA STA INY LDA STA INY BNE LDA STA LDA STA STA JMP LDY LDA AND LSR LSR LSR STA LDA AND ASL ASL STA INY BNE LDA STA LDY LDA AND ROL ROL ROL ORA STA LDA AND LSR STA LDA AND ASL ASL ASL ASL STA $52 $F7D9 ($2E},Y $53 ($2E},Y $54 ($2E) ,Y $55 $F7BA S3A S53 #SOO $54 S55 SF6DO $34 (S30) ,Y #$F8 A A A $56 ($30) , Y #$07 A A $ 57 $F802 $4E $31 S4F ($ 30) , Y lI$CO A A A S57 $57 (S30) , Y #$3E A S58 (S30) , Y #$01 A A A A $59 250 Anatomy of the 1541 Disk Drive F81E F81F F821 F823 F824 F825 F826 F827 F829 F82B F820 F82F F830 F832 F833 F835 F837 F838 F839 F83A F83C F83E F840 F842 F844 F845 F846 F848 F84A F84C F84D F84E F84F F851 F852 F854 F856 F858 F85A F85C F85E F85F F860 F861 F862 F864 F866 FB68 F86A F86C F86D F86F F871 F874 F876 C8 Bl 29 4A 4A 4A 4A 05 85 Bl 29 OA 85 C8 Bl 29 18 2A 2A 29 05 85 Bl 29 4A 4A 85 B1 29 OA OA OA 85 C8 DO AS 85 A4 B1 29 2A 2A 2A 2A 05 85 Bl 29 85 C8 B4 A6 BD 30 FO 59 59 30 OF SA 30 80 01 SA SA 30 7C 5B 30 03 5C 06 4E 31 4F 30 EO 5C 5C 30 IF 5D 34 56 AO F8 A6 57 10 CO F8 INY LOA AND LSR LSR LSR LSR ORA STA LOA AND ASL STA INY LDA AND CLC ROL ROL AND ORA STA LDA AND LSR LSR STA LDA AND ASL ASL ASL STA INY BNE LOA STA LDY LOA AND ROL ROL ROL ROL ORA STA LDA AND STA INY STY LOX LDA LDX ORA ($30), Y jI$FO A A A A $59 $59 ($30), Y jI$OF A $5A ($30),Y #$80 A A 11$01 $5A $5A ($30),Y 1I$7C A A $5B ($30), Y 1$03 A A A $5C $F85A $4E $31 $4F ($30),Y II$EO A A A A $5C $5C ($30),Y #$lF $5D $34 $56 SF8AO ,X $57 $FBCO,X 251 Ana tOllly of the 1541 Disk Drive FS79 FS7B FS70 FSSO FS82 FS85 F8S7 FS89 FS8C FS8E FS91 FS93 FS95 FS9S FS9A FS90 FS9F S5 A6 BO A6 10 S5 A6 BO A6 10 85 A6 BO A6 ID 85 60 52 5S AO 59 CO 53 5A AO 5B CO 54 5C AO 50 CO 55 FS FS F8 FS FS F8 STA LDX LOA LOX ORA STA LOX LOA LOX ORA STA LOX LOA LOX ORA STA RTS S52 S5S SFSAO,X S59 SFSCO ,X S53 S5A SF8AO,X S5B SFSCO,X S54 S5C SFSAO ,X S50 SF8CO,x S55 ****************************** FSM FF FF FF FF FF FF FF FF FSA8 FF 80 00 10 FF CO 40 50 FaBO FF FF 20 30 FF FO 60 70 F8B8 FF 90 AO BO FF 00 EO FF F8CO F8CS F8DO F80S FF FF FF FF FF OS FF 09 FF 00 02 OA FF 01 03 OB FF FF FF FF FF OC OF 00 FF 04 06 OE FF 05 07 FF ****************************** FSEO A9 00 LOA #SOO FSE2 S5 34 STA S34 F8E4 STA S2E 85 2E F8E6 85 36 STA S36 FSE8 A9 01 LDA #SOI F8EA 85 4E STA S4E LDA #SBA F8EC A9 BA S5 4F FSEE STA S4F FSFO A5 31 LOA S31 FSF2 S5 2F STA S2F FSF4 20 E6 F7 JSR $F7E6 F8F7 A5 52 LDA S52 FSF9 85 3S STA S3S FSFE! A4 36 LOY $36 FSFO A5 53 LOA $53 FSFF 91 2E STA ($2E),Y F901 CS INY F902 A5 54 LOA $54 F904 91 2E STA (S2E) ,Y F906 CS INY F907 A5 55 LOA $55 F909 91 2E STA ($2E) ,Y F90B CS INY F90C 84 36 STY S36 F90E 20 E6 F7 JSR $F7E6 252 Anatomy of the 1541 Disk Drive F911 F913 F915 F917 F918 F91A F91C F91E F91F F921 F923 F924 F926 F928 F929 F92B F92D F92F F931 F-933 A5 91 C8 FO A5 91 C8 A5 91 C8 A5 91 C8 DO A5 85 A5 85 60 F934 F936 F938 F93A F93C F93E F940 F942 F944 F946 F948 F94A F94C F94E F950 F953 F955 F957 F959 F9SB F9S0 F95F F961 F964 F966 F968 A5 85 A9 85 A9 85 A5 85 A5 85 A5 85 A5 85 20 A5 85 AS 85 A9 85 85 20 A5 85 60 F969 F96B F96E F970 F972 F975 F978 A4 99 AS FO 20 20 A6 A4 36 52 2E LDY LDA STA INY BEQ LDA STA INY LDA STA INY LDA STA INY BNE LDA STA LOA STA RTS $36 $52 ($ 2E), Y 31 2F 00 31 24 34 39 52 1A 53 19 54 18 55 DO F6 17 52 16 53 00 54 55 00 F6 2F 31 LOA STA LOA STA LDA STA LDA STA LDA STA LDA STA LDA STA JSR LDA STA LDA STA LOA STA STA JSR LOA STA RTS $31 $ 2~' #$00 $31 #$24 $ 34 $ 39 $52 $IA $53 $19 $ 54 $18 $55 $F6DO $17 $52 $16 $S3 3F 00 00 50 03 F2 F5 SF F9 49 LOY STA LDA BEQ JSR JSR LOX $3F $OOOO,y $ 50 $ F'9 7 5 $F5F2 $F98F $49 11 53 2E 54 2E 55 2E El 53 3A 2F 31 $F92B $53 ($2E),Y $54 (S2E),Y $55 ($2E),Y $F90C $53 $3A $2F $31 *SOD $54 $55 SF600 $2F $31 253 get stack pointer back AnatOllly of the 1541 Disk Drive F97A F97B 9A 4C BE F2 F97E F980 F982 F985 F987 F98A F98C F98E A9 85 AD 09 8D A9 85 60 AO 20 00 IC 04 00 IC 3C 48 LDA STA LDA ORA STA LDA STA RTS i$AO $20 $ICOO n04 $ICOO $3C $48 F98F F991 F993 F995 F997 F999 F99B A6 A5 09 85 A9 85 60 3E 20 10 20 FF 48 LDX LDA ORA STA LDA STA RTS $3E $20 #$10 S20 #$FF $48 F99C F99F . F9A2 F9A5 F9A7 F9A9 F9AB F9AD F9AF F9B1 F9B4 F9B6 F9BB F9BA F9BC F9BF F9C1 F9C3 F9C5 F9C8 AD 8D . AD 29 C5 85 FO A9 85 AD FO C9 DO A9 80 FO 85 A9 8D 4C 07 05 00 10 IE IE 04 01 lC FE 15 02 07 00 FE OA 4A 02 FE 2E 02 FA LDA STA LDA AND CMP STA BEO LDA STA LDA BEO CMP BNE LDA STA BEO STA LDA STA JMP $IC07 SlC05 $ICOO #$10 $1E $lE $F9B1 #$01 $IC $02FE $F9CB #$02 $F9C1 #$00 $02FE $F9CB $4A i$02 $02FE $FA2E F9CB F9CD F9CF F9D1 F9D2 F9D4 F9D6 A6 30 A5 A8 C9 DO 4C 3E 07 20 $3E $F9D6 $20 20 03 BE FA LDX BMI LDA TAY CMP BNE JMP F9D9 F9DB F9DD F9DE F9EO F9E2 C6 DO 98 10 29 85 48 ID 04 7F 20 IC IC IC 02 02 TXS JMP $F2BE DEC BNE TYA BPL AND STA turn drive motor off write protect? #$20 $F9D9 SFABE $48 $F9FA $F9E4 #$7F $20 254 Anatomy of the 1541 Disk Drive F9E4 F9E6 F9E8 F9EB F9ED F9FO F9F2 F9F4 F9F6 F9F8 F9FA F9FB F9FD F9FF 29 FO AD29 8D A9 85 A9 85 FO 98 29 DO 4C FA02 6C 62 00 FA05 FA07 FA09 FAOB FAOC FADE FA10 FA12 FA14 FA16 FA18 FA1A FA1C FA1E FA20 FA22 FA24 FA26 FA28 FA2A FA2C FA2E FA30 FA32 FA34 FA37 FA38 A5 10 49 18 69 C5 80 A9 85 A9 85 DO E5 ES 85 A5 85 A9 85 A9 85 A5 10 E6 AE CA 4C 10 12 00 1C FB 00 1C FF 3E 00 20 DC 40 03 BE FA 4A 05 FF 01 64 OA 3B 62 FA 63 12 SE SE 61 5E 60 7B 62 FA 63 4A 31 4A 00 1C 69 FA AND BEO LDA AND STA LDA STA LDA STA REO TYA AND BNE JMP #$10 $F9FA $lCOO #$FB $lCOO #$FF $3E #$00 $20 $F9D6 drive motor on #$40 $FA02 $FARE JMP ($0062) LOA BPL EOR CLC AOC CMP BCS LDA STA LDA STA BNE SBC SBC STA LDA STA LOA STA LDA STA LDA BPL INC LDX OEX JMP #$4A $FAOE #$FF #$01 $64 $FA1C #$3B $62 #$FA $63 $FA2E SSE SSE $61 SSE $60 #$7B $62 #$FA $63 $4A SFA63 $4A $lCOO pointer $62/$63 to $FA3B pointer S62/S63 to $FA7B step counter for head transport increment SFA69 ****************************** FA3B A5 4A LOA S4A FA3D DO EF BNE $FA2E FA3F A9 4E LOA #$4E FA41 85 62 STA S62 FA43 A9 FA LDA #$FA FA4S 85 63 STA $63 FA47 A9 OS LDA #$OS FA49 85 60 STA $60 FA4B 4C BE FA JMP $FABE 255 step counter for head tranFport not yet zero? pointer $62/$63 to $FA4E counter to 5 Anatomy of the 1541 Disk Drive ****************************** FA4E C6 60 DEC $60 BNE $FAFE FASO DO 6C FAS2 AS 20 LDA $20 FAS4 29 BF AND #$BF 85 20 FA56 STA $20 FAS8 LDA #$05 A9 05 85 62 FASA STA $62 FASC A9 FA LDA #$FA FASE 85 63 STA $63 FA60 4C BE FA JMP $FABE ****************************** FA63 C6 4A DEC $4A FA6S LDX $ICOO AE 00 IC FA68 E8 INX 8A TXA FA69 FA6A 29 03 AND #$03 FA6C 85 4B STA $4B FA6E AD 00 IC LDA $lCOO FA7l 29 FC AND #$FC 05 4B FA73 ORA $48 FA7S 8D 00 lC STA $ICOO FA78 JMP SFABE 4C BE FA ****************************** FA7B 38 SEC FA7C AD 07 lC LOA SlC07 FA7F E5 5F SBC $5F FA8l 80 05 lC STA $lCOS FA84 C6 60 DEC $60 FA86 DO OC RNE SFA94 FA88 A5 SE LDA SSE FA8A 85 60 STA S60 FA8C A9 97 STA .$97 FA8E 85 62 STA $62 FA90 A9 FA LOA #$FA 85 63 STA $63 FA92 FA94 4C 2E FA JMP $FA2E decrement counter not yet zero? erase bit 6 pointer $62/$63 to FAOS step counter for head transport stepper motor off decrement counter not yet zero? pointer $62/$63 to $FA97 ****************************** FA97 FA99 FA9B FA9D FA9F FAAI FAA3 C6 DO A9 85 A9 85 DO 61 F9 AS 62 r'A 63 EF DEC RNE LDA STA LDA STA BNE $61 SFA94 .SA5 $62 .$FA $63 $FA94 pointer 562/$63 to $FAA5 ****************************** FAA5 AD 07 lC LDA $IC07 FAA8 CLC 18 FAA9 65 5F ADC $SF FAAB 80 05 IC STA $lC05 256 Anatomy of the 1541 Disk Drive FAAE FABO FAB2 FAB4 FAB6 FAB8 FABA FABC FABE FAC1 FAC3 FAC6 C6 DO A9 85 A9 85 A9 85 AD 29 8D 60 60 E2 4E 62 FA 63 05 60 OC 1C FD OC 1C DEC BNE LDA STA LDA STA LDA STA LDA AND STA RTS decrement counter not yet zero? S60 SFA94 #S4E $62 #SFA 563 #S05 560 51COC #5FD SlCOC pointer $62/S63 to SFA4E counter to 5 erase bit 1 ****************************** FAC? FAC9 FACB FACD FACF FAD1 FAD3 FAD5 FAD? FAD9 FADB FADE FAEO FAE3 FAE5 FAE8 FAEA FAED FAEF FAF2 A5 51 10 2A A6 3D A9 60 95 20 A9 01 95 22 85 51 A9 M 85 4A AD 00 29 FC 8D 00 A9 OA 8D 20 A9 AO 8D 21 A9 OF 8D 22 4C 9C J~IP $51 $FAF5 $3D #$60 $20,X #$01 $22,X S51 #$M $4A SlCOO #$FC SlCOa #SOA $0620 #S40 S0621 #SOF $0622 $F99C FAF5 FAF? FAF9 FAFB FAFD AO D1 FO 91 4C 00 32 05 32 9C F9 LDY CMP BEO STA JMP #$00 (S32), Y SFBOO (532) , Y SF99C FBOO FB03 FB05 FBO? FB09 AD 29 DO A9 4C 00 lC 10 LDA AND BNE LDA $lCOO #SlO SFROC #$08 SFDf'3 05 FBOC FBOF FB12 FB14 FBl? FB1A FBID FB20 20 20 A9 8D 20 20 20 A9 A3 C3 55 01 C3 00 56 40 1C 1C 06 06 06 F9 08 D3 (,'D FD FD lC FD FE F'5 LDA BPL LDX LDA STA LDA STA STA LDA STA LDA AND STA LDA STA LDA STA LDA STA J~IP formatting track number fomatting already in progress drive number flag for head transport set set destination track running track # for format 164 step counter for head tran~port stepper motor on 10 error counter S621/$622 = 4000 initialize track capacity 4000 < capacity < 2*4000 bytes back in job loop to job loop write protect? no 26, 'write protect on' JSR $FDA3 JSR SFDC3 LDA #$55 STA $lC01 JSR $FDC3 JSR SFEOO JSR $F556 LOA #$40 write SFF to disk 10240 times code (S621/$622) times to disk 555 to write head and (S621/S622) times to disk switch to read set timer, find SFF (SYNC) 257 Anatomy of the 1541 Disk Drive FB22 FB25 FB28 FB2A FB20 FB2F FB32 FB35 FB37 FB39 FB3C FB3E FB41 FB43 FB46 FB49 FB4B FB4E FB4F FBSI FB52 FB54 FB55 FBS7 FBS9 00 80 A9 80 A9 80 80 AO A2 2C 30 2C 10 OB OB 62 06 00 07 05 00 00 00 FB 00 FB AD 04 2C 00 10 11 AD 00 OA 10 F5 E8 DO EF C8 DO EC A9 02 4C D3 FBSC FBSE FB60 FB62 FB64 FB67 FB6A FB6C FB6F FB70 FB72 FB73 FB75 FB76 FB78 FB7A 86 84 A2 AO AD 2C 30 AD OA 10 E8 00 C8 00 A9 4C FB70 FB7E FB7F t'B81 FB82 FB84 FB85 FB87 FB88 FB8A FB8C FB8E 38 8A E5 AA 85 98 E5 A8 8S 10 49 A8 18 18 18 18 18 lC lC 18 lC 18 FD 71 72 00 00 04 18 00 IC 11 00 18 FS EF EC 02 03 FO 71 70 72 71 OB FF ORA STA LOA STA LOA STA STA LOY LDX BIT BMI BIT BPL LDA BIT BPL LDA ASL BPL INX BNE INY BNE LDA JMP $180B $180B #$62 $1806 #SOO S1807 S1805 #$00 #SOO SICOO SFB39 SlCOO SFB3E S1804 SlCOO SFB5C $1800 A SFB46 S.FB43 #$02 SFDD3 overflow, then error 20, 'read error' STX STY LDX LDY LOA BIT BMI LOA ASL BPL INX BNE INY BNE LOA JMP S71 S72 #SOO #SOO S1804 SlCOO SFB70 S1800 A SFB67 counter to zero again reset timer 1 interrupt flag SYNC found? yes interrupt-flag register timer flag to bit 7 no, wait until timer run down SFB64 increment counter SFB64 #S02 $FOD3 overflow, then error 20, , read error' $71 difference between counter SEC TXA SBC TAX STA TYA SBe TAY STA BPL EOR TAY timer 1 free running 98 cycles, about 0.1 ms start timer counter to zero SYNC found? no, wait SYNC found? wait for SYNC reset interrupt flag timer SYNC found? not SYNC (SS5)? interrupt flag register shift timer flag timer not run down yet? increment counter $FB43 increment hi-byte of counter $70 and value for SFF-storage $72 bring to $70/S71 $71 SFB97 #SFF difference positive? 258 Anatomy of the 1541 Disk Drive FB8F FB90 FB92 FB93 FB94 FB96 FB97 FB98 FB9A FB9C FB9E FBAO FBA2 FBA3 FBA5 F8A8 FBAB FBAO FBBO FBB3 FBB6 FBB8 FBBA FBBB FBBE FBCO FBC2 FBC3 FBC4 FBC6 FBC7 FBC9 FBCB FBCE FBCF FBDO FB03 FBD4 FBD5 FB08 FBDA FBDO ~'BEO FBE2 FBE5 FBE7 FBE9 FBEA FBEB FBEE FBFO FBFl FBF2 8A 49 FF AA E8 DO C8 98 DO EO 90 06 26 18 A5 60 8D A5 6D 80 4C A2 AO B8 AD 10 50 B8 E8 DO C8 DO 01 04 04 18 70 71 70 21 21 71 22 22 OC 06 06 06 06 FB 00 00 TXA EOR #SFF TAX INX BNE SFB97 INY TYA BNE SFB9E CPX *S04 BCC SFBB6 ASL $70 ROL S71 CLC LOA S70 AOC S0621 STA S0621 LDAS71 AOC S0622 STA S0622 JMP SFBOC F2 A9 03 4C 03 FO LOX LOY CLV LOA BPL BVC CLV INX BNE INY BNE LOA JMP 8A OA 80 98 2A 80 A9 20 80 A9 80 A6 AO 98 18 6D 90 C8 C8 CA TXA ASL STA TYA ROL STA LOA AND STA LDA STA LOX L.OY TYA CLC AOC BCC INY INY DEX 00 1C OE 59 F5 25 06 24 BF OB OB 66 26 43 00 06 18 18 06 26 06 01 calculate abs. val of difference difference less than 4 yes * 0.1 ms double difference add to 4000 repeat until diff < 4 * 0.1 ms *$00 #$00 counter to zero SlCOO $FBCE SFBBB SYNC? no byte ready? SFBBB increment counter SFBBB #$03 SFD03 overflow, then error 21, read error A S0625 double counter A S0624 *SBF S180B S180B #S66 S0626 S43 #$00 and to S624/$625 as track cap. 102 number of sectors in this track S0626 SFBn 259 Anatomy of the 1541 Disk Drive FBF3 FBFS FBF7 FBF8 FBFA FBFB FBFE FCOO FC03 FC04 FCOS FC07 FC08 FCOA FCOB FCOE FC10 FC12 DO 49 38 69 18 6D BO CE AA 98 49 38 69 18 6D 10 A9 4C FC1S FC16 FC17 FCl9 FCIA FCIC FCIE FCIF FC21 FC22 FC24 FC27 FC29 FC2B FC2D FC30 FC31 FC33 FC36 FC38 FC3B FC3D FC3F FC41 FC44 FC45 FC46 FC49 PC4C FC4D FC4P FC52 F'CS3 PC55 PC58 FC59 A8 SA A2 38 E5 BO 88 30 E8 DO 8E EO BO A9 4C 18 65 8D A9 8D AO A6 A5 99 C8 C8 AD 99 C8 A5 99 C8 B5 99 C8 B5 F5 FF 00 25 06 03 24 06 FF 00 24 06 05 04 D3 FD 00 43 03 03 F'5 26 06 04 05 05 D3 FD 43 27 06 00 28 06 00 3D 39 00 03 28 06 00 03 51 00 03 13 00 03 12 BNE EOR 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 BNE STX CPX BCS LDA JMP CLC ADC STA LDA STA LDY LDX LDA STA INY INY LDA STA INY LDA STA INY LDA STA INY LDA calculate # of bytes $FBEA #$FF #$00 $0625 $FC03 $0624 #$FF #$00 $0624 $FC15 #$04 $FDD3 resul t in A/X 22, 'read error' #$00 total divided by number of sectors ($43) $43 $FC21 SFC24 $FCI9 $0626 #$04 $FC30 #$05 $FDD3 compare no. of bytes per interva with minimum value ok 23, 'read error' remainder of division plus number of sectors save $43 $0627 11$00 $0628 #$00 $3D $39 $0300,y counter for sectors counter 10 drive number constant 8, marker for heacer in buffer $0628 $0300,y sector number in buffer $51 $0300,y track number in buffer $13,x $0300,y ID 2 $12,X ID 1 260 in huffer Anatomy of the 1541 Disk Drive FC5B FC5E FC5F FC61 FC64 FC65 FC68 FC69 FC6B FC6E FC7l FC74 FC77 FC7A FC7D FC80 FC82 FC84 FC85 FC86 FC87 FC88 FC8B FC8C FCBE FC90 ~'C92 FC95 FC96 FC97 FC98 FC9B FC9E FCAO FCA2 FCA5 FCA7 FCAA FCAC FCAE FCBl FCB3 FCB6 FCB8 FCBA FCBB FCBC FCBE FCCO FCC2 FCC4 FCC5 FCCS FCCS FCCC 99 C8 A9 99 C8 99 C8 A9 59 59 59 59 99 EE AO C5 90 98 48 E8 8A 90 EB 00 A9 85 20 68 A8 88 20 20 A9 85 20 85 20 A9 85 20 A9 8D A2 50 88 CA 00 A2 00 03 OF 00 03 00 03 00 FA FB FC FD F9 28 28 43 BB 02 02 02 02 02 06 06 00 05 FA 03 31 30 FE E5 F5 05 31 E9 3A 8F 00 32 OE FF 01 05 FE FD FD F5 F'7 FE lC FA OA A4 32 50 FE B8 B9 00 03 SO 01 lC C8 CA STA INY LOA STA INY STA INY LOA EOR EOR EOR EOR STA INC LOA CMP BCC TYA PHA INX TXA STA INX BNE LOA STA JSR PLA TAY OEY JSR JSR LOA STA JSR STA JSR LOA STA JSR LOA STA LOX BVC CLV DEX BNE LOX LOY BVC CLV LOA STA INY S0300,Y in buffer #$OF $0300,y 15 in buffer $0300,y 15 in buffer #800 $02FA,Y $02FB,Y S02FC,Y S02FD,Y $02F9,Y $0628 $0628 843 $FC3F generate checksum increment counter counter compare with no. of sectors smaller, then continue $0500,X SFC88 lI$03 $31 SFE30 buffer pointer to $300 $FOE5 $FOF5 lI$05 $31 $F5E9 $3A $F78F #$00 $32 $FEOE #$FF SlCOl #$05 SFCB8 copy buffer data copy data in buffer to write head write $FF 5 times byte ready SFCB8 #$OA $32 $FCC2 10 times buffer pointer byte ready? $0300,y $lC01 data from buffer write buffer pointer to 8500 calculate parity for data buffer and save 10 data written? DEX 261 Anatomy of the 1541 Disk Drive FCCD ~~CCF FCD1 FCD3 FCD4 FCD6 FCD9 FCDA FCDC FCDE FCEO FCE2 FCE3 FCE6 FCE7 FCE9 FCEB FCED FCEE FCFl FCF4 FCF5 FCI-'7 FCF9 FCFB FCFC FCFE FOOl FD02 FD04 f'D06 FD09 FDOB FDOC FDOF FDIO FD12 FD14 FD15 FD17 FD19 FDIC FDIE FD20 FD21 FD23 FD24 FD27 FD29 FD2C FD2E FD30 FD32 FD34 FD36 DO A2 50 B8 A9 8D CA DO A9 A2 50 B8 80 CA DO A2 50 B8 BD 80 E8 DO AO 50 B8 Bl 8D C8 DO A9 AE 50 B8 8D CA DO AS 18 69 85 CE DO 50 B8 50 B8 20 A9 8D A9 85 A9 85 AS 80 F3 09 FE 55 01 lC F5 FF 05 FE 01 lC F7 BB FE 00 01 01 lC F4 00 FE 30 01 lC F5 55 26 06 FE 01 lC F7 32 OA 32 28 06 93 FE FE 00 FE C8 23 06 00 30 03 31 43 28 06 BNE LOX BVC CLV LDA STA DEX BNE LDA LDX BVC CLV STA DEX BNE LDX BVC CLV LOA STA INX BNE LDY BVC CLV LDA STA INY BNE LOA LOX BVC CLV STA DEX BNE LOA CLC ADC STA DEC BNE BVC CLV BVC CLV JSR LDA STA LDA STA LOA STA LDA STA SFCC2 #S09 SFCD1 9 times byte ready? #S55 SlCOl S55 write SFCDI #SFF #S05 SFCEO 9 times? SFF 5 times byte ready? SlC01 to wri te head SI-'CEO #SBB SFCEB SOlOO,X SlC01 area SIRB to SIFF save SFCEB #SOO SFCF9 byte ready? (S30), Y SlCOl 256 bytes of data write byte to disk SFCF9 #$55 S0626 SFD09 S55 (S626) times SlCOl write SFD09 S32 jlSOA S32 S0628 SFCBl SFD1E decrement sector number $FD21 byte ready? SFEOO HC8 $0623 #$00 S30 #S03 $31 S43 S0628 switch to reading 200 plus 10 byte ready? buffer pointer to $200 number of sectors per track 262 Anatomy of the 1541 Disk Drive FD39 FD3C FD3E FD40 FD42 FD43 FD46 FD48 FD4A FD4B F'D4C FD4E FD4F FDSI FDS3 FDS5 20 A2 AO 50 B8 AD Dl DO C8 CA DO 18 A5 69 85 4C FD58 FDSB FD5D FD5F 56 F5 OA 00 FE SF556 #$OA #SOO SFD40 wait for SYNC 10 data SlCOl (S30) ,Y SFD58 read byte compare with data in buffer not equal, error 30 OA 30 62 FD JSK LDX LDY BVC CLV LDA CMP BNE INY DEX BNE CLC LDA ADC STA JMP CE DO A9 4C 23 06 CF 06 D3 FD DEC BNE LDA JMP S0623 SFD2C #S06 SFDD3 decrement counter for attempts not yet zero? else error 24, Iread error l FD62 FD65 FD67 FD69 FD6A FD6D FD70 FD72 FD73 FD7S FD77 FD79 FD7A FD7D FD80 FD82 FD83 FD84 FD86 FD89 FD8B FD8D FD8F FD91 FD93 20 AO 50 B8 AD D9 DO C8 DO A2 50 B8 AD D9 DO C8 CA DO CE DO E6 A5 C9 BO 4C 56 F5 BB FE SF556 #SBB SFD67 wait for SYNC SlCOI S0100,y $FDS8 read byte compa re with buffer contents not equal, error SFD67 #$FC $FD77 next byte SlCOl S0500,y $FD58 read byte compare wi th buffer contents not equal, then error 28 06 AE 51 51 24 03 9C F9 JSR LDY BVC CLV LDA CMP BNE INY BNE LDX BVC CLV LDA CMP BNE INY DEX BNE DEC BNE INC LDA CMP BCS JMP FD96 FD98 FD9A FD9C FD9E FDAO A9 85 A9 85 A9 4C FF 51 00 50 01 69 F9 LDA STA LDA STA LDA JMP 01 lC 30 OE F2 01 lC 00 01 E6 F2 FC l"E 01 lC 00 OS D6 F'l byte ready? $FD40 S30 #$OA S30 $FD62 increment pointer by 10 byte ready? byte ready? next byte $FD77 S0628 $F'D39 $Sl $51 #S24 SFD96 $F99C decrement sector counter not yet zero? increment track number compare with 36, highest trkjf +1 greater, then formatting done continue #SFF S51 #SOO S50 #$01 SF969 track number to $FF ok 263 Anatomy of the 1541 Oisk Orive ****************************** FDA3 FDA6 FDA8 FDAA FDAD FDAF FDB2 FOBS FDB7 FDB9 FOBB FDBC FDBD FDBF FDCO FDC2 AO 29 09 80 A9 8D 80 A2 AO 50 B8 88 DO CA DO 60 OC IF CO OC FF 03 01 28 00 FE IC IC IC IC FA F7 LOA AND ORA STA LOA STA STA LOX LOY BVC CLV DEY BNE DEX BNE RTS $ICOC #$lF #$CO $ICOC #$FF $lC03 $ICOl #$28 #$00 $FDB9 switch PCR to writing port A(read/write head) to outp\ write $FF to disk 40 byte ready? $FD89 $FD89 ****************************** FDC3 FDC6 FOC9 FDCB FOCC FOCD FOCF FOOO F002 AE AC 50 B8 CA 00 88 10 60 21 06 22 06 FE FA F7 LOX LOY BVC CLV DEX BNE DEY BPL RTS $0621 $0622 $FDC9 AO 84 C8 84 4C F'F 51 50 69 F9 LDY STY INY STY JMP read/write ($621/$622) times byte ready? $FDC9 $FOC9 ****************************** FD03 CE 20 06 DEC $0620 FDD6 FO 03 BEO $FDDB FDDS 4C 9C F9 JMP $F99C FDDB FDDD FDDF FDEO FDE2 write $FF 10240 times attempt counter for formatting decrement number of attempts zero, then error continue #SF'F $51 flag for end of formatting $50 $f'969 error termination ****************************** FDE5 FDE8 FDEB F'DEC FDEE FDFl FDF4 B9 99 88 DO AD 8D 60 00 03 45 03 F7 00 03 45 03 LDA STA DEY BNE LDA STA RTS $0300,y $0345,Y copy buffer contents $FDES $0300 $0345 ****************************** FDFS FDF7 FDFA FDFC FDFD AO B9 91 88 10 44 BB 01 30 F8 LOY LDA STA DEY BPL #$44 $OlBB,Y ($30),Y $FDF7 264 SlBB to $lFF write in buffer $30/$31 Anatomy of the 1541 Disk Drive FDFF 60 RTS ****************************** FEOO AD OC lC LDA SlCOC FE03 09 EO ORA jl$EO FE05 8D OC lC STA SlCOC FE08 A9 00 LDA #SOO FEOA 80 03 lC STA SlC03 FEOD 60 RTS ****************************** FEOE AD OC lC LDA SlCOC 29 IF FEll AND flSlF 09 CO FEl3 ORA jlSCO FE15 80 OC lC STA $lCOC FE18 A9 FF LOA jI$FF 80 03 lC FEIA STA $lC03 FEID A9 55 LDA #$55 FElF 80 01 lC STA $lCOI FE22 A2 28 LDX #$28 FE24 AO 00 LDY #$00 50 FE FE26 BVC $FE26 FE28 B8 CLV FE29 88 DEY FE2A DO FA BNE $FE26 FE2C CA DEX FE2D DO F7 BNE $FE26 FE2F 60 RTS ****************************** FE30 A9 00 LOA #$00 FE32 85 30 STA $30 FE34 85 2E STA $2E FE36 85 36 STA $36 FE38 A9 BB LOA #$BB FE3A 85 34 STA $34 FE3C LOA S31 A5 31 FE3E 85 2F' STA $2F A9 01 FE40 LOA #$01 FE42 85 31 STA $31 FE44 A4 36 LDY S36 FE46 B1 2E LOA ($2E), Y FE48 85 52 STA $52 FE4A C8 INY Bl 2E FE4B LOA ($2E), Y 85 53 STA S53 FE4D FE4F C8 INY FE50 LDA ($2E) ,Y B1 2E FE52 85 54 STA S54 ~'E54 C8 INY FE55 B1 2E LOA (S2E) ,Y FE57 85 55 STA S55 FE59 C8 INY FO 08 FE5A BEO $FE64 FE5C 84 36 STY $36 265 switch to reading switch PCR to reading port A to input write S55 10240 times switch PCR to writing port A to output (write head) %01010101 to port A (write head) byte ready for write electronics 10240 times Anatomy of the 1541 Disk Drive FE5E FE61 02 DO F6 4C 44 FE JSR $F6DO FE64 4C DO F6 JMP $F6DO '****************************** FE67 FE68 FE69 FE6A FE6B FE6C FE6F FE7l FE73 FE76 FE79 FE7A FE7C FE7F FE80 FEBI FE82 FE83 FE84 48 8A 48 98 48 AD 29 FO 20 AD OA 10 20 68 A8 68 AA 68 40 00 18 02 03 53 E8 00 Ie 03 BO F2 PHA TXA PHA TYA PHA LOA AND BEQ JSR LOA ASL BPL JSR PLA TAY PLA TAX PLA RTI interrupt routine save registera $1800 *$02 $FE76 $E853 $lCOD A $FE7F $F2f\0 interrupt from serial bus no serve serial bus interrupt from timer I? no IRQ routine for disk controller get register 'back ****************************** 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, disk nam. ***********.****************** FE89 56 49 44 40 42 55 FE8F 50 26 43 52 53 4E table of command words 'V', 'I',)'D', 'M', 'B', 'u' 'p'., '&', 'C', 'R', IS', 'N' **************************'**** lo-bytes' of command addresses FE95 84 05 Cl F8 IB 5C FE9F 07 A3 FO 88 23 00 ****************************** hi-bytes of command addresses FEAI ED DO C8 CA CC CB FEA7 E2 E7 C8 CA C8 EE ****************************** FEAD 51 DO lC 9E lC bytes for syntax check ****************************** file control methods FEB2 52 57 41 40 ******************.************ FEB6 44 53 50 55 4C ****************************** FEBB 44 53 50 55 52 file types 'D', 'sot, 'P', 'u', 'L' names of file types 1st letters '0', 'S', 'P', 266 'U'. 'R' Anatomy of the 1541 Disk Drive FECO 45 45 52 53 45 FEC5 4C 51 47 52 4C 2nd letters 'E', 'E', 'R', 'S', 'E' 3rd letters 'L', '0', 'G', 'R', 'L' ****************************** FECA 08 00 00 ****************************** FECD 3F 7F BF FF roasks for bit command ****************************** FED1 11 12 13 15 number of sectors per track 17, 18, 19, 21 ****************************** FED5 4A FED6 04 FED7 24 FED8 IF 19 12 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 ****************************** FEDB 01 FF FF 01 00 ****************************** FEEO 03 04 05 06 07 control bytes for head position addresses of buffers high bytes ****************************** FEE5 07 OE ****************************** FEE7 6C 65 00 JMP ($0065) for UI command ****************************** FEEA 8D 00 lC STA $lCOO 8D 02 IC FEED STA $IC02 FEFO 4C 7D EA JMP $EA7D for diagnostic routine turn LED on port to output back to diagnostic routine ****************************** FEF3 8A TXA FEF4 A2 05 LOX #$05 FEF6 CA DEX FEF7 DO FD BNE $FEF6 FEF9 AA TAX FEFA 60 RTS delay loop for serial bus ****************************** data output to serial bus CLOCK OUT hi DATA OUT 10 FEFB FE FE 20 AE E9 4C 9C E9 JSR SE9AE JMP $E99C ****************************** FFOI AD 02 02 LOA $0202 FF04 C9 2D CMP #S2D FF06 FO 05 BEC) $FFOD FF08 38 SEC FF09 E9 2B SBC #$2B FFOB DO OA BNE SFEE7 267 about 40 microseconds ur vector '-' '+' indirect jump over ($65) Anatomy of the 1541 Disk Drive FFOD FFOF 85 23 60 STA $23 RTS ****************************** FFIO AA •• , FFEI ••• AA ****************************** FFE2 52 53 52 AA FFE6 C6 CB 8F F9 ****************************** FFEA FFEC FFEE FFFO FFF2 FFF4 FFF6 FFFB FFFA SF 97 00 03 06 09 OC OF 01 CD CD 05 05 05 05 05 05 FF' USER vectors UA, Ul, $CD5F UB, U2, $CD97 UC, U3, $0500 UD, U4, $0503 UE, U5, $0506 UF, U6, $0509 UG, U7, $050C UH, UB, $050F UI, U9, $FFOI (NMI vector not used) ****************************** FFFC OA EA FFFE 67 FE 268 hardware vectors $EAAO RESET and UJ (U:) vectc $FE67 IRQ vector Anatomy of the 1541 Disk Drive Chapter 4: 4.1 Programs and Tips for the 1541 Disk Drive utility Programs 4.1.1 Displaying all File Parameters The directory contains several important pieces of information about each file. Some information is not kept in the directory, such as the starting address of a program. These and other file parameters can be easily found ard 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 : SEO : PRG : USR : REL : File closed? File protected? Allocated blocks Side-sector blocks Data blocks Records Start address X X X : Free blocks, disk : Allocated bl. disk : X X X X X X X X X X X X X X X X X X X X X X X X x X 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 - Track of the actual block of the file entry in the directory S - Sector of the actual block of the file entry in the directory FL - Flag, set if the file name read from the diskette does not agree with the searched-for file TY - File type of the given file (byte 0 of the entry) 269 Anatomy of the 1541 Disk Drive FT - nybble of the file type (bits 0-3), contains the actual file type LB - Low byte of the starting address HB - High byte of the starting address BL - Number of allocated blocks in the file RL - Record length of a relative file DT - Track of the first data block of a program file, which contains the starting address DS - sector of the first data block of a program file SA - Starting address of a program file BF - Number of free blocks on a disk BA - Number of allocated blocks on a disk BS - Number of side-sector blocks in a relative file RC - Number of records in a relative file String variables F$ FF$FT$CL$- Name of the file to search for Contains the actual file name 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") RES- contains CHR$(l8), REVERSE ON RA$- contains CHR$(l46), REVERSE OFF Program Documentation: 110 120 210 250 280 500 540 600 620 640 - Set the color code of the screen 200 Program heading 230 Asks if the names should be listed out. sets flag FL to 1 and executes the routine at 280-490. no Input the filename. Asks for new input if the filename if greater than 16 characters. 490 Reads the file name from the directory and either displays it (FL=l) or compares it to the desired filename. 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. 590 Checks the file type and saves the text in FT$, and checks for invalid file type. 610 Checks bit 7 of the file type byte (file closed?) and saves the result in CL$. 630 Checks bit 6 of the file type byte (file protected?) and saves the result in PR$. 690 Reads the number of allocated blocks in the file from bytes 28 and 29 of the file entry and saves it in BL. 270 Anatomy o£ the 1541 Disk Drive 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. 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. BASIC Listing of the program: 100 110 120 130 140 150 160 170 180 200 210 220 230 240 250 260 270 280 290 300 310 320 325 330 340 350 360 370 380 390 CLR POKE 53280,2:POKE5328l,2:PRINTCHRS(158);CHR$(147); PRINT TAB(6);"===========================" PRINT TAB(6) ;"DISPLAY ALL FILE PARAMETERS" PRINT TAB(6);"===========================" PRINT:PRINT PRINT"WITH THIS PROGRAM, ALL PARAMETERS OF A" PRINT"FILE CAN BE OUTPUT TO THE SCREEN OR TO" PRINT"A PRINTER AT YOUR OPTION." PRINT:PRINT PRINT"LIST FILENAMES (YIN)?" GETX$:IFXS<>"Y"ANDX$<>"N"THEN220 IF XS="Y"THENFL=1:GOSUB280 FL=O INPUT"NAME OF THE FILE: ";FS IFLEN(F$)<=16THEN280 PRINT"FILENAME TOO LONG!":GOT0250 OPEN 15,8,15,"IO":OPEN2,8,2,"I" T=lB:S=l PRINTI15,"B-R";2;0;T;S PRINTI15,"B-P";2;0 GETI2,X$:IFXS=""THENXS=CHR$(0) T=ASC(X$) GETX$:IFX$=""THENX$=CHR$(O) S=ASC(X$) FORX=OT07 PRINT#15,"B-P";2;X*32+5 FF$="" FOR¥=OT015 GETI2,X$:IFX$=""THENX$=CHR$(0) 271 Anatomy of the 1541 Disk Drive 400 410 420 430 440 450 460 470 4BO 4B5 490 500 510 520 530 540 550 560 570 5BO 590 600 610 620 630 640 650 660 670 680 690 700 710 720 730 740 750 760 770 780 790 800 BI0 820 830 840 850 860 B70 8RO 890 900 910 920 930 IF ASC(XS)=160THEN430 FFS=FFS+X$ NEXT Y IFF$=FFSTHEN490 IFFLTHENPRINTFFS NEXT X IF T=O THEN 4BO GO TO 300 CLOSE2:CLOSEI5 IFFL=OTHENPRINT"FILENAME NOT FOUND!":GOT0210 IFFLTHENRETURN PRINTI15,"B-P";2;X*32+2 GETi2,X$:IFX$=""THENX$=CBRS(0) TY=ASC(XS) FT=TYAND15 IFFT=OTHENFT$="DELETED" IFFT=lTHENFT$="SEOUENTIAL" IFFT=2THENFTS"'''PROGRAM" IFFT=3THENFT$="USER" IFFT=4THENFT$="RELATIVE" IFFT>4THENPRINT"INVALID FILE TYPE!":GOT0200 IFTYAND128THENCLS"'''YES'':GOT0620 CLS="NO" IFTYAND64THENPR$="YES":GOT0640 PRS="NO" PRINTI15,"B-P";2;X*32+30 GET.2,X$:IFXS=""THENXS-CHRS(0) LB"'ASC(X$) GET,2,X$:IFX$=""THENX$-CHRS(0) HB=ASC(X$)*256 BL=LB+HB IFFT<>4THEN740 PRINTI15,"B-P";2;X*32+23 GETi2,XS:IFXS=""THENXS=CHR$(0) RL=ASC(X$) IFFT<>2THENB90 PRINTI15,"B-P";2;X*32+3 GETi2,X$:IFX$=""THENX$-CHR$(0) DT=ASC (X$) GETI2,X$:IFX$-""THENX$=CHR$(0) DS=ASC(X$) OPEN3,8,3,"," PRINT'15,"B-R";3;0;DT;DS PRINTI15,"R-P";3;2 GET#3,X$:IFX$=""THENX$=CHRS(0) LB=ASC(X$) GET.3,X$:IFX$=""THENX$=CHR$(0) HR=ASC(X$)*256 SA=LR+HB CLOSE3 PRINTi15,"R-R";2;0;18;0 BF=O FORI-4TOI40STEP4 IFI-72THEN960 PRINTi15,"B-P";2;I 272 Anatomy of the 1541 Disk Drive 940 GET#2,XS:IFX$=""THENX$=CHRS(O) 950 BF=ASC(X$)+BF 960 NEXT 980 BA=664-BF 990 IFFT<>4THENl040 1010 BS=BL/12l:IFBS<>INT(BS)THENBS=INT(BS+1) 1020 RC=INT«(BL-BS)*254)/RL) 1040 PRINTCHRS(147);"SCREEN OR PRINTER (S/P)?" 1050 GETXS:IFXS<>"S"ANDXS<>"P"THENl050 1060 RES=CHRS(18):RA$=CHRS(146) 1070 IFXS="S"THENOPENl,3:PRINTI1,CHR$(147) 1080 IFXS="P"THENOPENl,4 1090 PRINT'l,"FILE PARAMETERS ";RE$;FS;ROS 1100 PRINT#l,"------------------------------------" 1110 PRINTil,"FILE TYPE: ";RES ;FT$ ;RAS :PRINTjll 1120 PRINTil,"FILE CLOSED: ";RE$;CL$;RAS:PRINT'l 1130 PRINTi1,"FILE PROTECTED: ";RE$;PRS;RA$:PRINTll 1140 PRINTil,"ALLOCATED BLOCKS: ";RES;BL;RAS:PRINTll 1150 IFFT<>4THEN1200 1160 PRINTJI 1, "RECORD LENGTH: ";RES;RL;RA$:PRINTil 1170 PRINTil,"SIDE-SECTOR BLOCKS: ";RES;BS;RAS:PRINTII 1180 PRINTl1,"DATA BLOCKS: ";RE$;BL-BS;RA$:PRINTil 1190 PRINTi1,"RECORDS: ";RE$;RC;RA$:PRINTjll n: 1200 IFFT=2THENPRINTi1,"START ADDRESS: RES;SA;RAS:PRINTil ";RES;BF;RA$:PRINTU 1210 PRINTi1,"FREE BLOCKS (DISK): 1220 PRINTil,"ALLOCATED BLOCKS (D):";RE$;BA;RA$:PRINTII 1230 CLOSEI 1240 PRINT"MORE (Y/N)?" 1250 CLOSE2:CLOSE15 1260 GETX$:IFX$<>"Y"ANDX$<>"N"THEN1260 1270 IFXS="Y"THEN100 4.1.2 Scratch-protect Files - File Protect As already mentioned, it is possible to protect files on the VIC-IS4l 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 * unprotect files * erase files This program can delete protected files as well as unprotected files. If you wish to delete a protected file, 273 Anatomy of the 1541 Disk Drive 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. List of variables: OF FL FT T S TT SS FFS F$ - Flag, set in the routine "read/search file" if the desired filename is found - Set i f the routine "read/search file" is only to be used for listing files - variable for storing the filetype Track of the actual block of the file entry - Sector of the actual block of the file entry - Track, in which the file entry block of the desired file is found - Sector, in which the file entry block of the desired file is found . - last filename read from the directory - filename to search for Program Documentation: 100 Set the screen color 110 - 230 Program header and option menu 240 - 260'Read the menu choice and call the appropriate subroutine 270 Back to the option menu 280 - 350 Subprogram "list all files" 310 Erase screen 320 Set flag FL to list files in the subroutine "read/search file" 350 Reset the flag and jump back 360 - 600 Subroutine "protect file" 390 Call subroutine "input filename" 400 Call the subroutine "read/search file" 410 - 450 Test if the file is found 460 - 480 Read file type and store in FT 490 - 500 Test if the file is already protected 510 Protect file (bit 6 to 1) 520 - 550 Transfer the file type to the buffer and write the block to disk 560 Close the channel 570 - 600 Message "File protected" and jump back 610 - 850 Subroutine "unprotect file" 640 Call subroutine "input filename" 650 Call subroutine "read/search file" 660 - 700 Test if file is found 710 - 730 Read file type and store in FT 740 - 750 Test if the file is already unprotected 760 Unprotect the file (bit 6 to 0) 770 - 800 Transfer the file type to the buffer and write the block to the disk 810 Close the file 820 - 850 End the subroutine 274 Anatomy of the 1541 Disk Drive 860 -1170 890 900 910 - 950 960 - 980 990 1000-1030 1040-1060 1070 1080-1110 1120 1130 1140-1170 1190-1560 1220 1230-1240 1250-1320 1330 1340-1350 1360-1390 1400-1530 1540-1560 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 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 variab1e~ 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. BASIC Listing of the Program: 100 110 120 130 140 150 160 180 190 200 210 220 230 240 250 260 270 280 290 POKE 53280,2:POKE53281,2:PRINTCHR$(158);CHR$(147); PRINTTAB(8);"===================-===" PRINTTAB(8);"ERASE AND PROTECT FILES" PRINTTAB(8);"=======================" PRINT:PRINT PRINT"WITH THIS PROGRAM, FILES CAN BE" PRINT"PROTECTED, ERASED, AND UNPROTECTED" PRINT:PRINT PRINTTAB(6);" -1- LIST ALL FILES":PRINT PRINTTAB(6);" -2- PROTECT A FILE":PRINT PRINTTAB(6);" -3- UNPROTECT A FILE":PRINT PRINTTAB(6);" -4- ERASE A FILE":PRINT PRINTTAB(6);" -5- END THE PROGRAM":PRINT GETX$: I FX$= ''''ORVAL (X$ ) (lORVAL( X$) >5THEN240 IFVAL(X$)=5THENEND ONVAL(X$)GOSUB280,360,610,860 GaTO 100 REM -------------REM LIST ALL FILES 275 Anatomy of the 1541 Disk Drive 300 310 320 330 340 350 360 370 380 390 400 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640 650 660 670 680 690 700 710 7 20 730 740 750 760 770 780 790 800 810 820 830 840 REM -------------PRINTCHR$(147) FL=I:GOSUBI190 PRINT:PRINT"RETURN FOR MORE" INPUTX$ FL=O: RETURN REM -------------REM PROTECT A FILE REM -------------GOSUB1580 GOSUB1l90 IFDF=ITHEN460 PRINT"FILE NOT FOUND!":PRINT PRINT"RETURN FOR MORE" INPUTX$:CLOSE2:CLOSEI5 RETURN PRINT.15,·B-P"~2~X*32+2 GETII2,X$:IFX$="ITHENX$=CHR$(O) FT=ASC(X$) IF(FT AND 64)=0 THEN 510 PRINT"FILE IS ALREADY PROTECTED!":PRINT:GOT0430 FT=(FT OR 64) PRINTtI5,"B-P"~2~X*32+2 PRINT'2,CHR$(FT)~ PRINT'15,·B-P"~2~0 PRINTII15,·U2";2;0;TT~SS CLOSE2:CLOSE15 PRINT"FILE PROTECTED." PRINT"RETURN FOR MORE" INPUTX$ CLOSE2:CLOSEI5:RETURN REM ---------------REM UNPROTECT A FILE REM ---------------GOSUB158o GOSUB1l90 IFDF=lTHEN710 PRINT"FILE NOT FOUND!":PRINT PRINT"RETURN FOR MORE" INPUTX$:CLOSE2:CLOSE15 RETURN PRINTII15,"B-P":2;X*32+2 GET# 2 ,X$: I FX$=" "THENX$=CHR$ (0) FT=ASC(X$) IF (FT AND 64)=64THEN760 PRINT"FILE IS ALREADY UNPROTECTED!":PRINT:GOT0680 FT=(FTAND255-64) PRINT#15,"B-P":2:X*32+2 PRINTII2,CHR$(FT); PRINTlII5,"B-P";2;0 PRINT#15,"U2";2;0;TT;SS CLOSE2:CLOSEI5 PRINT"FILE UNPROTECTED." PRINT"RETURN FOR ~lORE" INPUTX$ 276 Anatomy of the 1541 Disk Drive 850 RETURN 860 REM -----------870 REM ERASE A FILE 880 REM -----------890 GOSUB1580 900 GOSUB1l90 910 IFDF=lTHEN960 920 PRINT"FILE NOT FOUND!":PRINT 930 PRINT"RETURN FOR MORE" 940 INPUTX$:CLOSE2:CLOSE15 950 RETURN 960 PRINTI15."B-P";2;X*32+2 970 GET.2.X$:IFX$= .... THENX$=CHR$(0) 980 FT=ASC(X$) 990 IF(FT AND 64)=OTHENI040 1000 PRINT"WARNING! FILE IS PROTECTED!" 1010 PRINT"UNPROTECT AND ERASE (YIN)?" 1020 GETX$:IFX$<>"Y"ANDX$<>"N"THENI020 1030 IFX$="N"THENl170 1040 PRINT"ARE YOU SURE (YIN)?" 1050 GETX$:IFX$<>"y"ANDX$<>"N"THENI050 1060 IFX$="N"THENl170 1070 FT=(FT AND 255-64) 1080 PRINTI15."B-P":2;X*32+2 1090 PRINT,2.CHR$(FT); 1100 PRINT,15."B-P";2;0 1110 PRINTI15."U2";2;0;TT;SS 1120 PRINT,15."IO" 1130 PRINTI15."S:"+F$ 1140 PRINT"FILE ERASED." 1150 PRINT"RETURN FOR MORE" 1160 INPUTX$ 1170 CLOSE2:CLOSEI5:RETURN 1180 REM 1190 REM -----------------1200 REM READ I SEARCH FILE 1210 REM -----------------1220 OPENI5.8.15 ... IO .. :OPEN2.8.2 ...... 1230 PRINTI15."B-R":2;0:18;0 1240 PRINTI15."B-P";2;0 1250 PRINTI15."U2";2;O;18;0 1260 INPUTI15.Xl$ 1270 IF VAL(Xl$)<>26 THEN 1330 1280 PRINT"PLEASE REMOVE THE WRITE PROTECT TAB FROM" 1290 PRINT"THE DISKETTE BEFORE USING THIS PROGRAM." 1300 PRINT"RETURN FOR MORE" 1310 INPUTXS 1320 CLOSE2:CLOSE15:RETURN 1330 T=18:S=I:TT=18:SS=1 1340 PRINTI15."B-R";2;0;T;S 1345 TT=T:SS=S 1350 PRINTI15."B-P";2;O 1360 GETI2.X$:IFXS= .... THENX$=CHR$(0) 1370 T=ASC(X$) 1380 GET.2.X$:IFX$= .... THENX$=CHR$(0) 277 Anatomy of the 1541 Disk 1390 1400 1410 1420 1430 1440 1450 1460 1470 1480 1490 1500 1510 1520 1530 1540 1550 1560 1570 1580 1590 1600 1610 1620 1630 1640 1650 1660 Dri~e S=ASC(X$) FORX=OT07 PRINTilS,"B-P";2;X*32+2 GET,2,X$:IFX$=""THENX$=CHR$(0) IFASC(X$)=OTHENlS30 PRINTI15,"B-P";2;X*32+5 FF$="" FORY=OTOI5 GET'2 ,X$: IFXS=" "THENX$=CHR$ (0) IFASC(X$)=160THEN1500 FF$=FF$+X$ NEXTY IFFLTHENPRINTFF$:GOTOI530 IFF$=FF$THENDF=1:GOT01570 NEXTX IFT<>OTHENI340 CLOSE2:CLOSEIS IFFL=OTHENPRINT"FILENAME NOT FOUND!":FORI=lT02000: NEXT RETURN REM -------------REM INPUT FILENAME REM -------------PRINT:PRINT INPUT"FILENAME:";F$ IFLEN(F$)<=16THEN1650 PRINT"FILENAME TOO LONG!":GOT01620 DF=O:FL=O RETURN 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. 4.1.3 Backup Program - Copying a Diskette The VIC 1541 disk drive does not allow disks to be duplicated since it is a single drive, as the double drives permit with the COpy or BACKUP commands of BASIC 4.0. With the 1541, each program to be copied must be transferred through the computer. Here's an example of how you might copy a diskette using a single disk drive: First, the BAM as well as the names and IDs of the disk to be copied are read into the computer. From the information in the BAM, you can determine which blocks of the original diskette are used. In order to save time, only the allocated 278 Anatomy of the 1541 Disk Drive blocks are copied. Then a direct access file is opened and the first 169 (as many as will fit in the memory of t~e Commodore 64) allocated blocks are read. Then the user is asked to put a new diskette in the drive. The new diskette is then formatted with the name and ID of the original diskette. Now the previously read blocks are written to the diskette. The next 169 blocks of the original diskette are read into memory and written out to the destination diskette. This ends after four disk swaps, at which time the entire diskette will have been copied. The program is written in BASIC except for the portion which reads and writes the direct access file. This part is written in machine language which is considerably faster than a GET# loop in BASIC. Because of the nature of the program, the number of diskette changes is dependent on the free storage in the computer. A VIC 20 with a 16K expansion requires 11 changes of original and destination diskettes. Here is a time comparison between this program and duplication on a double drive with the same capacity. Our program requires about 20 minutes, while the CBM 4040 does it in about 3 minutes. Duplicating a diskette with this program is quite simple. You need only follow the messages on the screen to insert the original or destination diskette. The program does the rest for you. 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 REM BACKUP PROGRAM C64 - VIC 1541 REM POKE56,23:CLR:GOSUB640 OPENl,8,l5 DIM B%(35,23),S%(35),Z(7),A$(1l A$ (0) ="DESTINATION" :A$ (1) ="ORIGINAL": R=l AD=23*256:GOSUB590 POKE250,0:POKE251,AD/256 GOSUB530:GOSUB290 PRINTNS"BLOCKS TO COPY":PRINT T=l:S=O FORI=lT04:TT=T:SS=S:R=1:IFI=lTHEN240 IFR=OANDI=lTHENGOSUB450:GOT0240 GOSUB590 POKE251,AD/256:FORJ=lT0169 IFB%(T,S)=OTHENGOSUB570 S=S+1:IFS=S%(T)THENT=T+l:S=0:IFT=36THENJ=169 NEXT:IFRTHENR=O:T=TT:S=SS:GOT0220 NEXT:GOT0510 T=18:S=0:GOSUB570 NS=0:FORT=lT035:S=0 NS=NS+S%(T)-PEEK(AD+4*T) FORJ=lT03 B=PEEK(AD+4*T+J) FORI=OT07 279 Anatomy of the 1541 Disk Drive 340 350 360 370 380 390 400 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640 650 660 670 680 690 700 710 FORI=OT07 B%(T,S)=B AND Z(I):S=S+l NEXT I,J FOR S=S%(T)T023 B%(T,S)=-l : NEXT S,T FOR I=OT015 A=PEEK(AD+144+I) IFA<>160THENN$=N$+CHR$(A) NEXT I$=CHR$(PEEK(AD+162»+CHR$(PEEK(AD+163» PRINTNS,I$:RETURN PRINT"PLEASE INSERT NEW DISKETTE" PRINT"AND PRESS RETURN":PRINT:POKE198,0:CLOSE2 GETA$:IFAS<>CHR$(13)THEN470 PRINT#I,"NO:"NS","I$ INPUTlIl,A ,B$,C, D: IFATHENPRINTA" , "BS" , "c" , "D: END GOT0630 CLOSE2:CLOSEl:END REM SECTORS PER TRACK FORT=lT035 S%(T)=21:IFT>17THENS%(T)=19:IFT>24THENS%(T)=18: IFT>30THENS%(T)=17 NEXT FORI=OT07:Z(I)=2'tI:NEXT:RETURN IFRTHENPRINT#l,"Ul 2 0"T1S:SYSIN:RETURN PRINT#l,"B-P 2 0":SYSOUT:PRINT#1,"U2 2 0"T1S:RETURN CLOSE2:PRINT"PLEASE INSERT "A$(R)" DISKETTE." PRINT"AND PRESS RETURN":PRINT:POKE198,0 GETA$:IFA$<>CHR$(13)THEN610 PRINT#I,"IO" OPEN2,8,2,"#":RETURN FOR I = 828 TO 873 : REM READ MACHINE LANG. PROGRAM READ X : POKE I,X : S=S+X : NEXT DATA 162, 2, 32,198,255,160, 0, 32,207,255,145,250 DATA 200,208,248,230,251, 32,204,255, 96,198, 1,162 DATA 2, 32,201,255,160, 0,177,250, 32,210,255,200 DATA 208,248,230,251, 32,204,255,230, 1, 96 IF S<>7312 THEN PRINT "ERROP IN DATA!!":END IN=828:0UT=849:PETURN 4.1.4 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 (SEO) or user files (USP). Relative files cannot be copied with this program1 these can be copied with a ~ASIC program that reads all data records into a string array and then writes them back again into a new file. In the first pass, the program reads the complete file into the memory of the Commodore 64. Then the destination 280 Anatomy of the 1541 Disk Drive 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. 100 REM FILE COPIER PROGRAM C64 llO REM 120 POKE 56,12 : CLR 130 GOSUB 1000 140 INPUT"FILENAME ";NS 150 PRINT"FILE TYPE "; 160 GETT$:IFT$<>"S"ANDT$<>"P"ANDT$<>"U"THENI60 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 POKE 3,0:POKE 4,12:SYS 828 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 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 fi Ie 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 281 Anatomy of the 1541 Disk Drive 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 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 PRINTCHR$(147); OPEN15,8,15,"IO":OPEN2,8,2,"JI" T-18:S=1 PRINT'15,"B-R";2;0;T;S PRINT'15,"B-P";2;0 GET.2,X$:IFXS=""THENX$=CHR$(0) T=ASC(X$) GET,2,X$:IFX$=""THENX$=CHR$(0) S=ASC(X$) FORX=OT07 PRINT'15,"B-P";2;X*32+5 FF$=·..• FORY=OT015 GET'2,X$:IFX$=""THENXS=CHRS(0) IFASC(X$)=160THEN270 FF$=n'S+X$ NEXTY IFA=OTHENA=1:PRINTFF$;:GOT0290 A=0:PRINTTAB(20);FF$ NEXTX IFT<>OTHEN130 CLOSEl:CLOSE2 PRINT"RETURN FOR MORE" INPUTX$ 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. 282 Anatomy of the 1541 Disk Drive 4.2 The utility Programs on the TEST/DEMO Disk There are many 1541 owners that know little about the programs contained on the Test/Demo 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 OOS. 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 commands: it on the Commodore 64, give the 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. The individual commands of the DOS 5.1 Command Function @$ or >$ @V or >V @C: ••• or >C: ••• cfile or /file @ or > @N: ••• or >N: ••• @I or >1 @R: ••• or >R: ••• @S: ••• or >S: ••• @#n or >lIn Display the directory Same function as "VALIDATE" 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 283 Anatomy of the 1541 Disk Drive 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 te 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. 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.~.3 DISK ADDR CHANGE with this program, the device address of a disk drive can tee changed through software. After starting the program, turn all drives off except for the one you wish to change. Now enter the old and new device addresses. 284 Anatomy of the 1541 Disk Drive After this, the address is be turned back on. changed and the other drive can The following drives can be changed with this program: 2031 2040 4040 4040 8050 8050 8250 4.2.4 DOS OOS DOS OOS DOS OOS DOS V2.6 Vl.l V2.l V2.7 V2.5 v2.7 V2.7 DIR This is a small possibil i tes: help program with the following 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 other commands. 4.2.5 in DOS 5.1, along with VIEW BAM With this utility program you can view the usage blocks on the screen. This table displays the columns and the tracks in rows. Crosses indicate and reverse crosses indicate allocated blocks. that these blocks do not exist on the track. of diskette sectors in free blocks 'n/a' means After outputting the table, the diskette name and the number of free blocks is 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 285 Anatomy of the 1541 Disk Drive block and the total number of tested blocks is displayed on the screen. 4.2.7 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. This will then be sent to the printer or screen. The DISK-MONITOR contained in this book is a 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. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Disk is formatted A file is opened for reading Data are written to this file The file is closed again This file is opened for reading The data are read The file is closed again The file is erased Track 35 is written Track 1 is written Track 35 is read 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. 286 Anatomy of the 1541 Disk Drive 4.3 BASIC-Expansion and Programs for easy Use of 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 (CHRS(13». The alternative, to read the input with a GET# statement but 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 OPEN 2,8,2,"FILE" 110 INPUT* 2,100,A$ This reads a string of 100 characters from the opened file into AS. 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 record into fields can be accomplished with the MIDS function. An elegant method of creating"records is described in the next section. 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 files: 100 110 120 130 140 OPEN 1,8,15 OPEN 2,8,2, "REL-FILE,L,"+CHRS(20) PRINT#l, "P"+CHR$(lO)+CHR$(O)+CHR$(l) PFINT#2, "12345678901234567890": PRINT#l, "P"+CHR$(lO)+CHF$(O)+CHRS(l) 287 Anatomy of the 1541 Disk Drive 150 INPUT* 2,20,A$ 160 PRINT A$ 12345678901234567890 Here is the assembler listing for the machine language program. It resides in the cassette buffer just lik.e a loader program in BASIC for the Commodore 64 and VIC 20. 110: 033C , 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 INPliT STAR BASVEC CHRGET CHRGOT , 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 1 033C 033C 033C 530 540 550 560 570 033C 033C 033E 0340 0343 $EllE $E1l2 $AEFD $A7AE $A7E7 $ABBF $B08B $B475 $B6A3 $B79E EOli EOli EOli EOli EOli EOli EOli EOli EOli EOli $EllB $EIOF $CEFD $C7AE $C7E7 $CBBF $008B $D475 $D6A3 $D79E COMMON LABELS VARADR CLRCH PARA A9 An 8D 8C EOli EOU EOli EOli EOli EOli EOli EOli EOli EOli VIC 20 VERSION CHKIN BASIN CHKCOM INTER EXECOLO INPliTOLO FINOVAR STRRES FRESTR GETBYT . $85 $AC $308 $73 CHRGET + 6 C64 VERSION CHKIN BASIN CHKCOM INTER EXECOLD INPUTOLO FINOVAR STRRES FRESTR GETBYT 1 490: 500: 510: EOli EOli EOli EOli EOli , 1 , 240: 250: 260: 270: 280: 290: 300: 310: 320: 330 : INPliT* LFN,LEN,A$ 47 INIT 03 08 03 0<) 03 288 EOli EOli EOli $49 $FFCC $61 ORG LOA LOY STA STY 828 # TEST BASVEC BASVEC+1 Anatomy of the 1541 Disk Drive 580: 0346 60 600: 610 : 620: 630 : 640: 0347 034A 034C 034E 0351 650: 660: 0354 20 73 00 FOUND 0357 C9 AC 670: 680 : 680: 690: 0359 035B 035E 0361 FO 20 4C 20 700: 710: 720: 730 : 730: 740: 750: 0364 0367 036A 036D 036E 036F 0372 760: 760: 770: 780: 790: 800: 810: 820: 830 : 840: 850: 860: 870: 880: 890: 900: 910: 910: , JSR CMP BEQ JSR JMP CHRGET #INPUT FOUND CHRGOT EXECOLD JSR CMP CHRGET #STAR 06 BF AB AE A7 9B B7 OKSTAR BEO JSR JMP JSR OKSTAR INPUTOLD INTER GETBYT-3 20 20 20 8A 48 20 20 IE El FD AE 9E B7 JSR JSR JSR TXA PHA JSR JSR CHKIN CHKCOM GETBYT 0375 0377 0379 037C 037D 85 84 20 68 20 49 4A A3 B6 STA STY JSR PLA JSR VARADR VARADR+l FRESTR 0380 0382 0385 0387 0388 038A 038B 038E 0390 0391 0393 0395 0398 AO B9 91 88 10 C8 20 91 C8 C4 DO 20 4C 02 61 00 STORE 49 LDY LDA STA DEY BPL INY JSR STA INY CPY BNE JSR JMP #2 PARA,Y (VARADR) ,Y 20 C9 FO 20 4C 73 00 TEST 85 06 79 00 E7 A7 RTS FD AE 8B BO 75 B4 F8 12 El FETCH 62 61 F6 CC FF AE A7 TO THE OLD ROUTINE NEW INPUT ROUTINE GET FILE NUMBER LENGTH NOTICE CHKCOM FINDVAR SEARCH FOR VARIABLE LENGTH RESERVE PLACE FOR STRING STRRES STORE Y=O BASIN (PARA+l) ,Y PARA FETCH CLRCH INTER ;TO INTERPRETER LOOP Here are the BASIC programs for entering language program for the INPUT* statement. INPUT* , the machine 64 Version 100 FOR I = 828 TO 922 110 READ X : POKE I,X S=S+X : NEXT 3,141, 8, 3,140, 120 DATA 169, 71,160, 289 9, 3, 96, 32 Anatomy of the 1541 Disk Drive 130 140 150 160 170 180 190 200 210 DATA 115, 0,201,133,240, 6, 32,121, 0, 76,231,167 DATA 32,115, 0,201,172,240, 6, 32,191,171, 76,174 DATA 167, 32,155,183, 32, 30,225, 32,253,174, 32,158 DATA ~83,138, 72, 32,253,174, 32,139,176,133, 73,132 DATA 74, 32,163,182,104, 32,117,180,160, 2,185, 97 DATA 0,145, 73,136, 16,248,200, 32, 18,225,145, 98 DATA 200,196, 97,208,246, 32,204,255, 76,174,167 IF S <> 11096 THEN PRINT "ERROR IN DATA!!" : END SYS 828 : PRINT ·OK." 'INPUT· , VIC 20 VERSION 100 110 120 130 140 150 160 170 180 190 200 210 FOR I = 828 TO 922 READ X : POKE I,X : S=S+X : NEXT DATA 169, 71,160, 3,141, 8, 3,140, 9, 3, 96, 32 DATA 115, 0,201,133,240, 6, 32,121, 0, 76,231,199 DATA 32,115, 0,201,172,240, 6, 32,191,203, 76,174 DATA 199, 32,155,215, 32, 27,225, 32,253,206, 32,158 DATA 215,138, 72, 32,253,206, 32,139,208,133, 73,132 DATA 74, 32,163,214,104, 32,117,212,160, 2,185, 97 DATA 0,145, 73,136, 16,248,200, 32, 15,225,145, 98 DATA 200,196, 97,208,246, 32,204,255, 76,174,199 IF S <> 11442 THEN PRINT "ERROR IN DATA!!" : END SYS 828 : PRINT ·OK." 4.3.2 Easy preparation of 'Data Records If you have worked with relative files before, you know that a definite record length must be established. This record is usually divided into several fields which likewise begin at a definite position within the record, and have a set length. If you create a new record, for example, a separate INPUT statement is generally used for each field. Befora the complete record can be written, it must be assembled properly. Each field must be checked for proper length. If it is longer than then the planned length of the corresponding data field, the remainder must 'be truncated to the proper length. Here are two new BASIC commands that are excellently suited for 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 command has the name !STR$ and serves to create a string with the length of the data record. A$ = !STR$(100,· ") 290 Anatomy of the 1541 Disk Drive creates a string with 100 blanks and puts it in the variable A$. The next command places our data field in 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 P$ remain (blanks, in our case). That is exactly as we wanteC!. 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$ ",H, ."",,. ; U) "., L$ F$ S$ C$ T$ Z$ L$ F$ S$ C$ 't$ Z$ 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: C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 CHKOPEN CHKCLOSE CHKCOM FRMEVL CHKSTR FRESTR YFAC CHRGET CHRGOT GETBYT INTEGER DESCRPT STRADR ADR2 291 ORG EOU EOU EOU EOU EOU EQU EOU EOU EOU EQU EQU EOU EOU EOU $C800 $AEFA $AEF7 $AEFD $AD9E $AD8F $B6A3 $B3A2 $73 CHRGET+6 $B79B $B1AA $64 $62 $FB Anatomy of the 1541 Disk Drive 232: 233: 234: 235: 236: 237: 238: 240: 241 : 242: 243: 245: 248: 248: 248: 248: 248: 250: 250: 250: 251 : 251: 251: 251 : 252: 252: 252: 253: C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C802 C804 C807 C80A C80D C80F C8ll C814 C816 C818 C81B C81E C821 C823 C825 ADRI LENI LEN2 NUMBER START TYPFLAG STRCODE ILLOUAN SYNTAX POSCODE VECTOR TEMP A9 AO 8D 8C 4C A9 85 20 C9 FO 20 4C 20 C9 FO 4C OD C8 OA OB 6B 00 OD 73 21 06 79 8D 73 C4 03 08 03 03 C8 TESTIN 00 00 AE 00 TEST2 AF EOU EOU EOU EOU EOU EOU EOU EOU EOU EOU EOU EOU LDA LDY STA STY JMP LDA STA JSR CMP BEO JSR JMP JSR CMP BEO JMP $FB+2 3 4 5 6 13 $C4 $B248 $AF08 $B9 $30A LEN1 # TESTIN VECTOR VECTOR+1 MIDSTR #0 TYPFLAG CHRGET # I'! .. TEST2 CHRGOT $AE8D CHRGET #STRCODE STRING SYNTAX STRING$ FUNCTION ; 900: 900: 910: 920 : 920: 930: 940: 950: 960: 970: 980: 990: 1000: C828 C82B C82E C831 C832 C833 C836 C839 C83B C83D C840 C842 C844 20 20 20 8A 48 20 20 24 30 20 A5 DO A5 1010: 1020: C846 4C 52 C8 C849 20 82 B7 STR JMP JSR 1030: 1040: 1050: 1060: 1070: 1080: C84C C84E C850 C852 C854 C855 BEO LDY LDA STA PLA JSR FO AO B1 85 68 20 73 00 STRING FA AE 9E B7 FD AE 9E AD OD OC AA Bl 64 24 65 lA 00 22 03 JSR JSR JSR TXA PHA JSR JSR BIT BMI JSR LDA BNE LDA STR2 7D B4 292 CHRGET CHKOPEN GETBYT+3 ;OPEN PAREN ,NOTICE LENGTH CHKCOM FRMEVL TYPFLAG ,STRING STR INTEGER DESCRPT ,HIGH BYTE ILL >255 DESCRPT+l ; LOW BYTE, LENGTH STR2 $B782 ;SETSTR TYPFLAG TO NUMERIC ILL ;LENGTH 0 #0 ($22) ,Y ,FIRST CHAR TEMP ;LENGTH $B47D ,FRESTR AnatOJ1lY of the 1541 Disk Drive A8 FO 07 A5 03 88 91 62 TAY BEO LDA DEY STA 1090: 1100 : 1110: ll20 : ll20: C858 C859 C85B C85D C85E 1130 : 1140 : C860 DO FB C862 20 CA B4 STR3 BNE JSR 1150: 1160 : C865 4C F7 AE C868 4C 48 B2 ILL JMP JMP LOOP ; ; ; ; STR3 TEMP (STRADR) ,Y ; CREATE STRING LOOP $B4CA ;BRING STRING IN DESCRIPTOR STACK CHKCLOSE ILLQDAN MID$(STRINGVAR,POS,LEN) = STRING EXP MID$(STRINGVAR,POS) = STRING EXP 200: 210: C86B C86B MIDconE EXECUT EOU EOD 240: 250: 255: 260: 270: 280: 290: 325: 330: 355: 360: 370: 372: 375: 378 : C86B C86B CB6B C86B CB6B C86B C86B CB6B C86B 0003 0004 0005 0007 0007 0007 EXECOLD VARNAM VARADR DESCRPT TESTSTR GETVAR SETSTR TEST GETBYT EOU EOU EOU EOD EQD EOU EOD EOU EQU ORG DST DST DST EOU EQU 400: 410: 420: 430: 440: 450: 460: 470: 480: 490: C86B C86D C86F C872 C875 C876 C879 C87B C87D C880 A9 AO 8D 8C 60 20 C9 FO 20 4C 76 MIDSTR C8 08 03 09 03 500 505 510 520 530 535 535 540 545 545 C883 C886 C889 C88C C88E C890 C892 C894 C897 C899 20 20 20 85 84 85 84 20 AO B1 73 FA 8B 64 65 49 4A A3 00 64 LENGTH POSITION VARSTR cmlP POINT2 73 00 MIDTEST CA 06 79 00 E7 A7 LDA LDY STA STY RTS JSR CMP BEO JSR JMP 00 MID AE BO JSR JSR JSR STA STY STA STY JSR LDY LDA B6 293 $CA $308 ;VECTOR FOR STATEMENT EXECUTE $A7E7 $45 $49 $64 SAD8F $B08B $AA52 $AEFF $B79E 3 1 1 2 SB2 $50 # rnDTEST EXECUT EXECUT+l CHRGET #MIDCODE ;CODE FOR MID$ MID ;? YES CHRGOT EXECOLD ;EXECUTF. NORt1AL STATEMENT CHRGET ;NEXT CHAR CHKOPEN ;OPEN PAREN GETVAR ;GET VAR DESCRPT DESCRPT+1 VARADR VARADR+l FRESTR #0 (DESCRPT) , Y Anatomy of the 1541 Disk Drive 545: 545: 550: CB9B 4B CB9C FO 2E CB9E 20 52 AA PHA BEO JSR 560: 560: 560: 570: 570: 570: 600: 610: 620: 630: 650: 650: 660: 660: CBAI CBA3 CBA5 CBA7 CBAB C8AA CBAC CBAF C8B2 C8B3 CBB5 CBB6 CBBB CBBB AO Bl B5 CB Bl B5 20 20 BA FO CA B6 20 C9 01 49 05 LDY LDA STA INY LDA STA JSR JSR TXA BEO DEX STX JSR CMP 665: 665 : 665: 670: 670 : 6BO: 690: 700: 710: 715 : 715: 715: 717: 717: 717: 720 : 730: 770: 7BO: 790: BOO: 800: BOO: 800 : 800: 800: 810: BI0: 820: 840 : B50: 860: 870: B80: B80: 910: CBBD CBBF CBCl CBC3 CBC6 C8C9 CBCA C8CC C8CF CBDI C8D2 CBD3 CBD5 C8D7 C8D9 C8DB CBDE CBEO CBE3 CBE6 CBE9 CBES CBED CBEF C8FO C8F2 C8F4 C8F5 C8F7 C8F9 C8FB C8FD C8FF C90l C902 C904 DO A9 DO 20 20 BA DO 4C B5 6B 3B E5 C5 BO 85 20 A9 20 20 20 04 FF OC FD AE NEXT 9E B7 49 06 FD AE 9E B7 17 04 79 00 29 03 4B B2 ILL STORE 03 04 03 02 03 F7 B2 FF 9E A3 AD 02 Bl 64 85 51 88 Bl 64 85 50 BB Bl 64 f'O D3 C5 03 80 02 85 03 AS 05 18 65 04 B5 05 AE OK AE AD B6 OKI BNE LDA BNE JSR JSR TXA BNE JMP STA PLA SEC SBC CMP BCS STA JSR LDA JSR JSR JSR LDY LDA STA DEY LDA STA DEY LDA BEO CMP BCS STA LDA CLC ADC STA 294 ; LENGTH ILL SETSTR ; PUT STRING IN RAM #1 (VARADR) ,Y VARSTR ;VAR ADDR (VARADR), Y VARSTR+l CHKCOM GETBYT ;GET POS ILL POSITION CHRGOT II") " ; END OF EXPRESSION? NEXT jI$FF ;MAX LENGTH STORE CHKCOM GETBYT ;GET LEN *+5 ILLOUAN LENGTH POSITION LENGTH OK LENGTH CHKCLOSE ;CLOSE ·PAREN #COMP TEST FRMEVL ;GET EXP FRESTR #2 (DESCRPT),Y POINT2+1 (DESCRPT),Y POINT2 (DESCRPT),Y ILL ;0 THEN ERROR LENGTH OKI LENGTH VARSTR POSITION VARSTR Anatomy of the 1541 Disk Drive 910: 920 : 940: 950: 950: C906 C908 C90A C90C C90D 90 02 E6 06 A4 03 88 B1 50 960: 970: 970: 980: C90F C911 C913 C915 91 CO DO 4C 05 00 F7 AE A7 LOOP BCC INC LDY DEY LDA STA CPY BNE JMP *+4 VARSTR+1 LENGTH (POINTl) ,Y ,TRANSFER CHARS FROM STRING (VARSTR) ,Y IEXP 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 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 FOR I = 51200 TO 51479 READ X : POKE I,X : S=S+X : NEXT DATA 169, 13,160,200,141, 10, 3,140, 11, 3, 76,107 DATA 200,169, 0,133, 13, 32,115, 0,201, 33,240, 6 DATA 32,121, 0, 76,141,174, 32,115, 0,201,196,240 DATA 3, 76, 8,175, 32,115, 0, 32,250,174, 32,158 DATA 183,138, 72, 32,253,174, 32,158,173, 36, 13, 48 DATA 12, 32,170,177,165,100,208, 36,165,101, 76, 82 DATA 200, 32,130,183,240, 26,160, 0,177, 34,133, 3 DATA 104, 32,125,180,168,240, 7,165, 3,136,145, 98 DATA 208,251, 32,202,180, 76,247,174, 76, 72,178,169 DATA 118,160,200,141, 8, 3,140, 9, 3, 96, 32,115 DATA 0,201,202,240, 6, 32,121, 0, 76,231,167, 32 DATA 115, 0, 32,250,174, 32,139,176,133,100,132,101 DATA 133, 73,132, 74, 32,163,182,160, 0,177,100, 72 DATA 240, 46, 32, 82,170,160, 1,177, 73,133, 5,200 DATA 177, 73,133, 6, 32,253,174, 32,158,183,138,240 DATA 23,202,134, 4, 32,121, 0,201, 41,208, 4,169 DATA 255,208, 12, 32,253,174, 32,158,183,138,208, 3 DATA 76, 72,178,133, 3,104, 56,229,. 4,197, 3,176 DATA 2,133, 3, 32,247,174,169,178, 32,255,174, 32 DATA 158,173, 32,163,182,160, 2,177,100,133, 81,136 DATA 177,100,133, 80,136,177,100,240,211,197, 3,176 DATA 2,133, 3,165, 5, 24,101, 4,133, 5,144, 2 DATA 230, 6,164, 3,136,177, 80,145, 5,192, 0,208 DATA 247, 76,174,167 IF S <> 31128 THEN PRINT "ERROR IN DATA!!" : END SYS 51200 : PRINT ·OK." 4.3.3 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 295 directly from disk to the Anatomy of the 1541 Disk Drive printer, without the need 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, AS : IF ST = 64 THEN 140 PRINT#l, ASl : 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 apd the program ended. The following is done when spooling: First both files are opened again. Then 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 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. "TEXTOPENs 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). You can CLOfE the file and turn 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 Wi th same command you can stop a transfer in progress. 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 296 Anatomy of the 1541 Disk Drive 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. ~ ~ 110: 130 : 140: 142 : 144: 160: 170: 175: 180 : 190, 200: 202 : 204 : 230: 240: 260: 280: 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 300: 310 : 320: 330: 340, 350: 360: 370: 380: 390: 400: 410: 411: 412: 413: 420 430 435 435 435 510 520 530 540 550 560 033C 033C 033F 0341 0344 0347 0349 034B 034D 034F 0351 0354 0357 0359 035C 035F 0361 0364 0367 036A 036D 036F 0371 0373 0374 0376 1541 - 64 SPOOL CHRGOT LISTEN ATNRES CLOCK DATA CLOSE CLALL SETFIL GETNAME OPEN CHKIN UNTALK UNLISTEN FNLEN INDEV NMBFLS ERROR 20 FO 20 20 A6 FO A9 A2 AO 79 33 E7 54 B7 38 02 08 02 BA CO 04 Bl BE 02 C6 BE 85 97 00 99 98 20 20 A9 20 20 A2 20 20 20 20 A9 85 85 60 A9 01 85 98 00 FF E2 FF FF FF ED FF ED EE EE OFF 297 EOU EOU EOU EOU EOU EOU EOU EOU EOU EOU EOU Eon EOU EOU EOU EOU EOU $79 $FFBI $EDBE $EE85 $EE97 $FFC3 $FFE7 $FFBA $E254 $FF'CO $FFC6 $FFAB $FFAE $87 $99 $98 $AF08 ORG JSR BEO JSR JSR LDX BEO LDA LDX LOY JSR JSR LOA JSR JSR LOX JSR JSR JSR JSR LDA STA STA RTS LOA STA 828 CHRGOT OFF CLALL GETNAME FNLEN SYNTAX #2 #8 #2 SETFIL OPEN #4 LISTEN ATNRES #2 CHKIN ATNRES CLOCK DATA #0 INDEV NMBFLS #l NMBFLS ~ATN HI HI ;DATA HI ~CLOCK ;GET FILENAME ; INPUT DEVICE ;NO. OF FILES ; SYNTAX ERROR ;MORE CHARS ;SPOOL DONE ;OPEN FILE ,PRINTER ,DISK Anatomy of the 1541 Disk Drive 570: 580: 620: 630 : 640: 0378 037B 037E 0380 0383 20 20 A9 4C 4C AE AB 02 C3 08 FF FF FF AF SYNTAX JSR JSR LDA JMP JMP UNLISTEN UNTALK *2 CLOSE ERROR Here is the BASIC loader program for the Commodore 64. 100 110 120 130 140 150 160 170 180 190 200 FOR I = 828 TO 901 READ X : POKE I,X : S=S+X : NEXT DATA 32,121, 0,240, 51, 32,231,255, 32, 84,226 DATA 166,183,240, 56,169, 2,162, 8,160, 2, 32 DATA 186,255, 32,192,255,169, 4, 32,177,255, 32 DATA 190,237,162, 2, 32,198,255, 32,190,237, 32 DATA 133,238, 32,151,238,169, 0,133,153,133,152 DATA 96,169, 1,133,152, 32,174,255, 32,171,255 DATA 169, 2, 76,195,255, 76, 8,175. IF S <> 9598 THEN PRINT "ERROR IN DATA I!" : END PRINT "OK." For the VIC 20, use the following program: 100 110 120 130 140 150 160 170 180 190 200 FOR I = 828 TO 901 READ X : POKE I,X : S=S+X : NEXT DATA 32,121, 0,240, 51, 32,231,255, 32, 81,226 DATA 166,183,240, 56,169, 2,162, 8,160, 2, 32 DATA 186,255, 32,192,255,169, 4, 32,177,255, 32 DATA 197,238,162, 2, 32,198,255, 32,197,238, 32 DATA 132,239, 32,160,228,169, 0,133,153,133,152 DATA 96,169, 1,133,152, 32,174,255, 32,171,255 DATA 169, 2, 76,195,255, 76, 8,207 IF S <> 9648 THEN PRINT "ERROR IN DATA!!" : END PRINT "OK." 298 Anatomy of the 1541 Disk Drive 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 a 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 : 110 120 130 I, REM PROGRAM 1 REM THIS PROGRAM IS LARGER THAN THE SECOND A = 1000 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 AS = "TEXT" the variable pointer points to the actual text within line number 100. When chaining, the next program does not chan~:e 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 AS = "TEXT" + "" 299 Anatomy of the 1541 Disk Drive 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 two 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 control 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, any display will be destroyed. In practice it looks like this: 1000 1010 1020 1030 1040 1050 PRINT CHR$(147) "LOAD"CHR$(34) "PROGRAM 2"CHR$(34)",8" PRINT : PRINT : PRINT : PRINT PRINT "RUN" POKE 632,13 POKE 633,13 POKE 631,19 POKE 634,13 POKE 635,13 POKE 636,13 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 300 Anatomy of the 1541 Disk Drive 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 1: 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: 100 IF A=O THEN A=l 110 LOAD "MACH-PRG",8,1 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 language programs to load. 100 IF A=O THEN A=l 110 IF A=l THEN A=2 120 IF A=2 THEN A=3 if you have several machine LOAD "PROG 1",8,1 LOAD "PROG 2",8,1 LOAD "PROG 3",R ,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. 301 Anatomy of the 1541 Disk Drive 4.5 Merge - Appending BASIC Programs Certainly you have thought about the possibility of combining two separate BASIC programs into one. without further details this is not possible, because loading the second program would overwrite the first. With the knowledge of how BASIC programs are stored in memory and on the diskette, you can develop a simple procedure to accomplish this task. BASIC programs are stored in memory as follows: NL NH LL LH XX yy ZZ 00 pointer to the next program line, 10 hi line number, 10 hi ••••• tokenized BASIC statements end-of-line marker At the end of the program are two additional zero bytes: 00 00 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 BASIC, 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. Now get the value of the ending address of the program. A = PEEK(45) + 256 * PEEK(46) This value is decremented by two so that the two zero bytes at the end of the program are known. 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. ·302 Anatomy o£ the 1541 Disk Drive POKE, 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 that are greater than the largest line number of the first program. Otherwise these line numbers can never be accessed with GOTO or GOSUB 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 2000025000, 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. 303 Anatomy of the 1541 Disk Drive 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, followed by the command. You can initialize a diskette with enter an '@' >@I YOU can send complete disk commands in this manner, that you would otherwise send with OPEN 15,8,15 PRINT# 15," command n CLOSE 15 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 12 01 304 Anatomy of the 1541 Disk Drive Each input must be given as a two-digit hex separated from each other with a blank. number, In order to display the block, use the command M. We receive the following output: DISK-MONITOR Vl.O >M >:00 12 04 82 11 > :08 46 49 4B 20 >:10 53 52 43 AO >: 18 00 00 00 00 >:20 00 00 82 13 >: 28 4F 54 2E 53 >:30 AO AO AO AD >:38 00 00 00 00 >:40 00 00 82 13 >:48 4F 54 2E 53 >:50 AD AO AO AO > :58 00 00 00 00 > : 60 00 00 82 13 > :68 2E 53 52 43 >:70 AD AO AO AO >:78 00 00 00 00 ) : 80 00 00 82 13 ):88 2E 4F 42 4A etc. 01 41 AO 00 00 52 AO 00 03 52 AO 00 09 AO AO 00 08 AO 47 49 00 00 48 43 00 00 56 43 00 00 4D AO 00 00 4D 52 41 44 2E 00 00 15 00 50 4C AO AO 00 00 05 00 50 4C AO AO 00 00 09 00 45 4D AO AO 00 00 06 00 45 4D AD AO AO ••••• GRA FIX AID. SRC ................ ••••• HPL OT.SRC ................ . " •• VPL OT.SRC ................ ••.•• MEM .SRC ................ ••.•• MEM .OBJ 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: )M 00 7F The second half with: >M 80 FF 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 305 Anatomy of the 1541 Disk Drive numbers in hexadecimal. >W 12 01 writes the block back to track 18, sector 1, from where we had read the block previously. 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 load it again. 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 only work with a copy. Here you find an issembler listing of the program. After this are the BASIC loader programs for the Commodore 64 and VIC 20. disk monitor vic 20 / II> 190: 200: COOO COOO PROMPT NCMDS EOU EOU 210: 220: 230: 240: 250: 260: 270: 280: 290: 300: 310: 320: 330: 340: 350: 360: 370: 380: 390: 400: 410: COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO 0200 INPUT TALK SECTALK IEEEIN UNTALK LISTEN SECLIST IEEEOUT UNLIST WRITE OPEN CLOSE SETPAR SETNAM CHKIN CKOUT CLRCH CR OUOTE OUOTFLG EOU EOU EOU EQU EOU EQU EOU EOU EOU E(lU EOU EOU EOU EOU EOU EOU EOU EOU EOU EOU ORG $FFCF $FFB4 $FF96 $FFA5 $FFAB $FFBI $FF93 $FFAB $FFAE $FFD2 $FFCO $FFC3 $FFBA $FFBD $FFC6 $FFC9 $FFCC 420: 430: 440: 0201 0202 0203 SAVX WRAP BAD BYT BYT BYT a 0 a 306 cbm 64 II 6 ;NUMBER OF COMMANDS 13 $22 $D4 $200 ; BASIC INPUT BUFFER Anatomy of the 1541 Disk Drive 450 460 470 480 0204 0205 0205 0205 490: 500: 510: 0205 0205 0205 520: 610: 620: 630: 640: 650: 660: 670: 680: 690: 700: 710: 710: 710: 720: 730: 740: 750: 760: 770: 0205 COOO COOO COOO C002 C005 C008 C009 COOB COOD COOF COll C014 C016 COl9 COlC COlE C020 C022 C024 780: 790: 800: 840: 850: 860: 870: 880: 890: 900: 910 : FROM STATUS SA BYT BYT EOU EOU 0 0 $90 $B9 FA FNADR FNLEN EOU EOU EOU $BA $BB $B7 TMPC COUNT READY INIT A2 00 BD 85 C2 MSGOUT 20 D2 FF E8 EO 12 DO F5 START A2 OD A9 3E 20 EB CO A9 00 8D 01 02 20 33 Cl STI C9 3E FO F9 C9 20 FO F5 A2 05 sO EOU EOU EOU LDX LDA JSR INX CPX BNE LDX LDA JSR LDA STA JSR CMP BEO CMP BEO LOX $97 8 ;t OF BYTES PER LINE $E37B ;$E467 FOR VIC to MESSAGE,X WRITE C026 C029 C02B C02E C03l DD 6A CO Sl DO OC 8E 00 02 BD 70 CO 48 CMP BNE STX LDA PHA C032 C035 C036 CO 37 C038 C03A BD 76 CO 48 60 CA S2 10 EC 4C OD CO LDA PHA RTS DEX BPL JMP TO C03D 85 C03F 20 C042 B9 990: 1000 1000 1000 1010 1020 C045 C048 C049 C04B C04E COSO 20 C8 DO EE C6 00 tASCDMP-MESSAGE MSGOUT tCR tPROMPT WRTWHR #0 WRAP RooC ;READ INPUT LINE tPROMPT STl t- Il ;READ OVER BLANK STI tNCMDS-l ;COMPARE WITH. COMMAND TABLE CMDS,X S2 SAVX ;# OF CMDS IN TABLE AD~H,X ;JUMP ADDR TO STACK ADRL,X Sl ; LOOP OF ALL CMDS START SUBROUTINE TO DISPLAY THE DISK CONTENTS 97 DM STA TMPC 62 CO DMI JSR SPACE EO C2 LDA BUFFER,y ;GET BYTE FROM BUFFER DC CO JSR WROB INY 03 BNE DM2 01 02 INC WRAP 97 DM2 DEC TMPC ED BNE DMI ; 960: 970: 980: ; SECONDARY ADDRESS ;DEVICE t ; FILENAME ADR ;LEN OF FILENAME 307 Anatomy of the 1541 Disk Drive 1030: C052 60 RTS READ BYTES AND WRITE TO MEMORY C053 20 FE CO BYT JSR RDOB BCC BY3 C056 90 03 ; BLANK? C058 99 EO C2 STA BUFFER,Y ;WRITE BYTE IN BUFFER BY3 C05B C8 INY DEC TMPC C05C C6 97 C05E 60 RTS C05F 20 62 CO SPAC2 JSR SPACE C062 A9 20 SPACE LDA II" n BYT $2C C064 2C CRLF LDA #CR C065 A9 OD JMP WRITE C067 4C D2 FF ; 1060: 1070: 1080: 1090: 1100 : 1110: 1120 : 1130: 1140 : 1150: 1160: ; 1 1190 : 1200: 1210: 1220: 1230: 1240: 1250: 1260: 1270: 1280: 1290: 1300 : 1310: 13 20: 1330: 1340 : 1350: 1360 : 1370: 1380 : 1370: 1370 : 1370 : 1370 : 1370: 1380 : C06A C06B C06C C06D C06E C06F C070 C07l C072 C073 C074 C075 C076 C077 C078 C079 C07A C07B C07C C07E C081 C082 C085 C088 C08A C08C 3A 57 52 4D 40 58 CO Cl Cl CO Cl E3 CO 90 90 7B 3E 7A AO 8C 88 8C 20 C9 FO 20 1390 1400 1410 1410 1410 1420 1430 1440 1450 1460 1470 1470 C08F C091 C094 C097 CD99 C09B CD9E COM COA3 COA6 COA9 COAC 90 8D 20 C9 FO 20 90 8D AC 20 20 98 00 03 02 04 02 CF FF OD 17 FE CO 12 03 CF OD 08 FE 03 04 03 C6 D6 COMMAND AND CMDS ASC ASC ASC ASC ASC ASC ADRH EOU EOU EOU EOU EOU EOU ADRL EOU EOU EOU EQU EOU EOU DSPLYM LDY STY DEY STY JSR CMP BEO JSR 02 FF CO 02 02 DSPI C2 DSP2 C2 BCC STA JSR CMP REO JSR BCC STA LDY JSR JSR TYA 308 ADDRESS TABLE 1: I lEDIT MEM CONTENTS ;WRITE BLOCK 'w' 'R' lREAD BLOCK 'M' lDISLPAY BYTES '@' ;DISK COMMAND 'X' lEXIT >ALTM-l >DIRECT-l >DIRECT-l >DSPLYM-l >DISK-l >READY-l DAOR SETNAM OPEN •# .13 CLOSE #15 CLOSE #'0 ;HEX i TO ASI UO NUMB2 NUMBl .$3B ~ '9' + 1 Anatomy of the 1541 Disk Drive 3390: 3400 : 3410: 3430: 3440: 3440: 3440: 3450: 3460: 3470: 3480: 3490: 3500: 3510: 3520: 3530: 3540: 3550: 3560 : 3570: 3570: 3580: 3580: 3590: 3600: 3610 : 3620: 3620 : 3630: 3640: 3650: 3660: 3660: 3660: 3670: 3680: 3690: 3700 : 3730: C284 60 C285 OD C286 44 49 4B 2D 4F 4E 54 4F 20 56 2E 30 C297 98 C298 38 C299 E9 08 C29B A8 C29C 20 62 C29F A9 12 C2Al 20 D2 C2M A2 08 C2A6 B9 EO C2A9 29 7F C2AB C9 20 C2AD BO 04 C2AF A9 2E C2B1 DO 03 C2B3 B9 EO C2B6 20 D2 C2B9 A9 00 C2BB 85 D4 C3BD C8 C2BE CA C2BF DO E5 C2Cl A9 92 C2C3 4C D2 C2C6 AD 01 C2C9 DO 06 C2CB CC 04 C2CE BO 01 C2DO 60 C2D1 68 C2D2 68 C2D3 4C OD C2D6 20 65 C2D9 A9 3A C2DB A2 3E C2DD 4C EB C2EO MESSAGE 53 4D 49 52 31 ASCDMP CO FF C2 AC2 C2 AC3 FF AC4 FF 02 TESTEND 02 ENDErliD CO CO ALTRIT CO BUFFER RTS EOU ASC TYA SEC SBC TAY JSR LDA JSR LDX LDA AND CMP BCS LDA BNE LDA JSR LDA STA INY DEX BNE LDA JMP LDA BNE CPY BCS RTS PLA PLA JMP JSR LDA LDX JMP DST CR 'DISK-MONITOR Vl.0' #COUNT SPACE U8 WRITE #COUNT BUFFER,Y #$7F #' AC3 #' • AC4 BUFFER,Y WRITE #0 OUOTFLG AC2 U46 WRITE WRAP ENDEND TO END END :RVS ON ;RVS OFF START CRLF #' : #PROMPT WRTWHR 256 ;256 BYTE BUFFER FOR BLOCK Here is the BASIC program for entering the disk monitor if you do not have an assembler. 313 Anatomy of the 1541 Disk Drive DISK-MONITOR, 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 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 C64 VERSION FOR I : 49152 TO 49887 READ X : POKE I,X : S:S+X : NEXT DATA 162, 0,189,133,194, 32,210,255,232,224, 18,208 DATA 245,162, 13,169, 62, 32,235,192,169, 0,141, 1 DATA 2, 32, 51,193,201, 62,240,249,201, 32,240,245 DATA 162, 5,221,106,192,208, 12,142, 0, 2,189,112 DATA 192, 72,189,118,192, 72, 96,202, 16,236, 76, 13 DATA 192,133,151, 32, 98,192,185,224,194, 32,220,192 3,238, 1, 2,198,151,208,237, 96, 32 DATA 200,208, 3,153,224,194,200,198,151, 96, 32 DATA 254,192,144, DATA 98,192,169, 32, 44,169, 13, 76,210,255, 58, 87 DATA 82, 77, 64, 88,192,193,193,192,193,227,192,144 0,140, 3, 2,136,140, 4 DATA 144,123, 62,122,160, 2, 32,207,255,201, 13,240, 23, 32,254,192,144 DATA DATA 18,141, 3, 2, 32,207,255,201, 13,240, 8, 32 3,141, 4, 2,172, 3, 2, 32,198 DATA 254,192,144, DATA 194, 32,214,194,152, 32,220,192, 32, 98,192,169 8, 32, 61,192, 32,151,194, 76,166,192, 76, 13 DATA DATA 192, 32,254,192,144,248,168,169, 8,133,151, 32 DATA 51,193, 32, 51,193, 32, 83,192,208,248, 32,151 DATA 194, 76, 13,192, 72, 74, 74, 74, 74, 32,244,192 DATA 170,104, 41, 15, 32,244,192, 72,138, 32,210,255 2,105, 6,105 DATA 104, 76,210,255, 24,105,246,144, 0,141, 2, 2, 32, 51,193,201, 32 DATA 58, 96,169, DATA 208, 9, 32, 51,193,201, 32,208, 15, 24, 96, 32 DATA 40,193, 10, 10, 10, 10,141, 2, 2, 32, 51,193 2, 2, 56, 96,201, 58, 8, 41 DATA 32, 40,193, 13, DATA 15, 40,144, 2,105, 8, 96, 32,207,255,201, 13 DATA 208,248,104,104, 76, 13,192, 32,207,255,201, 13 DATA 208, 39,169, 0,133,144, 32,101,192,169, 8,133 DATA 186, 32,180,255,169,111,133,185, 32,150,255, 32 DATA 165,255, 36,144,112, 5, 32,210,255,208,244, 32 8 DATA 171,255, 76, 13,192,201, 36,240, 29, 72,169, DATA 133,186, 32,177,255,169,111,133,185, 32,147,255 DATA 104, 32,168,255, 32,207,255,201, 13,208,246, 32 DATA 174,255, 76, 13,192, 32, 51,193, 32,254,192,144 DATA 245,141, 39,194, 32, 51,193, 32,254,192,144,234 0, 2,201, 1,240 DATA 141, 42,194, 32, 73,194,173, DATA 30,169, 49, 32,237,193,162, 13, 32,198,255,162 0, 32,207,255,157,224,194,232,208,247, 32,204 DATA DATA 255, 32,110,194, 76, 13,192, 32, 44,194,162, 13 DATA 32,201,255,162, 0,189,224,194, 32,210,255,232 DATA 208,247, 32,204,255,169, 50, 32,237,193, 76,201 DATA 193,141, 32,194,162, 15,173, 39,194, 32,120,194 DATA 142, 39,194,141, 40,194,173, 42,194, 32,120,194 DATA 142, 42,194,141, 43,194,162, 15, 32,201,255,162 DATA 0,189, 31,194, 32,210,255,232,224, 13,208,245 DATA 76,204,255, 85, 49, 58, 49, 51, 32, 48, 32, 0 DATA 0, 32, 0, 0,162, 15, 32,201,255,162, 0,189 DATA 65,194, 32,210,255,232,224, 8,208,245, 76,204 DATA 255, 66, 45, 80, 32, 49, 51, 32, 48,169, 15,168 DATA 162, 8, 32,186,255,169, 0, 32,189,255, 32,192 314 Anatomy of the 1541 Disk Drive 620 630 640 650 660 670 680 690 700 710 720 730 740 750 DATA 255,169, 13,168,162, 8, 32,186,255,169, 1,162 DATA 109,160,194, 32,189,255, 76,192,255, 35,169, 13 DATA 32,195,255,169, 15, 76,195,255,162, 48, 56,233 DATA 10,144, 3,232,176,249,105, 58, 96, 13, 68, 73 DATA 83, 75, 45, 77, 79, 78, 73, 84, 79, 82, 32, 86 DATA 49, 46, 48,152, 56,233, 8,168, 32, 98,192,169 DATA 18, 32,210,255,162, 8,185,224,194, 41,127,201 DATA 32,176, 4,169, 46,208, 3,185,224,194, 32,210 DATA 255,169, 0,133,212,200,202,208,229,169,146, 76 DATA 210,255,173, 1, 2,208, 6,204, 4, 2,176, 1 DATA 96,104,104, 76, 13,192, 32,101,192,169, 58,162 DATA 62, 76,235,192 IF S <> 90444 THEN PRINT "ERROR IN DATA !!" : END SYS 49152 DISK-MONITOR, VIC 20 VERSION In order to allow this program to be run on the VIC 20, it was split into two parts. Enter each program separately, saving the first under the name "DOS LOADER.l" and second under "DOS LOADER.2". To load the disk monitor, load the first program and start it with RUN. If all data are correct, the second program will automatically be loaded and the disk monitor started. 100 105 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 POKE 55, 6690 AND 255 : POKE 56, 6690 / 256 : CLR FOR I = 6690 TO 7056 : REM DOS LOADER.l READ X : POKE I,X : S=S+X : NEXT DATA 162, 0,189,164, 28, 32,210,255,232,224, 18,208 DATA 245,162, 13,169, 62, 32, 7, 27,169, 0,141, 1 DATA 2, 32, 79, 27,201, 62,240,249,201, 32,240,245 DATA 162, 5,221,140, 26,208, 12,142, 0, 2,189,146 DATA 26, 72,189,152, 26, 72, 96,202, 16,236, 76, 47 DATA 26,133,151, 32,132, 26,185, 0, 29, 32,248, 26 DATA 200,208, 3,238, 1, 2,198,151,208,237, 96, 32 DATA 26, 27,144, 3,153, 0, 29,200,198,151, 96, 32 DATA 132, 26,169, 32, 44,169, 13, 76,210,255, 58, 87 DATA 82, 77, 64, 88, 26, 27, 27, 26, 27,228,223,175 DATA 175,157, 90,102,160, 0,140, 3, 2,136,140, 4 DATA 2, 32,207,255,201, 13,240, 23, 32, 26, 27,144 DATA 18,141, 3, 2, 32,207,255,201, 13,240, 8, 32 DATA 26, 27,144, 3,141, 4, 2,172, 3, 2, 32,229 DATA 28, 32,245, 28,152, 32,248, 26,169, 4, 32, 95 DATA 26, 32,182, 28, 76,200, 26, 76, 47, 26, 32, 26 DATA 27,144,248,168,169, 4,133,151, 32, 79, 27, 32 DATA 117, 26,208,248, 32,182, 28, 76, 47, 26, 72, 74 DATA 74, 74, 74, 32, 16, 27,170,104, 41, 15, 32, 16 DATA 27, 72,138, 32,210,255,104, 76,210,255, 24,105 DATA 246,144, 2,105, 6,105, 58, 96,169, 0,141, 2 DATA 2, 32, 79, 27,201, 32,208, 9, 32, 79, 27,201 DATA 32,208, 15, 24, 96, 32, 68, 27, 10, 10, 10, 10 DATA 141, 2, 2, 32, 79, 27, 32, 68, 27, 13, 2, 2 DATA 56, 96,201, 58, 8, 41, 15, 40,144, 2,105, 8 315 Anatomy of the 1541 Disk Drive 370 380 390 400 410 420 430 440 DATA 96, 32,207,255,201, 13,208,248,104,104, 76, 47 DATA 26, 32,207,255,201, 13,208, 39,169, 0,133,144 DATA 32,135, 26,169, 8,133,186, 32,180,255,169,111 DATA 133,185, 32,150,255, 32,165,255, 36,144,112, 5 DATA 32,210,255,208,244, 32,171,255, 76, 47, 26,201 DATA 36,240, 29, 72,169, 8,133 IF S <> 35614 THEN PRINT "ERROR IN DATA ! ! II : END LOAD "oos LOADER.2",8 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 410 420 430 440 eLR : FOR I = 7057 TO 7422 : REM OOS LOADER. 2 READ X : POKE I,X : s=s+x : NEXT DATA 186, 32,177,255,169,111,133,185, 32,147,255,104 DATA 32,168,255, 32,207,255,201, 13,208,246, 32,174 DATA 255, 76, 47, 26, 76, 47, 26, 32, 79, 27, 32, 26 DATA 27,144,245,141, 70, 28, 32, 79, 27, 32, 26, 27 DATA 144,234,141, 73, 28, 32,104, 28,173, 0, 2,201 1,240, 30,169, 49, 32, 12, 28,162, 13, 32,198 DATA DATA 255,162, 0, 32,207,255,157, 0, 29,232,208,247 DATA 32,204,255, 32,141, 28, 76, 47, 26, 32, 75, 28 DATA 162, 13, 32,201,255,162, 0,189, 0, 29, 32,210 DATA 255,232,208,247, 32,204,255,169, 50, 32, 12, 28 DATA 76,232, 27,141, 63, 28,162, 15,173, 70, 28, 32 DATA 151, 28,142, 70, 28,141, 71, 28,173, 73, 28, 32 DATA 151, 28,142, 73, 28,141, 74, 28,162, 15, 32,201 DATA 255,162, 0,189, 62, 28, 32,210,255,232,224, 13 DATA 208,245, 76,204,255, 85, 49, 58, 49, 51, 32, 48 DATA 32, 0, 0, 32, 0, 0,162, 15, 32,201,255,162 DATA 0,189, 96, 28, 32,210,255,232,224, 8,208,245 DATA 76,204,255, 66, 45, 80, 32, 49, 51, 32, 48,169 DATA 15,168,162, 8, 32,186,255,169, 0, 32,189,255 DATA 32,192,255,169, 13,168,162, 8, 32,186,255,169 DATA 1,162,140,160, 28, 32,189,255, 76,192,255, 35 DATA 169, 13, 32,195,255,169, 15, 76,195,255,162, 48 DATA 56,233, 10,144, 3,232,176,249,105, 58, 96, 13 DATA 68, 73, 83, 75, 45, 77, 79, 78, 73, 84, 79, 82 DATA 32, 86, 49, 46, 48,152, 56,233, 4,168, 32,132 DATA 26,169, 18, 32,210,255,162, 4,185, 0, 29, 41 DATA 127,201, 32,176, 4,169, 46,208, 3,185, 0, 29 DATA 32,210,255,169, 0,133,212,200,202,208,229,169 DATA 146, 76,210,255,173, 1, 2,208, 6,204, 4, 2 DATA 176, 1, 96,104,104, 76, 47, 26, 32,135, 26,169 7, 76, DATA 58,162, 62, 27 IF S <> 39496 THEN PRINT "ERROR IN DATA !! .. : END SYS 6690 316 Anatomy of the 1541 Disk Drive Chapter 5: 5.1 The Larger CBM Disks IEEE-Bus and Serial Bus Standard Commodore 64's and VIC 20's have a serial bus over which they communicate with peripheral devices such as the VIC 1541 disk drive as well as printers and plotters. The principle of the bus makes it possible to chain peripherals. Each device has its own device address over which one can communicate with it. The standard address of the disk is a, a printer is usually 4. The device address is identical to the primary address in the OPEN command. For instance, OPEN .1,4 opens a channel to the printer. In order to open several disk files at once, another address, the secondary address, serves to distinguish them. The disk has 16 secondary addresses at its disposal, from 0 to 15. Three secondary addresses are reserved, while the other 13 can be freely used: Secondary address 0 is used for loading programs. secondary address 1 is used for saving programs. Secondary address 15 is the command and error channel. The secondary addresses from 2 to 14 can be used for opening files as desired. The transfer of information between the Commodore 64 and the VIC 1541 occurs serially over this bus. Serial means that the the data is sent a bit at a time over just one wire. Data within the computer and disk drive are stored and manipulated in 8 bit groups called bytes. When a byte is sent serially, each individual bit must be sent over the data line. In order that the sender and receiver can stay in step, a so-called 'handshake' line is needed. If we look at the pin-out of the serial bus, we find 6 wires: Pin 1 2 3 4 5 6 Function SRQ IN ground ATN CLCK DATA RESET If the computer wants to send data to the disk drive, the 317 Anatomy of the 1541 Disk Drive ATN (attention) line is set. When this signal is high, all peripherals on the bus stop their work and read the next byte. The data is sent bit-wise over the DATA line. So that the receivers know when the next bit comes. a signal is also sent along the CLCK (clock) line. This transmitted byte is the device address. If this value does not correspond with the device address of a receiving peripheral, the rest of the data is ignored. If, however, the device is addressed, a secondary address may be transmitted. Along with the device address (0 to 31), the device is informed by means of the other three bits whether it is supposed to receive data (LISTEN) or send data (TALK). Following this, data is sent from the computer or from the addressed device. The RESET line resets all attached devices when the computer is turned on. Over the SRO IN (service request) line, peripheral devices can inform the bus controller (in our case, the computer), if data is ready, for example. However, this line is not checked by the control system in the Commodore computers. If one wants to attach several disk drives to the same computer, each must have a different peripheral address. If this is done only occasionally, the program DISK'ADDR CHARGE can be used, as described in section 4.2.3. The new address (9 for example), remains only until the device is turned off. If the change should be permanent, it can be, changed with DIP switches in the drive. The principle of transfer of data over th'e IEEE 488 bus is similar to the serial bus function. The important difference is that the data is transmitted over 8 data lines in parallel, not serial. In addition, more handshake lines are needed, so the IEEE bus requires a 24-line cable. The main advantage of the IEEE 488 bus is its ability to transmit a byte at a time, resulting in a higher rate of transfer. Measurements indicate that the IEEE-bus is about 5 times faster than the serial bus: 1.8 Kbyte/second vs. 0.4 Kbyte/second. Loading a 10K program with the VIC 1541 takes about 25 seconds: on the identical 2031, it takes less than 6. This reason alone is enough to warrant outfitting your computer with an IEEE bus. At the same time, it is possible to use all the other peripherals that the large CBM computers can access. 318 Anatomy of the 1541 Disk Drive 5.2 Comparison of all CBM Disk Drives In the following table you find the technical data of all CBM disk drives compared. The Technical Data of all Commodore Disk Drives Model 1541 2031 4040 8050 8250 DOS version(s) 2.6 2.6 2.1/ 2.7 2.5/ 2.7 2.7 Drives Heads per drive 1 1 1 1 2 1 2 1 2 Storage capacity Sequential files Relative files 170 K 168 K 167 K 170 K 168 K 167 K 340 K 168 K 167 K 1. 05 M 521 K 183 K/ 518 K 2.12 M 1.05 M 1,04 M Buffer storage (KB) 2 2 4 4 4 Tracks Sectors per track Bytes per block Free blocks Directory and BAM (track) Directory entries 35 17-21 256 664 18 35 17-21 256 664 18 35 17-21 256 1328 18 77 77 23-29 256 4104 38/39 23-29 256 8266 38/39 144 144 144 224 224 Transfer rate (KB/s) internal 40 over ser./IEEE bus 0.4 40 1.8 40 1.8 40 1.8 40 1.8 Access time (ms) Track to track Average time 30 360 30 360 30 360 5 125 5 125 Revolutions/minute 300 300 300 300 300 Overview of the Illarge ll 2 CBM drives The VIC 1541 disk drive has the smallest storage capacity of the CBM disks, but it is also the only drive that can be connected directly to the Commodore 64 and VIC 20 over the serial bus. The functions, construct ion, and operation are identical to those of the CBM 2031 drive. The only difference from the VIC 1541 is the parallel IEEE bus instead of the serial bus. 319 Anatomy of the 1541 Disk Drive This results in an increase in the transfer rate to the computer of a factor of 5. To connect a Commodore 64 or VIC 20, one needs an IEEE interface, as with all other CBM drives. The storage format of the 2031 is compatible to the 1541; both have l70K per disk. Diskettes can be written with one device and read with the other. This is true for the next drive in the line, the CBM 4040. The 4040 is a double driVe with l70K per drive. The advantage of a double drive lies not only in the increased storage capacity, but also in the ability to transfer data from drive to drive. It is possible to copy complete programs and files using the existing 1541 command. OPEN 1,8,15, "Cl:TEST=O:TEST" or COpy "TEST",DO TO "TEST",Dl copies the file TEST from drive 0 to drive 1 with the same name. In this manner one can concatenate several files on di£ferent drives. The most important capability of double driv€s is the ability to duplicate entire diskettes. This is accomplished by a command from the computer; the drive automatically formats the disk and then makes a track ty track copy from one drive to the other. The command to do this is worded: OPEN 1,8,15, "01=0" or BACKUP DO TO Dl The process takes less than 3 minutes on the 4040; during this time the computer may be used since the disk drive performs the entire operation by itself. The two other CBM drives, the CBM 8050 and the CBM 8250 operate in double density (77 tracks). Disks written with the 1541 or 4040 are not compatible with the 8050/8250. Programs and data can be copied with the COPY/ALL program, which transfers from one format to another. This is the reason these drives have greater storage capacity: 1 MB for the 8050 and 2 MB for the 8250. The doubled capacity of the 8250 comes about because both sides of the disk are used (double-sided); it has two reads/write heads per drive. In order to be able to use the whole capacity for relative files (see section 3.4), a so-called 'super side-sector' was introduced, which contains pointers to 127 groups of 6 sidesector blocks each. Through this, a relative file can (theoretically) hold 23 MB of data. These drives can be connected to a Commodore 64 or VIC 20 over an IEEE bus, ~-o that these computers can also access several megabytes. An additional advantage of the large CBM drives is their larger buffer storage. It is possible to have more files open simultaneously than on the VIC 1541. Up to 5 sequential 320 Anatomy of the 1541 Disk Drive files or 3 relative files may be open at anyone time, as well as combinations of the two, of course. with the 8050/8250 format, tracks 38 and 39 are used for the BAM and directory. The disk name and format marker are in track 39 sector O. >:00 >:08 >:10 >:18 26 4E AD 30 00 20 AD 31 43 38 AD AD 00 30 AD 32 00 35 AD 43 00 30 AD AD 43 AD AD AD 42 AD AD AD &. C ••• CB M 8050 01 2C The track/sector pointer to the first BAM block (track 38 sector 0) is in bytes 0 and 1. Byte 2 contains the format marker 'C'. Bytes 3 through 5 are unused. The disk name is in 6 to 21, filled with shifted spaces, in our case CBM 8050. Bytes 24 and 25 contain the id '01', while bytes 26 and 27 contain the DOS format 2e. The BAM no longer occupies just one block, but is dispersed over track 38; sectors 0 and 3 are used in the 8050, the 8250 used sectors 6 and 9 in addition. Because more sectors are use per track, the BAM entry for each track has been enlarged to 5 bytes. The first byte still contains the number of free sectors per track and the following bytes contain the bit model of the free and allocated sectors (0 = sector allocated, 1 = sector free). Here we have the contents of track 38 sector 0 >:00 >:08 >:10 >:18 >:20 >:28 >:30 > : 38 >:40 >:48 >:50 >:58 >:60 >:68 >:70 >:78 >:80 >:88 >:90 >:98 >:AO >:A8 >: 80 > :B8 > :CO > :C8 26 FF ID FF FF IF FF ID FF FF IF FF 10 FF FF IF FF 10 FF FF IF FF 00 00 F4 IF 03 FF FF IF FF ID FF FF IF FF ID FF FF IF FF ID FF FF IF FF ID FF 00 00 93 00 43 IF FF ID FF FF IF FF 10 FF FF IF FF ID FF FF IF FF ID FF FF IF 00 00 46 00 00 1D FF FF IF FF ID FF FF IF FF ID FF FF IF FF ID FF FF IF FF 18 00 00 lA 00 01 FF IF FF ID FF FF IF FF In FF FF IF FF ID FF FF IF FF 10 FF FC 00 00 18 00 33 FF ID FF FF IF FF ID FF FF IF FF ID FF FF IF FF ID FF FF IF F3 00 00 6C 00 ID FF FF IF FF ID FF FF IF FF ID FF FF IF FF ID FF FF IF FF ID EF 00 00 FB 00 FF IF FF ID FF FF IF FF 10 FF FF IF FF ID FF FF IF FF ID FF FF IF 00 OF FF 00 321 Anatomy of the 1541 Disk Drive >:00 >:08 >:EO > :E8 >:FO > :F8 00 05 FF FF 07 FF 00 00 07 FF 1B F~ 00 00 1B FF FF 07 00 40 FF 07 FF 1B 00 04 FF 1B FF FF 00 1B FF FF 07 FF 00 FF 07 FF 1B FF 00 FF 1B FF FF 07 Bytes 0 and 1 point to the next BAM block, track 38 sector 3. Byte 2 contains the format marker 'e' again. The track numbers belonging to this BAM section are in bytes 4 and 5: here tracks 1 through 51. At position 6 we find the 5 byte entry for each track. The next BAM block is constructed similarly. The last BAM block always points to the first directory block: track 39 sector 1. Four BAM blocks are needed for the 8250: track 38 sector 0 contains the tracks 1 to 51, track 38 sector 3 contains 52 to 100, track 38 sector 6 contains track 101 through 150 and track 38 sector 9 pertains to tracks 151 to 154. The directory track, track 39, contains 28 free blocks: up to 28*8=224 directory entries can be stored, in contrast to 144 f,or the 1541/4040. The construction of the directory is a1 ike for all formats. The f'ollowing table illustrates the track/sector layout: 1541 / 4040 8050 / 8250 -----------------------------------------------------0 - 28 sectors Tracks 1 - 17 0 - 20 1 - 39 18- 24 0 - 18 40 - 53 0 - 26 54 - 64 0 - 24 25- 30 0 - 17 65 - 77 0 - 22 0 - 16 31- 35 78 117 131 142 Blocks Free blocks 683 664 8250 only 0 -116 -130 0 0 -141 0 -154 - 20R3 2052 322 4186 4133 28 26 24 22 Anatomy of the 1541 Disk Drive OTHER BOOKS AVAILABLE: The Anatomy of the Commodore 64 - is our insider's guide to your favorite computer. This book is a must for those of you who want to delve deep into your micro. This 300+ page book is full of information covering all aspects of the '64. Includes fully commented listing of the ROMs so you can investigate the mysteries of the BASIC interpreter, kernal and operating system. It offers numerous examples of machine language programming and several samples that make your programming sessions more enjoyable and useful. ISBN# 0-916439-00-3 Available now: S19.95 The Anatomy of the 1541 Disk Drive - unravels the mysteriEs of working the the Commodore 1541 disk drive. This 320+ page book starts by explaining program, sequential and relative files. It covers the direct access commands, diskette structure, DOS operation and utilties. The fully commented ROM 1 ist ings are presented for the real "hackers". Includes listings for several useful utilities including BACKUP, COPY, FILE PROTECTOR, DIRECTORY. This is the authoritive source for 1541 disk drive information. ISBN# 0-916439-01-1 Available now: S19.95 Tricks & Tips for the Commodore 64 - presents a collection of easy-to-use programming techniques and hints. Chapters cover advanced graphics, easy data entry, enhancements for advanced BASIC, CP/M, connecting to the outside world and more. Other tips include sorting', variable dumps, and POKEs that do tricks. All-in-all a solid set of useful features. ISBN# 0-916439-03-8 Available June 29th: $19.95 Machine Language Book of the Commodore 64 - is aimed at the owner who wants to progress beyond BASIC and write faster, more memory efficient programs in machine language. The book is specifically geared to the Commodore 64. Learn all of the 6510 instructions as they apply to the '64. Access PCM routines, I/O, extend BASIC, more. Included are listings of three full length programs: an ASSEMBLER; a DISASSEMBLER; and an amazing 6510 SIMULATOR so the reader can ·see"the operation of the '64. ISBN# 0-916439-02-X Available now: Optional program diskette: OTHER TITLES COMING SOON!!! 323 S14.95 $14.95 FREE CATALOG Ask for a listing of other AbaCus SOftware for Commodo....64orVlc-20 1III11IIIUTORS llutllrlblla: """"'" lBNuwictlAve AocII~.Lancs m·,..... .... ..,..,: -, --IfIItr.SIrW:at AYGuilauIMSi 147AYenut~ ""lCJO.lIeII1um 2-.,441 ,.".".. ......: AIIInIII:: DATA BECKER T1Al TRADING Merowingerslr:ll P0516 4OOO0usseId0rf 343OO~mhult 02111312085 476-12304 * RIIIIII~.FGnce CW ELECTRONICS 416~.. 1!oId 1IrIsbInII, Queens. 07.0397-0eD8 DEALER INQUIRIES INVITED c..dI~: raNG r.tCROWARE lTD. =:r~=~lZ6 514/737-9336 IIIW ZMIIMI: VlSCOI.lITElECTfIONICS 306-308 CftuFCII Street ........ PaImerstonNOrth AVAILABLE AT COMPUTER STORES, OR WRITE: Abacus _ Software P.O. BOX 7211 GRAND RAPIDS, MICH. 48510 IIti!III For postage & handfing, add $2.50 (U.S. and Canada), add $5.00 .1!Ia!J ~; =~c:~e(~1:;~ ~~~e:"~ bl:s~~~ :~)y order FOR QUICK SERVICE PHONE 616-241-551D
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.3 Linearized : No XMP Toolkit : Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 Create Date : 2013:09:17 12:17:26-08:00 Modify Date : 2013:09:17 13:58:15-07:00 Metadata Date : 2013:09:17 13:58:15-07:00 Producer : Adobe Acrobat 9.55 Paper Capture Plug-in Format : application/pdf Document ID : uuid:8ba32e43-ee30-354b-aefe-c942603df129 Instance ID : uuid:b59026d6-e2dc-4b41-8793-938c0774eb10 Page Layout : SinglePage Page Mode : UseNone Page Count : 336EXIF Metadata provided by EXIF.tools