The new anatomy of the 1541 disk drive : a complete guide to using the Commodore disk drive [2d ed.] 9780916439019, 0916439011

This in-depth guide for the Commodore 1541 disk drive owner, unravels the mysteries of using the 1541 for programs, sequ

874 105 36MB

English Pages 507 [524] Year 1985

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

The new anatomy of the 1541 disk drive : a complete guide to using the Commodore disk drive [2d ed.]
 9780916439019, 0916439011

Table of contents :
Chapter 1: Programming the VIC-1541 1
1.1 Getting started 1
1.1.1 After Unpacking 1
1.1.2 The Disk Operating System 4
1.1.3 The TEST/DEMO Diskette 4
1.1.4 Fomatting New Diskettes 5
1.1.5 Some Facts about a 1541 Diskette 5
1.1.6 Fundamentals of Disk Techniques 6

1.2 Program Management on Diskette 9
1.2.1 Save - Storing BASIC Programs 9
1.2.2 LOAD - Loading BASIC Programs 10
1.2.3 VERIFY - Checking Stored Programs 11
1.2.4 SAVE "@: ... " - Replacing Programs 12
1.2.5 Loading Machine Language Programs 13
1.2.6 Storing Machine Language Programs 15

1.3 Disk System Commands 19
1.3.1 Transmitting Commands to the Disk Drive 19
1.3.2 NEW - Formatting Diskettes 20
1.3.3 Reading the Error Channel 22
1.3.4 LOAD"$",8 - Loading the Directory 24
1.3.5 SCRATCH - Deleting Files 26
1.3.6 RENAME - Renaming Files 28
1.3.7 COPY - Copying Files 31
1.3.8 INITIALIZE - Initializing the Diskette 32
1.3.9 VALIDATE - "Cleaning Up" the Diskette 33
1.3.10 ? * - The Wildcards 34

1.4 Sequential Data Storage 37
1.4.1 The Principle 37
1.4.2 Opening a Sequential Data File 39
1.4.3 Transferring Data Between Disk and Computer 42
1.4.4 Adding Data to Sequential Files 46
1.4.5 Closing a Sequential File 47
1.4.6 Redirecting the Screen Output 48
1.4.7 Sequential Files as Tables in the Computer 50
1.4.8 Searching Tables 53
1.4.9 Simple Sorting of Tables 57
1.4.10 MAILING LIST MANAGEMENT with Sequential
Data Storage 60
1.4.11 Uses for Sequential Storage 70
1.5 Relative Data Storage 71
1.5.1 The Principle 71
1.5.2 The Advantage over Sequential Storage 72
1.5.3 Opening a Relative File 73
1.5.4 Preparing Data for Relative Storage 76
1.5.5 Transferring Data 78
1.5.6 Closing a Relative File 83
1.5.7 Searching Records with the Binary Method 83
1.5.8 Searching Records with a Separate Index File 87
1.5.9 Changing Records 90
1.5.10 Expanding a Relative File 92
1.5.11 Home Accounting with Relative Data Storage 93
1.6 Additional File Structures 105
1.6.1 Direct Addressing 105
1.6.2 Indirect Addressing 107

1. 7 Disk Error Messages and their Causes 109

1.8 Overview of Commands with a Comparison of BASIC 2.0 _
BASIC 4.0 - BASIC 7.0 - DOS 5.1 115
1.8.1 BASIC 4.0 - BASIC 7.0 Commands 116
1.8.2 BASIC 7.0 commands 122

Chapter 2: Advanced Programming 125

2.1 Direct Access of any Block of the Diskette 125

2.2 The Direct Access Commands 129
2.2.1 The Block-Read Command 129
2.2.2 The Block-Pointer Command 130
2.2.3 The Block-Write Command 131
2.2.4 The Block-Allocate Command 133
2.2.5 The Block-Free Command 134
2.2.6 The Block-Execute Command 135

2.3 Uses of Direct Access 137

2.4 Accessing the DOS - The Memory Commands 139
2.4.1 The Memory-Read Command 139
2.4.2 The Memory-Write Command 141
2.4.3 The Memory-Execute Command 142
2.4.4 The User Commands 143
2.4.5 Additional Possibilities for the User Commands 145


Chapter 3: Technical Information 147

3.1 TheConstructionoftheVIC-l541 147
3.1.1 Block Diagram of the Disk Drive 147
3.1.2 DOS Memory Map - ROM, RAM, I/O 148
3.1.3 Layout of the I/O Ports (VIA 6522) 149
3.1.4 The Layout of the Important Memory Locations 150

3.2 Operation of the DOS - An Overview 155
3.2.1 The Disk Controller Routines 156

3.3 The Structure of the VIC-1541 Diskette 159
3.3.1 The BAM of the VIC-1541 159
3.3.2 The Directory 161
3.3.3 The Directory Format 164
3.3.4 The Diskette Recording Process 170
3.4 The Organization of Relative Files 175

3.5 DOS 2.6 ROM Listings 181

Chapter 4: Programs and Tips for Using the 1541 Disk Drive 415

4.1 Utility Programs 415
4.1.1 Displaying all File Parameters 415
4.1.2 Scratch-protect Files - File Protect 422
4.1.3 Backup Program - Copying a Diskette 429
4.1.4 Copying Individual Files to another Diskette 432
4.1.5 Reading the Directory from within a Program 434
4.1.6 Searching for "Hidden" Files 435
4.1.7 Changing the Disk Name and the ID 438
4.1.8 Software Write Protect 441
4.1.9 Invisible Directory 442
4.2 The Utility Programs on the TESTIDEMO Disk 445
4.2.1 DOS 5.1 445
4.2.2 COPY/ALL 446
4.2.3 DISK ADDR CHANGE 447
4.2.4 DIR 448
4.2.5 VIEW BAM 448
4.2.6 CHECK DISK 448
4.2. 7 DISPLAY T &S 449
4.2.8 PERFORMANCE TEST 449

4.3 BASIC Extensions and Programs for the 1541 451
4.3.1 Input Strings of Desired Length from the Disk 451
4.3.2 Easy Preparation of Data Records 456
4.3.3 Spooling - Printing Directly from the Disk 465
4.4 Overlay Technique and Chaining Machine Language Programs 469
4.5 Merge - Appending BASIC Programs 473
4.6 Disk Monitor for the Commodore 64 and VIC 20 475

4.7 Using "WEDGE" Commands from BASIC Programs 497


Chapter 5: The Larger CBM Disks 499

5.1 IEEE-Bus and Serial Bus 499

5.2 Overview of the "large" CBM Disk Drives 503

Citation preview

The New Anatomy of the 1541 Disk Drive A Complete Guide to Using the Commodore Disk Drive By Lothar Englisch & Norbert Szczepanowski

A Data Becker Product Published by: Abacus Software P.O. Box 7211 Grand Rapids, MI 45910

Second Edition, First Printing, September 1985 Printed in the U.S.A.

Copyright (C) 1983,1984 Copyright (C) 1984,1985

DATA BECKER, GmbH Merowingerstr. 30 4000 Dusseldorf W. Germany ABACUS Software, Inc. P.O. Box 7211 Grand Rapids, MI 49510

This book is copyrighted. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, through photocopying, recording, or otherw , ise, without the prior written permission of ABACUS Sofware, Inc.

ISBN 0-916439-01-1

Table of Contents Chapter 1: Programming the VIC-1541

1

1.1 Getting started 1.1.1 After Unpacking 1.1.2 The Disk Operating System 1.1.3 The TEST/DEMO Diskette 1.1.4 Fomatting New Diskettes 1.1.5 Some Facts about a 1541 Diskette 1.1.6 Fundamentals of Disk Techniques

1 1 4 4

1.2 Program Management on Diskette 1.2.1 Save - Storing BASIC Programs 1.2.2 LOAD - Loading BASIC Programs 1.2.3 VERIFY - Checking Stored Programs 1.2.4 SAVE "@: ... " - Replacing Programs 1.2.5 Loading Machine Language Programs 1.2.6 Storing Machine Language Programs

5 5 6

9 9

10 11

12 13 15

1.3 Disk System Commands 1.3.1 Transmitting Commands to the Disk Drive 1.3.2 NEW - Formatting Diskettes 1.3.3 Reading the Error Channel 1.3.4 LOAD"$",8 - Loading the Directory 1.3.5 SCRATCH - Deleting Files 1.3.6 RENAME - Renaming Files 1.3.7 COPY - Copying Files 1.3.8 INITIALIZE - Initializing the Diskette 1.3.9 VALIDATE - "Cleaning Up" the Diskette 1.3.10 ? * - The Wildcards

19 19 20 22 24 26 28 31 32 33 34

1.4 Sequential Data Storage 1.4.1 The Principle 1.4.2 Opening a Sequential Data File 1.4.3 Transferring Data Between Disk and Computer 1.4.4 Adding Data to Sequential Files 1.4.5 Closing a Sequential File 1.4.6 Redirecting the Screen Output

37 37 39 42 46 47 48

1.4.7 1.4.8 1.4.9 1.4.10

Sequential Files as Tables in the Computer Searching Tables Simple Sorting of Tables MAILING LIST MANAGEMENT with Sequential Data Storage 1.4.11 Uses for Sequential Storage

1.5 Relative Data Storage 1.5.1 The Principle 1.5.2 The Advantage over Sequential Storage 1.5.3 Opening a Relative File 1.5.4 Preparing Data for Relative Storage 1.5.5 Transferring Data 1.5.6 Closing a Relative File 1.5.7 Searching Records with the Binary Method 1.5.8 Searching Records with a Separate Index File 1.5.9 Changing Records 1.5.10 Expanding a Relative File 1.5.11 Home Accounting with Relative Data Storage

50 53 57 60 70 71 71 72 73 76 78 83 83 87 90 92 93

1.6 Additional File Structures 1.6.1 Direct Addressing 1.6.2 Indirect Addressing

105 105 107

1. 7 Disk Error Messages and their Causes

109

1.8 Overview of Commands with a Comparison of BASIC 2.0 _ BASIC 4.0 - BASIC 7.0 - DOS 5.1 1.8.1 BASIC 4.0 - BASIC 7.0 Commands 1.8.2 BASIC 7.0 commands

115 116 122

Chapter 2: Advanced Programming

125

2.1 Direct Access of any Block of the Diskette

125

2.2 The Direct Access Commands 2.2.1 The Block-Read Command 2.2.2 The Block-Pointer Command 2.2.3 The Block-Write Command 2.2.4 The Block-Allocate Command

129 129 130 131 133

2.2.5 2.2.6

The Block-Free Command The Block-Execute Command

134 135

2.3 Uses of Direct Access

137

2.4 Accessing the DOS - The Memory Commands 2.4.1 The Memory-Read Command 2.4.2 The Memory-Write Command 2.4.3 The Memory-Execute Command 2.4.4 The User Commands 2.4.5 Additional Possibilities for the User Commands

139 139 141 142 143 145

Chapter 3: Technical Information

147

3.1 TheConstructionoftheVIC-l541 3.1.1 Block Diagram of the Disk Drive 3.1.2 DOS Memory Map - ROM, RAM, I/O 3.1.3 Layout of the I/O Ports (VIA 6522) 3.1.4 The Layout of the Important Memory Locations

147 147 148 149 150

3.2 Operation of the DOS - An Overview 3.2.1 The Disk Controller Routines

155 156

3.3 The Structure of the VIC-1541 Diskette 3.3.1 The BAM of the VIC-1541 3.3.2 The Directory 3.3.3 The Directory Format 3.3.4 The Diskette Recording Process

159 159 161 164 170

3.4 The Organization of Relative Files

175

3.5 DOS 2.6 ROM Listings

181

Chapter 4: Programs and Tips for Using the 1541 Disk Drive

415

4.1 Utility Programs 4.1.1 Displaying all File Parameters 4.1.2 Scratch-protect Files - File Protect 4.1.3 Backup Program - Copying a Diskette

415 415 422 429

4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9

Copying Individual Files to another Diskette Reading the Directory from within a Program Searching for "Hidden" Files Changing the Disk Name and the ID Software Write Protect Invisible Directory

432 434 435 438 441 442

4.2 The Utility Programs on the TESTIDEMO Disk 4.2.1 DOS 5.1 4.2.2 COPY/ALL 4.2.3 DISK ADDR CHANGE 4.2.4 DIR 4.2.5 VIEW BAM 4.2.6 CHECK DISK 4.2. 7 DISPLAY T &S 4.2.8 PERFORMANCE TEST

445 445 446 447 448 448 448 449 449

4.3 BASIC Extensions and Programs for the 1541 4.3.1 Input Strings of Desired Length from the Disk 4.3.2 Easy Preparation of Data Records 4.3.3 Spooling - Printing Directly from the Disk

451 451 456 465

4.4 Overlay Technique and Chaining Machine Language Programs

469

4.5 Merge - Appending BASIC Programs

473

4.6 Disk Monitor for the Commodore 64 and VIC 20

475

4.7 Using "WEDGE" Commands from BASIC Programs

497

Chapter 5: The Larger CBM Disks

499

5.1 IEEE-Bus and Serial Bus

499

5.2 Overview of the "large" CBM Disk Drives

503

ABACUS Software

The Anatomy of the 1541

Chapter 1: Programming the VIC-1541

1.1 Getting Started There it sits, your new Commodore VIC-1S41 disk drive. It's fast and efficient but also intimidating. But have no fear. We will instruct you in the ways of disk programming. The first part of this book gives the beginner an intensive look at the VIC-1S41. At least one example follows each command, thereby explaining its functions and capabilities. You will be surprised how easy the operation of your disk drive can be once you understand the "basics." Beginners probably use the disk drive just to store programs. But a disk drive can be used in many other ways, storing and retrieving data other than programs. This book attempts to uncover these other ways. Experienced programmers should not ignore the first chapter. There may be some sections that may shed light on disk usage. This is especially true concerning relative fIles and data management.

1.1.1 After Unpacking As the proud owner of a new disk drive for your Commodore 64, you probably had just one thought in mind as you left the store where you purchased it: get this "thing" hooked up to the '64 and try it out as soon as possible. When you took the drive out of the box, you noticed that the following parts are included along with it: A power cord A serial connection cable A TESTIDEMO diskette A user's manual Because the VIC-1S41 is not supplied with power from the computer, as is the case with most other computers, it has its own provisions for power. The 120 volt line cord is inserted into the appropriate socket on the back of the device: 1

ABACUS Softwa re

The Anatom y of the 1541

/

Now we need the cable which first looks somewhat like a hi-fi connector cable. It will carrya ll of the data to and from the C64. Connect one of the two ends to the back of the drive:

2

ABACUS Software

The Anatomy of the 1541

It doesn't matter which of the two sockets you use. The two sockets are not provided so that you can connect two '64s to one drive, something which you should never do. The second connection is intended for a printer or for a second drive. If a second drive and a printer are connected, the second drive connects the printer with the computer.

To use the disk drive, the other end of the cable must still be connected to the C64:

When both devices, the disk drive and the C64, are now turned on, you can begin with the first, hopefully successful tests. You will probably want to know if the drive is working properly. To find this out, insert the diskette included with the drive into the drive and close the disk door. Now enter the following command: LOAD "$",8 The RETURN key must be pressed after this string of characters! The disk drive begins to work, indicated by the operating noise and the red LED. A moment later the light is off and you can enter the second command: LIST Don't forget the RETURN key here either. You now see the directory of the TESTIDEMO diskette on the screen. You will learn more about this later.

3

ABACUS Software

1.1.2

The Anatomy of the 1541

The Disk Operating System

The disk drive is a rather complicated device which coordinates mechanical hardware and electronic circuitry to allow the storage of data on the diskette. When the Commodore 64 or VIC-20 needs to read from or write to the disk, it sends commands to the drive along the heavy black cable that connects the drive to the computer. The commands sent by the computer are understood at the disk drive by a built-in program called the Disk Operating System (DOS). The DOS is a lengthy program contained on ROM (Read Only Memory) in the disk drive and it carries out the activities of the drive as commanded by the Commodore 64 or VIC-20. The version of DOS contained in the VIC-lS41 carries the designation CBM DOS V2.6. The Commodore 64 and VIC-20 contain a version of BASIC called COMMODORE BASIC V2.0. Other versions of BASIC (e.g. BASIC 4.0, found in the Commodore 8032) have more advanced disk commands which the VIC-lS41 can also understand. In order to use these advanced disk functions, you have to simulate them in BASIC 2.0. At the end of the chapter is a listing of the BASIC 2.0 commands together with the corresponding BASIC 4.0 commands, as found on the larger Commodore computers.

1.1.3 The TEST/DEMO Diskette The VIC-lS41 disk drive is packaged with a diskette called TESTIDEMO. Some of the programs contained on it cannot be used without adequate knowledge of the way the disk drive works. For now, lay this diskette aside. It will be described in detail later.

4

The Anatomy of the 1541

ABACUS Software

1.1.4

Form atting New Diske ttes

Brand new diskettes must be prepared before using them to store data. Preparing them is called formatting. What does formatting accomplish? Each disk drive mechanism has its ation own special characteristics. A diskette is divided into tracks and inform ). record graph phono a of s is written along each track (similar to the groove r. The number of tracks per diskette varies from one manufacturer to anothe vary. also can which of r Each track is divided into sectors, the numbe During formatting, blank sectors are written to the diskette. A sector is own written to each track-and-sector location and each sector receives its A e. diskett the on n positio "address." This allows the DOS to identify its was sector is also given a code so that the DOS can recognize if this diskette drive disk 541 VIC-1 the for formatted by this type of disk drive. The code and is 2A. The remainder of the sector (called a block) is used to store data accommodates exactly 256 characters. The final purpose of formatting is to construct the directory for the the diskette. The directory is a "table of contents" of the files stored on bility Availa Block the diskette. There is also a special data block (called y in Map or BAM) which indicates if a given block on the diskette is alread the of 18 track on kept are use or available for use. The directory and BAM diskette.

1.1.5 Some Facts about a 1541 Diske tte Diskette: Number of tracks: Sectors per track: Bytes per block: Total number of blocks: Number of free blocks Entries in the directory:

35 17 to 21 (depending on track) 256 683 664 (the directory occupies the remainder) 144 per diskette

5

ABACUS Software

The Anatomy of the 1541

Mechanism: - intelligent peripheral with its own processor and control system - connection to serial bus from CBM 64 or VIC-20, device number 4-15 (8 standard)

1.1.6 Fundamentals of Disk Techniques Diskettes are small round pieces of magnetic film enclosed in square, black jackets. This diskette is prepared for storage by the disk drive. In this process it is divided into tracks and these tracks in tum are divided into sectors. The number of tracks and the number of sectors on a track is dependent on the type of drive. Most use 40 or 80 tracks. The Commodore VIC-1541 drive uses 35 tracks. The following diagram clarifies the division of the disk into tracks and sectors on the 1541:

TRACKS 1-17 (21 SECTORS) TRACKS 18-24 (19 SECTORS) TRACKS 25-30 (18 SECTORS) TRACKS 31-35 (17 SECTORS)

The closer a track is to the center of the disk, the smaller its circumference and the fewer the number of sectors on it. The varying 6

The Anatomy of the 1541

ABACUS Softwa re

tracks is numbe r of sector s is necess ary so that the data density on all of the on the tracks in ing occurr close to equal. Otherw ise the numbe r of errors tracks. outer in ing occurr inside would be greate r than the numbe r of errors is The proced ure by which the diskette is divide d into tracks and sectors has it after until te disket the called "forma tting." Data canno t be placed on been formatted. Let's take a look at the openin gs on the disk jacket:

WRIT E-PRO TECT NOTC H

CENT ER HOLE SLOT FOR READ IWRIT E HEAD

The center hole is placed on the axis of the motor in the drive which h the consta ntly rotates the disk.T he read/write head accesses the disk throug motor read/w rite slot. The head can be positio ned to any track with a second d with called a steppe r motor. Chang ing from track is therefo re accom plishe is disk the the steppe r motor. But how is the desire d sector selecte d? Since be only need head consta ntly turnin g during data access es, the magne tic sector activa ted at the approp riate time. The head recogn izes the addres sed d desire any allows by means of a marke r contai ned on every sector . This sector on the diskette to be accessed. tor The write- protec t notch is optica lly tested by a LED-P hotolT ransis the and it h throug pass Assem bly. If this notch remain s open, the light can es a disk is recogn ized as not being write- protec ted. If one attach

7

ABACUS Software

The Anatomy of the 1541

write-p rotect tab over this notch, the light beam will be broken and the drive recognizes the protec ted diskette. If the tab is attached, every write access to the disk will be rejecte d by the drive. It can no longer be forma tted or written to any other way. It is especi ally impor tant to put write protec t tabs on valuab le disks. All progra m disket tes should be protec ted, and also all data diskettes which will be mainly read from and not written to.

IData tran sfer C64 VIC-15411




8

The Anatomy of the 1541

ABACUS Software

1.2 Progr am Mana geme nt on Diskette The most comm on use of the disk drive is for storing programs. a Storing programs with a disk drive is considerably easier than with of speed the is drive disk the of tage cassette recorder. The greatest advan data transfer to and from the computer. Here's a comparison: Saving a 3 Kbyte program takes: - 75 seconds with the VIC-1530 Datasette - 12 seconds with the VIC-1541 disk drive An additional advantage is that a diskette can store more programs than the the cassette. To load a program, you can consult the directory to see store to you allows drive te casset the selection of programs. Even though time more than one program on a tape, searching for that program is very consuming. Before trying any of the following examples in this chapter, you should remember that the diskette must first be formatted as explained in section 1.3.2 in order to be able to save programs onto it.

1.2.1

SA VE - Storin g BASIC Progr ams Command:

SAVE "name",8

Parameter(s):

"name" - name of the program to be saved

Task:

Save a BASIC program

Example:

SAVE "DEMO 1",8 saves the program with the name "DEM01"

9

ABACUS Software

The Anatomy of the 1541

Perha ps you previo usly owned a datasette on which you stored programs. In this case the commands to save programs onto diskette should look familiar to you. The SAVE command for the disk drive is essent ially the same as for the cassette drive. You need only tell the computer that the program is to be saved onto the disk drive and not on cassette. This is done by adding the device number (usually 8) to the SAVE command. Norma lly the drive is preset to respond to this device number. Now write a small BASIC program and save it with the command: SAVE " TEST " ,8 Type in a NEW command so the program in the computer's memo ry erased. In the following section you will learn how the program can is be retrieved.

1.2.2

LOAD - Loadi ng BASI C Progr ams

Command:

LOAD "name",8

Parameter( s):

"name" - name of the program to be loaded·

Task:

Load a BASIC program

Example:

LOAD "DEMOI",8 loads the program called "DEMO 1"

,,-

As with the SAVE command, this command is similar to the LOAD comm and for the datasette with the addition of the device number. Now load in the previously saved program with: LOAD "TES T",8 10

The Anatomy or the 1541

ABACUS Software

You can check the program by using the LIST command. Any previous It is progra m in memory has now been replaced by the progra m "TEST". us previo the ing replac t possible to load a program into the memory withou called is ry memo in ms progra m in memo ry. Comb ining two progra "merging." An example of merging is presented in section 4.5.

1.2.3

VERI FY - Check ing Store d Progr ams

Command:

VERIFY "name",8

Parameter(s):

"name" - name of the program to be verified

Task:

Compare a program in the computer with a program on the diskette.

Example:

VERIFY "DEMOI",8 compares the program in memory with the program "DEMO 1" on the disk.

is When you have saved a program on disk with the SAVE command, it ut (witho ly proper writtep was m progra often desirable to make sure that the ing error). You can do this with the VERIFY command. It has the follow format:

VERI FY" filena me" ,8 Earlier you saved a progra m with SAVE "TEST" ,8. This progra m shouldt still be in memory. Using VERIFY, check the program in memory agains ter the program stored on diskette. If both programs are identical, the compu responds with OK. To try this out, type a few BASIC lines and then give the following commands: 11

ABACUS Software

The Anatomy of the 1541

SAVE "TES T2",8 VERIFY "TES T2",8 Your compu ter will respon d with OK if it is performing correctly.

1.2.4

SAVE" @: ... " - Replacing Progr ams

If you try to save your small TEST progra m on the disk again, the compu ter will respon d with a FILE EXIST S error and will not compl ete the SAVE . The operat ing system of the VIC-1 541 disk drive does not allow two progra ms to be saved under the same name. This is logical becaus e the compu ter would not be able to distinguish betwe en two progra ms with the same name. Howe ver, you may want to update a progra m on disket te that was previously saved. There are three ways to accomplish this: 1. 2. 3.

Save the program under a different name First erase the old progra m from the disk and save the new one under the old name Use the prefIx @O: in front of the fIle name in the SAVE comm and

This is used as follows:

SA VE" @O:TEST" ,8 If you forget to put the charac ters @O: in front of the filename and try to save a progra m whose name is already contained on the diskette, you get the FILE EXIST S error.

ATTE NTIO N: The developers of the DOS apparently had a bad day when they wrote the part which allows you to replace files by means of the at-sign. There a programming bug somewhere in this section of the DOS. Briefly: is The DOS of the VIC-1541 contains an error which causes the organization of a diskette to be destroyed when a program is saved on a nearly jull disk with 12

The Anatom y of the 1541

ABACUS Softwa re

m the at-sign. This can have the result that when you want to load progra avoid should you "A", progra m "B" will be loaded instead. For this reason rep/acing programs with the at-sign and choose some other method!

For those who would like to know more about saving programs with on the at-sign: The new program may not exceed the remaining free space realize will you file, the disk. If you follow how the DOS overwrites the why: 1.

A free block is designated as the first block of the progra m and its location is stored in the directory entry of the old copy.

2. The new copy of the program is stored in a free area of the diskette. 3. The address of the new files is placed in the address of the old file. 4.

All of the blocks of the old copy are marked as free.

Since the new file is saved onto free blocks on the disk before the the blocks making up the old file are freed, the new file may not exceed the exceed does r; amount of free space on the diskette. If the new progra free space, the save procedure is halted. and It is likely that the error in the DOS lies in step 3 of this procedure that the address of the old file is not put in the proper place.

1.2.5

Loadi ng Mach ine Langu age Progr ams

Machine language programs are handled a little differently from BASIC by programs. A machine language program is transferred to the computer the used, is 1 s addres ary second When using a secondary address of 1. ing program is loaded "absolutely," that is, it is loaded into memory beginn le: examp An file. disk the of bytes two at the address specified in the first

LOAD "MAC HPGR M" ,8,1

13

ABACUS Softwa re

The Anatomy of the 1541

loads the machine language program at an absolute address. For examp the program may be set up to load at the decimal address 49152, and le, started by the comm and "SYS 49152". Should you load a machi is language program without the secondary address, you will most likely ne see the message "SYNTAX ERROR IN .... " if you type RUN. Likewise, trying to LIST the machine language program will display nonsense. Unfortunately, machine language programs are not differentiated from BASIC programs in the directory. Both have the file type PRG. Usually, if typing RUN results in SYNTAX ERROR IN .... , you know that the program is not written in BASIC and should be treated as machine language program. In this case it must be loaded with the comm a LOAD "program" ,8,1. It cannot be started with RUN however! You and must first find the execution address of this program. In a Section 4.1.1 is a program that lists all the file parameters of program. One of the parameters is the load address. This load addres a s usually the initial execution address of the program and can be called is with the comm and SYS load address. You can find the load address of a program with the following program: 10 20 30 40 50 60 70 80

OPEN 1,8,2 , "prog ramn ame,S ,R" GET# l,X$: IF X$="" THEN X$=C HR$(O ) LB=A SC(X$ ) GET# l,X$: IF X$="" THEN X$=C HR$(O ) HB=ASC (X$) CLOSE 1 AD=H B*256 +LB PRINT"LOAD ADDR ESS:" ;AD

The program shows the load address of "programname". Here the program file is opened as a sequential data file. The starting addres s stored as the first two bytes of the file and read using the GET comm is and and appropriately constructed. The first byte is the low byte and the second byte the high byte of the two-byte address. If the function of this progra m is unclear, handling sequential files is clarified in the next sections.

14

---~-

>---------------

The Anatomy of the 1541

ABACUS Softwa re

1.2.6

Storin g Mach ine Langu age Progr ams

a Machi ne language programs are usually written with an assembler or ge langua ne Machi m. progra this machine language monitor and saved using of the programs can also be written from BASIC with the individual bytes ge langua ne machi A ents. statem program stored as decimal values in DATA s: follow ents statem DATA program written in BASIC with the help of 10 20 30 40 50 60 80 90

SA= start ing addr ess EA=e nding addr ess FOR I=SA TO EA READ X POKE I,X NEXT I

DATA DATA

in In this example, the decimal value of the starting address is placed the of values al decim The 20. line line 10 and the ending addres s in individual bytes of the machine language program are typed into the DATA statements of the program, separated by commas. in Naturally, you can save any machine language program that you find and s tediou a er, howev is, This m. progra this book in the form of a BASIC the complicated process. A more elegant and time-saving method is to store the e execut can you way This form. true machine language program in its ing. LOAD after iately immed sion conver icated program without any compl ry: The following program will save such a program that is already in memo 10 20 30 40 50 60 70 80 90

SA= start ing addr ess EA=e nding addr ess OPEN 1,8,1 , "prog ramn ame" HB=I NT(S A/256 ) :LB=S A-HB *256 PRIN T#l,C HR$( LB);C HR$( HB); FOR I=SA TO EA PRIN T#l,C HR$( PEEK (I»; NEXT I CLOSE 1

15

ABACUS Software

The Anatomy of the 1541

This routine assumes that the machine language program is already in the memory of the computer. If a program is already encoded into DATA statements, the following routine can be used to produced a pure machi ne language program: 10 20 30 40 50 60

SA= starti ng addr ess EA=e nding addr ess OPEN 1,8,1 , "prog ramn ame" HB=I NT(S A/256 ) :LB=S A-HB *256 PRIN T#l,C HR$( LB);C HR$( HB); FOR I=SA TO EA

70 READ X

80 PRIN T#l,C HR$( X); 90 NEXT I 100 CLOSE 1 110 DATA . . . . . . . . . . . . . . . . . . . . . . . . . . 120 DATA . . . . . . . . . . . . . . . . . . . . . . . . . .

The addresses and DATA statements must be filled in. The above program writes a machine language program to disk which can later loaded with the command LOAD "programname",8,1. Then the prograbe can be executed with the command SYS (starting address). Machi m ne language programs can also be loaded and executed from a BASIC program. Such a program might have this fonn: 10 IF A=O THEN A=1:L OAD "prog ramna me",8 ,1 20 SYS (star ting addre ss)

The IF command in line 10 is puzzling at first. It must be present becaus after performing a LOAD from within a program, the BASIC interpretere begins executing again at the first line of the new BASIC program. Becau se the machine language program doesn't usually overlay the BASIC progra m in memory, the original BASIC program remains intact and is therefore is re-executed. If you use the routine: 10 LOAD "prog ramna me",8 ,1 20 SYS (star ting addre ss)

the program proceeds to LOAD "programname" again, and the SYS command is never executed. If the variable A is present, the progra m 16

The Anatomy of the 1541

ABACUS Software

branches to line 20 at the end of the fIrst command on line 10. This loader m. can be placed on the diskette together with the machine language prograthe give only need you m, progra ge langua To execute the machine commands:

LOAD "load er" ,8

RUN

ge This has the advantage that the starting address of the machine langua . loader the of SYS the in ed includ is it program need not be known since

17

ABACUS Software

1.3

The Anatomy of the 1541

Disk System Commands

As already mentioned, the VIC-1541 disk drive is similar to the the earlier, larger disk drives of the Commodore family--the CBM 4040, 8050, 8250. They are all intelligent peripheral device with their own processors and operating system. The Disk Operating System (OOS) occupies no space in the memory of the Commodore 64 or VIC-20 and yet offers a flexible set of efficient commands. These commands effectively expand the built-in commands of your Commodore computer. Because the disk drive is an intelligent peripheral, the commands of the DOS can be executed independently of the computer. But because the commands are not found in the version of BASIC supplied in the Commodore 64 or VIC-20, you will have to communicate to the disk using a special method. When the commands are sent to the disk drive, the DOS interprets and carries out the desired task.

1.3.1 Transmitting Commands to the Disk Drive Commands intended for the disk drive are sent over a channel. You can communicate with the disk drive over any of the 15 available channels, but channel 15 is reserved as the command channel. Data transfer over this channel takes place as follows: - open the channel - data transfer - close the channel

(OPEN) (PRINT#) (CLOSE)

In the OPEN command you specify a logical file number (between 1 and 127), the device number of the disk drive (usually 8), and the secondary address (15 for the command channel). You can also send a command to the device as illustrated below:

OPEN lfn,8,15,"command" or OPEN lfn,8,15:PRINT#lfn,"command" 19

ABACUS Software

The Anatomy of the 1541

The number 8 is the device number of the disk drive and the number 15 is the secondary address or channel number. The parameter Ifn is the logica file numbe r which is used in subsequent comm ands (PRINT#, INPUT l #, GET#). It can be a numbe r in the range 1-127. The "command" can either follow the OPEN statement directly, or it can be transferred with a PRINT comm and following the opening. Any number of system commands can # be transmitted until the channel is closed, but must be referenced by the logica l file number used in the OPEN command.

1.3.2

NEW - Form atting Diskettes

Command:

NEW:name,id

Parameter( s):

name - name of the diskette (16 characters max.) id - disk identification (2 characters)

Task:

Format a diskette

Example:

OPEN 15,8,15,"NEW:TEST DISK,NH" formats the disk with the name "TEST DISK" and the ID "NR".

The comm and to forma t a diskette is called NEW and can, as every other command, be abbreviated to its fIrst letter (N). As already mentio ned, the comm and can follow an OPEN comm and or be given in a PRINT # command. The NEW command has the following format:

NEW :diskn ame,i d The parameter diskname may contain up to 16 characters and is stored in the header of the diskette directory. The parameter ID (identifIcation) consis ts of two arbitrary characters, so that the DOS can recognize if a different diskett e 20

ABACUS Software

The Anatomy of the 1541

has been used. Since you can freely choose the ID, this allows you to uniquely identify each diskette. Here is an example for formatting a disk:

OPEN 1,8,15,"NEW:ABCDISK,KL" This command can be abbreviated to:

OPEN 1,8,15,"N:ABCDISK,KL" You need only use the command once--when you first use a brand new diskette. Fonnatting takes about 80 seconds. Fonnatting uses the processor of the 1541 drive while the processor of the computer is not needed; you can continue to work with the computer. To use the command with a PRINT# statement, the following commands must be given:

OPEN 1,8,15 :REM to open the channel PRINT#1,"N:ABCDISK,KL" The number 1 in the PRINT# command is the logical file number corresponding to the OPEN command. Other commands may also be transmitted over this channel after the PRINT# statement. When no more commands are to be transmitted, the channel must be closed. This is accomplished through the use of the CLOSE statement. Give the following command after fonnatting:

CLOSE 1 Now the command channel is closed. The number 1 is again the logical file number of the corresponding OPEN command. NOTE: If no ID is given in the NEW command, the diskette is not formatted, only a new directory is put on and all of the files erased! This is naturally possible only for diskettes which are already fonnatted.

21

ABACUS Software

The Anatomy of the 1541

Once more, the two ways of sending system commands to the disk drive: Opening with simultaneous command transmission:

OPEN 1,8,1 5," ........ .. . CLOS E 1

Opening with subsequent command transmission:

OPEN 1,8,15 PRIN T#I," ....... . .. PRIN T#I," ....... . ..

CLOS E 1 Combination of both ways:

OPEN 1,8,1 5," ........ .. PRIN T#l," ....... . .. PRIN T#I," ....... .. .

CLOS E 1

1.3.3 Readi ng the Error Chann el When the Comm odore 64 or VIC-20 is incorrectly pro(~Tammed, it responds with an error message. Disk comm ands are carrIed out and verified by the processor of the disk drive. Therefore the computer canno directly display error messages that are produced by the disk drive. Errorst are indicated by the flashing red LEi) on the disk drive. In order to 22

ABACUS Software

The Anatomy of the 1541

detennine which error has occurred, the computer must read the error from channel 15. To do this, channel 15 must be OPENed, if this has not already been done. Then the error can be read with the INPUT# command. An error is sent back to the computer in four fields:

Field 1: Field 2: Field 3: Field 4:

Error number Description of the error (string) Track number Sector number

The track and sector infonnation indicate where the error occurred (if these fields are relevant to the command). These four fields of the error message must be read into four variables. You can use an INPUT# statement followed by four variables. An example of reading the error channel:

OPEN 1,8,15 (if not already open) INPUT#I,EN,DE$,TR,SE CLOSE 1 The INPUT# statement must be entered from within a program. It is not legal to issue an INPUT# statement from command mode. 10 OPEN 1,8,15 20 INPUT#l,EN,DE$,TR,SE 30 PRINT EN; DE$; TR; SE (to display the error) 40 CLOSE 1

To understand the operation of this program, first create the following error:

OPEN 1,8,15,"NEW ABCDISK,Tl" CLOSE 1 When you have given these commands, the red LED on the disk drive begins to blink. Did you spot the error? A colon is missing from the command NEW. Now type in the program to read the error channel and enter RUN. The error will appear on the screen:

34 SYNTAX ERROR 0 0

23

ABACUS Software

The Anatomy of the 1541

The 34 is the number of the error, which is explained later. The track and sector fields are 0 because this information is not relevant to this error. If you read the error channel when an error has not occurred, the message:

o OK 0

0

is returned. In any case, if the red LED on the drive blinks, check the syntax of the command, since most errors can be easily recognized. Otherwise, you can simply read the error channel to find the error which the DOS has detected. A detailed description of the error message and their causes follows in section 1.6.

1.3.4 LOAD"$",8 - Loading the Directory The directory is a "table of contents" of the diskette. All the files on the diskette are cataloged here. Be sure to note that loading the directory has a disadvantage: any program previously in memory is overlayed by the directory information, effectively destroying the program. The directory is loaded by typing:

LOAD "$",8 and can be viewed with the LIST command. Try LOADing the directory of the TESTIDEMO diskette that accompanies your disk drive. Insert this diskette into the disk drive and enter LOAD "$",8 to load the directory. Then display the directory by using the LIST command. What appears on the next page should be shown on the screen. A lot of information is kept in the directory. Let's look at the first line, the header of the directory. The number 0 in this line means that this directory is of the diskette in drive O. Other disk drives such as the 4040, contain two disk drives--drive 0 and drive 1. On the 1541 the drive number is always O. Next follows the name and ID of the diskette as set up by formatting. The characters 2A symbolize the disk format. If this format is not 2A then this diskette was not formatted with a 1541 drive.

24

ABACUS Software

o 13 5 4 1

4

11 4 4

6 4

14 9 5 13

The Anatomy of the 1541

"1541 test/ deme, " "how to use" "how part two" "vic-20 wedge" "c-64 wedge" "dos 5.1" "copy/all" "disk addr change" "dir" "view barn" "check disk" "display t&s" "performance test" "sequential file" "random file"

zx 2a prg prg prg prg prg prg prg prg prg prg prg prg prg prg

Next are the individual file names, their lengths in blocks in the first column and the file types in the last column. This diskette contains three main ftle types: PRG These are PROORAM ftles, written in either BASIC or machine language

SEQ Sequential data ftles, explained later REL This is another fonn of data storage, also explained later The length of the files is given in blocks. Each block contains 256 bytes. You can find the approximate size of a program by subtracting 2 bytes from each 256-byte block that the file occupies. Finally, at the end of the directory is the number of free blocks remaining on the disk. When you add the lengths of the files and the number of free blocks, the result is the total number of available blocks on a diskette (664).

25

ABACUS Software

The Anatomy of the 1541

If you own a printer, this directory can be printed as you would print a program listing. Use the following commands:

OPEN 1,4 CMDI LIST PRINT#1 CLOSE 1

open the printer the printer is now linked to the screen the directory will be printed send a RETURN to the printer close the printer again

It is assumed that the directory is already loaded with the LOAD"$",8 command before these commands are executed. By inserting a wildcard when loading the directory, you can cause only part of the directory to be loaded, such as only the programs. This is explained in section 1.3.10.

1.3.5

SCRATCH - Deleting Files

Command:

SCRATCH:namel,name2,name,3 ...

Parameter(s):

name 1 - name' of the file to be deleted (multiple files separated by commas)

Task:

Delete a file from the disk.

Example:

OPEN 1,8,15,"SCRATCH:DEM01" deletes the program with the name DEMO 1.

Sometimes an unneeded file must be removed from the diskette. The SCRA TCH command is provided for doing so. Before using this command, you must be sure that the name given in the SCRATCH command corresponds with the file to be deleted. An unintentionally deleted file can ruin many hours or even days of work, so be careful before using this command. 26

ABACUS Software

Anatomy of the 1541

To delete a file, the following format should be used:

PRINT#ifn, " SCRATCH: filenamel, filename2, ... " More than one file can be deleted by using a single command. But remember that only 40 characters at a time can be sent over the transmission channel to the disk drive. For example, to erase a file with the name TEST, the following commands are used:

OPEN l,8,l5,"S:TEST" CLOSE 1 If channel 15 is already open, only the PRINT# command is required:

PRINT#l," S:TEST" It is possible to delete the entire contents of a diskette. This is discussed in section 1.3.10, the wildcard character (*):

PRINT#l,"S:*" But be very careful! Make sure that you do not need any of the files on the diskette before using this command. After completing the operation the error channel transfers the message:

01 FILES SCRATCHED nn 00 where nn is the number of deleted files. This message can be read with the routine given in section 1.3.3.

27

ABACUS Software

1.3.6

Anatomy of the 1541

RENAME - Renaming Files

Command:

RENAME:new=old

Parameter(s):

new - new program name old - previous program name

Task:

Change the name of files on the disk.

Example:

OPEN 1,8,15,"RENAME:DEM02=DEMOI" changes the name of "DEMO 1" to "DEM02".

You can also change the name of a file on the diskette. The command RENAME is provided for this purpose. It has the following format:

RENAME:newname=oldname For example, if you want to change the name of the file from TEST to PEST you would use the following commands:

OPEN 1,8,15," R:PEST=TEST" CLOSE 1 or

OPEN 1,8,15 PRINT#I," R:PEST=TEST" CLOSE 1 Note that you cannot rename a file until it is CLOSEd. This command offers you a safe way of updating programs. Assume that we want to load the program" SUPERPROG" from disk, edit it, and then save the new version. The following procedure has proven itself in practice:

28

ABACUS Software

Anatomy of the 1541

1. Load the old version of the program

LOAD "SUPERPROG",8 2. Run or edit the program 3. Save the prof;!Iam with a dummy name

SA VE "SUPERPROG.NEW",8 4. Verify the save

VERIFY "SUPERPROG.NEW",8 5. Delete the old version of the prof;!Iam

OPEN 1,8,15,"S:SUPERPROG" 6. Rename the new version

PRINT#l,"R:SUPERPROG=SUPERPROG.NEW" 7. Close the command channel

CLOSE 1 Another, not quite so safe method, is the following: 1. Load the old version of the program

LOAD "SUPERPROG",8

29

ABACUS Software

Anatomy of the 1541

2. Run or edit the pro~ram 3. Delete the old version of the pro~ram

OPEN 1,8,15 ,"S:S UPER PROG " 4. Close the command channel

CLOSE 1 5. Save the pr01~ram

SAVE "SUP ERPR OG", 8 6. Verify the save

VERIFY "SUP ERPR OG", 8 Step 5 may come before step. 4. Note the following safety hierarchy in replacing one version of a program with another: Certainty factor

Method

Very high

Load old - change old - save new - verify new - delete old - rename new

High

Load old - change old - delete old - save new - verify new

"Luck"

Save with at-sign

When developing a program, it is advisable to save it from time to time. A power -outag e could have disastrous results. It is recom mende d that you

30

ABACUS Software

Anatomy of the 1541

always save the program under a new name (such as TESTI, TEST2, TEST3, ... ) and then delete all of the old versions of the program when you are done. This methcx.l saves time but is still safe.

1.3.7

COPY - Copying Files

Command:

COPY :new=old 1,old2,old3, ...

Parameter(s):

new - new file old x - files to copied over

Task:

Chains separate files into one.

Example:

OPEN 1,8, I5,"COPY :DATA=DATI ,DA T2,DAT3" combines the files DATI, DAT2, and DAT3 into one file called "DATA".

Using this command, a file can by copied on a diskette. Several different sequential files can be used to create a new file. If, for example, you have a data record for each month of your household expenses and they have the names EXP.Ol, EXP.02, etc. you can combine them into quarters (EXP.QI for example) with this command. The COpy command has the format:

COPY :newfile=oldfiIe l,oldfile2, ... So, the named data records can be combined as follows:

OPEN 1,8,15," C:EXP.Ql=EXP.Ol,EXP.02,EXP.03" CLOSE 1 This method of combining data records cannot be used for programs. Only a single program can be copied on the diskette. Also the name of the new file must not already exist on the diskette. 31

ABACUS Software

Anatomy of the 1541

The COpy command is rarely used. This is because copying files onto the same diskette usually makes no sense. The only sensible use of the command is to combine several sequential or user files into a single file. Copying files from one diskette to another diskette is much more sensible. This is indispensible for data security. If you own two disk drives, you can assign the device number 9 to one of them and use the program COPY/ALL to copy files from one to the other. This program is found on the TESTIDEMO diskette. We have also thought of those of you who have only one disk drive. A utility program is included in section 4.1 to allow you to copy individual files and even the entire diskette.

1.3.8

INITIALIZE - Initializing the Diskette

Command:

INITIALIZE

Parameter(s):

none

Task:

Resets the BAM

Example:

OPEN 1,8,15,"INITIALIZE" or OPEN 1,8,15,"1"

The DOS requires that a BAM (Block Allocation Map) be present on each disk. The BAM is a layout of the usage of the blocks on each diskette. It marks each block on the diskette as free for use or allocated (already in use). If you change diskettes in the drive and the new diskette has the same ID as the old diskette, the DOS will not recognize the fact that you have changed diskettes. The BAM of the new diskette will be different, but the DOS will still be working with the old BAM. 32

Anatomy of the 1541

ABACUS Softwa re

t Therefore, each diskette should be given a unique ID when you forma the force can You ID. nt differe a e diskett each it. It is a good practice to give disk drive to read the BAM of a new diskette by issuing the INITIALIZE command. This command has the following format:

PRIN T#lfn ," INITI ALIZ E" or shortened to

PRIN T#lfn ," I" Example:

OPEN 1,8,15,"1" CLOSE 1 ly If you change diskettes and also change data records, then we strong the ing chang after and comm LIZE INITIA the recom mend that you use diskettes, to be safe.

1.3.9 VAL IDAT E· "Clea ning Up" the Diskette Command:

VALIDA1E

Parameter( s):

none

Task:

Free all allocated blocks which do not belong to any file.

Example:

OPEN 1,8,15,"VALIDATE"

The VALIDA TE comm and frees all allocated blocks that are not and assigned to normally CLOSEd files. For example, if you OPEN a file

33

ABACUS Softwa re

Anatomy of the 1541

transfer data to that file, but forget to CLOS E it, the V ALID ATE comm and can be used to free the data blocks that were written to. If you use the direct access comm ands, be sure to allocate them (using the BLOC K-ALL OCAT E command) or the VALID ATE comm and will free them again. The comm and has an additio nal function: If a file is delete d using the SCRA TCH comm and, the file type in the first byte of the file entry is set to O. It no longer appear s in the directory. If you now change this byte back to its old file type with the DOS monit or (descr ibed later) or other direct access comm ands, V ALID A TE will restore the file. If it has not been overw ritten, it will be the same as before the SCRA TCH comm and. The comm and has the following format:

PRIN T#lfn ," VALID A TE" or the shorte r form

PRIN T#lfn ," V" An example:

OPEN 1,8,15 ,"V" CLOS E 1 If you have a disket te such that the sum of the file length s plus numbe r of free blocks does not equal the total numbe r availa ble (664), the use the VALID ATE comm and to restore it.

Anoth er examp le: If you try to store a progra m or data record that uses more than the numbe r of free blocks, the DOS will give the error DISK FULL . If the disk had shown some blocks free before, the numbe r is now zero. The VALID ATE comm and will restore the original free blocks.

1.3.10 ?

* - The

Wildc ards

There are two wildca rd charac ters--t he asteris k (*) and the questi on mark (?). The asteris k at a given place in the filenam e symbo lizes that the first or all files on the disket te which begin with the charac ters before the asterisk are relevant. An example:

34

ABACUS Software

Anatomy of the 1541

LOAD"TEST*" ,8 This command loads the first program that begins with the first four letters "TEST". The command:

LOAD" *" ,8 loads the first program on the diskette because there are no characters in front of the asterisk. The asterisk in the SCRATCH command has a different effect. If used in the SCRATCH command, not only the first file will be deleted, but all files. For instance, the command:

OPEN 1,8,15,"S:TEST*" CLOSE 1 erases all files beginning with the the letters "TEST". This must be taken into account! Loading the directory with an asterisk can also select certain files. An example:

LOAD"$A *",8 loads only the directory of the files that begin with the letter" A". The DOS offers an additional use of the asterisk that has not been mentioned yet. It can also select file types if the asterisk is followed by the first letter of the desired file type. Here is a summary:

*=S *=P *=R *=U

selects only sequential files selects program files selects relative files selects user-files

For example, the command:

LOAD "$*=P",8 causes only the directory entries of programs (PRO) to be loaded and shown when you type LIST. This can also be used with the SCRATCH command to delete all sequential files, for instance. Here is the command:

35

ABACUS Software

Anatomy of the 1541

OPEN 1,8,15," S:*=S" CLOSE 1 With the question mark, certain characters of a fIlename can be declared "not relevant." To illustrate the function of the question mark, here are two examples of shortened fIlenames and their effects: A?????

- refers to a six-letter fIlename, the fIrst character of which is A

????TEST

- refers to an eight-character filename, the last four letters of which are TEST

A combination of asterisks and question marks is allowed. You should notice, however, that an asterisk followed by question marks has no meaning. Two examples of combinations of asterisks and question marks: ???? *

- refers to all flle names that have four characters before a period TEST.??* - refers to all file names having at least 7characters, of which the fIrst five are"TEST." TEST-??O 1*=S - refers to all sequential files whose names have at least nine characters, the first five being TEST- and the eighth and ninth being 01

36

Anatomy of the 1541

ABACUS Softwa re

1.4

Sequential Data Storage

A disk drive can be used for more than just storing programs. If you need a have written a progra m that manages a large quantity of data, you it is but , fastest the not is fast way of organizing it. Sequential data storage to rable compa is d the easies t metho d of manag ing data. This metho as m progra a in ined sequential storage on a cassette, which can be mainta follows: 1. Load the program 2. Read the entire data file into the memory of the computer 3. Work with the data in memory (change, delete, combine) 4. Write the new fIle on an external medium (cassette, diskette) 5. Exit the program The maxim um numb er of data items that the progra m can handle item depends on the size of the computer's memory because a single data end, that To e. diskett cannot be changed or erased directly on the cassette or ten rewrit then and the entire set of data items must be read in, changed, drive disk a on faster again. Readi ng and rewriting the data occurs much than on cassette. data It is worth mentioning that programs which work with sequential the Only disk. with work on casset tes can be easily modif ied to d. corresponding OPEN commands need be change

1.4.1

The Princ iple

r A sequential data file consists of several data records that are furthe tes illustra and file s addres and name a is ing divided into fields. The follow ses the principle of sequen tial data storage. Individual names and addres fields l severa of ts consis record A file. this of s compr ise the data record like (last name, first name, etc.). The structure of the file looks something this:

37

ABACUS Software

Anatomy of the 1541

FILE Record 1 Record 2 Record 3 Record 4 Record 5

The data records of a file are stored one after another (sequentially) as are the the fields within each record. The fields and records may be of any length. For example, field 1 of record 1 may be longer than field 1 of record 2. This is possible because the fields are separated from each other by a special character (the RETURN character), which is generated by the PRINT# statement. When read back into the computer by the INPUT# statement, the RETURN character is recognized as a field separator. Each field is associated with a variable when written with a PRINT# statement or read with an INPUT# statement. How does the computer know, when reading the data, where each field ends? Each field ends with a RETURN character. The RETURN character has the decimal ASCII value 13. An example of a telephone directory file illustrates this. Our telephone directory file has three fields:

FIELD 1: FIELD 2: FIELD 3:

LAST NAME FIRST NAME TELEPHONE EXTENSION

38

Anatomy of the 1541

ABACUS Software

FILE Record Record 2 Record 3

ted You can see that the fields are of different lengths and are all separa written y aticall autom by a RETU RN character. This RETU RN character is ent after the data field by a PRINT # statement, provided the PRINT # statem ter). charac RN is not followed by a semicolon (which suppresses the RETU T# These data items are assign ed to the variab les with an INPU next the read to order statement. After that, another INPUT # must follow in writing field, and so on. The following sections explain the fundamentals of programs using sequential data storage.

1.4.2 Open ing a Seque ntial Data File To create a sequen tial data file, you must first OPEN the file. When opening a file to be written to, the following is carried out:

1. The disket te is check ed to see if an existing file has the same name. If so, the error message FILE EXISTS is given by the DOS. 2. The file entry in the directo ry is written. In the file type it is noted that this file is not yet CLOSEd. This appears in a directory listing with an asterisk which preceeds the file type. 3. A free block is found, into which the first data items are written. The address (track and sector) of this free block is stored in the file entry of the directory. 39

ABACUS Software

Anatomy of the 1541

4. The number of blocks in the file is set to 0, because no blocks of the file have been written yet. The OPEN command specifies for what purpose (mode) the file is to used (reading or writing). The format of the OPEN command looks be like this:

OPEN Ifn,8, sa," filena me,fi letype ,mode " When the logical file number (lfn) is between 1 and 127, a PRINT statement sends a RETURN character to the file after each variable. If # logical file number is greater than 127 (128-255), the PRINT# statem the ent sends an additi onalli nefeed after each RETURN. This is necessary for printe rs that do not provid e an automatic linefeed after a RETU RN character, for example. The secondary address (sa) can be a value between 2 and 14. The secondary address indicates the channel over which the compu ter is transfer data to and from the disk drive. Secondary addresses 0 and 1 to are reserved by the DOS for saving and loading programs. Secondary addres 15 is designated as the command and error channel. Should several files s open at once, they must all use different secondary addresses, as only be file can use a channel. If, however, a file is opened with the secondone ary address of a previously opened file, the previous file is closed. A maximum of 3 channels can be opened with the VIC-1541 at a When utilizing relative data files, the DOS requires 2 channels pertime. file. Therefore, the following maximum combinations are possible:

- 1 relative and 1 sequential file, or - 3 seque ntial files When specif ying the filename to be written to (in the OPEN command), you must be sure that the file name does not already exist on the diskette. If a file that already exists is to be to opened for writing, the file must first be deleted. The @-sign method should not be used. For examp le:

OPEN 1,8,15 ,"S:A DDRE SSES ":CLO SE 1 OPEN 1,8,2, " ADDR ESSE S,S,W "

40

ABACUS Software

Anatomy of the 1541

The file type must be given when the file is opened. The file type may be shortened to one of following:

S U P R

- sequential file - user file - program - relative file

User files are sequential files that are listed in the directory with the file type USR.They are not data files in the true sense. This file type is usually used when output that normally goes to the screen (BASIC listing, directory) is sent to the disk. In section 1.4.6 you find a description of this technique. The last parameter (mode) establishes how the channel will used. There are four possibilities:

W R A M

Write a file (WRITE - section 1.4.3) Read a file (READ - section 1.4.4) Add to a sequential file (APPEND - section 1.4.4) read a file that has not been closed (It discovered" by us in the DOS listing and explained in Section 1.4.5)

Now open a sequential file with the name SEQU.TEST for writing:

OPEN 1,8,2,"SEQU.TEST,S,W" If you now load the directory with LOAD" $",8 and then LIST it, you see this file listed with an asterisk before the file type:

o

SEQU.TEST

*SEQ

But you are no longer allowed to close this file! After a file is OPENed and data written to it, it must be closed before the directory is loaded! The command/error channel 15 may be opened while a file is open, but when channe115 is closed, all other channels are closed as well. You must take note of this.

41

ABACUS Software

Anatomy of the 1541

Now some examples of the OPEN command: OPEN 1,8,2," SEQU. TEST,S,R"

-

open a sequential fIle for reading - open a user fIle for writing - open a program fIle for reading - open a sequential fIle for appending data - open the unclosed customer fIle for reading

OPEN 2,8,3,"SEQU.TEST,U,W" OPEN 3,8,4,"TEST,P,R" OPEN 4,8,5,"SEQU.TEST,S,A" OPEN 5,8,6,"CSTMRS.1983,S,M"

1.4.3 Transferring Data Between Disk and Computer After opening a file for writing, you transfer data to be stored to the diskette with the PRINT# statement. This statement transmits an additional RETURN that is required for separating data. In the following example, a file is OPENed, data written to it, and the file is CLOSEd again. PRINT# can also be used as a direct command, that is, outside of the program, so the following commands can be typed one after the other and executed. Now open a file with the name "TEST':

OPEN 1,8,2,"TEST,S,W" You should notice that the red LED on the disk drive is lit. It signals the fact that a file was OPENed. You can now write to the file named TEST. Here is how we would write a name and address record consisting of 4 fields:

PRINT#l," SAM" PRINT#l," HARRIS" PRINT#1,"2001 MAIN STREET" PRINT#l," ANYTOWN" Now these data items have been written to the file, so we close the file with CLOSE 1. The red LED should go out. In order to read this data again, you must open the file in the read mode (R). Because the INPUT# statement cannot be used in the direct mode, a small program must be written: 42

ABACUS Software

Anatomy of the 1541

10 20 30 40 50

OPEN 1,8,2, "TEST,S,R" INPUT#l,NF$ INPUT#l,LN$ INPUT#l,ST$ INPUT#l,CT$ 60 CLOSE 1 70 PRINT"FIRST NAME: " ;NF$ 80 PRINT"LAST NAME: " ; LN$ 90 PRINT"STREET: ";ST$ H;CT$ 100 PRINT"CITY:

The program is simple to explain: Line 10

The file TEST is opened for reading

Lines 20-50

The data are read in the same order as they were written. Variables are used so that the data can be printed later.

Line 60

The file is closed.

Lines 70-100 The data are printed out on the screen. When you enter this program and type RUN, the data will appear on the screen as written earlier:

FIRST NAME: LAST NAME: STREET: CITY:

SAM HARRIS 2001 MAIN STREET ANYTOWN

Four INPUT# statements were used to read the data because the name and address record is composed of four fields. But when a record is written that has, say, 20 fields, it is very time-consuming to type out 20 INPUT# statements. A loop can make this much simpler. This is obvious in this example:

43

ABACUS Software

Anatomy of the 1541

10 20 30 40 50 60

OPEN 1,8,2 ,"TE ST,S ,R" FOR I=l TO 4 INPU T#l,D $(I) NEXT I CLOSE 1 PRIN T"FIR ST NAME: n;D$ (l) 70 PRINT "LAST NAME: ";D$( 2) 80 PRINT "STRE ET: ";D$( 3) 90 PRINT"CIT~: n;D$( 4)

Here, instead of four separate string variables, an array with index 1-4 is used. It should be noted that in BASIC 2.0, the array must be dimensioned with a DIM statement if an index higher than 10 is used. Should we want to read in 20 fields, the statement DIM D$(20) must be gi ven before any are read. There are still more ways of shortening input and output of data. With the INPUT statement for keyboard input, several variables can be given in one line, separated by commas. For example:

INPU T NF$,L N$,TE With this statement, three variables must be entered, such as:

NICH OLAS ,MUL LER, 7465 The read data can be printed on the screen with:

PRIN T NF$,L N$,TE In this manner, sequential data can be written and later read back again. The only difference is that the string variables containing the data in be written must be separated by commas enclosed in quotes. For examp to if you wish to write the previous variables to a file, the PRINT# statem le, ent command must changed as follows:

PRIN T#l,N F$" ,"LN$ " ,liTE Numeric variables need only be separated with a comma from the other variables. To read the data, use the command:

44

Anatomy of the 1541

ABACUS Softwa re

INPU T#l,N F$,LN $, TE Becau se the maxim um numbe r of characters read by an INPU T# ally statement may not exceed 88, this method of reading is only margin nt differe a long, ters charac useful. If a field in a record is more than 88 each statement must be used. This is the GET# statement, which reads of record a read to want individual character, one at a time. Suppose you string a in placed be can which a field is 100 characters long. This record variable with the following routine: 10 20 30 40 50 60 70 80

OPEN 1, 8, . . . . . . . . . . . . . . D$=" " FOR I=l TO 100 GET# l,X$ D$=D$+X$ NEXT I GET# l,X$ CLOSE 1

At the end of this program, the string variable D$ will contain the 100 DOS characters of the data field. After opening a sequential data file, the We read. be to ter establishes a pointer that always points to next charac assume that the data was written with a PRINT# statement without a trailing After semicolon, so that a RETURN was written at the end of the data item. The RN. RETU this to reading the first 100 characters, the pointer points of end the at found RN next GET# in line 70 is necessary to read the RETU the not and field next the the field. Then the next GET# statement can read RETURN. In the above example, we used data records with a constant length of of 100 characters. According to the rules of sequential access, the length only can ent statem # INPUT the Since nt. data records need not be consta to read a maxim um of 88 characters, we will use the GET# statement this: recognize the RETURN as the end of a field. Such a routine looks like 10 20 30 40 50 60

OPEN 1,8, . . . . . . . . . . . . . . . . . . . . . . S$="" GET# l,X$ IF X$=C HR$(1 3) THEN 80 S$=S$ +X$ IF ST 64 THEN 30

45

ABACUS Software

Anatomy of the 1541

70 CLOSE l:END 80 PRINT S$ 90 GOTO 20

Here a file with variable record length is read and printed on the screen. Naturally, you can use the data in other ways instead of printing it on the screen. To avoid the problem of reading data records of more than 88 characters, divide the record into several parts, which you can combine after reading them.

1.4.4

Adding Data to Sequential Files

If you want to add data to a sequential file, you have to read the entire file into memory, add the data, and write the new file back to the diskette again. This is a very time-consuming process. For this reason, the DOS offers an easier alternative to add to a sequential data file without reading the entire file. This is made possible through the OPEN mode A (Append). If you have a sequential data file, as in the previous section, you can add data to it by selecting the A mode in the OPEN command. An example follows. Give the following commands:

OPEN 1,8,2,"TEST2,S,W" PRINT#l,"lst DATA RECORD" CLOSE 1 Now you have a sequential data file containing one data record. This file can be expanded with two more records as follows:

OPEN 1,8,2,"TEST2,S,A" PRINT#1,"2nd DATA RECORD" PRINT#1,"3rd DATA RECORD" CLOSE 1

46

ABACUS Software

Anatomy of the 1541

Now the file TEST2 has three data records. You can check this with the following program: 100 110 120 130 140 150

OPEN 1,8,2, "TEST2,S,R" FOR I=l TO 3 INPUT#l,DR$ PRINT DR$ NEXT I CLOSE 1

After the program starts, the data record is read and printed on the screen. You can see that the append A mode makes it quick and easy to expand a sequential data fIle.

1.4.5

Closing a Sequential File

OPENed data files can be closed with the CLOSE command. This command has the format:

CLOSE Ifn The parameter lfn is the logical file number of the file that was used in the OPEN statement. Should several files need to be closed a CLOSE statement must be given for each one. When the last file is closed, the red LED on the drive goes out. As you already know, data are sent to the disk drive over a channel. This channel uses memory inside the disk (called a buffer) in which the data transmitted by the computer is stored. When this buffer is full, its contents are written to the diskette. When the file is closed, any data still in the buffer is written to the diskette. An unclosed file is incomplete and is also not recognized by the DOS as a properly closed file. The DOS allows no read access in the R (Read) mode and responds WRITE FILE OPEN when trying to read an unclosed file.

47

ABACUS Softwa re

Anatomy of the 1541

This could be a proble m if the DOS did not allow any read access to a file. For this reason, the DOS offers the M mode. A file that is marke d as an improperly closed file can be read in this mode. It is logical to then write these records to a second file which can then be properly closed. In this way one can "rescue" a file. The following program will transfer an improperly closed file (origin al me) to a correctly closed me (destination file): 100 110 120 130 140 150 160 170 180 190

INPUT "ORIG INAL FILE NAME";S$ INPUT"DESTINATION FILE NAME";D$ OPEN 1,8,2 ,S$+ ",S,M " OPEN 2,8,3 ,D$+ ",S,W " INPU T#l,X $ PRIN T#2,X $ IF ST 64 THEN 140 CLOSE l:CLO SE 2 OPEN 1,8,1 5,"S: "+S$ CLOSE 1

At the compl etion of the progra m, the unnee ded origin al file is delete d (scratched) .

1.4.6 Redir ecting the Scree n Outpu t Any output appearing on the video screen (PRINT, LIST, etc) can be redirected to a sequential data file. This is accomplished through the CMD command, which has the following format:

CMD Ifn For this to occur, a file of type USR must be opened. To transfer a BASIC progra m listing , for instan ce, as a sequen tial file on disket te, use the following commands:

OPEN 1,8,2, "TES T.LIS T,U,W " CMD 1 LIST 48

ABACUS Software

Anatomy of the 1541

CLOSE 1 The command CLOSE 1 causes further output to be sent to the screen. Storing a program as a sequential file on disk is very useful, if, for example, you would like to read a program with a word processor to edit it. It is assumed that the word processor in this case reads data stored in ASCII code. This is how the listings in this book were transferred from a Commodore 64 to a Commodore 8032 for final printing. In order to print this file on the screen again, you need the following routine: 10 20 30 40 50

OPEN 1,8,2, "TEST.LIST,U,R" GET#l,X$ PRINT X$ IF ST64 THEN 20 CLOSE 1

This routine is a loop that reads every character (byte) of the file and displays it on the screen. The end of the file is signalled by the status variable (ST) which is set to 64 at the end of the file. To send a sequential fIle to the printer, use the following program: 10 20 30 40 50 60

OPEN 1,8,2,"TEST.LIST,U,R" OPEN 2,4 GET#l,X$ PRINT#2,X$ IF ST64 THEN 30 CLOSE 1

Here it is ao;sumed that the printer is connected as device address 4.

49

ABACUS Software

Anatomy of the 1541

1.4.7 Sequential Files as Tables in the Computer Sequential data files must reside completely in the computer for data management. Most of the time, a two dimensional table can be used. This table is also called an array or matrix, because a data element can be addressed through the input of two coordinates. To this end, you use a two dimensional variable, which must be reserved with a DIM statement. The first dimension corresponds to the data record, the second dimension to the field inside the record. This diagram shows an example of a table: Field 1

Field 2

Field 3

Table

Record 1

in the

Record 2

Computer

Record 3 Record 4 Record 5 Record 6

This table is a file composed of six records which have three fields each. The variable D$ is reserved with DIM D$(6,3). To read a sequential file as a table, it is necessary to create such a file with, for example, six records with three fields each. For this purpose, use the following program: 100 110 120 130 140 150 160 170 180 190

OPEN 1,8,2, "TABFILE,S,W" FOR X=l TO 6 PRINT CHR$(147) PRINT"RECORD ";X PRINT"---------" FOR Y=l TO 3 PRINT"FIELD n;y;n: "; INPUT X$ PRINT#l,X$ NEXT Y

50

ABACUS Software

Anatomy of the 1541

200 NEXT X 210 CLOSE 1

Two nested loops are used here, whose variables are numbered with the record and field. Enter six data records. When the program is done, these records will be contained on the diskette with the filename of T ABFILE. A tip: save this program with SAVE"TABPROG",8 so you can use it later. This file can now be loaded into the computer as a table. Two nested loops indexed for the table are necessary: 100 110 120 130 140 150 160 170

OPEN 1,8,2,"TABFILE.SEQ,S,R" DIM D$(6,3) FOR X=l TO 6 FOR Y=l TO 3 INPUT#l,D$(X,Y) NEXT Y NEXT X CLOSE 1

This program places data into the table. You can check this with PRINT statements to see if the data has been stored in the right place. Because each field can be addressed with indices, you can give a command like PRINT D$(l,2) to see the second field of record one. It is meaningful to be able to display the fields of a given record. Use the following routine for this purpose, after you have saved the previous program: 100 110 120 130 140

INPUT" RECORD NUMBER: "; X PRINT"------------------" PRINT"FIELD 1: ";D$(X,l) PRINT"FIELD 2: ";D$(X,2) PRINT"FIELD 3: ";D$(X,3)

Notice that the first index (the record number) after the input is used as the variable in the field output. The second index (field number) is then constant. This table can now be altered as desired. Add the following lines to the preceeding program:

51

ABACUS Software

160 170 180 190 200 210 220 230 240

Anatomy of the 1541

PRINT"------------------lf INPUT"FIELD TO CHANGE:";Y INPUT"NEW CONTENTS: ";D$(X,Y) PRINT"OK" PRINT"FURTHER CHANGES (YIN)?" GET X$:IF X$="" THEN 210 IF X$="Y" THEN 100 IF X$="N" THEN END GOTO 210

Here the number of the field to be changed is used as the second index, which is adjacent to the index of the record whose element is being changed. This modified table must now be written to the diskette again. You can use the following routine. Don't forget to save the previous edit program first! 100 105 110 120 130 140 150 160

OPEN 1,8, 15, "S:TABFILE,S,W" OPEN 1,8,2, "TABFILE,S,W" FOR X=l TO 6 FOR Y=l TO 3 PRINT#l,D$(X,Y) NEXT Y NEXT X CLOSE 1

This routine also is relatively short because of the use of nested loops. The old file is erased before the new file is stored. This is done in line 100. Accessing data through the use of the table is very fast. The access time is independent of the size. The size of the table and therefore the quantity of data is dependent on the memory capacity of the computer, however. The large storage area of the Commodore 64 is excellent for table management. If you write a data management program that occupies 8K bytes, then 30K bytes still remain for storing data. If you consider that storing a name and address record of about 80 characters, you can still store 384 records in memory! And this with an access time that cannot be surpassed by refined data management techniques (indexed sequential, relative). But with larger quantities of riata, sequential storage is no longer feasible.

52

ABACUS Software

1.4.8

Anatomy of the 1541

Searching Tables

As mentioned in the table processing section, each data record of a table can be indexed. Because the table is two dimensional, the fIrst index selects the data record. If a record of the table is to be changed or accessed, the operator must know the record number. The record number can be a part or customer number. There are files, however, for which there is no suitable method of numbering. In such files, the number of the record must be found through a search of all the records. Here is a practical example: First of all, create a data file with the following program. Names and telephone numbers are saved in the example: 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240

OPEN 1,8,2, "TELEDAT,S,W" PRINT CHR$(147) INPUT"LAST NAME : " ; LN$ INPUT"FIRST NAME :";FN$ INPUT"AREA CODE :";AC$ INPUT"NUMBER :" ;NU$ PRINT"INFORMATION CORRECT (YIN)?" GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 170 IF X$="N" THEN 110 PRINT#l,LN$", "FN$","AC$", "NU$ PRINT"MORE INPUT (YIN)?" GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 200 IF X$="N" THEN 240 GOTO 110 CLOSE 1

Program Documentation: Line 100

The sequential ftle "TELEDAT' is opened for writing

Line 110

The screen is cleared

Lines 120-150

The four fields are entered from the keyboard

Lines 160-180

If the data are not correct, they can be entered again

53

ABACUS Software

Anatomy of the 1541

Line 190

The four fields are written to disk

Lines 200-220

Here the execution of the program can be ended

Line 230

Input will be continued

Line 240

The file opened in line 100 is closed

Type this program in, RUN it, and enter some data. Save the the program on diskette so you can combine it with other routines later if you like. In the last section of this chapter is a complete program for managing your telephone numbers. If you have entered some data, you would probably like to find a telephone number. To do so, you could print the entire file on the screen or printer and find it yourself. This is, however, a wasteful method, especially if you have entered many records.

The search for the telephone number corresponding to a given name can be performed by the computer. It runs through the whole list, looking for the desired name. Once found, it gives you the complete record which contains that name. The following routine accomplishes this: 100 OPEN l,8,2,"TE~EDAT,S,R" 110 DIM D$(100,4):X=1 120 INPUT#l,D$(X,l),D$(X,2),D$(X,3), D$(X,4) 130 IF ST64 THEN X=X+1:GOTO 120 140 CLOSE 1 150 PRINT CHR$(147) 160 PRINT"DESIRED NAME: ";N$ 170 FOR I=l TO X 180 ID D$(I,l)=N$ THEN 210 190 NEXT I 200 PRINT"NAME NOT FOUND! ":GOTO 280 210 PRINT"NAME FOUND:" 220 PRINT"-----------" 230 PRINT"LAST NAME: ";D$(I,l) 240 PRINT"FIRST NAME: ";D$(I,2) 250 PRINT"AREA CODE: ";D$(I,3) 260 PRINT"NUMBER: ";D$ (I, 4)

54

ABACUS Software

Anatomy of the 1541

270 PRINT"-----------" 280 PRINT"MORE (YIN)?" 290 GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 290 300 IF X$="Y" THEN 150 310 PRINT"PROGRAM DONE" : END

Program Documentation Line 100

The sequential file "TELEDAT" is opened for reading

Line 110

The table is dimensioned for 100 records and the index is set to one

Line 120

The data records are read into the table

Line 130

The status variable ST is checked for end of file (indicated by a value of 64). If the end has not been reached, the index is incremented and a new record is read.

Line 140

The file opened in line 100 is closed

Line 150

The screen is cleared

Line 160

The last name to be searched for is read from the keyboard and placed in the variable N$

Lines 170- 190

The loop searches the table of records, checking the name fields against the desired name. If the position is found, the program branches to the output routine

Line 200

The name was not found

Lines 210-270

The record containing the desired name is displayed

Lines 280-310

The possibility to search for a new name is allowed

You will notice that this search is quite fast when the data is already loaded into the computer. Searching the computer's memory is faster than searching the diskette. The program can be easily changed to search for a 55

ABACUS Software

Anatomy of the 1541

desired field other than the name. You might want to search for an area code, for instance. This program stops the search when the first matching data record is found. This is not always desired, however. If, for instance, you wish to search the table looking for a particular area code and want all matches to be displayed, a different routine is needed. The routine must continue the search after the first match is found. The next program takes care of this:

100 OPEN 1,8,2, "TELEDAT,S,R" 110 DIM D$(100,4) :X=l 120 INPUT#1,D$(X,1),D$(X,2),D$(X,3), D$(X,4) 130 IF ST64 THEN X=X+1:GOTO 120 140 CLOSE 1 150 PRINT CHR$(147) 160 PRINT"AREA CODE TO SEARCH FOR: n;AC$ 170 FOR I=l TO X 180 IF D$(I,3)=AC$ THEN 210 190 NEXT I 200 PRINT"END OF DATA! ":GOTO 270 210 PRINT"----------------" 220 PRINT"LAST NAME: " ; D$ (I, 1) 230 PRINT"FIRST NAME: ";D$(I,2) 240 PRINT"AREA CODE: ";D$(I,3) 250 PRINT"NUMBER: ";D$ (I, 4) 260 PRINT"----------------" 270 PRINT"MORE (YIN)?" 280 GETX$:IF X$="" OR X$"Y" AND X$"N" THEN 280 290 IF X$="Y" THEN 190 300 PRINT"SEARCH DONE!":END Here the search is continued if a record with the appropriate area code is found. This happens in line 290, which branches back to the loop instead of ending the program. After searching all of the records, the program responds END OF DATA. If you understand the operation of this program, you can now develop a search for the last name. With the help of the previous programs, this should present no difficulty.

56

ABACUS Software

1.4.9

Anatomy of the 1541

Simple Sorting of Tables

In data processing, it is often necessary to sort data into numeric or alphabetic order. This has always been a time-intensive task, which the programmer has tried to shorten by using better sorting methods. Sorting is certainly time consuming when performed with the programming language BASIC, which is relatively slow. Why should we sort the data at all? Suppose you had a telephone book in which the names were not ordered. You would have search the entire book from beginning to end to find a name. Sorting offers advantages when searching data. The computer can also search sorted data faster. There are several search methods which differ mainly in their speed of execution. The simplest method compares each data item with every other. If a table is supposed to be sorted in ascending order, the first item in the table is compared to the second. If the first is greater, it is exchanged with the second. After that, the first will be compared to the third, and so on, until the last item is reached. Now the smallest item is at the beginning, in the right place. The next time through, the first item is no longer needed. A flowchart of the program logic appears on the next page. This sort program starts using an index of 1, which is stored in the variable I. The second index is the variable X, which receives a value one greater than I. Then the first item is compared to the second. If the value of TA(I) is greater then TA(X), the program must use a temporary variable, TA(O), to make the exchange between the two. After this, the value of X is incremented, to three, and TA(I) is again compared to TA(X), etc. When the last item in the table is reached, (X> last index), the first item will be the smallest, and the index I is incremented by one. Now the second item is compared to every other (starting with the third), and so on. This sort method looks quite complicated at first glance. Comparisons in memory are done relatively quickly, however. This method is sufficient for small quantities of data.

57

ABACUS Software

Anatomy of the 1541

Simple Sort

TA(O)=TA(I) .--------- T A(I)= T A(X) TA(X)=TA(O)

>-"0

>--"0

58

ABACUS Software

Anatomy of the 1541

In order to run this program, a table must be constructed. This example uses a table with twelve items containing alphanumeric data (strings). The table is filled by the following routine: 100 110 120 130

DIM TA$(12) FOR I=l TO 12 INPUT TA$(I) NEXT I

This program allows you to enter twelve strings, which are then sorted with the following program: 140 150 160 170 180 190 200 210 220 230 240

I=l X=I+l IF TA$(I) < TA$(X) THEN 180 TA$(O)=TA$(I) :TA$ (I)=TA$ (X) : TA$(X)=TA$(O) X=X+l IF X O THEN 590 GOSUB2230:RETURN GOSUB 2030 OPEN 1,8,2,"@:"+NF$+",S,W" FORI=lTOX P R I NT # 1 , D$ (I, 1) " , "D $ (I, 2) " , "D $ (I , 3) ; PRINT#l,D$ (1,4)", "D$ (1,5)", "D$ (I, 6)", "D$ (1,7) NEXT PRINT"DATA IS SAVED":CLOSE1:RETURN PRINT"RETURN FOR MORE" INPUTX$:RETURN REM ********** REM INPUT DATA REM ********** IFX>OTHEN730 GOSUB2030:INPUT"FILENAME ";NF$ X=X+1 GOSUB2030 PRINT"INPUT DATA:" PRINT"-----------":PRINT I=X:GOSUB2110 FORI=lT07:PRINTCHR$(145); : NEXT FORI=lT07:PRINTTAB(12); :INPUTD$(X,I) :NEXT PRINT:PRINT"CORRECT (YiN)?" GETX$:IFX$"N"ANDX$"Y"THEN810 IFX$="Y"THEN840 GOTO 740 PRINT"MORE INPUT (YiN)?" GETX$:IFX$"N"ANDX$"Y"THEN850 IFX$="Y"THEN730 RETURN

65

Anatomy of the 1541

ABACUS Software

880 REM ********* 890 REM EDIT DATA 900 REM ********* 910 IF X>OTHEN930 920 GOSUB2230:RETURN 930 GOSUB2030 940 INPUT"NAME 1: "; N1$ 950 INPUT"NAME 2: n;N2$ 960 FORI=lTOX 970 IF 0$ (I,l)=N1$ANDD$(I,2)=N2$THEN1010 980 NEXTI 990 PRINT"NAME NOT FOUND!" 1000 PRINT"RETURN FOR MORE":INPUTX$:RETURN 1010 GOSUB2030 :";0$(1,1) 1020 PRINT"-l- NAME 1 :";0$(1,2) 1030 PRINT"-2- NAME 2 :";0$(1,3) 1040 PRINT"-3- STREET 1050 PRINT"-4- CITY STATE :";0$(1,4) :";D$(I,5) 1060 PRINT"-5- ZIP CODE 1070 PRINT"-6- TELEPHONE :";D$(I,6) 1080 PRINT"-7- NOTES :";0$(1,7) 1090 PRINT"NO. OF FIELD TO CHANGE: ":PRINT"(9=NO CHANGES)" 1100 GETX$:IFVAL(X$)OTHEN1240 1230 GOSUB2230:RETURN 1240 GOSUB2030:PRINT"OUTPUT TO PRINTER (P) OR SCREEN (S)?" 1250 GETX$:IFX$"S"ANDX$"P"THEN1250

66

ABACUS Software

1260 1270 1280 1290 1300 1310 1320 1330 1340 1350 1360 1370 1380 1390 1400 1410 1420 1430 1440 1450 1460 1470 1480 1490 1500 1510 1520 1530 1540 1550 1560 1570 1580 1590 1600 1610 1620

Anatomy of the 1541

O$=X$:IFO$="S"THEN1300 PRINT:PRINT"PAPER (P) OR MAILING LABELS (M}?" GETX$:IFX$"P"ANDX$"M"THEN1280 D$=X$ GOSUB2030 PRINT"ENTER THE SEARCH DATA:" PRINT"PRESS RETURN BY IRRELEVANT FIELDS." PRINT"----------------------------------": PRINT I=0:GOSUB2110 FORI=lT07:PRINTCHR$(145); :S$(I}="":NEXT FORI=lT07:PRINTTAB(12}; :INPUTS$(I} :NEXT IFO$="S"ORD$="M"THEN1450 GOSUB2030:PRINT"PRINTER READY (Y}?" GETX$:IFX$"Y"THEN1390 OPEN 1,4 PRINT#l,"NAME 1"iSPC(8}i"NAME 2"iSPC(8); "STREET";SPC(lO}i PRINT#l,"CITY STATE"iSPC(4}i "ZIP CODE TELEPHONE NOTES" FORI=lT079:PRINT#1,"="; :NEXT:PRINT#l CLOSEI FORI=lTOX FORY=lT07 IFS$(Y}=LEFT$(D$(I,Y},LEN(S$(Y} }}THENZ=Z+l: GOT01480 NEXTY IFZ=7THENGOSUB1550 Z=O:NEXTI PRINT:PRINT"END OF DATA!":PRINT PRINT"RETURN FOR MORE":PRINT INPUTX$ RETURN IFO$="S"THEN1730 IFD$="M"THEN1670 OPENl,4 PRINT#1,D$(I,1};SPC(14-LEN(D$(I,1))); PRINT#1,D$(I,2) ;SPC(14-LEN(D$(I,2))); PRINT#l,D$ (1,3); SPC (16-LEN (D$ (1,3))); PRINT#1,D$(I,4) ;SPC(15-LEN(D$(I,4))); PRINT#1,D$(I,5) ;SPC(8-LEN(D$(I,5))); 67

ABACUS Software

1630 1640 1650 1660 1670 1680 1690 1700 1710 1720 1730 1740 1750 1760 1770 1780 1790 1800 1810 1820 1830 1840 1850 1860 1870 1880 1890 1900 1910 1920 1930 1940 1950 1960 1970 1980 1990 2000 2010 2020

Anatomy of the 1541

PRINT#l,D$ (I, 6) ;SPC (12-LEN (D$ (I, 6»); PRINT#1,D$(I,7) PRINT#1:CLOSE1 RETURN OPEN2,4 PRINT#2 FORJ=lT05:PRINT#2,D$(I,J) :NEXT PRINT#2:PRINT#2:PRINT#2 CLOSE2 RETURN GOSUB2030:GOSUB2110 PRINT:PRINT"MORE (Y)?" GETX$:IFX$"Y"THEN1750 RETURN REM *********** REM DELETE DATA REM *********** IFX>OTHEN1820 GOSUB2230:RETURN GOSUB2030 INPUT"NAME 1 : ";N1$ INPUT"NAME 2 : ";N2$ FORI=lTOX IFD$(I,1)=Nl$ANDD$(I,2)=N2$THEN1900 NEXTI PRINT"NAME NOT FOUND!":PRINT PRINT"RETURN FOR MORE":INPUTX$:RETURN GOSUB2030:GOSUB2110 PRINT:PRINT"DELETE RECORD (YiN)?" GETX$:IFX$"Y"ANDX$"N"THEN1920 IFX$="N"THENRETURN FORY=ITOX-1 FORJ=lT06 D$(Y,J)=D$(Y+1,J) NEXTJ,Y FORJ=lT06:D$(X,J)="":NEXTJ X=X-1 PRINT"RECORD IS DELETED!" PRINT"RETURN FOR MORE" INPUTX$:RETURN

68

Anatomy of the 1541

ABACUS Software

2030 REM ***** ***** ***** 2040 REM PROGRAM HEADING 2050 REM ***** ***** ***** 2060 PRIN TCHR $(147 )i 2070 PRIN TTAB (8)i"= ==== ==== ==== ==== ==== ==" LIS T 2080 PRINT TAB( 8) i"M A I LIN G ====" ==== ==== ==== ==== i"=== 8) TAB( 2090 PRINT N 2100 RETUR 2110 REM ***** ***** ** 2120 REM PRINT RECORD 2130 REM ***** ***** ** iD$ (1,1) 2140 PRINT"NAME 1 I,2) iD$( 2 E 2150 PRINT"NAM (1,3) iD$ ET "STRE 2160 PRINT iD$( I,4) 2170 PRIN T"CIT Y STATE iD$ (1,5) CODE T"ZIP 2180 PRIN iD$ (I, 6) E PHON "TELE 2190 PRINT iD$( I,7) ES "NOT 2200 PRINT 2220 RETURN 2230 REM ***** *** 2240 REM NO DATA! 2250 REM ***** *** 2260 GOSUB2030 2270 PRINT"NO DATA IN MEMORY! ":PRI NT 2280 PRINT"RETURN FOR MORE" 2290 INPUTX$:RETURN

69

ABACUS Software

Anatomy of the 1541

1.4.11 Uses for Sequential Storage The great advantage of sequential storage as compared to relative and direct access storage, is that a lot of data can be written to the diskette quickly. Data of varying lengths can be stored together, without requiring the records to be of a definite length. It makes sense to make use of this advantage in cases in which the file must not be permanently divided into parts. Examples are:

* Bookkeeping files In a bookkeeping journal, all entries are recorded continuously. Changes should not be made to these entries. Instead, adjustment entries should be made to effect changes.

* Analysis files You analyze a direct access file, looking for, say, all customers with whom you have done more than 2000 dollars of business in a certain zip code, and write the found records in a sequential file for later access. Naturally, sequential files also offer a substitute for direct access files, as discussed in this chapter, if the user does not possess further programming knowledge. We must certainly recommend that you work through the other methods of data storage though, because they offer significant advantages.

70

ABACUS Software

1.5

Anatomy of the 1541

Relative Data Storage

Relative data storage and its programming is not described in the VIC-1S41 user's manual. The reason may lie in the fact that the Commodore 64 and the VIC-20 have no commands to process relative files using BASIC 2.0. Therefore, it is in principle not possible to use relative data storage on the Commodore 64 and VIC-20--but only in principle. We have developed a few tricks that work within the limitations of BASIC 2.0 and permit the Commodore 64 and also the VIC-20 to use relative data storage. The examples may seem to be somewhat complicated at first--for example, information about the record lengths will be transmitted to the disk using CHR$(x) codes--but they provide for a very easy method of data storage.

1.5.1 The Principle When using relative record data processing, the data records are numbered. It is assumed that all records in a relative file have the same length and that the record number of every record is known or can be calculated. To find a record, it is not necessary to search through the entire file. Only the record number need be given to access that record. Using the record number, the DOS can find where the record is "relative" to the beginning of the file on the diskette and can read it directly. Therefore, the entire file need not be read into the computer, only the desired records. The management of a relative file follows this pattern:

Create a relative file: 1. The file is opened. With this the length of a record is established. 2. The last record is marked. 3. The file is closed.

Write a record: 1. The file is opened. 2. The file is positioned on the record to be written. 3. The record is written. 71

Anatomy of the 1541

ABACUS Software

4. The file is closed.

Read a record: 1. The file is opened. 2. The file is positioned over the record to be read. 3. The record is read. 4. The file is closed. This is only an outline. In the following sections these processes will be explained in detail.

1.5.2 The Advantage over Sequential Storage The greatest advantages of relative storage are:

* *

faster access to individual records does not require much of the computer's memory

It has already been mentioned that the sequential file must reside completely in the computer's memory for processing. Using sequential techniques, it may be necessary to search the entire file to find a given record. The record must be read and compared during the search process. But if a sequential file cannot be entirely loaded into memory, this method of search is impossible.

Using relative data files, the processing is much simpler. By using the record number, a desired record can be read individually. The file size is not limited to the computer's memory. So, for example, a program that uses all 3.5K bytes of a standard VIC-20 can manage a file with up to 163 Kbytes! The advantages of relative over sequential file management are large enough that many of you, once acquainted with the techniques, will prefer to use them.

72

ABACUS Software

1.5.3

Anatomy of the 1541

Opening a Relative File

Relative files are also opened with the OPEN command. The command differs only slightly from that for sequential files. Take a look at the format of the OPEN command:

OPEN lfn,da,channel, "filename,L," +CHR$(recordlength) The first four parameters are identical to those for sequential files. They are logical file number, device address (normally 8), channel (2-14), and name of the file. Next follows an L which informs the DOS that a relative file should be opened, whose record length follows. This record length is transmitted with a CHR$ code. The length is between 1 and 254. Thus each record of a relative file is limited to a maximum of 254 characters. If the record length is less than 88, the record can be read with an INPUT# statement. For this, it is necessary that the PRINT# statement transfer the record with a trailing RETURN. A PRINT# statement sends a RETURN when it is not terminated with a semicolon. This RETURN is now a part of the record. When you want to read records with INPUT#, the record length must be increased by one. A file composed of 80-character records, to be read by the INPUT# statement, would be opened as follows:

OPEN 1,8,2,"FILE.REL,L," +CHR$(81) Here a relative file with the name "FILE.REL" is opened using channel 2. The record length should total 81 characters. Records comprised of 80 characters should be sent with a PRINT# statement, with no trailing semicolon. It is important to note that only one relative file can be opened at a time. If you want to work with two relative files, you must always close the first

before opening the second. One sequential file may be opened in addition to one relative file. When a relative file is opened for the first time, the DOS creates as many "null" or unused records as can fit in a single 254 byte block. It

73

ABACUS Software

Anatomy of the 1541

create s these "null" record s by writin g a record with a CHR$ (255) at the beginning of each record. This is called formatting a relative file. If you want to expan d a relativ e file beyon d the initial numbe r of record s that the DOS formatted, you can referen ce the last record numbe r that you want to write (by positioning to that record number) and the DOS autom aticall y formats the record s betwe en the curren t end of file and the new last record numb er by writin g record s contai ning CHR$ (255). Formatting takes time to complete. If you try to read a record whose numbe r greate r than that of the last record , the DOS returns the error RECO RD NOT PRES ENT. Howe ver, if you write a record which is greate r than the highes t curren t record , all record s less than the new record numbe r are also written with CHR$ (255). Subsequently accessing these record does not result in an error.

If you want to avoid long delays while relative records are formatted (as the file is expan ded), then you should refere nce the last record numbe r immed iately after openin g the file. The formatting of the null record s takes place at that time instead of at a more inconvenient time.

To positio n the DOS for a specif ic relativ e record you must send a position comm and over the comm and channel (15), as shown here: PRIN T#lfn ," P" +CHR $(cha nnel) +CHR $(low )+CH R$(hi gh)+ CHR$ (byte) If you are positio ning to a record which is beyon d the curren t end of file, the DOS presen ts the messa ge RECO RD NOT PRES ENT to the disk error chann el. If this record is to be writte n, then you can ignore the messa ge. The follow ing PRINT # statem ent is carried out in spite of the error message.

The param eters low and high in the P comm and design ate the record numbe r. The maxim um value that can be given with one byte is 255, but a relativ e file contai ns up to 65535 records. Theref ore, the record numbe r must be transm itted in two bytes. These two bytes are calcul ated with the following formula: HB=I NT(R N/256 ) LB=R N-HB *256 74

Anatomy of the 154l

ABACUS Software

HB = High Byte (parameter high) LB = Low Byte (parameter low) RN = Record Number The last parameter (byte) serves to position to a specific location wnh1ll the given record. An example:

PRINT#2," pIt +CHR$(2)+CHR$(lO)+CHR$(1 )+CHR$(5) Here the file is positioned to the fifth byte of the 266th record. This is coded as a low byte of 10 and a high byte of 1 (high byte * 256 + lov, byte = record number). To read or write a complete record, the file is positioned to the first byte of the record. If the last parameter is not given, the trailing RETlJRN (CHR$(13» is taken as the character location. The corresponding BASIC program to establish a file of 1 80-character records looks like this:

100 RN=100 110 HB=INT(RN/256) 120 LB=RN-HB*256 1300PEN1,8,2,"FILE.REL,L,"+CHR$(80) 140 OPEN2,8,15 150 PRINT#2,"P"+CHR$(2)+CHR$(LB)+ CHR$(HB)+CHR$(l) 160 PRINT#1,CHR$(255) 170 CLOSE l:CLOSE 15 Freeing 100 records takes some time. The creation of this file about ten minutes. Notice that of the 80 characters in a record, on1y be used to hold data, because transferring data with a PRINT# command adds a trailing RETURN.

75

ABACUS Software

Anatomy of the 1541

1.5.4 Prepa ring Data for Relative Stora ge As already mentioned, you cannot change the record length of a relativ e file. If a record consists of several fields, these fields must be combi ned. It is important that these fields always be in the same position so that they can be separated later. Let's work through a problem: We want to manag e an inventory using relativ e storage techniques. To that end, the following fields are necessary: PART NUMB ER DESC RIPTI ON QUAN TITY COST PRICE Recor d length

4 CHAR ACTE RS 15 CHAR ACTE RS 5 CHAR ACTE RS 6 CHAR ACTE RS 6 CHAR ACTE RS 36 bytes

The inventory contains approximately 200 items with a record length of 36 bytes. This inventory file can now be created: 100 110 120 130 140

RN=2 00:RE M NUMBER OF INVENTORY ITEMS RL=3 6 :REM RECORD LENGTH OPEN 1,8,2 , "INVE N,L, "+CH R$(36 ) OPEN 2,8,1 5 PRIN T#2," P"+C HR$( 2)+CH R$(20 0)+ CHR$ (O)+C HR$(l ) 150 PRIN T#1,C HR$( 255) 160 CLOSE l:CLO SE 2

Now the file is create d and all records are written. Let's suppo se that the invent ory is presen t as a sequen tial file. It consis ts of 200 record s, the fields of which are ordered one after the other. These fields must be written to the relativ e file. This is not simple , howev er, becau se many of the descriptions are not the full fifteen characters in length. The structu re of the relative file looks as follows:

76

--------

~-----------

Anatom y of the 1541

ABACUS Softwa re

POSITI ON

11111 11111 22222 22222 33333 33 12345 67890 12345 67890 12345 6 67890 12345

FIELD

PM$- DE$- ------- ----Q$ ---C$ ----P$ ----

CONTENTS

1

2 3

1/8 in. sheet No. 10 screw Valve A3A4

200 1/2 in.

1344 11.40 20.30 7.00 4.00 1231 1243 11.45 16.40

tubing 2321

3.35

4.10

les: The fields will be read from the sequential file into the following variab

Part numb er Description Quant ity Cost Price

PN$ DE$ Q$ C$ P$

The following command chains these fields together:

RC$ = PN$ + DE$ + Q$ + C$ + P$ The record variable RC$ does not have the desired structure. The se the reason is that the quantity immediately follows the description. Becaufifteen always not is ption descri quantity must begin at position 20 and the the characters long, we have a problem. In order to read the records from are that fields all ore, Theref ed. relative file, the structure must be observ this shorter than the planned length must be padded with blanks. Taking this: into account, the chaining goes like

" BL$=" RC$=PN$+ LEFf$ (BL$, 4. LEN (PN$)) RC$=RC$+DE$+LEFT$(BL$,15·LEN(DE$) RC$=RC$+Q$+LEFT$(BL$,5. LEN (Q$)) RC$=RC$+C$+LEFf$(BL$,6.LEN(C$») RC$=RC$+P$+LEFT$(BL$,6·LEN(P$»

77

ABACUS Softwa re

Anatomy of the 1541

This concatenation looks more complicated than it really is. Each field must be filled with enough blanks to bring it to its appropriate length . The blanks are added to the individual fields from the string BL$, defined at the beginning. Let's go through an example: Suppo se the first part numb er is 8. The length of this string LEN(PN$), is then one. The maximum length of this field (4) minus , the actual length (1) is 3. The string PN$ must therefore be padded with three blanks, LEFf$ (BL$, 3). Each record of the old sequential file must be prepared in this manne r before it can be transferred to the relative file. Naturally, the above is true for all input values to be used in a relativ e file. Therefore you must always remember to use a routine to fill each field with blanks to its full length when working with relative data processing.

1.5.5 Trans ferrin g Data In principle, transferring data to and from a relative file does not differ from sequential storage. Records are written with PRINT# and read with INPUT# or GET#. The only difference is that before a record is written read, the file must be positioned to that record. This is accomplished or the P command. This example program illustrates what we have discus with sed: 100 105 110 120 130 140 150 160 170

BL$= " " OPEN 1,8,2 ,"TES T.RE L,L," +CHR $(41) OPEN 2,8,1 5 PRIN T#2," P"+C HR$( 2)+CH R$(10 0)+ CHR$ (O)+C HR$(l ) PRIN T#1,C HR$( 255) PRINT CHR$ (147) PRINT "INPU T RECORD:" PRIN T"-- ----- ----- -" INPUT"RECORD NUMBER (1-10 0) "; RN

78

ABACUS Software

Anatomy of the 1541

180 IF RN100 THEN PRINTCHR$(145);: GOT0160 190 INPUT"FIELD 1 (MAX.10 CHAR.) : "iF1$ 200 IF LEN(F1$»10 THEN PRINTCHR$(145) i : GOT0190 210 INPUT"FIELD 2 (MAX. 5 CHAR.) : "iF2$ 220 IF LEN(F2$»5 THEN PRINTCHR$(145) i :GOT0210 230 INPUT"FIELD 3 (MAX.10 CHAR.) : "iF3$ 240 IF LEN(F3$»10 THEN PRINTCHR$(145);: GOT0230 250 INPUT"FIELD 4 (MAX.15 CHAR.) : "iF4$ 260 IF LEN(F4$»15 THEN PRINTCHR$(145) i : GOT0250 270 PRINT"CORRECT (YiN)?" 280 GETX$:IF X$"Y" AND X$"N" THEN 280 290 IF X$="N" THEN 140 300 RC$=F1$+LEFT$(BL$,10-LEN(F1$)) 310 RC$=RC$+F2$+LEFT$(BL$,5-LEN(F2$)) 320 RC$=RC$+F3$+LEFT$(BL$,10-LEN(F3$)) 330 RC$=RC$+F4$+LEFT$(BL$,15-LEN(F4$)) 340 PRINT#2,"P"+CHR$(2)+CHR$(RN)+ CHR$(O)+CHR$(l) 350 PRINT#l,RC$ 360 PRINT"MORE INPUT (YiN)?" 370 GETX$:IF X$"Y" AND X$"N" THEN 370 380 IF X$="Y" THEN 140 390 CLOSE l:CLOSE 2:END The following line-oriented documentation explains the operation of the program: A blank-character string with 15 blanks is defined. The relative file is opened with a length of 15. The command channel 15 is opened. To initialize the relative file, the head is positioned over the first byte of the last (lOOth) record. The last record is freed and the initialization begun. 130 The screen is erased. 140 150-260 The record no. and fields 1-4 are entered and checked for correct length. 270-290 The entered data can be corrected.

100 105 110 120

79

Anatomy of the 1541

ABACUS Software

300-330 The record is prepared. 340 The head is positioned over the first byte of the record. The record is written to the disk. 350 360-380 New data can be entered. 390 The program ends. Now write some records with this program, but don't forget to save it in case you need it later. Certainly it also necessary to read and change existing records. To do this, the relative file is opened, the file is positioned to the appropriate record, and the record is read. This record must then be divided into its fields. Let's read a record that was recorded with the previous program. The following routine reads the record: 100 110 115 120 130 140 160 170 250

OPEN 1,8,2,"TEST.REL,L,"+CHR$(41) OPEN 2,8,15 PRINT CHR$(147) INPUT"RECORD NUMBER :";RN PRINT#2,"P"+CHR$(2)+CHR$(RN)+ CHR$(O)+CHR$(l) INPUT#l,RC$ IF ASC(RC$)255 THEN PRINT"RECORD NOT FOUND!":GOT0250 PRINT RC$ CLOSE l:CLOSE 2

This routine reads a specified record. If this record has never been written, it is recognized by the value 255 with which every record was marked at the creation of the file. A record that is found is displayed. You can see that the four fields are in the same positions. If you want to divide the record into its individual parts, you must use the function MID$. For example, in order to extract field 1 of the record, give the following statements in the direct mode after the record is found and read:

Fl$=MID$(RC$,l,lO) PRINT Fl$

80

Anatomy of the 1541

ABACUS Softwa re

Now the variable Fl$ contains the first field, as written by the first d by program. The division of records into individual fields is accomplishe lines: ing follow the change or building on the previous program. Add Fl$=M ID$(R C$,1, 10) F2$= MID$ (RC$ ,11,S) F3$= MID$ (RC$ ,16,10 ) F4$= MID$ (RC$ ,26,1S ) PRIN T"FIE LD 1: ";F1$ PRIN T"FIE LD 2: ";F2$ PRIN T"FIE LD 3: H;F3$ PRIN T"FIE LD 4: n;F4$ PRINT"MORE (Y/N) ?" GETX $:IF X$ "Y" AND X$ "N" THEN 260 270 IF X$="Y " THEN 115 280 CLOSE l:CLO SE 2

170 180 190 200 210 220 230 240 250 260

Here the record is separated into the individual fields and the fields are ns of displayed. It is important for the MID$ function that the exact positio the within eter param first The ined. the fields within the record be mainta second The . record the ning contai le parent heses is the string variab by parameter is the position at which the number of characters represented d selecte the with done may work r Furthe the parameter will be taken out. fields inside L1e program. the So far we have read the records with the INPUT# statement. If the with read be longer no can it ters, charac 88 than record is longer ent is INPUT# statement. The way to get around the limited INPUT# statem with time a at with the GET# statement. The bytes of a record are read one a this comm and and assembled into a single string. Suppose you have tenth the read to relative file with 128-character records. Now you want the record of this file and place it in the variable RC$. The example of following routine illustrates reading this with GET#: 100 OPEN 1,8,2 , "TES T.GE T,L," +CHR $(128 ) 110 OPEN 2,8,1 5 120 PRIN T#2," P"+C HR$( 2)+CH R$(10 )+ CHR$ (O)+C HR$ (1) 130 Re$= ""

81

ABACUS Software

140 150 160 170

Anatomy of the 1541

FOR I=l TO 128 GET#l,X$ RC$=RC$+X$ NEXT I

After running this routine, the record is contained in the variable Re$. If this record had been written with a PRINT# statement without a trailing semicolon, the last character in the string will be a RETURN. To ignore this RETURN, allow the loop in line 140 to run only to 127. The last character of the record (RETURN) is not read. As already mentioned, the last parameter of the P command specifies at which character the transfer of data should begin. If, for instance, in the 127-character record of the previous example, you want to read positions 40-60 into a field, the head must be positioned over the 40th character and the next 21 bytes read. The following routine clarifies this: 100 OPEN 1,8,2, "TEST.GET,L, "+CHR$(128) 110 OPEN 2,8,15 120 PRINT#2, "P"+CHR$ (2)+CHR$ (10)+ CHR$ (O)+CHR$ (40) 130 F$="" 140 FOR I=l TO 21 150 GET#l,X$ 160 F$=F$+X$ 170 NEXT I

In line 120, the head is positioned over the the 40th byte of the tenth record in line 120 and the loop in lines 140- 170 reads the following 21 bytes (bytes 40-60 of the record) into F$.

82

ABACUS Software

Anatomy of the 1541

You see then that the entire record need not be read if you only want to work with part of it.

1.5.6

Closing a Relative File

There is no difference between closing a relative file and closing a sequential file. Because the command channel must always be open to send the position command when working with relative storage, it must also be closed.

1.5.7 Searching Records with the Binary Method Normally each record is accessed by record number. But what if you want to search for a specific name in a relative file and the record number is not known? It is possible to read each record and compare each for the desired name. But this is very time consuming if the file has many records. If the file is kept in name order, the records can be searched using an alternative method. This method is called a binary search. In order to use a binary search, the relative file must be arranged in sorted order. Using the above example, relative record 1 must contain a name with the lowest collating sequence while the last relative record must contain a name with the highest collating sequence. Thus the name AARON might be contained in relative record 1 and ZEPHYR might be contained in the last relative record of the file and all other names would be ordered throughout. When records are added to the file, then the records must be reordered. Similarly if a name is changed, the records must again be reordered. The binary search can be explained using a simple example. When you want to find a name in the telephone book, you don't search through it sequentially. You open the book in the middle and compare the first letter of the desired name with the first letter of names on the page. If the desired name comes before these, you tum halfway into the first section of the book, and so on. You go through it systematically.

83

ABACUS Software

Anatomy of the 1541

The binary search is not a sequential search. It identifies a record halfway through the remaining number of records. The following example will clarify this: There exists the following relative file, sorted in ascending order:

Record number Contents 1 1985 2 1999 3 2005 4 2230 5 2465 6

7 8 9

10 11 12 13

14 15

2897 3490 3539 4123 5000 5210 6450 6500 6550 6999

Within these fifteen records we will search for a contents of 3490. It is not known which record it is stored in. We must first know how many records are in the file. In this case, there are fifteen. We divide this by two. The middle of the file is record eight with the contents 3539. We determine if the contents of this record are equal to the target value, and if not, whether they are larger or smaller. In this case, they (3539) are larger. This means the record we are looking for is in the first half of the file. So we divide eight by two and examine the contents of record four, 2230. Since 2230 is less than 3490, it lies between four and eight. We again divide by two and add this to record 4 which results in record 6, the contents of which are 2897. 2897 is less than 3490, so our target lies between records six and eight. Record seven is indeed the record we are looking for.

84

ABACUS Software

Anatomy of the 1541

The principle of the binary search is to determine by the result of each comparison whether to search upwards or downwards until the search data is found. The maximum number of comparisons can be found using the following formula:

S=INT(LOG(N)/LOG(2)+1) S is the number of comparisons (searches) and N is the number of records in the file. In a sorted relative data file with 1000 records, no more than ten comparisons will be necessary to find the desired record! Let's create a relative data file with fifteen records to test the binary search: 100 110 120 130 140 150 160

Ol?EN1,8,2, "BINARY.REL,L, "+CHR$(5) FORI=lT015 READ RC$ l?RINT#l,RC$ NEXT I CLOSE l:CLOSE 2:END DATA 1985,1999,2005,2230,2465,2897, 3490,3539 170 DATA 4123,5000,5210,6450,6500,6550, 6999

This program puts the fifteen records in a file called BINARY.REL using the values given in lines 160-170. The position command is not necessary because the data will be written straight through from first to last record. After opening the file the pointer points to the first record. This file is designed to be searched with the binary method. The following program is based on the logic of the binary search: 100 110 120 140 150 160 170 180 190

Ol?EN1,8,2, "BINARY.REL,L, "+CHR$(5) Ol?EN2,8,15 l?RINTCHR$(147) N=15: REM NUMBER OF RECORDS I=LOG(N)/LOG(2) IF I-INT(I)O THEN I=INT(I)+l M=I-1 I=2""I X=I/2

85

ABACUS Software

Anatomy of the 1541

210 INPUT"RECORD TO FIND (* TO END) : ";SR$ 220 IF SR$="*" THEN 320 230 IF M:BO >:B8 >:CO >:C8 >:DO >:D8 >:EO >:E8 >:FO >:F8

AO 00 00 2F AO 00 00 4B 48 00

AO 00 00 53 AO 00 00 20 41 00

00 00 54 AO 00 00 44 52 47 45 00 00 00 00

00 OB 31 AO 00 06 49 20 00 04

00 00 32 AO 00 00 53 43 00 00

· ..... .. · .... T12 /SOl File type . . . Track, 1st block

· ..... ..

· .... DIS K ADDR C HANGE ... Sector, 1st block

· ..... ..

This is an section from the directory (track 18, sector 1) of the TEST /DEM O diskette. You can follow the organization of the file DISK with ADDR CHANGE. The entry of this file begins at byte $E2 and ends $82 type file byte $FF. This is a PRG file, which can be recognized by the from t eviden in byte $E2. This file comprises 4 blocks on the disk. This is data bytes $FE and $FF. Bytes $E3 and $E4 of the entry address the first 0). block of the file ($10, $00, corresponding to track 16, sector Let's look at a section of this block: Address of the

>:00 110 97 >:08 >: 10 32 93 >: 18 49 >: 20 45 >:28 47 >:30 41 >:38 99 >: 40 4F >: 48

OAlo l 35 39 00 39 13 11 56 45 53 53 45 20 4D 22 22 11 46 46

04 34 04 11 20 20 50 00 54 20

OF 36 6E 11 41 43 52 59 55 41

04 38 00 11 44 48 4F 04 52 4C

64 2C 99 44 44 41 47 6F 4E 4C

00 31 22 52 52 4E 52 00 20 20

. . . . . . $ 'lst block

.5946 8,1 2.9 .... ..... . DR IVE ADDR ESS CHAN GE PROGR AM" .y./. " .TURN OFF ALL II

This block contains the first part of the program. It is stored on the diskette exactly as it is stored in the computer's memory. The BASIC only commands are converted to one-byte codes called tokens. This is why l ecima hexad the of tion transla hand the text can be recognized in the right 167

ABACUS Softwa re

Anatomy of the 1541

codes. The first two bytes of this data block indicate the second data block ($10 and $OA, track 16, sector 10) from which this section follows: >:00 >:08 >:10 >: 18 >:20 >: 28 >:30 >:38 >:40 >: 48

r-~.....,r-:--:---::-::---::-;:--:-:--;:-::-~:'-----:-;:

110 00 8F 52 45 36 48 44 B4 20

14134 30 00 ID 05 AO 8D 203 330 30 3A 20 20 46 49 4E 44 20 44 49 56 45 20 54 59 50 00 39 05 AA 00 8D 20 30 30 3A 20 8F 20 43 41 4E 47 45 20 41 44 52 4 5 5 3 5 3 0 0 68 05 00 992 211 544 845 53 45 4C 45 43 54 45

-- Address of the .. 40 ... third block .. 300: FIND D RIVE TYP E.9 . . . 600: C HANGE AD DRE S S. ( . .. ".THE SELECTE

The progra m is contin ued in this block. Bytes $00 and $01 point to the third data block of the file ($10, $14, track 16, sector 20): >:00 110 081 31 30 30 30 00 23 >:08 06 54 01 8B 20 43 B2 32 >: 10 35 34 20 A7 20 4D 54 B2 >: 18 31 31 39 3A 20 SF 3A 20 >:20 32 30 33 31 20 56 32 2E >:28 36 00 45 06 5E 01 8B 20 >:30 43 B2 32 32 36 20 A7 20 >:38 4D 54 B2 35 30 3A 20 8F >: 40 3A 20 32 30 34 30 20 56 >:48 31 2E 32 00 67 06 68 01

. . 1 0 00 . # Address of the . T.. C 2 fourth block 54 HT 119: .. 2031 V2. 6.E. C 226 HT 50: : 2040 V 1. 2.

. (.

This is the next to the last block of the program. You have no doubt recognized that the data blocks are in the same track, but are not contig uous. The first data block is block O. The next is block 10, 10 blocks from the first block. 9 blocks are always skipped between data blocks of a file. The third data block is block numbe r 20. The DOS begins again with the first block if the calculated block oversteps the highest block. Becau se track 16 contai ns 21 blocks , the last data block is block numbe r 8. The first two bytes of this third block address it:

168

--~-~-

---------------

Anatomy of the 1541

ABACUS Softwa re

>:00 >: 08 >: 10 >: 18 > :20 >: 28 >:30 >:38 >: 40 >: 48

5A 34 20 30 31 C7 31 2C C6 30

42 30 53 30 35 28 36 5A 28 29

B2 00 54 00 2C 31 29 43 5A 29

31 14 20 45 22 37 3A 24 43 00

20 07 A7 07 4D 32 Al 3A 24 66

Characters in last block

ZB 1

A7 AE 20 B8 2D 29 23 5A

Numbe r of ',:00 00 >:08 00 >:10 11 >:18 11 >:20 11 >:28 11 >:30 11 >:38 10 >:40 10 >:48 00 >:50 00 >:58 00 >:60 00 >:68 00 >:70 00 >:78 00 >:80 00 >:88 00 >:90 00 >:98 00 >:AO 00 >:A8 00 >:BO 00 >:B8 00 >:CO 00 >:C8 00 >:DO 00 >:D8 00 >:EO 00 >:E8 00 >:FO 00 >:F8 00

47 00 00 02 04 06 08 08 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 11 11 11 11 11 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

64 00 DB OD OF 11 13 12 DE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

11 00 11 11 11 11 11 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

OA 00 00 00 01 11 03 11 05 11 07 11 09 11 06 10 02 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

176

00 00 DC DE 10 12 14 10 DC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

.G.$ .... ......... ....... II

..............

....

II

..........

......... ....... ......... ....... '"

......... .....

10

..............

...... " ........ ......... ....... .......... '" .... .......... ....... " .. ,. .......... ......... .......

......... ....... .......

.........

'"

......... .......

...... '"

..

....

,.

..

"

..........

"

.........

"

......

............

&

............

10

..

II

"

..

iO

......

10

..

.......... ... " .. ......... .......

......... .......

....

., .......... ......... ....... ......... .......

..

.,

.......... ...

......... ....... ......

to

10

......

ABACUS Software

Anatomy of the 1541

The first two bytes point to the track and sector of the next side-sector block, as usual. In our case, no further side-sector blocks exist ($00) and only $47 = 71 bytes of this sector are used. Byte 2 contains the number of the side-sector block, 00. A relative file can contain a maximum of 6 such blocks; the numbering goes from 0 to 5. The record length, $64 (100), is in byte 3. The next twelve bytes (bytes 4 through 15) contain the track and sector pointers (two bytes each) to the 6 side-sector blocks (00,00 means the block is not yet used). Starting at byte 16 ($10) are the pointers to the data, and the track and sector pointers to the first 120 data blocks (in our case, only 28 pointers). Using the record number and record length, the DOS can calculate in which block the data lies and at which position within the block the record begins. Take the following example, for instance: To read the 70th record from the file with a record length of 100 characters, you can perform the following calculations:

(70-1)

*

100 / 254

We get a quotient of 27 and a remainder of 42. The DOS now knows that the record can be found in the 27th data block at the 42+2 or 44th position. Here's an explanation of the calculation. Each block contains 256 bytes, the first two of which are used as a pointer to the next block. 254 bytes are then left over for data storage. We can calculate the byte number from the start of the file (which is record 1) from the record number and record length. If we divide this value by the number of bytes per block, we get the number of the block containing the record. The remainder of the division gives the position within the block (add 2, because the first two bytes serve as a pointer). If the record overlaps the end of the block, the next block must also be read. In our example, the 27th data block lies in track $10 = 16 and sector SOC = 12. If we read this block, we get the following picture:

177

ABACUS Softwa re

>:00 00 F3 00 00 00 >:08 00 00 00 00 00 >:10 00 00 00 00 00 >:18 00 00 00 00 00 >:20 00 00 00 00 00 >:28 00 00 00 00 44 >:30 20 46 4E 52 20 >:38 46 52 44 20 37 >:40 00 00 00 00 00 >:48 00 00 00 00 00 >:50 00 00 00 00 00 >:58 00 00 00 00 00 >:60 00 00 00 00 00 >:68 00 00 00 00 00 >:70 00 00 00 00 00 >:78 00 00 00 00 00 >:80 00 00 00 00 00 >:88 00 00 00 00 00 >:90 FF 00 00 00 00 >:98 00 00 00 00 00 >:AO 00 00 00 00 00 >:A8 00 00 00 00 00 >:BO 00 00 00 00 00 >:B8 00 00 00 00 00 >:co 00 00 00 00 00 >:C8 00 00 00 00 00 >:DO 00 00 00 00 00 >:D8 00 00 00 00 00 >:EO 00 00 00 00 00 >:E8 00 00 00 00 00 >:FO 00 00 00 00 FF >:F8 00 00 00 00 00

Anatom y of the 1541

00 00 00 00 00 41 52 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 54 45 OD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 41 43 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

......... ....... .... .., .......... ...... ., ........ ......... ....... ......... .......

.... DATA FOR REC ORD 70 .. ill"

............

.... '" .......... ......... ....... .......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ............

II

..

......... ....... ......... ....... ......... ....... ......... ....... 10

..............

......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ......... ....... ......

III

........

......... ....... ......... .......

If we get a block numbe r greate r than 120 from the calculation, the pointer can no longer be found on the first side-sector block, but in the next side-sector blocks. In this case, you divide the block numbe r by 120, the quotient being the number of the side-sector block. The remainder gives the location of the pointer within this block. For instance, to find record numbe r 425, divide by 120, getting a quotient 3, remainder 65. Therefore, you must read side-sector block 3 and get the pointer to the 65th data block. Betwe en 2 and 4 block accesses are necessary to access a record in a relative data file,

178

ABACUS Software

Anatomy of the 1541

When creating or expanding a relative file, the following takes place: First, a directory entry is created for the relative file, containing the record length. Two channels are reserved for the relative file, one for the data, the other for the side-sectors. If a record pointer is set to a specific record, the DOS first checks to see if the record already exists. If so, the corresponding block is read and the buffer pointer is set so that the contents can be accessed. If not, the record is created. All records preceding this record number which do not already exist are also created. The first byte of a new record is written to contain $FF (255), and the rest of the record is filled with $00. If the corresponding record is at the beginning of a block, the rest of the block is filled with empty records. Each time a non-existing record is accessed, the error message 50,RECORD NOT PRESENT is returned. When writing a new record, this is not considered an error, but indicates that a new record was created.

You can use this method for creating a new file if you know the maximum number of data records. You simply set the record pointer to this record and write $FF (CHR$(255» to this record. By allocating a file like this, the error message 50 no longer appears. You also know if there is sufficient space on the diskette. If not, the error message 52, FILE TOO LARGE is returned. With a maximum of 6 side sectors, a relative file can contain 6 * 120 * 254 = 182,880 bytes. In the case of the VIC 1541, this is more than the capacity of the whole diskette. With the bigger 8050 drive, which contains more than 500K of storage, this may present a limitation. But DOS version 2.7 has an expansion of the side-sector procedure ("super side-sector"), with which a relative file may contain up to 23 MB. DOS 2.7 is contained in the CBM 8250 and the Commodore hard drives as well as the newer 8050 drives (see section 5.2). Because a relative file requires two data channels and the VIC 1541 has only 3 channels available, only one relative file can be open at a time. The third channel can still be used for a sequential file open at the same time. With the larger CBM drives, more channels are available (3 relative files open simultaneously, see also section 5.2).

179

Anatomy of the 1541

ABACUS Software

3.5 DOS 2.6 R01\'1 LIST INGS

***** ***** ***** ***** ***** ***** SEI 78 C100 LDA #$F7 A9 F7 C101 $lCOO AND 2D 00 1C C103 PHA 48 C106 LDA $7F AS 7F C107 $C110 BEQ FO 05 C109 PLA 68 C10B ORA #$00 09 00 C10C BNE $Cl13 DO 03 C10E PLA 68 CII0 ORA #$08 09 08 C111 STA $lCOO lC 8D 00 C113 CLI 58 C116 RTS 60 C117

turn LED on erase LED bit drive numb er O? not drive 0, turn LED off turn LED on

***** ***** ***** ***** ***** ***** SEI 78 C118 LDA #$08 A9 08 C119 $lCOO ORA lC OD 00 CIIB $lCOO STA lC 8D 00 CIIE CLI 58 C121 RTS 60 C122

turn LED on

***** ***** ***** ***** ***** ***** LDA #$00 A9 00 C123 STA $026C 8D 6C 02 C125

clea r erro r flags

C128 C12B

8D 6D 02 60

STA $026D RTS

***** ***** ***** ***** ***** ***** C12C C12D C12E

78 8A 48

SEI TXA PHA

LED on

clea r coun ter for LED flash clea r bit numb er prep are for LED flash after erro r save X regis ter

181

ABACUS Software

Anatomy or the 1541

C12F C131

A9 50 8D 6C 02

LDA #$50 STA $026C

C134 C136 C139 C13C C13F C142 C143 C144 C145

A2 BD 8D OD 8D 68

LDX LDA STA ORA STA PLA TAX CLI RTS

00 CA 6D 00 00

FE 02 1C 1C

AA

58 60

#$00 $FECA,X $026D $lCOO $lCOO

C146 C148

A9 00 8D F9 02

LDA #$00 STA $02F9

C14B C14E C150

AD 8E 02 85 7F 20 BC E6

LDA $028E STA $7F JSR $E6BC

C153 C155 C157 C159 C15B

A5 10 29 C9 FO

LDA BPL AND CMP BEQ

C15D

4C B4 D7

JMP $D7B4

C160

20 B3 C2

JSR $C2B3

C163 C165 C168 C16A C16D

B1 8D A2 BD CD

LDA STA LDX LDA CMP

C170 C172 C173

FO 08 CA 10 F5

A3 75 02 OB 89 FE 75 02

8 store bit for LED turn LED on get x register back

******************************

84 09 OF OF 03

cntr for LED flash to 80

$84 $C160 #$OF #$OF $C160

($A3),Y $0275 #$OB $FE89,X $0275

BEQ $C17A DEX BPL $C16A

182

interpret command from computer clear flag for no BAM write last drive number drive number prepare 'ok' message secondary address data address 15, command channel yes, interpret filename as command else to OPEN command determine line len and clear flags get first character and store 11 commands compare to first character found?

ABACUS Software

Anatomy of the 1541

C175 C177 C17A C17D C17F CI81

A9 4C 8E EO 90 20

31 C8 C1 2A 02 09 03 EE C1

LDA JMP STX CPX BCC JSR

#$31 $C1C8 $022A #$09 $C184 $C1EE

C184 C18"? C18A C18C C18F C191

AE BD 85 BD 85 6C

2A 95 6F A1 70 6F

LDX LDA STA LDA STA JMP

$022A $FE95,X $6F $FEA1,X $70 ( $006F)

02 FE FE 00

****************************** C194 C196

A9 00 8D F9 02

LDA #$00 STA $02F9

C199 CI9C

AD 6C 02 DO 2A

LDA $026C BNE $C1C8

C19E CIAO CIAI CIA3 C1A5 C1A7 CIi\A ClAD CIAF ClB2 ClB3 CIB5 CIB7 C1BA

AO 98 84 84 84 20 20 A5 8D AA A9 95 20 4C

LDY TYA STY STY STY JSR JSR LDA STA TAX LDA STA JSR JMO

00 80 81 A3 C7 E6 23 C1 7F 8E 02 00 FF BD C1 DA D4

not found 31, 'syntax error' number of cmd word command number < 9? test for 'R' , 'S' , and 'N' command number jump address 10 jump address hi jump to command prepare error msg after executing cmd clear flag for no BAM write error flag set? yes, then set error message

#$00 $80 $81 $A3 $E6C7 $C123 $7F $028E #$00 $FF,X $C1BD $D4DA

****************************** 1-\0 28 LDY #$28 C1BD LDA #$00 A9 00 C1BF

183

error number 0 track number 0 sector number 0 prepare 'ok' msg erase error flag drive number save as last drv #

erase input buffer close internal channel erase input buffer erase 41 characters

ABACUS Software

C1C1 C1C4 C1C5 C1C7

99 00 02 88 10 FA 60

Anatomy of the 1541

STA $0200,Y DEY BPL $C1C1 RTS

****************************** C1C8 C1CA C1CC C1CE

AO 84 84 4C

00 80 81 45 E6

LDY STY STY JMP

#$00 $80 $81 $E645

****************************** C1D1 A2 00 LDX #$00 C1D3 STX $027A 8E 7A 02 C1D6 A9 3A LDA #$3A C1D8 20 68 C2 JSR $C268 C1DB C1DD C1DE C1DF

FO 05 88 88 8C 7A 02

BEQ $C1E2 DEY DEY STY $027A

CIE2

4C 68 C3

JMP $C368

$200 to $228

output error msg (track & sector 0) track = 0 sector = 0 error number in A, generate error msg check input

1 '

~lne

pointer to drive # I



I

test line t.o ' • to end no colon found?

I

or

points to drive # (before colon) get drive # and turn LED on

****************************** C1E5 AO 00 LDY #$00 C1E7 A2 00 LDX #$00 C1E9 A9 3A LDA #$3A C1EB 4C 68 C2 JMP $C268

check input line ptr to input buffer counter for commas

****************************** C1EE JSR $CIE5 20 E5 C1

check input line test line to ' . , or end colon found?

C1F1 C1F3 C1F5 C1F8

DO 05 A9 34 4C C8 C1 88

BNE $CIF8 LDA #$34 JMP $CIC8 DEY 184

I



I

test line to colon or to end

34,

'syntax error'

ABACUS Software

Anatomy of the 1541

C1F9 C1FA C1FD C1FE

88 8C 7A 02 8A DO F3

DEY STY $027A TXA BNE $C1F3

C200 C202 C205 C206 C208 C20A C20C

A9 20 8A FO A9 09 8D

LDA JSR TXA BEQ LDA ORA STl'1.

C20F C2l0 C2l3 C2l6 C219 C21B C21D C220 C223 C225 C228 C229 C22B C22E

E8 8E 8E AD FO A9 OD 8D A9 8D 98 FO 9D

C231 C234 C236 C239 C23A C23D C23E C24A C243 C245 C248 C24A C24C

8D A9 20 E8 8E CA AD FO A9 EC FO 09 09

3D 68 C2 02 40 21 8B 02 77 78 8A OD 80 8B 8B 00 8A

02 02 02 02 02 02

29 7A 02 AD 77 02 79 02 8D 68 C2 78 02 8A 02 02 08 77 02 02 04 03

INX S'I,·( STX LDA BEQ LDA ORA STA LDA STA TYA BEQ STA LDA STA LDA JSR INX STX DEX LDA BEQ LDA. CPX BEQ ORA ()P,A

#$3D $C268 $C20A #$40 #$21 $028B $0277 $0278 $028A $C228 #$80 $028B $028B #$00 $028A $C254 $027A,X $0277 $0279 #$8D $C268

set ptr to pos of the " , " before yes, then error'

colon drive # the 11 • " 'syntax

'='

check input to 1==' comma found? no set bit 6 and bit 0 and 5 flag for syntax check

wildcard found? no set bit 7 reset wildcard flag '=' found? no number of commas before '='

$0278

shift CR check line to end increment comma ctr store # of commas

$028A $C245 #$08 $0277 $C24C #$04 #$03

wildcard found? no set bit 3 comma after '='? no set bit 2 set bits 0 and 1

185

ABACUS Software

Anatomy of the 1541

C24E C251

4D 8B 02 8D 8B 02

EOR $028B STA $028B

C254 C257 C25A

AD BB 02 AE 2A 02

3D A5 FE

LDA $028B LDX $022A AND $FEA5,X

C25D C25F C260 C263 C265

DO 60 8D A9 4C

BNE RTS STA LDA JMP

01 6C 02 30 C8 C1

$C260 $026C #$30 $C1C8

****************************** C268 C26B C26E C270

8D CC BO B1

C272 C273 C276 C278 C27A C27C C27E C280 C283 C285 C287 C288 C28B C28E C290 C292 C294 C296

C8 CD FO C9 FO C9 DO EE C9 DO 98 9D AD 29 FO A9 95 8D

C299 C29A

E8 EO 04

75 02 74 02 2E A3 75 02 28 2A 04 3F 03 8A 02 2C E4 7B 02 8A 02 7F 07 80 E7 8A 02

STA CPY BCS LDA INY CMP BEQ CMP BEQ CMP BNE INC CMP BNE TYA STA LDA AND BEQ LDA STA STA

$0275 $0274 $C29E ($A3),Y

as flag for syntax check syntax flag command number combine with check byte syntax error? set error flag 30,

'syntax error'

search characters in input buffer save character already done? yes get char from buffer

$0275 $C2AO #$2A $C280 #$3F $C283 $028A #$2C $C26B

compared with char found '* ,

$027B,X $028A #$7F $C299 #$80 $E7,X $028A

note comma position wildcard flag

INX CPX #$04

186

'? ' set wildcard flag

,, ,

no wildcard note flag and save as wildcard flag inc comma counter 4 commas already?

Anatomy of the 1541

ABACUS Software

C29C C29E C2AO C2A3 C2A6 C2A9 C2AB C2AD C2AF C2B1 C2B2

90 AO AD 9D AD 29 FO A9 95 98 60

CD 00 74 02 7B 02 8A 02 7F 04 80 E7

BCC LOY LOA STA LDA AND BEQ LDA STA TYA RTS

$C26B #$00 $0274 $027B ,X $028A #$7F $C2B1 #$80 $E7,X

***** ***** ***** ***** ***** ***** LDY $A3 A4 A3 C2B3 C2B5 C2B7 C2B8 C2BA

FO 14 88 FO 10 B9 00 02

C2BD C2BF C2C1 C2C2 C2C5 C2C7 C2C9 C2CA

C9 FO 88 B9 C9 FO C8 C8

C2CB C2CE

8C 74 02 CO 2A

C2DO C2D2 C2D4 C2D7 C2D9

AO 90 8C A9 4C

OD OA 00 02 OD 02

FF 08 2A 02 32 C8 C1

BEQ $C2CB DEY BEQ $C2CA LDA $0200 ,Y CMP BEQ DEY LDA CMP BEQ INY INY

set flag for ln end wild card flag no wild card set flag

check line lengt h ptr in comm and inpu t buff er zero?

#$OD $C2CB

one? char from inpu t buff er 'CR' yes, line end

$0200 ,Y #$OD $C2CB

prece ding char acter 'CR' yes

STY $0274 CPY #$2A LDY BCC STY LDA JMP

no, conti nue

#$FF $C2DC $022A #$32 $C1C8

187

poin ter to old value again same line lengt h comp are with 42 char acter s smal ler, then ok 32, 'synt ax erro r' line too long

ABACUS Software

Anatomy of the 1541

****************************** C2DC C2DE C2DF

AO 00 98 85 A3

C2E1 C2E4 C2E7 C2EA C2EC C2EF C2F2 C2F5 C2F8 C2FB C2FD

8D 8D 8D 85 8D 8D 8D 8D 8D A2 9D

58 4A 96 D3 79 77 78 8A 6C 05 79

C300 C302 C304 C306 C308 C30B C30E C30F C311

95 95 95 95 9D 9D CA DO 60

D7 DC E1 E6 7F 02 84 02 EC

LDY #$00 TYA STA $A3 02 02 02 02 02 02 02 02 02

STA STA STA STA STA STA STA STA STA LDX STA

$0258 $024A $0296 $D3 $0279 $0277 $0278 $028A $026C #$05 $0279,X

STA STA STA STA STA STA DEX BNE RTS

$D7,X $DC,X $E1, X $E6, X $027F,X $0284,X

A6 D3

pointer to input buffer 10 record length file type comma counter

"

"

wildcard flag error flag flags for line analysis directory sectors buffer pointers drive numbers wildcard flags track numbers sector numbers

$C2FD

****************************** C312 AD 78 02 LDA $0278 C315 8D 77 02 STA $0277 C318 A9 01 LDA #$01 C31A 8D 78 02 STA $0278 C31D 8D 79 02 STA $0279 C320 AC 8E 02 LDY $028E C323 A2 00 LDX #$00 C325 86 D3 STX $D3 C327 BD 7A 02 LDA $027A,X C32A 20 3C C3 JSR $C33C C32D

clear flag for command input

LDX $D3

188

preserve drive # number of commas save # of drive numbers last drive number position of the get drive no. before colon

Anatomy of the 1541

ABACUS Software

C32F C332 C333 C335 C336 C339 C33B

9D 98 95 E8 EC 90 60

7A 02 E2 78 02 EA

STA TYA STA INX CPX BCC RTS

$027A

save exact position

$E2,X

drive # in tablE::

$0278 $C325

got all drive #s? no, continue

****************************** TAX AA C33C LDY #$00 C33D AO 00 LDA #$3A C33F A9 3A DD 01 02 CMP $0201,X C341 FO OC BEQ $C352 C344 DD 00 02 CMP $0200,X C346 BNE $C361 DO 16 C349 INX C34B E8 TYA C34C 98 AND #$01 C34D 29 01 TAY C34F A8 TXA 8A C350 RTS C351 60 00 02

LDA INX INX CMP BEQ CMP BEQ BNE TYA ORA

colon behind it? yes colon here? no drive number

get drive number

#$30 $C34D #$31 $C34D $C34C

'0' ? yes '1' ? yes no,use last drive # last drive number set bit 7, unclear drive # clear remaining bits

BD E8 E8 C9 FO C9 FO DO 98 09

C364

29 81

AND #$81

C366

DO E7

BNE $C34F

80

' .,

$0200,X

C352 C355 C356 C357 C359 C35B C35D C35F C361 C362

30 F2 31 EE EB

search for drive # note position

#$80

****************************** LDA #$00 A9 00 C368 STA $028B 8D 8B 02 C36A

189

get drive number clear syntax flag

Anatomy of the 1541

ABACUS Software

C36D C370

AC 7A 02 Bl A3

LDY $027A LDA ($A3),Y

C372 C375 C377 C378 C37B C37D C380 C381

20 10 C8 CC BO AC 88 DO

BD C3 11

$C3BD $C388

ED

JSR BPL INY CPY BCS LDY DEY BNE

C383 C386 C388 C38A C38C

CE A9 29 85 4C

8B 02 00 01 7F 00 Cl

DEC LDA AND STA JMP

$028B #$00 #$01 $7F $CIOO

74 02 06 74 02

$0274 $C383 $0274 $C370

pos in cmd line get chars from cmd buffer get drive number certain number? increment pOlnter line end? yes search line for drive no.

drive number turn LED on

****************************** C38F A5 7F LDA $7F 49 01 EOR #$01 C391 29 01 AND #$01 C393 STA $7F 85 7F C395 C397 RTS 60

reverse drive # drive number switch bit 0

****************************** LDY #$00 C398 AO 00 C39A AD 77 02 LDA $0277 CMP $0278 C39D CD 78 02 C3AO FO 16 BEQ $C3B8 C3A2 CE 78 02 DEC $0278 C3A5 AC 78 02 LDY $0278 LDA $027A,Y B9 7A 02 C3A8

establish file type

C3AB C3AC C3AE

A8 Bl A3 AO 04

TAY LDA ($A3),Y LDY #$04

C3BO C3B3 C3B5

D9 BB FE FO 03 88

CMP $FEBB,Y BEQ $C3B8 DEY

190

'='

found?

no get pointer set pointer to char behind '=' char from buffer compare with marker for file type 'S' , 'P' , 'U' , 'R' match?

ABACUS Software

Anatomy of the 1541

C3B6 C3B8 C3B9

DO F8 98 8D 96 02

BNE $C3BO TYA STA $0296

C3BC

60

RTS

****************************** C3BD CMP #$30 C9 30 C3BF FO 06 BEQ $C3C7 CMP #$31 C3C1 C9 31 FO 02 BEQ $C3C7 C3C3 09 80 ORA #$80 C3C5 C3C7 C3C9

29 81 60

note file type (1-4) check drive number '0 ' '1 ' no zero or one, then set bit 7

AND #$81 RTS

****************************** C3CA A9 00 LDA #$00 STA $6F C3CC 85 6F C3CE 8D 8D 02 STA $028D 48 PHA C3D1 C3D2 AE 78 02 LDX $0278 C3D5 PLA 68 ORA $6F 05 6F C3D6 PHA C3D8 48 LDA #$01 C3D9 A9 01 STA $6F C3DB 85 6F DEX C3DD CA BMI $C3EF C3DE 30 OF B5 E2 LDA $E2,X C3EO 10 04 BPL $C3E8 C3E2 ASL $6F 06 6F C3E4 ASL $6F C3E6 06 6F 4A LSR A C3E8 BCC $C3D5 C3E9 90 EA $6F ASL 06 6F C3EB $C3D5 BNE DO E6 C3ED PLA C3EF 68 TAX AA C3FO LDA $C43F,X BD 3F C4 C3F1 PHA 48 C3F4 191

verify drive number

# of drive numbers

get syntax flag

Anatomy of the 1541

ABACUS Software

3E E2 01 7F 8C 02 28 3D C6 12 8F C3

AND STA PLA ASL BPL LDA AND STA LDA BEQ JSR BEQ JSR

A $C43C $E2 #$01 $7F $028C $C434 $C63D $C420 $C38F

00 8C 02 3D C6 1E 74 CS C1

LDA STA JSR BEQ LDA JSR

#$00 $02SC $C63D $C439 #$74 $C1CS

C3F5 C3F7 C3FA C3FB C3FC C3FE C400 C402 C404 C407 C409 C40C C40E

29 8D 68 OA 10 A5 29 85 AD FO 20 FO 20

C411 C413 C416 C419 C41B C41D

A9 8D 20 FO A9 20

C420

20 SF C3

JSR $C3SF

C423 C426 C427

20 3D C6 OS 20 SF C3

JSR $C63D PHP JSR $C3SF

C42A C42B C42D C42F C432 C434 C437 C439 C43C

2S FO A9 SD FO 20 DO 4C 2A

PLP BEQ LDA STA BEQ JSR BNE JMP ROL

C43D

4C 00 C4

03 8C 02

OC 00 SC 02 05 3D C6 E2 00 C1

#$03 $028C

$C439 #$00 $02SC $C439 $C63D $C41B $C100 A

JMP $C400

192

isolate drive #

initialze drive error? switch to other drive initialize drive no error? 74, 'drive not ready' initialize drive switch to other drive no error? number of drives initialize drive error? Turn LED on drive # from carry after bit 0

Anatomy of the 1541

ABACUS Software

***** ***** ***** ***** ***** ***** C440 C448

flags for drive check

00 80 41 01 01 01 01 81 81 81 81 42 42 42 42

***** ***** ***** ***** ***** ***** CA C3 00 92 02 AC C5

JSR LDA STA JSR

$C3CA #$00 $0292 $C5AC

C44F C452 C454 C457

20 A9 8D 20

C45A C45C C45F C461

DO 19 CE 8C 02 10 01 60

C462 C464 C467 C46A C460

A9 80 20 20 4C

C470

20 17 C6

JSR $C617

C473 C475 C478 C47B C470

FO 10 20 D8 C4 AD 8F 02 FO 01 60

BEQ JSR LDA BEQ RTS

$C485 $C4D8 $028F $C47E

C47E C481 C483 C485 C488 C48A

AD 53 02 30 ED 10 FO AD 8F 02 FO 02 60

LOA BMI BPL LOA BEQ RTS

$0253 $C470 $C475 $028F $C45C

C48B

20 04 C6

JSR $C604

C48E

FO 1A

BEQ $C4AA

01 8D 8F 00 52

02 C3 C1 C4

BNE $C475 DEC $028C BPL $C462 RTS LOA STA JSR JSR JMP

#$01 $0280 $C38F $C100 $C452

193

searc h for file in direc tory initi alize drive poin ter read first direc tory block entry prese nt? drive numb er clear ? no

chang e drive turn LEO on and searc h searc h for next file in direc tory not found ? verif y dir entry more files ?

file not found ? yes

searc h next direc tory block not found ?

ABACUS Software

Anatomy of the 1541

C490

DO 28

C492 C494 C497 C49A C49D C49F C4A2 C4A5 C4A7 C4AA C4AD C4AF C4B2 C4B4

A9 8D 20 20 A9 8D 20 DO 8D AD DO CE 10 60

01 8D 8F 00 00 92 AC 13 8F 8F 28 8C DE

C4B5 C4B8 C4BA C4BD C4CO C4C2 C4C5 C4C7

20 FO 20 AE 10 AD FO DO

17 FO D8 53 07 8F EE OE

C4C9 C4CC C4CE C4DO C4D2

AD FO B5 29 CD

96 02 09 E7 07 96 02

C4D5 C4D7

DO DE 60

BNE $C4B5 RTS

C4D8 C4DA C4DD C4DE C4E1 C4E4

A2 8E E8 8E 20 FO

LDX STX INX STX JSR BEQ

BNE $C4BA 02 C3 C1 02 C5 02 02 02

C6 C4 02 02

FF 53 02 8A 02 89 C5 06

LDA STA JSR JSR LDA STA JSR BNE STA LDA BNE DEC BPL RTS

#$01 $028D $C38F $C100 #$00 $0292 $C5AC $C4BA $028F $028F $C4D7 $028C $C492

JSR BEQ JSR LDX BPL LDA BEQ BNE

$C617 $C4AA $C4D8 $0253 $C4C9 $028F $C4B5 $C4D7

LDA BEQ LDA AND CMP

$0296 $C467 $E7,X #$07 $0296

#$FF $0253 $028A $C589 $C4EC 194

change drive turn LED on read dir block found?

next entry in dir not found? check entry file found? yes no, then done

file type same as desired file type? no

flag for file found set pointer to file

Anatomy of the 1541

ABACUS Software

C4E6

60

C4E7 C4EA C4EC C4EE C4FO C4Fl C4F3 C4F5 C4F7 C4F9 C4FC C4FE C501 C502 C505 C507

20 DO A5 55 4A 90 29 FO A9 CD FO BD

RTS 94 C5 FA 7F E2 OB 40 FO 02 8C 02 E9 7A 02

AA

20 A6 C6 AO 03 4C ID C5

C50A

BD 00 02

C50D C50F C511 C513 C515 C517

Dl FO C9 DO B1 C9

C519 C51B C51C C51D

FO cc E8 C8 EC 76 02

C520 C522 C525 C527 C529

BO BD C9 FO DO

C52B C52D

CO 13 BO 06

94 OA 3F D2 94 AO

09 00 02 2A OC DF

JSR BNE LDA EOR LSR BCC AND BEQ LDA CMP BEQ LDA TAX JSR LDY JMP

$C594 $C4E6 $7F $E2,X A $C4FE #$40 $C4E7 #$02 $028C $C4E7 $027A ,X

ptr to next file end, then done drive numb er

$C6A6 #$03 $C51D

get len of filen ame

LDA $0200 ,X CMP BEQ CMP BNE LDA CMP

($94) ,Y $C51B #$3F $C4E7 ($94) ,Y #$AO

BEQ $C4E7 INX INY CPX $0276 BCS LDA CMP BEQ BNE

$C52B $0200 ,X #$2A $C535 $C50A

CPY #$13 BCS $C535

195

searc h both drive s yes

get chars out of comm and line same char in dir? yes I? I no shif t blank , end of name? yes incre ment poin ter end of the name in the comm and? yes next char acter I* I yes, file found else cont searc h 19 reach ed end of name

ABACUS Software

C52F C531

B1 94 C9 AO

C533 C535 C538 C53B C53D C53F C542 C545 C547 C549 C54B C54D C54F C550 C551

DO AE 8E B5 29 80 AD 95 A5 95 AO B1 C8 48 29

B2 79 53 E7 80 8A 94 DD 81 D8 00 94

C553 C555 C556 C558 C55A C55C C55E C560 C562 C564

85 68 29 30 09 29 05 85 A9 35

6F

C566 C568 C56A C56C C56E C570 C572 C574 C577 C578 C57A

05 95 B5 29 05 95 Bl 9D C8 Bl 9D

Anatomy of the 1541

LDA ($,94 ),Y CMP #$AO 02 02 02 02

40

DF 02 20 27 6F 6F 80 E7 6F E7 E2 80 7F E2 94 80 02 94 85 02

BNE LDX STX LDA AND STA LOA STA LDA STA LDY LDA INY PHA AND STA PLA AND BMI ORA AND ORA STA LDA AND ORA STA LDA AND ORA STA LDA STA INY LDA STA

$C4E7 $0279 $0253 $E7,X #$80 $028A $0294 $DD,X $81 $D8,X #$00

shif t blank , end of name not found

secto r # of the dir ente r in table

($94) ,Y

file type

#$40

isola te scrat chprote ct bit ( 6) and save

$6F #$DF $C55C #$20 #$27 $6F $6F #$80 $E7,X $6F,X $E7,X $E2,X #$80 $7F $E2,X

clea r bit 7 set bit 5 clea r bits 3 and 4 get bit 6 again isola te flag for wildc ard write in table drive numb er

($94) ,Y

$0280 ,X

first track of file

($94) ,Y

$0285 ,X

196

get secto r from dir

Anatomy of the 1541

ABACUS Software

C57D C580 C582 C584 C586 C589 C58B C58E C591 C594 C597 C599

58 07 15 94 58 FF 8F AD 78 8D 79 CE 79 10 01 60 AD

DO AO B1 8D A9 8D

02

02 02 02 02 02

LDA BNE LDY LDA STA LDA STA LDA STA DEC BPL RTS

$0258 $C589 #$15 ($94),Y $0258 #$FF $028F $0278 $0279 $0279 $C59A

C59A C59D C59F C5A1 C5A4 C5A6 C5A8 C5AB

AE B5 30 BD DO A9 8D 60

79 02 E7 05 80 02 EE 00 8F 02

LDX LDA BMI LDA BNE LDA STA RTS

$0279 $E7,X $C5A6 $0280,X $C594 #$00 $028F

C5AC C5AE C5B1 C5B2 C5B5 C5B8 C5BA C5BC C4BE C5C1 C5C4 C5C7 C5C9

AO 00 8C 91 02 88 8C 53 02 AD 85 FE 85 80 A9 01 85 81 8D 93 02 20 75 D4 AD 93 02 DO 01 60

LDY STY DEY STY LDA STA LDA STA STA JSR LDA BNE RTS

#$00 $0291

C5CA C5CC

A9 07 8D 95 02

LDA #$07 STA $0295

C5CF

A9 00

LDA #$00

$0253 $FE85 $80 #$01 $81 $0293 $D475 $0293 $C5CA

197

record length record length get from directory

wildcard flag set? yes trk # already set? yes

18, directory track sector 1 read sector

number of directory entries (-1 )

ABACUS Software

Anatomy of the 1541

C5D1

20 F6 D4

JSR $D4F6

C5D4 C5D7 C5DA C5DD C5DF C5E1 C5E3 C5E6 C5ES

SD 20 CE AO B1 DO

93 ES 95 00 94 lS AD 91 DO 2F 20 3B

STA JSR DEC LDY LDA BNE LDA BNE JSR

$0293 $D4ES $0295 #$00 ($94),Y $C5FB $0291 $C617 $DE3B

C5EB C5ED C5FO C5F2 C5F5 C5FS C5FA

A5 SD A5 AE SD FO 60

Sl 91 02 94 92 02 92 02 1D

LDA STA LDA LDX STA BEQ RTS

$Sl $0291 $94 $0292 $0292 $C617

C5FB C5FD C600 C602

A2 EC DO FO

01 92 02 2D 13

LDX CPX BNE BEQ

#$01 $0292 $C62F $C617

C604 C607 C609 C60C C60E C611 C614 C617 C619

AD S5 S5 SO AD 90 S5 Sl 20 75 AD 94 20 CS AD FF SD 53

LDA STA LDA STA JSR LDA JSR LDA STA

$FES5 $SO $0290 $81 $D475 $0294 $D4CS #$FF $0253

C61C C61F

AD 95 02 30 OS

LDA $0295 BMI $C629

C621 C623

A9 20 20 C6 D1

LDA #$20 JSR $D1C6

02 D4 02

02 DE

FE 02 D4 02 D4 02

198

get char from buffer save as track # set buffer pointer decrement counter first byte from dir

get track and sector number sector number buffer pointer

buffer ptr to one?

lS, track # of BAM track number sector number read block set buffer pointer clear flag for file found all directory entries checked? inc buffer ptr by 32, next entry

ABACUS Software

Anatomy of the 1541

C626

4C D7 C5

JMP $C567

and continue

C629 C62C

20 4D D4 4C C4 C5

JSR $D44D JMP $C5C4

set buffer pointer read next block

C62F C631 C634

AS 94 8D 94 02 20 3B DE

LDA $94 STA $0294 JSR $DE3B

C637 C639 C63C

AS 81 8D 90 02 60

LDA $81 STA $0290 RTS

******************************

get track & sector no. from buffer save sector number test and initialize drive

C63D C63F C641 C643 C645 C647 C649 C64C C64F C651 C653 C655 C657 C659

AS DO A6 56 90 A9 8D 20 AO C9 FO C9 FO C9

68 28 7F 1C 22 FF 98 02 OE DO FF 02 OA 03 06 OF

LDA BNE LDX LSR BCC LDA STA JSR LDY CMP BEQ CMP BEQ CMP

$68 $C669 $7F $lC,X $C669 $FF $0298 $DOOE #$FF #$02 $C65F #$03 $C65F #$OF

C65B C65D C65F C661 C662 C664 C666 C669 C66B C66D

FO AO A6 98 95 DO 20 A6 B5 60

02 00 7F

BEQ LDY LDX TYA STA BNE JSR LDX LDA RTS

$C65F #$00 $7F

drive number

$FF,X $C669 $D042 $7F $FF,X

save error flag error? load BAM drive number transmit error code

FF 03 42 DO 7F FF

199

drive number disk changed? no, then done set error flag read dir track 20, 'read error'? yes 21, 'read error'? yes 74, 'drive not ready'? yes

ABACUS Software

Anatomy of the 1541

****************************** C66E C66F C672

48 20 A6 C6 20 88 C6

PHA JSR $C6A6 JSR $C688

C675 C676 C677

68 38 ED 4B 02

PLA SEC SBC $024B

C67A C67B C67D C67F C681 C683 C684 C685 C687

AA

TAX BEQ BCC LDA STA INY DEX BNE RTS

FO 90 A9 91 C8 CA DO 60

OA 08 AO 94 FA

$C687 $C687 #$AO ($94),Y

name of file in directory buffer get end of the name write filename in buffer compare len with max length

pad with shift spc

$C681

****************************** C688 98 TYA C689 OA ASL A C68A A8 TAY C68B B9 99 00 LDA $0099,Y C68E 85 94 STA $94 C690 B9 9A 00 LDA $009A C693 85 95 STA $95 C695 AO 00 LDY #$00 C697 BD 00 02 LDA $0200,x C69A C69C C69D

91 94 C8 FO 06

STA ($94),Y INY BEQ $C6A5

C69F C6AO C6A3 C6A5

E8 EC 76 02 90 F2 60

INX CPX $0276 BCC $C697 RTS

200

buffer number times 2 as pointer bffr ptr to $94/$95 transmit characters in buffer buffer already full?

-----~-----------

ABACUS Software

Anatomy of the 1541

****************************** C6A6 C6A8 C6AB C6AC C6AD

A9 00 8D 4B 02 8A 48 BD 00 02

C6BO C6B2 C6B4 C6B6 C6B8 C6BB C6BC C6BE C6C1 C6C3 C6C6 C6C8 C6CB C6CC C6CD

C9 FO C9 FO EE E8 A9 CD 90 EC 90 8E 68

2C 14 3D 10 4B 02 OF 4B 02 05 74 02 E5 76 02

AA

60

LDA #$00 STA $024B TXA PHA LDA $0200,X CMP BEQ CMP BEQ INC INX LDA CMP BCC CPX BCC STX PLA TAX RTS

#$2C $C6C8 #$3D $C6C8 $024B #$OF $024B $C6C8 $0274 $C6AD $0276

search for end of name in command preparation for len get characters out of buffer

,, , '='

inc len of name 15 greater? end of input line?

ptr to end of name

****************************** LDA $83 AS 83 C6CE 48 PHA C6DO C6D1 C6D3 C6D4

A5 82 48 20 DE C6

LDA $82 PHA JSR $C6DE

C6D7 C6D8 C6DA C6DB C6DD

68 85 82 68 85 83 60

PLA STA $82 PLA STA $83 RTS

secondary address and channel no. create file entry for directory get data back

****************************** LDA #$11 A9 11 C6DE STA $83 85 83 C6EO

201

17 secondary address

ABACUS Software

Anatomy of the 1541

C6E2

20 EB DO

JSR $DOEB

C6E5 C6E8 C6EB C6ED C6FO C6F2

20 E8 D4 AD 53 02 10 OA AD 8D 02 DO OA 20 06 C8

JSR LDA BPL LDA BNE JSR

$D4E8 $0253 $C6F7 $028D $C6FC $C806

C6F5 C6F6 C6F7 C6FA C6FC C6FF C701 C704 C707

18 60 AD FO CE DO CE 20 20

CLC RTS LDA BEQ DEC BNE DEC JSR JSR

$028D $C71B $028D $C70E $028D $C38F $C806

C70A C708

38 4C 8F C3

SEC JMP $C38F

C70E C710

A9 00 8D 73 02

LDA #$00 STA $0273

C713 C716 C719 C71A

8D 8D 02 20 B7 C7 38 60

STA $028D JSR $C7B7 SEC RTS

C71B C71D C71F C721 C724 C726 C728 C729 C72B C72E C730

A2 AO B1 8D FO A2 88 B1 8D EO FO

LDX LDY LDA STA BEQ LDX DEY LDA STA CPX BEQ

8D 1F 8D OD 8D 8F 06

02 02 02 C3 C8

18 1D 94 73 02 02 16 94 72 02 16 OA

#$18 #$1D ($94), Y $0273 $C728 #$16 ($94),Y $0272 #$16 $C73C

202

open channel for reading set buffer pointer not yet last entry? write 'blocks free. ,

change drive write 'blocks free. , change drive drive #. for header, hi-byte write header

number of blocks hi in buffer zero? number of blocks 10 in buffer

Anatomy of the 1541

ABACUS Software

C732 C734 C736 C737 C739 C73B C73C C73F C741 C742 C743 C745

C9 90 CA C9 90 CA 20 B1 48 OA 10 A9

OA 06 64 01 AC C7 94 05 3C

CMP BCC DEX CMP BCC DEX JSR LDA PHA ASL BPL LDA

#$OA $C73C

10

#$64 $C73C

100

$C7AC ($94),Y

erase buffer file type

A $C74A #$3C

bit 7 in carry bit 6 not set? ,= 2? get track and sector number s '? drive

Il1Jmr. l e

r

Anatomy of the 1541

ABACUS Software

DA01 DA03 DA06

A5 81 8D 6F 02 4C 99 C1

LDA $81 STA $026F JMP $C199

******************************

DA09 DAOC DAOF DA11 DA12 DA14

BC B9 AO 88 30 D9

7A 02 00 02 04

DA17 DA19 DA1C DAlE DA1F DA21

DO 8C AO 88 30 D9

DA24 DA26 DA29

DO F8 8C 4A 02 60

08 B2 FE F8 97 02 05 08 B6 FE

LDY LDA LDY DEY BMI CMP

$027A,X $0200,Y #$04

BNE STY LDY DEY BMI CMP

$DA11 $0297 #$05

$DA1C $FEB2,Y

$DA29 $FEB6,Y

BNE $DA1E STY $024A RTS

******************************

DA2A

20 39 CA

JSR $CA39

DA2D DA2F DA32 DA34

A9 20 FO 20

LDA JSR BEQ JSR

DA37 DA39 DA3A DA3B DA3D

A6 81 E8 8A DO 05 20 A3 D1

LDX $81 INX TXA BNE $DA42 JSR $D1A3

DA40 DA42

A9 02 20 C8 D4

LDA #$02 JSR $D4C8

80 A6 DD F6 95 DE

#$80 $DDA6 $DA 2A $DE95

272

sector

check file type and control mode pointer in cmd line get chars from line

control modes 'R' , 'w' , 'A' , 'M' save

file types 'D', 'S', 'P', 'U', 'L' save preparation for append open channel to read, get byte last byte? no get track and sector numbers sector number not $FF? close buffer, write block buffer pointer to 2

ABACUS Software

DA45 DA47 DA49 DA4B DA4D DA4F DA51 DA54

A6 A9 95 A9 05 A6 9D 60

82 01 F2 80 82 83 2B 02

Anatomy of the 1541

LDX LDA STA LDA ORA LDX STA RTS

$82 #$01 $F2,X #$80 $82 $83 $022B,X

****************************** DA55 A9 OC LDA #$OC DA57 8D 2A 02 STA $022A DA5A A9 00 LDA #$00 LDX $0274 DA5C AE 74 02 DA5F CA DEX DA60 FO OB BEQ $DA6D DA62 CA DEX BNE $DA86 DA63 DO 21 LDA $0201 DA65 AD 01 02 20 BD C3 JSR $C3BD DA68 BMI $DA86 DA6B 30 19 DA6D STA $E2 85 E2 INC $0277 DA6F EE 77 02 DA72 EE 78 02 INC $0278 INC $027A DA75 EE 7A 02 LDA #$80 DA78 A9 80 DA7A STA $E7 85 E7 DA7C A9 2A LDA #$2A DA7E 8D 00 02 STA $0200

DA81 DA84 DA86

8D 01 02 DO 18 20 E5 C1

STA $0201 BNE $DA9E JSR $C1E5

DA89 DA8B DA8E DA90 DA91 DA92

DO 20 AO 88 88 8C

BNE JSR LDY DEY DEY STY

05 DC C2 03 7A 02

$DA90 $C2DC #$03 $027A

273

channel number set flag for WRITE

channel # in table OPEN "$" command number 12

second character get drive number not a plain number?

set wildcard flag '* , as file name in command buffer unconditional jump test input line up to ' . , found? clear flags

pointer to drive # in command

ABACUS Software

Anatomy of the 1541

DA95 DA98 DA9B DA9E

20 20 20 20

DAA1 DAA4 DAA7

20 B7 C7 20 9D C4 20 9E EC

JSR $C7B7 JSR $C49D JSR $EC9E

DAAA

20 37 D1

JSR $D137

DAAD DAAF DAB2 DAB4

A6 9D A4 8D

82 3E 02 7F 8E 02

LDX STA LDA STA

$82 $023E $7F $028E

DAB7 DAB9 DABB DABD

09 95 A9 85

04 EC 00 A3

ORA STA LDA STA

#$04 $EC,X #$00 $A3

DABF

60

00 98 20 CA

C2 C3 C3 C3

JSR JSR JSR JSR

$C200 $C398 $C320 $C3CA

analyze line ascertain file type get drive number initialize drive 1'.f'..... necessary prepare disk title load directory create and prepare directory get byte from buffer channel number byte in output reg drive number save as last drive number PRG-flag reset pointer in input buffer

RTS

****************************** DACO A9 00 LDA #$00 DAC2 8D F9 02 STA $02F9 DAC5 A5 83 LDA $83 DAC7 DO 08 BNE $DAD4 DAC9 A9 00 LDA #$00 DACB DACE DAD1

8D 54 02 20 27 D2 4C DA D4

STA $0254 JSR $D227 JMP $D4DA

DAD4 DAD 6

C9 OF FO 14

CMP #$OF BEQ $DAEC

DAD8 DADE DADD

20 02 DB A5 83 C9 02

JSR $DB02 LDA $83 CMP #$02

274

CLOSE-routine secondary address not zero? secondary address 0, LOAD close channel close internal channels 17 & 18 15 "1 1 yes, close a~~ channels close file secondary address

ABACUS Software

DADF DAEI DAE4 DAE6 DAE9 DAEC DAEE DAFO DAF3 DAF5 DAF7 DAFA DAFC DAFF

Anatomy of the 1541

DO 03 4C 94 C1

BCC LDA BNE JMP

$DAD1 $026C $DAE9 $C194

4C A9 85 20 C6 10 AD DO 4C 4C

JMP LDA STA JSR DEC BPL LDA BNE JMP JMP

$C1AD #$OE $83 $DB02 $83 $DAFO $026C $DAFF $C194 $CIAD

90 t 0 1

A.D

f~' ) ....."

AD OE 83 02 83 F9 6C 03 94 AD

02

C1 DB 02 C1 Cl

****************************** LDX $83 A6 83 DB02 .Bll 2B 02 LDA $022B,X DB04 CMP #$FF DB07 C9 FF ~

DB09 DBOB

DO 01 60

BNE $DBOC RTS

DBOC DBOE DBIO DB13 DB15 DB17 DB19 DBIB

29 85 20 C9 FO C9 FO 20

AND STA JSR CMP BEQ CMP BEQ JSR

DBIE

BO 09

BCS $DB29

DB20 DB23

20 62 DB 20 A5 DB

JSR $DB62 JSR $DBA5

DB26 DB29

20 F4 EE 4C 27 D2

JSR $EEF4 JMP $D227

OF 82 25 D1 07 OF 04 11 07 D1

#$OF $82 $D125 #$07 $DB26 #$04 $DB2C $Dl07

275

less than 2? termination 14 secondary address close file next secondary addr

termination close file secondary address get channel number no channel assigned? no, then done isolate channel # check file type direct access? yes reI-file? yes channel for writing open no file for writing? write last block write entry in dir and block write BAM close channel

Anatomy of the 1541

ABACUS Software

DB2C

20 F1 DD

JSR $DDF1

DB2F DB32

20 1E CF 20 CB E1

JSR $CF1E JSR $E1CB

DB35 DB37 DB39 DB3B DB3D DB3F DB41 DB43 DB44 DB46 DB48

A6 86 E6 A9 85 85 A5 38 E9 85 20

D5 73 73 00 70 71 D6

$D5 $73 $73 #$00 $70 $71 $D6

OE 72 51 DF

LDX STX INC LDA STA STA LDA SEC SBC STA JSR

DB4B DB4D DB4F DB51 DB53 DB55 DB57 DB5A DB5C DB5F

A6 A5 95 A5 95 A9 20 FO 20 AC

82 70 B5 71 BB 40 A6 DD 03 A5 DB 27 D2

LDX LDA STA LDA STA LDA JSR BEQ JSR JMP

$82 $70 $B5,X $71 $BB,X #$40 $DDA6 $DB5F $DBA5 $D227

#$OE $72 $DF51

****************************** DB62 A6 82 LDX $82 DB64 B5 B5 LDA $B5,X DB66 15 BB ORA $BB,X DO OC DB68 BNE $DB76 DB6A 20 E8 D4 JSR $D4E8 DB6D CMP #$02 C9 02 DB6F DO 05 BNE $DB76 DB71 A9 OD LDA #$OD DB73 20 F1 CF JSR $CFF1 DB76 20 E8 D4 JSR $D4E8 DB79 C9 02 CMP #$02 DB7B DO OF BNE $DB8C 276

get buffer #, write block change buffer get last side-sector side-sector number

minus 14 for ptr calculate block number of file channel number record number 10 record number hi bit 6 set? no enter in dirctory close channel write last block channel number record number 10 record number hi not zero? set buffer pointer not 2 CR in buffer set buffer pointer now equal to 2? no

ABACUS Software

Anatomy of the 1541

DB7D DB80 DB82 DB84 DB86 DB88 DB8A DB8C DB8D DB8F DB90 DB92 DB95 DB98

20 A6 BS DO D6 D6 A9 38 E9 48 A9 20 20 68

IE CF 82 BS 02 BB BS 00

DB99 DB9C DB9F DBA2

20 20 20 4C

F1 C7 99 1E

01 00 C8 D4 F1 CF CF DO DS CF

JSR LDX LDA BNE DEC DEC LDA SEC SBC PHA LDA JSR JSR PLA

$CF1E $82 $BS,X $DB88 $BB,X $B5,X #$00 #$01 #$00 $04C8 $CFF1

JSR $CFF1 JSR $D0C7 JSR $DS99 JMP $CF1E

****************************** LDX $82 DBA5 A6 82 STX $0270 DBA7 8E 70 02 LDA $83 DBAA A5 83 PHA 48 DBAC LDA $0260,X BD 60 02 DBAD STA $81 DBBO 8S 81 LDA $0266,X DBB2 BD 66 02 STA $0294 DBBS 8D 94 02 LDA $EC,X DBB8 B5 EC AND #$01 DBBA 29 01 STA $7F DBBC 85 7F LDA $FE85 DBBE AD 85 FE STA $80 DBC1 85 80 JSR $DF93 20 93 DF OBC3 PHA 48 DBC6 STA $F9 DBC7 85 F9 JSR $D460 20 60 D4 DBC9 LDY #$00 AO 00 DBCC LDA $FEEO,X BD EO FE DBCE STA $87 DBD1 85 87

277

change buffer channel number record number 10 decrement blk # hi and block # 10 set pointer to end buffer ptr to zero write 0 in buffer second byte = pointer to end write in buffer write block to disk and verify change buffers directory entry channel number save secondary address save sector # in dir set pointer in dir

drive number 18, directory track set increment buffer # read dir block buffer address

ABACUS Software

94 02 86 86 20 43 25 01 04 44 86 8F 86

Anatomy of the 1541

DBD3 DBD6 DBD8 DBDA DBDC DBDE DBE1 DBE3 DBES DBE7 DBE9 DBEB DBEC DBEE DBFO DBF2 DBF4

AD 85 B1 29 FO 20 C9 FO B1 29 91 C8 B1 85 84 AO B1

DBF6 DBF7 DBF8

48 88 B1 86

PHA DEY LOA (:$86), Y

DBFA DBFC DBFE DBFF DCOl DC03

DO 85 68 85 A9 20

BNE STA PLA STA LOA JSR

DC06 DC07 DC09 DCOB DCOC DCOE DC OF DC11 DC13

48 A9 91 C8 91 68 A4 91 C8

DC14 DC16

B1 86 85 81

86 80 71 1B 86

OA 80 81 67 45 E6 00 86 86 71 86

LOA STA LOA AND BEQ JSR CMP BEQ LOA AND STA INY LOA STA STY LOY LOA

PHA LOA STA INY STA PLA LDY STA INY

$0294 $86 ($86), Y #$20 $DC21 $0125 #$04 $DC29 (:$86) ,Y #:$8F ($86), Y

buffer pointer

($86),Y $80 $71 #$lB ($86),Y

track number

$DC06 $80 $81 #$67 $E645 #$00 ($86),Y ($86) ,Y

file type file closed? yes check file type rel-file? yes clear bits 4,5, & 6 in file type

sectr # of the file for overwriting save track # for overwriting set? set track number sector number 67, 'illegal track or sector' erase track number and sector # of the substitute file

$71 ($86), Y set track & sec # of the new file

LDA ($86) ,Y STA $8l

278

ABACUS Software

Anatomy

DC18 DC19 DC1B DC1E

68 91 86 20 7D C8 4C 29 DC

PLA STA ($86),Y JSR $C870 JMP $OC29

DC21 OC23 OC25

B1 86 29 OF 09 80

LOA ($86),Y AND #$OF ORA #$80

DC27 DC29 OC2C OC2E DC30 DC32 OC33 DC35 DC37 OC38 DC39 DC3B DC40 DC41 DC43

91 AE AO B5 91 C8 B5 91 68

STA LOX LOY LOA STA INY LOA STA PLA TAX LOA JSR PLA STA JMP

86 70 02 1C B5 86 BB 86

AA

A9 20 68 85 4C

90 90 05 83 07 01

($86), Y $0270 #$lC $B5,X ($86), Y

erase old file get file type isolate bits 0-3 set bit 7 for closed file channel number block number 10 in directory entry and block number hi write buffer number

#$90 $0590

code for 'writing' write block

$83 $0107

secondary address open channel for writing

DC46 DC48

A9 01 20 E2 01

LOA #$01 JSR $01E2

OC4B DC4E DC51 DC52 OC53 OC55 OC57

20 AD 48 OA 05 95 20

JSR LOA PHA ASL ORA STA JSR

DC5A OC5C

A6 82 A5 80

7F EC 9B DO

1541

$BB,Y ($86), Y

******************************

B6 DC 4A 02

or the

$OCB6 $024A A $7F $EC,X $009B

LOX $82 LOA $80

279

read block, allocate buffer find channel and buffer for read set pointer file type save drive number read block in buffer channel number track

Anatomy of the 1541

ABACUS Software

05 81 44 02

DO A5 9D 68 C9 DO A4 B9 09 99

DC74 DC77 DC79

AD 58 02

95 C7 20 8E D2

LDA $0258 STA $C7,X JSR $D28E

DC7C DC7E DC81 DC83 DC85 DC88 DC8A DC8D De8F

10 4C A6 95 AC 84 AC 84 20

03 OF 82 CD 59 80 5A 81 D3

BPL JMP LDX STA LDY STY LDA STY JSR

$DC81 $D20F $82 $CD,X $0259 $80 $025A $81 $D6D3

DC92 DC95 DC98 DC9A DC9C DC9E DCAO DCA3 DCA6

20 20 A6 A9 95 A9 20 20 4C

73 99 82 02 C1 00 C8 53 3E

JSR JSR LDX LDA STA LDA JSR JSR JMP

$DE73 $D599 $82 #$02 $C1,X #$00 $D4C8 $E153 $DE3E

DCA9

20 56 D1

JSR $D156

DCAC DCAE DCB1

A6 82 9D 3E 02 A9 88

LDX $82 STA $023E,X LDA #$88

04 3F 83 2B 02 40 2B 02

D2 02 02 D6 DE D5

D4 E1 DE

BNE LDA STA PLA CMP BNE LDA LDA ORA STA

$DC65 $81 $0244,X

DC5E DC60 DC62 DC65 DC66 DC68 DC6A DC6C DC6F DC71

#$04 $DCA9 $83 $022B,Y #$40 $022B,Y

280

following track? sector as end pointer file type rei-file? no secondary address channel number set flag for READ and WRITE record length find buffer for side-sector found? 70, 'no channel' channel number trk for side-sector sec for side-sector transmit parameters to disk controller read block and verify channel number pointer for writing buffer ptr to zero find next record get track and sector numbers get byte from buffer channel number byte in output reg set flag for READ

ABACUS Software

DCB3 DCB5

95 F2 60

Anatomy of the 1541

STA $F2,X RTS

****************************** DCB6 A6 82 LDX $82 DCB8 LDA $A7,X B5 A7 DCBA OA ASL A DCBB A8 TAY DCBC LDA #$02 A9 02 DCBE STA $0099,y 99 99 00 DCC1 B5 AE LDA $AE,X ORA #$80 DCC3 09 80 DCC5 DCC7 DCC8 DCC9 DCCB DCCE DCDO DCD2 DCD4 DCD6 DCD9

95 OA A8 A9 99 A9 95 95 A9 9D 60

AE

02 99 00 00 B5 BB 00 44 02

STA ASL TA-' LDA STA LDA STA STA LDA STA RTS

#$02 $0099,Y #$00 $B5,X $BB,X #$00 $0244,X

DCDA

20 A9 Fl

JSR $FIA9

DCDD DCDF

A9 01 20 DF Dl

LDA #$01 JSR $DIDF

DCE2

20 DO D6

JSR $D6DO

DCE5 DCE8 DCEA DCED DCEE DCEF DCF1

20 A6 AD 48 OA 05 95

JSR LDX LDA PHA ASL ORA STA

7F EC

buffer pointer 10 set bit 7, buffer not allocated

$AE,X A

******************************

B6 DC 82 4A 02

reset pointer channel number buffer number times 2

buffer pointer 10 block number 10 block number hi end pointer construct a new block find free sector in BAM

$DCB6 $82 $024A

open channel and allocate buffer transmit param to disk controller reset pointer channel number file type

A $7F $EC,X

drive number save as flag

281

Anatomy of the 1541

ABACUS Software

OCF3 OCF4 OCF6 OCF8 OCFA DCFC

68 C9 FO A9 95 60

OCFO OCFF 0002

A4 83 B9 2B 02 29 3F

LOY $83 LOA $022B,Y ANO #$3F

0004 0006 0009 OOOC OOOE

09 40 99 2B 02 AD 58 02 95 C7 20 8E 02

ORA #$40

STA LOA STA JSR

$022B,Y $0258 $C7,X $028E

0011 0013 0016 0018

10 4C A6 95

BPL JMP LOX STA

$0016 $020F $82 $CO,X

001A 0010

20 C1 OE 20 1E Fl

JSR $OEC1 JSR $F11E

0020 0022 0025 0027 002A D02C OD2E

A5 80 A5 80 A6 B5 20

80 59 02 81 5A 02 82 CO 03 06

LOA STA LOA STA LOX LOA JSR

$80 $0259 $81 $025A $82 $CO,X $0603

0031 0033 0036 0038

A9 20 A9 20

00 E9 OE 00 80 00

LOA JSR LOA JSR

#$00 $OEE9 #$00 $0080

003B 0030

A9 11 20 80 00

04 05 01 F2

03 OF 02 82 CO

PLA CMP BEQ LOA STA RTS

#$04 $OCFO #$01 $F2,X

LOA #$11 JSR $0080

282

rei-file? yes set WRITE flag secondary address channel # in table clear the top two bits set bit 6 REAO and WRITE flag record length in table find buffer and allocate found? 70, 'no channel' channel number buffer number for side-sector erase buffer find free block in BAM track for 1st side-sector sector for side-sector channel number buffer number transmit param to disk controller buffer ptr to zero zero as track pointer in buffer 17 as end pointer in buffer

ABACUS Software

Anatomy of the 1541

DD40 DD42

A9 00 20 SD DD

LDA #$00 JSR $DDSD

DD45 DD48 DD4B

AD 5S 02 20 SD DD AS SO

LDA $0258 JSR $DD8D LDA $80

DD4D DD50 DD52 DD55 DD57 DD5A

20 A5 20 A9 20 20

JSR LDA JSR LDA JSR JSR

DD5D

A5 SO

LDA $80

DD5F DD62

20 SD DD A5 Sl

JSR $DD8D LDA $81

DD64 DD67 DD6A DD6D DD6F DD72 DD74 DD75 DD77 DD79 DD7B DD7E

20 20 20 A9 20 A6 38 A9 F5 95 20 20

8D 6C 99 02 CS S2

DDS1 DDS4 DDS7 DDSA

20 20 20 4C

SD Sl SD 10 E9 3E

DD DD DE DE

DD DE D5

$DDSD $81 $DD8D #$10 $DEE9 $DE3E

$DD8D $DE6C $D599 #$02 $D4C8 $S2

00 C7 C1 E2 E2 19 DE

JSR JSR JSR LDA JSR LDX SEC LDA SBC STA JSR JSR

5E 99 F4 98

JSR JSR JSR JMP

$DE5E $D599 $EEF4 $DC9S

D4

DE D5 EE DC

#$00 $C7,X $C1,X $E2E2 $DE19

****************************** DDSD DDSE

48 A6 82

PHA LDX $82

283

zero as side-sector number in buffer record length in buffer track number of this block in buffer sector number in buffer 16 buffer ptr to 16 get track and sector numbers track # of the first data block in buffer sector # of the first data block in buffer write block to disk and verify buffer pointer to 2 channel number record length pointer for writing erase buffer write link bytes in buffer write block to disk and verify write BAM and done write byte in side-sector block save byte channel number

Anatomy of the 1541

ABACUS Software

DD90

B5 CD

LDA $CD,X

DD92

4C FD CF

JMP $CFFD

****************************** DD95 BCC $DD9D 90 06 A6 82 LDX $82 DD97 DD99 15 EC ORA $EC,X DD9B DO 06 BNE $DDA3 A6 82 LDX $82 DD9D DD9F 49 FF EOR #$FF AND $EC,X DDA1 35 EC DDA3 STA $EC,X 95 EC DDA5 RTS 60 DDA6 DDA8 DDAA

A6 82 35 EC 60

LDX $82 AND $EC,X RTS

20 93 DF AA

BD 5B 02 29 FO C9 90 60

JSR TAX LDA AND CMP RTS

BD 2B 02

DDBE DDCO DDC2 DDC4 DDC5 DDC7

C9 DO A6 E8 EO 90

FF 08 71 10 FO

channel number clear flag

channel number test flag

$025B,X #$FO #$90

isolate cmd code code for writing?

LDA $022B,X CMP BNE LDX INX CPX BCC

channel number set flag

$DF93

****************************** DDB7 A2 00 LDX #$00 DDB9 STX $71 86 71 DDBB

manipulate flags

verify command code for writing get buffer number

****************************** DDAB DDAE DDAF DDB2 DDB4 DDB6

buffer # of the side-sector write byte in buffer

#$FF $DDCA $71 #$10 $DDB9 284

counter for secondary address get channel number from table file open? increment counter still less than 16?

ABACUS Software

DDC9

60

DDCA DDCC DDCE DDCF DDD2 DDD4 DDD6 DDD9 DDDB DDDD DDDF DDE1 DDE4 DDE6 DDE8 DDEB DDED DDEF DDFO

86 29 A8 B9 29 85 AE

B5 29 C5 DO B9 D5 DO B9 D5 DO 18 60

Anatomy of the 1541

RTS 71 3F EC 01 70 53 E2 01 70 E1 60 D8 DA 66 DD D3

00 02

02 02

STX AND TAY LDA AND STA LDX LDA AND CMP BNE LDA CMP BNE LDA CMP BNE CLC RTS

$71 #$3F $OOEC,Y #$01 $70 $0253 $E2,X #$01 $70 $DDC2 $0260,Y $D8,X $DDC2 $0266,Y $DD,X $DDC2

******************************

DDF1 DDF4 DDF6 DDF9 DDFC

20 9E DF 50 06 20 5E DE 20 99 D5 60

JSR BVC JSR JSR RTS

$DF9E $DDFC $DE5E $D599

20 AS 91 C8 AS 91 4C

2B DE 80 94 81 94 05 E1

JSR LDA STA INY LDA STA JMP

isolate drive #

isolate drive # same drive? no sector # in dir same as file? no pointer same? no

write a block of a rel-file get buffer number no rel-file? write block and verify

$DE2B $80 ($94),Y

write bytes for following track set buffer pointer track number in buffer

$81 ($94),Y $E105

sector number in buffer set rel-flag

******************************

DDFD DEOO DE02 DE04 DE05 DE07 DE09

isolate channel #

285

Anatomy of the 1541

ABACUS Software

****************************** DEOC DEOF DEll DE13 DE14 DE16 DE18

20 2B DE Bl 94 85 80 C8 B1 94 85 81 RTS

JSR LDA STA INY LDA STA

$DE2B (!$:94),Y $80 ($94),Y $81

20 A9 91 C8 A6 B5

2B DE 00 94 82 C1

AA

CA 8A 91 94 60

JSR LDA STA INY LDX LDA TAX DEX TXA STA RTS

following track sector #s buffer pointer following trk #

and sector #

$DE2B #$00 ($94),Y

following track for last block set buffer pointer zero as track number

$82 $Cl,X

channel number pointer in block

****************************** DE19 DE1C DElE DE20 DE21 DE23 DE25 DE26 DE27 DE28 DE2A

get and set get

minus 1 ($94),Y

as pointer in block

****************************** DE2B 20 93 DF JSR $DF93 DE2E OA ASL A DE2F AA TAX DE30 B5 9A LDA $9A,X DE32 STA $95 85 95 DE34 A9 00 LDA #$00 DE36 STA $94 85 94 DE38 AO 00 LDY #$00 DE3A RTS 60

buffer ptr to zero get buffer number times 2

****************************** DE3B 20 EB DO JSR $DOEB DE3E 20 93 DF JSR $DF93 DE41 STA $F9 85 F9 DE43 OA ASL A A8 TAY DE44

get trk and sector get channel number get buffer number save times 2

286

buffer pointer hi buffer pointer 10

ABACUS Software

Anatomy of the 1541

DE45 DE48 DE4A

B9 06 00 85 80 B9 07 00

LDA $0006,Y STA $80 LDA $0007,Y

DE4D DE4F

85 81 60

STA $81 RTS

****************************** DE.50 LDA #$90 A9 90 STA $024D DE52 8D 4D 02 DE55 DO 28 BNE $DE7F

get track and sector #s from disk controller

cmd code for write

#$80 $024D $DE7F #$90 $024D $DE8B

cmd code for read

A9 80 8D 4D 02 DO 1F

LDA #$·80 STA $024D BNE $DE8B

cmd code for read

DE6C DE6E DE71

A9 90 8D 4D 02 DO 02

LDA #$90 STA $024D BNE $DE75

cmd code for write

DE73 DE75 DE78 DE7A

A9 8D A6 B5

LDA STA LDX LDA

cmd code for read

DE7C DE7D DE7F

AA

DE57 DE59 DE5C DE5E DE60 DE63

A9 8D DO A9 8D DO

DE65 DE67 DE6A

DE82 DE85 DE86 DE88 DE8B

80 4D 02 21 90 4D 02 26

80 4D 02 82 CD

10 13 20 DO D6 20 93 DF AA

A5 7F 9D 5B 02 20 15 E1

LDA STA BNE LDA STA BNE

#$80 $024D $82 $CD,X

TAX BPL $DE92 JSR $D6DO JSR TAX LDA STA JSR

$DF93 $7F $025B,X $El15 287

cmd code for write

channel number side-sector buffer number buffer assigned? generate header for disk controller get buffer number drive number buffer number

Anatomy of the 1541

ABACUS Software

DE8E DE91 DE92

20 93 DF AA

4C 06 D5

JSR $DF93 TAX JMP $D506

****************************** DE95 DE97 DE9A DE9D DE9F DEA2 DEA4

A9 20 20 85 20 85 60

00 C8 D4 37 D1 80 37 D1 81

LDA JSR JSR STA JSR STA RTS

#$00 $D4C8 $D137 $80 $D137 $81

****************************** DEA5 48 PHA DEA6 A9 00 LDA #$00 DEA8 STA $6F 85 6F DEAA 85 71 STA $71 DEAC B9 EO FE LDA $FEEO,y DEAF STA $70 85 70 DFB1 BD EO FE LDA $FEEO,X DEB4 85 72 STA $72 DEB6 PLA 68 A8 DEB7 TAY DEB8 88 DEY DEB9 B1 6F LDA ($ 6F) , Y DEBB DEBD DEBE DECO

91 71 88 10 F9 60

STA ($71) , Y DEY BPL $DEB9 RTS

****************************** DEC1 A8 TAY DEC2 B9 EO FE LDA $FEEO,y DEC5 70 STA $70 85 DEC7 A9 00 LDA #$00 DEC9 85 6F STA $6F DECB A8 TAY DECC 91 6F STA ($ 6F) , Y

288

get buffer number write block get following track & sec from buffer buffer ptr to zero get byte save as track get byte as sector copy buffr contents

buffer addr Y, hi buffer addr X, hi

copy contents of buffer Y to buffer X

erase buffer Y buffer number get hi-address lo-address erase buffer

ABACUS Software

DECE DECF DEDl

C8 DO FB 60

Anatomy or the 1541

INY BNE $DECC RTS

****************************** DED2 A9 00 LDA #$00 DED4 20 DC DE JSR $DEDC DED? AO 02 LDY #$02 Bl 94 LDA ($94), Y DED9

DEDB

60

85 94 A6 82 B5 CD AA

BD EO FE 85 95 60

48 20 DC DE 48 8A OA AA

68 95 9A 68 95 99 60

byte 2 contains the side-sector #

$94 $82 $CD,X

set buffer ptr to side-sector pointer 10 channel number buffer number

STA LDX LDA TAX LDA STA RTS

$FEEO,X $95

buffer address hi set

$DEDC

buffer pointer for side-sector ptr in side-sector set buffer pointer

A

buffer number times 2

******************************

DEE9 DEEA DEED DEEE DEEF DEFO DEFl DEF2 DEF4 DEF5 DEF?

buffer ptr to zero

RTS

******************************

DEDC DEDE DEEO DEE2 DEE3 DEE6 DEE8

get side-sector #

PHA JSR PHA TXA ASL TAX PLA STA PLA STA RTS

buffer pointer hi $9A,X buffer pointer 10 $99,X

******************************

DEF8

20 66 DF

JSR $DF66

DEFB

30 OE

BMI $DFOB

289

get side-sector and buffer ptr is side-sector in buffer? no

ABACUS Software

13 82 CD 1B DF 66 DF

Anatomy or the 1541

DEFD DEFF DF01 DF03 DF06

50 A6 B5 20 20

BVC LDX LDA JSR JSR

$DF12 $82 $CD,X $DF1B $DF66

DF09 DFOB

10 07 20 CB E1

BPL $DF12 JSR $E1CB

DFOE DF11 DF12 DF14

2C CE FE 60 A5 D6 20 E9 DE

BIT $FECE RTS LDA $D6 JSR $DEE9

DF17 DF1A

2C CD DE 60

BIT $FECD RTS

ok channel number buffer number read side-sector and check if in buffer yes? get last side-sector set V bit side-sector end ptr set pointer in side-sector clear V bit

****************************** DF1B 85 F9 STA $F9 DF1D A9 80 LDA #$80 DF1F DO 04 BNE $DF25

read side-sector buffer number cmd code for read

****************************** DF21 STA $F9 85 F9 DF23 A9 90 LDA #$90 DF25 48 PHA DF26 LDA $EC,X B5 EC DF28 29 01 AND #$01 DF2A STA $7F 85 7F DF2C 68 PLA DF2D 05 7F ORA $7F

write side-sector buffer number cmd code for write

DF2F DF32 DF34 DF36 DF37 DF39 DF3B DF3D

8D B1 85 C8 B1 85 A5 20

4D 02 94 80 94 81 F9 D3 D6

STA LDA STA INY LDA STA LDA JSR

$024D ($94), Y $80 ($94) ,Y $81 $F9 $D6D3

290

isolate drive # command code plus drive number save track number sector number buffer number transmit param to disk controller

ABACUS Software

OF40 DF42

A6 F9 4C 93 05

Anatomy of the 1541

LOX $F9 JMP $0593

****************************** OF45 OF47 OF49

A6 82 B5 CD 4C EB 04

LOX $82 LOA $CO,X JMP $04EB

****************************** OF4C

A9 78

LDA #$78

OF4E OF51 OF52 OF54

20 5C OF CA 10 F8 AS 72

JSR $OF5C OEX BPL $OF4C LOA $72

OF56 OF57 OF5A

4A 20 5C OF A5 73

LSR A JSR $OF5C LOA $73

OF5C OF50 OF5F OF61 DF63 DF65

18 65 85 90 E6 60

CLC AOC STA BCC INC RTS

70 70 02 71

$70 $70 $OF65

set buffer pointer in side-sector channel number buffer number set buffer pointer calculate # of blks in a rel-file 120 block ptrs per side-sector add to $70/$71 side-sector number next side-sector? # of pointers in last block divided by 2 add to previous sum number of assigned side-sector blocks add

$71

****************************** DF66 DF69

20 D2 DE C5 D5

JSR $OE02 CMP $05

OF6B DF60 OF6F OF71 OF73 OF76

DO A4 B1 FO 2C 60

BNE LOY LOA BEQ BIT RTS

OE 06 94 04 CD FE

buffer number tranmit cmd to disk controller

$OF7B $06 ($94),Y $OF77 $FECO

291

verify side-sector in buffer get side-sector # = number of required block? no ptr in side-sector track number not yet allocated? clear bits

ABACUS Software

Anatomy of the 1541

DF77 DF7A

2C CF FE 60

BIT $FECF RTS

set N-bit

DF7B DF7D DF7F DF81 DF82 DF83 DF85 DF87 DF89 DF8B DF8E

A5 C9 BO OA A8 A9 85 B1 DO 2C 60

LDA CMP BCS ASL TAY LDA STA LDA BNE BIT RTS

side-sector number 6 or greater? yes

DF8F DF92

2C CE FE 60

D5 06 OA 04 94 94 04 DO FE

$D5 #$06 $DF8B A #$04 $94 ($94),Y $DF8F $FEDO

BIT $FECE RTS

****************************** A6 82 LDX $82 DF93 LDA $A7,X DF95 B5 A7 DF97 10 02 BPL $DF9B LDA $AE,X DF99 B5 AE DF9B DF9D

29 BF 60

DF9E DFAO DFA3 DFA5 DFA7 DFA8 DFA9 DFAB DFAE DFBO DFB2

A6 8E B5 10 8A 18 69 8D B5 85 29

DFB4 DFB6

24 70 60

82 57 02 A7 09 07 57 02 AE 70 1F

AND #$BF RTS LDX STX LDA BPL TXA CLC ADC STA LDA STA AND

track number set N and V bits set V bit get buffer number channel number buffer number allocated? buffer number from second table clear V bit

$82 $0257 $A7,X $DFBO

channel number save get buffer number buffer allocated?

#$07 $0257 $AE,X $70 #$lF

increment # by 7 and save buf # from table 2

BIT $70 RTS

292

clear the highest 3 bits

ABACUS Software

Anatomy or the 1541

DFB7 DFB9 DFBB DFBD

AD B5 30 B5

DFBF DFC1

C9 FF 60

CMP #$FF RTS

DFC2 DFC4 DFC6 DFC8 DFCA DFCC DFCD DFCF

A6 09 B4 10 95 60 95 60

LDX ORA LDY BPL STA RTS STA RTS

82 A7 02 AE

82 80 A7 03 A7 AE

LDX LDA BMI LDA

$82 $A7,X $DFBF $AE,X

$82 #$80 $A7,X $DFCD $A7,X $AE,X

****************************** 20 9D DD 80 A6 DD 41 82 B5 02 BB 82 C1 2E E8 D4 82 Cl

LDA JSR LDA JSR BNE LDX INC BNE INC LDX LDA BEQ JSR LDX CMP

channel number buffer number buffer free? buffer number from table 2 free?

#$20 $DD9D #$80 $DDA6 $E01D $82 $B5, X $DFE4 $BB,X $82 $C1,X $E018 $D4E8 $82 $C1,X

DFDO DFD2 DFD5 DFD7 DFDA DFDC DFDE DFEO DFE2 DFE4 DFE6 DFE8 DFEA DFED DFEF

A9 20 A9 20 DO A6 F6 DO F6 A6 B5 FO 20 A6 D5

DFF1 DFF3

90 03 20 3C EO

BCC $DFF6 JSR $E03C

DFF6 DFF8

A6 82 B5 Cl

LDX $82 LDA $C1,X 293

get next record in rel-file clear bit 5 test bit 7 set? channel number increment record # record number hi channel number write-pointer zero? set buffer pointer channel number buffer ptr less than write ptr? yes write block, read next block channel number write pointer

ABACUS Software

Anatomy of the 1541

DFFA

20 C8 D4

JSR $D4C8

DFFD DFFF E001 E003 E006

A1 85 A9 20 20

LDA STA LDA JSR JSFz

E009 EOOA

48 90 28

PHA BCC $E034

EOOC EOOE E011 E013 E014 E016 E018 E01A E01D E020 E022 E025 E027 E029

A9 20 DO 68 C9 FO A9 20 20 B5 99 A9 85 60

00 F6 D4 21

LDA JSR BNE PLA CMP BEQ LDA JSR JSR LDA STA LDA STA RTS

#$00 $D4F6 $E034

E02A E02D E02F E031 E033

20 A6 A9 95 60

35 EO 82 00 C1

JSR LDX LDA STA RTS

$E035 $82 #$00 $e1, X

E034 E035 E037 E039

68 A6 82 95 C1 4C 6E E1

99 85 20 9D DD 04 E3

02 12. 80 97 DD 2F D1 99 44 02 OD 85

($99) ,X $85 #$20 $DD9D $E304

#$02 $E02A #$80 $DD97 $D12F $99,X $0244,Y #$OD $85

PLA LDX $82 STA $C1, X JMP $E16E

****************************** E03C

20 D3 D1

JSR $D1D3

294

set buffer pointer = write ptr byte from buffer put in output reg clear bit 5 add record length to write ptr and save not yet in last block? get track number does block exist? pointer = 2 yes set bit 7 get byte from buffr buffer pointer as end pointer CR in output register

channel number write-ptr to zero

channel number set write pointer write block and read next block get drive number

ABACUS Software

Anatomy of the 1541

E03F

20 95 DE

JSR $DE95

E042 E045 E047 E04A E04D E04F E052 E055 E057 E05A

20 50 20 20 A9 20 20 DO 20 4C

9E 16 5E 1E 02 C8 AB 24 57 99

JSR BVC JSR JSR LDA JSR JSR BNE JSR JMP

$DF9E $E05D $DE5E $CF1E #$02 $D4C8 $DDAB $E078 $DE57 $D599

E05D E060 E063 E065 E068 E06B

20 20 DO 20 20 20

1E AB 06 57 99 95

JSR JSR BNE JSR JSR JSR

$CF1E $DDAB $E068 $DE57 $D599 $DE95

E06E E070 E072 E075 E078 E07B

A5 FO 20 20 20 60

80 09 1E CF 57 DE 1E CF

LDA BEQ JSR JSR JSR RTS

$80 $E07B $CF1E $DE57 $CF1E

DF DE CF D4 DD DE D5 CF DD DE D5 DE

******************************

E07C E07F E082 E083 E084 E086 E088 E08A E08B E08D E08F E092

20 05 E1 20 93 DF OA AA

A5 81 B4 C8 DO A4 B9 FO

85 99 99 09 82 C1 00 OA

JSR JSR ASL TAX LDA STA LDY INY BNE LDY LDA BEQ

$E105 $DF93 A $85 ($99,X) $99,X $E096 $82 $00C1,Y $E09E

295

get track and sector numbers get buffer number no rel-file? write block change buffers buffer pointer to 2 cmd code for write? no read block and verify change buffers cmd code for write? no read block and verify get track and sector numbers track no following track? change buffers read block change buffers write a byte in a record get buffer number times 2 data byte write in buffer buffer pointer increment not equal zero? channel number write-pointer equal zero?

ABACUS Software

Anatomy of the 1541

E094 E096 E097 E099

AO 02 98 AS 82 D9 C1 00

LDY #$02 TYA LDY $82 CMP $00C1,Y

E09C E09E EOAO

DO 05 A9 20 4C 97 DD

BNE $E043 LDA #$20 JMP $DD97

EOA3 EOA5 EOA7

F6 99 DO 03 20 3C EO

INC $99,X BNE $EOAA JSR $E03C

EOAA

60

RTS

****************************** EOAB EOAD EOBO EOB2 EOB4 EOB7 EOB9 EOBB

A9 20 DO AS 20 AS

EOBC EOBE EOC1 EOC3

A9 20 FO A9

EOC5 EOC8

8D 6C 02 20 F3 EO

STA $026C JSR $EOF3

EOCB EOCE EOD1 EOD3

20 AD FO 4C

JSR LDA BEQ JMP

EOD6

4C BC E6

Fa

AO A6 DD 27 85 7C EO F8 00

LDA JSR BNE LDA JSR LDA BEQ RTS

#$AO $DDA6 $EOD9 $85 $E07C $F8 $EOC8

20 A6 DD 05 51

LDA JSR BEQ LDA

#$20 $DDA6 $EOC8 #$51

60

53 E1 6C 02 03 C8 C1

$E153 $026C $EOD6 $C1C8

JMP $E6BC

296

buffer pointer to 2 channel number buffer pointer write pointer? no set bit 5 inc buffer pointer not zero? else write block, read next one write byte in rel-file test bits 6 & 7 set? data byte write in record end? yes

test bit 5 not set 51, 'overflow in record' set error flag fill remainder with zeros error flag set? no set error message error-free execution

ABACUS Software

Anatomy of the 1541

EOD9 EODB EODD EODF EOEl

29 DO AS FO 60

80 05 F8 DB

AND BNE LDA BEQ RTS

#$80 $EOE2 $F8 $EOBC

bit 7 set? yes

EOE2 EOE4 EOE5 EOE8 EOE9 EOEB EOED EOFO

AS 48 20 68 85 A9 20 4C

85

LDA PHA JSR PLA STA LDA JSR JMP

$85

data byte

$E31C

expand side-sector

$85 #$80 $DD9D $EOB2

clear bit 7 write byte in file

lC E3 85 80 9D DD B2 EO

****************************** LDA #$20 EOF3 A9 20 20 A6 DD JSR $DDA6 EOF5 BNE $E104 DO OA EOF8 LDA #$00 EOFA A9 00 STA $85 EOFC 85 85 $E07C JSR EOFE 20 7C EO $EOF3 JMP E10l 4C F3 EO

E104

end?

fill record with Os test bit 5 set? zero as data byte write in record until record full

RTS

60

******************************

write buffer number in table

E105 E107 E10A E10D E10F El12 El14

A9 20 20 09 AE 95 60

40 97 DD 9E DF 40 57 02 A7

LDA JSR JSR ORA LDX STA RTS

#$40 $DD97 $DF9E #$40 $0257 $A7,X

set bit 6 get buffer number set bit 6 channel number + 7 write in table

EllS El18 EllA EllD EllF

20 29 AE 95 60

9E DF BF 57 02 A7

JSR AND LDX STA RTS

$DF9E #$BF $0257 $A7,X

get buffer number clear bit 6 channel number + 7 write in table

297

ABACUS Software

Anatomy of the 1541

****************************** E120 E122 E125 E127

A9 20 DO 20

80 A6 DD 37 2F D1

LDA JSR BNE JSR

#$80 $DDA6 $E15E $D12F

E12A E12C E12F E131 E133 E135

B5 D9 FO F6 DO 20

99 44 02 22 99 06 3C EO

LDA CMP BEQ INC BNE JSR

$99,x $0244,Y $E135 $99,X $E13B $E03C

E138 E13B E13D E140 E142

20 A1 99 A9 99

2F D1 99 3E 02 89 F2 00

JSR LDA STA LDA STA

$D12F ($99,X) $023E,Y #$89 $00F2,Y

E145 E147 E14A E14C

B5 99 D9 44 02 FO 01 60

LDA $99,Y CMP $0244,Y BEQ $E14D RTS

E14D E14F E152

A9 81 99 F2 00 60

LDA #$81 STA $00F2,Y RTS

E153 E156

20 DO DF 20 2F D1

JSR $DFDO JSR $D12F

E159 E15B

A5 85 4C 3D E1

LDA $85 JMP $E13D

E15E E160 E162 E165 E167

A6 A9 9D A9 95

LDX LDA STA LDA STA

82 OD 3E 02 81 F2

$82 #$OD $023E,X #$81 $F2,X

298

get byte from reI-file test bit 7 set? get byte from buffer buffer pointer compare to end ptr equal? inc buffer ptr not zero? write block, read next one get byte from buf in output register set READ and WRITE flag buffer pointer compare to end ptr same?

set flag for end find next record get buffer and channel numbers data byte into output reg channel number CR into output reg set flag for end

ABACUS Software

Anatomy of the 1541

E169 E16B

A9 50 20 C8 CI

LDA #$50 JSR $C1C8

E16E E170 E172 E174 E176 E178 E17A E17C E17E E180 E182 E185 E187

A6 B5 85 C6 C9 DO A9 85 B5 85 20 A6 C5

82 C1 87 87 02 04 FF 87 C7 88 E8 D4 82 87

LDX LDA STA DEC CMP BNE LDA STA LDA STA JSR LDX CMP

$82 $C1, X $87 $87 #$02 $E17E #$FF $87 $C7,X $88 $D4E8 $82 $87

E189 E18B E18D E190 E193 E195 E197 E19A

90 FO 20 20 90 A6 9D 4C

19 17 1E B2 08 82 44 1E

BCC BEQ JSR JSR BCC LDX STA JMP

$E1A4 $E1A4 $CF1E $E1B2 $E19D $82 $0244,X $CF1E

E19D E1AO E1A2 E1A4 EIA7 EIA9 E1AC E1AE E1B1

20 A9 85 20 BO 20 A6 9D 60

1E FF 87 B2 03 E8 82 44

JSR LDA STA JSR BCS JSR LDX STA RTS

$CFIE #$FF $87 $EIB2 $E1AC $D4E8 $82 $0244,X

EIB2 EIB5 E1B7 E1B9

20 A4 B1 DO

2B DE 87 94 OD

JSR LDY LDA BNE

$DE2B $87 ($94),Y $EIC8

CF E1 02 CF CF E1 D4 02

299

50, 'record not present' channel number write-pointer save equal 2? no record length set buffer pointer channel number buffer pointer > write pointer? no change buffers channel number change buffers change :buffers

set buffer pointer channel number end pointer buffer ptr to zero byte from buffer not zero?

ABACUS Software

EIBB EIBC EIBE EICO EIC2 EIC4 EIC6 EIC7

88 CO 90 C6 DO C6 18 60

EIC8 EIC9 EICA

98 38 60

02 04 88 F3 88

Anatomy of the 1541

DEY CPY BCC DEC BNE DEC CLC RTS

#$02 $EIC4 $88 $EIB7 $88

TYA SEC RTS

****************************** EICB

20 D2 DE

EICE EIDO EID2 EID4 EID6

85 A9 85 AO DO

EID8 EID9 EIDA EIDC

88 88 30 26 Bl 94

DEY DEY BMI $E202 LDA ($94), Y

EIDE EIEO EIEl EIE2

FO F8 98 4A C5 D5

BEQ $EID8 TYA LSR A CMP $D5

EIE4 EIE6 EIE8 EIEA EIEC EIEF EIFl EIF3

FO 85 ' A6 BS 20 AO 84 Bl

D5 04 94 OA 04

09 D5 82 CD IB DF 00 94 94

JSR $DED2 STA LDA STA LDY BNE

BEQ STA LDX LDA JSR LDY STY LDA

$D5 #$04 $94 #$OA $EIDC

$EIEF $DS $82 $CD,X $DFIB #$00 $94 ($94),Y

300

get last side-sector get number of the side-sector save ptr to side-sectors

track # of the previous block not allocated? divide by 2 = number of the current block? yes else save all #s channel number buffer number read block buffer pointer track number

Anatomy of the 1541

ABACUS Software

OB

EIF5 EIF7 EIF8 EIFA EIFB EIFC EIFE EIFF

DO C8 Bl A8 88 84 98 4C

E202 E204

A9 67 20 45 E6

94 D6 E9 DE

BNE INY LDA TAY DEY STY TYA JMP

$E202

anothel. block?

($94),Y

sector #

$D6

save end pointer

$DEE9

set buffer pointer

#$67 JSR $E645

**********~*******************

C1

JSR LDA STA JSR BCC LDA JSR

$C2B3 $0201 $83 $DOEB $E219 #$70 $C1C8

9D DD 25 D1 05 64 C8 Cl

LDA JSR JSR BEQ LDA JSR

#$AO $DD9D $D125 $E228 #$ 64 $CIC8

EC 01 7F 02 02 B5 03 02 BB B2 89 F2 04 02

LDA AND STA LDA STA LDA STA LDA LDA STA LDA

$EC,X #$01 $7F $0202 $B5, X $0203 $BB,X $82 #$89 $F2,X $0204

E207 E20A E20D E20F E212 E214 E216

20 AD 85 20 90 A9 20

B3 01 83 EB 05 70 C8

E219 E21B E21E E221 E223 E22S

A9 20 20 FO A9 20

AO

E228 E22A E22C E22E E231 E233 E236 E238 E23A E23C E23E

BS 29 85 AD 95 AD 95 A6 A9 95 AD

C2 02 DO

301

=

end ptr

67, 'illegal track or sector' p-command, 'Record' verify lines secondary address find channel number found? 70,

'no block'

clear bits 6 & 7 check if !REL'-file yes 64, 'file type mismatch'

drive number record number 10 record number hi channel number READ and WRITE flag byte-pointer

ABACUS Software

10

Anatomy of the 1541

BEQ SEC SBC BEQ CMP

$E253

E241 E243 E244 E246 E248

FO 38 E9 FO D5

E24A E24C E24E

90 07 A9 51 8D 6C 02

BCC $E253 LDA #$51 STA $026C

E251 E253 E255

A9 00 85 D4 20 OE CE

LDA #$00 STA $D4 JSR $CEOE

E258

20 F8 DE

JSR $DEF8

E25B E25D E25F E262

50 A9 20 4C

08 80 97 DD 5E El

BVC LDA JSR JMP

$E265 #$80 $DD97 $E15E

E265 E268 E26A E26D E26F

20 A9 20 FO 4C

75 E2 80 A6 DD 03 5E El

JSR LDA JSR BEQ JMP

$E275 #$80 $DDA6 $E272 $E15E

E272

4C 94 Cl

JMP $C194

E275 E278 E27A E27D E27F E281 E282 E284 E286

20 A5 20 A6 B5 38 E5 BO 4C

JSR LDA JSR LDX LDA SEC SBC BCS JMP

01 OB C7

9C E2 D7 C8 D4 82 C7 D4 03 02 E2

#$01 $E253 $C7,X

$E29C $D7 $D4C8 $82 $C7,X $D4 $E289 $E202

302

zero?

compare with record length 51, 'overflow in record' calculate pointer in reI-file and read corresponding side-sector does block exist? set bit 7 and 50, 'record not present'

test bit 7 not set 50, 'record not present' done pointer in reI-file set buffer pointer channel number record length minus position positive? 67, 'illegal track or sector'

ABACUS Software

Anatomy or the 1541

E289 E28A

18 65 D7

E28C E28E E290 E291 E294

90 69 38 20 4C

E297 E299

A9 51 20 C8 Cl

LDA #$51 JSR $CIC8

E29C E29E E2AO E2A2 E2A4 E2A7 E2A9

AS 85 AS 85 20 DO 60

94 89 95 8A DO E2 01

LDA STA LDA STA JSR BNE RTS

$94 $89 $95 $8A $E2DO $E2AA

E2AA E2AD E2BO E2B2 E2B4

20 20 AS FO 20

Fl DD OC DE 80 OE D3 E2

JSR JSR LDA BEQ JSR

$DDFI $DEOC $80 $E2C2 $E2D3

E2B7 E2B9 E2BC E2BF E2C2 E2C4 E2C6 E2C8 E2C9

DO 20 4C 20 AO B1 85 C8 B1

06 IE CF DA D2 DA D2 00 89 80

BNE JSR JMP JSR LDY LDA STA INY LDA

$E2BF $CF1E $D2DA $D2DA #$00 ($89),Y $80

E2CB E2CD

85 81 4C AF DO

STA $81 JMP $DOAF

E2DO

20 3E DE

JSR $DE3E

03 01 09 EO 38 El

89

CLC ADC $D7 BCC ADC SEC JSR JMP

$E291 #$01

add pointer in data block no overflow plus 2

$E009 $E138

set pointer get byte from buf

($89),Y

303

51, 'overflow in record' buffer pointer 10 buffer pointer hi compare trk and sec not equal?

track no block following? compare track and sector numbers not equal? change buffers

track and sector of the next block read block

Anatomy of the 1541

ABACUS Software

E2D3 E2D5 E2D7 E2D9 E2DB E2DC E2DD E2DF E2E1

AO B1 C5 FO 60 C8 B1 C5 60

00 89 80 01 89 81

LDY LDA CIvIP BEQ RTS INY LDA CMP RTS

#$00 ($89),Y $80 $E2DC

track number compa.ce

($89),Y $81

sector number compare

***************k************** E2E2 E2E5 E2E7 E2E9 E2EB E2EC E2EE

20 AO A9 91 C8 DO 20

E2F1 E2F3 E2F4 E2F6

95 C1 A8 A9 FF 91 94

STA $C1,X TAY LDA #$FF STA ($94), Y

E2F8

20 04 E3

JSR $E304

90 F4

BCC BNE LDA STA RTS

E2FB E2FD E2FF E301 E303

2B DE 02 00 94 FB 04 E3

CO 04 A9 00 95 C1 60

JSR LDY LDA STA INY BNE JSR

$DE2B #$02 #$00 ($94), Y $E2E9 $E304

$E2F1 $E303 #$00 $C1,X

****************************** E304 E306 E308 E309 E30B E30C

A6 B5 38 FO 18 75

82 C1 OD C7

LDX LDA SEC BEQ CLC ADC

divide data blocks into records set buffer pointer erase buffer set pointer to next record

$FF as 1st character in record set pointer to next record done in this block? block full? write-pointer to 0

$82 $C1,X

set pointer to next record channel number write-pointer

$E318

equal zero?

$C7,X

add record length

304

ABACUS Software

E30E E310 E312 E314 E317

90 DO A9 2C 60

OB 06 02 CC FE

E318 E31A E31B

69 01 38 60

Anatomy of the 1541

BCC BNE LDA BIT RTS

$E31B $E318 #$02 $FECC

ADC #$01 SEC RTS

****************************** JSR $0103 20 03 01 E31C JSR $E1CB E31F 20 CB E1 E322 E325 E328 E32A E32C E32E E330 E332 E334 E336 E338

20 20 A5 85 A5 85 A9 85 A9 85 20

9C E2 7B CF 06 87 05 86 00 88 00 04 OE CE

JSR JSR LOA STA LOA STA LOA STA LOA STA JSR

$E29C $CF7B $06 $87 $05 $86 #$00 $88 #$00 $04 $CEOE

E33B E33E E340 E342 E343 E344 E345

20 A4 B6 CA 8A 18 65

40 EF 82 C7

JSR LDY LOX OEX TXA CLC ADC

$EF40 $82 $C7,Y

E347 E349 E34B

90 OC E6 06 E6 06

BCC $E355 INC $06 INC $06

E340 E34F

DO 06

BNE $E355 INC $D5

07

E6 05

smaller than 2561 equal 256?

add two

expand side-sector get drive number get last side-sector

side-sector number

calculate sidesector # and ptr # of free blocks channel number record length

plus pointer in data block

$07

305

increment ptr to end by 2 increment side-sector #

ABACUS Software

E351 E353 E355 E357 E358 E35A

A9 85 A5 18 69 20

E35D E35F E361 E363 E365

10 D6 87

Anatomy of the 1541

#$10 #D6 $87

02 E9 DE

LDA STA LDA CLC ADC JSR

A5 C9 90 A9 20

D5 06 05 52 C8 Cl

LDA CMP BCC LDA JSR

$D5 #$06 $E368 #$52 $CIC8

E368 E36A E36B E36D E36F E371 E372 E374 E376

A5 38 E5 BO E9 18 85 A5 E5

D6

LDA SEC SBC BCS SBC CLC STA LDA SBC

$D6

£378 E37A E37C

85 73 A2 00 86 70

STA $73 LDX #$00 STX $70

E37E E380 E381

86 71 AA

20 51 DF

STX $71 TAX JSR $DF51

E384 E386 E388 E38A E38B E38D E38F E392

A5 DO A6 CA DO E6 CD 90

LDA BNE LDX DEX BNE INC CMP BCC

87 03 OF 72 D5 86

71 07 70 02 88 73 02 09

#$02 $DEE9

$87 $E372 #$OF $72 $D5 $86

set pointer to 16

set buffer ptr for side-sector side-sector number less than 6? 52, 'file too large' end pointer minus last end ptr minus 16 side-sector number minus last side-sector number save erase sum for calculation calculate # of blocks in rei-file

$71 $E38F $70 $E38F $88 $0273 $E39D

306

block # of rel·-file greater than free blocks on disk?

Anatomy of the 1541

ABACUS Software

E394

00 CO

BNE $E363

E396 E399 E39B

AO 72 02 C5 70 90 C6

LOA $0272 CMP $70 BCC $E363

E390 E39F

A9 01 20 F6 04

LOA #$01 JSR $04F6

E3A2 E3A3 E3A5 E3A7 E3A9

18 69 A6 95 20

CLC AOC LOX STA JSR

E3AC E3AF E3B1

20 FO 00 A5 88 00 15

JSR $OOFO LOA $88 BNE $E3C8

E3B3 E3B6 E3B9

20 5E OE 20 IE CF 20 00 06

JSR $OE5E JSR $CFIE JSR $0600

E3BC

20 IE Fl

JSR $FIIE

E3BF

20 FO 00

JSR $OOFO

E3C2 E3C5

20 E2 E2 4C 04 E3

JSR $E2E2 JMP $E304

E3C8 E3CB

20 1E CF 20 00 06

JSR $CF1E JSR $0600

E3CE E301

20 E2 E2 20 19 DE

JSR $E2E2 JSR $DE19

E3D4 E3D7 E3DA E3DC E3DD

20 20 A5 48 A4

01 82 C1 IE Fl

5E DE OC DE 80 81

JSR JSR LDA PHA LDA

#$01 $82 $Cl,X $FIIE

52, 'file too large' 52, 'file too large' get byte from buffer plus 1 as write pointer find free block in BAM trk and sec in buf only one block needed? write block change buffers transmit param to disk controller find free block in BAM track and sector in buffer erase buffer

$DE5E $DEOC $80

change buffers transmit param to disk controller erase buffer zero byte and end ptr in buffer write block get trk and sector track

$81

and sector

307

ABACUS Software

Anatomy of the 1541

E3DF E3EO

48 20 3E DE

PHA JSR $DE3E

E3E3 E3E5 E3E6 E3E8 E3E9

AS 81 48 AS 80 48 20 45 DF

LDA $81 PHA LDA $80 PHA JSR $DF45

E3EC E3ED E3EF E3F2 E3F4 E3F7

AA

DO 20 A9 20 E6

TAX BNE JSR LDA JSR INC

E3F9 E3FA E3FD E3FE E401 E402 E404 E405 E407 E409 E40B E40D E40F

68 20 68 20 68 85 68 85 FO AS C5 DO 20

E412 E414 E416 E418

C5 90 FO 20

E41B E41C E41E E421 E423 E424

48 A9 20 A9 A8 91

OA 4E E4 10 E9 DE 86

80 OF 86 D5 A7 45 DF

PLA JSR PLA JSR PLA STA PLA STA BEQ LDA CMP BNE JSR

D6 AO BO 45 DF

CMP BCC BEQ JSR

8D DD 8D DD 81

00 DC DE 00 94

PHA LDA JSR LDA TAY STA

save get trk and sector from disk cont. save sector and track set buffer ptr for side-sector

$E3F9 $E44E #$10 $DEE9 $86

pointer not zero? write side-sector

$DD8D

track in side-sect

$DD8D

sector in side-sec

$81

get sector

$80 $E418 $86 $D5 $E3B6 $DF45

and track back no more blocks? side-sector number changed? yes set buffer ptr in side-sector end pointer smaller? same set buffer ptr in side-sector

$D6 $E3B6 $E3C8 $DF45

buffer ptr to 16 increment side-sector number

#$00 $DEDC #$00

buffer ptr to zero

($94),Y

o

308

as track number

ABACUS Software

E426 E427 E428 E429 E42B E42D E430 E433 E436

C8 68 38 E9 91 20 20 20 20

01 94 6C 99 F4 OE

E439 E43C E43F E441 E444 E446 E449 E44B

Anatomy or the 1541

DE D5 EE CE

INY PLA SEC SBC STA JSR JSR JSR JSR

#$01 ($94), Y $DE6C $D599 $EEF4 $CEOE

20 20 70 4C

1E CF F8 DE 03 75 E2

JSR .JSR BVS JMP

$CF1E $OEF8 $E444 $E275

A9 20 A9 20

80 97 DD 50 C8 C1

LDA JSR LDA JSR

#$80 $D097 #$50 $C1C8

end pointer

$DEC1 $82 $CD,X

erase buffer channel number buffer number

#$10

16 bytes of the side-sector copy in buffer

20 1E F1

JSR $F11E

E451 E454 E457 E45A E45B E45E E460 E462 E463 E464 E465

20 20 20 48 20 A6 B5 A8 68

A9 10

JSR JSR JSR PHA JSR LOX LDA TAY PLA TAX LDA

E467 E46A E46C

20 A5 DE A9 00 20 DC OE

JSR $OEA5 LOA #$00 JSR $OEDC

AA

50, 'record not present'

$CF1E $DDF1 $OF93

E44E

C1 DE 82 CD

set bit 7

write side-sector and allocate new find free block in BAM change buffers write block get buffer number

******************************

1E CF F1 DD 93 OF

minus one as sector write block and verify update BAM update ptr for rel-file change buffers right side-sector? no

309

buffer ptr to 0, old side-sector

ABACUS Software

02 94

Anatomy of the 1541

E46F E471 E473 E474 E476

AO B1 48 A9 20

E479 E47A E47B

68 18 69 01

PLA CLC ADC #$01

E47D E47F E480 E482

91 94 OA 69 04 85 89

STA ASL ADC STA

E484 E485 E486 E488

A8 38 E9 02 85 8A

TAY SEC SBC #$02 STA $8A

E48A E48C E48E E490 E491 E493 E495 E497 E499 E49A E49C E49D E49F E4A1 E4A3 E4A6 E4A9 E4AC E4AE

A5 85 91 C8 A5 85 91 AO 98 91 C8 A9 91 A9 20 20 20 A6 B5

LDA STA STA INY LDA STA STA LDY TYA STA INY LDA STA LDA JSR JSR JSR LDX LDA

E4BO

48

00 C8 D4

80 87 94 81 88 94 00 94 11 94 10 C8 D4 50 DE 99 D5 82 CD

LDY LDA PHA LDA JSR

#$02 ($94),Y #$00 $D4C8

($94),Y A #$04 $89-

$80 $87 ($94),Y

side-sector number buffer ptr to 0, new side-sector increment sidesector number and in buffer times 2 plus 4 equals ptr to track/sector minus 2 equals pointer to old side-sector track in buffer

$81 $88 ($94),Y #$00

sector

($94) ,Y

zero in buffer

#$11 ($94),Y #$10 $D4C8 $DE50 $D599 $82 $CD,X

17 # of bytes in block 16 buffer ptr to 16 write block and verify channel number buffer number of the side-sector

PHA 310

in buffer

Anatomy of the 1541

ABACUS Software

$DF9E $82 $CD,X

get buffer number channel number write in table

$0257 $A7,X #$00

channel number + 7 in table

$D4C8

buffer ptr to zero

#$00 $80 ($94), Y

track in buffer

81 94 DE E4

JSR LDX STA PLA LDX STA LDA JSR LDY LDA STA INY LDA STA JMP

$81 ($94) , Y $E4DE

sector in buffer

20 A6 20 A9 20 C6 C6

93 DF 82 IB DF 00 C8 D4 8A 8A

JSR LDX JSR LDA JSR DEC DEC

$DF93 $82 $DFIB #$00

get buffer number channel number read block

$D4C8

buffer ptr to zero

E4E2 E4E4 E4E6 E4E8 E4E9 E4EB E4ED E4FO E4F3

A4 AS 91 C8 AS 91 20 20 A4

89 87 94

LDY LDA STA INY LDA STA JSR JSR LDY

$89 $87 ($94),Y

track number in buffer

$88 ($94), Y $DE5E $D599 $8A

sector number in buffer write block and verify counter for side-sector blocks

E4F5 E4F7

CO 03 BO D8

CPY #$03 BCS $E4Dl

E4F9

4C IE CF

JMP $CFIE

E4B1 E4B4 E4B6 E4B8 E4B9 E4BC E4BE E4CO E4C3 E4C5 E4C7 E4C9 E4CA E4CC E4CE

20 A6 95 68 AE 95 A9 20 AO AS 91 C8 AS 91 4C

9E DF 82 CD

E4Dl E4D4 E4D6 E4D9 E4DB EFDE E4EO

57 02 A7 00 C8 D4 00 80 94

88 94 5E DE 99 D5 8A

$8A $8A

counter for side-sector blocks

311

greater than or equal to 3? change buffers

ABACUS Software

Anatomy of the 1541

******************************

table of error messages E4FC 00 00 , oK' E4FO AO 4F CB E500 20 21 22 23 24 27 error numbers of 'read error' E506 02 45 41 44 'Read' E50A 89 pointer to 'error' E50B 52 52 E50C 83 pointer to 'file' , too largE' E500 20 54 4F 4F 20 AC 4A 52 47 C5 E517 50 50 E518 8B 06 pointer to 'record' and 'not' / E51A 20 50 52 45 53 45 4E 04 presenT' E522 51 51 E523 CF 56 45 52 46 4C 4F 5 -, 20 'Overflow in' E52E 8B pointer to 'record' E52F 25 28 error numbers of 'write error' E531 8A 89 pointer to 'write' and 'error I E533 26 26 E534 8A pointer to "drite' E535 20 50 52 4E' 54 45 43 54 20 4F CE I protect oN' E540 29 29 E541 88 pointer to 'disk' I E542 20 49 85 id' E545 85 ptr to I mismatch' E546 30 31 32 33 34 error numbers for 'syntax error' E54B 03 59 4E 54 41 58 'Syntax' , error' E551 89 pointer to E552 60 60 E553 8A 03 84 ptrs to 'write' f 'file' & 'open' E556 63 63 E557 83 pointer to 'file' , existS' E558 20 45 58 49 53 54 D3 E55F 64 64 E560 83 pointer to 'file' 312

Anatomy of the 1541

ABACUS Software

E561 E566 E567 E568 E570

20 54 59 50 45 85 65 CE 4F 20 42 4C 4F 43 CB 66 67

E572 E57A E582 E589 E58A

C9 54 20 61 83

4C 4C 52 41 53 45 06 84

E58D 39 62 E590 83 06 87 E593 01 E594 83 E594 53 20 53 E59F E5AO E5AA E5AB E5AE E5AF E5BO E5B1 E5B6 E5B7 E5BF E5C4 E5C5 E5CA E5CB E5D5 E5D6 E5DB E5DC E5E1 E5E2

, type'

ptr to 'mismatch' 65 'No block' 'illegal track or sector' , 'Illegal 45 47 41 4C 20 'track or' 43 4B 20 4F 52 'sectoR' 43 54 4F D2 61 pointer to ' file' , 'not' & 'open' error #s for 'file not found' ptrs to 'file', 'not' & 'found' 01 pointer to 'file' 43 52 41 54 43 48 45 C4 's scratcheD' 70 43 48 41 4E 4E 45 CC 'No channeL' 71 'Dir' pointer to 'error' 72 pointer to 'disk' , fulL' 4C CC 73 , 'Cbm dos 20 44 4F 53 20 36 20 31 35 34 B1 'v2.6 1541' 74 'Drive' 56 45 pointer to 'not' , readY' 41 44 D9

70 CE 4F 20 71 C4 49 52 89 72 88 20 46 55 73 C3 42 4D 56 32 2E 74 C4 42 49 06 20 52 45 09 C5 52 52 4F D2 OA D7 52 49 54 C5 03 C6 49 4C C5

'ErroR' 'WritE' 'FilE'

313

Anatomy of the 1541

ABACUS Software

E5E6 E6E7 E5EB E5EC E5F4 E5F5 E5F8 E5F9 E5FE E5FF E603 E604

04 CF 05 CD 06 CE 07 C6 08 C4 OB D2

50 45 CE

'OpeN'

49 53 4D 41 54 43 C8

'MismatcH'

4F D4

'NoT'

4F 55 4E C4

'FounD'

49 53 CB

'DisK'

45 43 4F 52 C4

'RecorD'

******************************

B5 85 B5 85 68 29 FO

06 80 07 81 OF 08

PHA STX TXA ASL TAX LDA STA LDA STA PLA AND BEQ

E61D E61F E621 E623

C9 DO A9 DO

OF 06 74 08

CMP BNE LDA BNE

E625 E627 E629 E62A E62B E62C E62D E62E

A9 06 09 20

E60A E60B E60D E60E E60F E610 E612 E614 E616 E618 E619 E61B

48 86 F9 8A OA AA

AA

CA CA 8A 48 AD 2A 02

$F9 A

prepare error # and message save error code drive number times 2 as pointer

$06, X $80 $07,X $81 #$OF $E625 #$OF $E627 #$74 $E62D

LDA #$06 ORA #$20 TAX DEX DEX TXA PHA LDA $022A 314

get track and sector numbers get error code back isolate bits 0-3 $10, then 24, 'read error' 15? 74, 'drive not ready' 6 add $20 subtract two save error number # of the disk cmd

Anatomy of the 1541

ABACUS Software

C9 DO A9 8D 68 20

E63E E641

20 42 DO 4C 48 E6

JSR $D042 JMP $E648

E644 E645 E648 E64B E64D E650 E653

68 20 20 A9 8D 20 20

PLA JSR JSR LDA STA JSR JSR

E656 E658

A9 00 85 A3

LDA #$00 STA $A3

E65A E65C

A2 45 9A

LDX #$45 TXS

E65D E65F E661 E663 E665 E667 E668 E66A E66C E66E E670 E672

A5 29 85 C9 FO 78 AS DO AS DO A6 BD

84 OF 83 OF 31

E675 E677 E679 E67B

C9 FO 29 85

00 OF FF 2A 02 C7 E6

C7 BD 00 F9 2C DA

E6 C1 02 Cl D4

CMP BNE LDA STA PLA JSR

#$00 $E644 #$FF $022A

E631 E633 E635 E637 E63A E63B

$E6C7

$E6C7 $C1BD #$00 $02F9 $CI2C $D4DA

$84 #$OF $83 #$OF $E698

79 lC 7A 10 83 2B 02

LDA AND STA CMP BEQ SEI LDA BNE LDA BNE LDX LDA

FF IF OF 82

CMP BEQ AND STA

#$FF $E698 #$OF $82

$79 $E688 $7A $E680 $83 $022B,X

315

VALIDATE? no get error # back generate error message load BAM set error message set error message erase input buffer clear error flag turn LED off close channels 17 and 18 input-buffer pointer to zero initialize stack pointer secondary address 15? yes, cmd channel LISTEN active? yes TALK active? yes channel number channel to this second. addr open? no channel number

ABACUS Software

E67D

4C 8E E6

Anatomy of the 1541

JMP $E68E

******************************

E680

20 EB DO

JSR $DOEB

E683 E684 E685 E686

EA EA EA DO 06

NOP NOP NOP BNE $E68E

******************************

E688

20 07 Dl

JSR $0107

E68B E68C E68D E68E E691 E693 E695 E698

EA EA EA 20 C9 BO 20 4C

NOP NOP NOP JSR CMP BCS JSR JMP

25 Dl 04 03 27 D2 E7 EB

$0125 #$04 $E698 $D227 $EBE7

******************************

E69B E69C E69E E69F F6Al E6A3 E6A4 A6A6 E6A7 E6AA

AA A9 F8 EO FO 18 69 CA 4C D8

00 00 07 01 9F E6

TAX LDA SED CPX BEQ CLC ADC DEX JMP CLD

AA 4A 4A

LISTEN open channel for writing

verify file type file type REL? yes close channel convert hex to decimal (2 bytes)

#$00 #$00 $E6AA

convert hex to BCD

#$01 $E69F

******************************

E6AB E6AC E6AD

TALK open channel for reading

TAX LSR A LSR A

divide BCD number into two bytes shift hi-nibble down

316

Anatomy of the 1541

ABACUS Software

E6A.E E6AF E6BO E6B3 E6B4 E6B6 E6B8 E6BA E6BB

4A 4A 20 8A 29 09 91 C8 60

B4 E6 OF 30 A5

LSR LSR JSR TXA AND ORA STA INY RTS

A A $E6B4 #$OF #$30 ($A5),Y

****************************** E6BC E6BF E6C1 E6C3 E6C5

20 A9 AO 84 84

23 C1 00 00 80 81

JSR LDA LDY STY STY

$C123 #$00 #$00 $80 $81

****************************** LDY #$00 AO 00 E6C7 LDX #$D5 A2 D5 E6C9 STX $A5 86 A5 E6C8 LDX #$02 A2 02 E6CD STX $A6 86 A6 E6CF JSR $E6AB 20 AB E6 E6D1 E6D4 E6D6 ED68 E6D9

A9 2C 9A A5 C8 AD D5 02

LDA #$2C STA ($A5),Y INY LDA $02D5

E6DC E6DF E6EO E6E3 E6E5 E6E7 E6E8 E6EA

8D 8A 20 A9 91 C8 A5 20

STA TXA JSR LDA STA INY LDA JSR

E6ED

A9 2C

43 02 06 E7 2C A5 80 9B E6

$0243 $E706 #$2C ($A5),Y $80 $E69B

LDA #$2C 317

convert to ASCII clear top 4 bits add '0' write in buffer inc buffer pointer write 'ok' in buffer clear error flags error number 0 track 0 sector 0 error msg in buffer buffer pointer ptr $A5/$A6 to $2D5 error # to ASCII and in buffer ',' comma write in buffer inc buffer pointer first digit of the disk status in output register error # in acc error msg in buffer ',' comma write in buffer and inc buffer ptr track number to ASCII and in buffer , , , comma

ABACUS Software

Anatomy of the 1541

E6EF E6F1 E6F2 E6F4

91 AS C8 AS 81 20 9B E6

STA ($A5) , Y INY LDA $81 JSR $E69B

E6F7 E6F8 E6F9 E6FA E6FC E6FF E701 E703 E705

88 98 18 69 8D E6 A9 85 60

DEY TYA CLC ADC STA INC LDA STA RTS

D5 49 02 AS 88 F7

#$D5 $0249 $A5 #$88 $F7

****************************** TAX LDA PHA LDA PHA LDA STA

E706 E707 E709 E70A E70C E70D E70F

AS 48 AS 48 A9 85

E713 E715 E716 E718

85 87 8A A2 00 C1 86

STA $87 TXA LDX #$00 CMP ($86,X)

E71A E71C E71D

FO 21 48 20 75 E7

BEQ $E73D PHA JSR $E775

E720 E722 E725

90 05 20 75 E7 90 FB

BCC $E727 JSR $E775 BCC $E722

E727 E729

AS 87 C9 E6

LDA $87 CMP #$E6

AA

86 87 FC 86

write in buffer inc buffer pointer sector convert to ASCII and in buffer

end pointer inc buffer pointer set READ flag

write error message to buffer error code to X

$86 save ptr $86/$87 $87 #$FC #$E4

318

start of the error messages error # in acc compare with error # in table bit 7 into carry and clear not set? bit 7 into carry wait for character with bit 7 set

Anatomy of the 1541

ABACUS Software

Bee $E735

E72B

90 08

E720 E72F E731 E733 E735 E736 E739 E73A

00 AO e5 90 68 4e 68 4e

E730

20 67 E7

JSR $E767

E740

90 FB

Bee $E730

E742 E745 E748

20 54 E7 20 67 E7 90 F8

JSR $E754 JST $E767 Bee $E742

E74A E740 E74E E750 E751 E753

20 54 E7 68 85 87 68 85 86 60

JSR $E754 PLA STA $87 PLA STA $86 RTS

OA OA 86 04 18 E7 40 E7

BNE LOA eMP Bee PLA JMP PLA JMP

$E60A, check for end of table

$E739 #$OA $86 $E739 $E718

no, continue

$E74D

done

******************************

E754 E756

e9 20 BO OB

eMP #$20 BeS $E763

E758 E759 E75B E750 E75E E75F

AA

A9 20 91 A5 e8 8A 20 06 E7

TAX LOA #$20 STA ($A5),Y INY TXA JSR $E706

E762 E763 E765

60 91 A5 e8

RTS STA ($A5),Y INY

319

get a character, bit 7 in carry wait for character with bit 7 set and write in buffer get next character wait for character with bit 7 set put char in buffer get ptr $86/$87

get character and in buffer , , blank greater, then write in buffer save code blank write in buffer inc buffer pointer code in accumulator output associated text write char in buffr and increment ptr

ABACUS Software

E766

60

Anatomy of the 1541

RTS

******************************

E767 E769 E76B E76D E76F E770 E772 E774

E6 DO E6 A1 OA A1 29 60

86 02 87 86 86 7F

INC BNE INC LDA ASL LDA AND RTS

$86 $E76D $87 ($86,X) A ($86,X) #$7F

****************************** E775 20 6D E7 JSR $E76D E778 E6 86 INC $86 E77A DO 02 BNE $E77E E77C E6 87 INC $87 E77E 60 RTS

get a char of the error message increment pointer get character bit 7 into carry get character clear bit 7 increment pointer bit 7 into carry increment pointer

****************************** E77F 60 RTS ******************************

E780 E781 E7A1 E7A2

60 EA ... ... EA 60

RTS NOP NOP RTS

test for AUTO start is no longer present in current operating system

****************************** E7A3 A9 8D LDA #$8D E7A5 20 68 C2 JSR $C268

E7A8 E7AB E7AE E7AF E7B1 E7B4

20 58 F2 78 02 48 A9 01 8D 78 02 A9 FF AD

JSR LDA PHA LDA STA LDA

check for AUTO-start

'&' - command

$F258 $0278

check command line to end (RTS) number of filenames save

#$01 $0278 #$FF

a filename

320

ABACUS Software

Anatomy of the 1541

E7B6 E7B8 E7BB E7BE E7CO E7C2

85 20 AD DO A9 20

E7C5 E7C6

68 8D 78 02

PLA STA $0278

E7C9 E7CC E7CE E7D1 E7D3 E7D5

AD 85 AD 85 A9 20

80 02 80 85 02 81 03 77 D4

LDA STA LDA STA LDA JSR

$0280 $80 $0285 $81 #$03 $D477

E7D8 E7DA E7DC E7DF

A9 85 20 85

00 87 39 E8 88

LDA STA JSR STA

#$00 $87 $E839 $88

E7E1 E7E4 E7E7 E7E9 E7EC E7EE E7FO E7F2

20 20 85 20 A5 FO A5 48

4B E8 39 E8 89 4B E8 86 OA 88

JSR JSR STA JSR LDA BEQ LDA PHA

$E84B $E839 $89 $E84B $86 $E7FA $88

E7F3 E7F5 E7F6 E7F8 E7FA E7FD E7FF E802 E805

A5 48 A9 85 20 85 20 20 AO

89

LDA PHA LDA STA JSR STA JSR JSR LDY

$89

86 4F C4 80 02 05 39 C8 C1

00 86 39 E8 8A 4B E8 39 E8 00

STA JSR LDA BNE LDA JSR

$86 $C44F $0280 $E7C5 #$39 $C1C8

find file found? 39, 'file not found' get number of filenames back track and sector file type 'USR' buffer allocated, read 1st block erase checksum get byte from file save as start address 10 form checksum get byte from file as start address hi form checksum

save program start address #$00 $86 $E839 $8A $E84B $E839 #$00

321

get byte from file save as counter form checksum get byte from file

ABACUS Software

Anatomy of the 1541

E807

91 88

STA ($88),Y

E809 E80C E80E E80F E811 E813 E815 E817 E819 E81B E81E E820 E822 E824

20 A5 18 69 85 90 E6 C6 DO 20 A5 C5 FO 20

JSR LDA CLC ADC STA BCC INC DEC BNE JSR LDA CMP BEQ JSR

E827 E829

A9 50 20 45 E6

LDA #$50 JSR $E645

E82C E82E E830 £831 E833

A5 F8 DO A8 68 85 89 68

LDA $F8 BNE $E7D8 PLA STA $89 PLA

E834 E836 E839 E83C E83E E840

85 6C 20 A5 DO 20

STA JMP JSR LDA BNE JSR

E843 E845

A9 51 20 45 E6

LDA #$51 JSR $E645

E848 E84A

A5 85 60

LDA $85 RTS

4B E8 88 01 88 02 89 8A E7 35 CA 85 87 08 3E DE

88 88 00 35 CA F8 08 3E DE

$E84B $88 #$01 $88 $E817 $89 $8A $E802 $CA35 $85 $87 $E82C $DE3E

$88 ($0088) $CA35 $F8 $E848 $DE3E

****************************** E84B A8 CLC

322

save as program bytes form checksum

increment $88/$89 decrement pointer get next byte data byte equal to checksum? yes transmit param to disk controller 50, 'record not present' end? no, next data block get program start address back and execute program get byte from file end? no transmit param to disk controller 51, 'overflow in record' data byte generate checksum

Anatomy of the 1541

ABACUS Software

E84C E84E E850 E852

AOC $87 AOC #$00 STA $87 RTS

65 87 69 00 85 87 60

add carry

****************************** E853

AO 01 18

LOA $1801

E856 E858

A9 01 85 7C

LOA #$01 STA $7C

E85A

60

RTS

****************************** E85B E85C E85E

78 A9 00 85 7C

SEI LOA #$00 STA $7C

E860

85 79

STA $79

E862 E864 E866

85 7A A2 45 9A

STA $7A LOX #$45 TXS

E867 E869 E86B E860 E870

A9 85 85 20 20

80 F8 70 B7 E9 A5 E9

LOA STA STA JSR JSR

#$80 $F8 $70 $E9B7 $E9A5

E873 E876 E878 E87B E87E E880 E882 E884 E887

AD

00 10 00 00 57 04 F7 C9 3F

18

LOA ORA STA LOA BPL ANO BNE JSR CMP

$1800 #$10 $1800 $1800 $E807 #$04 $E87B $E9C9 #$3F

09 80 AD 10 29 DO 20 C9

18 18

E9

323

IRQ routine for serial bus read port A, clear IRQ flag set flag for 'ATN received' service the serial bus erase flag for 'ATN received' erase flag for LISTEN erase flag for TALK initialize stack pointer clear end clear EOI CLOCK OUT DATA OUT, hi

flag flag 10 bit '0' ,

set ATN acknowledge read IEEE port EOI? CLOCK IN? no get byte from bus unlisten?

ABACUS Software

Anatomy of the 1541

E889 E88B E88D

DO 06 A9 00 85 79

E88F E891 E893 E895 E897 E899 E89B E89D E89F E8A1 E8A3 E8A5

FO C9 DO A9 85 FO C5 DO A9 85 A9 85

71 5F 06 00 7A 67 78 OA 01 7A 00 79

BEQ CMP BNE LDA STA BEQ CMP BNE LDA STA LDA STA

$E902 #$5F $E89B #$00 $7A $E902 $78 $E8A9 #$01 $7A #$00 $79

E8A7 E8A9 E8AB E8AD E8AF E8B1 E8B3 E8B5 E8B7 E8B8 E8BA E8BC E8BE E8BF

FO C5 DO A9 85 A9 85 FO

29 77 OA 01 79 00 7A 1B

$E8D2 $77 $E8B7 #$01 $79 #$00 $7A $E8D2

29 C9 DO 8A 85

60 60 3F

BEQ CMP BNE LDA STA LDA STA BEQ TAX AND CMP BNE TXA STA

E8C1 E8C3 E8C5 E8C7 E8C9 E8CB E8CD E8CE E8D1

29 85 A5 29 C9 DO 58 20 78

OF 83 84 FO EO 35

AND STA LDA AND CMP BNE CLI JSR SEI

#$OF $83 $84 #$FO #$EO $E902

AA

84

CO DA

BNE $E891 LDA #$00 STA $79

#$60 #$60 $E8FD $84

no reset flag for LISTEN untalk? no reset flag for TALK TALK address? no set flag for TALK reset flag for LISTEN LISTEN address? no set flag for LISTEN reset flag for TALK

set bit 5 and 6 no byte is secondary address

$DACO

324

channel number CLOSE? CLOSE routine

Anatomy of the 1541

ABACUS Software

E8D2 E8D5

2C 00 18 30 AD

BIT $1800 BMI $E884

E8D7 E8D9 E8DB E8DE

A9 85 AD 29

00 7D 00 18 EF

LDA STA LDA AND

#$00 $7D $1800 #$EF

E8EO E8E3 E8E5 E8E7 E8EA

8D A5 FO 20 4C

00 18 79 06 2E EA E7 EB

STA LDA BEQ JSR JMP

$1800 $79 $E8ED $EA2E $EBE7

E8ED E8EF E8Fl

A5 7A FO 09 20 9C E9

E8F4 E8F7 E8FA E8FD

20 20 4C A9

E8FF

8D 00 18

STA $1800

E902 E905

2C 00 18 10 DO

BIT $1800 BPL $E8D7

E907

30 F9

BMI $E902

AE E9 09 E9 4E EA 10

LDA $7A BEQ $E8FA JSR $E99C JSR JSR JMP LDA

$E9AE $E909 $EA4E #$10

****************************** SEI 78 E909 JSR $DOEB DO EB 20 E90A E90D E90F E911 E913 E915

BO A6 B5 30 60

06 82 F2 01

BCS LDX LDA BMI RTS

$E915 $82 $F2,X $E916

325

test ATN active, then get next byte clear ATN flag clear ATN acknowledge LISTEN active? no receive data to delay loop TALK active? no DATA OUT, bit ' 1 ' , 10 CLOCK OUT hi send data to delay loop neither TALK nor LISTEN, ignore byte switch data lines to input test ATN ATN no longer active? wait until command mode ended send data open channel for reading channel active? channel number READ flag set? yes

ABACUS Software

E916 E919 E91C E91E E91F E922 E923 E925 E928 E92B E92D E92F E931 E933 E935 E937 E93A E93D E93F

20 20 29 08 20 28 FO 20 20 29 DO A6 B5 29 DO 20 20 29 DO

12 59 CO 01 F6 82 F2 08 14 59 CO 01 F6

E941 E944 E947 E949 E84B E94E E951 E954 E956 E958

20 20 29 FO 20 20 20 29 DO A9

59 CO 01 F6 AE 59 CO 01 F3 08

E95A E95C E95F E961

85 20 29 DO

E963 E965 E968 E969 E96C

A6 BD 6A 90 BO

Anatomy of the 1541

59 EA CO E9 01

JSR JSR AND PHP JSR PLP BEQ JSR JSR AND BNE LOX LOA AND BNE JSR JSR AND BNE

$E937 $EA59 $E9CO #$01 $E925 $82 $F2,x #$08 $E94B $EA59 $E9CO #$01 $E937

JSR JSR AND BEQ JSR JSR JSR AND BNE LOA

$EA59 $E9CO #$01 $E941 $E9AE $EA59 $E9CO #$01 $E94B #$08

98 CO E9 01 36

STA JSR AND BNE

$98 $E9CO #$01 $E999

82 3E 02

LDX LOA ROR STA BCS

$82 $023E,X A $023E,X $E973

B7 E9 EA E9

EA E9

EA E9 E9 EA E9

3E 02 05

$EA59 $E9CO #$01 $E9B7

326

test for ATN read IEEE port isolate data bit and save CLOCK OUT 10 check for ATN read IEEE port isolate data bit channel number no end? test for ATN read IEEE port isolate data bit output byte with EOI test for ATN read IEEE port isolate data bit CLOCK OUT hi test for ATN read IEEE port isolate data bit counter to 8 bits for serial transfer read IEEE port isolate data bit no activity on serial bus? channel number byte to output lowest bit in carry bit set

ABACUS Software

Anatomy of the 1541

E96E

20 A5 E9

JSR $E9A5

E971 E973

DO 03 20 9C E9

BNE $E976 JSR $E99C

E976 E979 E97B E97D

20 A5 DO 20

JSR LDA BNE JSR

E980

20 FB FE

JSR $FEFB

E983 E985 E987 E98A E98D E98F E991 E992 E99S E996

C6 DO 20 20 29 FO 58 20 78 4C

DEC BNE JSR JSR AND BEQ CLI JSR SEI JMP

E999

4C 4E EA

B7 E9 23 03 F3 FE

98 D5 59 EA CO E9 01 F6 AA D3 OF E9

$E9B7 $23 $E980 $FEF3

$98 $E95C $EAS9 $E9CO #$01 $E987

DATA OUT, output bit '0 ' unconditional jump DATA OUT, output bit ' 1 ' set CLOCK OUT 1540 mode? yes, skip delay delay for serial bus set DATA OUT and CLOCK OUT all bits output? no test for ATN read IEEE port isolate data bit

$D3AA

get next data byte

$E90F

and output

JMP $EA4E

to delay loop

****************************** E99C AD 00 18 LDA $1800 AND #$FD E99F 29 FD STA $1800 E9A1 8D 00 18 E9A4 RTS 60

DATA OUT 10

****************************** LDA $1800 E9A5 AD 00 18 ORA #$02 E9A8 09 02 STA $1800 8D 00 18 E9AA RTS E9AD 60

DATA OUT hi

****************************** LDA $1800 AD 00 18 E9AE ORA #$08 E9Bl 09 08 STA $1800 8D 00 18 E9B3

CLOCK OUT hi

327

output bit ' 1 '

output bit '0 '

set bit 3

ABACUS Software

E9B6

Anatomy of the 1541

60

RTS

****************************** E9B7 AD 00 18 LDA $1800 E9BA 29 F7 AND #$F7 E9BC 8D 00 18 STA $1800 E9BF 60 RTS

CLOCK OUT 10

****************************** E9CO AD 00 18 LDA $1800 E9C3 CD 00 18 CMP $1800 E9C6 DO F8 BNE $E9CO E9C8 60 RTS

read IEEE port read port wait for constants

******************************

get data byte from bus

E9C9 E9CB

A9 08 85 98

E9CD E9DO E9D3 E9D5 E9D7 E9DA E9DC E9DF E9E2 E9E5 E9E7 E9E9 E9EC E9EE

20 20 29 DO A9 4C 20 AD 29 DO 20 29 FO

E9FO

DO 19

20

59 CO 04 F6 9C 01 20 59 OD 40 09 CO 04 EF

LDA #$08 STA $98 EA E9 E9 FF EA 18 E9

JSR JSR AND BNE JSR LDA JMP JSR LDA AND BNE JSR AND BEQ

$EA59 $E9CO #$04 $E9CD $E99C #$01 $FF20 $EA59 $180D #$40 $E9F2 $E9CO #$04 $E9DF

BNE $EAOB

****************************** E9F2 E9F5

20 AS E9 A2 OA

JSR $E9A5 LDY #$OA

328

clear bit 3

bit counter for serial output test for ATN read IEEE port CLOCK IN? no, wait DATA OUT, bit I I' patch test for ATN timer run out? yes, EOI read IEEE port CLOCK IN? no, wait receive normal data byte accept byte with EOI DATA OUT bit '0 ' hi 10

ABACUS Software

Anatomy of the 1541

E9F7

CA

DEX

E9F8 E9FA E9FD EAOO EA03 EA05 EA07 EA09 EAOB EAOE EA10 EA11 EA13 EA15 EA16 EA17 EA18 EA1A EA1D EA20 EA22 EA24

DO 20 20 20 29 FO A9 85 AD 49 4A 29 DO EA EA EA 66 20 20 29 FO C6

EA26 EA28 EA2B

DO E3 20 AS E9 AS 85

BNE $EAOB JSR $E9AS LDA $85

EA2D

60

RTS

FD 9C 59 CO 04 F6 00 F8 00 01

E9 EA E9

18

02 F6

85 59 EA CO E9 04 F6 98

BNE JSR JSR JSR AND BEQ LDA STA LDA EOR LSR AND BNE NOP NOP NOP ROR JSR JSR AND BEQ DEC

delay loop, approx 50 micro sec. $E9F7 $E99C $EA59 $E9CO #$04 $E9FD #$00 $F8 $1800 #$01 A #$02 $EAOB

$85 $EA59 $E9CO #$04 $EA1A $98

****************************** EA2E EA2F

78 20 07 D1

SEI JSR $D107

EA32 EA34 EA36

BO 05 B5 F2 6A

BCS $EA39 LDA $F2,X ROR A

329

DATA OUT, bit '1'10 test for ATN read IEEE port CLOCK IN? no, wait set EOI flag IEEE port invert data byte and into carry CLOCK IN?

accept next bit test for ATN read IEEE port CLOCK IN? no decrement bit counter all bits received? DATA OUT bit '0 ' hi load data byte again

accept data from serial bus open channel for writing channel not active? WRITE flag into carry

ABACUS Software

OB 84 FO FO 03 4E EA

Anatomy of the 1541

$EA44 $84 #$FO #$FO $EA44 JMP $EA4E

BCS LDA AND CMF BEQ

set, accept byte secondary address

EA37 EA39 EA3B EA3D EA3F EA41

BO A5 29 C9 FO 4C

EA44

20 C9 E9

JSR $E9C9

EA47 EA48 EA4B

58 20 B7 CF 4C 2E EA

CLI JSR $CFB7 JMP $EA2E

and write in buffer to loop beginning

EA4E EA50 EA53

A9 00 8D 00 18 4C E7 EB

LDA #$00 STA $1800 JMP $EBE7

reset IEEE port to wait loop

EA56

4C 5B E8

JMP $E85B

****************************** $7D $EA63 $1800 $EA6B

OPEN command? yes else ignore, to wait loop get data byte from bus

to serial bus main loop test for ATN ATN active? no IEEE port ATN no longer active?

EA59 EA5B EA5D EA60

A5 7D FO 06 AD 00 18 10 09

LDA BEQ LDA BPL

EA62

60

RTS

EA63 EA66

AD

00 18 10 FA

LDA $1800 BPL $EA62

IEEE port ATN not active, then return

EA68

4C 5B E8

JMP $E85B

EA6B

4C D7 E8

JMP $E8D7

receive command byte clear ATN flag, serve serial bus

330

ABACUS Software

Anatomy of the 1541

****************************** EA6E

A2 00

LDX #$00

EA70 EA71

2C A5 6F

.BYTE $2C LDX $6F

EA73 EA74 EA75

9A BA A9 OS

TXS TSX LDA #$OS

EA77 EA7A

OD 00 1C 4C EA FE

ORA $lCOO JMP $FEEA

EA7D EA7E EA7F EAS1 EAS3 EAS4 EAS6 EAS9 EASB EASE EASF EA90 EA92 EA94 EA95 EA97 EA98 EA9A EA9C EA9E

9S lS 69 DO SS DO AD 29 8D 9S lS 69 DO 88 DO CA 10 EO DO FO

TYA CLC ADC BNE DEY BNE LDA AND STA TYA CLC ADC BNE DEY BNE DEX BPL CPX BNE BEQ

01 FC FS 00 1C F7 00 1C 01 FC F8 DB FC FO D4

flash LED for hardware defects, self-test blink once, zero page blink X+1 times for RAM/ROM error select LED bit in the port turn LED on, back to $EA7D

#$01 $EA7F $EA7E $lCOO #$F7 $lCOO #$01 $EA90

turn LED off

delay l_'JOp

$EA8F $EA75 #$FC $EASE $EA74

****************************** SEI 7S EAAO CLD DS EAA1 LDX #$FF EAA2 A2 FF STX $1803 EAA4 8E 03 18 331

wait for delay turn LED on again RESET routine

direction output

ABACUS Software

EAA7 EAA8 EAAA EAAC EAAD EAAF EABO EAB2 EAB3 EAB5

4C AO A2 8A 95 E8 DO 8A D5 DO

EAB7 EAB9 EABA EABC EABE EACO EAC2 EAC4 EAC6 EAC7 EAC9 EACB EACD EACF EAD1 EAD2 EAD4 EAD5 EAD7 EAD9 EADA EADC EADD EADF EAE1 EAE2 EAE4 EAE6 EAE8 EAEA

F6 C8 DO D5 DO 94 B5 DO E8 DO E6 86 A9 85 A8 A2 18 C6 71 C8 DO CA DO 69 AA C5 DO EO DO A9

10 FF 00 00 00 FA 00 B7 00 FB 00 AE 00 00 A8 E9 6F 76 00 75

20 76 75 FB F6 00 76 39 CO DF 01

Anatomy of the 1541

JMP LDY LDX TXA STA INX BNE TXA CMP BNE

$FF10 #$00 #$00

patch

$OO,X

erase zero page

INC INY BNE CMP BNE STY LDA BNE INX BNE INC STX LDA STA TAY LDX CLC DEC ADC INY BNE DEX BNE ADC TAX CMP BNE CPX BNE LDA

$OO,X

$EAAC $OO,X $EA6E

$EAB7 $OO,X $EA6E $OO,X $OO,X $EA6E

is byte erased? no, then to error display (flash)

error error

$EAB2 $6F $76 #$00 $75 #$20

test 32 pages

$76 ($75), Y $EAD7 $EAD5 #$00 $76 $EB1F #$CO $EAC9 #$01

332

test ROM

ROM error

Anatomy of the 1541

ABACUS Software

EAEC EAEE EAFO

85 76 E6 6F A2 07

STA $76 INC $6F LDX #$07

EAF2 EAF3 EAF4 EAF6 EAF8 EAF9 EAFB EAFD EAFE EBOO EB02 EB04 EB05 EB06 EB07 EB09 EBOB EBOD EBOF EBll EB13 EB15 EB17 EB1S EBIA EBIB EB1D EB1F

98 18 65 76 91 75 C8 DO F7 E6 76 CA DO F2 A2 07 C6 76 88 98 18 65 76 D1 75 DO 12 49 FF 91 75 51 75 91 75 DO 08 98 DO EA CA DO E5 FO 03 4C 71 EA

TYA CLC ADC $76 STA ($75) , Y INY BNE $EAF2 INC $76 DEX BNE $EAF2 LDX #$07 DEC $76 DEY TYA CLC ADC $76 CMP ($75) ,Y BNE $EB1F EOR #$FF STA ($75), Y EOR ($75), Y STA ($75), Y BNE $EB1F TYA BNE $EB04 DEX ENE $EB02 BEQ $EB22 JMP $EA71

EB22 EB24

A2 45 9A

EB25 EB28 EB2A EB2D

AD 29 8D A9

00 lC F7 00 lC 01

test RAM, beginning at page 7

LDX #$45 TXS LDA AND STA LDA

$lCOO #$F7 $lCOO #$01

333

RAM error

RAM error

continue test ok to error display initialize stack pointer turn LED off

ABACUS Software

Anatomy of the 1541

EB2F

8D OC 18

STA $180C

EB32 EB34

A9 82 8D OD 18

LDA #$82 STA $180D

EB37 EB3A EB3D

8D OE 18 AD 00 18 29 60

STA $180E LDA $1800 AND #$60

EB3F EB40 EB41

OA 2A 2A

ASL A ROL A ROL A

EB42 EB43

2A 09 48

ROL A ORA #$48

EB45

85 78

STA $78

EB47

49 60

EOR #$60

EB49

85 77

STA $77

EB4B EB40 EB4F EB51

A2 AO A9 95

LDX LOY LDA STA

EB53 EB54

E8 B9 EO FE

INX LOA $FEEO,y

EB57 EB59 EB5A EB5B EB5D EB5F EB61 EB63

95 E8 C8 CO DO A9 95 E8

STA INX INY CPY BNE LDA STA INX

EB64 EB66

A9 02 95 99

00 00 00 99

99 05 FO 00 99

#$00 #$00 #$00 $99,X

$99, X

CAl (ATN IN) trigger on pos edge interrupt allowed through ATN IN read port B isolate bits 5 (device #)

&

6

rotate to bit positions o & 1 add offset from 8 + $40 for TALK device number for TALK (send) erase bit 6, set bit 5 device number + $20 for LISTEN

low-byte of buffer address high byte of address from table save

#$05 $EB4F #$00 $99,X

LDA #$02 STA $99, X

334

ptr $A3/$A4 to $200, input buffer

Anatomy of the 1541

ABACUS Software

INX LDA #$D5 STA $99,X INX

EB68 EB69 E86B EB6D

E8 A9 D5 95 99 E8

EB6E EB70 EB72 EB74 EB76

A9 95 A9 A2 9D

02 99 FF 12 2B 02

LDA STA LDA LDX STA

#$02 $99,X #$FF #$12 $022B,X

EB79 EB7A EB7C EB7E EB80 EB82

CA 10 A2 95 95 95

FA 05 A7 AE CD

DEX BPL LDX STA STA STA

$EB76 #$05 $A7,X $AE,X $CD,X

EB84 EB85 EB87 EB89 EB8B EB8D EB8F EB91 EB93 EB95 EB97

CA 10 A9 85 A9 85 A9 85 85 A9 8D

F7 05 AB 06 AC FF AD B4 05 3B 02

DEX BPL LDA STA LDA STA LDA STA STA LDA STA

$EB7E #$05 $AB #$06 $AC #$FF $AD $B4 #$05 $023B

EB9A EB9C

A9 84 8D 3A 02

LDA #$84 STA $023A

EB9F

A9 OF

LDA #$OF

EBAI

8D 56 02

STA $0256

EBA4 EBA6 EBA8

A9 01 85 F6 A9 88

LDA #$01 STA $F6 LDA #$88 335

pointer $A5/$A6 to $2D5, buffer error msg message pointer

fill channel table with $FF ( "not allocated" )

erase buffer table erase side-sector table buffer assign buffer assign

5 to channel 4 6 to channel 5

channel 5 WRITE flag cleared channel 4 WRITE flag set initialize channel allocation reg bit '1 ' equals channel free WRITE flag

ABACUS Software

Anatomy of the 1541

EBAA EBAC EBAE

85 F7 A9 FO 8D 4F 02

STA $F7 LL. .. ,;::$EO STA $024F

EBBI

A9 FF

LDA #$FF

EBB3 EBB6 EBB8

8D 50 02 A9 01 85 lC

STA $0250 LDA #$01 STA $IC

EBBA EBBC EBBF

85 ID 20 63 CB 20 FA CE

STA $lD JSR $CB63 JSR $CEFA

EBC2

20 59 F2

JSR $F259

EBC5 EBC7 EBC9

A9 22 85 65 A9 EB

LDA #$22 STA $65 LDA #$EB

EBCB EBCD EBCF EBDI

85 A9 85 A9

STA LDA STA LDA

EBD3 EBD5

85 6A A9 73

STA $6A LDA #$73

EBD7

20 Cl E6

JSR $E6Cl

EBDA EBDC EBDF

A9 00 8D 02 18 A9 00

LDA #$00 STA $1800 LDA #$lA

EBEI EBE4

8D 02 18 20 80 E7

STA $1802 JSR $E780

EBE7 EBE8 EBEB EBED

58 AD 00 18 29 £5 8D 00 18

CLI LDA $1800 AND #$E5 STA $1800

66 OA 69 05

$66 #$OA $69 #$05

336

READ flag 5 buffers free initialize buffer allocation reg $24F/$250, 16 bit, l=buffer allocated set flags for WRITE protect set vector for UO initialize channel table initialization for disk controller pointer $65/$66 to $EB22 step width 10 for sector assignment 5 read attempts prepare power-up message 73, Icbm dos v2.6 1541' clear data register DATA OUT, CLOCK OUT and ATN A to output data dir port B check for auto-start reset serial po:::-t

ABACUS Software

EBFO EBF3 EBF5 EBF7 EBFA EBFC

AD FO A9 8D 85 20

55 02 OA 00 55 02 67 46 C1

Anatomy of the 1541

LDA BEQ LDA STA STA JSR

$0255 $EBFF #$00 $0255 $67 $C146

****************************** EBFF 58 CLI LDA $7C ECOO A5 7C EC02 EC04 EC07 EC08 ECOA ECOC ECOE EC10 EC12 EC14 EC17 EC19 EC1B EC1D EC1F EC22 EC23 EC26 EC28 EC29 EC2B EC2D EC2F EC31

FO 4C 58 A9 85 A9 85 85 A6 BD C9 FO 26 85 20

03 5B E8

EC34 EC36 EC38 EC39

10 05 29 01

OE 72 00 6F 70 72 2B 02 FF 10 3F 82 93 DF

AA

BD 5B 02 29 01 AA

F6 C6 10 AO B9

6F 72 E3 04 00 00

AA

F6 6F

BEQ JMP CLI LDA STA LDA STA STA LDX LDA CMP BEQ AND STA JSR TAX LDA AND TAX INC DEC BPL LDY LDA

$EC07 $E85B #$OE $72 #$00 $6F $70 $72 $022B,X #$FF $EC2B #$3F $82 $DF93

command flag set? no reset command flag analyze and execute command wait loop ATN signal discovered? no to IEEE routine 14 as secondary addr job counter secondary address channel assigned? no channel number get buffer number

$025B,X #$01

drive number

$6F,X $72 $EC12 #$04 $OOOO,Y

increment job cntr 10 address continue search buffer counter disk controller in action? no isolate drive #

BPL $EC3B AND #$01 TAX INC $6F,X

337

increment job cntr

ABACUS Software

Anatomy of the 1541

EC3B EC3C EC3E EC3F EC42 EC44 EC45 EC47 EC49 EC4B EC4D EC4F EC51

88 10 F3 78 AD 00 1C 29 F7 48 A5 7F 85 86 A9 00 85 7F A5 6F FO OB A5 1C

DEY BPL SEI LDA AND PHA LDA STA LDA STA LDA BEQ LDA

EC53 EC55

FO 03 20 13 D3

BEQ $EC58 JSR $D313

EC58 EC59 EC5B EC5C EC5E EC60 EC62

68 09 48 E6 A5 FO A5

EC64 EC66

FO 03 20 13 D3

EC69 EC6A EC6C EC6D EC6F EC71

68 09 00 48 A5 86 85 7F 68

PHA LDA $86 STA $7F PLA

EC72

AE 6C 02

LDX $026C

FO 21 00 lC EO 80 DO 03

BEQ LDA CPX BNE

EC75 EC77 EC7A EC'IC

AD

$EC31

next buffer

$lCOO #$F7

erase LED bit

$7F $86 #$00 $7F $6F $EC5C $lC

drive number drive 0 job for drive O? no write protect for drive O? no close all channels to drive 0

PLA 08

ORA #$08

7F 70 OB ID

PHA INC LDA BEQ LDA

$7F $70 $EC6D $lD

BEQ $EC69 JSR $D313

set LED bit increment drive # job for drive 1? no write protect for drive I? no close all channels to drive 1

PLA ORA #$00

get drive # back bit for LED

$EC98 $lCOO #$80 $EC81 338

interrupt counter for LED flash to zero?

ABACUS Software

Anatomy of the 1541

EC7E EC81

4C 8B EC AE 05 18

EC84 EC86 EC88 EC8B EC8E EC90

30 A2 8E CE 00 40

EC93 EC95 EC98 EC9B

A2 8E 80 4C

12

JMP $EC8B LOX $1805

05 18 6C 02 08 60 02

BMI LOX STX OEC BNE EOR

$EC98 #$AO $1805 $026C $EC98 $0260

10 6C 02 00 1C FF EB

LOX STX STA JMP

#$10 $026C $lCOO $EBFF

AO

****************************** EC9E A9 00 LOA #$00 ECAO 85 83 STA $83 ECA2 A9 01 LOA #$01 ECA4 20 E2 01 JSR $01E2

ECA7 ECA9

A9 00 20 C8 04

LDA #$00 JSR $04C8

ECAC ECAE ECBO ECB3 ECB6 ECB7 ECB9 ECBC ECBE ECCl ECC3 ECC6 ECC8 ECCB

A6 A9 90 20

LOX LOA STA JSR TAX LOA STA LOA JSR LOA JSR LOA JSR JSR

ECCE

AD 72 02

82 00 44 02 93 OF

AA

AS 90 A9 20 A9 20 A9 20 20

7F SB 01 F1 04 F1 01 Fl F1

02 CF CF CF CF

$82 #$00 $0244,X $OF93 $7F $02SB,X #$01 $CFF1 #$04 $CFF1 #$01 $CFF1 $CFF1

LOA $0272

339

clear timer interrupt set timer decrement counter not yet zero? invert condition bit for LEO reset counter turn LEO on/off back to wait loop LOAD "$" secondary address 0 find channel and buffer initialize buffer pointer channel number ptr to end = zero get buffer number drive number bring in table 1 write in buffer 4, start addr $0401 write in buffer 2 times 1 write in buffer as link address drive number

Anatomy of the 1541

ABACUS Software

ECD1

20 F1 CF

JSR $CFF1

ECD4 ECD6 ECD9 ECDC ECDF ECEO ECE1

A9 20 20 20 OA

D6 99

LDA JSR JSR JSR ASL TAX DEC

ECE3 ECE5 ECE7

D6 99 A9 00 20 F1 CF

DEC $99,X LDA #$00 JSR $CFF1

ECEA ECEC

A9 01 20 F1 CF

LDA #$01 JSR $CFF1

ECEF ECF2 ECF5 ECF7 ECFA ECFD EDOO ED03 ED06 ED08

20 F1 CF 20 CE C6 90 2C AD 72 02 20 F1 CF AD 73 02 20 F1 CF 20 59 ED A9 00 20 F1 CF

JSR JSR BCC LDA JSR LDA JSR JSR LDA JSR

$CFF1 $C6CE $ED23 $0272 $CFF1 $0273 $CFF1 $ED59 #$00 $CFF1

EDOB EDOD ED10 ED11 ED12 ED14 ED16 ED18 ED1A ED1D ED20 ED22

DO DD 20 93 DF OA

BNE JSR ASL TAX LDA STA LDA LDY STA STA LDA RTS

$ECEA $DF93 A

00 F1 CF 59 ED 93 DF

AA

AA

A9 95 A9 A4 8D 99 A5 60

00 99 88 82 54 02 F2 00 85

#$00 $CFF1 $ED59 $DF93 A $99, X

#$00 $99, X #$88 $82 $0254 $00F2,Y $85

340

write in buffer as line number line number hi in buffer dir entry in buffer get buffer number decrement buffer pointer

o as line end in buffer 2 times 1 as link address dir entry in buffer another entry? block number 10 in buffer block number hi in buffer dir entry in buffer zero as end marker in buffer buffer full? no get buffer number

buffer ptr to zero set READ flag channel number flag for channel data byte

ABACUS Software

Anatomy of the 1541

****************************** ED23 AD 72 02 LDA $0272 ED26 20 F1 CF JSR $CFF1 ED29 AD 73 02 LDA $0273 ED2C 20 Fl CF JSR $CFF1 ED2F 20 59 ED JSR $ED59 ED32 ED35 ED36 ED37 ED39 ED3B ED3D ED40

20 93 DF OA D6 D6 A9 20 20

99 99 00 F1 CF F1 CF

ED43 ED46 ED49 ED4A ED4B ED4E ED50 ED53 ED56

20 20 OA A8 B9 A6 9D DE 4C

F1 CF 93 DF

AA

99 82 44 44 OD

02 02 02 ED

JSR ASL TAX DEC DEC LDA JSR JSR

$DF93 A

JSR JSR ASL TAY LDA LDX STA DEC JMP

$CFF1 $DF93 A

$99,X $99,X #$00 $CFF1 $CFF1

$0099,Y $82 $0244,X $0244,X $EDOD

****************************~*

ED59 ED5B ED5E

AO 00 B9 B1 02 20 F1 CF

LDY #$00 LDA $02B1,Y JSR $CFF1

ED61 ED62 ED64 ED66

C8 CO IB DO F5 60

INY CPY #$lB BNE $ED5B RTS

****************************** ED67 ED6A ED6C

20 37 D1 FO 01 60

JSR $D137 BEQ $ED6D RTS 341

block number 10 write in buffer block number hi in buffer , in 'Blocks free. buffer get buffer number times 2 buffer ptr minus 2 three zeroes as program end get buffer number times 2 buffer pointer as end marker

transmit dir line char from buffer write in output buffer 27 characters?

get byte trom buffer get byte buffer ptr zero?

ABACUS Software

Anatomy of the 1541

ED6D ED6F ED71 ED74 ED76 ED78 ED7B ED7D

85 A4 B9 FO A9 99 A5 60

ED7E ED7F

48 20 EA EC

PHA JSR $ECEA

ED82 ED83

68 60

PLA RTS

85 82 44 02 08 80 F2 00 85

STA LDY LDA BEQ LDA STA LDA RTS

$85 $82 $0244,Y $ED7E #$80 $00F2,Y $85

****************************** ED84 JSR $C1D1 20 D1 C1 ED87 ED8A ED8C ED8F

20 A9 8D 20

42 DO 40 F9 02 B7 EE

ED92 ED94 ED97

A9 00 8D 92 02 20 AC C5

LDA #$00 STA $0292 JSR $C5AC

ED9A ED9C ED9E EDAO EDA3 EDA5

DO A9 85 AD 85 20

BNE LDA STA LDA STA JSR

EDA8 EDAA EDAD

A9 00 8D F9 02 20 FF EE

LDA #$00 STA $02F9 JSR $EEFF

EDBO

4C 94 C1

JMP $C194

3D 00 81 8E FE 80 E5 ED

JSR LDA STA JSR

$D042 #$40 $02F9 $EEB7

$EDD9 #$00 $81 $FE85 $80 $EDE5

342

save data byte channel number set end marker zero (LOAD $)? set READ flag data byte

create directory line in buffer

V command, 'collect' find drive number in input line load BAM create new BAM in buffer load directory, find 1st entry found? sector 0 18 track 18 for BAM mark dir blocks as allocated write BAM back to disk done, prepare disk status

ABACUS Software

Anatomy of the 1541

****************************** EDB3 INY C8 EDB4 LDA ($94),Y B1 94 ED86 48 PHA EDB7 C8 INY EDB8 LDA ($94) ,Y B1 94 EDBA 48 PHA EDBB AO 13 LDA #$13 94 OA 80

B1 FO 85 C8 B1 85

EDC8

20 E5 ED

JSR $EDE5

EDCB EDCC EDCE

68 85 81 68

PLA STA $81 PLA

EDCF EDD1

85 80 20 E5 ED

STA $80 JSR $EDE5

EDD4

20 04 C6

JSR $C604

EDD7 EDD9 EDDB EDDD

FO AO B1 30

BEQ LDY LDA BMI

EDDF

20 B6 C8

JSR $C8B6

EDE2

4C D4 ED

JMP $EDD4

94 81

C3 00 94 D4

LDA BEQ STA INY LDA STA

($94),Y $EDCB $80

EDBD EDBF EDC1 EDC3 EDC4 EDC6

($94),Y $81

save track and sector pointer to side-sector block no track following? track and sector of 1st side-sector block mark side-sector blocks as allocated get track and sector back

$ED9C #$00 ($94),Y $EDB3

****************************** EDE5

20 5F D5

JSR $D55F

EDE8

20 90 EF

JSR $EF90

343

mark blocks of file as allocated read next entry in directory end of directory? file type bit 7 set, file closed? file type to zero and write BAM allocate file blocks in BAM check track and sector numbers allocate blk in BAM

Anatomy of the 1541

ABACUS Software

75 00 C8 37 80 37 81 80 03 27

D4

EDEB EDEE EDFO EDF3 EDF6 EDF8 EDFB EDFD EDFF EE01

20 A9 20 20 85 20 85 A5 DO 4C

EE04 EE07 EEOA

20 90 EF 20 4D D4 4C EE ED

D4 D1 D1

D2

JSR LDA JSR JSR STA JSR STA LDA BNE JMP

buffer pointer zero get byte from buffr track get byte from buffr sector another block? yes close channel

JSR $EF90 JSR $D44D JMP $EDEE

allocate blk in BAM read next block continue

****************************** 20 12 C3 JSR $C312 EEOD LDA $E2 EE10 A5 E2 BPL $EE19 EE12 10 05 LDA #$33 EE14 A9 33 4C C8 C1 JMP $C1C8 EE16 kJD #$01 EE19 29 01 STA $7F EE1B 85 7F JSR $CIOO EEID 20 00 Cl EE20 A5 7F LDA $7F ASL A EE22 OA TAX EE23 AA LDY $027B EE24 AC 7B 02 EE27 CPY $0274 CC 74 02 EE2A EE2C EE2F EE31 EE34 EE36 EE39 EE3B EE3D EE40 EE43

FO B9 95 B9 95 20 A9 85 20 20 4C

1A 00 12 01 13 07 01 80 C6 05 56

02 02 D3 C8 FO EE

read next block

$D475 #$00 $D4C8 $D137 $80 $D137 $81 $80 $EE04 $D227

BEQ LDA STA LDA STA JSR LDA STA JSR JSR JMP

$EE46 $0200,Y $12,X $0201,Y $13,X $D307 #$01 $80 $C8C6 $FOO5 $EE56 344

N command, 'header' get drive number drive number not clear? 33,

'syntax error'

drive number turn LED on drive number times 2 comma position compare with end name format without ID first char of ID save second character close all channels track 1 format disk erase buffer continue as below

ABACUS Software

Anatomy of the 1541

EE46 EE49 EE4B EE4E

20 A6 BD CD

EE51 EE53

FO 03 4C 72 D5

BEQ $EE56 JMP $D572

EE56 EE59 EE5B EE5C EE5D EE5E

20 B7 EE AS F9 A8 OA AA AD

88 FE

JSR LDA TAY ASL TAX LD"\

EE61 EE63 EE66 EE68

95 AE A9 20

99 7A 02 IB 6E C6

STA LDX LDA JSR

$99,X $027A #$lB $C66E

EE6B EE6D EE6F EE72 EE75 EE76 EE77 EE78 EE7A EE7C EE7D EE7F EE81 EE82 EE83 EE85 EE87 EE88 EE8B

AO A6 AD 9D 8A OA

12 7F D5 FE 01 01

LDY LDX LDA STA TXA ASL TAX LDA STA INY LDA STA INY INY LDA STA INY LDA STA

#$12 $7F $FED5 $0101,X

42 DO 7F 01 01 D5 FE

AA

B5 91 C8 B5 91 C8 C8 A9 91 C8 AD 91

12 94 13 94 32 94 D5 FE 94

JSR LDX LDA CMP

$D042 $7F $0101,X $FED5

$EEB7 $F9

load BAM drive number 'A' , marker for 1541 format ok 73, 'cbm dos v2.6 1541' create BAM buffer number

A $FE88

$90, start of disk name buffer ptr to name 27 write filenames in buffer position 18 drive number 'A' , 1541 format

A

times 2

$12,X ($94),Y

ID, first character in buffer

$13,X ($94),Y

and second char in buffer

#$32 ($94),Y

'2 ' in buffer

$FED5 ($94),Y

'A' 1541 format in buffer

345

ABACUS Software

Anatomy of the 1541

EE8D EE8F EE91 EE94 EE96

AO 91 AD 85 20

EE99 EE9B EE9D

A9 01 85 81 20 93 EF

LDA #$01 STA $81 JSR $EF93

EEAO EEA3

20 FF EE 20 05 FO

JSR $EEFF JSR $£'005

EEA6 EEA8 EEAA EEAC EEAF EEB1 EEB4

AO A9 9A 20 C6 20 4C

LDY LDA STA JSR DEC JSR JMP

02 6D 85 FE 80 93 EF

01 FF 6D 64 D4 81 60 D4 94 C1

LDY STA LDA STA JSR

#$02 ($ 6D) , Y $FE85 $80 $EF93

#$01 #$FF ($ 6D) , Y $D464 $81 $D460 $C194

****************************** EEB7 20 D1 FO JSR $FOD1 EEBA AO 00 LDY #$00 EEBC A9 12 LDA #$12 EEBE STA ($ 6D) , Y 91 6D EECO C8 INY EEC1 98 TYA EEC2 STA ($ 6D) , Y 91 6D EEC4 C8 INY EEC5 C8 INY EEC6 INY C8 EEC7 A9 00 LDA #$00 EEC9 STA $6F 85 6F EECB STA $70 85 70 EECD EECF EEDO EED1

85 71 98 4A 4A

STA $71 TYA LSR A LSR A

and at position 2 18 track number mark block as allocated 1 sector number mark block as allocated write BAM pointer $6D/$6E to buffer, erase buffr trk following is 0 write BAM dec sector #, 0 read block prepare disk status create BAM 18 pointer to dir trk 1 pointer to dir sec

3 bytes = 24 bits for sectors byte position divided by 4 track number

346

ABACUS Software

EED2 EED5 EED7 EEDB EED9 EEDA EEDC EEDE EEEO EEE1 EEE3 EEE5 EEE7 EEEB EEE9 EEEB EEED EEEF EEF1

20 4B F2 91 6D CB AA

3B 26 26 26 CA DO B5 91 CB EB EO 90 CO 90 4C

6F 70 71 F6 6F 6D 03 F6 90 D6 75 DO

Anatomy of the 1541

JSR STA INY TAX SEC ROL ROL ROL DEX BNE LDA STA INY INX CPX BCC CPY BCC JMP

$F24B ($ 6D) , Y

get # of sectors and in BAM

$6F $70 $71

create bit model

$EED9 $6F,X ($ 6D) , Y #$03 $EEE3 #$90 $EEC7 $D075

****************************** EEF4 20 93 DF JSR $DF93 TAX EEF7 AA BD 5B 02 LDA $025B,X EEFB #$01 $7F $7F $0251,Y

EEFB EEFD EEFF EF01

29 01 85 7F A4 7F B9 51 02

AND STA LDY LDA

EF04 EF06

DO 01 60

BNE $EF07 RTS

EF07 EF09

A9 00 99 51 02

LDA #$00 STA $0251,Y

EFOC

20 3A EF

JSR $EF3A

EFOF EF11

A5 7F OA

LDA $7F ASL A

347

3 bytes the BAM in buffer

position 144? no, next track calculate # of free blocks write BAM if needed get buffer number command for disk controller isolate drive # BAM-changed flag set? yes

reset BAM-changed flag set buffer pointer for BAM drive number times 2

ABACUS Software

EF12 EF13 EF16 EF17 EF18 EFIA EFID EFIF EF20 EF22 EF24 EF25 EF26 EF28 EF2B EF2D EF2F

48 20 68 18 69 20 A5 48 A9 85 OA OA 85 20 E6 A5 CD

EF32 EF34 EF35 EF37

90 FO 68 85 80 4C 8A D5

A5 FO 01 A5 FO 80 01 80 6D 20 F2 80 80 D7 FE

Anatomy of the 1541

PHA JSR PLA CLC ADC JSR LDA PHA LDA STA ASL ASL STA JSR INC LDA CMP

$FOA5

verify BAM entry

#$01 $FOA5 $80

increment track # verify BAM entry track

#$01 $80 A A $6D $F220 $80 $80 $FED7

BCC $EF24 PLA STA $80 JMP $D58A

****************************** EF3A EF3D EF3E EF41 EF43 EF46 EF48 EF4A EF4C

20 OF Fl AA

20 A6 BD 85 A9 85 60

DF FO F9 EO FE 6E 00 6D

JSR TAX JSR LDX LDA STA LDA STA RTS

$FIOF $FODF $F9 $FEEO,X $6E #$00 $6D

****************************** EF4D EF4F EF52 EF55

A6 BD 8D BD

7F FA 02 72 02 FC 02

LDX LDA STA LDA

$7F $02FA,X $0272 $02FC,X

348

track 1 times 4 verify BAM increment track # and compare with max val + 1 = 36 ok, next track get track # back write BAM to disk set buffer pointer for BAM get 6 for drive 0 allocate buffer buffer number buffer adr, hi byte

10 byte pointer to $6D/$6E get # of free blocks for dir drive number # of blocks, 10 # of blocks, hi

Anatomy or the 1541

ABACUS Software

EF58 EF5B

8D 73 02 60

STA $0273 RTS

****************************** JSR $EFF1 EF5C 20 F1 EF JSR $EFCF EF5F 20 CF EF EF62 EF63

38 DO 22

SEC BNE $EF87

EF65 EF67

B1 6D 1D E9 EF

LDA ($ 6D) , Y ORA $EFE9

EF6A EF6C

91 6D 20 88 EF

STA ($ 6D) , Y JSR $EF88

EF6F EF71 EF72 EF74

A4 6F 18 B1 6D 69 01

LDY $6F CLC LDY ($ 6D) , Y ADC #$01

EF76 EF78 EF7A EF7D EF7F

91 A5 CD FO FE

EF82 EF84

DO 03 FE FC 02

BNE $EF87 INC $02FC,X

EF87

60

RTS

6D 80 85 FE 3B FA 02

STA LDA CMP BEQ INC

($ 6D) , Y $80 $FE85 $EFBA $02FA,X

****************************** EF88 EF8A EF8C EF8F

A6 7F A9 01 9D 51 02 60

LDX $7F LDA #$01 STA $0251,X RTS

349

in buffer for dir mark block as free set buffer pointer clear bit for sector in BAM block already free, then done bit pattern of BAM set bit X, marker for free set flag for BAM changed

increment # of free blocks per track track equal to 18? then skip inc # of free blocks in disk increment number of blocks hi set flag for 'BAM changed' drive number flag

=

1

Anatomy or the 1541

ABACUS Software

****************************** EF90 EF93

20 F1 EF 20 CF EF

JSR $EFF1 JSR $EFCF

EF96

FO 36

BEQ $EFCE

EF98 EF9A EF9D EF9F

B1 5D 91 20

LDA EOR STA JSR

EFA2 EFA4 EFA6 EFA7

A4 6F B1 6D 38 E9 01

LDA $6F LDA ($6D), Y SEC SBC #$01

EFA9 EFAB EFAD EFBO EFB2

91 AS CD FO BD

STA LDA CMP BEQ LDA

EFB5 EFB7

DO 03 DE FC '02

BNE $EFBA DEC $02FC,X

EFBA EFBD

DE FA 02 BD FC 02

DEC $02FA,X LDA $02FC,X

EFCO

DO OC

BNE $EFCE

EFC2 EFC5 EFC7 EFC9 EFCB EFCE

BD C9 BO A9 20 60

LDA CMP BCS LDA JSR RTS

6D E9 EF 6D 88 EF

6D 80 85 FE OB FA 02

FA 02 03 05 72 C7 E6

($ 6D) , Y $EFE9,X ($ 6D) , Y $EF88

($ 6D) , Y $80 $FE85 $EFBD $02FA,X

$02FA,X #$03 $EFCE #$72 $E6C7

350

mark block as allocated set buffer pointer clear bit for sector in BAM already allocated, then done clear bit for block set flag for BAM changed

decrement # of blocks per track track 18? number of free blocks 10 decrement number of free blocks number of free blocks hi more than 255 blocks free? free blocks 10 less than 3? 72,

'disk full'

Anatomy of the 1541

ABACUS Software

****************************** EFCF

20 11 FO

JSR $F011

EFD2 EFD3 EFDS EFD7 EFD8 EFD9 EFDA EFDB EFDD EFDE EFEO EFE2 EFE3 EFES

98 85 AS 4A 4A 4A 38 65 A8 AS 29

B1 6D 3D E9 EF

TYA STA LDA LSR LSR LSR SEC ADC TAY LDA AND TAX LDA AND

EFE8

60

RTS

6F 81

6F 81 07

AA

$6F $81 A A A

erase bit for sector in BAM entry find BAM field for this track sector divide by 8

$6F $81 #$07 ($6D),Y $EFE9,X

byte # in BAM entry sector number bit # in BAM entry byte in BAM clear bit for corresponding sector

****************************** 01 02 04 08 10 20 40 80 EFE9

powers of 2

******************************

write BAM after change

EFF1 EFF3

A9 FF 2C F9 02

LDA #$FF BIT $02F9

EFF6 EFF8 EFFA EFFC EFFE FOOl F004

FO 10 70 A9 8D 4C 60

BEQ BPL BVS LDA STA JMP RTS

OC OA 08 00 F9 02 8A DS

$F004 $F004 $F004 #$00 $02F9 $DS8A

****************************** JSR $EF3A 20 3A EF FOOS F008

AO 00

LDY #$00

351

flag for BAM changed set? no reset flag write block erase BAM buffer pointer $6D/$6E to BAM buffer

ABACUS Software

FOOA FOOB FOOD FOOE F010

Anatomy of the 1541

98 91 6D C8 DO FB 60

TYA STA ($6D) , Y INY BNE $FOOB RTS

erase BAM buffer

****************************** F011 F013 F014 F016 F017 F019 FOIB FOlD FOIF F022

A5 48 A5 48 A6 B5 FO A9 20 20

F025 F027 F028 F029 F02B F02C F02E F03l F033 F034 F036 F039 F03B F03E F040 F042 F045 F046 F047 F048 F04A F04C F04E

85 6F 8A OA 85 70 AA AS 80 DD 9D FO OB E8 86 70 DD 9D FO 03 20 5B A5 70 A6 7F 9D 9B OA OA 18 69 A1 85 6D A9 02 69 00

6F 70 7F FF 05 74 48 E6 OF Fl

02

02 FO 02

LDA PHA LDA PHA LDX LDA BEQ LDA JSR JSR

$6F $70 $7F $FF,X $F022 #$74 $E648 $FlOF

STA $6F TXA ASL A STA $70 TAX LDA $80 CMP $029D,X BEQ $F03E INX STX $70 CMP $029D,X BEQ $F03E JSR $F05B LDA $70 LDX $7F STA $029B,X ASL A ASL A CLC ADC #$Al STA $6D LDA #$02 ADC #$00

352

drive number drive zero? 'drive not ready' get buffer number for BAM

track

drive number times 4

Anatomy of the 1541

ABACUS Software

F050 F052 F054 F055 F057 F058 F05A

85 AO 58 85 68 85 60

6E 00 70 6F

STA LDY PLA STA PLA STA RTS

$6E #$00 $70 $6F

****************************** LDX $6F A6 6F F05B JSR $FODF F05D 20 DF FO LDA $7F A5 7F F060 TAX AA F062 ASL A OA F063 ORA $029B,X 1D 9B 02 F064 EOR #$01 01 49 F067 #$03 AND 29 03 F069 $70 STA 70 85 F06B JSR $FOA5 20 A5 FO F06D LDA $F9 A5 F9 F070 ASL A OA F072 TAX AA F073 LDA $80 A5 80 F074 A ASL OA F076 ASL A OA F077 STA $99,X F078 95 99 F07A F07C F07D F07E F07F F081 F084 F086 F088 F08A F08B F08C F08E F090

A5 OA OA A8 A1 99 A9 81 F6 C8 98 29 DO A6

70

99 A1 02 00 99 99 03 EF 70

LDA ASL ASL TAY LDA STA LDA STA INC INY TYA AND BNE LDX

drive number

buffer number track times 4 equals pointer in BAM field

$70 A A ($99,X) $02A1,X #$00 ($99,X) $99, X #$03 $F07F $70

353

zero in buffer inc buffer pointer

Anatomy of the 1541

ABACUS Software

F092 F094 F097 F09A F09C

A5 9D AD DO 4C

SO 9D 02 F9 02 03 SA D5

F09F FOAl FOA4

09 SO SD F9 02 60

ORA #$SO STA $02F9 RTS

FOA5 FOA6 FOA9 FOAB FOAC FOAE FOBl FOB3 FOB4 FOB5 FOB6 FOB7 FOBB FOBA FOBB FOBC FOBD FOBE FOC1 FOC3 FOC5 FOCS FOCA FOCB FOCC FOCE FODO

AS B9 FO 4S A9 99 A5 OA AA 6S OA OA 95

TAY LDA BEQ PHA LDA STA LDA ASL TAX PLA ASL ASL STA TYA ASL ASL TAY LDA STA LDA STA INC INY TYA AND BNE RTS

FODl FOD3 FOD4

A5 7F OA

9D 02 25 00 9D 02 F9

99

98

OA OA AB B9 Sl A9 99 F6 CS 9B 29 DO 60

AA

Al 02 99 00 Al 02 99 03 EE

LDA STA LDA BNE JMP

$SO $029D,X $02F9 $F09F $D5SA

track

'tlrite block set for BAM write

$029D,Y $FODO #$00 $029D,Y $F9 A

buffer number times 2

A A $99, X A A $02A1,Y ($99,X) #$00 $02Al,Y $99,X

write in buffer inc buffer pointer

#$03 $FOBE

LDA $7F ASL A TAX

drive number

354

ABACUS Software

FOD5 FOD7 FODA FODB FODE

A9 00 9D 9D 02 E8 9D 9D 02 60

Anatomy of the 1541

LDA #$00 STA $029D,X INX STA $029D,X RTS

****************************** FODF B5 A7 LDA $A7,X FOE1 CMP #$FF C9 FF FOE3 DO 25 BNE $F10A TXA FOE5 8A FOE6 48 PHA FOE7 20 8E D2 JSR $D28E FOEA AA TAX FOEB BPL $FOF2 10 05 FOED LDA #$70 A9 70 FOEF 20 C8 C1 JSR $C1C8 FOF2 STX $F9 86 F9 PLA FOF4 68 TAY FOF5 A8 TXA FOF6 8A ORA #$80 FOF7 09 80 STA $00A7,Y FOF9 99 A7 00 FOFC OA ASL A TAX FOFD AA FOFE LDA $FE85 AD 85 FE F101 STA $06,X 95 06 LDA #$00 F103 A9 00 F105 STA $07,X 95 07 F107 4C 86 D5 JMP $D586

F10A FlOC FlOE

29 OF 85 F9 60

AND #$OF STA $F9 RTS

******************************

F10F F111 Fl13 Fl15

A9 06 A6 7F DO 03 18

LDA #$06 LDX $7F BNE $Fl18 CLC

355

find free buffer found 70,

'no channel'

18, directory track save 0 as sector write block buffer number get buffer number for BAM drive number

ABACUS Software

Fl16 Fl18

69 07 60

Anatomy of the 1541

ADC #$07 RTS

****************************** Fl19 F11C F11D

20 OF F1 AA

60

JSR $F10F TAX RTS

****************************** F11E

20 3E DE

JSR $DE3E

F121 F123 F125 F127

A9 85 A9 OD

LDA STA LDA ORA

F12A F12D F12F F130

8D F9 02 A5 6F 48 20 11 FO

STA $02F9 LDA $6F PHA JSR $F011

F133 F134 F136

68 85 6F B1 6D

PLA STA $6F LDA ($ 6D) , Y

F138 F13A F13C F13F F141

DO A5 CD FO 90

BNE LDA CMF BEQ BCC

F143 F145 F147

E6 80 A5 80 CD D7 FE

INC $80 LDA $80 CMP $FED7

F14A

DO E1

BNE $F12D

F14C F14F F150

AE 85 FE CA 86 80

LDX $FE85 DEX STX $80

03 6F 01 F9 02

39 80 85 FE 19 1C

#$03 $6F #$01 $02F9

$F173 $80 $FE85 $F15A $F15F

356

gives 13 for drv 0 buffer # for BAM get buffer number

find and allocate free block get track and sector numbers counter set flag for BAM write save counter find BAM field for this track get counter back number of free blocks in track blocks still free? track 18, dir track? yes, 'disk full' smaller, then next lower track increment track # 36, highest track number plus one no, continue searching this trk 18, directory track decrement save as track #

Anatomy of the 1541

ABACUS Software

F152 F154 F156 F158

A9 85 C6 DO

00 81 6F D3

LDA STA DEC BNE

#$00 $81 $6F $F12D

F15A F15C F15F F161

A9 20 C6 DO

72 C8 C1 80 CA

LDA JSR DEC BNE

#$72 $C1C8 $80 $F12D

F163 F166 F167 F169 F16B F16D F16F

AE E8 86 A9 85 C6 DO

85 FE

LDX INX STX LDA STA DEC BNE

$FE85

F171

FO E7

BEQ $F15A

F173 F175 F176

AS 81 18 65 69

LDA $81 CLC ADC $69

F178 F17A F17C F17F F182 F185

85 AS 20 8D 8D C5

F187 F189 F18A F1BC

BO OC 38 AS 81 ED 4E 02

BCS $F195 SEC LDA $81 SBC $024E

F18F F191 F193

85 81 FO 02 C6 81

STA $81 BEQ $F195 DEC $81

80 00 81 6F BC

81 80 4B F2 4E 02 4D 02 81

STA LDA JSR STA STA CMP

$80 #$00 $81 $6F $F12D

begin with sect #0 decrement counter not yet zero, then continue 72, 'disk full' decrement track # not yet 0, continue in this track 18, directory track increment save as track # begin with sector 0 decrement counter not yet zero, then continue else 'disk full' sector number

$81 $80 $F24B $024E $024D $81

357

plus step width (10) as new number track number get max sector # and save greater than selected sector #? yes else sector number minus maximum sector number save as new sect # zero? else decrement sector # by 1

ABACUS Software

Anatomy of the 1541

F195

20 FA F1

JSR $F1FA

F198 F19A

FO 03 4C 90 EF

BEQ $F19D JMP $EF90

F19D F19F F1A1 F1A4 F1A6

A9 85 20 DO 4C

LDA STA JSR BNE JMP

00 81 FA F1 F4 F5 F1

#$00 $81 $F1FA $F19A $F1F5

****************************** F1A9 FlAB F1B1 F1B3 F1B4 F1B6 F1B8 F1BB F1BC F1BE FICO F1C2

A9 OD A5 48 49 85 AD 38 E5 85

01 F9 02 86

FO 07

LDA ORA LDA PHA LDA STA LDA SEC SBC STA BCC BEQ

F1C4

20 11 FO

JSR $F011

F1C7

B1 6D

LDA ($ 6D) , Y

F1C9 F1CB F1CE F1CF F1D1 F1D3 F1D5

DO AD 18 65 85 E6 CD

BNE LDA CLC ADC STA INC CMP

F1D8 F1DA

90 05 A9 67

01 86 85 FE 86 80

90 09

1B 85 FE 86 80 86 D7 FE

check BAM, find free sector not found? allocate block in BAM sector zero find free sector found? no, 'dir sector' find free sector and allocate

#$01 $02F9 $86 #$01 $86 $FE85

track counter

$86 $80 $FICB $F1CB

minus counter save as track # result no, 20, 'read error' , header block not found byte ready?

Anatomy of the 1541

ABACUS Software

LDA $lCOl

F3CB

AD 01 lC

F3CE F3DO F3Dl F3D3 F3D5

95 E8 EO DO 20

F3D8 F3DA F3DC

AO 04 A9 00 59 16 00

LDY #$04 LDA #$00 EOR $0016,Y

F3DF F3EO F3E2 F3E4

88 10 FA C9 00 DO 38

DEY BPL $F3DC CMP #$00 BNE $F41E

F3E6 F3E8 F3EA F3EC F3EE

A6 A4 95 A5 C9

3E 18 22 45 30

LDX LDA STA LDA CMP

$3E $18 $22,X $45 #$30

F3FO F3F2 F3F4 F3F5 F3F6 F3F9 F3FB F3FD F400 F402

FO A5 OA A8 B9 C5 DO B9 C5 DO

lE 3E

BEQ LDA ASL TAY LDA CMP BNE LDA CMP BNE

$F410 $3E A

F404

4C 23 F4

JMP $F423

F407

C6 4B

DEC $4B

F409 F40B

DO BO A9 02

BNE $F3BB LDA #$02

25 07 F3 97 F4

12 00 16 lE 13 00 17 17

STA INX CPX BNE JSR

$25,X #$07 $F3C8 $F497

$0012,Y $16 $F41B $0013,Y $17 $F41B

367

data byte from disk (block header) save 7 bytes continue reading decode GCR header bytes 4 bytes plus parity form checksum for header parity ok? 27, 'read error', parity error in block header drive number track # of header use as actual trk # command code code for 'preserve header'? preserve header drive number times 2 compare with 1D1 not equal? compare with 1D2 , then 29, 'disk id mismatch' decrement counter for attempts and try again else

ABACUS Software

F40D

20 69 F9

Anatomy of the 1541

JSR $F969

****************************** F410 F412 F414 F416 F418 F41A F41B

A5 85 A5 85 A9 2C A9

OB

LDA $16 STA $12 LDA $17 STA $13 LDA #$01 .BYTE $2C LDA #$OB

F41D F41E F420

2C A9 09 4C 69 F9

.BYTE $2C LDA #$09 JMP $F969

16 12 17 13 01

20, 'read error', block header not found preserve block header IDI and ID2 preserve ok 29, 'disk id mismatch' 27, 'read error' done

******************************

job optimization

F423 F425 F427 F429 F42A F42C

A9 85 AS 18 69 C5

last sector

F42E F430 F432

90 02 E5 43 85 4D

BCC $F432 SBC $43 STA $4D

F434 F436 F438 F43A

A2 86 A2 20

05 3F FF 93 F3

LDX STX LDX JSR

#$05 $3F #$FF $F393

F43D F43F F441 F443 F445 F447

10 85 29 C5 DO AO

44 44 01 3E 3C 00

BPL STA AND CMP BNE LDY

$F483 $44 #$01 $3E $F483 #$00

7F 4C 19 02 43

LDA STA LDA CLC ADC CMP

#$7F $4C $19 #$02 $43

368

plus 2 compare with max sector # smaller? else wrap around store as valid sector buffer number set buffer ptr for disk controller isolate drive # motor running? no

Anatomy or the 1541

ABACUS Software

F449 F44B F44D F44F F451 F453 F455 F457 F458 F45A F45C F45E F45F F461 F463 F465 F466 F468 F46A F46B F460 F46F F471 F473 F475 F477 F478 F47A

B1 C5 DO AS C9 FO AO 38 B1 E5 10 18 65 C4 BO 48 A5 FO 68 C9 90 C9 BO 85 A5

32 40 34 45 60 OC 01

F47C F47E F47F F481 F483 F485 F487 F488 F48A

DO 68 C9 90 C6 10 8A 10 4C

F48D F48F

86 3F 20 93 F3

32 40 03 43 4C 1E 45 14 09 14 OC 10 4C 3F

AA

69 03 85 31 05 06 FO 3F B3 03 9C F9

LOA CMP BNE LOA CMP BEQ LOY SEC LOA SBC BPL CLC AOC CMP BCS PHA LOA BEQ PLA CMP BCC CMP BCS STA LOA TAX AOC STA

($32),Y $40 $F483 $45 #$60 $F461 #$01

BNE PLA CMP BCC DEC BPL TXA BPL JMP

$F483

desired track same as last trk? no command code position head?

($32),Y $40 $F461 $43 $4C $F483 $45 $F47E #$09 $F483 #$OC $F483 $4C $3F #$03 $31

command code read? sector difference less than 9? more than 12 store buffer number plus 3 equals pointer in buffer

#$06 $F473 $3F $F43A

next buffer

$F480 $F99C

to job loop

STX $3F JSR $F393 369

buffer number get buffer number

ABACUS Software

Anatomy of the 1541

F492 F494

AS 45 4C CA F4

LOA $45 JMP $F4CA

F497 F499 F49A F49C F490 F49F F4A1 F4A3 F4A5 F4A7 F4A9

AS 48 AS 48 A9 85 A9 85 A9 85 20

30

$30

24 30 00 31 00 34 E6 F7

LOA PLA LOA PHA LOA STA LOA STA LOA STA JSR

F4AC F4AE F4BO F4B2 F4B4 F4B6 F4B8

AS 85 AS 85 AS 85 20

55 18 54 19 53 1A E6 F7

LOA STA LOA STA LOA STA JSR

$55 $18 $54 $19 $53 $lA $F7E6

F4BB F4BO F4BF F4C1 F4C3 F4C4 F4C6 F4C7 F4C9

AS 85 AS 85 68 85 68 85 60

52 17 53 16

LDA STA LDA STA PLA STA PLA STA RTS

$52 $17 $53 $16

31

31 30

save ptr $30/$31 $31 #$24 $30 #$00 $31 #$00 $34 $F7E6

C9 00 FO 03 4C 6E F5

ptr $30/$31 to $24

decode 5 GCR bytes into 4 normal bytes fourth byte track third byte sector second byte parity decode 5 GCR bytes into 4 normal bytes first byte 102 second byte 101

$31 get ptr $30/$31 $30

****************************** F4CA F4CC F4CE

command code continue checking

CMF #$00 BEQ $F401 JMP $F56E

370

test command code further cmd code for read? yes continue checking command code

Anatomy of the 1541

ABACUS Software

****************************** JSR $F50A 20 OA F5 F4Dl

$F4D4

read find data byte

sector beginning of block ready?

F4D4 F4D6 F4D7 F4DA F4DC F4DD F4DF F4El F4E3 F4E4 F4E7 F4EA F4EB F4ED

50 B8 AD 91 C8 DO AO 50 B8

01 lC 99 00 01 C8 DO F4 20 EO F8

BVC CLV LDA STA INY BNE LDY BVC CLV LDA STA INY BNE JSR

F4FO

AS 38

LDA $38

F4F2

C5 47

CMP $47

F4F4 F4F6

FO 05 A9 04

BEQ $F4FB LDA #$04

F4F8

4C 69 F9

JMP $F969

F4FB

20 E9 F5

JSR $F5E9

F4FE F500 F502

C5 3A FO 03 A9 05

CMP $3A BEQ $F505 LDA #$05

calculate parity of data block match? yes 23, 'read error', parity error in data block

F504 F505 F507

2C A9 01 4C 69 F9

.BYTE $2C LDA #$01 JMP $F969

ok prepare error msg

FE 01 lC 30 F5 BA FE

AD

$lCOI ($30),Y $F4D4 #$BA $F4E1

byte ready?

$lCOI $0100,Y

read bytes from $lBA to $lFF

$F4E1 $F8EO

******************************

F50A

20 10 F5

get data byte and write in buffer 256 times

JSR $F510 371

calculate data from group code data block marker r>ad equal 7, start of data block? yes 22, 'read error', data blk not found error termination

find start of data block read block header

ABACUS Software

F50D

4C 56 F5

Anatomy of the 1541

JMP $F556

****************************** F510 A5 3D LDA $3D F512 OA ASL A F513 AA TAX B5 12 LDA $12,X F514 STA $16 F516 85 16 F518 B5 13 LDA $13,x F51A STA $17 85 17 F51C AO 00 LDY #$00 F51E Bl 32 LDA ($32),Y F520 STA $18 85 18 F522 INY C8 F523 Bl 32 LDA ($32),Y F525 F527

85 19 A9 00

STA $19 LDA #$00

F529 F52B F52D F52F F531 F533

45 45 45 45 85 20

16 17 18 19 lA 34 F9

EOR EOR EOR EOR STA JSR

$16 $17 $18 $19 $lA $F934

F536 F538 F53B F53D F53F F540

A2 20 AO 50 B8

5A 56 F5 00 FE

#$5A $F556 #$00 $F35D

AD 01 lC

LDX JSR LDY BVC CLV LDA

F543

D9 24 00

CMP $0024,Y

F546

DO 06

BNE $F54E

F548 F549 F54B F54D

C8 CO 08 DO FO 60

INY CPY #$08 BNE $F53D RTS

$lCOI

372

wait for next SYNC read block header drive number IDI save ID2 save get track and sector numbers from buffer calculate parity for block header IDI ID2 track sector and save as parity convert block header to GCR code 90 attempts wait for SYNC byte ready? read data from block header compare with saved data not the same, try again 8 bytes read? no

Anatomy of the 1541

ABACUS Software

F54E F54F F551 F553

CA DO E7 A9 02 4C 69 F9

DEX BNE $F538 LDA #$02 JMP $F969

****************************** LDA #$DO A9 DO F556 STA $1805 8D 05 18 F558 LDA #$03 F55B A9 03 F55D F560

2C 05 18 10 F1

F562 F565 F567 F56A F56B F56D

2C 30 AD B8 AO 60

00 1C F6 10 1C 00

BIT $1805 BPL $F553 BIT BMI LDA CLV LDY RTS

$lCOO $FS5D $lC01

C9 10 FO 03 4C 91 F6

20, 'read error', block header not found wait for SYNC 208 start timer error code for SYNC not found time diff>20ms, then 21, 'read error' SYNC signal not yet found? read byte

#$00

****************************** F56E F570 F572

decrement C()t~ . ·r not yet zero?

eMP #$10 BEQ $F575 JMP $F691

****************************** F575

20 E9 F5

JSR $FSE9

FS7B F57A FS7D

8S 3A AD 00 1C 29 10

STA $3A LDA $lCOO AND #$10

FS7F FS81 F583

DO OS A9 08 4C 69 F9

BNE $FS86 LDA #$08 JMP $F969

373

test command code further cmd code for write yes continue checking command code write data block to disk calculate parity for buffer and save read port B isolate bit for 'write protect' not set, ok 26, on'

'write protect

ABACUS Software

SF F7 10 F5 09 FE

Anatomy of the 1541

F5S6 F5S9 F5SC F58E F590 F591

20 20 A2 50 BS CA

F592 F594 F596

00 FA A9 FF SO 03 lC

BNE $F5SE LOA #$FF STA $lC03

F599 F59C F59E

AO OC lC 29 iF 09 CO

LOA $lCOC ANO #$lF ORA #$CO

F5AO F5A3 F5A5 F5A7

SO A9 A2 SO

STA LOA LOX STA

F5AA F5AB F5AO F5AE F:lAF F5Bl F5B3

BS 50 B8 CA 00 AO B9

F5B6 F5BS F5B9 F5BC F5BO F5BF

50 BS 80 CS 00 Bl

F5Cl F5C3 F'5C4 F5C7 F5CS

50 FE B8 SO 01 lC CS 00 F5

OC lC FF 05 01 lC FE FA BB 00 01 FE 01 lC F4 30

JSR JSR LOX BVC CLV OEX

CLV BVC CLV OEX BNE LOY LOA BVC CLV STA INY BNE LOA

$F7SF $F510 #$09 $F5SE

calc. group code find block header byte ready? 9 bytes GAP after skipping block header

$lCOC #$FF #$05 $lCOl $F5AB $F5AB #$BB $0100,Y

port A (write/read head) to output change PCR to output, CB2 10 SYNC write SYNC to disk 5 times byte ready?

bytes $lBB to $lFF to disk

$F5B6 $lCOl $F5B3 ($30),Y

BVC $F5Cl CLV STA $lCOl INY BNE $F5BF 374

write to disk data buffer 256 bytes GCR code write to disk

----

---------------------------------

ABACUS Software

Anatomy of the 1541

FSCA FSCC FSCF

SO FE AD OC 1C 09 EO

BVC $FSCA LDA $lCOC ORA #$EO

FSD1 FSD4 FSD6

8D OC 1C A9 00 8D 03 1C

STA $lCOC LDA #$00 LDA $lC03

FSD9

20 F2 FS

JSR $FSF2

FSDC FSDE FSE1

A4 3F B9 00 00 49 30

LDY $3F LDA $OOOO,Y EOR #$30

FSE3 FSE6

99 00 00 4C B1 F3

STA $OOOO,y JMP $F3B1

****************************** FSE9 F5EB F5EC FSEE F5EF FSF1

A9 00 AS 51 30 C8 DO FB 60

LDA #$00 TAY EOR ($30),Y INY BNE $FSEC RTS

****************************** F5F2 F5F4 F5F6 F5F8 F5FA F5FC F5FE F600

A9 85 85 85 A5 85 A9 8S

F602 F604 F606

85 2F A9 BB 8S 34

00 2E 30 4F 31 4E 01 31

LDA STA STA STA LDA STA LDA STA

#$00 $2E $30 $4F $31 $4E #$01 $31

STA $2F LDA #$BB STA $34 375

byte ready? PCR to input again, CB2 hi port A (read/write head) to input convert GCR data to normal data buffer number convert cmd code 'write' to 'verify' and read block header calculate parity for data buffer generate parity

convert GCR data to normal data

initialize ptr

set pointer to buffer $lBB

ABACUS Software

Anatomy of the 1541

F608 F60A

85 36 20 E6 F7

STA $36 JSR $F7E6

F60D F60F

A5 52 85 38

LDA $52 STA $38

F611 F613 F615

A4 36 A5 53 91 2E

LDY $36 LDA $53 STA ($2E),Y

F617 F618 F61A F61C F61D F61F

C8 A5 91 C8 A5 91

INY LDA STA INY LDA STA

F621 F622 F624

C8 84 36 20 E6 F7

INY STY $36 JSR $F7E6

F627 F629 F62B F62D F62E F630 F632 F633

A4 36 A5 52 91 2E C8 A5 53 91 2E C8 FO OE

LLlY LDA STA INY LDA STA INY BEQ

$36 $52 ($2E),Y

1st decoded byte in buffer

$53 ($2E),Y

2nd decoded byte in buffer

$F643

F635 F637 F639 F63A F63C F63E F63F

A5 91 C8 A5 91 C8 84

LDA STA INY LDA STA INY STY

$54 ($2E),Y

no longer in overflow buffer? 3rd decoded byte in buffer

$55 ($2E),Y

4th decoded byte in buffer

F641

DO El

BNE $F624

F643

A5 54

LDA $54

54 2E 55 2E

54 2E 55 2E 36

convert 5 GCR bytes to 4 normal first byte save as data block marker 2nd byte save as first data byte

$54 ($2E),y

third byte as 2nd data byte

$55 ($2E),Y

fourth byte save as 3rd data byte

$36

376

store buffer ptr convert 5 GCR bytes to 4 normal bytes

inc buffer pointer and save still in overflow buffer $1BB to $lFF? 3rd decoded byte

ABACUS Software

Anatomy of the 1541

F645 F647 F648 F64A F64C F64D F64F

91 C8 A5 91 C8 84 20

30

F652 F654 F656 F658 F659 F65B F65D F65E F660 F662 F663 F665 F667 F668 F66A F66C F66E F670 F672 F674 F676 F678

A4 A5 91 C8 A5 91 C8 A5 91 C8 A5 91 C8 84 CO 90 A9 85 A5 85 AO B1

36 52 30

F67A

91 2E

STA ($2E),Y

F67C F67D F67F F681 F683 F685

88 DO B1 91 A2 BD

DEY BNE LDA STA LDX LDA

55 30 36 E6 F7

53 30 54 30 55 30 36 BB E1 45 2E 31 2F BA 30

F9 30 2E BB 00 01

STA INY LDA STA INY STY JSR LDY LDA STA INY LDA STA INY LDSTA INY LDA STA INY STY CPY BCC LDA STA LDA STA LDY LDA

($30),Y

in buffer

$55 ($30),Y

4th decoded byte in buffer

$36 $F7E6 $36 $52 ($30),Y

save buffer ptr convert 5 GCR bytes to 4 normal bytes load buffer ptr 1st decoded byte in buffer

$53 ($30),Y

2nd decoded byte in buffer

$54 ($30),Y

3rd decoded byte in buffer

$55 ($30),Y

4th decoded byte in buffer

$36 #$BB $F64F #$45 $2E $31 $2F #$BA ($30),Y

save buffer ptr all bytes decoded? not yet, continue 69 bytes

$F678 ($30),Y ($2E),Y #$BB $0100,X

377

copy the bytes in the lower part of the data buffer to the upper part

copy the bytes from the overflow buffer

Anatomy of the 1541

ABACUS Software

F688

91 30

STA ($30),Y

F68A F68B F68C F68E F690

C8 E8 DO F7 86 SO 60

INY INX BNE $F68S STX $SO RTS

****************************** F691

C9 20

CMP #$20

F693 F69S

FO 03 4C CA F6

BEQ $F698 JMP $F6CA

****************************** F698

20 E9 FS

JSR $FSE9

F69B F69D F6AO

8S 3A 20 8F F7 20 OA FS

STA $3A JSR $F78F JSR $FSOA

F6A3 F6AS F6A8 F6AA F6AB

AO B9 SO B8 4D

F6AE

DO 15

BNE $F6CS

F6BO F6Bl F6B3 F6BS F6B7 F6B8

C8 DO Bl SO B8 4D

INY BNE LDA BVC CLV EOR

BB 00 01 FE 01 lC

F2 30 FE 01 lC

LDY LDA BVC CLV EOR

#$BB $0100,Y $F6A8 $lCOI

$F6AS ($30),Y $F6BS $lCOI

378

to the lower part of the data buffer

clear GCR flag continue to test command code command code for 'verify'? yes continue checking command code compare written data with data on disk calculate parity for data buffer and save calculate GCR code find start of data block ptr to GCR buffer data from buffer byte ready? compare with data from disk not equal, then error data from buffer compare with data from disk

Anatomy of the 1541

ABACUS Software

F6BB

DO 08

BNE $F6C5

F6BD F6BE F6CO F6C2

C8 CO FD DO F1 4C 18 F4

INY CPY #$FD BNE $F6B3 JMP $F418

F6C5 F6C7

A9 07 4C 69 F9

LDA #$07 JMP $F969

******************************

F6CA F6CD

20 10 F5 4C 18 F4

JSR $F510 JMP $F418

******************************

LDA #$00 STA $57

F6DO F6D2

A9 00 85 57

F6D4 F6D6 F6D8 F6DA F6DC F6DD

85 A4 A5 29 4A 4A

F6DE F6DF F6EO

4A 4A AA

LSR A LSR A TAX

F6E1 F6E4 F6E5

BD 7F F7 OA OA

LDA $F77F,X ASL A ASL A

F6E6 F6E7 F6E9

OA 85 56 A5 52

ASL A STA $56 LDA $52

5A 34 52 FO

STA LDY LDA AND LSR LSR

$5A $34 $52 #$FO A A

not equal, then 25, 'write error'

error-free termination 25, 'write error' , no match command code for find sector read block header done convert 4 bytes ($52-$55) to 5 GCR bytes ($56-$5A) erase destination area first data byte isolate hi-nibble and rotate to lower nibble as index in GCR code table get GCR code shift bit pattern to pos 3-7 and save get first data byte

379

ABACUS Software

Anatomy of the 1541

F6EB

29 OF

AND #$OF

F6ED

AA

TAX

F6EE F6F1 F6F2

BD 7F F7 6A 66 57

LDA $F77F,X ROR A ROR $57

F6F4 F6F5 F6F7

6A 66 57 29 07

ROR A ROR $57 AND #$07

F6F9 F6FB F6FD F6FE F700

05 91 C8 AS 29

ORA STA INY LDA AND

F702 F703 F704

4A 4A 4A

LSR A LSR A LSR A

F705

4A

F706

AA

LSR A TAX

F707 F70A F70B

BD 7F F7 OA 05 57

LDA $F77F,X ASL A ORA $57

F70D F70F F711 F713

85 57 A5 53 29 OF AA

STA $57 LDA $53 AND #$OF TAX

F714 F717 F718

BD 7F F7 2A 2A

LDA $F77F,X ROL A ROL A

F719 F71A

2A 2A

ROL A ROL A

56 30 53 FO

$56 ($30),Y $53 #$FO

isolate lower nibble as index in GCR code table bring in 2nd destination byte and in lowest 3 bits second data byte in buffer increment buffer isolate upper nibble shift to upper nibble

380

as index in GCR code table get GCR code bring to proper pos in 2nd dest byte 3rd data byte lower nibble as index in GCR table get GCR code shift to required bit position

ABACUS Software

Anatomy of the 1541

F71B

85 58

STA $58

F71D F71E F720 F722 F724 F725 F727 F729 F72A F72B

2A 29 05 91 C8 AS 29 4A 4A 4A

ROL AND ORA STA INY LDA AND LSR LSR LSR

F72C F72D

AA

01 57 30 54 FO

and copy to dest byte

A #$01 $57 ($30),Y $54 #$FO A A A

LSR A TAX

4A 7F F7

$F77F,X

F72E F731 F732 F733 F735 F737 F738 F739 F73B F73D F73F F741

BD 18 6A 05 91 C8 6A 29 85 AS 29 AA

LDA CLC ROR ORA STA INY ROR AND STA LDA AND TAX

F742 F745 F746

BD 7F F7 OA OA

LDA $F77F,X ASL A ASL A

F747 F749 F74B F74D F74F F751 F752

29 05 85 AS 29 4A 4A

58 30 80 59 54 OF

7C 59 59 55 FO

AND ORA STA LDA AND LSR LSR

A $58 ($30),Y A #$80 $59 $54 #$OF

#$7C $59 $59 $55 #$FO A A

381

one bit left in 2nd dest byte in buffer inc buffer ptr 3rd data byte isolate hi-nibble shift to lower nibble as index in GCR code table get GCR code

in buffer inc buffer pointer copy to dest byte 3rd data byte lower nibble as index in GCR table get GCR code shift bits to proper pos copy to dest byte 4th data byte isolate hi-nibble shift to lower nibble

ABACUS Software

F753 F754 F755

LSR A LSR A TAX

4A 4A AA

F756 F759 F75A F75C F750 F75F F760 F762 F764 F766 F768 F769 F76B F760 F76F F771 F773

BO 6A 66 6A 66 6A 66 29 05 91 C8 00 A5 85 A5 29

F774 F777 F779 F77B F77C F77E

BO 05 91 C8 84 60

Anatomy of the 1541

7F F7 5A 5A 5A 03 59 30 04 2F 31 55 OF

AA

7F F7 5A 30 34

as index in GCR code table

LOA ROR ROR ROR ROR ROR ROR ANO ORA STA INY BNE LOA STA LOA ANO TAX

$F77F,X A $5A A $5A A $5A #$03 $59 ($30),Y

LOA ORA STA INY STY RTS

$F77F,X $5A ($30),Y

$F76F $2F $31 $55 #$OF

$34

shift bits

copy to dest byte in buffer inc buffer pointer

4th data byte isolate lwr nibble as index in GCR code table get GCR code in buffer inc buffer pointer and save

****************************** F77F OA OB 12 13 OE OF 16 17 F787 09 19 1A 1B 00 10 1E 15

GCR code table

******************************

convert 260 bytes to 325 bytes group code

F78F F791 F793 F795 F797

A9 85 85 85 A9

00 30 2E 36 BB

LOA STA STA STA LOA

#$00 $30 $2E $36 #$BB

382

initialize pointer

Anatomy of the 1541

ABACUS Software

F799 F79B

85 34 85 50

STA $34 STA $50

F79D F79F F7Al F7A3 F7A5

A5 85 A9 85 A5

LDA STA LDA STA LDA

F7A7

85 52

STA $52

F7A9 F7AB F7AD F7AF F7BO F7B2 F7B4 F7B5 F7B7 F7B9 F7BA F7BC

A4 Bl 85 C8 Bl 85 C8 Bl 85 C8 84 20

36 2E 53

LDY LDA STA INY LDA STA INY LDA STA INY STY JSR

$36 ($2E),Y $53

data block marker (7 ) bring in work storage load buffer ptr 1st data byte bring in work storg

($2E),Y $54

2nd data byte bring in work storg

($2E),Y $55

3rd data byte bring in work storg

$36 $F6DO

F7BF F7Cl F7C3 F7C5 F7C6 F7C8 F7CA F7CC F7CD F7CF F7Dl F7D2 F7D4 F7D6 F7D7 F7D9 F7DB

A4 Bl 85 C8 FO Bl 85 C8 Bl 85 C8 Bl 85 C8 DO A5 85

36 2E 52

LDY LDA STA INY BEQ LDA STA INY LDA STA INY LDA STA INY BNE LDA STA

$36 ($2E),Y $52

store buffer ptr convert 4 bytes to 5 bytes GCR code load buffer ptr first byte bring in work storg

$F7D9 ($2E),Y $53

2nd byte bring in work storg

($2E),Y $54

3rd byte bring in work storg

($2E),Y $55

4th byte bring in work storg

$F7BA $3A $53

convert bytes checksum in work storg

31 2F 01 31 47

2E 54 2E 55 36 DO F6

11 2E 53 2E 54 2E 55 El 3A 53

set pointer to buffer $lBB

$31 $2F #$01 $31 $47

383

ABACUS Software

Anatomy of the 1541

F7DD F7DF

A9 00 85 54

LDA #$00 STA $54

F7E1 F7E3

85 55 4C DO F6

STA $55 JMP $F6DO

****************************** F7E6 F7E8 F7EA F7EC F7ED F7EE F7EF F7Fl F7F3

A4 B1 29 4A 4A 4A 85 Bl 29

34 30 F8

56 30 07

LDY LDA AND LSR LSR LSR STA LDA AND

$34 ($30),Y #$F8 A A A $56 ($30),Y #$07

F7F5 F7F6 F7F7 F7F9 F7FA F7FC

OA OA 85 57 C8 DO 06 A5 4E

ASL ASL STA INY BNE LDA

A A $57

F7FE F800 F802 F804

85 A4 Bl 29

STA LDY LDA AND

$31 $4F ($30),Y #$CO

F806 F807

2A 2A

ROL A ROL A

F808 F809

2A 05 57

ROL A ORA $57

F80B

85 57

STA $57

F80D

Bl 30

LDA ($30),Y

31 4F 30 CO

2 zero bytes in work storage convert 4 bytes to 5 bytes GCR code convert 5 GCR bytes to 4 normal bytes get GCR byte isolate top 5 bits

and save get the lowest 3 bits of the 1st GCR byte shift 2 bits up and save inc buffer pointer

$F802 $4E

if zero then change buffers load 2nd GCR byte and isolate the top two bits bring in bit position 0-1

384

combine with the 2nd isolated GCR pattern and save load 2nd GCR byte

Anatomy of the 1541

ABACUS Software

AND #$3E LSR A

isolate bits 1-5 shift to bit pos 1-4 and save load 2nd GCR byte isolate bit 0

F80F F811

29 3E 4A

F812 F814 F816 F818 F819 F81A F81B F81C F81E F81F F821 F823 F824 F825

85 B1 29 OA OA OA OA 85 C8 B1 29 4A 4A 4A

F826 F827

4A 05 59

LSR A ORA $59

F829 F82B F82D F82F

85 59 B1 30 29 OF OA

STA LDA AND ASL

$59 ($30), Y #$OF A

F830 F832 F833 F835 F837 F838 F839 F83A F83C

85 C8 B1 29 18 2A 2A 29 05

5A

$5A ($30),Y #$80

load 4th GCR byte isolate bit 7

01 5A

STA INY LDA AND CLC ROL ROL AND ORA

load 3rd GCR byte isolate bits 0-3 shift to bit pot 1-4 and store

A A #$01 $5A

F83E F840 F842 F844

85 5A B1 30 29 7C 4A

STA LDA AND LSR

$5A ($30),Y #$7C A

58 30 01

59 30 FO

30 80

STA LDA AND ASL ASL ASL ASL STA INY LDA AND LSR LSR LSR

$58 ($30),Y #$01 A A A A $59 ($30),Y #$FO A A A

shift in bit pos 4 and save load 3rd GCR byte isolate bits 4-7 shift to bit pos 0-4 combine with previous bit and store

385

shift to bit pos 0 isolate bit 0 combine with previous part pattern and store load 4th GCR byte isolate bits 2-6

ABACUS Software

Anatomy of the 1541

F845

4A

LSR A

F846 F848 F84A F84C F84D

85 5B Bl 30 29 03 OA OA

STA LDA AND ASL ASL

$5B ($30),Y #$03 A A

F84E F84F F851 F852 F854

OA 85 5C C8 DO 06 A5 4E

ASL STA INY BNE LDA

A $5C

F856 F858 F85A F85C F85E F85F F860

85 A4 Bl 29 2A 2A 2A

STA LDY LDA AND ROL ROL ROL

$31 $4F ($30), Y #$EO A A A

F861 F862

2A 05 5C

ROL A ORA $5C

F864 F866 F868 F86A F86C F86D F86F

85 Bl 29 85 C8 84 A6

STA LDA AND STA INY STY LDX

F871

BD AO F8

LDA $F8AO,X

F874

A6 57

LDX $57

F876

ID CO F8

ORA $F8CO,X

F879

85 52

STA $52

31 4F 30 EO

5C 30 IF 5D 34 56

$F85A $4E

$5C ($30),Y #$lF $5D $34 $56

386

shift to bit pos 0-4 and store load 4th GCR byte isolate bits 0-1 shift to bit pos 2-4 and store increment pointer if zero, change buffers load 5th GCR byte isolate bits 5-7 bring in bit pos 0-2 combine with last pattern and store load 5th GCR byte isolate bits 0-4 and store store buffer ptr load first GCR pattern get binary code for hi nibble load 2nd GCR pattern combine with binary code for 10 nibble store as first result byte

Anatomy of the 1541

ABACUS Software

F87B

A6 58

LDX $58

F87D

BD AO F8

LDA $F8AO,X

F880

A6 59

LDX $59

F882

1D CO F8

ORA $F8CO,X

F885

85 53

STA $53

F887

A6 5A

LDX $5A

F889

BD AO F8

LDA $F8AO,X

F88C

A6 5B

LDX $5B

F88E

1D CO F8

ORA $F8CO,X

F891

85 54

STA $54

F893

A6 5C

LDX $5C

F895

BD AO F8

LDA $F8AO,X

F898

A6 5D

LDX $5D

F89A

1D CO F8

ORA $F8CO,X

F89D

85 55

STA $55

F89F

60

RTS

****************************** F8AO F8A8 F8BO F8B8

FF FF FF FF

FF 80 FF 90

FF 00 20 AO

FF 10 30 BO

FF FF FF FF

FF CO FO DO

FF 40 60 EO

FF 50 70 FF

387

load 3rd GCR pattern get binary code for hi nibble load 4th GCR pattern combine with binary code for 10 nibble store as 2nd result byte load 5th GCR pattern get binary code for hi nibble load 6th GCR pattern combine with binary code for 10 nibble store as 3rd result byte load 7th GCR pattern get binary code for hi nibble load 8th GCR pattern combine with binary code for 10 nibble store as 4th result byte conversion table GCR code to binary, hi byte $FF means invalid

Anatomy of the 1541

ABACUS Software

****************************** F8CO F8C8 F8DO F8D8

FF FF FF FF

FF 08 FF 09

FF 00 02 OA

FF 01 03 OB

FF FF FF FF

FF OC OF OD

FF 04 06 OE

FF 05 07 FF

****************************** LDA #$00 F8EO A9 00 F8E2 STA $34 85 34 F8E4 STA $2E 85 2E F8E6 STA $36 85 36 LDA #$01 F8E8 A9 01 F8EA STA $4E 85 4E BA 4F 31 2F E6 F7

A9 85 A5 85 20

F8F7 F8F9

A5 52 85 38

LDA $52 STA $38

F8FB F8FD F8FF F901 F902 F904 F906 F907 F909 F90B F90C F90E

A4 A5 91 C8 A5 91 C8 A5 91 C8 84 20

LDY LDA STA INY LDA STA INY LDA STA INY STY JSR

F911 F913 F915

A4 36 A5 52 91 2E

36 53 2E 54 2E 55 2E 36 E6 F7

LDA STA LDA STA JSR

#$BA $4F $31 $2F $F7E6

F8EC F8EE F8FO F8F2 F8F4

conversion table GCR code to binary, 10 byte $FF means invalid

decode 69 GCR bytes

pointer to overflow buffer $lBA

$36 $53 ($2E),Y

decode 5 GCR bytes to $52-$55 1st decoded byte as block header marker load buffer ptr 2nd decoded byte in data buffer

$54 ($2E) ,Y

3rd decoded byte in data buffer

$55 ($2E),Y

4th decoded byte in data buffer

$36 $F7E6

store buffer ptr decode 5 GCR bytes to $52-$55 load buffer ptr 1st decoded byte in data buffer

LDY $36 LDA $52 STA ($2E),Y

388

Anatomy of the 1541

ABACUS Software

F917 F918

C8 FO 11

F91A F91C F91E F91F F921 F923 F924 F926 F928 F929 F92B F92D F92F F931 F933

A5 91 C8 A5 91 C8 A5 91 C8 DO A5 85 A5 85 60

53 2E 54 2E 55 2E E1 53 3A 2F 31

INY BEQ $F92B LDA STA INY LDA STA INY LDA STA INY BNE LDA STA LDA STA RTS

$53 ($2E),Y

all bytes from overflow buffer decoded? 2nd decoded byte in data buffer

$54 ($2E),Y

3rd decoded byte in data buffer

$55 ($2E),Y

4th decoded byte in data buffer

$F90C $53 $3A $2F $31

****************************** 31 2F 00 31 24

F934 F936 F938 F93A F93C

A5 85 A9 85 A9

F93E F940

85 34 A5 39

F942 F944 F946 F948 F94A F94C F94E F950

85 A5 85 A5 85 A5 85 20

F953

A5 17

52 1A 53 19 54 18 55 DO F6

LDA STA LDA STA LDA

$31 $2F #$00 $31 #$24

STA $34 LDA $39 STA LDA STA LDA STA LDA STA JSR

$52 $lA $53 $19 $54 $18 $55 $F6DO

LDA $17

389

2nd data byte store as parity load buffer ptr convert block header to GCR code

ptr to buffer for GCR data constant for data header (8) in work storage parity in work storage sector in work storage track in work storage convert 4 bytes to 5 GCR bytes ID2

ABACUS Software

F955 F957 F959 F95B F95D F95F F961

85 A5 85 A9 85 85 20

F964 F966 F968

A5 2F 85 31 60

52 16 53 00 54 55 DO F6

Anatomy of the 1541

STA LDA STA LDA STA STA JSR

$52 $16 $53 #$00 $54 $55 $F6DO

in work storage ID1 in work storage 2 zero bytes in work storage convert 4 bytes to 5 GCR bytes

LDA $2F STA $31 RTS

****************************** F969 F96B

A4 3F 99 00 00

LDY $3F STA $OOOO,Y

F96E

A5 50

LDA $50

F970 F972

FO 03 20 F2 F5

BEQ $F975 JSR $F5F2

F975 F978 F97A F97B

20 8F F9 A6 49 9A 4C BE F2

JSR $F98F LDX $49 TXS JMP $F2BE

error entry disk controller buffer number error code in command register data still in GCR format? no decode GCR data again reset motor flags get stack ptr back to main loop disk controller

****************************** F97E A9 AO LDA #$AO F980 85 20 STA $20 F982 AD 00 1C LDA $lCOO F985 09 04 ORA #$04 F987 8D 00 1C STA $lCOO F98A A9 3C LDA #$3C F98C 85 48 STA $48 F98E 60 RTS

turn drive motor on

****************************** F98F A6 3E LDX $3E F991 A5 20 LDA $20

turn drv motor off motor flag drive status

390

turn drive motor on motor on drive status

60

Anatomy of the 1541

ABACUS Software

F993 F995 F997 F999 F99B

09 85 A9 85 60

10 20 FF 48

ORA STA LDA STA RTS

set bit 4

#$10 $20 #$FF $48

****************************** 07 1C 05 1C 00 1C 10 1E

LDA STA LDA AND CMP

$lC07 $lC05 $lCOO #$10 $lE

F99C F99F F9A2 F9A5 F9A7

AD 8D AD 29 C5

F9A9

85 1E

STA $lE

F9AB F9AD F9AF

FO 04 A9 01 85 1C

BEQ $F9B1 LDA #$01 STA $lC

F9B1

AD FE 02

LDA $02FE

F9B4 F9B6 F9BB F9BA F9BC F9BF F9C1 F9C3 F9C5 F9C8

FO C9 DO A9 8D FO 85 A9 8D 4C

15 02 07 00 FE 02 OA 4A 02 FE 02 2E FA

BEQ CMP BNE LDA STA BEQ STA LDA STA JMP

$F9CB #$02 $F9C1 #$00 $02FE $F9CB $4A #$02 $02FE $FA2E

****************************** LDX $3E A6 3E F9CB BMI $F9D6 30 07 F9CD LDA $20 A5 20 F9CF TAY A8 F9D1 CMP #$20 C9 20 F9D2 BNE $F9D9 DO 03 F9D4 391

job loop disk controller restart timer write protect? compare with last time store current condition unchanged? set flag for diskette change phase of the stepper motor head on track?

head is over track

move head one half track farther motor running? no bit 5 set? yes

ABACUS Software

F9D6

4C BE FA

Anatomy of the 1541

JMP $FABE

end of disk controller routine

******************************

F9D9 F9DB F9DD F9DE F9EO F9E2 F9E4 F9E6 F9E8 F9EB F9ED F9FO F9F2

C6 DO 98 10 29 85 29 FO AD 29 8D A9 85

F9F4 F9F6 F9F8 F9FA F9FB

A9 85 FO 98 29

F9FD F9FF

DO 03 4C BE FA

BNE $FA02 JMP $FABE

bit 6 set, head movement? yes end of the disk controller routine

FA02

6C 62 00

JMP ($0062)

move head

48 ID 04 7F 20 10 12 00 lC FB 00 lC FF 3E 00 20 DC 40

DEC BNE TYA BPL AND STA AND BEQ LDA AND STA LDA STA LDA STA BEQ TYA AND

$48 $F9FA

decrement counter still running?

$F9E4 #$7F $20 #$10 $F9FA $lCOO #$FB $lCOO #$FF $3E

bit 7 cleared? clear bit 7

#$00 $20 $F9D6 #$40

bit 4 set? no drive motor off set flag for motor off clear flag

****************************** FAOS

AS 4A

LDA #$4A

FA07 FA09

10 05 49 FF

BPL $FAOE EOR #$FF

FAOB FAOC FAOE FAI0 FA12

18 69 CS BO A9

step counter for head transport positive? negative, generate two's complement

CLC ADC CMP BCS LDA

200

01 64 OA 3B

#$01 $64 $FAIC #$3B

392

Anatomy of the 1541

ABACUS Software

FA14 FA16

85 62 A9 FA

STA $62 LDA #$FA

FA18 FAIA

85 63 DO 12

STA $63 BNE $FA2E

pointer $62/$63 to $FA3B

****************************** 5E 5E 61 5E 60 7B 62 FA

SBC SBC STA LDA STA LDA STA LDA

$5E $5E $61 $5E $60 #$7B $62 #$FA

FAIC FAIE FA20 FA22 FA24 FA26 FA28 FA2A

E5 E5 85 A5 85 A9 85 A9

FA2C FA2E

85 63 A5 4A

STA $63 LDA $4A

FA30 FA32 FA34

10 31 E6 4A AE 00 lC

BPL $FA63 INC $4A LDX $lCOO

FA37 FA38

CA 4C 69 FA

DEX JMP $FA69

calculate # of head steps -4 -4

pointer $62/$63 to $FA7B step counter for head transport

****************************** LDA $4A

FA3B

AS 4A

FA3D FA3F FA41 FA43

DO A9 85 A9

EF 4E 62 FA

BNE LDA STA LDA

$FA2E #$4E $62 #$FA

FA45 FA47 FA49 FA4B

85 A9 85 4C

63 05 60 BE FA

STA LDA STA JMP

$63 #$05 $60 $FABE

393

increment bits for stepper motor decrement move stepper motor short distance step counter for head transport not yet zero? pointer $62/$63 to $FA4E counter to 5

ABACUS Software

Anatomy of the 1541

****************************** FA4E C6 60 DEC $60 FASO DO 6C BNE $FABE FAS2 AS 20 LDA $20 FAS4 29 BF AND #$BF FAS6 FAS8 FASA FASC

8S A9 8S A9

FASE FA60

8S 63 4C BE FA

20 OS 62 FA

STA LDA STA LDA

$20 #$OS $62 #$FA

AE E8 8A 29 8S AD 29 OS 8D 4C

00 IC 03 4B 00 IC FC 4B 00 IC BE FA

LDX INX TXA AND STA LDA AND ORA STA JMP

$ICOO #$03 $4B $ICOO #$FC $4B $ICOO $FABE

****************************** FA7B FA7C FA7F FA81 FA84 FA86 FA88 FA8A FA8C FA8E

38 AD ES 8D C6 DO AS 8S A9 8S

07 IC SF OS IC 60 OC SE 60 97 62

clear bit 6, head transport ended

pointer $62/$63 to $FAOS

STA $63 JMP $FABE

****************************** FA63 C6 4A DEC $4A FA6S FA68 :CA69 FA6A FA6C FA6E FA71 FA73 FA7S FA78

load head decrement counter not yet zero?

SEC LDA SBC STA DEC BNE LDA STA STA STA

$IC07 $SF $ICOS $60 $FA94 $SE $60 #$ 97 $62

394

dec step cntr for head transport bits for step motor increment

serve stepper motor

prepare fast head movement timer minus 4 restart decrement counter not yet zero? 4 restart counter

ABACUS Software

Anatomy of the 1541

FA90

A9 FA

LDA #$FA

FA92 FA94

85 63 4C 2E FA

STA $63 JMP $FA2E

****************************** FA97 DEC $61 C6 61 FA99 DO F9 BNE $FA94 FA9B A9 A5 LDA #$A5 STA $62 FA9D 85 62 FA9F A9 FA LDA #$FA FAAI FAA3

85 63 DO EF

07 lC

$lC07

5F 05 lC 60 E2 4E 62 FA

LDA CLC ADC STA DEC BNE LDA STA LDA

63 05 60 OC lC FD

STA LDA STA LDA AND

$63 #$05 $60 $lCOC #$FD

AD 18 65 8D C6 DO A9 85 A9

FAB8 FABA FABC FABE FACI

85 A9 85 AD 29

FAC3 FAC6

8D OC lC 60

fast head movement decrement counter

pointer $62/$63 to $FAA5

STA $63 BNE $FA94

****************************** FAA5 FAA8 FAA9 FAAB FAAE FABO FAB2 FAB4 FAB6

pointer $62/$63 to $FA97

$5F $lC05 $60 $FA94 #$4E $62 #$FA

prepare slow head movement timer plus 2 restart decrement counter not yet zero? pointer $62/$63 to $FA4E counter to 5 clear bit 1, CA2 10, disable SO (Byte Ready)

STA $lCOC RTS

****************************** LDA $51 FAC7 A5 51 BPL $FAF5 10 2A FAC9

395

formatting track number fomatting already in progress?

ABACUS Software

Anatomy of the 1541

FACB FACD

A6 3D A9 60

LDX $3D LDA #$60

FACF FAD 1 FAD3 FAD5

95 A9 95 85

STA LDA STA STA

FAD7 FAD9

A9 A4 85 4A

LDA #$A4 STA $4A

FADB FADE

AD 00 1C 29 FC

LDA $lCOO AND #$FC

FAEO FAE3 FAE5 FAE8 FAEA

8D A9 8D A9 8D

STA LDA STA LDA STA

FAED

A9 OF

LDA #$OF

FAEF FAF2

8D 22 06 4C 9C F9

STA $0622 JMP $F99C

back in job loop

FAF5 FAF7 FAF9 FAFB FAFD

AO D1 FO 91 4C

00 32 OS 32 9C F9

LDY CMP BEQ STA JMP

#$00 ($32),Y $FBOO ($32),Y $F99C

still same track? yes store new track to job loop

FBOO FB03 FB05 FB07 FB09

AD 29 DO A9 4C

00 1C 10 05 08 D3 FD

LDA AND BNE LDA JMP

$lCOO #$10 $FBOC #$08 $FDD3

FBOC

20 A3 FD

20 01 22 51

00 1C OA 20 06 AO 21 06

$20,X #$01 $22,X $51

$lCOO #$OA $0620 #$40 $0621

JSR $FDA3

396

drive number flag for head transport set set dest track running track # for format -92 (46 tracks out) step counter for head transport stepper motor phase on whole track 10 error counter $621/$622 = 4000 initialize track capacity 4000 < capacity < 2*4000 bytes

write protect? no 26, on'

'write protect

erase track, write SYNC 10240 times

ABACUS Software

Anatomy of the 1541

FBOF

20 C3 FD

JSR $FDC3

FB12 FB14 FB17

A9 55 8D 01 1C 20 C3 FD

LDA #$55 STA $lCOI JSR $FDC3

FBIA FB1D FB20 FB22

20 20 A9 OD

FB25 FB28

8D OB 18 A9 62

FB2A FB2D FB2F FB32 FB35 FB37 FB39 FB3C FB3E FB41

8D A9 8D 8D AO A2 2C 30 2C 10

FB43

AD 04 18

LDA $1804

FB46 FB49

2C 00 lC 10 11

BIT $lCOO BPL $FB5C

FB4B

AD OD 18

LDA $180D

FB4E FB4F

OA 10 F5

ASL A BPL $FB46

FB51 FB52 FB54

E8 DO EF C8

INX BNE $FB43 INY

FB55 FB57

DO EC A9 02

BNE $FB43 LDA #$02

00 FE 56 F5 40 OB 18

06 00 07 05 00 00 00 FB 00 FB

18 18 18 lC lC

JSR JSR LDA ORA

$FEOO $F556 #$40 $180B

STA $180B LDA #$62 STA LDA STA STA LDY LDX BIT BMI BIT BPL

$1806 #$00 $1807 $1805 #$00 #$00 $lCOO $FB39 $lCOO $FB3E

397

write SYNC ($621/$622) times $55, no SYNC to write head and ($621/$622) times to disk switch to read wait for SYNC timer 1 free running 98 clock cycles, about 0.1 ms

start timer counter to zero SYNC found? no, wait SYNC found? wait until SYNC range done reset interrupt flag timer SYNC found? SYNC range not done ($55)? interrupt flag register timer flag to bit 7 timer not run out yet? increment counter increment hi-byte of counter overflow, error

ABACUS Software

Anatomy of the 1541

FB59 FB5C

4C D3 FD 86 71

FB5E FB60 FB62 FB64

84 A2 AO AD

72 00 00 04 18

STY LDX LDY LDA

$72 #$00 #$00 $1804

FB67 FB6A FB6C FB6F FB70

2C 30 AD OA 10

00 lC 11 OD 18

BIT BMI LDA ASL BPL

$ICOO $FB7D $180D A $FB67

FB72 FB73 FB75 FB76 FB78 FB7A FB7D FB7E FB7F

E8 DO C8 DO A9 4C 38 8A E5

FB81 FB82 FB84

AA

85 70 98

TAX STA $70 TYA

FB85 FB87 FB88 FB8A

E5 72 A8 85 71 10 OB

SBC $72 TAY STA $71 BPL $FB97

FB8C FB8E FB8F FB90

49 FF A8 8A 49 FF

EOR #$FF TAY TXA EOR #$FF

FB92 FB93 FB94

AA

TAX INX BNE $FB97

F5 EF EC 02 D3 FD 71

E8 DO 01

JMP $FDD3 STX $71

INX BNE INY BNE LDA JMP SEC TXA SBC

formatting error counter = duration of $55 range store counter to 0 again reset timer 1 interrupt flag SYNC found? yes interrupt flag reg timer flag to bit 7 no, wait until timer run out

$FB64

increment counter

$FB64 #$02 $FDD3

overflow, error formatting error

$71

difference between counter ($ 55) and value for SYNC range

398

bring to $70/$71 difference positive?

calculate abs. val of difference

ABACUS Software

Anatomy of the 1541

FB96 FB97 FB98 FB9A

C8 98 DO 04 EO 04

INY TYA BNE $FB9E CPX #$04

FB9C FB9E FBAO FBA2 FBA3 FBA5 F8A8

90 06 26 18 A5 6D 8D

$FBB6 $70 $71

70 21 06 21 06

BCC ASL ROL CLC LDA ADC STA

FBAB FBAD FBBO FBB3

A5 6D 8D 4C

71 22 06 22 06 OC FB

LDA ADC STA JMP

$71 $0622 $0622 $FBOC

FBB6 FBB8 FBBA FBBB FBBE FBCO FBC2 FBC3 FBC4 FBC6 FBC7 FBC9 FBCB FBCE FBCF FBDO FBD3 FBD4

A2 AO B8 AD 10 50 B8 E8 DO C8 DO A9 4C 8A OA 8D 98 2A

00 00

#$00 #$00

counter to zero

$lCOO $FBCE $FBBB

SYNC? no byte ready?

F5

LDX LDY CLV LDA BPL BVC CLV INX BNE INY BNE LDA JMP TXA ASL STA TYA ROL

$FBBB

increment counter

$FBBB #$03 $FDD3

overflow, error formatting error

FBD5 FBD8 FBDA FBDD

8D A9 2D 8D

24 06 BF OB 18 OB 18

18 70 71

00 lC OE 59

F2 03 D3 FD 25 06

STA LDA AND STA

$70 $0621 $0621

difference less than 4 * 0.1 ms? yes double difference

add to output value 4000

repeat until diff < 4 * 0.1 ms

A $0625

double counter

A

and to $624/$625 as track capacity

$0624 #$BF $180B $180B

399

turn timer off

ABACUS Software

Anatomy of the 1541

FBEO FBE2 FBE5

A9 66 8D 26 06 A6 43

LDA #$66 STA $0626 LDX $43

FBE7 FBE9 FBEA FBEB FBEE FBFO FBFl FBF2 FBF3

AO 98 18 6D 90 C8 C8 CA DO

LDY TYA CLC ADC BCC INY INY DEX BNE

FBF5

49 FF

EOR #$FF

FBF7 FBF8 FBFA FBFB FBFE FCOO FC03 FC04 FC05 FC07 FC08 FCOA FCOB FCOE FCI0 FC12 FC15 FC16 FC17 FC19 FCIA FCIC FCIE FCIF FC21

calculate # of all bytes in spaces between blocks

38 69 18 6D BO CE

SEC ADC CLC ADC BCS DEC TAX TYA EOR SEC ADC CLC ADC BPL LDA JMP TAY TXA LDX SEC SBC BCS DEY BMI INX

result in A/X

00 26 06 01

F5

00 25 06 03 24 06

AA

98 49 38 69 18 6D 10 A9 4C A8 8A A2 38 E5 BO 88 30 E8

FF 00 24 06 05 04 D3 FD 00 43 03 03

102 number of sectors in this track

#$00 $0626 $FBFl

$FBEA

#$00 $0625 $FC03 $0624 #$FF #$00 $0624 $FC15 #$04 $FDD3

4 formatting error

#$00 $43 $FC21 $FC24

400

total divided by # of sectors ($43 )

----------------~-------------.----------------------

Anatomy or the 1541

ABACUS Software

FC22 FC24

DO F5 8E 26 06

BNE $FC19 STX $0626

FC27 FC29 FC2B FC2D FC30 FC31 FC33 FC36 FC38 FC3B FC3D FC3F

EO BO A9 4C 18 65 8D A9 8D AO A6 A5

04 05 05 D3 FD

CPX BCS LDA JMP CLC ADC STA LDA STA LDY LDX LDA

#$04 $FC30 #$05 $FDD3

FC41 FC44 FC45 FC46 FC49 FC4C FC4D FC4F FC52 FC53 FC55 FC58 FC59 FC5B FC5E FC5F FC61 FC64 FC65 FC68 FC69 FC6B FC6E FC71 FC74

99 C8 C8 AD 99 C8 A5 99 C8 B5 99 C8 B5 99 C8 A9 99 C8 99 C8 A9 59 59 59 59

00 03

STA INY INY LDA STA INY LDA STA INY LDA STA INY LDA STA INY LDA STA INY STA INY LDA EOR EOR EOR EOR

$0300,Y

counter for sectors counter 10 drive number constant 8, marker for header start in buffer

$0628 $0300,Y

sector number in buffer

$51 $0300,Y

track number in buffer

$13,X $0300,Y

ID 2 in buffer

$12,X $0300,Y

ID 1 in buffer

#$OF $0300,Y

15 in buffer

$0300,Y

15 in buffer

43 27 06 00 28 06 00 3D 39

28 06 00 03 51 00 03 13 00 03 12 00 03 OF 00 03 00 03 00 FA FB FC FD

02 02 02 02

$43 $0627 #$00 $0628 #$00 $3D $39

#$00 $02FA,Y $02FB,Y $02FC,Y $02FD,Y 401

compare # of bytes per gap with minimum value ok 5 format error rem of division plus # of sectors save

generate checksum

ABACUS Software

F9 02 28 06 28 06 43

Anatomy of the 1541

FC77 FC7A FC7D FC80

99 EE AD C5

FC82

90 BB

BCC $FC3F

FC84 FC85 FC86 FC87 FC88 FC8B FC8C FC8E FC90 FC92

98 48 E8 8A 9D E8 DO A9 85 20

FA 03 31 30 FE

TYA PHA INX TXA STA INX BNE LDA STA JSR

FC95 FC96 FC97 FC98 FC9B FC9E FCAO FCA2

68 A8 88 20 20 A9 85 20

E5 FD F5 FD 05 31 E9 F5

PLA TAY DEY JSR JSR LDA STA JSR

FCA5 FCA7

85 3A 20 8F F7

STA $3A JSR $F78F

FCAA FCAC FCAE

A9 00 85 32 20 OE FE

LDA #$00 STA $32 JSR $FEOE

FCB1 FCB3 FCB6 FCB8 FCBA FCBB FCBC

A9 8D A2 50 B8 CA DO

LDA STA LDX BVC CLV DEX BNE

00 05

FF 01 1C 05 FE FA

STA INC LDA CMF

$02F9,Y $0628 $0628 $43

$0500,X $FC88 #$03 $31 $FE30

$FDE5 $FDF5 #$05 $31 $F5E9

#$FF $lC01 #$05 $FCB8 $FCB8

402

and write in buffer increment counter counter compare with # of sectors smaller, then continue

generate data block buffer ptr to $300 convert blk header data to GCR code

copy buffer data copy data in buffer buffer ptr to $500 calculate parity for data buffer and save convert data block to GCR code erase track, write SYNC 10240 times SYNC to write head write SYNC 5 times byte ready?

Anatomy of the 1541

ABACUS Software

FCBE FCCO FCC2 FCC4 FCC5 FCC8 FCCB FCCC FCCO FCCF FC01 FC03 FC04

A2 A4 50 B8 B9 80 C8 CA 00 A2 50 B8 A9

OA 32 FE

FC06 FC09 FCOA FCOC FCOE FCEO FCE2 FCE3 FCE6 FCE7 FCE9 FCEB FCEO FCEE

80 CA DO A9 A2 50 B8 80 CA DO A2 50 B8 BO

01 1C

FCF1 FCF4 FCF5 FCF7 FCF9 FCFB FCFC

80 E8 DO AO 50 B8 B1

FCFE FOOl F002

80 01 1C C8 DO F5

00 03 01 1C F3 09 FE 55

F5 FF 05 FE 01 1C F7 BB FE 00 01 01 1C F4 00 FE 30

LOX LOY BVC CLV LOA STA INY OEX BNE LOX BVC CLV LOA

#$OA $32 $FCC2

10 times buffer pointer byte ready?

$0300,Y $lC01

blk header GCR code write 10 bytes written?

$FCC2 #$09 $FC01

9 times byte ready?

STA OEX BNE LOA LOX BVC CLV STA OEX BNE LOX BVC CLV LOA

$lC01

$55, GAP between block header and data block write

$FC01 #$FF #$05 $FCEO

9 times? SYNC 5 times byte ready?

$lC01

to write head

$FCEO #$BB $FCEB

byte ready?

STA INX BNE LOY BVC CLV LOA

$lC01

area $lBB to $lFF, 69 bytes GCR code write

$FCEB #$00 $FCF9

byte ready?

#$55

$0100,X

($30),Y

STA $lC01 INY BNE $FCF9 403

plus 256 bytes GCR code = 325 bytes write to disk

ABACUS Software

Anatomy of the 1541

FD04 FD06 FD09

A9 55 AE 26 06 50 FE

LDA #$55 LDX $0626 BVC $FD09

FDOB FDOC FDOF FD10 FD12

B8 8D 01 1C CA DO F7 A5 32

CLV STA $lC01 DEX BNE $FD09 LDA $32

FD14 FD15 FD17 FD19 FD1C FD1E FD20 FD21 FD23 FD24 FD27 FD29 FD2C FD2E FD30 FD32 FD34

18 69 85 CE DO 50 B8 50 B8 20 A9 8D A9 85 A9 85 A5

CLC ADC STA DEC BNE BVC CLV BVC CLV JSR LDA STA LDA STA LDA STA LDA

FD36 FD39 FD3C

8D 28 06 20 56 F5 A2 OA

STA $0628 JSR $F556 LDX #$OA

FD3E FD40 FD42 FD43 FD46

AO 50 B8 AD D1

LDY BVC CLV LDA CMP

FD48 FD4A

DO OE C8

OA 32 28 06 93 FE FE 00 FE C8 23 06 00 30 03 31 43

00 FE 01 1C 30

$55 ($626) times GAP between data block and next block header write ptr to block header GCR code

#$OA $32 $0628 $FCB1 $FD1E

plus 10

$FD21

byte ready?

$FEOO #$C8 $0623 #$00 $30 #$03 $31 $43

switch to reading 200 attempts

#$00 $FD40 $lC01 ($30),Y

BNE $FD58 INY

404

decrement sector # write next sector byte ready?

buffer ptr to $300 # of sectors per track wait for SYNC 10 data block header GCR code byte ready? read byte compare with data in buffer not equal, error

Anatomy of the 1541

ABACUS Software

FD4B FD4C FD4E FD4F FD51

CA DO F2 18 A5 30 69 OA

DEX BNE $FD40 CLC LDA $30 ADC #$OA

FD53 FD55

85 30 4C 62 FD

STA $30 JMP $FD62

FD58 FD5B FD5D FD5F

CE DO A9 4C

FD62 FD65

inc ptr by 10 to next block header

$0623 $FD2C #$06 $FDD3

dec attempt counter not yet zero? 6 format error

20 56 F5 AO BB

JSR $F556 LDY #$BB

FD67 FD69 FD6A FD6D

50 FE B8 AD 01 lC D9 00 01

BVC $FD67 CLV LDA $lCOI CMP $0100,Y

wait for SYNC ptr to first 69 GCR bytes byte ready?

FD70 FD72 FD73 FD75 FD77 FD79 FD7A FD7D

DO C8 DO A2 50 B8 AD D9

FD80

DO D6

BNE $FD58

FD82 FD83 FD84 FD86 FD89 FD8B FD8D

C8 CA DO CE DO E6 A5

INY DEX BNE DEC BNE INC LDA

23 06 CF 06 D3 FD

E6 F2 FC FE 01 lC 00 05

Fl 28 06 AE 51 51

DEC BNE LDA JMP

BNE INY BNE LDX BVC CLV LDA CMP

$FD58 $FD67 #$FC $FD77 $lCOI $0500,Y

read byte compare with buffer contents not equal, error next byte byte ready? read byte compare with next 256 GCR bytes not equal, then error next byte

$FD77 $0628 $FD39 $51 $51

405

dec sector counter not yet zero? increment track #

Anatomy or the 1541

ABACUS Software

FD8F

C9 24

CMP #$24

FD91

BO 03

BCS $FD96

FD93

4C 9C F9

JMP

$F99C

FD96 FD98 FD9A FD9C

A9 85 A9 85

LDA STA LDA STA

#$FF $51 #$00 $50

FD9E FDAO

A9 01 4C 69 F9

FF 51 00 50

LDA #$01 JMP $F969

****************************** FDA3 FDA6

AD

OC 1C 29 1F

LDA $lCOC AND #$lF

FDA8 FDAA FDAD FDAF

09 8D A9 8D

CO OC 1C FF 03 1C

ORA STA LDA STA

#$CO $lCOC #$FF $lC03

FDB2 FDB5 FDB7 FDB9 FDBB FDBC FDBD FDBF FDCO FDC2

8D A2 AO 50 B8 88 DO CA DO 60

01 1C 28 00 FE

STA LDX LDY BVC CLV DEY BNE DEX BNE RTS

$lC01 #$28 #$00 $FDB9

FA F7

AE 21 06

AC 22 06 50 FE B8

track number to $FF clear flag for GCR data ok write SYNC 10240 times, erase track switch PCR to writing, CB2 10

port A (read/write head) to output write SYNC to disk 40 byte ready?

$FD89 $FD89

****************************** FDC3 FDC6 FDC9 FDCB

compare with 36, highest track#+l greater, then formatting done continue

LDX $0621 LDY $0622 BVC $FDC9 CLV

406

read/write ($621/$622) times byte ready?

-------------------------~----------------------

ABACUS Software

FDCC FDCD FDCF FDDO FDD2

CA DO FA 88 10 F7 60

Anatomy of the 1541

DEX BNE $FDC9 DEY BPL $FDC9 RTS

****************************** FDD3 FDD6 FDD8

CE 20 06 FO 03 4C 9C F9

DEC $0620 BEQ $FDDB JMP $F99C

FDDB FDDD

AO FF 84 Sl

LDY #$FF STY $Sl

FDDF FDEO

C8 84 SO

INY STY $SO

FDE2

4C 69 F9

JMP $F969

****************************** FDES B9 00 03 LDA $0300,y FDE8 99 4S 03 STA $034S,Y FDEB DEY 88 FDEC FDEE FDF1 FDF4

DO F7 AD 00 03 8D 45 03 60

attempt counter for formatting dec # of attempts zero, then error continue flag for end of formatting flag for erasing GCR data error termination

copy buffer contents

BNE $FDES LDA $0300 STA $0345 RTS

****************************** FDFS FDF7 FDFA

AO 44 B9 BB 01 91 30

LDY #$44 LDA $OlBB,Y STA ($30),Y

FDFC FDFD FDFF

88 10 F8 60

DEY BPL $FDF7 RTS

407

copy data from overflow buffer $lBB to $lFF write in buffer $30/$31

ABACUS Software

Anatomy of the 1541

****************************** FEOO AD OC 1C LDA $lCOC FE03 09 EO ORA #$EO FE05 FE08 FEOA FEOD

8D OC 1C A9 00 8D 03 1C 60

STA $lCOC LDA #$00 STA $lC03 RTS

****************************** FEOE FEll FE13

AD

OC 1C 29 1F 09 co

LDA $lCOC AND #$lF ORA #$CO

FE15 FE18 FE1A

8D OC 1C A9 FF 8D 03 1C

STA $lCOC LDA #$FF STA $lC03

FE1D FE1F

A9 55 8D 01 1C

LDA #$55 STA $lC01

FE22 FE24 FE26 FE28 FE29 FE2A FE2C FE2D FE2F

A2 AO 50 B8 88 DO CA DO 60

LDX LDY BVC CLV DEY BNE DEX BNE RTS

28 00 FE FA F7

A9 85 85 85 A9 85 A5

00 30 2E 36 BB 34 31

LDA STA STA STA LDA STA LDA

switch PCR to reading, CB2 hi port A to input write $55 10240 times switch PCR to writing, CB2 10 port A to output (write head) %01010101, not SYNC to port A (write head)

#$28 #$00 $FE26

byte ready

$FE26

10240 times

$FE26

****************************** FE30 FE32 FE34 FE36 FE38 FE3A FE3C

switch to reading

#$00 $30 $2E $36 #$BB $34 $31

408

convert header in buffr 0 to GCR code

clear byte counter

Anatomy of the 1541

ABACUS Software

2F 01 31 36 2E 52

STA LOA STA LOY LOA STA INY LOA STA INY LOA STA INY LDA STA INY BEQ STY JSR

$2F #$01 $31 $36 ($2E),Y $52

byte counter

($2E),Y $53

second data byte

($2E),Y $54

third data byte

($2E),Y $55

fourth data byte

FE3E FE40 FE42 FE44 FE46 FE48 FE4A FE4B FE4D FE4F FE50 FE52 FE54 FE55 FE57 FE59 FE5A FE5C FE5E

85 A9 85 A4 B1 85 C8 B1 85 C8 B1 85 C8 B1 85 C8 FO 84 02

FE61

4C 44 FE

JMP $FE44

FE64

4C DO F6

JMP $F6DO

2E 53 2E 54 2E 55 08 36 00 F6

$FE64 $36 $F6DO

****************************** PHA 48 FE67 TXA 8A FE68 PHA 48 FE69 TYA FE6A 98 PHA FE6B 48 LOA $1800 AD 00 18 FE6C

02 03 53 E8 00 1C

FE6F FE71 FE73 FE76

29 FO 20 AO

FE79 FE7A

OA 10 03

AND BEQ JSR LOA

#$02 $FE76 $E853 $lCOO

ASL A BPL $FE7F

409

first data byte

done? convert 4 bytes to 5 GCR bytes continue convert 4 bytes to 5 GCR bytes interrupt routine save registers int from serial bus (ATN in)? no serve serial bus interrupt from timer 1? no

ABACUS Software

Anatomy of the 1541

FE7C

20 BO F2

JSR $F2BO

FE7F FE80 FE81 FE82 FE83 FE84

68 A8 68

PLA TAY PLA TAX PLA RTI

AA

68 40

IRQ routine for disk controller restore registers

******************************

FE85 12 FE86 04 FE87 04 FE88 90

constants for disk format 18, track for BAM and directory start of BAM at position 4 4 bytes in BAM for each track $90 = 144, end of BAM, start diskname

******************************

table of command words

FE89 56 49 44 4D 42 55

'v' ,

' I ' ,

'B' ,

'u'

FE8F 50 26 43 52 53 4E ******************************

'P' ,

' & ' ,

'S' ,

'N'

'D' ,

'M' ,

'C' ,

'R' ,

lo-bytes of command addresses

FE95 84 05 C1 F8 1B 5C FE9F 07 A3 FO 88 23 OD ******************************

hi-bytes of command addresses

FEA1 ED DO C8 CA CC CB FEA7 E2 E7 C8 CA C8 EE ****************************** FEAD 51 DD 1C 9E IC

410

bytes for syntax check

Anatomy of the 1541

ABACUS Software

****************************** FEB2 52 57 41 4D

file control methods 'R' , 'w' , 'A' ,

'M'

****************************** FEB6 44 53 50 55 4C

file types 'D' , 'S' , 'P' , 'L'

****************************** FEBB 44 53 50 55 52

names of file types 1st letters 'D' , 'S' , 'P' , 'U' , 'R' 2nd letters 'E' , 'E' , 'R' , , S ' , 'E' 3rd letters 'L' , 'Q' , 'G' , 'R' , 'L'

FECO 45 45 52 53 45 FEC5 4C 51 47 52 4C

'U' ,

****************************** FECA 08 00 00 ****************************** FE CD 3F 7F BF FF ****************************** FED1 11 12 13 15 ****************************** FED5 4A FED6 04 FED7 24 FED8 1F 19 12

****************************** FE DB 01 FF FF 01 00

411

masks for bit cmd # of sectors per track 17, 18, 19, 21

contants for disk format 'A' marker for 1541 format 4 track numbers 36, highest track number + 1 31, 25, 18 tracks with change of number of sectors control bytes for head position

ABACUS Software

Anatomy of the 1541

****************************** FEEO 03 04 05 06 07 07 ****************************** FEE6 3E

addresses of buffers high bytes checksum for ROM $EOOO-$FFFF

****************************** JMP ($0065) FEE7 6C 65 00

from ur command $EB22, to rest w/o RAM/ROM test

******************************

patch for diagnostic routine turn LED on port to output back to diagnostic routine

FEEA FEED FEFO

8D 00 1C 8D 02 1C 4C 7D EA

STA $lCOO STA $lC02 JMP $EA7D

****************************** FEF3 FEF4 FEF6

8A A2 05 CA

TXA LDX #$05 DEX

FEF7 FEF9 FEFA

DO FD AA

BNE $FEF6 TAX RTS

60

****************************** FEFB FE FE

20 AE E9 4C 9C E9

JSR $E9AE JMP $E99C

****************************** FF01 FF04 FF06 FF08 FF09

AD C9 FO 38 E9

02 02 2D 05 2B

LDA CMP BEQ SEC SBC

$0202 #$2D $FFOD #$2B 412

delay loop for serial bus in 1541 mode about 40 microseconds

patch for data output to serial bus CLOCK OUT hi DATA OUT 10 U9 vector, switch 1540/1541 char after "U9" '_'?

yes, then 1540 mode

'+'?

Anatomy of the 1541

ABACUS Software

FFOB

DO DA

BNE $FEE7

FFOD

85 23

STA $23

FFOF

60

RTS

****************************** 03 18 02 00 18 lA

FFI0 FF13 FF15 FF18

8E A9 8D A9

FFIA FFID

8D 02 18 4C A7 EA

STX LDA STA LDA

$1803 #$02 $1800 #$lA

STA $1802 JMP $EAA7

****************************** FF20 FF23 FF25 FF27 FF29 FF2C

AD 29 DO A9 8D 4C

00 18 01 F9 01 05 18 DF E9

LDA AND BNE LDA STA JMP

$1800 #$01 $FF20 #$01 $1805 $E9DF

indirect jump via ($ 65) 0=1541 mode, else 1540 mode patch for reset routine, from $EAA4 port A to output DATA OUT hi port B DATA OUT, CLOCK OUT & ATN A to output data dir port B back to initialization patch for LISTEN to serial bus, from $E9DC wait for DATA IN 10 load timer back to LISTEN routine

****************************** FF2F AA ... FFE1 ... AA ****************************** FFE2 52 53 52 AA ****************************** $C8C6 FFE6 C6 C8 $F98F FFE8 8F F9

413

format routine turn drv motor off

ABACUS Software

Anatomy of the 1541

****************************** USER vectors FFEA 5F CD UA, U1, $CD5F FFEC 97 CD UB, U2, $CD97 FFEE 00 05 UC, U3, $0500 FFFO 03 05 UD, U4, $0503 FFF2 06 05 UE, U5, $0506 FFF4 09 05 UF, U6, $0509 FFF6 OC 05 UG, U7, $050C FFF8 OF 05 UH, U8, $050F FFFA 01 FF UI, U9, $FF01 (NMI vector not used) ************************** FFFC OA EA FFFE 67 FE

414

hardware vectors $EAAO RESET and UJ (U: ) vector $FE67 IRQ vector

ABACUS Software

Anatomy or the 1541

Chapter 4: Programs and Tips for Using the 1541 Disk Drive

4.1 4.1.1

Utility Programs Displaying all File Parameters

Not all of the information about a file can be gathered from the directory. Perhaps you need to know the starting address of a program on the diskette. This starting address is located in the program file itself and not in the directory entry. These and other file parameters can be easily found and displayed by the following program. The number and kind of file parameters are naturally dependent on the file type. A relative file, for instance, has no starting address. The following table presents the parameters displayed by this program. FILE TYPE

PARAMETER DEL

SEQ

PRG

USR

REL

File closed? File protected Allocated blocks Record length Side-sector blocks Data blocks Records Starting address

X X X

X X X

X X X

X X X

X X X X X X X

Free blocks, disk Allocated blocks, disk

X X

X X

X X

X X X

415

X X

ABACUS Software

Anatomy of the 1541

This program is documented in detail so that the serious programmer can get a good overview of the file parameters. In addition, the variables used by the program are explained.

Variables used in the program: Numerical Variables T S FL TY FT LB HB BL RL DT DS SA BF BA BS RC

Track of the actual block of the file entry in the directory Sector of the actual block of the file entry in the directory Flag, set if the file name read from the diskette does not agree with the searched-for file File type of the given file (byte 0 of the entry) nibble of the file type (bits 0-3), contains the actual file type Low byte of the starting address High byte of the starting address Number of allocated blocks in the file Record length of a relative file Track of the first data block of a program file, which contains the starting address Sector of the first data block of a program file Starting address of a program file Number of free blocks on a disk N umber of allocated blocks on a disk Number of side-sector blocks in a relative file Number of records in a relative file

String Variables Name of the file to search for Contains the actual filename from the directory File type Indicates whether the file is closed or not (contains "YES" or "NO") PR$ Indicates whether the file is protected or not (contains "YES" or "NO") RE$ contains CHR$(18), REVERSE ON RA$ contains CHR$(146), REVERSE OFF

F$ FF$ FT$ CL$

416

ABACUS S(lftware

Anatomy of

~he

1541

Program Documentation: Set the color code of the screen Program heacling Asks if the names should be listed out. Sets flag FL to 1 and executes the routine at 280-490. 250 - 270 Input the filename. Asks for new input if the filename if greater than 16 characters. 280 - 490 Reads the file name from the directory and either displays it (FL= 1) or compares it to the desired filename. 500 - 530 Reads byte 0 (file type) of the file entry of the desired file and stores it in TY. Also, the right half-byte is stored in FT. 540 - 590 Checks the file type and saves the text in FT$, and checks for invalid file type. 600 - 610 Checks bit 7 of the file type byte (file closed?) and saves the result in CL$. 620 - 630 Checks bit 6 of the file type byte (file protected?) and saves the result in PR$. 640 - 690 Reads the number of allocated blocks in the file from bytes 28 and 29 of the file entry and saves it in BL. 700 - 730 If it is relative file, the record length is read from byte 21 and saved in RL 740 - 880 If it is a program file, the starting address of the file is taken from the first data block and stored in SA. 890 - 980 Free blocks on the disk are calculated by reading the first byte of the track-marked BAM section and added to BF. The allocated blocks are calculated by BA = 664 - BF 990 -1020 Here the number of side-sector blocks (BS) of a relative file is calculated with the help of the record length (RL) and the number of allocated blocks in the file (RC). 1040-1230 Here the data can be sent to the screen or the printer as one chooses. The file parameters are shown in REVERSE. 1240-1280 The parameters of another file can be output. 110

120 - 200 210 - 230

The program is written for a CBM 64. In spite of this, it can be run without major changes on a VIC 20. Only line 110, where the color of the screen is set, need be changed for the VIC 20.

417

ABACUS Software

Anatomy of the 1541

100 CLR 110 POKE 53280,2:POKE53281,2:PRINTCHR$(158); CHR$(147); 120 PRINT TAB(6);"===========================" 130 PRINT TAB(6);"DISPLAY ALL FILE PARAMETERS" 140 PRINT TAB(6);"===========================" 150 PRINT:PRINT 160 PRINT"WITH THIS PROGRAM, ALL PARAMETERS OF A" 170 PRINT"FILE CAN BE OUTPUT TO THE SCREEN OR TO" 180 PRINT"A PRINTER AT YOUR OPTION." 200 PRINT:PRINT 210 PRINT"LIST FILENAMES (YIN)?" 220 GETX$:IFX$"Y"ANDX$"N"THEN220 230 IF X$="Y"THENFL=1:GOSUB280 240 FL=O 250 INPUT"NAME OF THE FILE: ";F$ 260 IFLEN(F$)4THENPRINT"INVALID FILE TYPE!":GOT0200 600 IFTYAND128THENCL$="YES":GOT0620 610 CL$="NO" 620 IFTYAND64THENPR$="YES":GOT0640 630 PR$="NO" 640 PRINT#15,"B-P";2;X*32+30 650 GET#2,X$:IFX$=""THENX$=CHR$(0) 660 LB=ASC(X$) 670 GET#2,X$:IFX$=""THENX$=CHR$(0) 680 HB=ASC(X$) *256 690 BL=LB+HB 700 IFFT4THEN740 710 PRINT#15,"B-P";2;X*32+23 720 GET#2,X$:IFX$=""THENX$=CHR$(0) 730 RL=ASC (X$) 740 IFFT2THEN890 750 PRINT#15,"B-P";2;X*32+3 760 GET#2,X$:IFX$=""THENX$=CHR$(0) 770 DT=ASC(X$) 780 GET#2,X$:IFX$=""THENX$=CHR$(0) 790 DS=ASC(X$) 8000PEN3,8,3,"#" 810 PRINT#15,"B-R";3;0;DT;DS 820 PRINT#15,"B-P";3;2 830 GET#3,X$:IFX$=""THENX$=CHR$(0) 840 LB=ASC(X$) 850 GET#3,X$:IFX$=""THENX$=CHR$(0) 860 HB=ASC(X$) *256 870 SA=LB+HB 880 CLOSE3 419

ABACUS Software

Anatomy of the 1541

890 PRINT#15,"B-R";2;0;18;0 900 BF=O 910 FORI=4T0140STEP4 920 IFI=72THEN960 930 PRINT#15,"B-P";2;I 940 GET#2,X$:IFX$=""THENX$=CHR$(O) 950 BF=ASC(X$)+BF 960 NEXT 980 BA=664-BF 990 IFFT4THEN1040 1010 BS=BL/121:IFBSINT(BS)THENBS=INT(BS+1) 1020 RC=INT«(BL-BS)*254)/RL) 1040 PRINTCHR$(147);"SCREEN OR PRINTER (Sip)?" 1050 GETX$:IFX$"S"ANDX$"P"THEN1050 1060 RE$=CHR$(18) :RA$=CHR$(146) 1070 IFX$="S"THENOPEN1,3:PRINT#1,CHR$(147) 1080 IFX$="P"THENOPEN1,4 1090 PRINT#l,"FILE PARAMETERS ";RE$;F$;RO$ 1100 PRINT#l,"------------------------------------" 1110 PRINT#l, "FILE TYPE: ";RE$;FT$;RA$: PRINT#l 1120 PRINT#l,"FILE CLOSED: ";RE$;CL$;RA$: PRINT#l 1130 PRINT#l, "FILE PROTECTED: ";RE$;PR$;RA$: PRINT#l 1140 PRINT#l,"ALLOCATED BLOCKS: ";RE$;BL;RA$: PRINT#l 1150 IFFT4THEN1200 1160 PRINT#1,"RECORD LENGTH: ";RE$;RL;RA$: PRINT#1 1170 PRINT#l,"SIDE-SECTOR BLOCKS: ";RE$;BS;RA$: PRINT#l 1180 PRINT#l,"DATA BLOCKS: ";RE$;BL-BS;RA$: PRINT#l 1190 PRINT#l,"RECORDS: ";RE$;RC;RA$: PRINT#1 1200 IFFT=2THENPRINT#1,"START ADDRESS: ";RE$;SA;RA$:PRINT#l 1210 PRINT#1,"FREE BLOCKS (DISK): ";RE$;BF;RA$: PRINT#l

420

ABACUS Software

Anatomy of the 1541

1220 PRINT#l,"ALLOCATED BLOCKS (D) :"iRE$iBAiRA$: PRINT#l 1230 CLOSE1 1240 PRINT"MORE (YIN)?" 1250 CLOSE2:CLOSE15 1260 GETX$:IFX$"Y"ANDX$"N"THEN1260 1270 IFX$="Y"THEN100

421

Anatomy or the 1541

ABACUS Software

4.1.2

Scratch-protect Files - File Protect

As already mentioned, it is possible to protect files on the VIC-1541 diskette and save this information in the directory. A file's type is contained in byte 0 of the file entry. Bit 6 denotes a protected file. If this bit is set to 1, the file can no longer be deleted with the SCRATCH command. But because the DOS has no command to set this bit, an alternative way must be used to protect a file. With the following program, you can:

• • • •

display all files on the disk protect files un protect files erase files

This program can delete protected files as well as unprotected files. If you wish to delete a protected file, you must confirm it. This program is also documented with a variable usage and descriptions so that you can use these techniques in your own programs. This utility program was written for the CBM 64. This version can also be run on the VIC 20. Only line 100 which sets the screen color on the CBM 64 need be changed or ignored. If you value perfect video output, lines 110-230 can also be changed to accommodate the VIC 20's smaller screen size.

List of Variables: DF

Flag, set in the routine "read/search file" if the desired filename is found FL Set if the routine "read/search file" is only to be used for listing files FT Variable for storing the filetype T Track of the current block of the file entry S Sector of the current block of the file entry IT Track, in which the file entry block of the file is found SS Sector, in which the file entry block of the desired file is found FF$ Last filename read from the directory F$ Filename to search for 422

ABACUS Software

Anatomy of the 1541

Program Documentation: 100 110 - 230 240 - 260 270 280 - 350 310 320 350 360 - 600 390 400 410 - 450 460 - 480 490 - 500 510 520 - 550 560 570 - 600 610 - 850 640 650 660 - 700 710 - 730 740 - 750 760 770 - 800 810 820 - 850 860 -1170 890 900 910 - 950 960 - 980 990 1000-1030 1040-1060 1070

Set the screen color Program header and option menu Read the menu choice and call the appropriate subroutine Back to the option menu Subprogram "list all files" Erase screen Set flag FL to list files in the subroutine "read/search file" Reset the flag and jump back Subroutine "protect file" Call subroutine "input filename" Call the subroutine "read/search file" Test if the file is found Read file type and store in FT Test if the file is already protected Protect file (bit 6 to 1) Transfer the file type to the buffer and write the block to disk Close the channel Message "File protected" and jump back Subroutine "unprotect file" Call subroutine "input filename" Call subroutine "read/search file" Test if file is found Read file type and store in FT Test if the file is already unprotected Unprotect the file (bit 6 to 0) Transfer the file type to the buffer and write the block to the disk Close the file End the subroutine Subroutine "erase a file" Call the subroutine "input filename" Call the subroutine "read/search file" Test if the file is found Read the file type and save in FT Test if the file is protected Indicate that the file is protected, with the possibility to erase it anyway Ask if the file should really be erased Bit 6 set back, if protected 423

ABACUS Software

1080-1110 1120 1130 1140-1170 1190-1560 1220 1230-1240 1250-1320

1330 1340-1350 1360-1390 1400-1530 1540-1560

Anatomy of the 1541

Transfer the file type to the buffer and write the block to the disk Initialize the diskette Erase the file End the subroutine Subroutine "read/search file" Open the command and data channels Read directory and set buffer pointer Test if the disk contains a write protect. For this purpose, the directory is written back to the disk unchanged (line 1250). If the disk has a write protect tab on it, the error message 26, WRITE PROTECT ON will occur. Initial values for the track and sector variables are set Read the file entry block and position the buffer pointer to the fIrst byte Read the address of the next file entry block Loop to read filenames. The names are then either listed on the screen or compared to the desired filename, based on the value of flag FL If the variable T (track) contains zero, no more file entry blocks follow and the subroutine ends.

424

ABACUS Software

Anatomy of the 1541

100 POKE 53280,2:POKE53281,2:PRINTCHR$(158); CHR$(147); 110 PRINTTAB(8) ; "=======================" 120 PRINTTAB(8);"ERASE AND PROTECT FILES" 130 PRINTTAB(8);"=======================" 140 PRINT:PRINT 150 PRINT"WITH THIS PROGRAM, FILES CAN BE" 160 PRINT"PROTECTED, ERASED, AND UNPROTECTED" 180 PRINT:PRINT 190 PRINTTAB(6); -1- LIST ALL FILES":PRINT 200 PRINTTAB(6); -2- PROTECT A FILE":PRINT 210 PRINTTAB(6); -3- UNPROTECT A FILE":PRINT 220 PRINTTAB(6); -4- ERASE A FILE":PRINT 230 PRINTTAB(6); -5- END THE PROGRAM":PRINT 240 GETX$:IFX$=" ORVAL(X$)24THENS%(T)=18: IFT>30THENS%(T)=17 550 NEXT 560 FORI=OT07:Z(I)=2I:NEXT:RETURN 570 IFRTHENPRINT#1,"U1 2 O"T;S:SYSIN:RETURN 580 PRINT#l,"B-P 2 0":SYSOUT:PRINT#1,"U2 2 O"T;S:RETURN 590 CLOSE2:PRINT"PLEASE INSERT "A$(R)" DISKETTE." 600 PRINT"AND PRESS RETURN":PRINT:POKE198,0 610 GETA$:IFA$CHR$(13)THEN610 620 PRINT#l,"IO" 6300PEN2,8,2,"#":RETURN 640 FOR I = 828 TO 873 : REM READ MACH LANG PROG 650 READ X : POKE I,X : S=S+X : NEXT 660 DATA 162, 2, 32,198,255,160, 0, 32,207,255, 145,250 670 DATA 200,208,248,230,251, 32,204,255, 96,198, 1,162 680 DATA 2, 32,201,255,160, 0,177,250, 32,210, 255,200 690 DATA 208,248,230,251, 32,204,255,230, 1, 96 700 IF S7312 THEN PRINT "ERROR IN DATA! !":END 710 IN=828:0UT=849:RETURN

431

ABACUS Software

4.1.4

Anatomy of the 1541

Copying Individual Files to another Diskette

The following program permits you to copy individual files from one diskette to another. The files can be programs (PRG), sequential files (SEQ) or user files (USR). Relative files cannot be copied with this program; these can be copied with a BASIC program that reads all data records into a string array and then writes them back again to a new file. In the first pass, the program reads the complete file into the memory of the Commodore 64. Then the destination diskette is inserted and the file opened with the same name. Next the complete file is written on the second disk. The computer has 49 Kbytes for data storage; you can handle up to 196 blocks on the diskette. For reasons of speed, the reading and writing of the data is performed by a machine language program, which is stored in DATA statements. The program is suited for copying sequential files as already mentioned, as well as programs of all kinds; the start address (of a machine language program) is not relevant.

432

ABACUS Software

Anatomy of the 1541

100 REM FILE COPIER PROGRAM C64 110 REM 120 POKE 56,12 : CLR 130 GOSUB 1000 140 INPUT"FILENAME "iN$ 150 PRINT"FILE TYPE "i 160 GETT$:IFT$"S"ANDT$"P"AUDT$"U"THEN160 170 PRINTT$:PRINT 180 PRINT"PLEASE INSERT ORIGINAL DISK" 190 PRINT"AND PRESS A KEY":PRINT 200 GETA$:IFA$=""THEN200 210 OPEN 2,8,2,N$+","+T$ 220 POKE 3,0:POKE 4,12:SYS 866 230 CLOSE 2 240 PRINT"PLEASE INSERT DESTINATION DISK" 250 PRINT"AND PRESS A KEY":PRINT 260 GETA$:IFA$=""THEN260 270 OPEN 2,8,2,N$+","+T$+",W" 280 POKE3,0:POKE4,12:SYS828 290 CLOSE 2:END 1000 FOR I = 828 TO 898 1010 READ X : POKE I,X : S=S+X : NEXT 1020 DATA 162, 2, 32,201,255,198, 1,160, 0, 56, 165, 3 1030 DATA 229, 5,165, 4,229, 6,176, 13,177, 3, 32,210 1040 DATA 255,230, 3,208,236,230, 4,208,232,230, 1, 76 1050 DATA 204,255,162, 2, 32,198,255,160, 0, 32, 207,255 1060 DATA 145, 3,230, 3,208, 2,230, 4, 36,144, 80,241 1070 DATA 165, 3,133, 5,165, 4,133, 6, 76,204, 255 1080 IF S 8634 THEN PRINT "ERROR IN DATA! !":END 1090 RETURN

433

Anatomy of the 1541

ABACUS Software

4.1.5 Reading the Directory from within a Program Sometimes applications programs store user data in a file under a desired name. If you want to use this file again, but you cannot remember the file name, then you have a problem. If this happens, you must exit the program, search for the name in the directory, reload the program and start again. To avoid this, you can include a directory listing routine in your program. If you forget the filename, you can display the directory with a function key, for example, without the need to leave the program. Here is a sample of such a routine: 100 PRINTCHR$(147) i 1100PEN15,8,15,"IO":OPEN2,8,2,"#" 120 T=18:S=1 130 PRINT#15,"B-R"i2iOiT;S 140 PRINT#15,"B-P";2iO 150 GET#2,X$:IFX$=""THENX$=CHR$(0) 160 T=ASC(X$) 170 GET#2,X$:IFX$=""THENX$=CHR$(0) 180 S=ASC(X$) 190 FORX=OT07 200 PRINT#15,"B-P"i2;X*32+5 210 FF$="" 220 FORY=OT015 230 GET#2,X$:IFX$=""THENX$=CHR$(0) 240 IFASC(X$)=160THEN270 250 FF$=FF$+X$ 260 NEXTY 270 IFA=OTHENA=l:PRINTFF$i :GOT0290 280 A=0:PRINTTAB(20) iFF$ 290 NEXTX 300 IFTOTHEN130 310 CLOSE1:CLOSE2 320 PRINT"RETURN FOR MORE" 330 INPUTX$ 340 END:REM IF SUBROUTINE, THEN RETURN HERE

In order to select the filename, the directory is printed on the screen. Should this program be used as a subroutine (called with GOSUB) line 340 must contain RETURN instead of END. We used this routine in the utility programs in sections 4.1.1 and 4.1.2. 434

ABACUS Software

Anatomy of the 1541

4.1.6 Searching for "Hidden" Files Many of our readers are familiar with this situation: Some program or even the entire diskette is "shot to pieces." This can have serious consequences. The work of days or weeks can be destroyed by a wrong command. What error conditions can occur? Often it happens that diskettes are formatted without IDs. This causes all of the files on the disk to be erased. Erased is really the wrong term. Only the first block of the directory is actually erased (track 18, sector 1). The blocks originally allocated by the files are still present. Another example: You overwrote a file with the @-sign. Here it can occur that the disk drive does not execute the corresponding routine properly. The error that usually occurs is that when trying to load one program, another appears instead. The reason is the following: Instead of the starting block of the new program, the starting block of some other program is entered in the directory. The "lost" program is stilI on the diskette, only the first block is unknown. The following program returns all of the data blocks on the disk which could be the starting block of a file. If a program is lost, you can determine its starting block by comparing these blocks with the actual starting blocks. This starting block must then be placed in the directory entry with the disk monitor. NOTE: The following program outputs the blocks in decimal, but the disk monitor works in hexadecimal. With a completely erased disk you must restore the entire file entry in the directory. Since the number of blocks allocated to the file is not known, a 0 appears in the directory. It is advisable to load the reconstructed prograrr once and then save it on another disk.

435

Anatomy of the 1541

ABACUS Software

1 PRINT CHR$(147) "SeaL'ching for Hidden Files" 5 DIMBL(35,20) 6 PRINT"PLEASE INSERT THE DISKETTE AND PRESS RETURN" 7 INPUTX$ 10 OPEN 1,8,15,"10" 20 OPEN 2,8,2,"#" 40 REM READ SECTORS FOR 1=1 TO 4 52 53 READ T1,T2,Sl 54 DATA 1,17,20 55 DATA 18,24,18 56 DATA 25,30,17 57 DATA 31,35,16 60 FOR T=T1 TO T2 65 IF T=18 THEN 140 68 PRINT"track ";t; 70 FOR S=O TO Sl 75 PRINT"sector ";s;"{cursor up}" 80 PRINT#1,"U1";2;0;T;S 85 PRINT#1,"B-P";2;0 90 GET#2,B1$:GET#2,B2$ 100 IF B1$="" THEN B1$=CHR$ (0) 110 IF B2$="" THEN B2$=CHR$(0) 115 TR=ASC(B1$) :SC=ASC(B2$) 120 IF BL(T,S)2 THEN BL(T,S)=3 125 IF TR=O OR TR>35 OR SC>20 THEN BL(T,S)=1:GOT0130 126 BL(TR,SC)=2 130 NEXT S 135 PRINT"{2 cursor ups}" 140 NEXT T 150 :NEXT I 155 CLOSE1:CLOSE2 160 FOR T=l TO 35 170 FOR S=O TO 20 180 IF BL(T,S)=3 THEN PRINT"TRK:";T;" SEC:";S:FI=FI+1 190 NEXT S 195 :NEXT T 200 PRINT"FILES:"FI

436

ABACUS Software

Anatomy

or the

1541

After starting this program the first two bytes of each block ( diskette are read. These two bytes contain the address of the next blo::k the corresponding program. This takes about two minutes. Then the program prints all blocks which could themselves be a data block and to which no other data blocks point. Only these can be the first data blocks of a file. If there are relative files on the disk, however, blocks may be printed which are not the first data blocks of any file. We are not perfect either and there have been situations when this program has helped us a great deal. We hope that it can save you hours and days of work as well.

437

ABACUS Software

Anatomy of the 1541

4.1.7 Changing the Disk Name and the ID The name of the disk and the ill are set when the disk is formatted. Without some help, this name cannot be changed without reformatting the disk. But since both of these data are stored on track 18, sector 0, we can change both of them in a roundabout way. The following program allows you to change the name and ill of the diskette without changing anything else or losing any other data. After starting, the program requires you to insert the appropriate disk and press RETURN. Once this is done, the disk name is displayed. This can be changed if you answer the following question with "Y". The same applies for the ill. Here is the listing: 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 285 290 300

REM ======================= REM CHANGE DISK NAME AND ID REM ======================= PRINT CHR$(147); PRINT"INSERT DISK AND PRESS RETURN" GETX$:IF X$CHR$(13) THEN 150 OPEN 15,8,15 OPEN 2,8,2,"'" PRINT'15,"U1";2;0;18;0 PRINT'15,"B-P";2;144 DN$="" FOR 1=0 TO 15 GET,2,X$ DN$=DN$+X$ NEXT PRINT"NAME: ";DN$ PRINT"CHANGE (YIN)?" GET X$:IF X$"Y" AND X$"N" THEN 270 IF X$="N n THEN 340 F1=1 INPUT "NEW NAME: n;DN$ IF DN$="" OR LEN(DN$»16 THEN PRINT CHR$(145); :GOT0290 310 FOR 1=1 TO 16-LEN(DN$) 320 DN$=DN$+CHR$(160)

438

ABACUS Software

330 340 350 360 370 380 390 400 405 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580

Anatomy of the 1541

NEXT PRINT#15,"B-P";2;162 GET#2,X$:ID$=X$ GET#2,X$:ID$=ID$+X$ PRINT "ID: ";ID$ PRINT"CHANGE (YiN)?" GET X$:IF X$"Y" AND X$"N" THEN 390 IF X$="N" THEN 430 F2=1 ";ID$ INPUT "NEW ID: IF LEN(ID$)2 THEN PRINT CHR$(145);: GOTO 410 IF F1=0 THEN 480 PRINT#15,"B-P";2;144 FOR 1=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT IF F2=0 THEN 520 PRINT#15,"B-P";2;162 PRINT#2,LEFT$(ID$,1); PRINT#2,RIGHT$(ID$,1); IF F1=0 AND F2=0 THEN 570 PRINT#15,"U2";2;0;18;0 PRINT#15,"IO" INPUT#15,E1$,E2$,E3$,E4$ PRINT E1$"-"E2$"-"E3$"-"E4$ CLOSE 2:CLOSE 15 END

The most important lines and their function: Read track 18, sector 0 into the buffer Position the buffer pointer to the disk name Read the name byte-by-byte and build it in DN$ Set flag Fl (new name) Input the new name; check to see that it is not longer than 16 characters 310-330 Pad disk name with SHIff SPACE (160) 340-360 Position to ID and read into ID$ Set flag F2 (new ID) 405 180 190 200-240 285 290-300

439

Anatomy of the 1541

ABACUS Software

410-420 430-470 480-510 520-540 560-580

Input new ID; check if length is 2 bytes Write new name if changed (F1=1) Write new ID if changed (F2=1) Write block back Output the error channel and end program

440

ABACUS Software

Anatomy of the 1541

':;!.1.8 Software Write Protect With this program you can protect your disketes from accidental erasure. This protection can also be removed, of course. If the software protection is enabled, no more programs can be saved on the diskette. The program listing: 100 110 120 13() 140 150 160 170 180 190 200 210 220 230 240 250 260

REM ============================ REM WRITE PROTECT REM ============================ A$=CHR$(233) PRINT CHR$(147); PRINT"WRITE PROTECT ENABLE OR DISABLE (E/D)?" GET X$:IF X$"E" AND X$"D" THEN 160 IF X$="D" THEN A$="A" PRINT"INSERT DISK AND PRESS RETURN" GET X$:IF X$CHR$(13) THEN 190 OPEN 15,8,15 PRINT#15,"IO" OPEN 2,8,2,"#" PRINT#15, "M-W"CHR$(l)CHR$ (l)CHR$ (1)CHR$(65) PRINT#15,"U1 2 0 18 0" PRINT#15,"B-P 2 2" PRINT#2,A$;

270 PRINT#15,"U2 2 0 18 0"

280 CLOSE 2 290 PRINT#15,"IO":CLOSE 15

This program tricks the DOS. The actual protection consists of writing the byte CHR$(233) in the second byte of sector 0 in track 18. This is normally the format id of the disk. But this alone is not sufficient, so we must dig a little deeper into our bag of tricks in order to be able to remove this protection again. Once the protection is enabled, no more write accesses to the disk are possible. But we can also no longer set the byte back to its original value. Here we trick the DOS by changing the format id not on the disk, but first on the buffer in which it is contained. The most important line of this program is line 230.

441

ABACUS Software

Anatomy of the 1541

4.1.9 Invisible Directory With this program you can amaze the '64 owners in your circle of acquaintances. You produce diskettes whose directories are no longer visible. After LOAD"$",8 and LIST, only READY appears! This can also be reversed, of course. The program listing: 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 360 370 380 390 400

REM ========================= REM INVISIBLE DIRECTORY REM ========================= PRINT CHR$(147); PRINT "INSERT DISK AND PRESS RETURN" GET X$:IF X$CHR$(13) THEN 150 PRINT "INVISIBLE OR VISIBLE (I/V)?" GET X$:IF X$"I" AND X$"V" THEN 170 OPEN 15,8,15:0PEN 2,8,2,"#" IF X$="I" THEN 390 REM *** DIRECTORY VISIBLE *** PRINT#15,"U1";2;Oi18;0 PRINT#15,"B-P";2;144 GET#2,X$ IF X$=CHR$(20) THEN 270 PRINT"DIRECTORY IS VISIBLE ... " GO TO 630 PRINT#15,"B-P";2;200:DN$="" FOR 1=1 TO 16 GET#2,X$ DN$=DN$+X$ NEXT PRINT#15,"B-P";2;144 FOR 1=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT PRINT#15,"U2";2;0;18;0 PRINT#15,"IO" GOTO 630 REM *** DIRECTORY INVISIBLE *** PRINT#15,"U1";2;0;18;0

442

ABACUS Software

410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640

Anatomy of the 1541

PRINT#15,"B-P";2;144:DN$="" FOR I=1 TO 16 GET#2,X$ DN$=DN$+X$ NEXT IF LEFT$(DN$,1)CHR$(20) THEN 490 PRINT"DIRECTORY IS INVISIBLE ... " GOTO 630 PRINT#15,"B-P";2;200 FOR I=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT DN$=CHR$(20)+CHR$(20)+CHR$(20) FOR I=1 TO 13 DN$=DN$+CHR$(O) NEXT PRINT#15,"B-P";2;144 FOR I=1 TO 16 PRINT#2,MID$(DN$,I,1); NEXT PRINT#15,"U2";2;0;18;0 PRINT#15,"IO" CLOSE 2:CLOSE 15 END

Because this program is somewhat more complicated than the previous one, we will make only the following comment: The directory is made invisible by overwriting the disk name with the following characters: Three CHR$(20)s and Thirteen CHR$(O)s In order to be able to restore the name later, it is stored in an unused area of block 18/0. This unused area is from position 200 to 215.

443

ABACUS Software

Anatomy of the 1541

4.2 The Utility Programs on the TEST/DEMO Disk There are many 1541 owners who know little about the programs contained on the TestlDemo disk. The main reason is that these programs are largely undocumented. The following descriptions of these programs should help you:

4.2.1

DOS 5.1

The DOS 5.1 simplifies the operation of the VIC-1541 DOS. It can run on the VIC-20 or Commodore 64. To load DOS 5.1 on the VIC-20, give the commands

LOAD"VIC-20 WEDGE",8

RUN

This is the loader for DOS 5.1 for the VIC 20. If you want to use it on the Commodore 64, give the commands:

LOAD"C-64 WEDGE",8

RUN

This loads DOS 5.1 into the CBM 64. What does this DOS 5.1 offer? It allows you to send convenient commands to the 1541 disk drive. If, for example, you want to display the directory on the screen, you use the DOS 5.1 command @$ or >$. This does not erase the program in memory.

445

ABACUS Software

Anatomy of the 1541

The individual commands of the OOS 5.1 Command

Function

@$or>$ @Vor>V @C: ... or>C: ... "fIle or /fIle @or> @N: ... or>N: ... @lor>1 @R: ... or>R: .. . @S: ... or>S: .. . @#nor>#n

Display the directory Same function as "V ALIDATE" Copy files (COPY) Load program Read and display error message Format a diskette Intitialize the disk Rename a file (RENAME) Erase a file (SCRATCH) Change disk device to n

4.2.2

COPY/ALL

With the program COPY/ALL, files can be copied between disk drives with different addresses. A drive must be changed from device address 8 with the program DISK ADDR CHANGE before this can occur. After starting the program, the message: disk copy all

jim butterfield

from unit? 8

appears on the screen. Here you give the device address of the disk drive from which you wish to get the files. If this address is 8, just press RETURN. After this you give the corresponding drive number of this unit (always 0 for single drives). In this manner you also give the device address of the destination drive. Once this has occurred, the program asks want to new the output disk ?n

You are being asked if the destination diskette should be formatted. You answer with "y" (yes) or "n" (no). Then you can choose the files you want to copy with the wildcard (*). If all files are supposed to be copied, just give the asterisk. 446

ABACUS Software

Anatomy of the 1541

Now the program gives the message

hold down 'y' or 'n' key to select The program displays the files on the original disk, which you can select with the "y" key (yes) or "n" (no). The files by which you pressed "y" will be copied. If, during the copying process, asterisks (***) appear behind the files, it means that an error has occurred. If there is not enough room on the destination disk, "*** output disk full" and "do you have a new one" appears. The remaining files can be put on another formatted diskette. To do this, answer "y" when ready. At the the conclusion of the copying process, the number of free blocks on the destination disk is displayed.

4.2.3

DISK ADDR CHANGE

This program allows you to change the device address of a disk drive. After starting the program, tum off all drives except for the one you wish to change. Now enter the old and new device addresses. After this, the address is changed and the other drive can be turned back on. The following drives can be changed with this program:

1541 2031 2040 4040 4040 8050 8050 8250

DOS V2.6 DOS V2.6 DOS Vl.1 DOS V2.1 DOS V2.7 DOS V2.5 DOS V2.7 DOS V2.7

447

ABACUS Software

4.2.4

Anatomy of the 1541

DIR

This is a small utility program with the following options: d - display the directory on the screen > - With this character, a disk command can be given in shortened form (for example, >N:TEST,KN to format a diskette) q - exit the program s - display the error channel These possibilities are also found in DOS 5.1, along with other commands.

4.2.5

VIEW BAM

With this utility program you can view the usage of diskette blocks on the screen. This table displays the sectors in columns and the tracks in rows. Crosses indicate free blocks and reverse crosses indicate allocated blocks. "n/a" means that these blocks do not exist on the track. After outputting the table, the diskette name and the number of free blocks are displayed.

4.2.6

CHECK DISK

The utility program CHECK DISK tests every block on the diskette by writing to and reading from it. The current block and the total number of tested blocks is displayed on the screen. WARNING! THIS PROGRAM DESTROYS (FORMATS) THE DISKETTE!

448

ABACUS Software

4.2.7

Anatomy of the 1541

DISPLAY T&S

If you are interested in the construction of the individual blocks of the disk and want to display these on the screen, this utility program will help you. After starting the program you give the desired track and sector. The contents of this block will then be sent to the printer or screen. The DISK-MONITOR contained in this book is easier to use, because it allows you to change blocks and save them again.

4.2.8

PERFORMANCE TEST

This program makes it possible to test the mechanics of the VIC-1541 disk drive. To accomplish this, all the access commands are executed in the following order: 1. The disk is formatted 2. A file is opened for reading 3. Data are written to this file 4. The file is closed again 5. This file is opened for reading 6. The data are read 7. The file is closed again 8. The file is erased 9. Track 35 is written 10. Track 1 is written 11. Track 35 is read 12. Track 1 is read After each access of the disk the error channel is displayed. In this manner, it can be established which access of the disk is not executed properly. When using this program, use only diskettes containing no important data because the entire diskette is erased during the testing.

449

ABACUS Software

Anatomy of the 1541

4.3

BASIC Extensions and Programs for the 1541

4.3.1

Input strings of desired length from the disk

Reading data from the disk with the INPUT# statement has one major disadvantage--only data items having fewer than 88 characters can be read. This is because the input buffer of the computer is limited. In addition, not all characters can be read with the INPUT# statement. If a record contains a comma or colon, BASIC views it as a separating character and the remainder of the input is assigned to the next variable. If the INPUT# statement has only one variable, the remainder is ignored and the next INPUT# statement continues reading past the next carriage return (CHR$(13)). The alternative is to read the input with a GET# statement but this results in much slower input. To avoid these disadvantages, we can use a small machine language routine. We will change the INPUT# statement so that we can specify the number of characters to be read. To distinguish it from the normal INPUT# statement, we name the command INPUT*. The syntax looks like this:

INPUT* Ifn, len, var Lfn is the logical file number of the previously OPENed file, len is the number of characters to be read, and var is the string variable into which the characters are to be read. A program excerpt might look like this: 100 110

OPEN 2,8,2, "FILE" INPUT* 2,100,A$

This reads a string of 100 characters from the opened file into A$. This procedure is especially suited for relative files, because a complete record can be read with one command after positioning the record pointer. The partitioning of a record into fields can be accomplished with the MID$ function. An elegant method of creating records is described in the next section.

451

ABACUS Software

Anatomy of the 1541

With this procedure it is no longer necessary to end a record with a carriage return. You can especially make use of the maximum record length with relative flles: 100 OPEN 1,8,15 110 OPEN 2,8,2, "REL-FILE,L, "+CHR$ (20) 120 PRINT#l, "P"+CHR$(2)+CHR$(0)+ CHR$(l)+CHR$(l) 130 PRINT#2, "12345678901234567890"; 140 PRINT#l, "P"+CHR$(2)+CHR$(0)+ CHR$(l)+CHR$(l) 150 INPUT* 2,20,A$ 160 PRINT A$ 12345678901234567890

Here is the assembler listing for the machine language program as well as a loader program in BASIC for the Commodore 64 and VIC 20. The program resides in the cassette buffer. 110:

033C ; INPUT* LFN,LEN,A$

150: 160: 170: 180: 190:

033C 033C 033C 033C 033C

210: 220: 380: 390: 400: 410: 420: 430: 440: 450: 460 : 470:

033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C 033C

INPUT STAR BASVEC CHRGET CHRGOT

$85 $AC $308 $73 CHRGET + 6

; C64 VERSION CHKIN BASIN CHKCOM INTER EXECOLD INPUTOLD FINDVAR STRRES FRESTR GETBYT

452

=

$E11E $E112 $AEFD $A7AE $A7E7 $ABBF $B08B $B475 $B6A3 $B79E

Anatomy of the 1541

ABACUS Software

VIC 20 VERSION 240: 250: 260: 270: 280: 290: 300: 310: 320: 330:

$EIIB $EI0F $CEFD $C7AE $C7E7 $CBBF $D08B

CHKIN BASIN CHKCOM INTER EXECOLD INPUTOLD FINDVAR STRRES FRESTR GETBYT

033C 033C 033C 033C 033C 033C 033C 033C 033C 033C

;

$D475

$D6A3 $D79E

COMMON LABELS $49 $FFCC $61

VARADR CLRCH PARA

490: 500: 510:

033C 033C 033C

530: 540: 550: 560: 570: 580:

033C 033C 033E 0340 0343 0346

A9 AO 8D 8C 60

47 INIT 03 08 03 09 03

*= LDA LDY STA STY RTS

828 #TEST BASVEC BASVEC+l

600: 610: 620: 630: 640:

0347 034A 034C 034E 0351

20 C9 FO 20 4C

73 00 TEST 85 06 79 00 E7 A7

JSR CMP BEQ JSR JMP

650: 660:

0354 20 73 00 FOUND 0357 C9 AC

670: 680: 680: 690:

0359 035B 035E 0361

CHRGET #INPUT FOUND CHRGOT EXECOLD ; TO THE OLD ROUTINE CHRGET ; NEW #STAR INPUT ROUTINE OKSTAR INPUTOLD INTER GETBYT-3 ; GET FILE NUMBER

FO 20 4C 20

06 BF AB AE A7 9B B7 OKS TAR

453

JSR CMP BEQ JSR JMP JSR

ABACUS Software

700: 710: 720:

Anatomy of the 1541

0364 20 1E E1 0367 20 FD AE 036A 20 9E B7

730: 730:

036D 8A 036E 48

740: 750:

036F 20 FD AE 0372 20 8B BO

760: 760: 770: 780:

0375 0377 0379 037C

790:

037D 20 75 B4

800: 810: 820: 830: 840: 850: 860: 870: 880: 890: 900: 910: 910:

0380 0382 0385 0387 0388 038A 038B 038E 0390 0391 0393 0395 0398

JSR JSR JSR TXA PHA

85 49 84 4A 20 A3 B6 68

AO B9 91 88 10 C8 20 91 C8 C4 DO 20 4C

02 61 00 STORE 49 F8 12 E1 FETCH 62 61 F6 CC FF AE A7

454

CHKIN CHKCOM GETBYT

;

LENGTH

STORE JSR CHKCOM JSR FINDVAR SEARCH FOR VARIABLE STA VARADR STY VARADR+1 JSR FRESTR PLA LENGTH JSR STRRES RESERVE PLACE FOR STRING LDY #2 LDA PARA,Y STA (VARADR) ,Y DEY BPL STORE INY y=o JSR BASIN STA (PARA +1), Y INY CPY PARA BNE FETCH JSR CLRCH JMP INTER iTO INTERPRETER LOOP

Anatomy of the 1541

ABACUS Softwa re

Here are the BASIC programs for entering the machine language program for the INPUT* statement. INPUT* , 64 Version 100 FOR I = 828 TO 922 S=S+ X: NEXT 110 READ X : POKE I,X 3, 9, 3,140 , 8, , 3,141 0, 71,16 120 DATA 169, 96, 32 0, 76, 6, 32,12 1, 0,201 ,133, 240, 130 DATA 115, 231,1 67 6, 32,19 1,171 , 0,201 ,172, 240, 140 DATA 32,11 5, 76,17 4 , 150 DATA 167, 32,15 5,183 , 32, 30,22 5, 32,25 3,174 32,15 8 160 DATA 183,1 38, 72, 32,25 3,174 , 32,13 9,176 ,133, 73,13 2 2, 170 DATA 74, 32,16 3,182 ,104, 32,11 7,180 ,160, 185, 97 0,145 , 73,13 6, 16,24 8,200 , 32, 18,22 5, 180 DATA 145, 98 190 DATA 200,1 96, 97,20 8,246 , 32,20 4,255 , 76, 174,1 67 200 IF S 11096 THEN PRINT "ERROR IN DAT A!!" END 210 SYS 828 : PRINT "OK." INPUT* , VIC 20 Version 100 FOR I = 828 TO 922 S=S+X : NEXT 110 READ X : POKE I, X 3, 9, 3,140 , 8, 3,141 , 120 DATA 169, 71,16 0, 96, 32 0, 76, 6, 32,12 1, 0,201 ,133, 240, 115, DATA 130 231,1 99 6, 32,19 1,203 , 0,201 ,172, 240, 32,11 5, DATA 140 76,17 4 455

ABACUS Softwa re

Anatomy of the 1541

150 DATA 199, 32,15 5,215 , 32, 27,22 5, 32,25 3,206 , 32,15 8 160 DATA 215,1 38, 72, 32,25 3,206 , 32,13 9,208 ,133, 73,13 2 170 DATA 74, 32,16 3,214 ,104, 32,11 7,212 ,160, 2, 185, 97 180 DATA 0,145 , 73,13 6, 16,24 8,200 , 32, 15,22 5, 145, 98 190 DATA 200,1 96, 97,20 8,246 , 32,20 4,255 , 76, 174,1 99 200 IF S 11442 THEN PRINT "ERROR IN DATA ' '" END 210 SYS 828 : PRINT "OK."

4.3.2 Easy Prepa ration of Data Records If you have worked with relative files before, you know that a definit e record length must be established. This record is usually divide d into several fields which likewise begin at a definite position within the record , and have a set length.

If you create a new record, a separate INPUT statement is genera used for each field. Before the complete record can be written, it must lly assembled properly. Each field must be checked for proper length. If be longer than then the planne d length of the corresponding data field, it is the remainder must be truncated to the proper length. Here are two new BASIC commands that are excellently suited to this task. These new commands are written in machine language and are initialized with a SYS command. You can then use them as any other BASIC commands. The first comm and has the name !STR$ and serves to create a string with the length of the data record. A$ = !STR$(lOO,If If)

creates a string with 100 blanks and puts it in the variable A$.

456

ABACUS Software

Anatomy of the 1541

The next command places our data field within the previously created string. For example, if you want to assign the variable N$ containing the last name as a field of 25 characters at position 1 in the string A$, our new command looks like this:

MID$ (A$,1,25) = N$ Here the MID$ command is used as a so-called pseudo-variable on the left side of the assignment statement. What happens here is as follows: The variable N$ replaces the first 25 characters of A$. If the variable N$ is longer than 25 characters, only the first 25 characters are replaced and the rest are disregarded. If N$ is shorter than 25 characters, only as many characters are replaced as N$ contains. The original characters in A$ remain (blanks, in our case). That is exactly as we wanted. Now we can program the following:

200 210 220 230 240 250 260 270 280 290 300 310 320 330

INPUT "LAST NAME INPUT "FIRST NAME INPUT "STREET INPUT "CITY INPUT "STATE INPUT "ZIP CODE A$ = !STR$ (92, " MID$ (A$,1,25) = MID$ (A$,26,20) = MID$ (A$,46,20) = MID$ (A$, 66,15) = MID$ (A$,81,2) = MID$ (A$,83,9) = PRINT#2, A$

; ; ; ; ; ;

") L$ F$ S$ C$ T$ Z$

457

L$ F$ S$ C$ T$ Z$

ABACUS Software

Anatomy of the 1541

Here is the machine language program for the Commodore 64 135: 140: 150: 160: 170: 180: 190: 200: 205: 210: 220: 226: 229: 230: 231: 232: 233: 234: 235: 236 : 237: 238: 240: 241: 242: 243: 245: 248: 248: 248: 248: 248: 250: 250: 250: 251: 251: 251: 251:

C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C800 C802 C804 C807 C80A C800 C80F C811 C814 C816 C818 C81B

*= CHKOPEN CHKCLOSE CHKCOM FRMEVL CHKSTR FRESTR YFAC CHRGET CHRGOT GETBYT INTEGER OESCRPT STRAOR ADR2 ADR1 LEN1 LEN2 NUMBER START TYPFLAG STRCODE ILLQUAN SYNTAX POSCOOE VECTOR TEMP A9 AO 8D 8C 4C A9 85 20 C9 FO 20 4C

00 C8 OA OB 6B 00 00 73 21 06 79 80

03 03 C8 TESTIN 00 00 AE 458

LOA LOY STA STY JMP LOA STA JSR CMP BEQ JSR JMP

$C800 $AEFA $AEF7 $AEFO $A09E $A08F $B6A3 $B3A2 $73 CHRGET+6 $B79B $B1AA $64 $62 $FB $FB+2 3 4 5 6 13 $C4 $B248 $AF08 $B9 $30A LEN1 #TESTIN VECTOR VECTOR+1 MIOSTR #0 TYPFLAG CHRGET #"!" TEST2 CHRGOT $AE80

~---

----------------~-

--

Anatomy of the 1541

ABACUS Software

252: 252: 252: 253:

C81E C821 C823 C825

20 C9 FO 4C

JSR CMP BEQ JMP

73 00 TEST2 C4 03 08 AF ; ;

CHRGET #STRCODE STRING SYNTAX

STRING$ FUNCTION

900: 900:

C828 20 73 00 STRING C82B 20 FA AE

JSR JSR

CHRGET CHKOPEN

910: 920: 920:

C82E 20 9E B7 C831 8A C832 48

JSR TXA PHA

GETBYT+3

930: 940: 950: 960:

C833 C836 C839 C83B

FD AE 9E AD OD OC

JSR JSR BIT BMI

970: 980:

C83D 20 AA B1 C840 A5 64

JSR LDA

990: 1000 :

C842 DO 24 C844 A5 65

BNE LDA

1010 : 1020:

C846 4C 52 C8 C849 20 82 B7 STR

JMP JSR

1030 :

C84C FO 1A

BEQ

1040 : 1050 :

C84E AO 00 C850 B1 22

LDY LDA

1060 : 1070 :

C852 85 03 C854 68

1080 : 1090 : 1100 :

20 20 24 30

STA PLA

STR2

STORE LENGTH CHKCOM FRMEVL TYPFLAG STR STRING INTEGER ;HIGH DESCRPT BYTE ;>255 ILL DESCRPT+1 ; LOW BYTE,LENGTH STR2 $B782 SETSTR TYPFLAG TO NUMERIC ILL LENGTH 0 #0 ($22) ,Y FIRST CHAR TEMP LENGTH

C855 20 7D B4

JSR

$B47D

C858 A8 C859 FO 07

TAY BEQ

STR3

459

;OPEN PAREN

FRESTR

ABACUS Software

Anatomy of the 1541

1110: 1120: 1120:

C85B A5 03 C85D 88 C85E 91 62

LDA DEY STA

1130: 1140:

C860 DO FB C862 20 CA B4 STR3

BNE JSR

1150: 1160:

C865 4C F7 AE C868 4C 48 B2 ILL

IN JMP JMP

LOOP

TEMP (STRADR) ,Y CREATE STRING LOOP $B4CA i BRING STRING DESCRIPTOR STACK CHKCLOSE ILLQUAN

MID$(STRINGVAR,POS,LEN) = STRING EXP MID$(STRINGVAR,POS) STRING EXP 200: 210:

C86B C86B

MIDCODE EXECUT

240: 250: 255: 260 : 270: 280: 290: 325: 330: 355: 360: 370: 372: 375: 378:

C86B C86B C86B C86B C86B C86B C86B C86B C86B 0003 0004 0005 0007 0007 0007

EXECOLD VARNAM VARADR DESCRPT TESTSTR GETVAR SETSTR TEST GETBYT

400: 410: 420: 430: 440: 450:

C86B C86D C86F C872 C875 C876

LENGTH POSITION VARSTR COMP POINT2 A9 AO 8D 8C 60 20

76 MIDSTR C8 08 03 09 03 73 00 MID TEST

460

*= *= *= *=

LDA LDY STA STY RTS JSR

$CA $308 iVECTOR FOR STATEMENT EXECUTE $A7E7 $45 $49 $64 $AD8F $B08B $AA52 $AEFF $B79E 3 *+1 *+1 *+2 $B2 $50 #MIDTEST EXECUT EXECUT+1 CHRGET

--------

------------

ABACUS Software

Anatomy of the 1541

460:

C879 C9 CA

CMP

470:

C87B FO 06

BEQ

480: 490:

C87D 20 79 00 C880 4C E7 A7

JSR JMP

500:

C883 20 73 00 MID

JSR

505:

C886 20 FA AE

JSR

510:

C889 20 8B BO

JSR

520: 530: 535: 535: 540: 545: 545: 545:

C88C C88E C890 C892 C894 C897 C899 C89B

64 65 49 4A A3 B6 00 64

STA STY STA STY JSR LDY LDA PHA

545: 550:

C89C FO 2E C89E 20 52 AA

BEQ JSR

560: 560: 560:

C8A1 AO 01 C8A3 B1 49 C8A5 85 05

LDY LDA STA

570: 570: 570: 600: 610:

C8A7 C8A8 C8AA C8AC C8AF

C8 B1 85 20 20

49 06 FD AE 9E B7

INY LDA STA JSR JSR

620: 630: 650: 650: 660:

C8B2 C8B3 C8B5 CSB6 C8B8

8A FO 17 CA 86 04 20 79 00

TXA BEQ DEX STX JSR

85 84 85 84 20 AO B1 48

461

#MIDCODE iCODE FOR MID$ ,• ?. MID YES CHRGOT EXECOLD EXECUTE NORMAL STATEMENT CHRGET iNEXT CHAR CHKOPEN iOPEN PAREN GETVAR iGET VAR DESCRPT DESCRPT+1 VARADR VARADR+1 FRESTR #0 (DESCRPT) , Y LENGTH ILL SETSTR iPUT STRING IN RAM #1 (VARADR),Y VARSTR iVAR ADDR (VARADR),Y VARSTR+1 CHKCOM GETBYT iGET POS ILL POSITION CHRGOT

ABACUS Software

Anatomy of the 1541

660:

C8BB C9 29

CMF

665: 665:

C8BD DO 04 C8BF A9 FF

BNE LDA

665: 670: 670:

C8C1 DO OC C8C3 20 FD AE NEXT C8C6 20 9E B7

BNE JSR JSR

680: 690: 700: 710: 715: 715: 715: 717: 717: 717: 720:

C8C9 C8CA C8CC C8CF C8D1 C8D2 C8D3 C8D5 C8D7 C8D9 C8DB

730: 770: 780:

C8DE A9 B2 C8EO 20 FF AE C8E3 20 9E AD

LDA JSR JSR

790: 800: 800: 800: 800: 800: 800: 810: 810: 820:

C8E6 C8E9 C8EB C8ED C8EF C8FO C8F2 C8F4 C8F5 C8F7

20 AO B1 85 88 B1 85 88 B1 FO

A3 B6 02 64 51

JSR LDY LDA STA DEY LDA STA DEY LDA BEQ

840: 850: 860: 870: 880:

C8F9 C8FB C8FD C8FF C901

C5 BO 85 A5 18

03 02 03 05

8A DO 4C 85 68 38 E5 C5 BO 85 20

03 48 B2 ILL STORE 03 04 03 02 03 F7 AE OK

64 50 64 D3

TXA BNE JMP

STA PLA SEC SBC CMF BCS STA JSR

CMP BCS STA LDA CLC

OK1

462

#")" iEND OF EXPRESSION? NEXT #$FF ; MAX LENGTH STORE CHKCOM ;GET GETBYT LEN *+5 ILLQUAN LENGTH POSITION LENGTH OK LENGTH CHKCLOSE ; CLOSE PAREN #COMP TEST FRMEVL iGET EXP FRESTR #2 (DESCRPT) , Y POINT2+1 (DESCRPT) , Y POINT2 (DESCRPT),Y ;0 ILL THEN ERROR LENGTH OK1 LENGTH VARSTR

ABACUS Software

Anatomy of the 1541

880: 910: 910: 920: 940: 950: 950:

C902 C904 C906 C908 C90A C90C C90D

50

ADC STA BCC INC LDY DEY LDA

960:

C90F 91 05

STA

970: 970 : 980:

C911 CO 00 C913 DO F7 C915 4C AE A7

CPY BNE

65 85 90 E6 A4 88 B1

04 05 02 06 03 LOOP

JMP

POSITION VARSTR *+4 VARSTR+1 LENGTH (POINT1) , Y TRANSFER CHARS FROM STRING (VARSTR),Y;EXP TO VAR #0 LOOP $A7AE ;TO INTERPRETER LOOP

For those who have no monitor or assembler for the Commodore 64, we have written a loader program in BASIC.

100 FOR I = 51200 TO 51479 110 READ X : POKE T,X : S=S+X : NEXT 120 DATA 169, 13,1.60,200,141, 10, 3,140, 11, 3, 76,107 130 DATA 200,169, 0,133, 13, 32,115, 0,201, 33, 240, 6 140 DATA 32,121, 0, 76,141,174, 32,115, 0,201, 196,240 150 DATA 3, 76, 8,175, 32,115, 0, 32,250,174, 32,158 160 DATA 183,138,72,32,253,174,32,158,173,36, 13, 48 170 DATA 12, 32,170,177,165,100,208, 36,165,101, 76, 82 180 DATA 200, 32,130,183,240, 26,160, 0,177, 34, 133, 3 190 DATA 104, 32,125,180,168,240, 7,165, 3,136, 145, 98 200 DATA 208,251, 32,202,180, 76,247,174, 76, 72, 178,169

463

ABACUS Software

Anatomy of the 1541

210 DATA 118,160,200,141, 8, 3,140, 9, 3, 96, 32,115 220 DATA 0,201,202,240, 6, 32,121, 0, 76,231, 167, 32 230 DATA 115, 0, 32,250,174, 32,139,176,133,100, 132,101 240 DATA 133, 73,132, 74, 32,163,182,160, 0,177, 100, 72 250 DATA 240, 46, 32, 82,170,160, 1,177, 73,133, 5,200 260 DATA 177, 73,133, 6, 32,253,174, 32,158,183, 138,240 270 DATA 23,202,134, 4, 32,121, 0,201, 41,208, 4,169 280 DATA 255,208, 12, 32,253,174, 32,158,183,138, 208, 3 290 DATA 76, 72,178,133, 3,104, 56,229, 4,197, 3,176 300 DATA 2,133, 3, 32,247,174,169,178, 32,255, 174, 32 310 DATA 158,173, 32,163,182,160, 2,177,100,133, 81,136 320 DATA 177,100,133, 80,136,177,100,240,211,197, 3,176 330 DATA 2,133, 3,165, 5, 24,101, 4,133, 5, 144, 2 340 DATA 230, 6,164, 3,136,177, 80,145, 5,192, 0,208 350 DATA 247, 76,174,167 360 IF S 31128 THEN PRINT "ERROR IN DATA!!" END 370 SYS 51200 : PRINT "OK."

464

ABACUS Software

4.3.3

Anatomy of the 1541

Spooling - Printing Directly from the Disk

If you have a printer connected to your computer in addition to the disk drive, you can use a special characteristic of the the serial bus.

It is possible to send files directly from disk to the printer, without having to transfer it byte by byte with the computer. For example, if you have text saved as a sequential file, and you want to print it on the printer, the following program allows you to do so:

100 110 120 130 140 150

OPEN 1,4 : REM PRINTER OPEN 2,8,2, "O:TEST" : REM TEXT FILE GET#2, A$ : IF ST = 64 THEN 140 PRINT#l, A$; : GOTO 120 CLOSE 1 : CLOSE 2 END

Characters are sent from the disk to the printer until the end of file is recognized. Then the two files are closed and the program ended. The following is done when spooling: First both files are opened again. A command to receive data (Listen) is sent to the printer, while the disk drive receives the command to send data (Talk). Data are sent automatically from the disk to the printer until the end of the file is reached. During this time, the computer can be used without interferring with the transfer of data. Only the use of peripheral devices is not possible during this time. In practice, this is done with a small machine language program. When you want to start printing, you call the program and give the name of the file which you want to send.

SYS 828, "TEXT" OPENs the file TEXT on the diskette and sends it to the printer. As soon as the transfer is begun, the computer responds with READY again and you can use it, as long as no attempt is made to access the serial bus. You can prove that the computer is no longer needed for transfer by pulling out the bus cable to the disk, so that the diskette is connected only to the printer. When the spooling is done, the disk file is still open (the red LED is still lit). 465

Anatomy of the 1541

ABACUS Software

You can CLOSE the file and tum the printer off and then back on, and give the SYS command without a filename (the cable to the disk must be attached, of course). SYS 828

You can stop a transfer in progress with the same command. The machine language program in the form of a loader program for the Commodore 64 and the VIC 20 is found at the end. Here are some hints for use: We have successfully used the printer spooling with a Commodore 64 and a VIC 20 with a printer such as the the VIC 1525. Attempts using an Epson printer with a VIC interface as well as the VIC 1526 did not succeed. The serial bus, in contrast with the parallel IEEE bus, appears to be capable of spooling only with limitations. This is why it is necessary to turn the printer off after spooling, because it still blocks the bus. We would be happy if you would inform us of your experience with other printers.

;

1541 - 64 SPOOL

110: 130: 140: 142: 144: 160: 170: 175: 180:

033C 033C 033C 033C 033C 033C 033C 033C 033C

CHRGOT LISTEN ATNRES CLOCK DATA CLOSE CLALL SETFIL GETNAME

$79 $FFB1 $EDBE $EE85 $EE97 $FFC3 $FFE7 $FFBA $E254

190: 200: 202: 204: 230: 240:

033C 033C 033C 033C 033C 033C

OPEN CHKIN UNTALK UNLISTEN FNLEN INDEV

$FFCO $FFC6 $FFAB $FFAE $B7 $99

260:

033C

NMBFLS

$98

466

;ATN HI ;CLOCK HI ;DATA HI

;GET FILENAME

; INPUT DEVICE ;# OF FILES

------------

----------------

ABACUS Software

Anatomy of the 1541

280:

033C

ERROR

300: 310:

033C 033C 20 79 00

*= JSR

828 CHRGOT

320:

033F FO 33

BEQ

OFF

330: 340: 350: 360: 370: 380: 390: 400: 410:

0341 0344 0347 0349 034B 034D 034F 0351 0354

20 20 A6 FO A9 A2 AO 20 20

E7 54 B7 38 02 08 02 BA CO

JSR JSR LDX BEQ LDA LDX LDY JSR JSR

411: 412: 413: 420: 430: 432: 434: 436: 510: 510: 530: 540: 550: 560: 570: 580: 620: 630: 640 :

0357 0359 035C 035F 0361 0364 0367 036A 036D 036F 0371 0373 0374 0376 0378 037B 037E 0380 0383

A9 20 20 A2 20 20 20 20 A9 85 85 60 A9 85 20 20 A9 4C 4C

04 B1 BE 02 C6 BE 85 97 00 99 98

CLALL GETNAME FNLEN SYNTAX #2 #8 #2 SETFIL OPEN iOPEN FILE #4 LISTEN iPRINTER ATNRES #2 CHKIN iFLOPPY ATNRES CLOCK DATA #0 INDEV NMBFLS

01 98 AE AB 02 C3 08

$AF08

FF E2

FF FF FF ED FF ED EE EE

OFF FF FF FF AF SYNTAX

467

iSYNTAX ERROR iMORE CHARACTERS iSPOOLING DONE

LDA JSR JSR LDX JSR JSR JSR JSR LDA STA STA RTS LDA #1 STA NMBFLS JSR UNLISTEN JSR UNTALK LDA #2 JMP CLOSE JMP ERROR

Anatomy of the 1541

ABACUS Software

Here is the BASIC loader program for the Commodore 64. 100 FOR I = 828 TO 901 110 READ X : POKE I,X : S=S+X : NEXT 120 DATA 32,121, 0,240,51,32,231,255,32,84, 226,166 130 DATA 183,240, 56,169, 2,162, 8,160, 2, 32, 186,255 140 DATA 32,192,255,169, 4, 32,177,255, 32,190, 237,162 150 DATA 2, 32,198,255, 32,190,237, 32,133,238, 32,151 160 DATA 238,169, 0,133,153,133,152, 96,169, 1, 133,152 170 DATA 32,174,255, 32,171,255,169, 2, 76,195, 255, 76 180 DATA 8,175 190 IF S 9598 THEN PRINT "ERROR IN DATA! !":END 200 PRINT "OK" Use the following loader program for the VIC 20. 100 FOR I = 828 to 901 110 READ X : POKE I,X : S=S+X : NEXT 120 DATA 32,121, 0,240, 51, 32,231,255, 32,81, 226,166 130 DATA 183,240, 56,169, 2,162, 8,160, 2,32, 186,255 140 DATA 32,192,255,169, 4, 32,177,255, 32,197, 238,162 150 DATA 2, 32,198,255, 32,197,238, 32,132,239, 32,160 160 DATA 228,169, 0,133,153,133,152, 96,169, 1, 133,152 170 DATA 32,174,255, 32,171,255,169, 2, 76,195, 255, 76 180 DATA 8,207 190 IF S9642 THEN PRINT "ERROR IN DATA! !":END 200 PRINT "OK"

468

ABACUS Software

Anatomy of the 1541

4.4 Overlay Technique and Chaining Machine Language Programs A proven programming technique involves the creation of a menu program which then loads and executes other programs based on the user's choice. There are two variations: preserving or clearing the old variables in the chained program. It is possible to pass the old variables if the calling program is as large or larger than the chained program. If one program is chained from another program, the pointer to the end of the previous program remains intact, and the new program loads over the old. In this example, we would get the following result:

100 REM PROGRAM 1 110 REM THIS PROGRAM IS LARGER THAN THE SECOND 120 A = 1000 130 LOAD "PROGRAM 2",8 100 REM PROGRAM 2 110 PRINT A 1000

If the chained program is larger than the original program, part of the variables are overwritten and contain meaningless values. Moreover, when the variables that the program destroyed are assigned new values, part of the program is also destroyed. There are two characteristics of passing variables from the previous program that should be noted--for strings and for functions. Any string variables that are defined as constants enclosed in quotes in the fIrst program will have a problem. The string variable pointer points to the actual text in the program. If, for example, a string is defined in the first program with the following assignment

100 A$ = "TEXT"

469

ABACUS Software

Anatomy of the 1541

the variable pointer points to the actual text within line number 100. When chaining, the next program does not change this pointer. New text is now at the original location, so the variable has unpredictable contents. We can easily work around this, however. We need only ensure that the text is copied from the program into string storage where text variables are normally stored. You can do this as follows:

100 A$ = "TEXT" + "" By concatenating an empty string, you force the contents of the variable to be copied to the string storage area. Similar considerations apply to function definitions, because here also the pointer points to the definition within the program. Here you must define the function again in the second program, for example:

100 DEF FN A(X) = 0.5 * EXP (-X*X) If you want to chain a program, you can continue to use the old variables provided the second program is not longer than the first. If the chained program is longer, and we do not want to preserve the old variables, there is a trick we can use. We need only set the end-of-program pointer to the end of the new program immediately after loading. This can be done with a pair of POKE commands:

POKE 45, PEEK(174) : POKE 46, PEEK (175) : CLR The CLR command is absolutely necessary. This line should be the first line in the chained program. This allows us to chain a large program without transfer of variables. Another, not so elegant, method involves writing the load command in the keyboard buffer so the program will automatically be loaded in the direct mode. To do this, we write the LOAD and RUN commands on the screen and fill the keyboard buffer with "HOME" and carriage returns. An END statement must come after this in the program. The operating system then gets the contents of the keyboard buffer in the direct mode and reads the LOAD and RUN commands that control the loading and execution of the program. Because this occurs in the direct mode, the end address of the program is automatically set, the variables are erased and the program is started with the RUN. The disadvantage of this method is that since the LOAD command must appear on the video screen, a.1'}y display will be destroyed. In practice it looks like this:

470

ABACUS Software

Anatomy of the 1541

1000 PRINT CHR$ (147) "LOAD " CHR$ (34) "PROGRAM 2" CHR$(34)",8" 1010 PRINT : PRINT : PRINT : PRINT 1020 PRINT "RUN" 1030 POKE 631,19 POKE 632,13 POKE 633,13 1040 POKE 634,13 POKE 635,13 POKE 636,13 1050 POKE 198,6 END You can see that this procedure is more complicated than the previous one; it is only mentioned for the sake of completeness. With the first procedure, only the LOAD command need be programmed in line 1000:

1000 LOAD "PROGRAM 2",8 There is another technique for chaining machine language programs. If a machine language program is to be used from a BASIC program, it must usually be loaded at the beginning of the BASIC program. You must take note of two things: First of all, you must make sure that the machine language program loads to a specific place in memory. If you load a program without additional parameters, the control system treats it as a BASIC program and loads it at the starting address of the BASIC RAM, generally at 2049 (Commodore 64). Machine language programs can only be run, however, when they are loaded at the address for which they were written. This absolute loading can be accomplished by adding the secondary address I:

LOAD "MACH-PRG" ,8,1 But remember that when loading a program from within another program, BASIC attempts to RUN the program from the beginning. This leads to an endless loop when loading machine language programs, because the operating system thinks that a new BASIC program has been chained:

100 LOAD "MACH-PRG" ,8,1 Here we can make use of the fact that the variables are preserved when chaining. If we program the following, we have reached our goal:

471

ABACUS Software

Anatomy of the 1541

100 IF A=O THEN A=l : LOAD "MACH-PRG" ,8,1 110 ... When the program is started with RUN, A has the value zero and the assignment after the THEN is executed, A contains the value 1 and the machine language program is then LOADed. When the program begins again after LOADing the program MACH-PRG, A has the value 1 so the next line is executed. The procedure is similar if you have several machine language programs to load.

100 IF A=O THEN A=l : LOAD" PROG 1" ,8,1 110 IF A=l THEN A=2 : LOAD" PROG 2" ,8,1 120 IF A=2 THEN A=3 : LOAD "PROG 3" ,8,1 130 .... The first time through, PROG 1 will be loaded, the next time, PROG 2, and so on. Once all the programs are loaded, execution continues with line 130.

472

ABACUS Software

4.5

Anatomy of the 1541

Merge - Appending BASIC Programs

Certainly you have thought about the possibility of combining two separate BASIC programs into one. This is not possible without some work because loading the second program would overwrite the first. With the knowledge of how BASIC programs are stored in memory and on the diskette, we can develop a simple procedure to accomplish this task. BASIC programs are stored in memory as follows:

NLNH LLLH XXYYZZ

00

pointer to the next program line, 10 hi line number, 10 hi ..... tokenized BASIC statements end-of-Iine marker

At the end of the program are two additional zero bytes: 00 00 for a total of 3 zero bytes Programs are also saved in this format. Where the program starts and ends lies in two pointers in page zero:

PRINT PEEK(43) + 256

* PEEK(44)

gives the start of BASIC, 2049 for the Commodore 64,

PRINT PEEK(45) + 256

* PEEK(46)

points to the byte behind the three zero bytes. Because a program is always loaded at the start of the BASIC storage area, contained in the pointer at 43/44, one can cause a second program to load at the end of the first. In practice, we must proceed as follows: First we load the fIrst program into memory.

LOAD "PROGRAM 1",8 Now get the value of the ending address of the program.

A = PEEK(45) + 256 * PEEK(46)

473

ABACUS Software

Anatomy of the 1541

This value is decremented by two so that the two zero bytes at the end of the program will be overwritten later.

A=A-2 Now, note the original value of the start of BASIC.

PRINT PEEK(43), PEEK(44) Next, set the start of BASIC to this value.

POKE 43,(A AND 255): POKE 44, A / 256 Now, LOAD the second program.

LOAD "PROGRAM 2",8 If you set the start of BASIC back to the original value, 1 and 8 for the Commodore 64 (as shown above with the PRINT commands), you have the complete program in memory and can view it with LIST or save it with SAVE.

POKE 43,1: POKE 44,8 The following should be noted when using this method: The appended program may contain only line numbers which are greater than the largest line number of the first program. Otherwise these line numbers can never be accessed with OOTO or OOSUB and the proper program order cannot be guaranteed. This procedure is especially well suited for constructing a subroutine library for often-used routines, so they need not be typed in each time. It will work out best if you reserve specific line numbers for the subroutines, such as 20000- 25000, 25000-30000, and so on. If you want to merge several programs in this manner, you must first load the program with smallest line numbers, and then the program with the next highest numbers, etc.

474

ABACUS Software

Anatomy of the 1541

4.6 Disk Monitor for the Commodore 64 and VIC 20 In this section we present a very useful tool for working with your disk drive, allowing you to load, display, modify, and save desired blocks on the diskette. For reasons of speed, the program is written entirely in machine language. The following commands are supported:

* * * * * * *

Read a block from the disk Write a block to the disk Display a block on the screen Edit a block on the screen Send disk commands Display disk error messages Return to BASIC

The program announces its execution (automatically by the BASIC load program) with

DISK-MONITOR Vl.O >

and waits for your input. If you enter '@', the error message from the disk will be displayed, for example

00, OK,OO,OO If you want to send a command to the disk, enter an '@' followed by the command.

You can initialize a diskette with >@I

You can send complete disk commands in this manner, commands that you would otherwise send with

OPEN 15,8,15 PRINT# 15,"command" CLOSE 15

475

ABACUS Software

Anatomy of the 1541

For example, you can erase files, format disks, and so on. The most important function of the disk monitor is the direct access of any block on the diskette. For this you use the commands Rand W. R stands for READ and reads a desired block, W stands for WRITE and writes a block to the disk. You need only specify the track and sector you want to read. These must be given in hexadecimal, exactly as the output is given on the screen. If, for example, you want to read track 18, sector 1 (the first directory block), enter the following command: >R 1201

Each input must be given as a two-digit hex number, separated from each other with a blank. In order to display the block, use the command M. We receive the following output: DISK-MONITOR >M >:00 12 04 82 >: 08 46 49 4B >:10 53 52 43 >: 18 00 00 00 >:20 00 00 82 >:28 4F 54 2E >:30 AO AO AO >:38 00 00 00 >: 40 00 00 82 >: 48 4F 54 2E >:50 AO AO AO >:58 00 00 00 >:60 00 00 P2 >:68 2E 53 52 >: 70 AO AO AO >:78 00 00 00 >:80 00 00 82 >:88 2E 4F 42 >:90 AO AO AO >:98 00 00 00 >:AO 00 00 82 >:A8 50 2E 53

V1.0 11 20 AO 00 13 53 AO 00 13 53 AO 00 13 43 AO 00 13 4A AO 00 10 52

01 41 AO 00 00 52 AO 00 03 52 AO 00 09 AO AO 00 08 AO AO 00 00 43

47 49 00 00 48 43 00 00 56 43 00 00 4D AO 00 00 4D AO 00 00 53 AO

52 44 00 15 50 AO 00 05 50 AO 00 09 45 AO 00 06 45 AO 00 01 57 AO

41 2E 00 00 4C AO 00 00 4C AO 00 00 4D AO 00 00 4D AO 00 00 41 AO

476

· . . . . GRA

FIK AID. SRC

·....... · . . . . HPL

OT.SRC

·....... · . . . . VPL

OT.SRC

·....... · ..•• MEM

.SRC

·....... · .... MEM .OBJ

·.... ... · .... SWA P.SRC

ABACUS Software

>:BO >:B8 >:cO >:C8 >:DO >:D8 >:EO >:E8 >:FO >:F8

AO 00 00 52 AO 00 00 53 AO 00

AO 00 00 49 AO 00 00 53 AO 00

AO 00 82 58 AO 00 82 2E AO 00

Anatomy of the 1541

AO 00 10 2E AO 00 13 54 AO 00

AO 00 01 53 AO 00 OC 45 AO 00

00 00 4D 52 00 00 47 53 00 00

00 04 41 43 00 00 41 54 00 01

00 00 54 AO 00 00 55 AO 00 00

· ... . . . . · .... MAT RIX.SRC

·....... · .... GAU SS.TEST

·.. .....

Let's take a closer look at the output. The first hex number after the colon gives the address of the following 8 bytes in the block, 00 indicates the first byte in the block (the numbering goes from 00 to FF (0-255». 8 bytes follow the address (4 on the VIC 20). In the right half are the corresponding ASCII characters. If the code is not printable ($00 to $lF and $80 to $9F), a period is printed. When you give the command M, as above, the entire block is displayed. Because the block does not fit on the screen completely, it is possible to display only part of it. You can give an address range that you would like to display. If you only want to see the first half, enter:

>M007F The second half with:

>M80FF With the VIC 20, you can view quarters of the block. If you now wish to change some data, you simply move the cursor to the corresponding place, overwrite the appropriate byte, and press RETURN. The new value is now stored and the right half is updated with the proper ASCII character. To write the modified block back to the diskette, you use the command W. Here also you must give the track and sector numbers in hexadecimal.

>W 12 01 writes the block back to track 18, sector 1, from where we had read the block previously.

477

ABACUS Software

Anatomy of the 1541

If you want to get back to BASIC, enter X and the computer will respond with READY .. If you then want to use the disk monitor again, you need not reload it. Just type SYS 49152 for the C64 or SYS 6690 for the VIC 20. A warning: Be sure to make a copy of any diskette that you work with in this way. Should you make an error when editing or writing a block, you can destroy important information on the disk so that it can no longer be used in the normal manner. You should make it a rule to work only with a copy. Here you find an assembler listing of the program. After this are the BASIC loader programs for the Commodore 64 and VIC 20. ; ;

disk monitor vic 20 / cbm 64

190: 200:

COOO COOO

PROMPT NCMDS

210: 220: 230: 240: 250: 260: 270: 280: 290: 300: 310: 320: 330: 340: 350: 360: 370: 380: 390: 400:

COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO COOO

INPUT TALK SECTALK IEEE IN UNTALK LISTEN SECLIST IEEEOUT UNLIST WRITE OPEN CLOSE SETPAR SETNAM CHKIN CKOUT CLRCH CR QUOTE QUOTFLG

478

,.>,.

6 NUMBER OF COMMANDS $FFCF $FFB4 $FF96 $FFA5 $FFAB $FFB1 $FF93 $FFA8 $FFAE $FFD2 $FFCO $FFC3 $FFBA $FFBD $FFC6 $FFC9 $FFCC 13 $22 $D4

ABACUS Software

Anatomy of the 1541

410:

0200

420: 430: 440: 450: 460: 470: 480:

0201 0202 0203 0204 0205 0205 0205

SAVX WRAP BAD FROM TO STATUS SA

490:

0205

FA

500:

0205

FNADR

510:

0205

FNLEN

520: 610:

0205 COOO

TMPC COUNT

620 :

COOO

READY

630: 640: 650: 660: 670: 680: 690: 700: 710: 710: 710: 720:

COOO C002 C005 C008 C009 COOB COOD COOF C011 C014 C016 C019

730: 740: 750:

C01C C9 3E COlE FO F9 C020 C9 20

760: 770:

C022 FO F5 C024 A2 05

*=

A2 BD 20 E8 EO DO A2 A9 20 A9 8D 20

INIT 00 85 C2 MSGOUT D2 FF 12 F5 OD START 3E EB CO 00 01 02 33 C1 ST1

SO

479

$200 BASIC INPUT BUFFER .BYT 0 .BYT 0 .BYT 0 .BYT 0 .BYT 0 $90 $B9 SECONDARY ADDRESS $BA DEVICE # $BB FILENAME ADR $B7 ;LEN OF FILENAME $97 ;# OF BYTES 8 PER LINE $E37B ; $E467 FOR VIC LDX #0 LDA MESSAGE, X JSR WRITE INX CPX #ASCDMP-MESSAGE BNE MSGOUT LDX #CR LDA #PROMPT JSR WRTWHR LDA #0 STA WRAP JSR RDOC ; READ INPUT LINE CMP #PROMPT BEQ ST1 CMP #" " ; READ OVER BLANK BEQ ST1 LDX #NCMDS-1 COMPARE WITH COMMAND TABLE

Anatomy of the 1541

ABACUS Software

780: 790: 800:

C026 DD 6A CO Sl C029 DO OC C02B 8E 00 02

CMP BNE STX

840: 850:

C02E BD 70 CO C031 48

LDA PHA

860: 870: 880: 890: 900:

C032 C035 C036 C037 C038

910:

C03A 4C OD CO

LDA PHA RTS DEX BPL

BD 76 CO 48 60 S2 CA 10 EC

960: 970: 980:

C03D 85 97 C03F 20 62 CO C042 B9 EO C2

990: 1000: 1000: 1000: 1010: 1020: 1030:

C045 C048 C049 C04B C04E C050 C052

1060: 1070:

C053 20 FE CO C056 90 03

1080:

C058 99 EO C2

1090: 1100: 1110: 1120: 1130: 1140: 1150: 1160:

C05B C05C C05E C05F C062 C064 C065 C067

20 C8 DO EE C6 DO 60

C8 C6 60 20 A9 2C A9 4C

DC CO 03 01 02 97 ED

97 62 CO 20 OD D2 FF

JMP

CMDS,X S2 SAVX ;# OF CMDS IN TABLE ADRH,X ; JUMP ADDR TO STACK ADRL,X

;LOOP OF ALL CMDS

Sl START

SUBROUTINE TO DISPLAY THE DISK CONTENTS STA TMPC DM JSR SPACE DM1 LDA BUFFER,Y ;GET BYTE FROM BUFFER JSR WROB INY BNE DM2 INC WRAP DM2 DEC TMPC BNE DM1 RTS READ BYTES AND WRITE TO MEMORY BYT JSR RDOB BCC BY3 BLANK? STA BUFFER,Y WRITE BYTE IN BUFFER INY BY3 DEC TMPC RTS JSR SPACE SPAC2 SPACE LDA #" BYT $2C LDA #CR CRLF JMP WRITE II

480

ABACUS Software

Anatomy of the 1541

1190:

C06A 3A

1200:

C06B 57

1210:

C06C 52

1220:

C06D 4D

1230:

C06E 40

1240: 1250: 1260: 1270: 1280: 1290 : 1300: 1310: 1320: 1330: 1340: 1350: 1360: 1370: 1380: 1370: 1370: 1370: 1370: 1370: 1380:

C06F C070 C071 C072 C073 C074 C075 C076 C077 C078 C079 C07A C07B C07C C07E C081 C082 C085 C088 C08A C08C

58 CO C1 C1 CO C1 E3 CO 90 90 7B 3E 7A AO 8C 88 8C 20 C9 FO 20

04 02 CF FF OD 17 FE CO

1390: 1400: 1410: 1410: 1410: 1420:

C08F C091 C094 C097 C099 C09B

90 8D 20 C9 FO 20

12 03 02 CF FF OD 08 FE CO

1430:

C09E 90 03

00 03 02

COMMAND AND ADDRESS TABLE CMDS .ASC ' . , ;EDIT MEM CONTENTS .ASC 'w' ;WRITE BLOCK .ASC 'R' ; READ BLOCK ;DISLPAY .ASC 'M' BYTES .ASC '@ , ;DISK COMMAND .ASC 'x' ;EXIT ADRH .BYT >ALTM-1 .BYT >DIRECT-1 .BYT >DIRECT-1 .BYT >DSPLYM-1 .BYT >DISK-1 .BYT >READY-1 .BYT