*********

Welcome to Project 64!

The goal of Project 64 is to preserve Commodore 64 related documents
in electronic text format that might otherwise cease to exist with the
rapid advancement of computer technology and declining interest in 8-
bit computers on the part of the general population. If you would like
to help by converting C64 related hardcopy documents to electronic
texts please contact the manager of Project 64, Cris Berneburg, at
74171.2136@compuserve.com.

Extensive efforts were made to preserve the contents of the original
document.  However, certain portions, such as diagrams, program
listings, and indexes may have been either altered or sacrificed due
to the limitations of plain vanilla text.  Diagrams may have been
eliminated where ASCII-art was not feasible.  Program listings may be
missing display codes where substitutions were not possible.  Tables
of contents and indexes may have been changed from page number
references to section number references. Please accept our apologies
for these limitations, alterations, and possible omissions.

Document names are limited to the 8.3 file convention of DOS. The
first characters of the file name are an abbreviation of the original
document name. The version number of the etext follows next. After
that a letter may appear to indicate the particular source of the
document. Finally, the document is given a .TXT extension.

The author(s) of the original document and members of Project 64 make
no representations about the accuracy or suitability of this material
for any purpose.  This etext is provided "as-is".  Please refer to the
warantee of the original document, if any, that may included in this
etext.  No other warantees, express or implied, are made to you as to
the etext or any medium it may be on.  Neither the author(s) nor the
members of Project 64 will assume liability for damages either from
the direct or indirect use of this etext or from the distribution of
or modification to this etext. Therefore if you read this document or
use the information herein you do so at your own risk.

*********

The Project 64 etext of the Commodore 1581 Disk Drive User's Guide.
Converted to etext by Frank Jeno Kontros <jeno@kontr.uzhgorod.ua>, the
Non Stop Cracker.

1581D11.TXT, December 1996, etext #139. This replaces 1581D10.TXT.

*********

Note: To extract the ascii text basic programs all at once from this
etext use "tok64" by Cris Berneburg <74171.2136@compuserve.com>. Or to
extract the uuencoded basic programs all at once use "uud" by Edwin
Kremer <edwin@zlotty>.

*********

  Here  is  another  piece  of  (ASCII)  art:  The Commodore 1581
Disk  Drive  User's  Manual. I hope this one better than original
because it was corrected & debugged. So, enjoy it!

  If  you  find  any  errors  in  the  text  or  programs, please
report  them  so  that  they  can  be  fixed. There should not be
many, though...

Frank Kontros <jeno@kontr.uzhgorod.ua>

*********

COMMODORE 1581 Disk Drive User's Guide


USER'S MANUAL STATEMENT

WARNING:  This  equipment  has  been certified to comply with the
limits  for a Class B computing device,  pursuant to subpart J of
Part 15  of the Federal Communications Commission's rules,  which
are  designed  to provide reasonable protection against radio and
television  interference  in  a residential installation.  If not
installed properly,  in strict accordance with the manufacturer's
instructions,  it  may  cause  such interference.  If you suspect
interference,  you  can test this equipment by turning it off and
on.  If  this  equipment  does cause interference,  correct it by
doing any of the following:

  o Reorient the receiving antenna or AC plug.

  o Change  the  relative  positions  of  the  computer  and  the
    receiver.

  o Plug the computer into a different outlet so the computer and
    receiver are on different circuits.

CAUTION:  Only  peripherals with shield-grounded cables (computer
input-output devices,  terminals,  printers, etc.),  certified to
comply  with  Class B  limits,  can be attached to this computer.
Operation  with  non-certified peripherals is likely to result in
communications interference.

Your  house  AC  wall receptacle must be a three-pronged type (AC
ground).  If  not,  contact  an electrician to install the proper
receptacle.  If  a  multi-connector  box  is  used to connect the
computer and peripherals to AC,  the ground must be common to all
units.

If  necessary,  consult  your  Commodore dealer or an experienced
radio-television  technician for additional suggestions.  You may
find  the  following  FCC  booklet helpful:  "How to Identify and
Resolve   Radio-TV   Interference   Problems."  This  booklet  is
available from the  U.S. Government Printing Office,  Washington,
D.C. 20402, stock no. 004-000-00345-4.



1581
Disk Drive
User's Guide



Copyright (c) 1987 by Commodore Electronics Limited
All rights reserved

This manual contains copyrighted  and proprietary information. No
part of this publication may be reproduced, stored in a retrieval
system,  or transmitted in any form or by any means,  electronic,
mechanical,  photocopying,  recording  or otherwise,  without the
prior written permission of Commodore Electronics Limited.

COMMODORE 64  is a registered trademark of  Commodore Electronics
Limited
COMMODORE 128,  Plus 4,  and  VIC 20  are trademarks of Commodore
Electronics Limited



CONTENTS

 INTRODUCTION
 HOW THIS GUIDE IS ORGANIZED

PART ONE: BASIC OPERATING INFORMATION

   1. UNPACKING, SETTING UP AND USING THE 1581

 1.1. Step-by-Step Instructions
 1.2. Troubleshooting Guide
 1.3. Tips For Maintenance and Care
 1.4. Inserting a Diskette
 1.5. Using Pre-Programmed (Software) Diskettes
 1.6. How to Prepare a New Diskette
 1.7. Diskette Directory
 1.8. Selective Directories
 1.9. Printing a Directory
1.10. Pattern Matching
1.11. Splat Files

   2. BASIC 2.0 COMMANDS

 2.1. Error Checking
 2.2. Basic Hints
 2.3. SAVE
 2.4. SAVE With Replace
 2.5. VERIFY
 2.6. SCRATCH
 2.7. More About SCRATCH
 2.8. RENAME
 2.9. Renaming and Scratching Troublesome Files
2.10. COPY
2.11. VALIDATE
2.12. INITIALIZE

   3. BASIC 7.0 COMMANDS

 3.1. Error Checking
 3.2. SAVE
 3.3. SAVE With Replace
 3.4. VERIFY
 3.5. COPY
 3.6. CONCAT
 3.7. SCRATCH
 3.8. More About SCRATCH
 3.9. RENAME
3.10. Renaming and Scratching Troublesome Files
3.11. COLLECT
3.12. DCLEAR

PART TWO: ADVANCED OPERATION AND PROGRAMMING

   4. SEQUENTIAL DATA FILES

 4.1. Opening a File
 4.2. Closing a File
 4.3. Reading File Data: Using INPUT#
 4.4. More About INPUT#
 4.5. Numeric Data Storage on Diskette
 4.6. Reading File Data: Using GET#
 4.7. Demonstration of Sequential Files

   5. RELATIVE DATA FILES

 5.1. Files, Records, and Fields
 5.2. File Limits
 5.3. Creating a Relative File
 5.4. Using Relative Files: RECORD# Command
 5.5. Completing Relative File Creation
 5.6. Expanding a Relative File
 5.7. Writing Relative File Data
 5.8. Designing a Relative Record
 5.9. Writing the Record
5.10. Reading a Relative Record
5.11. The Value of Index Files

   6. DIRECT ACCESS COMMANDS

 6.1. Opening a Data Channel for Direct Access
 6.2. Block-Read
 6.3. Block-Write
 6.4. The Original Block-Read and Block-Write Commands
 6.5. The Buffer Pointer
 6.6. Allocating Blocks
 6.7. Freeing Blocks
 6.8. Partitions and Sub-Directories
 6.9. Using Random Files

   7. INTERNAL DISK COMMANDS

 7.1. Memory-Read
 7.2. Memory-Write
 7.3. Memory-Execute
 7.4. Block-Execute
 7.5. User Commands
 7.6. Utility Loader
 7.7. Auto Boot Loader

   8. MACHINE LANGUAGE PROGRAMS
      Disk-Related Kernal Subroutines

   9. BURST COMMANDS

 9.1. CMD 1 -- Read
 9.2. CMD 2 -- Write
 9.3. CMD 3 -- Inquire Disk
 9.4. CMD 4 -- Format
 9.5. CMD 6 -- Query Disk Format
 9.6. CMD 7 -- Inquire Status
 9.7. CMD 8 -- Dump Track Cache Buffer
 9.8. CHGUTL Utility
 9.9. FASTLOAD Utility
9.10. Status Byte Breakdown
9.11. Burst Transfer Protocol
9.12. Explanation of Procedures

  10. 1581 INTERNAL OPERATION

10.1. Logical Versus Physical Disk Format
10.2. Track Cache Buffer
10.3. Controller Job Queue
10.4. Vectored Jump Table

APPENDICES:

   A: Changing the Device Number
   B: DOS Error Messages
   C: DOS Diskette Format
   D: Disk Command Quick Reference Chart
   E: Specifications of the 1581 Disk Drive
   F: Serial Interface Information


INTRODUCTION

  The  Commodore 1581  is a versatile 3.5" disk drive that can be
used with a variety of computers,  including  the  COMMODORE 128,
the COMMODORE 64, the Plus 4, COMMODORE 16, and VIC 20.
  Also,  in  addition to the convenience of 3.5" disks,  the 1581
offers the following features:

  o Standard  and  fast  serial data transfer rates  --  The 1581
    automatically selects the proper data transfer rate  (fast or
    slow) to match the operating modes available on the Commodore
    128 computer.

  o Double-sided, double-density MFM data recording  --  Provides
    more than 800K formatted storage capacity per disk (400K+ per
    side).

  o Special high-speed burst commands -- These commands, used for
    machine language programs, transfer data several times faster
    than the standard or fast serial rates.


HOW THIS GUIDE IS ORGANIZED

  This guide is divided into two main parts and seven appendices,
as described below:

  PART  ONE:  BASIC  OPERATING  INFORMATION  --  includes all the
  information needed by novices and advanced users  to set up and
  begin  using  the 1581 disk drive.  PART ONE is subdivided into
  three chapters:

  o Chapter 1,  Unpacking,  Setting Up and Using the 1581,  tells
    you  how  to  use disk software programs that you buy.  These
    prewritten  programs help you perform a variety of activities
    in fields such as business,  education, finance, science, and
    recreation.  If you're interested only in loading and running
    prepackaged disk programs, you need read no further than this
    chapter.  If you are also interested in saving,  loading, and
    running  your  own  programs,  you  will  want  to  read  the
    remainder of the guide.

  o Chapter 2, Basic 2.0 Commands, describes the use of the BASIC
    2.0  disk  commands with the Commodore 64  and  Commodore 128
    computers.

  o Chapter 3, Basic 7.0 Commands, describes the use of the BASIC
    7.0 disk commands with the Commodore 128.

  PART TWO:  ADVANCED OPERATION AND PROGRAMMING  --  is primarily
  intended for users familiar with computer programming. PART TWO
  is subdivided into six chapters:

  o Chapter 4,  Sequential Data Files,  discusses  the concept of
    data files,  defines sequential data files, and describes how
    sequential data files are created and used on disk.

  o Chapter 5,  Relative  Data  Files,  defines  the  differences
    between sequential and relative data files, and describes how
    relative data files are created and used on disk.

  o Chapter 6,  Direct Access Commands,  describes  direct access
    disk  commands  as  a tool for advanced users and illustrates
    their use.

  o Chapter 7,  Internal Disk Commands,  centers on internal disk
    commands.  Before  using these advanced commands,  you should
    know how to program a 6502 chip in machine language.

  o Chapter 8,  Machine Language Programs,  provides  a  list  of
    disk-related  kernal  ROM  subroutines  and gives a practical
    example of their use in program.

  o Chapter 9,  Burst Commands,  gives  information on high-speed
    burst commands.

  o Chapter 10, 1581 Internal Operations,  describes how the 1581
    operates internally.

APPENDICES A THROUGH F --  provide various reference information;
for  example,  Appendix A  tells you how to set the device number
through use of two switches on the back of the drive.



1. HOW TO UNPACK, SET UP AND BEGIN USING THE 1581


1.1. STEP-BY-STEP INSTRUCTIONS

1) INSPECT THE SHIPPING CARTON FOR DAMAGE.
   If you find any damage to the shipping carton and suspect that
   the disk drive may have been affected, contact your dealer.
2) CHECK THE CONTENTS OF THE SHIPPING CARTON.
   Packed  with  the  1581  and  this  book,  you should find the
   following: electrical power supply, interface cable, Test/Demo
   diskette, and a warranty card to be filled out and returned to
   Commodore.
3) REMOVE THE SHIPPING SPACER FROM THE DISK DRIVE.
   The spacer is there  to protect the inside of the drive during
   shipping.  To  remove it,  push the button on the front of the
   drive (see Figure 1) and pull out the spacer.


              Figure 1. Front of the 1581 Disk Drive

           ____________________________________________
          /                    |________|              \
         |_____________________|________|_______________|
         |   ==     ################################    |
         |~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~|~~~~~~~~~~~~~~~|
         |                     |________|      [====]   |
         |   Commodore 1581    |        |               |
         |  FLOPPY DISK DRIVE  |        |               |
          \____________________|________|______________/
             \______________________________________/
                   ~~                        ~~

           THE PRODUCT DOES NOT NECESSARILY RESEMBLE THE
                 PICTURE INSIDE THE USER'S MANUAL


4) CONNECT THE POWER CORD.
   Check  the  ON/OFF  switch  on  the  back  of  the  drive (see
   Figure 2)  and  make  sure it's OFF.  Connect the power supply
   where  indicated  in  Figure  2.  Plug  the  other end into an
   electrical outlet. Don't turn the power on yet.


 Figure 2. Connection of Power Cord and Interface Cables to 1581


    ____/##_##_##_##__##_##_##_##__##_##_##_##__##_##_##_##\____
   |------------------------------------------------------------|
   | +-----------+  +------+  /-\  /-\       +----+ +---------+ |
   | |===========|  |======|  \_/  \_/ [=] O |\../| |=========| |
   +---------------------------|--------------------------------+
                               |
    BACK OF C128               | SERIAL PORT
                               | CONNECTOR
                               | ON C128
                               |
                               |
                               |     POWER CORD
                               |       SOCKET
                               |         |
                     /---------|---------|-------\
                     |         |         |       |
                     |_________|_________|_______|
                     |         |         |       |
                     |   /-\  /|\       /-\ +-+  |
                     |_  \_/  \_/   [=] \_/ |_| _|
        BACK OF 1581   \___\__/______|___|___|_/
                         ~~ \/       |   | ~~|
                        SERIAL PORT  |   | ON/OFF
                        CONNECTORS   |   | SWITCH
                           FOR       |   |
                        INTERFACE    |   |
                          CABLES     |   |
                                     |   |
                                     |   |
                            DIP SWITCHES |
                            FOR CHANGING |
       _______                 DEVICE    |
      |  ___  |                NUMBER    |
      | |###|_|__________________________|
      | |###| |
      |  ___  |
      | |! !| |
      | |_!_| |
      |_______|
        POWER
        OUTLET


5) CONNECT THE INTERFACE CABLE.
   Make  sure  your  computer  and any other peripherals are OFF.
   Plug either end of the interface cable into either serial port
   on the back of the drive (see Figure 2). Plug the other end of
   the  cable into the back of the computer.  If you have another
   peripheral (printer or extra drive),  plug its interface cable
   into the remaining serial port on the drive.
6) TURN ON THE POWER.
   With everything hooked up and the drive empty, you can turn on
   the  power  to  the peripherals in any order,  but turn on the
   power to the computer last.  When everything is on,  the drive
   goes through a self test. If all is well, the green light will
   flash once  and the red power-on light will glow continuously.
   If  the red light continues to flash,  there may be a problem.
   In that case, refer to the Troubleshooting Guide.


1.2. TROUBLESHOOTING GUIDE

-----------------------------------------------------------------
Problem              Possible Cause      Solution
-----------------------------------------------------------------
Red power-on         Power not on        Make sure ON/OFF switch
indicator not                            is ON
lit
                     Power cable not     Check both ends of
                     plugged in          power cable to be sure
                                         they are fully inserted

                     Power off to wall   Replace fuse or reset
                     outlet              circuit breaker in house
-----------------------------------------------------------------
Red light flashing   Drive failing its   Turn the system off for
                     self test           a moment then try again.
                                         If the light still
                                         flashes, turn the drive
                                         off and on again with
                                         the interface cable
                                         disconnected. If the
                                         problem persists,
                                         contact your dealer. If
                                         unplugging the interface
                                         cable made a difference,
                                         make sure the cable is
                                         properly connected. If
                                         that doesn't work, the
                                         problem is probably in
                                         the cable itself or
                                         somewhere else in the
                                         system
-----------------------------------------------------------------
Programs won't load  Interface cable     Be sure the cable is
and the computer     not well connected  properly connected and
says "DEVICE NOT     or drive not ON     the drive is ON
PRESENT ERROR"
                     Switches on back    Check Appendix A for
                     of drive may not    correct setting to match
                     be set for correct  LOAD command
                     device number

Programs won't       Another part of     Unplug all other
load, but the        the system may be   machines on the
computer and disk    interfering         computer. If that cures
drive give no error                      it, plug them in one at
message                                  a time. The one just
                                         added when the trouble
                                         repeats is most likely
                                         the problem

                                         Trying to load a
                                         machine language
                                         program into BASIC
                                         space will cause this
                                         problem
-----------------------------------------------------------------
Programs won't load  Disk error          Check the error channel
and red light                            to determine the error,
flashes                                  then follow the advice
                                         in Appendix B to correct
                                         it. The error channel is
                                         explained in Chapters 2
                                         and 3

(Be sure to spell program names correctly and include the exact
punctuation when loading the programs)
-----------------------------------------------------------------
Your programs load   Either the          Try another copy of the
OK, but commercial   diskette is         program. If several
programs and those   faulty, or your     programs from several
from other 1581s     disk drive is       sources fail to load,
don't                misaligned          have your dealer align
                                         your disk drive
-----------------------------------------------------------------
Your programs that   Older diskettes     Recopy from backups
used to load, won't  have been damaged
anymore, but
programs saved on    The disk drive has  Have your dealer align
newly-formatted      gone out of         your disk drive
diskettes will       alignment
-----------------------------------------------------------------


1.3. TIPS FOR MAINTENANCE AND CARE

1) KEEP THE DRIVE WELL VENTILATED.
   A  couple  of  inches of space to allow air circulation on all
   sides will prevent heat from building up inside the drive.
2) THE 1581 SHOULD BE CLEANED ONCE A YEAR IN NORMAL USE.
   Several times are likely to need attention: the two read/write
   heads  may  need  cleaning  (with  91%  isopropyl alcohol on a
   cotton  swab).  The  rails along which the head moves may need
   lubrication  (with  a special molybdenum lubricant,  not oil),
   and the write protect sense may need to be dusted. Since these
   chores require special materials or parts, it is best to leave
   the  work  to  an  authorized Commodore service center. If you
   want  to  do  the  work  yourself,  ask  your  dealer  for the
   appropriate materials. IMPORTANT: Home repair of the 1581 will
   void your warranty.
3) USE GOOD QUALITY DISKETTES.
   Badly-made  diskettes  can cause increased wear on the drive's
   read/write head.  If you're using a diskette that is unusually
   noisy, it could be causing added wear and should be replaced.
4) KEEP DISKETTES (AND DISK DRIVE) AWAY FROM MAGNETS.
   That  includes  the electromagnets in telephones, televisions,
   desk lamps, and calculator cords.  Keep smoke, moisture, dust,
   and food off the diskettes.
5) REMOVE A DISKETTE BEFORE TURNING THE DRIVE OFF.
   If  you  don't,  you  might  lose  part or all the data on the
   diskette.
6) DON'T  REMOVE A DISKETTE FROM THE DRIVE  WHILE THE GREEN LIGHT
   IS GLOWING AND THE DRIVE MOTOR IS TURNING.
   If  you  remove  the  diskette   then,   you  might  lose  the
   information currently being written to the diskette.


1.4. INSERTING THE DISKETTE

  Grasp the diskette by the side opposite the metal shutter. Hold
it with the label up  and the write-protect notch down and to the
left  (See Figure 3).  Insert the diskette by pushing it straight
into the drive  with the access slot going in first and the label
last. Be sure the diskette goes in until it drops into place; you
shouldn't have to force it.

                          _______________________
    WRITE PROTECT TAB -->|#| |               |   |
           ____          |_| |_______________|   |
          |    |         |                       |
          |    |         |                       |
          |    |         |          ___          |
          |    |         |         /   \         |
          |    |         |        | Oo  |----------- CENTER HUB
          |    |         |         \___/         |
          |    |         |  _______________      |
        __|    |__       | |   |      |  | |     |
        \        /       |o|   |      |  | |    o|
          \    /         |]|   |      |    |    [|
            \/           |_|___|.__|__|__|_|____/
       INSERT THIS                 |
        EDGE FIRST              SHUTTER


  When  the  write-protect  notch  is  open,  the contents of the
diskette cannot be altered or added to.  That prevents accidental
erasing of information you want to preserve.

  Blank  diskettes may not have a label on them when you purchase
them.


1.5. USING PRE-PROGRAMMED (SOFTWARE) DISKETTES

  Your  software  user's  guide  should  list  the  procedure for
loading  the  program  into  your  computer.  Nevertheless, we've
included the following procedure as a general guide.  You'll also
use  this  procedure  to  load  programs  or  files from your own
diskettes.  For  purposes  of  demonstration,  use  the Test/Demo
diskette included with the disk drive.

1) Turn on system.
2) Insert diskette.
3) If you are using a VIC 20,  Commodore 64,  or  a Commodore 128
   computer in C64 mode, type: LOAD"HOW TO USE",8
   If you are using a Plus/4 or Commodore 128 in C128 mode, type:
   DLOAD"HOW TO USE"
4) Press the [RETURN] key.
5) The following will then appear on the screen.

   SEARCHING FOR HOW TO USE
   LOADING
   READY.
   _

6) Type: RUN
7) Press the [RETURN] key.

  To load a different program or file, simply substitute its name
in place of HOW TO USE inside the quotation marks.

+---------------------------- NOTE -----------------------------+
| The HOW TO USE program is the key to the  Test/Demo diskette. |
| When you LOAD and RUN it,  it provides instructions for using |
| the rest of the programs on the diskette.  To  find  out what |
| programs are on your Test/Demo diskette, refer to the section |
| entitled "DIRECTORIES" later in this chapter.                 |
+---------------------------------------------------------------+

  If  a  program  doesn't  load  or  run properly using the above
method,  it  may  be  that  it is a machine language program. But
unless  you'll  be doing advanced programming,  you need not know
anything about machine language.  A program's user's guide should
tell  you  if it is written in machine language.  If it is, or if
you  are  having trouble loading a particular program, simply add
a ,1 (comma and number 1) at the end of the command.

+---------------------------- NOTE -----------------------------+
|   Throughout  this  manual,  when the format for a command is |
| given,  it will follow a particular style.  Anything  that is |
| capitalized must be typed in exactly as it  is  shown  (these |
| commands are listed in capital letters for style purposes, DO |
| NOT use the SHIFT key when entering these commands). Anything |
| in  lower  case  is more or less a definition of what belongs |
| there. Anything in brackets is optional.                      |
|   For instance, in the format for the HEADER command given on |
| the following page,  the word  HEADER,  the capital I in Iid, |
| the capital D in Ddrive#,  and the capital U in Udevice# must |
| all be typed in as is (Ddrive# and Udevice# are optional).    |
|   On the other hand,  diskette name tells you  that  you must |
| enter a name for the diskette,  but it is up to you to decide |
| what that name will be.  Also,  the id in Iid is left to your |
| discretion,  as is the  device#  in  Udevice#.  The drive# in |
| Ddrive#  is  always  0 on the 1581,  but could be 0 or 1 on a |
| dual disk drive.  Be aware,  however,  that there are certain |
| limits placed on what you can use. In each case, those limits |
| are explained immediately following the format (for instance, |
| the diskette name cannot be more than sixteen characters  and |
| the device# is usually 8).                                    |
|   Also  be  sure to type in all punctuation exactly where and |
| how it is shown in the format.                                |
|   Finally, press the [RETURN] key at the end of each command. |
+---------------------------------------------------------------+


1.6. HOW TO PREPARE A NEW DISKETTE

  A diskette needs a pattern of circular magnetic tracks in order
for  the  drive's  read/write  head  to  find  things on it. This
pattern is not on your diskettes  when you buy them,  but you can
use  the  HEADER  command  or  the  NEW  command  to  add it to a
diskette.  That  is  known  as  formatting the disk.  This is the
command to use with the C128 in C128 mode or Plus/4:

  HEADER "diskette name",Iid,Ddrive#[,Udevice#]

where "diskette name" is any desired name for the diskette, up to
16  characters  long  (including spaces).  "id"  can  be  any two
characters as long as they don't form a BASIC keyword (such as IF
or  ON)  either  on  their own or with the capital I before them.
"drive#" is 0.  "device#" is 8, unless you have changed it as per
instructions in Appendix A  (the 1581 assumes 8 even if you don't
type it in).

  The command for the C64, VIC 20, or C128 in C64 mode is this:

  OPEN 15,device#,15,"NEWdrive#:diskette name,id"
  CLOSE 15

  The  device#,  drive#,  diskette  name,  and id are the same as
described above.
  The  OPEN  command  is  explained in the next chapter. For now,
just copy it as is.

+---------------------------- NOTE -----------------------------+
| FOR ADVANCED USERS                                            |
|                                                               |
| If you want to use variables for the diskette name or id, the |
| format is as follows:                                         |
|                                                               |
|   C128, Plus/4: HEADER (A$),I(B$),D0                          |
|                                                               |
|   C64:          OPEN 15,8,15:PRINT#15,"N0:"+A$+","+B$:CLOSE15 |
|                                                               |
| Where:                                                        |
|                                                               |
|   A$ contains the diskette name (16 character limit)          |
|   B$ contains the id (2 characters long)                      |
+---------------------------------------------------------------+

  After you format a particular diskette,  you can reformat it at
any  time.  You can change its name and erase its files faster by
omitting the id number in the HEADER command.


1.7. DISKETTE DIRECTORY

  A directory is a list of the files on a diskette.  To  view the
directory on the  C128 or Plus/4,  type the word  DIRECTORY  on a
blank line and press the  [RETURN]  key or simply press the  [F3]
key  on  the C128.  That doesn't erase anything in memory, so you
can  call up a directory anytime  --  even from within a program.
The C64 directory command, LOAD"$",8 (press [RETURN]) LIST (press
[RETURN]), does erase what's in memory.
  If a directory doesn't all fit on the screen, it will scroll up
until  it  reaches the last line.  If you want to pause, stop, or
slow  down  the  scrolling,  refer  to your particular computer's
user's manual for instructions as to which keys to use.
  To  get  an  idea  of  what  a  directory  looks like, load the
directory from the Test/Demo diskette.
  The 0 on the left-hand side of the top line is the drive number
of the 1581.  The diskette name is next, followed by the diskette
id  --  both  of  which  are  determined  when  the  diskette  is
formatted.
  The  3D  at the end of the top line means the 1581 uses version
3D of Commodore's disk operating system (DOS).
  Each   of   the   remaining  lines  provides  three  pieces  of
information  about the files on the diskette.  At the left end of
each  line  is  the size of the file in blocks of 254 characters.
Four  blocks  are  equivalent  to  almost 1K of memory inside the
computer.  The  middle  of the line contains the name of the file
enclosed in quotation marks.  All characters within the quotation
marks  are  part  of  the  filename.  The right side of each line
contains a three-letter abbreviation of the file type.  The types
of files are described in later chapters.
  The  bottom  line  of  a  directory  shows  how many blocks are
available  for  use.  This  number  ranges  from  3160 on a newly
formatted diskette to 0 on one that is completely full.


1.8. SELECTIVE DIRECTORIES

  By altering the directory  LOAD command,  you can create a sub-
directory that lists a single selected type of file. For example,
you  could  request  a list of all sequential data files (Chapter
4), or one of all the relative data files (Chapter 5). The format
for this command is:

  LOAD"$0:pattern=filetype",8    (for the C64)

where pattern specifies a particular group of files, and filetype
is  the  one-letter  abbreviation  for  the types of files listed
below:

  P = Program
  S = Sequential
  R = Relative
  U = User

The command for the C128 and Plus/4 is this:

  DIRECTORY"pattern=filetype"

Some examples:

  LOAD"$0:*=R",8  and  DIRECTORY"*=R" display all relative files.

  LOAD"$0:Z*=R",8  and  DIRECTORY"Z*=R"  display  a sub-directory
  consisting of all relative files  that start with the letter Z.
  (the asterisk (*) is explained in the Section 1.10.)


1.9. PRINTING A DIRECTORY

  To printout a directory, use the following:

  LOAD"$",8
  OPEN 4,4:CMD 4:LIST
  PRINT#4:CLOSE 4


1.10. PATTERN MATCHING

  You  can  use  special  pattern-matching  characters  to load a
program   from  a  partial  name  or  to  provide  the  selective
directories described earlier.
  The  two  characters  used in pattern matching are the asterisk
(*)  and  the question mark  (?).  They act something like a wild
card in a game of cards.  The difference between the two  is that
the  asterisk  makes  all  characters in  and beyond its position
wild,  while  the question mark makes only its own position wild.
Here are some examples and their results:

  LOAD"A*",8  loads the first file on disk that begins with an A,
  regardless of what follows

  DLOAD"SM?TH"  loads  the  first  file that starts with SM, ends
  with TH, and one other character between

  DIRECTORY"Q*"  loads  a  directory  of  files whose names begin
  with Q

  LOAD"*",8  is a special case. When an asterisk is used alone as
  a name,  it matches the last file used  (on the C64 and C128 in
  C64 mode).

  LOAD "0:*",8 loads the first file on the diskette (C64 and C128
  in C64 mode).

  DLOAD"*"  loads the first file on the diskette (Plus/4 and C128
  in C128 mode).


1.11. SPLAT FILES

  One  indicator you may occasionally notice on a directory line,
after  you  begin  saving  programs  and  files,  is  an asterisk
appearing  just  before  the file type of a file that is 0 blocks
long.  This  indicates  the file was not properly closed after it
was created, and that it should not be relied upon. These "splat"
files normally need to be erased from the diskette and rewritten.
However,  do not use the SCRATCH command to get rid of them. They
can  only  be  safely erased by the VALIDATE or COLLECT commands.
One  of  these  should  normally be used whenever a splat file is
noticed on a diskette. All of these commands are described in the
following chapters.
  There  are  two  exceptions  to the above warning:  one is that
VALIDATE  and  COLLECT  cannot  be  used  on  some diskettes that
include direct access  (random) files  (Chapter 6).  The other is
that  if  the information in the splat file was crucial and can't
be  replaced,  there is a way to rescue whatever part of the file
was  properly  written.  This  option  is  described  in the next
chapter.



2. BASIC 2.0 COMMANDS

  This chapter describes the disk commands used with the  VIC 20,
Commodore 64 or the Commodore 128 computer in C64 mode. These are
Basic 2.0 commands.
  You send command data to the drive through something called the
command  channel.  The first step is to open the channel with the
following command:

  OPEN 15,8,15

  The  first  15  is a file number or channel number. Although it
could  be  any  number from 1 to 255,  we'll use 15 because it is
used  to match the secondary address of 15,  which is the address
of the command channel. The middle number is the primary address,
better known as the  device number.  It is usually 8,  unless you
change it (see Appendix A).
  Once  the  channel  has been opened,  use the PRINT# command to
send information to the disk drive  and  the  INPUT#  command  to
receive  information  from the drive.  You must close the channel
with the CLOSE 15 command.
  The  following  examples show the use of the command channel to
NEW an unformatted disk:

  OPEN 15,8,15
  PRINT#15,"NEWdrive#:diskname,id"
  CLOSE 15

  You can combine the first two statements and abbreviate the NEW
command like this:

  OPEN 15,8,15,"Ndrive#:diskname,id"

  If  the  command  channel  is  already  open,  you must use the
following  format  (trying to open a channel that is already open
results in a "FILE OPEN" error):

  PRINT#15,"Ndrive#:diskname,id"


2.1. ERROR CHECKING

  In Basic 2.0,  when the red drive light flashes, you must write
a small program to find out what the error is. This causes you to
lose  any  program variables already in memory.  The following is
the error check program:

  10 OPEN 15,8,15
  20 INPUT#15,EN,EM$,ET,ES
  30 PRINT EN,EM$,ET,ES
  40 CLOSE 15

  This  little  program  reads  the error channel into four BASIC
variables  (described  below),  and  prints  the  results  on the
screen.  A message is displayed whether there is an error or not,
but if there was an error, the program clears it from disk memory
and stops the error light from blinking.
  Once  the  message  is  on  the  screen,  you can look it up in
Appendix B to see what it means, and what to do about it.
  For those of you who are writing programs,  the  following is a
small error-checking subroutine you can include in your programs:

  59980 REM READ ERROR CHANNEL
  59990 INPUT#15,EN,EM$,ET,ES
  60000 IF EN>1 THEN PRINT EN,EM$,ET,ES: STOP
  60010 RETURN

  This  assumes  file  15  was opened earlier in the program, and
that it will be closed at the end of the program.
  The  subroutine  reads  the  error channel and puts the results
into  the  named  variables  --  EN  (Error  Number),  EM$ (Error
Message),  ET (Error Track),  and ES (Error Sector). Of the four,
only  EM$  has  to  be a string.  You could choose other variable
names, although these have become traditional for this use.
  Two error numbers are harmless -- 0 means everything is OK, and
1  tells  how  many  files  were  erased  by  a  SCRATCH  command
(described  later  in  this  chapter).  If  the  error  status is
anything else,  line 60000 prints the error message and halts the
program.
  Because  this  is  a  subroutine,  you access it with the BASIC
GOSUB  command,  either  in immediate mode or from a program. The
RETURN  statement  in line 60010 will jump back to immediate mode
or the next statement in your program, whichever is appropriate.


2.2. BASIC HINTS

1. It  is  best  to  open  file  15  once  at the very start of a
program,  and only close it at the end of the program,  after all
other files  have already been closed.  By opening it once at the
start,  the  file  is  open  whenever  needed  for  disk commands
elsewhere in the program.

2. If  BASIC  halts with an error when you have files open, BASIC
aborts  them  without closing them properly on the disk. To close
them properly on the disk, you must type:

  CLOSE 15: OPEN 15,8,15,"I": CLOSE 15

This  opens  the command channel and immediately closes it, along
with all other disk files.  Failure to close a disk file properly
both  in  BASIC  and  on the disk may result in losing the entire
file.

3. One  disk  error  message  is  not  always an error. Error 73,
"COPYRIGHT CBM DOS V10 1581"  will  appear  if  you read the disk
error  channel  before sending any disk commands when you turn on
your computer.  This is a handy way to check which version of DOS
you  are  using.  However,  if  this message appears later, after
other disk commands, it means there is a mismatch between the DOS
used  to  format  your diskette and the DOS in your drive. DOS is
Disk Operating System.

4. To reset drive, type: OPEN 15,8,15,"UJ":CLOSE 15.


2.3. SAVE

  The  SAVE  command  preserves  a program or file on a formatted
diskette for latter use.

FORMAT FOR THE SAVE COMMAND:

  SAVE "drive#:file name",device#

where   "file  name"  is  any  string  expression  of  up  to  16
characters,  preceded  by  the  drive  number  and  a  colon, and
followed by the device number of the disk, normally 8.
  However,  the  SAVE  command  will not work in copying programs
that  are  not in the BASIC text area,  such as "DOS 5.1" for the
C64.  To copy it and similar machine-language programs,  you will
need a machine-language monitor program, such as the one resident
in the C128.

FORMAT FOR A MONITOR SAVE:

  S "drive#:file name",device#,starting address,ending address+1

where "drive#:" is the drive number,  0 on the 1581;  "file name"
is any valid file name up to 14 characters long  (leaving two for
the  drive  number  and  colon);  "device#" is a two digit device
number,  normally 08 (the leading 0 is required); and the address
to be saved are given in Hexadecimal but without a leading dollar
sign  ($).  Note  the  ending address listed must be one location
beyond the last location to be saved.

EXAMPLE:

  Here is the required syntax to SAVE a copy of "DOS 5.1":

  S "0:DOS 5.1",08,CC00,D000


2.4. SAVE WITH REPLACE

  If a file already exists, it can't be saved again with the same
name  because  the  disk  drive only allows one copy of any given
file name per diskette. It is possible to get around this problem
using the  RENAME and  SCRATCH commands described later. However,
if  all  you  wish to do is replace a program or data file with a
revised  version,  another  command  is more convenient. Known as
SAVE-WITH-REPLACE, or @SAVE.  This option tells the disk drive to
replace any file it finds in the diskette directory with the same
name, substituting the new file for the old version.

FORMAT FOR SAVE WITH REPLACE:

  SAVE "@drive#:file name",device#

where all the parameters are as usual except for adding a leading
"at" sign (@). The "drive#:" is required here.

EXAMPLE:

  SAVE"@0:REVISED PROGRAM",8

  The  actual  procedure   is  that  the  new  version  is  saved
completely, then the old version is erased. Because it works this
way,  there  is  little  danger  a  disaster such as losing power
midway  through  the  process  would destroy both the old and new
copies  of the file.  Nothing happens to the old copy until after
the new copy is saved properly.


2.5. VERIFY

  The  VERIFY  command can be used to make certain that a program
file  was  properly  saved  to disk.  It works much like the LOAD
command,  except  that  it  only  compares  each character in the
program  against  the  equivalent  character  in  the  computer's
memory, instead of actually being copied into memory.
  If  the  disk  copy of the program differs even a tiny bit from
the copy in memory, "VERIFY ERROR" will be displayed, to tell you
that the copies differ. This doesn't mean either copy is bad, but
if they were supposed to be identical, there is a problem.
  Naturally,  there's no point in trying to VERIFY a disk copy of
a program after the original is no longer in memory. With nothing
to compare to,  an apparent error will always be announced,  even
though  the  disk copy is automatically verified as it is written
to the diskette.

FORMAT FOR THE VERIFY COMMAND:

  VERIFY "drive#:pattern",device#,relocate flag

where  "drive#:"  is  an optional drive number,  "pattern" is any
string expression that evaluates to a file name,  with or without
pattern-matching  characters,  and  "device#"  is the disk device
number, normally 8. If the relocate flag is present and equals 1,
the  file  will  be verified where originally saved,  rather than
relocated into the BASIC text area.

A useful alternate form of the command is:

  VERIFY "*",device#

It  verifies  the last files used without having to type its name
or drive number. However, it won't work properly after SAVE-WITH-
REPLACE,  because the last file used was the one deleted, and the
drive  will  try  to  compare  the deleted file to the program in
memory.  No  harm will result,  but "VERIFY ERROR" will always be
announced.  To  use VERIFY after @SAVE,  include at least part of
the file name that is to be verified in the pattern.

  One  other  note  about  VERIFY  -- when you VERIFY a relocated
BASIC  file,  an  error  will  nearly always be announced, due to
changes  in  the  link  pointers  of  BASIC  programs made during
relocation.  It  is best to VERIFY files saved from the same type
of  machine,  and  identical  memory  size.  For example, a BASIC
program  saved from a Plus/4 can't be verified easily with a C64,
even  when  the  program  would  work fine on both machines. This
shouldn't  matter,  as the only time you'll be verifying files on
machines  other  than  the  one  which wrote them is when you are
comparing  two  disk  files  to see if they are the same. This is
done by loading one and verifying against the other, and can only
be  done  on the same machine and memory size as the one on which
the files were first created.


2.6. SCRATCH

  The SCRATCH command allows you to erase unwanted files and free
the space they occupied for use by other files. It can be used to
erase either a single file  or several files at once via pattern-
matching.

FORMAT FOR THE SCRATCH COMMAND:

  PRINT#15,"SCRATCH0:pattern"

or abbreviate it as:

  PRINT#15,"S0:pattern"

"pattern"  can  be any file name or combination of characters and
wildcard characters.  As usual, it is assumed the command channel
has  already  been  opened  as  file 15.  Although not absolutely
necessary,  it  is  best  to  include the drive number in SCRATCH
commands.
  If  you  check  the  error channel after a SCRATCH command, the
value  for  ET  (error  track)  will tell you how many files were
scratched.  For example,  if your diskette contains program files
named  "TEST",  "TRAIN",  "TRUCK" and "TAIL", you may SCRATCH all
four,  along  with any other files beginning with the letter "T",
by using the command:

  PRINT#15,"S0:T*"

Then, to prove they are gone, you can type:

  GOSUB 59990

to  call  the  error  checking  subroutine  given earlier in this
chapter.  If  the  four listed were the only files beginning with
"T", you will see:

  01, FILES SCRATCHED,04,00
  READY.

The "04" tells you 4 files were scratched.


2.7. MORE ABOUT SCRATCH

  SCRATCH  is  a powerful command and should be used with caution
to be sure you delete only the files you really want erased. When
using  it  with  a  pattern,  we  suggest  you first use the same
pattern in a  DIRECTORY  command,  to be sure exactly which files
will  be  deleted.  That  way you'll have no unpleasant surprises
when you use the same pattern in the SCRATCH command.
  If you accidentally SCRATCH a file you shouldn't have, there is
still  a  chance of saving it by using the "UNSCRATCH" program on
your Test/Demo diskette.

More about Splats

  Never SCRATCH a splat file.  These are files  that show up in a
directory listing with an asterisk (*)  just before the file type
for  an entry.  The asterisk (or splat) means that file was never
properly  closed,  and  thus  there  is  no valid chain of sector
links for the SCRATCH command to follow in erasing the file.
  If you  SCRATCH such a file,  odds are you will improperly free
up  sectors  that are still needed by other programs or files and
cause  permanent damage to those later when you add more files to
the  diskette.  If you find a splat file,  or if you discover too
late  that  you have scratched such a file,  immediately validate
the diskette using the  VALIDATE  command described later in this
chapter.  If  you  have  added  any  files  to the diskette since
scratching  the  splat  file,  it is best to immediately copy the
entire  diskette onto another fresh diskette,  but do this with a
copy  program  rather than with a backup program.  Otherwise, the
same problem will be recreated on the new diskette.  When the new
copy is done,  compare the number of blocks free in its directory
to  the  number  free  on  the original diskette.  If the numbers
match, no damage has been done.  If not, very likely at least one
file  on  the  diskette  has  been  corrupted,  and all should be
checked immediately.

Locked Files

  Occasionally,  a diskette will contain a locked file; one which
cannot  be  erased with the  SCRATCH  command.  Such files may be
recognized  by  the  "<"  character which immediately follows the
file type in their directory entry. If you wish to erase a locked
file, you will have to use a sector editor program to clear bit 6
of  the  file-type  byte  in the directory entry on the diskette.
Conversely, to lock a file, you would set bit 6 of the same byte.


2.8. RENAME

  The RENAME command allows you to alter the name of a program or
other file in the diskette directory. Since only the directory is
affected, RENAME works very quickly.

FORMAT FOR RENAME COMMAND:

  PRINT#15,"RENAME0:new name=old name"

or it may be abbreviated as:

  PRINT#15,"R0:new name=old name"

where  "new name" is the name you want the file to have, and "old
name"  is  the name it has now.  "new name" may be any valid file
name,  up  to  16  characters  in length.  It is assumed you have
already opened file 15 to the command channel.
  One  caution  --  be  sure  the  file you are renaming has been
properly closed before you rename it.

EXAMPLES:

Just before saving a new copy of a "calendar" program,  you might
type:

  PRINT#15,"R0:CALENDAR/BACKUP=CALENDAR"

Or to move a program called  "BOOT",  currently the first program
on a diskette to someplace else in the directory, you might type:

  PRINT#15,"R0:TEMP=BOOT"

followed by a COPY command (described later),  which turns "TEMP"
into a new copy of  "BOOT",  and finishing with a SCRATCH command
to get rid of the original copy of "BOOT".


2.9. RENAMING AND SCRATCHING TROUBLESOME FILES

  Eventually,  you  may  run  across  a  file  which  has  an odd
filename,  such as a comma by itself (",") or one that includes a
Shifted Space (a Shifted Space looks same as a regular space, but
if  a  file  with a space in its name won't load properly and all
else is correct,  it's probably a Shifted Space).  Or perhaps you
will find one that includes non-printing characters. Any of these
can be troublesome.  Comma files,  for instance, are an exception
to  the  rule  that no two files can have the same name. Since it
shouldn't  be possible to make a file whose name is only a comma,
the disk never expects you to do it again.
  Files  with  a   Shifted  Space  in  their  name  can  also  be
troublesome,  because  the  disk  interprets the Shifted Space as
signaling  the end of the file name,  and prints whatever follows
after  the  quotation  mark  that  marks the end of a name in the
directory.  This  technique can be useful by allowing you to have
a  long file name,  and making the disk recognize a small part of
it  as  being  the same as the whole thing without using pattern-
matching characters.
  In any case,  if  you have a troublesome filename,  you can use
the  CHR$()  function  to  specify troublesome characters without
typing  them  directly.  This  may allow you to build them into a
RENAME  command.  If  this  fails,  you may also use the pattern-
matching characters in a SCRATCH command. This gives you a way to
specify the name without using the troublesome characters at all,
but also means loss of your file.
  For  example,  if  you  have  managed  to  create  a file named
""MOVIES",  with an extra quotation mark at the front of the file
name,  you can rename it to  "MOVIES" using the CHR$() equivalent
of a quotation mark in the RENAME command:

  PRINT#15,"R0:MOVIES="+CHR$(34)+"MOVIES"

The  CHR$(34)  forces  a  quotation  mark into the command string
without  upsetting  BASIC.  The  procedure  for  a file name that
includes a Shifted Space is similar, but uses CHR$(160).
  In cases  where even this doesn't work,  for  example,  if your
diskette contains a comma file,  (one named ",")  you can get rid
of it this way:

  PRINT#15,"S0:?"

  This example deletes all files with one-character names.

  Depending  on  the  exact  problem,  you  may  have  to be very
creative in choosing pattern-matching characters that will affect
only  the desired file,  and may have to rename other files first
to keep them from being scratched.
  In  some  cases,  it  may  be easier to copy desired files to a
different diskette and leave the troublesome files behind.


2.10. COPY

  The COPY command allows you to make a spare copy of any program
or file on a diskette.  On a single drive like the 1581, the copy
must  be  on  the  same diskette,  which means it must be given a
different name from the file copied. It's also used to combine up
to  four sequential data file  (linking the files one to another,
end  to end in a chain).  Files are linked in the order and other
files  on  the  diskette  are  not changed.  Files must be closed
before they are copied or linked.

FORMAT FOR THE COPY COMMAND:

  PRINT#15,"COPYdrive#:new file=old file"

EXAMPLES:

  PRINT#15,"COPY0:BACKUP=ORIGINAL"

or abbreviated as:

  PRINT#15,"Cdrive#:new file=old file"

  PRINT#15,"C0:BACKUP=ORIGINAL"

where  "drive#"  is the drive number  "new file"  is the copy and
"old file" is the original.

FORMAT FOR THE COMBINE OPTION:

  PRINT#15,"Cdrive#:new file=file 1,file 2,file 3,file 4"

where "drive#" is always 0,

+---------------------------- NOTE -----------------------------+
| The  length  of  a  command string (command and filenames) is |
| limited to 41 characters.                                     |
+---------------------------------------------------------------+

EXAMPLES:

  After  renaming  a  file  named  "BOOT"  to  "TEMP" in the last
section's  example,  you can use the COPY command to make a spare
copy of the program elsewhere on the diskette, under the original
name:

  PRINT#15,"C0:BOOT=TEMP"

  After  creating  several small sequential files that fit easily
in  memory  along  with  a program we are using,  you can use the
concatenate option to combine them in a master file,  even if the
result  is  too  big  to  fit in memory.  (Be sure it will fit in
remaining  space on the diskette  --  it will be as big as sum of
the sizes of the files in it).

  PRINT#15,"C0:A-Z=A-G,H-M,N-Z"


2.11. VALIDATE

  The VALIDATE command recalculates the  Block  Availability  Map
(BAM)  of  the  current  diskette,  allocating only those sectors
still  being  used by valid,  properly-closed files and programs.
All other sectors  (blocks) are left unallocated and free for re-
use, and all improperly closed files are automatically scratched.
This  brief  description  of its workings doesn't indicate either
the power or the danger of the VALIDATE command.  Its power is in
restoring  to  good  health  many  diskettes whose directories or
block availability maps have become muddled.  Any time the blocks
used  by  the  files  on a diskette plus the blocks shown as free
don't add up to the 3160 available on a fresh diskette,  VALIDATE
is  needed,  with  one  exception  below.  Similarly,  any time a
diskette   contains   an  improperly-closed  file  (splat  file),
indicated  by  an  asterisk  (*)  next  to  its  file type in the
directory,  that diskette needs to be validated. In fact, but for
the  one  exception,  it  is  a  good  idea to VALIDATE diskettes
whenever you are the least bit concerned about their integrity.
  The  exception  is diskettes containing direct access files, as
described in Chapter 6.  Most direct access (random) files do not
allocate  their  sectors  in  a  way  the  VALIDATE  command  can
recognize.  Thus, using VALIDATE on such a diskette may result in
unallocating  all  direct  access  files,  with loss of all their
contents   when  other  files  are  added.   Unless  specifically
instructed otherwise, never use VALIDATE on a diskette containing
direct access files.

FORMAT FOR THE VALIDATE COMMAND:

  PRINT#15,"VALIDATE0"

or abbreviated as:

  PRINT#15,"V0"

where  "0"  is the drive number.  As usual, it is assumed file 15
has  been  opened to the command channel and will be closed after
the command has been executed.


2.12. INITIALIZE

  When  a  diskette is inserted into the drive,  its directory is
automatically  re-read  into  a  disk  buffer.  You would use the
command only if that information became unreliable.

FORMAT FOR THE INITIALIZE COMMAND:

  PRINT#15,"INITIALIZEdrive#"

or it may be abbreviated to

  PRINT#15,"Idrive#"

EXAMPLE:

  PRINT#15,"I0"

  PRINT#15,"INITIALIZE0"

where the command channel is assumed to be opened by file 15, and
"drive#" is 0.



3. BASIC 7.0 COMMANDS


  This  chapter  describes  the  disk  commands   used  with  the
Commodore 128 computer  (in C128 mode).  This is BASIC 7.0, which
includes BASIC 2.0,  BASIC 3.5,  and  BASIC 4.0 commands,  all of
which can be used.

3.1. ERROR CHECKING

  When  the  drive  light  (red light) flashes,  you must use the
following command to find out what the error is:

  PRINT DS$

  A  message  is  displayed  whether there is an error or not. If
there  was an error,  this command clears it from disk memory and
turns off the error light on the disk drive.
  Once  the  message  is  on  the  screen,  you can look it up in
Appendix B to see what it means, and what to do about it.
  For those of you who are writing programs,  the  following is a
small error-checking subroutine you can include in your programs:

  59990 REM READ ERROR CHANNEL
  60000 IF DS>1 THEN PRINT DS$: STOP
  60010 RETURN

  The  subroutine  reads  the  error channel and puts the results
into  the  reserved  variables  DS  and  DS$.  They  are  updated
automatically by BASIC.
  Two error numbers are harmless -- 0 means everything is OK, and
1  tells  how  many  files  were  erased  by  a  SCRATCH  command
(described  later  in  this  chapter).  If  the  error  status is
anything else,  line 60000 prints the error message and halts the
program.
  Because  this  is  a  subroutine,  you access it with the BASIC
GOSUB  command,  either  in immediate mode or from a program. The
RETURN  statement  in line 60010 will jump back to immediate mode
or the next statement in your program, whichever is appropriate.


3.2. SAVE

  This  command  will save a program or file so you can reuse it.
The  diskette  must  be  formatted before you can save it to that
diskette.

FORMAT FOR THE SAVE COMMAND:

  DSAVE "file name"[,Ddrive#][,Udevice#]

  This  command  will  not  work in copying programs that are not
written  in  BASIC.  To copy these machine-language programs, you
can use the BSAVE command or the built-in Monitor S command.

FORMAT FOR THE BSAVE COMMAND:

  BSAVE "file name"[,Ddrive#][,Udevice#][,Bbank#]
                   [,Pstarting address][TO Pending address+1]

where  the  usual options are the same and bank# is one of the 16
banks of the C128.  The address to be saved are given in decimal.
Note  that  the ending address must be 1 location beyond the last
location to be saved.
  To access a built-in monitor, type MONITOR.  To exit a monitor,
type X alone on a line.

FORMAT FOR A MONITOR SAVE:

  S "drive#:file name",device#,starting address,ending address+1

where "drive#:" is the drive number,  0 on the 1581;  "file name"
is any valid file name up to 14 characters long  (16 if you leave
out the drive# and the colon that follows it); "device#" is a two
digit device number,  normally  08 on the 1581  (the leading 0 is
required); and the addresses to be saved are given in Hexadecimal
(base 16), but without a leading dollar sign (for the Plus/4). On
the C128, the addresses need not be in Hexadecimal. Note that the
ending address listed must be 1 location beyond the last location
to be saved.


3.3. SAVE WITH REPLACE

  If a file already exists, it can't be saved again with the same
name  because  the  disk  drive allows only one copy of any given
file name per diskette. It is possible to get around this problem
using the  RENAME  and  SCRATCH  commands described later in this
chapter.  If all you wish to do is replace a program or data file
with a revised version, another command is more convenient. Known
as SAVE-WITH-REPLACE, or @SAVE.  This option tells the disk drive
to  replace  any file it finds in the diskette directory with the
same name, substituting the new file for the old version.

FORMAT FOR SAVE WITH REPLACE:

  DSAVE "@file name"[,Ddrive#][,Udevice#]

  The  actual  procedure  is  this  --  the  new version is saved
completely,  then  the old version is scratched and its directory
entry altered to point to the new version.  Because it works this
way,  there  is little danger a disaster such as having the power
going  off  midway through the process would destroy both the old
and new copies of the file. Nothing happens to the old copy until
after the new copy is saved properly.


3.4. VERIFY

  This  command  makes  a  byte-by-byte comparison of the program
currently   in   memory  against  a  program  on  diskette.  This
comparison includes the BASIC line links,  which may be different
for different types of memory configurations.  What this means is
that  a  program  saved to disk on a C64 and reloaded into a C128
wouldn't   verify  properly  because  the  line  links  point  to
different  memory  locations.  If  the  disk  copy of the program
differs at all from the copy in memory,  a "VERIFY ERROR" will be
displayed. This doesn't mean either copy is bad, but if they were
supposed to be identical, there is a problem.

FORMAT FOR THE DVERIFY COMMAND:

  DVERIFY "file name"[,Ddrive#][,Udevice#]

  The  following  version of the command verifies a file that was
just saved:

  DVERIFY"*"

  This  command  won't  work  properly  after  SAVE-WITH-REPLACE,
because  the  last  file used was the one deleted,  and the drive
will try to compare the deleted file to the program in memory. No
harm will result, but "VERIFY ERROR" will always be announced. To
use  DVERIFY after @SAVE,  include at least part of the file name
that is to be verified in the pattern.


3.5. COPY

  The COPY command allows you to make a spare copy of any program
or file on a diskette. However, on a single derive like the 1581,
the  copy  must  be on the same diskette,  which means it must be
given a different name from the file copied.  The source file and
other files on the diskette are not changed. Files must be closed
before they can be copied or concatenated.

FORMAT FOR THE COPY COMMAND:

  COPY [Ddrive#,]"old file name" TO [Ddrive#,]"new file name"
       [,Udevice#]

where both drive#s would be 0 if included.


3.6. CONCAT

  The  CONCAT  command  allows  you  to concatenate (combine) two
sequential files.

FORMAT FOR THE CONCAT COMMAND:

  CONCAT [Ddrive#,]"add file" TO [Ddrive#,] "master file"
         [,Udevice#]

where  the  optional  "drive#"  would be 0 in both cases. The old
"master file"  is  deleted and replaced with a new  "master file"
which  is  the concatenation of the old  "master file"  and  "add
file".

+---------------------------- NOTE -----------------------------+
| The  length  of  a  command string (command and filenames) is |
| limited to 41 characters.                                     |
+---------------------------------------------------------------+


3.7. SCRATCH

  The  SCRATCH  command allows you to erase unwanted programs and
files  from  your diskettes,  and free up the space they occupied
for  use  by  other  files and programs.  It can be used to erase
either  a  single  file,  or  several  files at once via pattern-
matching.

FORMAT FOR THE SCRATCH COMMAND:

  SCRATCH "pattern"[,Ddrive#][,Udevice#]

where  "pattern"  is  any  valid  file  name  or pattern-matching
character.

  You will be asked as a precaution:

  ARE YOU SURE?_

If you ARE sure, simply press Y and RETURN.  If not, press RETURN
alone or type any other answer, and the command will be canceled.
  The  number  of files that were scratched will be automatically
displayed.  For example,  if your diskette contains program files
named "TEST",  "TRAIN",  "TRUCK", and "TAIL", you may SCRATCH all
four,  along  with any other files beginning with the letter "T",
by using the command:

  SCRATCH "T*"

and  if  the  four listed were the only files beginning with "T",
you will see:

  01, FILES SCRATCHED,04,00
  READY
  _

The "04" tells you 4 files were scratched.

  You can perform a  SCRATCH within a program,  but there will be
no prompt message displayed.


3.8. MORE ABOUT SCRATCH

  SCRATCH  is  a powerful command and should be used with caution
to be sure you delete only the files you really want erased. When
using  it  with  a  pattern,  we  suggest  you first use the same
pattern in a  DIRECTORY  command,  to be sure exactly which files
will  be  deleted.  That  way you'll have no unpleasant surprises
when you use the same pattern in the SCRATCH command.
  If you accidentally SCRATCH a file you shouldn't have, there is
still  a  chance of saving it by using the "UNSCRATCH" program on
your Test/Demo diskette.

More about Splats

  Never SCRATCH a splat file.  These are files  that show up in a
directory listing with an asterisk (*)  just before the file type
for  an entry.  The asterisk (or splat) means that file was never
properly  closed,  and  thus  there  is  no valid chain of sector
links for the  SCRATCH  command to follow in erasing the file. If
you  SCRATCH  such  a file,  odds are you will improperly free up
sectors  that  are  still  needed  by other programs or files and
cause  permanent damage to those later when you add more files to
the diskette.
  If you find a splat file,  or if you discover too late that you
have  scratched  such  a  file, immediately validate the diskette
using the COLLECT command described later in this chapter. If you
have  added  any files to the diskette since scratching the splat
file,  it  is  best  to immediately copy the entire diskette onto
another  fresh  diskette,  but do this with a copy program rather
than with a backup program.  Otherwise,  the same problem will be
recreated on the new diskette. When the new copy is done, compare
the  number of blocks free in its directory to the number free on
the  original diskette.  If the numbers match, no damage has been
done.  If not,  very likely at least one file on the diskette has
been corrupted, and all should be checked immediately.

Locked Files

  Occasionally,  a diskette will contain a locked file; one which
cannot  be  erased  with  the  SCRATCH command. Such files may be
recognized  by  the  "<"  character which immediately follows the
file type in their directory entry. If you wish to erase a locked
file,  you  will have to use a disk monitor to clear bit 6 of the
file-type   byte   in   the  directory  entry  on  the  diskette.
Conversely, to lock a file, you would set bit 6 of the same byte.


3.9. RENAME

  The RENAME command allows you to alter the name of a program or
other file in the diskette directory. Since only the directory is
affected, RENAME works very quickly.  If you try to RENAME a file
by using a file name already in the directory,  the computer will
respond  with  a  "FILE EXISTS"  error.  A file  must be properly
closed before it can be renamed.

FORMAT FOR RENAME COMMAND:

  RENAME [Ddrive#,] "old name" TO [Ddrive#,] "new name"
         [,Udevice#]

where both drive#s, if included, would be 0.


3.10. RENAMING AND SCRATCHING TROUBLESOME FILES

  Eventually,  you  may  run  across  a  file  which  has a crazy
filename,  such as a comma by itself (",") or one that includes a
Shifted  Space.  Or  perhaps you will find one that includes non-
printing  characters.  Any  of  these  can be troublesome.  Comma
files,  for  instance,  are  an exception to the rule that no two
files can have the same name.  Since  it shouldn't be possible to
make  a  file whose name is only a comma,  the disk never expects
you to do it again.
  Files  with  a   Shifted  Space  in  their  name  can  also  be
troublesome,  because  the  disk  interprets the Shifted Space as
signaling  the end of the file name,  and prints whatever follows
after  the  quotation  mark  that  marks the end of a name in the
directory.  This  technique can be useful by allowing you to have
a long file name,  and  making the disk recognize a small part of
it  as  being  the same as the whole thing without using pattern-
matching characters.
  In any case,  if  you have a troublesome filename,  you can use
the  CHR$()  function  to  specify troublesome characters without
typing  them  directly.  This  may allow you to build them into a
RENAME  command.  If  this  fails,  you may also use the pattern-
matching characters  discussed for a SCRATCH command.  This gives
you  a  way  to  specify  the  name without using the troublesome
characters at all, but also means loss of your file.
  For  example,  if  you  have  managed  to  create  a file named
""MOVIES",  with an extra quotation mark at the front of the file
name,  you can rename it to  "MOVIES" using the CHR$() equivalent
of a quotation mark in the RENAME command:

  RENAME (CHR$(34)+"MOVIES") TO "MOVIES"

The  CHR$(34)  forces  a  quotation  mark into the command string
without  upsetting  BASIC.  The  procedure  for  a file name that
includes a Shifted Space is similar, but uses CHR$(160).
  In cases  where even this doesn't work,  for  example,  if your
diskette contains a comma file,  (one named ",")  you can get rid
of it this way:

  SCRATCH "?"

  This example deletes all files with one-character names.

  Depending  on  the  exact  problem,  you  may  have  to be very
creative in choosing pattern-matching characters that will affect
only  the desired file,  and may have to rename other files first
to keep them from being scratched.
  In  some  cases,  it  may  be easier to copy desired files to a
different diskette and leave the troublesome files behind.


3.11. COLLECT

  The  COLLECT  command  recalculates  the Block Availability Map
(BAM)  of  the  current  diskette,  allocating only those sectors
still  being  used by valid,  properly closed files and programs.
All other sectors  (blocks) are left unallocated and free for re-
use, and all improperly closed files are automatically scratched.
However,  this  brief  description  of  COLLECT  doesn't indicate
either  the  power or the danger of the command.  Its power is in
restoring  to  good  health  many  diskettes whose directories or
Block Availability Maps have become muddled.  Any time the blocks
used  by  the  files  on a diskette plus the blocks shown as free
don't  add  up to the 3160 available on a fresh diskette, COLLECT
is  needed  (with  one  exception below).  Similarly,  any time a
diskette   contains  an  improperly  closed  file  (splat  file),
indicated  by  an  asterisk  (*)  next  to  its  file type in the
directory, that diskette needs to be collected.  In fact, but for
the one exception below,  it  is a good idea to COLLECT diskettes
whenever  you are concerned about their integrity.  Just note the
number  of  blocks  free  in  the diskette's directory before and
after  using  COLLECT.  If the totals differ,  there was indeed a
problem,  and the diskette should probably be copied onto a fresh
diskette  file-by-file,  using  a  copy  program described in the
previous section, rather than using backup program.
  The  exception  is diskettes containing direct access files, as
described in Chapter 6.  Most direct access (random) files do not
allocate  their  sectors  in a way COLLECT command can recognize.
Thus,  collecting  such a diskette may result in unallocating all
direct access files,  with  loss of all their contents when other
files are added.  Unless specifically instructed otherwise, never
COLLECT  a  diskette containing direct access files. (Note: these
are  not  the  same as the relative files described in Chapter 5.
COLLECT may be used on relative files without difficulty.)

FORMAT FOR THE COLLECT COMMAND:

  COLLECT [,Ddrive#][,Udevice#]


3.12. DCLEAR

  One command that should not often be needed on the 1581, but is
still of occasional value is DCLEAR.  On the 1581, and nearly all
other Commodore drives, this function is performed automatically,
whenever a new diskette is inserted.
  The result of an DCLEAR,  whether forced by a command,  or done
automatically  by  the  disk,  is  a  re-reading  of  the current
diskette's BAM  into a disk buffer.  This information must always
be  correct  in  order  for the disk to store new files properly.
However,  since the chore is handled automatically, the only time
you'd  need  to  use the command is if something happened to make
the information in the drive buffers unreliable.

FORMAT FOR THE DCLEAR COMMAND:

  DCLEAR [Ddrive#]



4. SEQUENTIAL DATA FILES


  A file on a diskette is just like a file cabinet in your office
-- an organized place to put things. Nearly everything you put on
a diskette goes in one kind of file or another. So far all you've
used are program files,  but there are others.  In  this  chapter
you'll learn about sequential data files.
  The primary purpose of a data file  is to store the contents of
program variables, so they won't be lost when the program ends. A
sequential  data  file  is  one  in  which  the  contents  of the
variables are stored "in sequence",  one right after another. You
may  already  be  familiar  with  sequential  files  from using a
DATASSETTE,  because  sequential  files on diskette are just like
the  data  files  used  on  cassettes.  Whether  on  cassette  or
diskette, sequential files must be read from beginning to end.
  When  sequential  files  are  created,  information  (data)  is
transferred  byte-by-byte,  through  a buffer,  onto the magnetic
media.  Once  in  the disk drive, program files,  sequential data
files,  and user files all work sequentially.  Even the directory
acts like a sequential file.
  To use sequential files properly, we will learn some more BASIC
words  in  the next few pages.  Then we'll put them together in a
simple but useful program.

+---------------------------- NOTE -----------------------------+
|   Besides  sequential  data  files,  two other file types are |
| recorded sequentially on a diskette.  They are program files, |
| and user files.  When you save a program on a diskette, it is |
| saved  in  order  from  beginning  to  end,   just  like  the |
| information in a sequential data file. The main difference is |
| in the commands you use to access it.  User files can be even |
| more similar to sequential data files.  User files are almost |
| never used,  but like program files, they could be treated as |
| though  they  were  sequential  data  files  and  some can be |
| accessed with the same commands.                              |
|   For the advanced user,  the similarity  of the various file |
| types  offers  the possibility of reading a program file into |
| the computer a byte (character) at a time and rewriting it to |
| the diskette in a modified form.                              |
+---------------------------------------------------------------+


4.1. OPENING A FILE

  One  of  the most powerful tools in Commodore BASIC is the OPEN
statement.  With it, you may send data almost anywhere, much like
a telephone switchboard.  As you might expect, a command that can
do  this  much  is  fairly  complex.  You  have already used OPEN
statements regularly in some of your diskette commands.
  Before you study the format of the OPEN statement, let's review
some of the possible devices in a Commodore computer system.

Device#:  Name:   Used for:
-----------------------------------------------------------------
0     Keyboard    Receiving input from the computer operator
1     DATASSETTE  Sending and receiving information from cassette
2     RS232       Sending and receiving information from a modem
3     Screen      Sending output to a video display
4,5   Printer     Sending output to a hard copy printer
8-11  Disk Drive  Sending and receiving information from diskette
-----------------------------------------------------------------

  Because of the flexibility of the OPEN statement it is possible
for  a  single  program  statement  to  contact  any one of these
devices,  or  even  others,  depending  on  the value of a single
character in the command. If the character is kept in a variable,
the  device can even change each time that part of the program is
used,  sending  data alternately and with equal ease to diskette,
cassette, printer and screen.

+---------------------------- NOTE -----------------------------+
|   In  the  last  chapter  you  learned  how to check for disk |
| errors  after  disk  commands  in  a  program.  It is equally |
| important  to check for disk errors after using file-handling |
| statements.  Failure  to  detect  a  disk  error before using |
| another file-handling statement could cause loss of data, and |
| failure of the BASIC program.                                 |
|   The  easiest  way  to check the disk is to follow all file- |
| handling statements with a GOSUB statement  to an error check |
| subroutine.                                                   |
|                                                               |
| EXAMPLE:                                                      |
|                                                               |
|   BASIC 7.0:  840 DOPEN#4,"DEGREE DAY DATA",D0,U8,W           |
|               850 GOSUB 59990: REM CHECK FOR DISK ERRORS      |
|                                                               |
|   BASIC 2.0:  840 OPEN 4,8,4,"0:DEGREE DAY DATA,S,W"          |
|               850 GOSUB 59990: REM CHECK FOR DISK ERRORS      |
|                                                               |
+---------------------------------------------------------------+

FORMAT FOR THE DISK OPEN STATEMENT FOR SEQUENTIAL FILES:

  BASIC 7.0: DOPEN#file#,"file name"[,Ddrive#][,Udevice#][,W]
  BASIC 2.0: OPEN file#,device#,channel#,"drive#:file name,
                                          file type,direction"

where:
  "file#"  is  an  integer  (whole number)  between 1 and 255. Do
not open a disk file with a file number greater than 127, it will
cause  severe  problems.  After the file is open,  all other file
commands will refer to it by the number given here. Only one file
can use any given file number at a time.
  "device#" is the number,  or primary address,  of the device to
be  used.  This  number  is  an integer in the range 8-11, and is
normally 8 on the 1581.
  "channel#" is a secondary address,  giving further instructions
to  the  selected  device  about  how  further commands are to be
obeyed.  In  disk files,  the channel number selects a particular
channel  along which communications for this file can take place.
The  possible  range  of  disk  channel numbers is 0-15, but 0 is
reserved for program loads,  1 for program saves,  and 15 for the
disk  command  channel.  Also be sure that no two disk files have
the  same  channel  number  unless they will never be open at the
same time.  (One way to do this is to make the channel number for
each file the same as its file number.)
  "drive#" is the drive number, always 0 on the 1581. Do not omit
it, or you will only be able to use two channels at the same time
instead of the normal maximum of three.  If any pre-existing file
of the same name is to be replaced, precede the drive number with
the "at" sign (@) to request OPEN-WITH-REPLACE.
  "file name"  is  the  file name,  maximum length 16 characters.
Pattern   matching  characters  are  allowed  in  the  name  when
accessing existing files, but not when creating new ones.
  "file type" is the file type desired:  S=sequential, P=program,
U=user, A=append and L=length of a relative file.
  "direction"  is  the  type  of access desired.  There are three
possibilities:  R=read,  W=write,  and M=modify.  When creating a
file,  use  "W"  to  write  the data to diskette.  When viewing a
completed file,  use "R" to read the data from diskette. Only use
the  "M" (modify) option as a last ditch way of reading back data
from  an  improperly closed (splat) file.  If you try this, check
every  byte  as it is read to be sure the data is still valid, as
such files always include some erroneous data, and have no proper
end.
  "file type"  and "direction" don't have to be abbreviated. They
can be spelled out in full for clarity in printed listings.
  "file#",   "device#"  and  "channel#"  must  be  valid  numeric
constants, variables or expressions. The rest of the command must
be a valid string literal, variable or expression.
  "w" is an option that must be specified to write the sequential
file, or the file will be opened to read.
  The maximum number of files  that may be open simultaneously is
10,  including  all  files to all devices.  The maximum number of
sequential  disk  files that can be open at once is three (or two
of  you  neglect  to  include  the  drive  number  in  your  OPEN
statement), plus the command channel.

EXAMPLES OF OPENING SEQUENTIAL FILES:

  To create a sequential file of phone numbers, you could use:

  BASIC 7.0:  DOPEN#2,"PHONES",D0,U8,W
  BASIC 2.0:  OPEN 2,8,2,"0:PHONES,SEQUENTIAL,WRITE"
              or
              OPEN 2,8,2,"0:PHONES,S,W"

  On  the  chance  you've  already  got  a  "PHONES"  file on our
diskette, you can avoid a "FILE EXISTS" error message by doing an
@OPEN:

  BASIC 7.0:  DOPEN#2,"@PHONES",D0,U8,W
  BASIC 2.0:  OPEN 2,8,2,"@0:PHONES,S,W"

This  erases  all  your old phone numbers,  so make sure that any
information  that  may  be  deleted  is  of  no importance. After
writing  our  phone  file,  remove  the diskette and turn off the
system.  To recall the data in the file, reopen it with something
like:

  BASIC 7.0:  DOPEN#8,"PHONES",D0,U8
  BASIC 2.0:  OPEN 8,8,8,"0:PHONES,S,R"

It doesn't matter  whether the file and channel numbers match the
ones we used before,  but the file name does have to match.  It's
possible  to  use an abbreviation form of the file name, if there
are no other files that would have the same abbreviation:

  BASIC 7.0:  DOPEN#10,"PH*",D0,U8
  BASIC 2.0:  OPEN 10,8,6,"0:PH*,S,R"

  If you have too many phone numbers,  they  might not fit in one
file.  In  that  case,  use  several similar file names and let a
program choose the correct file.

  BASIC 7.0:  100 INPUT"WHICH PHONE NUMBERS FILE (1-3)";PH
              110 IF PH<>1 AND PH<>2 AND PH<>3 THEN 100
              120 DOPEN#4,"PHONE"+STR$(PH),D0,U8

  BASIC 2.0:  100 INPUT"WHICH PHONE NUMBERS FILE (1-3)";PH
              110 IF PH<>1 AND PH<>2 AND PH<>3 THEN 100
              120 OPEN 4,8,2,"PHONE"+STR$(PH)+",S,R"

You can omit the drive number on an OPEN command  to read a file.
Doing  so  allows those with dual drives to search both diskettes
for the file.

FORMAT FOR THE PRINT# COMMAND:

  PRINT#file#,data list

where "file#" is the same file number given in the desired file's
current  OPEN statement.  During any given access of a particular
file, the file number must remain constant because it serves as a
shorthand  way  of relating all other file-handling commands back
to the correct OPEN statement.  Given a file number, the computer
can look up everything else about a file that matters.
  The "data list" is the same as for a PRINT statement  -- a list
of  constants,  variables and/or expressions,  including numbers,
strings or both. However, it's better if each PRINT# statement to
disk  include  only  one  data item.  If you wish to include more
items,  they  should be separated by a carriage return character,
not  a comma.  Semicolons are permitted,  but not recorded in the
file, and do not result in any added spaces in the file. Use them
to  separate  items in the list that might otherwise be confused,
such  as  a  string  variable  immediately  following  a  numeric
variable.

+---------------------------- NOTE -----------------------------+
|   Do  not  leave  a  space between PRINT  and  #,  and do not |
| abbreviate  the  command as ?#.  The correct abbreviation for |
| PRINT# is pR.                                                 |
+---------------------------------------------------------------+

EXAMPLES:

  To record a few grades for John Paul Jones,  using a sequential
disk file #1 previously opened for writing, use:

  200 FOR CLASS=1 TO COURSES
  210 PRINT#1,GRADE$(CLASS)
  220 GOSUB 59990: REM CHECK FOR DISK ERRORS
  230 NEXT CLASS

assuming your program includes an error check subroutine like the
one in the last chapter.
  In  using  PRINT#,  there is an exception to the requirement to
check  for  disk errors after every file-handling statement. When
using PRINT#, a single check after an entire set of data has been
written  will  still  detect  the error,  so long as the check is
made before any other file-handling statement  or disk command is
used.  You may be familiar with PRINT statements in which several
items follow each other:

  400 PRINT NAME$,STREET$,CITY$

To  get  those  same variables onto sequential disk file number 5
instead  of  the screen,  the best approach would be to use three
separate PRINT# statements, as follows:

  400 PRINT#5,NAME$
  410 PRINT#5,STREET$
  420 PRINT#5,CITY$

If you need to combine them, here is a safe way to do it:

  400 PRINT#5,NAME$;CHR$(13);STREET$;CHR$(13);CITY$

CHR$(13)  is  the  carriage  return  character,  and has the same
effect  as  putting  the print items in separate lines. If you do
this  often,  some  space  and  time  may  be saved by previously
defining a variable as equal to CHR$(13):

   10 CR$=CHR$(13)
  400 PRINT#5,NAME$;CR$;STREET$;CR$;CITY$

  The  basic idea is that a proper sequential disk-file write, if
redirected  to  the  screen,  will display only one data item per
line, with each succeeding item on the next line.


4.2. CLOSING A FILE

  After you finish using a data file,  it  is extremely important
that you CLOSE it.  During the process of writing a file, data is
accumulated  in  a  memory  buffer,  and  only written out to the
diskette when the buffer fills.
  Working this way, there is almost always a small amount of data
in  the  buffer  that  has  not been written to diskette yet, and
which would simply be lost if the computer system were tuned off.
Similarly,  there  are  diskette  housekeeping  matters,  such as
updating the BAM  (Block Availability Map) of sectors used by the
current file,  which are not performed during the ordinary course
of  writing  a  file.  This  is  the  reason  for  having a CLOSE
statement.  When  you  are done with a file,  the CLOSE statement
will  write  the  rest of the data buffer out to diskette, update
the  BAM,  and complete the file's entry in the directory. Always
close  a  data file when you are done using it.  Failure to do so
may cause loss of the entire file.
  However,  do not close the disk command channel until all other
files  have been closed.  The command channel should be the first
file opened, and the last file closed in any program.

FORMAT FOR THE CLOSE STATEMENT:

  BASIC 7.0:  DCLOSE#file#[,Udevice#]
  BASIC 2.0:  CLOSE file#

where "file#" is the same file number given in the desired file's
current OPEN statement.

EXAMPLES:

  To  close  the  data file #5 used as an example on the previous
page, use:

  BASIC 7.0:  DCLOSE#5
  BASIC 2.0:  CLOSE 5

  In BASIC 7.0,  when the DCLOSE statement is used alone (no # or
file# parameters),  it closes all disk files at once.  With a bit
of planning, the same can be done via a program loop. Since there
is no harm in closing a file  that wasn't open,  close every file
you  even  think  might  be  open before ending a program. If you
always gave your files numbers  between 1 and 5,  you could close
them all with

  9950 FOR I=1 TO 5
  9960 CLOSE I
  9970 GOSUB 59990: REM CHECK FOR DISK ERRORS
  9980 NEXT I

assuming your program includes an error check subroutine like the
one in the last chapter.


4.3. READING FILE DATA: USING INPUT#

  Once  information has been written properly to a diskette file,
it  may  be read back into the computer with an INPUT# statement.
Just  as  the  PRINT# statement is much like the PRINT statement,
INPUT#  is  nearly  identical to  INPUT,  except that the list of
items  following  the  command  word comes from a particular file
instead of the keyboard.  Both statements are subject to the same
limitations-halting  input after a comma or colon,  not accepting
data  items  too  large  to  fit in BASIC's input buffer, and not
accepting non-numeric data into a numeric variable.

FORMAT FOR THE INPUT# STATEMENT:

  INPUT#file#,variable list

where "file#" is the same file number given in the desired file's
current OPEN statement,  and "variable list" is one or more valid
BASIC  variable  names.  If  more  than one data element is to be
input  by a particular INPUT# statement,  each variable name must
be separated from others by a comma.

EXAMPLES:

To read back in the grades written with the PRINT# example, use:

  300 FOR CLASS = 1 TO COURSES
  310 INPUT#1,GRADE$(CLASS)
  320 GOSUB 59990: REM CHECK FOR DISK ERRORS
  330 NEXT CLASS

assuming your program includes an error check subroutine like the
one in the last chapter.
  To  read  back  in  the  address data written by another PRINT#
example, it is safest to use:

  800 INPUT#5,NAME$
  810 GOSUB 59990: REM CHECK FOR DISK ERRORS
  820 INPUT#5,STREET$
  830 GOSUB 59990: REM CHECK FOR DISK ERRORS
  840 INPUT#5,CITY$
  850 GOSUB 59990: REM CHECK FOR DISK ERRORS

but many programs cheat on safety a bit and use

  800 INPUT#5,NAME$,STREET$,CITY$
  810 GOSUB 59990: REM CHECK FOR DISK ERRORS

This  is  done  primarily  when  top  speed  in  the  program  is
essential, and there is little risk of reading improper data from
the file.


4.4. MORE ABOUT INPUT#

  After you begin using data files regularly,  you  may encounter
two BASIC error messages.  They are  "STRING TOO LONG ERROR"  and
"FILE DATA ERROR".  Both  are  likely  to halt your program at an
INPUT#  statement,  but  may also have been caused by errors in a
PRINT# statement when the file was written.

"STRING TOO LONG" ERROR

  A BASIC string may be up to 255 characters long,  although  the
longest string you can enter via a single INPUT statement is just
under two lines of text. This lower limitation is due to the size
of the input buffer in Commodore's serial bus computers. The same
limit  applies  to  INPUT#  statements.  If a single data element
(string  or  number)  being  read from a disk file into an INPUT#
statement  contains  more  than  88  (BASIC 2)  and 160 (BASIC 7)
characters, BASIC will halt with a "STRING TOO LONG ERROR".

"FILE DATA" ERROR

  The  other  error  message   "FILE DATA ERROR"   is  caused  by
attempting  to  read  a  non-numeric  character  into  a  numeric
variable.  To a computer, a number is the characters 0 through 9,
the  "+"  and  "-"  signs,  the  decimal  point  (.),  the  SPACE
character, and the letter "E" used in scientific notation. If any
other character appears in an INPUT# to a numeric variable, "FILE
DATA ERROR"  will  be  displayed  and the program will halt.  The
usual  causes  of  this error are a mismatch between the order in
which variables are written to  and  read from a file,  a missing
carriage return within a  PRINT#  statement that writes more than
one data item,  or a data item  that includes either a comma or a
colon without a preceding quotation mark.  Once a file data error
has occurred, you should correct it by reading the data item into
a  string  variable,  and converting it back to a number with the
BASIC VAL() statement  after removing non-numeric characters with
the string functions described in your computer user's manual.

COMMAS (,) AND COLONS (:)

  As suggested before,  commas  and colons can cause trouble in a
file,  because they delimit  (end) the data element in which they
appear  and cause any remaining characters in the data element to
be read into the next INPUT# variable.  They have the same effect
in an INPUT statement,  causing the common  "EXTRA IGNORED" error
message.  However,  sometimes  you  really  need a comma or colon
within a data element,  such as a name written as  "Last, First".
The cure  is to precede such data elements with a quotation mark.
After a quotation mark,  in either an  INPUT or INPUT# statement,
all   other  characters  except  a  carriage  return  or  another
quotation mark are accepted as part of the current data element.

EXAMPLES:

  To force a quotation mark into a data element  going to a file,
append a CHR$(34) to the start of the data element. For example:

  PRINT#2,CHR$(34)+"DOE,JOHN"

or

  PRINT#2,CHR$(34);"DOE,JOHN"

If  you  do  this  often,  some  space  and time may be saved by
previously  defining  a  variable as equal to CHR$(34) as we did
earlier with CHR$(13):

   20 QT$=CHR$(34)
  ...
  400 PRINT#5,QT$+NAME$

  In  each  case,  the added quotation mark will be stripped from
the data  by the  INPUT  or  INPUT#  statement,  but the comma or
colon will remain part of the data.


4.5. NUMERIC DATA STORAGE ON DISKETTE

  Up  to  this  point  we have discussed string data storage, now
let's look at numeric storage.
  Inside the computer,  the space  occupied by a numeric variable
depends  only  on  its  type.  Simple numeric variables use seven
bytes  (character locations) of memory.  Real array variables use
five bytes per array element,  and integer array elements use two
bytes each.  In contrast,  when a numeric variable or any type is
written to a file,  the space it occupies depends entirely on its
length, not its type.  This is because numeric data is written to
a  file  in  the form of a string,  as if the STR$() function had
been  performed on it.  The first character will be a blank space
if the number is positive,  and a minus sign (-) if the number is
negative.   Then  comes  the  number,  digit-by-digit.  The  last
character is a cursor right character.
  This  format allows the disk data to be read back into a string
or  numeric  variable  later.  It is,  however,  wasteful of disk
space,  and  it can be difficult to anticipate the space required
by  numbers  of  unknown  length.  For this reason, some programs
convert all numeric variables into strings before writing them to
diskette,  and  use  string  functions  to  remove  any  unneeded
characters in advance.  Doing so still allows those data elements
to be read back into a numeric variable by INPUT# later, although
file  data  errors  may  be  avoided  by  reading  all data in as
strings, and converting to numbers using the VAL() function after
the information is inside the computer.
  For example, "N$=RIGHT$(STR$(N),LEN(STR$(N))-1)" will convert a
positive  number  N  into a string  N$  without the usual leading
space for its numeric sign.  Then instead of  writing  PRINT#5,N,
you would use PRINT#5,N$.


4.6. READING FILE DATA: USING GET#

  The  GET#  statement  retrieves  data  from the disk drive, one
character  at a time.  Like the similar keyboard GET statement in
BASIC,  it  only  accepts  a  single  character  into a specified
variable. However, unlike the GET statement, it doesn't just fall
through  to  the next statement if there is no data to be gotten.
The  primary  use  of  GET# is to retrieve from diskette any data
that  cannot be read into an INPUT# statement,  either because it
is  too  long  to  fit in the input buffer or because it includes
troublesome characters.

FORMAT FOR THE GET# STATEMENT:

  GET#file#,variable list

where "file#" is the same file number given in the desired file's
current OPEN statement,  and "variable list" is one or more valid
BASIC  variable  names.  If  more  than one data element is to be
input by a particular GET# statement,  each variable name must be
separated from others by a comma.
  In practice,  you will almost never see a GET or GET# statement
containing  more  than  one  variable  name.  If  more  than  one
character  is  needed,  a  loop  is  used  rather than additional
variables.  Also  as in the INPUT# statement,  it is safer to use
string  variables  when  the file to be read might contain a non-
numeric character.
  Data in a GET# statement comes in byte-by-byte,  including such
normally  invisible  characters  as  the Carriage Return, and the
various cursor controls.  All but one will be read properly.  The
exception is CHR$(0),  the ASCII Null character.  It is different
from an empty string  (one of the form A$=""),  even though empty
strings are often referred to as null strings.  Unfortunately, in
a GET# statement,  CHR$(0) is converted into an empty string. The
cure is to test for an empty string after a GET#, and replace any
that  are  found  with  CHR$(0) instead.  The first example below
illustrates the method.

EXAMPLES:

  To  read  a file that may contain a CHR$(0),  such as a machine
language program file, you could correct any CHR$(0) bytes with

  1100 GET#3,G$:IF G$="" THEN G$=CHR$(0)

  If an overlong string has managed to be recorded in a file,  it
may be read back safely into the computer with GET#, using a loop
such as this

  3300 B$=""
  3310 GET#1,A$
  3320 IF A$<>CHR$(13) THEN B$=B$+A$: GOTO 3310

The limit for such a technique is 255 characters.  It will ignore
CHR$(0),  but that may be an advantage in building a text string.
If CHR$(0) is required in the file, then add the following line:

  3315 IF A$="" THEN A$=CHR$(0)

  GET# may be useful in recovering damaged files,  or files  with
unknown contents. The BASIC reserved variable ST (the file STatus
variable)  can  be used to indicate when all of a properly closed
file has been read.

  500 GET#2,S$
  510 SU=ST: REM REMEMBER FILE STATUS
  520 PRINT S$;
  530 IF SU=0 THEN 500: REM IF THERE'S MORE TO BE READ
  540 IF SU<>64 THEN PRINT"STATUS ERROR: ST =";SU

Copying  ST into  SU is often an unnecessary precaution, but must
be done  if any other file-handling statement appears between the
one which read from the file  and the one that loops back to read
again.  For example, it would be required if line 520 was changed
to

  520 PRINT#1,S$;

Otherwise,  the  file status checked in line 530 would be that of
the write file, not the read file.

  The  following  table applies to single errors or a combination
of two or more errors.

+---------------------------------------------------------------+
|       POSSIBLE VALUES OF THE FILE STATUS VARIABLE "ST",       |
|                       AND THEIR MEANINGS                      |
|                                                               |
| IF ST=                        THEN                            |
|    0     All is OK                                            |
|    1     Receiving device was not available                   |
|          (time out on talker)                                 |
|    2     Transmitting device was not available                |
|          (time out on listener)                               |
|    4     Cassette data file block was too short               |
|    8     Cassette data file block was too long                |
|   16     Unrecoverable read error from cassette, verify error |
|   32     Cassette checksum error -- one or more faulty        |
|          characters were read                                 |
|   64     End of file reached (EOI detected)                   |
|  128     Device not present, or end of tape mark found        |
|          on cassette                                          |
+---------------------------------------------------------------+


4.7. DEMONSTRATION OF SEQUENTIAL FILES (BASIC 7.0)

  Use  the  following  program  for  your  first experiments with
sequential  files.  Comments  have  been added to help you better
understand it.

 150 cr$=chr$(13)                 Make a carriage return variable
 170 print chr$(147):rem clear
     screen
 190 print"** write a file **"
 210 print
 220 dopen#2,"@seq file",w        Open demo file with replace
 230 gosub 500                    Check for disk errors
 240 print"enter a word,
     then a number"
 250 print"or 'end,0' to stop"
 260 print
 270 input a$,b                   Accept a string & number
                                  from keyboard
 280 print#2,a$;cr$;b             Write them to the disk file
 290 gosub 500
 300 if a$<>"end" then 270
 310 print
 320 dclose#2                     Tidy up
 340 print"** read same file
     back **"
 360 print
 370 dopen#2,"seq file"           Reopen same file for reading
 380 gosub 500
 390 input#2,a$,b                 Read next string & number
                                  from file
 400 rs=st
 410 gosub 500
 420 print a$,b                   Display file contents
 430 if rs=0 then 390             until done,
 440 if rs<>64 then
     print"status=";rs            unless there's an error
 450 dclose#2                     Then quit
 460 end
 480 rem ** error check s/r **
 500 if ds>0 then print ds$:stop
 510 return

begin 644 demoseq.prg
M`1P/')8`0U(DLL<H,3,I`"L<J@"9(,<H,30W*3J/($-,14%2(%-#4D5%3@!%
M'+X`F2(J*B!74DE412!!($9)3$4@*BHB`$L<T@"9`&(<W`#^#2,R+")`4T51
M($9)3$4B+%<`;!SF`(T@-3`P`(\<\`"9(D5.5$52($$@5T]21"P@5$A%3B!!
M($Y534)%4B(`J1SZ`)DB3U(@)T5.1"PP)R!43R!35$]0(@"O'`0!F0"Z'`X!
MA2!!)"Q"`,H<&`&8,BQ!)#M#4B0[0@#4'"(!C2`U,#``ZAPL`8L@022SL2)%
M3D0B(*<@,C<P`/`<-@&9`/D<0`'^#R,R`!H=5`&9(BHJ(%)%040@4T%-12!&
M24Q%($)!0TL@*BHB`"`=:`&9`#0=<@'^#2,R+")315$@1DE,12(`/AU\`8T@
M-3`P`$H=A@&$,BQ!)"Q"`%0=D`%24[)35`!>'9H!C2`U,#``:1VD`9D@020L
M0@!Z':X!BR!24[(P(*<@,SDP`)<=N`&+(%)3L[$V-""G()DB4U1!5%53/2([
M4E,`H!W"`?X/(S(`IAW,`8``PAW@`8\@*BH@15)23U(@0TA%0TL@4R]2("HJ
>`-<=]`&+($13L3`@IR"9($13)#J0`-T=_@&.````
`
end



5. RELATIVE DATA FILES


  Sequential files are very useful  when you're just working with
a continuous stream of data --  i.e. information that can be read
or written all at once.  However, sequential files are not useful
in some situations.  For  example,  after writing a large list of
mail labels,  you wouldn't want to have to reread the entire list
each time you need a person's record. Instead, you need some kind
of random access, a way to get to a particular label in your file
without having to read through all those preceding it.
  As  an  example,  compare  a  record  turntable with a cassette
recorder. You have to listen to a cassette from beginning to end,
but  a  turntable  needle  can  be  picked  up  at  any time, and
instantly moved to any spot on the record.  Your disk drive works
like a turntable in that respect.  In this chapter you will learn
about a type of file that reflects this flexibility.
  Actually,  two  different  types  of random access files may be
used on Commodore disk drives:  relative files  and random files.
Relative  files  are  much more convenient for most data handling
operations,  but  true  random  access  file  commands  are  also
available  to  advanced users,  and will be discussed in the next
chapter.


5.1. FILES, RECORDS, AND FIELDS

  When learning about sequential files,  you  did not worry about
the organization of data within a file,  so long as the variables
used to write the file  matched up properly with those which read
it  back  into the computer.  But in order for relative access to
work,  you need a more structured and predictable environment for
our data.
  The  structure  you  will  use  is  similar to that used in the
traditional filing cabinet. In a traditional office, all customer
records might be kept in a single file cabinet. Within this file,
each  customer  has a personal record in a file folder with their
name on it,  that contains everything the office knows about that
person.  Likewise,  within  each  file folder,  there may be many
small  slips  of  paper,  each  containing one bit of information
about  that customer,  such as a home phone number or the date of
the most recent purchase.
  In  a  computerized office,  the file cabinet is gone,  but the
concept of a file containing all the information about a group or
topic  remains.  The file folders are gone too, but the notion of
subdividing the file into individual records remains. The slip of
paper  within  the  personal  records  are gone too,  replaced by
subdivisions  within  the records,  called fields.  Each field is
large enough to hold one piece of information about one record in
the  file.  Thus,  within  each  file there are many records, and
within each record there are typically many fields.
  A  relative  file takes care of organizing the records for you,
numbering them from 1 to the highest record number,  by ones, but
the fields are up to you to organize.  Each record will be of the
same size, but the 1581 won't insist that they all be divided the
same way. On the other hand, they normally will be subdivided the
same  way,  and  if it can be known in advance exactly where each
field  starts  within  each  record,  there are even fast ways to
access  a  desired  field within a record without reading through
the  other  fields.  As  all  of this implies,  access speed is a
primary reason for putting information into a relative disk file.
Some  well-written  relative  file  programs are able to find and
read  the record of one desired person out of a thousand in under
15 seconds, a feat no sequential file program could match.


5.2. FILE LIMITS

  With  relative  files,  you  don't  have to worry about exactly
where  on  the  diskette's surface a given record will be stored,
or  whether  it will fit properly within the current disk sector,
or need to be extended onto the next available sector.  DOS takes
care of all that for you.  All you need to do is specify how long
each  record  is,  in bytes,  and how many records you will need.
DOS  will do the rest,  and organize things in such a way that it
can  quickly find any record in the file,  as soon as it is given
the record number (ordinal position within the file).
  The  only  limit that will concern you is that each record must
be  the  same  size,  and  the  record  length you choose must be
between 2 and 254 characters.  Naturally the entire file also has
to fit on your diskette, along with any other existing file(s).


5.3. CREATING A RELATIVE FILE

  When a relative file is to be used for the first time, its OPEN
statement will create the file; after that, the OPEN statement is
used to reopen the file for both reading and writing.

FORMAT STATEMENT TO OPEN A RELATIVE FILE:

  BASIC 7.0: DOPEN#file#,"file name",Lrecord length
             [,Ddrive#][,Udevice#]
  BASIC 2.0: OPENfile#,device#,channel#,"drive#:file name,L,"+
             CHR$(record length)

where  "file#" is the file number,  normally an integer between 1
and 127; "device#" is the device number to be used, normally 8 on
the  1581;  "channel#"  selects  a particular channel along which
communications  for this file can take place,  normally between 2
and 14;  "drive#" is the drive number,  always 0 on the 1581; and
"file name" is the name of the file,  with a maximum length of 16
characters.  Pattern  matching characters are allowed in the name
when accessing an existing file, but not when creating a new one.
The  record  length is the size of each record within the file in
bytes used, including carriage returns, quotation marks and other
special characters.

+---------------------------- NOTE -----------------------------+
|  o Do not precede the file name  (in BASIC 7.0)  or the drive |
| number  (in BASIC 2.0)  with  the "at" sign (@);  there is no |
| reason to replace a relative file.                            |
|  o L record length (in BASIC 7.0) or ,L,"+CHR$(record length) |
| (in BASIC 2.0) is only required when a relative file is first |
| created,  though it may be used later,  so long as the record |
| length is the same as when the file was first created.  Since |
| relative files may be read from or written to alternately and |
| with  equal  case,  there is no need to specify Read or Write |
| mode when opening a relative file.                            |
|  o "file#",  "device#"  and  "channel#" must be valid numeric |
| constants, variables or expressions.  The rest of the command |
| must be a valid string literal,  variable  or  expression. In |
| BASIC 7.0 DOPEN, whenever a variable or expression is used as |
| a file name it must be surrounded by parentheses.             |
+---------------------------------------------------------------+

EXAMPLES:

  To create or reopen a relative file named  "GRADES",  of record
length 100 use:

  BASIC 7.0: DOPEN#2,"GRADES",L100,D0,U8
  BASIC 2.0: OPEN 2,8,2,"GRADES,L,"+CHR$(100)

  To  reopen  an  unknown relative file of the user's choice that
has already been created, use:

  BASIC 7.0:  200 INPUT"WHICH FILE";FI$
              210 DOPEN#5,(FI$),D0,U8
  BASIC 2.0:  200 INPUT"WHICH FILE";FI$
              210 OPEN 5,8,5,FI$


5.4. USING RELATIVE FILES: RECORD# COMMAND

  When  a  relative file is opened for the first time,  it is not
quite ready for use. Both to save time when using the file later,
and to assure  that the file will work reliably,  it is necessary
to  create  several records before closing the file for the first
time.  At  a  minimum,  enough records to fill more than two disk
sectors (512 bytes) should be written. In practice, most programs
go ahead  and create as many records as the program is eventually
expected  to  use.  That  approach  has the additional benefit of
avoiding  such  problems  as  running out of room on the diskette
before the entire file is completed.
  If  you  simply  begin  writing  data to a just-opened relative
file,  it will act much like a sequential file,  putting the data
elements  written  by  the  first  PRINT# statement in record #1,
those  written by the second PRINT# statement in record #2 and so
on.  This  means  each  record must be written by a single PRINT#
statement,  using  embedded  carriage  returns within the data to
separate  fields  that  will  be  read  in via one or more INPUT#
statements later. However, it is far better to explicitly specify
which record number is desired via a RECORD# command to the disk.
This  allows  you to access records in any desired order, hopping
anywhere in a file with equal ease.

FORMAT FOR THE RECORD# COMMAND:

  BASIC 7.0: RECORD#file#,record number[,offset]
  BASIC 2.0: PRINT#15,"P"+CHR$(channel#+96)+CHR$(<record#)+
             CHR$(>record#)+CHR$(offset)

where  "file#"  is  the  file#  specified  in  the  current DOPEN
statement for the specified file,  "record number" is the desired
record number,  "channel#" is the channel number specified in the
current OPEN statement for the specified file,  "<record#" is the
low  byte  of the desired record number,  expressed as a two-byte
integer,  ">record#"  is  the  high  byte  of  the desired record
number,  and an optional "offset" value,  if present, is the byte
within  the  record  at  which  a  following Read or Write should
begin.
  To fully understand this command,  you must understand how most
integers  are  stored  in computers based on the 6502 and related
microprocessors.   In   the   binary   arithmetic   used  by  the
microprocessor,  it  is  possible to express any unsigned integer
from  0-255  in  a single byte.  It is also possible to store any
unsigned integer from 0-65535 in two bytes, with one byte holding
the  part  of the number that is evenly divisible by 256, and any
remainder  in the other byte.  In machine language,  such numbers
are  written backwards,  with the low-order byte  (the remainder)
first,  followed  by  the  high-order byte.  In assembly language
programs written with the Commodore Assembler,  the low part of a
two-byte  number  is  indicated  by  preceding its label with the
less-than character (<).  Similarly,  the high part of the number
is indicated by greater-than (>).

+---------------------------- NOTE -----------------------------+
|   To avoid the remote possibility of corrupting relative file |
| data, it is necessary to give RECORD# command once before the |
| Read or Write access and once after the access.               |
|   Although  this  is  not  necessary  for  the  1581,   other |
| Commodore drives require it. To make your programs compatible |
| with those other drives, it's a good idea to use it.          |
+---------------------------------------------------------------+

EXAMPLES:

  In  BASIC  7.0,  to  position the record pointer for file #2 to
record number 3, type:

  RECORD#2,3

  In BASIC 2.0,  to position the record pointer for channel #2 to
record number 3, type:

  PRINT#15,"P"+CHR$(98)+CHR$(3)+CHR$(0)

The  CHR$(98)  comes from adding the constant (96) to the desired
channel  number  (2).  (96+2=98)  Although the command appears to
work  even  when  96  is  not  added  to  the channel number, the
constant is normally added to maintain compatibility with the way
RECORD# works in BASIC 7.0.
  Since  3  is  less  than  256,  the  high  byte  of  its binary
representation is 0, and the entire value fits into the low byte.
Since you want to read or write from the beginning of the record,
no offset value is needed.
  Since these calculations quickly become tedious,  most programs
are  written to do them for you.  Here is an example of a program
which  inputs  a  record number and converts it into the required
low-byte/high-byte form:

  450 INPUT"RECORD NUMBER DESIRED";RE
  460 IF RE<1 OR RE>65535 THEN 450
  470 RH=INT(RE/256)
  480 RL=RE-256*RH
  490 PRINT#15,"P"+CHR$(98)+CHR$(RL)+CHR$(RH)

Assuming  RH  and  RL  are calculated as in the previous example,
programs  may  also  use  variables  for  the channel, record and
offset required:

  570 INPUT"CHANNEL, RECORD, OFFSET DESIRED";CH,RE,OF
  630 PRINT#15,"P"+CHR$(CH+96)+CHR$(RL)+CHR$(RH)+CHR$(OF)


5.5. COMPLETING RELATIVE FILE CREATION

  Now that you have learned how to use both the  OPEN and RECORD#
commands,  you  are  almost  ready  to properly create a relative
file. The only additional fact you need to know is that CHR$(255)
is  a  special character in a relative file.  It is the character
used  by  the  DOS  to fill relative records as they are created,
before a program fills them with other information.  Thus, if you
want  to  write the last record,  you expect to need in your file
with  dummy  data  that  will not interfere with your later work,
CHR$(255)  is  the  obvious  choice.  Here  is how it works in an
actual  program  which  you may copy for use in your own relative
file programs.

BASIC 7.0:

1380 input"enter relative file name";fi$  Select file parameters
1390 input"enter max. # of records";nr
1400 input"enter record length";rl
1410 dopen#1,(fi$),l(rl)                  Begin to create desired
                                          file
1420 gosub 60000                          Check for disk errors
1450 record#1,(nr)                        Position to last record
                                          number
1455 record#1,(nr)                        Re-position for safely
1460 gosub 60000
1470 print#1,chr$(255);                   Send default character
                                          to it
1480 gosub 60000
1500 gosub 60000
1510 dclose#1                             Now the file can be
                                          safely closed
1520 gosub 60000                          Check for disk errors
9990 end                                  before we end the
                                          program
59980 rem check disk subroutine           Error check subroutine
60000 if ds>1 and ds<>50 then             Ignore "RECORD NOT
      print ds,ds$:stop                   PRESENT"
60010 return

begin 644 creat128.prg
M`1PE'&0%A2)%3E1%4B!214Q!5$E612!&24Q%($Y!344B.T9))`!''&X%A2)%
M3E1%4B!-05@N(",@3T8@4D5#3U)$4R([3E(`91QX!84B14Y415(@4D5#3U)$
M($Q%3D=42"([4DP`>AR"!?X-(S$L*$9))"DL3"A23"D`AAR,!8T@-C`P,#``
ME!RJ!?X2(S$L*$Y2*0"B'*\%_A(C,2PH3E(I`*X<M`6-(#8P,#`P`+T<O@68
M,2S'*#(U-2D[`,D<R`6-(#8P,#`P`-4<W`6-(#8P,#`P`-X<Y@7^#R,Q`.H<
M\`6-(#8P,#`P`/`<!B>```P=3.J/($-(14-+($1)4TL@4U5"4D]55$E.10`M
H'6#JBR!$4[$Q(*\@1%.SL34P(*<@F2!$4RQ$4R0ZD``S'6KJC@``````
`
end

BASIC 2.0:

1020 open 15,8,15                         Open command channel
1380 input"enter relative file name";fi$  Select file parameters
1390 input"enter max. # of records";nr
1400 input"enter record length";rl
1410 open 1,8,2,"0:"+fi$+",l,"+chr$(rl)   Begin to create desired
                                          file
1420 gosub 59990                          Check for disk errors
1430 rh=int(nr/256)                       Calculate length values
1440 rl=nr-256*rh
1450 print#15,"p"+chr$(96+2)+chr$(rl)+    Position to last record
     chr$(rh)                             number
1455 print#15,"p"+chr$(96+2)+chr$(rl)+    Re-position for safely
     chr$(rh)
1460 gosub 59990
1470 print#1,chr$(255);                   Send default character
1480 gosub 59990                          to it
1500 gosub 59990
1510 close 1                              Now the file can be
                                          safely closed
1520 gosub 59990
9980 close 15                             And the command channel
                                          closed
9990 end                                  Before we end the
                                          program
59980 rem check disk subroutine           Error check subroutine
59990 input#15,en,em$,et,es
60000 if en>1 and en<>50 then             Ignore "RECORD NOT
      print en,em$,et,es:stop             PRESENT"
60010 return

begin 644 create64.prg
M`0@/"/P#GR`Q-2PX+#$U`#,(9`6%(D5.5$52(%)%3$%4259%($9)3$4@3D%-
M12([1DDD`%4(;@6%(D5.5$52($U!6"X@(R!/1B!214-/4D13(CM.4@!S"'@%
MA2)%3E1%4B!214-/4D0@3$5.1U1((CM23`"4"((%GR`Q+#@L,BPB,#HBJD9)
M)*HB+$PL(JK'*%),*0"@"(P%C2`U.3DY,`"Q")8%4DBRM2A.4JTR-38I`,((
MH`523+).4JLR-3:L4D@`X@BJ!9@Q-2PB4"*JQR@Y-JHR*:K'*%),*:K'*%)(
M*0`"":\%F#$U+")0(JK'*#DVJC(IJL<H4DPIJL<H4D@I``X)M`6-(#4Y.3DP
M`!T)O@68,2S'*#(U-2D[`"D)R`6-(#4Y.3DP`#4)W`6-(#4Y.3DP`#T)Y@6@
M(#$`20GP!8T@-3DY.3``4@G\)J`@,34`6`D&)X``=`E,ZH\@0TA%0TL@1$E3
M2R!354)23U5424Y%`(D)5NJ$,34L14XL14TD+$54+$53`+`)8.J+($5.L3$@
DKR!%3K.Q-3`@IR"9($5.+$5-)"Q%5"Q%4SJ0`+8):NJ.````
`
end

  Two  lines  require  additional  explanation.  When  line  1470
executes,  the disk drive will operate for up to several minutes,
creating  all  the records in the file,  up to the maximum record
number you selected in line 1390.  This is normal, and only needs
to be done once.  During the process you may hear the drive motor
turning  and  an  occasional  slight click as the head steps from
track to track.  Second,  line  60000 above is different from the
equivalent line in the error check subroutine given earlier. Here
disk error number 50 is specifically ignored,  because it will be
generated when the error channel is checked in line 1460.  Ignore
it  because  not having a requested record would only be an error
if that record had been created previously.


5.6. EXPANDING A RELATIVE FILE

  If  you  underestimate your needs and want to expand a relative
file later, simply request the record number you need, even if it
doesn't  currently exist in the file.  If there is no such record
yet,  DOS  will create it as soon as you try to write information
in  it,  and  also automatically create any other missing records
below it in number.  When the first record beyond the current end
record  is  written,  the  DOS  returns  "50, RECORD NOT PRESENT"
error. This is expected and correct.


5.7. WRITING RELATIVE FILE DATA

  The commands used  to read and write relative file data are the
same  PRINT#,  INPUT#,  and  GET# commands  used in the preceding
chapter  on  sequential files.  Each command is used as described
there.  However,  some  aspects of relative file access do differ
from  sequential  file  programming,  and  we  will  cover  those
differences here.


5.8. DESIGNING A RELATIVE RECORD

  As  stated earlier in this chapter,  each relative record has a
fixed length, including all special characters. Within that fixed
length, there are two popular ways to organize various individual
fields of information. One is free-format, with individual fields
varying in length from record to record, and each field separated
from the next by a carriage return character  (each of which does
take  up  one character space in the record).  The other approach
is to use fixed-length fields,  that may  or may not be separated
by carriage returns. If fixed length fields are not all separated
by  carriage returns,  you will either need to be sure a carriage
return is included within each 88-character portion of the record
(88 is for BASIC 2, 160 is for BASIC 7). If this is not done, you
will  have  to  use  the  GET#  command  to read the record, at a
significant cost in speed.
  Since  each  relative record is most easily written by a single
PRINT# statement,  the recommended approach is to build a copy of
the current record in memory before writing it to disk. It can be
collected into a single string variable  with the help of BASIC's
many string-handling functions,  and then all written out at once
from that variable.
  Here  is  an  example.  If  we are writing a 4-line mail label,
consisting of 4 fields named  "NAME",  "STREET",  "CITY & STATE",
and "ZIP CODE", and have a total record size of 87 characters, we
can organize it in either of two ways:

  WITH FIXED LENGTH  FIELDS         WITH VARIABLE LENGTH FIELDS

Field Name     Length             Field Name        Length

NAME           27 characters      NAME              31 characters
STREET         27 characters      STREET            31 characters
CITY & STATE   23 characters      CITY & STATE      26 characters
ZIP CODE       10 characters      ZIP CODE          11 characters
----------------------------      -------------------------------
Total length   87 characters      Potential length  99 characters
                                  Edited length     87 characters

  With fixed length records,  the field lengths add up to exactly
the  record  length.  Since  the  total length is just within the
input  buffer size limitation,  no carriage return characters are
needed.  With variable length records,  you can take advantage of
the  variability  of  actual  address  lengths.  While  one  name
contains  27  letters,  another  may  have only 15,  and the same
variability exists in street and city lengths.  Although variable
length records lose one character per field for carriage returns,
they  can  take advantage of the difference between maximum field
length  and  average  field length.  A program that uses variable
record  lengths must calculate the total length of each record as
it is entered,  to be sure the total of all fields doesn't exceed
the space available.


5.9. WRITING THE RECORD

  Here  is  an  example of program lines to enter variable length
fields for the above file design,  build them into a string,  and
send them to record number RE  in file number 3  (assumed to be a
relative file that uses channel number 3).

BASIC 7.0:

start tok64 /128 writv128.prg
  100 input"enter record number";re
  110 :
  120 dopen#3,"myrelfile",l88
  130 cr$=chr$(13)
  140 input"name";na$
  150 if len(na$)>30 then 140
  160 input"street";sa$
  170 if len(sa$)>30 then 160
  180 input"city & state";cs$
  190 if len(cs$)>25 then 180
  200 input"zip code";zp$
  210 if len(zp$)>10 then 200
  220 da$=na$+cr$+sa$+cr$+cs$+cr$+zp$
  230 if len(da$)<88 then 260
  240 print"record too long"
  250 goto 140
  260 :
  270 :
  280 record#3,(re),1
  290 if ds=50 then print#3,chr$(255):gosub 1000:goto 280
  300 gosub 1000
  310 print#3,da$
  320 gosub 1000
  330 record#3,(re),1
  340 gosub 1000
  350 dclose#3:end
 1000 if ds<20 then return
 1002 :
 1010 print"error:";ds$:dclose#3:end
stop tok64

begin 644 writv128.prg
M`1P?'&0`A2)%3E1%4B!214-/4D0@3E5-0D52(CM210`E'&X`.@`^''@`_@TC
M,RPB35E214Q&24Q%(BQ,.#@`3!R"`$-2)++'*#$S*0!<'(P`A2).04U%(CM.
M020`<AR6`(L@PRA.020IL3,P(*<@,30P`(0<H`"%(E-44D5%5"([4T$D`)H<
MJ@"+(,,H4T$D*;$S,""G(#$V,`"R'+0`A2)#2519("8@4U1!5$4B.T-3)`#(
M'+X`BR##*$-3)"FQ,C4@IR`Q.#``W!S(`(4B6DE0($-/1$4B.UI0)`#R'-(`
MBR##*%I0)"FQ,3`@IR`R,#``%AW<`$1!)+).022J0U(DJE-!)*I#4B2J0U,D
MJD-2)*I:4"0`+!WF`(L@PRA$020ILS@X(*<@,C8P`$,=\`"9(E)%0T]21"!4
M3T\@3$].1R(`31WZ`(D@,30P`%,=!`$Z`%D=#@$Z`&D=&`'^$B,S+"A212DL
M,0".'2(!BR!$4[(U,""G()@S+,<H,C4U*3J-(#$P,#`ZB2`R.#``F1TL`8T@
M,3`P,`"D'38!F#,L1$$D`*\=0`&-(#$P,#``OQU*`?X2(S,L*%)%*2PQ`,H=
M5`&-(#$P,#``U1U>`?X/(S,Z@`#E'>@#BR!$4[,R,""G((X`ZQWJ`SH`!![R
8`YDB15)23U(Z(CM$4R0Z_@\C,SJ`````
`
end

BASIC 2.0:

start tok64 writev64.prg
  100 input"enter record number";re
  110 open 15,8,15
  120 open 3,8,3,"myrelfile,l,"+chr$(88)
  130 cr$=chr$(13)
  140 input"name";na$
  150 if len(na$)>30 then 140
  160 input"street";sa$
  170 if len(sa$)>30 then 160
  180 input"city & state";cs$
  190 if len(cs$)>25 then 180
  200 input"zip code";zp$
  210 if len(zp$)>10 then 200
  220 da$=na$+cr$+sa$+cr$+cs$+cr$+zp$
  230 if len(da$)<88 then 260
  240 print"record too long"
  250 goto 140
  260 rh=int(re/256)
  270 rl=re-256*rh
  280 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
  290 gosub 1000:if en=50 then print#3,chr$(255):gosub 1000:\
      goto 280
  300 gosub 1000
  310 print#3,da$
  320 gosub 1000
  330 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
  340 gosub 1000
  350 close 3:close 15:end
 1000 input#15,en,em$,et,es
 1002 if en<20 then return
 1010 print"error:";em$:close 3:close 15:end
stop tok64

begin 644 writev64.prg
M`0@?"&0`A2)%3E1%4B!214-/4D0@3E5-0D52(CM210`M"&X`GR`Q-2PX+#$U
M`$X(>`"?(#,L."PS+")-65)%3$9)3$4L3"PBJL<H.#@I`%P(@@!#4B2RQR@Q
M,RD`;`B,`(4B3D%-12([3D$D`(((E@"+(,,H3D$D*;$S,""G(#$T,`"4"*``
MA2)35%)%150B.U-!)`"J"*H`BR##*%-!)"FQ,S`@IR`Q-C``P@BT`(4B0TE4
M62`F(%-4051%(CM#4R0`V`B^`(L@PRA#4R0IL3(U(*<@,3@P`.P(R`"%(EI)
M4"!#3T1%(CM:4"0``@G2`(L@PRA:4"0IL3$P(*<@,C`P`"8)W`!$022R3D$D
MJD-2)*I3022J0U(DJD-3)*I#4B2J6E`D`#P)Y@"+(,,H1$$D*;,X.""G(#(V
M,`!3"?``F2)214-/4D0@5$]/($Q/3D<B`%T)^@")(#$T,`!N"00!4DBRM2A2
M1:TR-38I`'\)#@%23+)21:LR-3:L4D@`I`D8`9@Q-2PB4"*JQR@Y-JHS*:K'
M*%),*:K'*%)(*:K'*#$I`-`)(@&-(#$P,#`ZBR!%3K(U,""G()@S+,<H,C4U
M*3J-(#$P,#`ZB2`R.#``VPDL`8T@,3`P,`#F"38!F#,L1$$D`/$)0`&-(#$P
M,#``%@I*`9@Q-2PB4"*JQR@Y-JHS*:K'*%),*:K'*%)(*:K'*#$I`"$*5`&-
M(#$P,#``,`I>`:`@,SJ@(#$U.H``10KH`X0Q-2Q%3BQ%320L150L15,`50KJ
L`XL@14ZS,C`@IR".`'(*\@.9(D524D]2.B([14TD.J`@,SJ@(#$U.H``````
`
end

  To  use  the  above  program  lines  for the version with fixed
length fields, we would alter a few lines as follows:

BASIC 7.0:

start tok64 /128 writf128.prg
  100 input"enter record number";re
  110 :
  120 dopen#3,"myrelfile",l88
  130 bl$="{160*27}"
  140 input"name";na$
  145 ln=len(na$)
  150 if ln>27 then 140
  155 na$=na$+left$(bl$,27-ln)
  160 input"street";sa$
  165 ln=len(sa$)
  170 if ln>27 then 160
  175 sa$=sa$+left$(bl$,27-ln)
  180 input"city & state";cs$
  185 ln=len(cs$)
  190 if ln>23 then 180
  195 cs$=cs$+left$(bl$,23-ln)
  200 input"zip code";zp$
  205 ln=len(zp$)
  210 if ln>10 then 200
  215 zp$=zp$+left$(bl$,10-ln)
  220 da$=na$+sa$+cs$+zp$
  260 :
  270 :
  280 record#3,(re),1
  290 if ds=50 then print#3,chr$(255):gosub 1000:goto 280
  300 gosub 1000
  310 print#3,da$
  320 gosub 1000
  330 record#3,(re),1
  340 gosub 1000
  350 dclose#3:end
 1000 if ds<20 then return
 1002 :
 1010 print"error:";ds$:dclose#3:end
stop tok64

begin 644 writf128.prg
M`1P?'&0`A2)%3E1%4B!214-/4D0@3E5-0D52(CM210`E'&X`.@`^''@`_@TC
M,RPB35E214Q&24Q%(BQ,.#@`9!R"`$),)+(BH*"@H*"@H*"@H*"@H*"@H*"@
MH*"@H*"@H*"@(@!T'(P`A2).04U%(CM.020`@AR1`$Q.LL,H3D$D*0"4')8`
MBR!,3K$R-R"G(#$T,`"M')L`3D$DLDY!)*K(*$),)"PR-ZM,3BD`OQR@`(4B
M4U121454(CM3020`S1RE`$Q.LL,H4T$D*0#?'*H`BR!,3K$R-R"G(#$V,`#X
M'*\`4T$DLE-!)*K(*$),)"PR-ZM,3BD`$!VT`(4B0TE462`F(%-4051%(CM#
M4R0`'AVY`$Q.LL,H0U,D*0`P';X`BR!,3K$R,R"G(#$X,`!)'<,`0U,DLD-3
M)*K(*$),)"PR,ZM,3BD`71W(`(4B6DE0($-/1$4B.UI0)`!K'<T`3$ZRPRA:
M4"0I`'T=T@"+($Q.L3$P(*<@,C`P`)8=UP!:4"2R6E`DJL@H0DPD+#$PJTQ.
M*0"N'=P`1$$DLDY!)*I3022J0U,DJEI0)`"T'00!.@"Z'0X!.@#*'1@!_A(C
M,RPH4D4I+#$`[QTB`8L@1%.R-3`@IR"8,RS'*#(U-2DZC2`Q,#`P.HD@,C@P
M`/H=+`&-(#$P,#``!1XV`9@S+$1!)``0'D`!C2`Q,#`P`"`>2@'^$B,S+"A2
M12DL,0`K'E0!C2`Q,#`P`#8>7@'^#R,S.H``1A[H`XL@1%.S,C`@IR".`$P>
?Z@,Z`&4>\@.9(D524D]2.B([1%,D.OX/(S,Z@```````
`
end

BASIC 2.0:

start tok64 writef64.prg
  100 input"enter record number";re
  110 open 15,8,15
  120 open 3,8,3,"myrelfile,l,"+chr$(88)
  130 bl$="{160*27}"
  140 input"name";na$
  145 ln=len(na$)
  150 if ln>27 then 140
  155 na$=na$+left$(bl$,27-ln)
  160 input"street";sa$
  165 ln=len(sa$)
  170 if ln>27 then 160
  175 sa$=sa$+left$(bl$,27-ln)
  180 input"city & state";cs$
  185 ln=len(cs$)
  190 if ln>23 then 180
  195 cs$=cs$+left$(bl$,23-ln)
  200 input"zip code";zp$
  205 ln=len(zp$)
  210 if ln>10 then 200
  215 zp$=zp$+left$(bl$,10-ln)
  220 da$=na$+sa$+cs$+zp$
  260 rh=int(re/256)
  270 rl=re-256*rh
  280 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
  290 gosub 1000:if en=50 then print#3,chr$(255):gosub 1000:\
      goto 280
  300 gosub 1000
  310 print#3,da$
  320 gosub 1000
  330 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
  340 gosub 1000
  350 close 3:close 15:end
 1000 input#15,en,em$,et,es
 1002 if en<20 then return
 1010 print"error:";em$:close 3:close 15:end
stop tok64

begin 644 writef64.prg
M`0@?"&0`A2)%3E1%4B!214-/4D0@3E5-0D52(CM210`M"&X`GR`Q-2PX+#$U
M`$X(>`"?(#,L."PS+")-65)%3$9)3$4L3"PBJL<H.#@I`'0(@@!"3"2R(J"@
MH*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H"(`A`B,`(4B3D%-12([3D$D`)((
MD0!,3K+#*$Y!)"D`I`B6`(L@3$ZQ,C<@IR`Q-#``O0B;`$Y!)+).022JR"A"
M3"0L,C>K3$XI`,\(H`"%(E-44D5%5"([4T$D`-T(I0!,3K+#*%-!)"D`[PBJ
M`(L@3$ZQ,C<@IR`Q-C``"`FO`%-!)+)3022JR"A"3"0L,C>K3$XI`"`)M`"%
M(D-)5%D@)B!35$%412([0U,D`"X)N0!,3K+#*$-3)"D`0`F^`(L@3$ZQ,C,@
MIR`Q.#``60G#`$-3)+)#4R2JR"A"3"0L,C.K3$XI`&T)R`"%(EI)4"!#3T1%
M(CM:4"0`>PG-`$Q.LL,H6E`D*0"-"=(`BR!,3K$Q,""G(#(P,`"F"=<`6E`D
MLEI0)*K(*$),)"PQ,*M,3BD`O@G<`$1!)+).022J4T$DJD-3)*I:4"0`SPD$
M`5)(LK4H4D6M,C4V*0#@"0X!4DRR4D6K,C4VK%)(``4*&`&8,34L(E`BJL<H
M.3:J,RFJQRA23"FJQRA22"FJQR@Q*0`Q"B(!C2`Q,#`P.HL@14ZR-3`@IR"8
M,RS'*#(U-2DZC2`Q,#`P.HD@,C@P`#P*+`&-(#$P,#``1PHV`9@S+$1!)`!2
M"D`!C2`Q,#`P`'<*2@&8,34L(E`BJL<H.3:J,RFJQRA23"FJQRA22"FJQR@Q
M*0"""E0!C2`Q,#`P`)$*7@&@(#,ZH"`Q-3J``*8*Z`.$,34L14XL14TD+$54
M+$53`+8*Z@.+($5.LS(P(*<@C@#3"O(#F2)%4E)/4CHB.T5-)#J@(#,ZH"`Q
&-3J`````
`
end

  If field contents vary in length,  variable  field  lengths are
often  preferable.  On  the other hand,  if the field lengths are
stable,  fixed field lengths are preferable.  Fixed length fields
are  also  required  if  you  want  to  use  the  optional offset
parameter of the  RECORD#  command  to point at a particular byte
within a record.  However,  when any part of a record is written,
DOS overwrites any remaining spaces in the record.  Thus,  if you
must use the offset option,  never  update  any field in a record
other than the last one unless all succeeding fields will also be
updated from memory later.
  The above programs  are careful to match record lengths exactly
to the space available.  Programs  that don't do so will discover
that   DOS  pads  short  records  out  to  full  size  with  fill
characters,  and  truncates  overlong  records to fill only their
allotted  space.  When  a  record is truncated, DOS will indicate
error "51,OVERFLOW IN RECORD", but short records will be accepted
without a DOS error message.


5.10. READING A RELATIVE RECORD

  Once  a  relative record has been written properly to diskette,
reading it back  into computer memory  is fairly simple,  but the
procedure  again  varies,  depending  on whether it uses fixed or
variable  length  fields.  Here  are  the program lines needed to
read  back  the  variable fields created above from record number
RE in file and channel 3:

BASIC 7.0:

start tok64 /128 readv128.prg
   10 :
   20 dopen#3,"myrelfile",l88
   30 input"enter record number";re
   40 :
   50 :
   60 record#3,(re),1
   70 gosub 1000
   80 input#3,na$,sa$,cs$,zp$
   90 gosub 1000
  100 record#3,(re),1
  110 gosub 1000
  120 print na$:print sa$
  130 print cs$:print zp$
  140 dclose#3:end
 1000 if ds<20 then return
 1002 :
 1010 print"error:";ds$:dclose#3:end
stop tok64

begin 644 readv128.prg
M`1P''`H`.@`@'!0`_@TC,RPB35E214Q&24Q%(BQ,.#@`/AP>`(4B14Y415(@
M4D5#3U)$($Y534)%4B([4D4`1!PH`#H`2APR`#H`6AP\`/X2(S,L*%)%*2PQ
M`&4<1@"-(#$P,#``?!Q0`(0S+$Y!)"Q3020L0U,D+%I0)`"''%H`C2`Q,#`P
M`)<<9`#^$B,S+"A212DL,0"B'&X`C2`Q,#`P`+(<>`"9($Y!)#J9(%-!)`#"
M'((`F2!#4R0ZF2!:4"0`S1R,`/X/(S,Z@`#='.@#BR!$4[,R,""G((X`XQSJ
>`SH`_!SR`YDB15)23U(Z(CM$4R0Z_@\C,SJ`````
`
end

BASIC 2.0:

start tok64 readv64.prg
   10 open 15,8,15
   20 open 3,8,3,"myrelfile,l,"+chr$(88)
   30 input"enter record number";re
   40 rh=int(re/256)
   50 rl=re-256*rh
   60 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
   70 gosub 1000
   80 input#3,na$,sa$,cs$,zp$
   90 gosub 1000
  100 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
  110 gosub 1000
  120 print na$:print sa$
  130 print cs$:print zp$
  140 close 3:close 15:end
 1000 input#15,en,em$,et,es
 1002 if en<20 then return
 1010 print"error:";em$:close 3:close 15:end
stop tok64

begin 644 readv64.prg
M`0@/"`H`GR`Q-2PX+#$U`#`(%`"?(#,L."PS+")-65)%3$9)3$4L3"PBJL<H
M.#@I`$X('@"%(D5.5$52(%)%0T]21"!.54U"15(B.U)%`%\(*`!22+*U*%)%
MK3(U-BD`<`@R`%),LE)%JS(U-JQ22`"5"#P`F#$U+")0(JK'*#DVJC,IJL<H
M4DPIJL<H4D@IJL<H,2D`H`A&`(T@,3`P,`"W"%``A#,L3D$D+%-!)"Q#4R0L
M6E`D`,((6@"-(#$P,#``YPAD`)@Q-2PB4"*JQR@Y-JHS*:K'*%),*:K'*%)(
M*:K'*#$I`/((;@"-(#$P,#```@EX`)D@3D$D.ID@4T$D`!()@@"9($-3)#J9
M(%I0)``A"8P`H"`S.J`@,34Z@``V">@#A#$U+$5.+$5-)"Q%5"Q%4P!&">H#
KBR!%3K,R,""G((X`8PGR`YDB15)23U(Z(CM%320ZH"`S.J`@,34Z@```````
`
end

  Here are the lines  needed to read back  the version with fixed
length fields:

BASIC 7.0:

start tok64 /128 readf128.prg
   10 :
   20 dopen#3,"myrelfile",l88
   30 input"enter record number";re
   40 :
   50 :
   60 record#3,(re),1
   70 gosub 1000
   80 input#3,da$
   90 gosub 1000
  100 record#3,(re),1
  110 gosub 1000
  112 na$=left$(da$,27)
  114 sa$=mid$(da$,28,27)
  116 cs$=mid$(da$,55,23)
  118 zp$=right$(da$,10)
  120 print na$:print sa$
  130 print cs$:print zp$
  140 dclose#3:end
 1000 if ds<20 then return
 1002 :
 1010 print"error:";ds$:dclose#3:end
stop tok64

begin 644 readf128.prg
M`1P''`H`.@`@'!0`_@TC,RPB35E214Q&24Q%(BQ,.#@`/AP>`(4B14Y415(@
M4D5#3U)$($Y534)%4B([4D4`1!PH`#H`2APR`#H`6AP\`/X2(S,L*%)%*2PQ
M`&4<1@"-(#$P,#``<!Q0`(0S+$1!)`!['%H`C2`Q,#`P`(L<9`#^$B,S+"A2
M12DL,0"6'&X`C2`Q,#`P`*@<<`!.022RR"A$020L,C<I`+T<<@!3022RRBA$
M020L,C@L,C<I`-(<=`!#4R2RRBA$020L-34L,C,I`.0<=@!:4"2RR2A$020L
M,3`I`/0<>`"9($Y!)#J9(%-!)``$'8(`F2!#4R0ZF2!:4"0`#QV,`/X/(S,Z
M@``?'>@#BR!$4[,R,""G((X`)1WJ`SH`/AWR`YDB15)23U(Z(CM$4R0Z_@\C
&,SJ`````
`
end

BASIC 2.0:

start tok64 readf64.prg
   10 open 15,8,15
   20 open 3,8,3,"myrelfile,l,"+chr$(88)
   30 input"enter record number";re
   40 rh=int(re/256)
   50 rl=re-256*rh
   60 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
   70 gosub 1000
   80 input#3,da$
   90 gosub 1000
  100 print#15,"p"+chr$(96+3)+chr$(rl)+chr$(rh)+chr$(1)
  110 gosub 1000
  112 na$=left$(da$,27)
  114 sa$=mid$(da$,28,27)
  116 cs$=mid$(da$,55,23)
  118 zp$=right$(da$,10)
  120 print na$:print sa$
  130 print cs$:print zp$
  140 close 3:close 15:end
 1000 input#15,en,em$,et,es
 1002 if en<20 then return
 1010 print"error:";em$:close 3:close 15:end
stop tok64

begin 644 readf64.prg
M`0@/"`H`GR`Q-2PX+#$U`#`(%`"?(#,L."PS+")-65)%3$9)3$4L3"PBJL<H
M.#@I`$X('@"%(D5.5$52(%)%0T]21"!.54U"15(B.U)%`%\(*`!22+*U*%)%
MK3(U-BD`<`@R`%),LE)%JS(U-JQ22`"5"#P`F#$U+")0(JK'*#DVJC,IJL<H
M4DPIJL<H4D@IJL<H,2D`H`A&`(T@,3`P,`"K"%``A#,L1$$D`+8(6@"-(#$P
M,#``VPAD`)@Q-2PB4"*JQR@Y-JHS*:K'*%),*:K'*%)(*:K'*#$I`.8(;@"-
M(#$P,#``^`AP`$Y!)++(*$1!)"PR-RD`#0ER`%-!)++**$1!)"PR."PR-RD`
M(@ET`$-3)++**$1!)"PU-2PR,RD`-`EV`%I0)++)*$1!)"PQ,"D`1`EX`)D@
M3D$D.ID@4T$D`%0)@@"9($-3)#J9(%I0)`!C"8P`H"`S.J`@,34Z@`!X">@#
MA#$U+$5.+$5-)"Q%5"Q%4P"(">H#BR!%3K,R,""G((X`I0GR`YDB15)23U(Z
3(CM%320ZH"`S.J`@,34Z@```````
`
end


5.11. THE VALUE OF INDEX FILES

  In the last two chapters you have learned how to use sequential
and relative files separately.  But they are often used together,
with the sequential file used to keep brief records of which name
in  the  relative  file is stored in each record number. That way
the  contents  of  the  sequential file can be read into a string
array and sorted alphabetically. After sorting, a technique known
as a binary search can be used to quickly find an entered name in
the  array,  and  read  in  or write the associated record in the
relative  file.  Advanced  programs can maintain two or more such
index files, sorted in differing ways simultaneously.



6. DIRECT ACCESS COMMANDS


  Direct  access  commands  specify  individual  sectors  on  the
diskette,  reading  and  writing  information entirely under your
direction.  This  gives them almost complete flexibility in data-
handling programs, but imposes tremendous responsibilities on the
programmer.  As a result,  they are normally used only in complex
commercial  programs  able to properly organize data without help
from the disk drive itself.
  A far more common use of direct access commands is  in  utility
programs  used  to  view and alter parts of the diskette that are
not normally seen directly.  For  instance,  such commands can be
used to change the name of a diskette  without erasing all of its
programs,  to lock a program so it can't be erased,  or hide your
name in a location where it won't be expected.


6.1. OPENING A DATA CHANNEL FOR DIRECT ACCESS

  When  working  with  direct access data,  you need two channels
open to the disk:  the  command channel we've used throughout the
book,  and  another for data.  The command channel is opened with
the  usual  OPEN 15,8,15  or  equivalent.  A  direct  access data
channel  is  opened  much like other files,  except that the hash
sign (#),  optionally followed by a memory buffer number, is used
as a file name.

FORMAT FOR DIRECT ACCESS FILE OPEN STATEMENTS:

  OPEN file#,device#,channel#,"#buffer#"

where "file#" is the file number,  "device#" is the disk's device
number,  normally  8;  "channel#" is the channel number, a number
between  2 and 14  not used by other files open at the same time;
and  "buffer#",  if present,  is a 0,  1,  2,  3,  4,  5,  or  6,
specifying  the  memory  buffer  within  the 1581 to use for this
file's data.

EXAMPLES:

To specify which disk buffer to use:

  OPEN 4,8,4,"#2"

If  you  don't  specify  which to use  (OPEN 5,8,5,"#"), the 1581
selects one.


6.2. BLOCK-READ

  The  purpose  of  a  BLOCK-READ  is  to  load the contents of a
specified  sector  into  a  file buffer.  Although the BLOCK-READ
command (B-R) is still part of the DOS command set,  it is nearly
always replaced the U1 command (See Chapter 6).

FORMAT FOR THE BLOCK-READ COMMAND:

  PRINT#15,"U1";channel#;drive#;track#;sector#

where  "channel#"  is  the channel number specified when the file
into  which  the  block will be read was opened,  "drive#" is the
drive number,  and  "track#"  and  "sector#" are respectively the
track  and sector numbers containing the desired block of data to
be read into the file buffer.

ALTERNATE FORMATS:

  PRINT#15,"U1:"channel#;drive#;track#;sector#
  PRINT#15,"UA:"channel#;drive#;track#;sector#
  PRINT#15,"U1:channel#,drive#,track#,sector#"

EXAMPLE:

  Here  is  a  complete program to read a sector into disk memory
using  U1,  and  from  there into computer memory via GET#. (If a
carriage  return will appear at least once in every 88 characters
of data, INPUT# may be used in place of GET#).

  110 MB=7936: REM $1F00            Define a memory buffer.
  120 INPUT"TRACK TO READ";T        Select a track
  130 INPUT"SECTOR TO READ";S       and sector.
  140 OPEN 15,8,15                  Open command channel.
  150 OPEN 5,8,5,"#"                Open direct access channel.
  160 PRINT#15,"U1";5;0;T;S         Read sector into disk buffer.
  170 FOR I=MB TO MB+255            Use a loop to
  180 GET#5,A$: IF A$=""            copy disk buffer
      THEN A$=CHR$(0)               into computer memory.
  190 POKE I,ASC(A$)
  200 NEXT
  210 CLOSE 5:CLOSE 15              Tidy up after.
  220 END

  As the loop progresses, the contents of the specified track and
sector are copied into computer memory,  beginning at the address
set by variable MB in line 160,  and  may be examined and altered
there.

  The  DOS  always checks that the track and sector parameters of
the  BLOCK-READ  command are within the proper range.  If they're
not,  a "66, ILLEGAL TRACK AND SECTOR"  error occurs.  In certain
instances it might be necessary to access a track and sector that
are not within what the DOS considers the proper bounds.  This is
a  special  case  and,  unless  absolutely  necessary,  should be
avoided. Nonetheless, there is a command identical in function to
"U1" that doesn't check to see if the track and sector parameters
are within bounds before attempting to read it. Its format is:

  PRINT#15,"B-_";channel#;drive#;track#;sector#
  (The character following the B- is a shifted R.)

                        or

  PRINT#15,"B-";CHR$(210);channel#;drive#;track#;sector#


6.3. BLOCK-WRITE

The  purpose  of  a BLOCK-WRITE is to save the contents of a file
buffer  into  a  specified sector.  It is thus the reverse of the
BLOCK-READ  command.  Although  the  BLOCK-WRITE command (B-W) is
still  part of the DOS command set,  it is nearly always replaced
by the U2 command.

FORMAT FOR THE BLOCK-WRITE COMMAND:

  PRINT#15,"U2";channel#;drive#;track#;sector#

where  "channel#"  is the channel number specified  when the file
into  which  the  block will be read was opened;  "drive#" is the
drive number;  and  "track#"  and  "sector#" are respectively the
track  and  sector  numbers that should receive the block of data
being saved from the file buffer.

ALTERNATE FORMATS:

  PRINT#15,"U2:"channel#;drive#;track#;sector#
  PRINT#15,"UB:"channel#;drive#;track#;sector#
  PRINT#15,"U2:channel#,drive#,track#,sector#"

EXAMPLES:

  To restore  Track 40,  Sector 3  of the directory from the disk
buffer filled by a BLOCK-READ, use:

  PRINT#15,"U2";5;0;40;3

You'll return to this example on the next page,  after  you learn
to alter the directory in a useful way.
  You  can  also  use  a  BLOCK-WRITE to write a name in Track 1,
Sector 1,  a  rarely-used  sector.  This  can be used as a way of
marking a diskette  as belonging to you.  Here is a program to do
it, using the alternate form of the BLOCK-WRITE command:

  110 INPUT"YOUR NAME";NA$            Enter a name.
  120 OPEN 15,8,15                    Open command channel.
  130 OPEN 4,8,4,"#"                  Open direct access channel.
  140 PRINT#4,NA$                     Write name to buffer.
  150 PRINT#15,"U2";4;0;1;1           Write buffer to Track1,
  160 CLOSE 4                         Sector 1 of diskette.
  170 CLOSE 15                        Tidy up after.
  180 END

As with the  BLOCK-READ command,  there is a  BLOCK-WRITE command
identical in function to  "U2"  that does not check the track and
sector parameters for valid bounds before attempting to write the
sector. Its format is:

  PRINT#15,"B-o";channel#;drive#;track#;sector#
  (The character after the B- is a shifted W.)

                       or

  PRINT#15,"B-";CHR$(215);channel#;drive#;track#;sector#


6.4. THE ORIGINAL BLOCK-READ AND BLOCK-WRITE COMMANDS

  Although  the  BLOCK-READ  and  BLOCK-WRITE commands are nearly
always  replaced  by  the  U1  and  U2 commands respectively, the
original  commands  can  still  be  used,  as  long  as you fully
understand their effects. Unlike U1 and U2, B-R and B-W allow you
to read or write less than a full sector. In the case of B-R, the
first  byte  of  the  selected  sector  is used to set the buffer
pointer (see next section), and determines how many bytes of that
sector are read into a disk memory buffer. A program may check to
be sure it  doesn't attempt to read past the end of data actually
loaded  into  the  buffer,  by watching for the value of the file
status  variable  ST  to change from 0 to 64.  When the buffer is
written  back  to diskette by B-W,  the first byte written is the
current  value  of  the buffer pointer.  Only that many bytes are
written into the specified sector. B-R and B-W may thus be useful
in working with custom-designed file structures.

FORMAT FOR THE ORIGINAL BLOCK-READ AND BLOCK-WRITE COMMANDS:

  PRINT#15,"BLOCK-READ";channel#;drive#;track#;sector#

abbreviated as: PRINT#15,"B-R";channel#;drive#;track#;sector#

and

  PRINT#15,"BLOCK-WRITE";channel#;drive#;track#;sector#

abbreviated as: PRINT#15,"B-W";channel#;drive#;track#;sector#

where  "channel#"  is  the channel number specified when the file
into  which  the  block will be read was opened,  "drive#" is the
drive number, and "track#" and "sector#" are the track and sector
numbers containing the desired block of data to be partially read
into or written from the file buffer.

+---------------------------- NOTE -----------------------------+
|   In a true BLOCK-READ, the first byte of the selected sector |
| is  used  to  determine how many bytes of that sector to read |
| into the disk  memory buffer.  It thus cannot be used to read |
| an entire sector  into the buffer,  as the first data byte is |
| always  interpreted  as  being  number of characters to read, |
| rather than part of the data.                                 |
|   Similarly,  in  a  true  BLOCK-WRITE,  when  the  buffer is |
| written  back  to  diskette,  the  first  byte written is the |
| current value of the  buffer  pointer.  Only  that many bytes |
| are written into the specified  sector.  It cannot be used to |
| rewrite an entire sector onto diskette unchanged, because the |
| first data byte is overwritten by the buffer pointer.         |
+---------------------------------------------------------------+


6.5. THE BUFFER POINTER

  The buffer pointer points to where the next  READ or WRITE will
begin within a disk memory buffer.  By moving the buffer pointer,
you can access individual bytes within a block in any order. This
allows  you to edit any portion of a sector,  or organize it into
fields, like a relative record.

FORMAT FOR THE BUFFER-POINTER COMMAND:

  PRINT#15,"BUFFER-POINTER";channel#;byte

usually abbreviated as: PRINT#15,"B-P";channel#;byte

where  "channel#"  is  the channel number specified when the file
reserving the buffer was opened,  and  "byte"  is  the  character
number within the buffer at which to point (from 0 through 255).

ALTERNATE FORMATS:

  PRINT#15,"B-P:"channel#;byte
  PRINT#15,"B-P:channel#,byte"

EXAMPLE:

  Here  is  a  program  that locks the first program or file on a
diskette.  It works by reading the start of the directory  (Track
40, Sector 3) into disk memory, setting the buffer pointer to the
first  file  type  byte  (see Appendix C for details of directory
organization), locking it by setting bit 6 and rewriting it.

  110 OPEN 15,8,15                 Open command channel.
  120 OPEN 5,8,5,"#"               Open direct access channel.
  130 PRINT#15,"U1";5;0;40;3       Read Track 40, Sector 3.
  140 PRINT#15,"B-P";5;2           Point to Byte 2 of the buffer.
  150 GET#5,A$: IF A$=""
      THEN A$=CHR$(0)              Read it into memory.
  160 A=ASC(A$) OR 64              Turn on bit 6 to lock.
  170 PRINT#15,"B-P";5;2           Point to Byte 2 again.
  180 PRINT#5,CHR$(A);             Overwrite it in buffer.
  190 PRINT#15,"U2";5;0;40;3       Rewrite buffer to diskette.
  200 CLOSE 5                      Tidy up after.
  210 CLOSE 15
  220 END

After the above program is run,  the  first file on that diskette
can  no  longer be erased.  If you later need to erase that file,
rerun the same program, but substitute the revised line 160 below
to unlock the file again:

  160 A=ASC(A$) AND 191            Turn off bit 6 to unlock.


6.6. ALLOCATING BLOCKS

  Once  you  have  written  something in a particular sector on a
diskette  with  the  help of direct access commands, you may wish
to mark that sector as  "already used",  to keep other files from
being written there. Blocks thus allocated will be safe until the
diskette is validated.

FORMAT FOR BLOCK-ALLOCATE COMMAND:

  PRINT#15,"BLOCK-ALLOCATE";drive#;track#;sector#

usually abbreviated as: PRINT#15,"B-A";drive#;track#;sector#

where  "drive#" is the drive number,  and  "track#" and "sector#"
are  the track and sector containing the block of data to be read
into the file buffer.

ALTERNATE FORMAT:

  PRINT#15,"B-A:";drive#;track#;sector#

EXAMPLE:

  If  you  try  to allocate a block that isn't available, the DOS
will set the error message to number  65,  NO BLOCK,  and set the
track  and  sector  numbers  in  the  error  message  to the next
available track and sector number.  Therefore, before selecting a
block to write,  try  to allocate that block.  If the block isn't
available,  read  the next available block from the error channel
and allocate it instead.  However, do not allocate data blocks in
the  directory  track.  If  the  track  number returned is 0, the
diskette is full.
  Here is a program  that allocates a place to store a message on
a diskette.

  100 OPEN 15,8,15             Open command channel.
  110 OPEN 5,8,5,"#"           Open direct access channel.
  120 PRINT#5,"I THINK
      THEREFORE I AM"          Write a message to buffer.
  130 T=1: S=1                 Start at first track & sector.
  140 PRINT#15,"B-A";0;T;S     Try allocating it.
  150 INPUT#15,EN,EM$,ET,ES    See if it worked.
  160 IF EN=0 THEN 210         If so, we're almost done.
  170 IF EN<>65 THEN PRINT     "NO BLOCK"
      EN,EM$,ET,ES: STOP       means already allocated.
  180 IF ET=0 THEN PRINT       If next track is 0,
      "DISK FULL": STOP        we're out of room.
  190 IF ET=40 THEN ET=41:ES=0 Don't allocate the directory.
  200 T=ET: S=ES: GOTO 140     Try suggested track & sector next.
  210 PRINT#15,"U2";5;0;T;S    Write buffer to allocated
                               sector.
  220 PRINT "STORED AT:";T,S   Say where message went
  220 CLOSE 5: CLOSE 15        and tidy up.
  230 END


6.7. FREEING BLOCKS

  The  BLOCK-FREE  command is the opposite of  BLOCK-ALLOCATE. It
frees  a  block  that you don't need any more,  for re-use by the
DOS.  BLOCK-FREE  updates  the BAM to show a particular sector is
not in use, rather than actually erasing any data.

FORMAT FOR BLOCK-FREE COMMAND:

  PRINT#15,"BLOCK-FREE";drive#;track#;sector#

abbreviated as: PRINT#15,"B-F";drive#;track#;sector#

where  "drive#" is the drive number,  and  "track#" and "sector#"
are  respectively  the  track  and  sector numbers containing the
desired block of data to be read into the file buffer.

ALTERNATE FORMAT:

  PRINT#15,"B-F:";drive#;track#;sector#

EXAMPLE:

  To  free  the  sector  in which we wrote our name in the BLOCK-
WRITE example, and allocated in the first BLOCK-ALLOCATE example,
we could use the following command:

  PRINT#15,"B-F";0;1;1


6.8. PARTITIONS AND SUB-DIRECTORIES

  The 1581 allows the user to create partition areas on the disk.
Partitions were originally implemented to provide a mechanism for
easily  protecting  a  particular  section  of  the disk. That is
useful  for  permanently  allocating  part of the disk for things
such as BOOT sectors, CP/M work area, or reserving space for user
defined random files.
  Normally,  sectors on the disk can be marked as used by setting
the appropriate bit in the RAM  (most easily done with the BLOCK-
ALLOCATE  command).  That prevents them from being overwritten. A
VALIDATE command, however, will de-allocate this area. To protect
these  special  blocks from being de-allocated during a VALIDATE,
place them in a user defined partition area. The VALIDATE command
in  the  1581  automatically  skips  over  file  entries that are
partition files (file type = CBM),  which guarantees the intended
area is, and remains, allocated.
  Partition areas are given names by the user when first created.
They appear in the main directory as file type CBM.
  A partition area is created by the following command:

  PRINT#15,"/0:partition name,"+CHR$(starting track)+CHR$
  (starting sector)+CHR$(<# of sectors)+CHR$(># of sectors)+",C"

  Large  enough  partitions  can also be used as sub-directories.
There are, however, certain limitations if a partition area is to
be used as a sub-directory area.

  1) The partition are must be at least 120 sectors in size.
  2) The starting sector must be 0.
  3) The ending sector must be a multiple of 40.
  4) The area to be allocated cannot contain track 40 (the
     original system track).

  Partitions  can  also  be  created with a partition. This means
that  sub-sub-directories can be created if their partitions meet
the above rules. Graphically, it looks like this:

               ROOT (/)
                  |
  ----------------------------------       ...     ----------
      |            |            |                       |
  /0:PART1     /0:PART2     /0:PART3      .....     /0:PARTn
                   |
         ---------------------
            |             |
        /0:PART2      /0:PART2
        /0:PART21     /0:PART22

  Partition  areas  which meet the qualifications of being a sub-
directory can then be selected by the following command:

  PRINT#15,"/0:partition name"

  Once  selected,  the  partition  are  cannot  be used as a sub-
directory until it is formatted.  The  HEADER or NEW commands are
used  to  format  this  sub-disk  area.  Make  sure that you have
successfully  selected  this partition area before formatting. If
not, the wrong directory area will be reformatted.  You can check
if  the  area  was  successfully  selected  by checking the error
channel. If everything went OK, the error channel would read:

  02, SELECTED PARTITION,first track#,last track#

  If   the   area  you  attempt  to  select  does  not  meet  the
qualifications of a sub-directory,  then  the error channel would
return:

  77, SELECTED PARTITION ILLEGAL,00,00

  Only  one  level of sub-directory can be selected at a time. To
get from the ROOT to PART21 you would have to execute the command
twice.

  PRINT#15,"/0:PART2"
  PRINT#15,"/0:PART21"

  Directories  can only be traversed in the forward direction. To
get  to  sub-directory  which  is  on  a node above the presently
selected node of the tree, you must select the ROOT directory and
work your way down the tree, selecting a branch at a time. To get
to the ROOT directory directly from any node type:

  PRINT#15,"/"

  When the user selects a particular sub-directory area,  it then
becomes  the  default  working  area.  Accesses  to  the disk for
directories, loading files, saving files, etc.,  will all be done
within  this  area.  Files  outside  of  the  selected  area  are
effectively invisible.
  File  and  local BAM information for sub-directories are stored
within  the  sub-directory  areas themselves.  The information is
stored  on  the  first allocated track of the partition area, and
has the same format as track 40.  When  creating  partitions  and
sub-directories  within  sub-directories it is the responsibility
of  the  user  to  make  sure  that  he  doesn't  overwrite  this
information!  The  DOS  only  checks  to make sure that you don't
attempt  to  overwrite  this  information  for the ROOT directory
(track 40).  It  is  up  to  the  user  to  make  sure  that this
information isn't corrupted in the sub-directories.
  Partitioned  areas  can  be freed up  simply by  SCRATCHING the
partition  file  entry  in  the  appropriate  directory.  If  the
partition was being used as a sub-directory,  all of the files in
that sub-directory will be lost.


6.9. USING RANDOM FILES

  By combining the commands in this chapter,  it  is  possible to
develop a file-handling program that uses random files.  What you
need to know now is how to keep track of which blocks on the disk
such a file has used. (Even though you know a sector has not been
allocated by your random file,  you  must  also be sure it wasn't
allocated by another unrelated file on the diskette.)
  The  most  common way of recording which sectors have been used
by  a  random  file is in a sequential file.  The sequential file
stores a list of record numbers, with the track, sector, and byte
location of each record.  This means three channels are needed by
a random file:  one  for the command channel,  one for the random
data, and the last for the sequential data.



7. INTERNAL DISK COMMANDS


  Expert  programmers  can  give commands that directly alter the
workings of the  1581,  much as skilled programmers can alter the
workings of BASIC inside the computer with PEEKs,  POKEs  and SYS
calls.  It  is  also  possible to write machine language programs
that  load  and  run entirely within the 1581,  either by writing
them into disk memory from  the  computer,  or  by  loading  them
directly  from diskette into the desired disk memory buffer. This
is  similar  to  loading and running machine language programs in
your computer.
  As when learning to use PEEK,  POKE  and  SYS in your computer,
extreme caution is advised in using the commands in this chapter.
They are essentially machine language commands,  and  lack all of
BASIC's safeguards.  If anything goes wrong, you may have to turn
the disk drive off and on again  (after removing the diskette) to
regain  control.  Do not practice these commands on any important
diskette.  Rather,  make a spare copy and work with that. Knowing
how  to program a 6502 in machine language will help greatly, and
you  will  also need a good memory map of the 1581.  A brief 1581
map appears below.

                         1581 MEMORY MAP

Location                        Purpose
-----------------------------------------------------------------
0000-00FF       Zero page work area, job queue, variables
0100-01FF       Stack, variables, vectors
0200-02FF       Command buffer, tables, variables
0300-09FF       Data buffers (0-6)
0A00-0AFF       BAM for tracks 0-39
0B00-0BFF       BAM for tracks 40-79
0C00-1FFF       Track cache buffer
4000-5FFF       8520A CIA
6000-7FFF       WD177X FDC
8000-FEFF       32K byte ROM, DOS and controller routines
FF00-FFFF       Jump table, vectors
-----------------------------------------------------------------


+---------------------------- NOTE -----------------------------+
|   The  1581,  as  well  as  other  Commodore  peripherals, is |
| designed   to   support   interfacing  via  software  command |
| structures.  The software commands provided in the 1581 allow |
| for   a   smooth   and  controllable  interface  between  the |
| peripheral  and  CPU.  Although  Commodore  has  provided the |
| mechanism  enabling  users  to  load  and  execute  their own |
| machine language programs within the 1581 system, please keep |
| in mind that Commodore reserves the right to change ROM, RAM, |
| I/O and hardware structure at any time.  Consequently, if the |
| defined software interface is bypassed,  future compatibility |
| of  the  user's machine language software within the 1581 may |
| be in question. The 1581 was not designed primarily as a user |
| programmable  device,  but Commodore recognizes that  certain |
| operations   (such  as  copy  protection)  cannot  be  easily |
| achieved without this ability.                                |
+---------------------------------------------------------------+

  If  you  find  it  necessary to use machine language within the
1581,  use  the jump table listed in this chapter and Chapter 10.
That  will  lessen the possibility of incompatibility if a future
version of the 1581 changes internally.  Also, let the controller
work for you on the physical level by requesting its help via the
JOB QUEUE.  That  too  will  greatly  increase  the likelihood of
future compatibility.


7.1. MEMORY-READ

  The 6502 has an address  space  from  $0000-$FFFF.  You can get
direct  access  to  any  location  within  this  by  using memory
commands. MEMORY-READ allows you to select which byte or bytes to
read from disk memory into the computer.  The MEMORY-READ command
is  the  equivalent  of the BASIC PEEK() function,  but reads the
disk's memory instead of the computer's memory.

+---------------------------- NOTE -----------------------------+
|   Unlike other disk commands, those in this chapter cannot be |
| spelled out in full. Thus, M-R is correct, but MEMORY-READ is |
| not a permitted alternate wording.                            |
+---------------------------------------------------------------+

FORMAT FOR THE MEMORY-READ COMMAND:

  PRINT#15,"M-R"CHR$(<address)CHR$(>address)CHR$(# of bytes)

where  "<address"  is the low order part,  and  ">address" is the
high order part of the address in disk memory to be read.  If the
optional  "# of bytes"  is specified,  it selects how many memory
locations will be read in,  from 1-256  (# of bytes = 0 for 256).
Otherwise, 1 character will be read.

  The next byte read using the GET# statement through channel #15
(the  error  channel),  will  be  from  that  address in the disk
controller's memory, and successive bytes will be from successive
memory locations.
  Any  INPUT#  from  the error channel will give peculiar results
when you're using this command. This can be cleared up by sending
any other command to the disk, except another memory command.

EXAMPLES:

  To  see  how many tries the disk will make to read a particular
sector,  and  whether  "bumps"  to  track  one  and  back will be
attempted before declaring the sector unreadable, you can use the
following  lines.  They  will read a special variable in the zero
page  of  disk  memory,  called  REVCNT.  It  is  located  at $30
hexadecimal.

110 OPEN 15,8,15                            Open command channel.
120 PRINT#15,"M-R"CHR$(48)CHR$(0)           Same as G=PEEK(48).
130 GET#15,G$: IF G$="" THEN G$=CHR$(0)
140 G=ASC(G$)
150 B=G AND 128:B$="ON":IF B THEN B$="OFF"  Check bit 7.
160 T=G AND 31: PRINT"# OF TRIES IS";T      Check bits 0-5
170 PRINT "BUMPS ARE";B$                    and give results.
180 CLOSE 15                                Tidy up after.
190 END

Here's  a  more  general  purpose  program that reads one or more
locations anywhere in disk memory:

110 OPEN 15,8,15                            Open command channel.
120 INPUT "# OF BYTES TO READ (0=END)";NL   Enter number of bytes
                                            wanted
130 IF NL<1 THEN CLOSE 15: END              unless done.
140 IF NL>255 THEN 120                      or way out of line.
150 INPUT "STARTING AT ADDRESS";AD          Enter starting
                                            address.
160 AH=INT(AD/256): AL=AD-AH*256            Convert it into disk
                                            form.
170 PRINT#15,"M-R"CHR$(AL)CHR$(AH)CHR$(NL)  Actual Memory-Read.
180 FOR I=1 TO NL                           Loop until have all
                                            the data,
190 GET#15,A$: IF A$="" THEN A$=CHR$(0)
200 PRINT ASC(A$);                          printing it as we go,
210 NEXT I
220 PRINT
230 GOTO 120                                forever.


7.2. MEMORY-WRITE

  The  MEMORY-WRITE  command is the equivalent of the  BASIC POKE
command,  but has its effect in disk memory instead of within the
computer.  M-W  allows you to write up to 35 bytes at a time into
disk  memory.  The  MEMORY-EXECUTE  and some USER commands can be
used to run any programs written this way:

FORMAT FOR THE MEMORY-WRITE COMMAND:

  PRINT#15,"M-W"CHR$(<address)CHR$(>address)CHR$(# of bytes)
           CHR$(data byte(s))

where  "<address"  is the low order part,  and  ">address" is the
high order part of the address  in disk memory  to begin writing,
"# of bytes"  is  the  number  of  memory  locations that will be
written (from 1-35),  and "data byte" is 1 or more byte values to
be written into disk memory, each as a CHR$() value.

EXAMPLES:

We  can  use  this line to turn off the "bumps" when loading DOS-
protected  programs  (i.e.,  programs  that  have  been protected
against  being  copied by creating and checking for specific disk
errors).

  PRINT#15,"M-W"CHR$(48)CHR$(0)CHR$(1)CHR$(133)

  The following line can be used to recover bad sectors,  such as
when  an  important  file  has  been  damaged  and cannot be read
normally:

  PRINT#15,"M-W"CHR$(48)CHR$(0)CHR$(1)CHR$(31)

  These two examples may be very useful under some circumstances.
They   are   the   equivalent   of   POKE 48,133  and  POKE 48,31
respectively,  but  in  disk memory,  not inside the computer. As
mentioned in the previous section's first example, location 48 in
the  1581  disk  drive  signifies  two separate activities to the
drive,  all related to error recovery.  Bit 7  (the high bit), if
set means no  "bumps"  (don't move the read head to track 1). The
bottom six bits are the count of how many times the disk will try
to  read  each  sector  before  and  after trying seeks and bumps
before  giving  up.  Since  31  is the largest number that can be
expressed  in  six  bits,  that  is  the  maximum number of tries
allowed.
  From this example,  you  can see the value of knowing something
about  PEEKS,  POKES,  and  machine-language before using direct-
access disk commands, as well as their potential power.


7.3. MEMORY-EXECUTE

  Any routine in disk memory,  either  in  RAM  or  ROM,  can  be
executed with the MEMORY-EXECUTE command. It is the equivalent of
the  BASIC  SYS call to a machine language program or subroutine,
but works in disk memory instead of within the computer.

FORMAT FOR THE MEMORY-EXECUTE COMMAND:

  PRINT#15,"M-E"CHR$(<address)CHR$(>address)

where  "<address"  is the low order part,  and  ">address" is the
high order part of the address in disk memory  at which execution
is to begin.

  Most  uses  require intimate knowledge of the inner workings of
the  DOS,  and  preliminary  setup  with other commands,  such as
MEMORY-WRITE.

  The  routine  should  end  with an RTS to return control to the
1581.


7.4. BLOCK-EXECUTE

  This  rarely-used  command  will  load  a  sector  containing a
machine  language routine into a memory buffer from diskette, and
execute  it  from  the first location within the buffer,  until a
ReTurn from Subroutine (RTS) instruction ends the command.

FORMAT FOR THE BLOCK-EXECUTE COMMAND:

  PRINT#15,"B-E:";channel#;drive#;track#;sector#

where  "channel#"  is  the channel number specified when the file
into which the block will be loaded was opened,  "drive#"  is the
drive number,  and  "track#"  and  "sector#" are respectively the
track  and sector numbers containing the desired block of data to
be loaded into the file buffer and executed there.

ALTERNATE FORMATS:

  PRINT#15,"B-E:";channel#;drive#;track#;sector#
  PRINT#15,"B-E:channel#,drive#,track#,sector#"

EXAMPLES:

  Assuming  you've  written a machine language program onto Track
1,  Sector 8  of  a diskette,  and would like to run it in buffer
number 1  in  disk  memory  (starting  at $0400 hexadecimal), you
could do so as follows:

110 OPEN 15,8,15               Open command channel.
120 OPEN 2,8,2,"#1"            Open direct access channel to
                               buffer 1.
130 PRINT#15,"B-E:";2;0;1;8    Load Track1, Sector 8 in it
                               & execute.
140 CLOSE 2                    Tidy up after.
150 CLOSE 15
160 END


7.5. USER COMMANDS

  Most  USER commands are intended to be used as machine language
JMP  or  BASIC  SYS  commands  to  machine language programs that
reside inside the disk memory.  However,  some of them have other
uses  as  well.  The USER1 and USER2 commands are used to replace
the  BLOCK-READ  and BLOCK- WRITE commands, UI re-starts the 1581
without  changing many variables,  UJ cold-starts the 1581 almost
as if it had been turned off and on again.

USER Command                       Function
-----------------------------------------------------------------
U0                     restores default user jump table
U0 + (CMD)             burst utility command
                       (see Chapter 9 Burst Commands)
U1 or UA               block read replacement
U2 or UB               block write replacement
U3 or UC               jump to $0500
U4 or UD               jump to $0503
U5 or UE               jump to $0506
U6 or UF               jump to $0509
U7 or UG               jump to $050C
U8 or UH               jump to $050F
U9 or UI               jump to ($FFFA) reset tables
U: or UJ               power up vector
-----------------------------------------------------------------

  By loading these memory locations with another machine language
JMP  command,  such as JMP $0520,  you can create longer routines
that  operate in the disk's memory along with an easy-to-use jump
table.

FORMAT FOR USER COMMANDS:

  PRINT#15,"Ucharacter";

where  "character" defines one of the preset user commands listed
above.

EXAMPLES:

  PRINT#15,"U:";             Form of DOS RESET command
  PRINT#15,"U3";             Execute program at start of buffer 2


7.6. UTILITY LOADER

  This command loads a user-type  (USR)  file into the drive RAM.
The  first  two  bytes  of the file must contain the low and high
addresses   respectively.   The  third  byte  is  the  amount  of
characters to follow.  In the addition,  a trailing checksum byte
must be included. The load address is the starting address.

FORMAT FOR THE UTILITY LOADER COMMAND:

  PRINT#15,"&0:filename"

  To return from this routine,  the  program  should  end with an
RTS.


7.7. AUTO BOOT LOADER

  During some operations  (power-up reset,  burst INQUIRE,  burst
QUERY,  an  initialize command)  the 1581 will automatically look
for  a  file or the disk named  'COPYRIGHT CBM 86'  that is a USR
type-file.  The format of the file is the same  as that described
previously for the utility loader.  If it is present, the file is
automatically loaded and executed.

  The  automatic  loading  of this file can be disabled by either
renaming it, setting the appropriate flag in the RAM sectors (see
Appendix C),  or  by  setting  a  flag variable in RAM to disable
further autoboots (see JDEJAVU jump table vector in Chapter 10).

  At  the  end of the autobooted program it should return control
to the 1581 via the JCBMBOOTRTN jump table vector.



8. MACHINE LANGUAGE PROGRAMS


  Here  is  a  list  of  host  computer  disk-related  Kernal ROM
subroutines  and  a  practical  example of their use in a program
that reads a sequential file into memory from disk.  Most require
advance  setup  of  one  or  more  processor  registers or memory
locations  and  all  are  called  with  the assembly language JSR
command.
  For a more  complete  description  as to what each routine does
and how parameters are set for each routine, see the Programmer's
Reference Guide for your specific computer.


                 DISK-RELATED KERNAL SUBROUTINES

Label        Address                    Functions
-----------------------------------------------------------------
SETLFS  =    $FFBA     ; SET LOGICAL, FIRST & SECOND ADDRESSES
SETNAM  =    $FFBD     ; SET LENGTH & ADDRESS OF FILENAME
OPEN    =    $FFC0     ; OPEN LOGICAL FILE
CLOSE   =    $FFC3     ; CLOSE LOGICAL FILE
CHKIN   =    $FFC6     ; SELECT CHANNEL FOR INPUT
CHKOUT  =    $FFC9     ; SELECT CHANNEL FOR OUTPUT
CLRCHN  =    $FFCC     ; CLEAR ALL CHANNELS & RESTORE DEFAULT I/O
CHRIN   =    $FFCF     ; GET BYTE FROM CURRENT INPUT DEVICE
CHROUT  =    $FFD2     ; OUTPUT BYTE TO CURRENT OUTPUT DEVICE
        ;
START   LDA  #4        ; SET LENGTH & ADDRESS
        LDX  #<FNADR   ; OF FILE NAME, LOW
        LDY  #>FNADR   ; & HIGH BYTES
        JSR  SETNAM    ; FOR NAME SETTER
        LDA  #3        ; SET FILE NUMBER
        LDX  #8        ; DISK DEVICE NUMBER
        LDY  #0        ; AND SECONDARY ADDRESS
        JSR  SETLFS    ; AND SET THEM
        JSR  OPEN      ; OPEN 3,8,0,"TEST"
        LDX  #3
        JSR  CHKIN     ; SELECT FILE 3 FOR INPUT
NEXT    JSR  CHRIN     ; GET NEXT BYTE FROM FILE
        BEQ  END       ; UNTIL FINISH OR FAIL
        JSR  CHROUT    ; OUTPUT BYTE TO SCREEN
        JMP  NEXT      ; AND LOOP BACK FOR MORE
        ;
END     LDA  #3        ; WHEN DONE
        JSR  CLOSE     ; CLOSE FILE
        JSR  CLRCHN    ; RESTORE DEFAULT I/O
        RTS            ; BACK TO BASIC
        ;
FNADR   .BYT "TEST"    ; STORE FILE NAME HERE



9. BURST COMMANDS


  The  Burst  Command  Instruction  Set  (BCIS)  is  a  series of
powerful,  versatile,  and complex commands that enables the user
to format,  read,  and write in numerous formats.  Burst commands
are sent via kernal calls, but the handshaking of data is done by
the user for maximum performance. There is no parameter checking,
so exercise care  when using the BCIS.  For instance,  if a burst
read  with an illegal track address is sent to a 1581,  the drive
will keep trying to find the invalid track.  Reading  and writing
in other formats is automatic if the commands are given in proper
sequence. Please become thoroughly familiar with all the commands
and follow the examples given in this chapter.  It's important to
follow the handshake conventions exactly for maximum performance.
  With the exception of  READ  and  WRITE,  burst commands do not
translate  from  logical to physical track and sector.  All track
and  sector  parameters  refer to physical locations (see Chapter
10).  Burst  sector  READ  and  WRITE  commands provide a flag to
enable logical to physical translation.  If the flag is set,  the
drive  does  the  translation  and  the default logical number of
bytes  per  sector  (256)  is transferred instead of the physical
number of bytes per sector (512).


9.1. CMD 1 -- READ

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       L      E      X      S      0      0      0      N
-----------------------------------------------------------------
  03                       DESTINATION TRACK
-----------------------------------------------------------------
  04                       DESTINATION SECTOR
-----------------------------------------------------------------
  05                       NUMBER OF SECTORS
-----------------------------------------------------------------
  06                      NEXT TRACK (OPTIONAL)
-----------------------------------------------------------------

RANGE: All  values  are  determined by the particular disk format
       and format of translation table.

SWITCHES: L -- logical flag(1=do logical to physical translation)
          E -- ignore error (1 = ignore)
          S -- side select
          N -- drive number

PROTOCOL: Burst handshake.

CONVENTIONS: Before you can READ or WRITE to a diskette,  it must
             be logged-in using either the  INQUIRE DISK or QUERY
             DISK FORMAT command (both are described later). This
             must be done once each time you change diskettes.

OUTPUT: One burst status byte,  followed  by burst data,  is sent
        for each sector transferred.  An error prevents data from
        being sent unless the E bit is set.


9.2. CMD 2 -- WRITE

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       L      E      X      S      0      0      1      N
-----------------------------------------------------------------
  03                       DESTINATION TRACK
-----------------------------------------------------------------
  04                       DESTINATION SECTOR
-----------------------------------------------------------------
  05                       NUMBER OF SECTORS
-----------------------------------------------------------------
  06                      NEXT TRACK (OPTIONAL)
-----------------------------------------------------------------

RANGE: All  values  are  determined by the particular disk format
       and format of translation table.

SWITCHES: L -- logical flag(1=do logical to physical translation)
          E -- ignore error (1 = ignore)
          S -- side select
          N -- drive number

PROTOCOL: Burst  data  to  the drive,  then host must perform the
          following:  fast  serial input,  pull the clock low and
          wait  for  the  burst status byte,  pull clock high, go
          output for multi-sector transfers and continue.

CONVENTIONS: Before you can READ or WRITE to a diskette,  it must
             be logged-in using either the  INQUIRE DISK or QUERY
             DISK FORMAT command (both are described later). This
             must be done once each time you change diskettes.

INPUT: Host must transfer burst data.

OUTPUT: One burst status byte following each WRITE operation.


9.3. CMD 3 -- INQUIRE DISK

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       X      X      X      S      0      1      0      N
-----------------------------------------------------------------

SWITCHES: N -- drive number

PROTOCOL: Burst handshake.

OUTPUT: One   burst   status  byte  following  each  INQUIRE DISK
        operation.


9.4. CMD 4 -- FORMAT

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       M      X      X      X      0      1      1      N
-----------------------------------------------------------------
  03   SECTOR SIZE           *(OPTIONAL, DEF-02,512 BYTE SECTORS)
-----------------------------------------------------------------
  04   LAST TRACK NUMBER      (OPTIONAL, DEF-79)
-----------------------------------------------------------------
  05   NUMBER OF SECTORS    **(OPTIONAL, DEF DEPENDS ON BYTE 03)
-----------------------------------------------------------------
  06   STARTING TRACK         (OPTIONAL, DEF-0)
-----------------------------------------------------------------
  07   FILL BYTE              (OPTIONAL, DEF-$E5)
-----------------------------------------------------------------
  08   STARTING SECTOR        (OPTIONAL, DEF-1)
-----------------------------------------------------------------

SWITCHES: M -- mode (1 = will accept BYTES 03-08,0 = will format,
          create directory and BAM)
          N -- drive number

PROTOCOL: Conventional.

CONVENTIONS: CMD 4 must be followed with CMD 3  or  CMD 6 once to
             log the disk in.

OUTPUT: None. Status will be updated within the drive.


9.5. CMD 6 -- QUERY DISK FORMAT

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       F      X      T      S      1      0      1      N
-----------------------------------------------------------------
  03               OFFSET      (OPTIONAL, F-BIT SET)
-----------------------------------------------------------------

SWITCHES: F -- force flag  (F = 1 steps the head  with the offset
          specified in byte 03)
          T -- sector table (T = 1, send sector table)
          N -- drive number
          X -- don't care
          S -- side select

PROTOCOL: Burst handshake.

CONVENTIONS: Determines  the  diskette  format  on any particular
             track.   Also   logs  non-standard  diskettes  (i.e.
             minimum sector addresses other than one).

OUTPUT:  * burst status byte (no bytes will follow if there is an
           error)
        ** burst status byte  (no bytes will follow  if there was
           an error in compiling MFM format information)
           number of sectors (on a particular track)
           logical track (track number found in the disk header)
           minimum sector (sector with the lowest value address)
           maximum sector (sector with the highest value address)
           interleave (always returns 1)
           sector table (with T bit set, sector table is sent)
 * status from track offset zero
** if F bit is set, status is from offset track


9.6. CMD 7 -- INQUIRE STATUS

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       W      C      M      0      1      1      0      N
-----------------------------------------------------------------
  03                  NEW STATUS (W-BIT CLEAR)
-----------------------------------------------------------------
  04                  NEW ORA MASK (M-BIT SET)
-----------------------------------------------------------------
  05                  NEW AND MASK (M-BIT SET)
-----------------------------------------------------------------

SWITCHES: W -- write switch (0 = write)
          M -- write AND/OR mask (04 new OR mask (M-bit set),  05
          new AND mask (M-bit set))
          C -- change (C=1 and W=0 -- log in disk, C=1 and W=1 --
          return  whether  disk was logged,  i.e. $B error or old
          status)
          N -- drive number
          X -- don't care

PROTOCOL: Burst handshake (W=1), conventional (W=0).

CONVENTIONS: This  is  a  method  of  reading  or writing current
             status, and changing the status mask value.

OUTPUT: None (W=0), Burst status byte (W=1).


9.7. CMD 8 -- DUMP TRACK CACHE BUFFER

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       F      S      X      1      1      1      0      1
-----------------------------------------------------------------
  03                         PHYSICAL TRACK
-----------------------------------------------------------------

SWITCHES: X -- don't care
          S -- side select
          F -- (1 = write even if not "dirty")


9.8. CHGUTL UTILITY

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       X      X      X      1      1      1      1      0
-----------------------------------------------------------------
  03     UTILITY COMMANDS: 'B','S','R','T','V',#DEV,'MR','MW'
-----------------------------------------------------------------
  04     COMMAND PARAMETER
-----------------------------------------------------------------

SWITCHES: X -- don't care

UTILITY COMMANDS; 'B' -- serial bus mode
                  'S' -- DOS sector interleave
                  'R' -- DOS retries
                  'T' -- ROM signature analysis
                  'V' -- verify select
                  #DEV -- device#

Note: Byte 02 is equivalent to '>'.

EXAMPLES: "U0>B1" = Fast Serial, "U0>B0" = Slow Serial
          "U0>S" + CHR$(SECTOR INTERLEAVE)
          "U0>R" + CHR$(RETRIES)
          "U0>T" (If the ROM signature failed, the activity LED
                 blinks 4 times)
          "U0>V0" = Disk Verify ON, "U0>V1" = Disk Verify OFF
          "U0>" + CHR$(#DEV), where #DEV = 4 - 30
          "U0>MR" + CHR$(>memory address) + (# of pages)*
          "U0>MW" + CHR$(>memory address) + (# of pages)*

 * Burst memory read and memory write use standard burst protocol
   (without status byte).


9.9. FASTLOAD UTILITY

 BYTE    BIT 7    6      5      4      3      2      1      0
-----------------------------------------------------------------
  00       0      1      0      1      0      1      0      1
-----------------------------------------------------------------
  01       0      0      1      1      0      0      0      0
-----------------------------------------------------------------
  02       P      X      X      1      1      1      1      1
-----------------------------------------------------------------
  03                          FILE NAME
-----------------------------------------------------------------

SWITCHES: P -- sequential file bit (P = 1,  does not have to be a
          program file)
          X -- don't care

PROTOCOL: Burst handshake.

OUTPUT: Burst status byte preceding each sector transferred.

STATUS IS AS FOLLOWS:   0000000X -- OK
                      * 00000010 -- file not found
                     ** 00011111 -- EOI

*  Values between 3 and 15 should be considered a file read error
** The  byte  following the EOI status byte is the number of data
   bytes to follow.


9.10. STATUS BYTE BREAKDOWN

 BIT 7    6       5       4       3       2       1       0
-----------------------------------------------------------------
 MODE     DN     SECTOR SIZE         [ CONTROLLER STATUS]
-----------------------------------------------------------------
*MODE -- 1 = Alien Disk Format  (non-default physical format,  or
         default  physical  format  without   Directory  and  BAM
         information)
         0 = Resident Disk Format  (default  physical format with
         Directory and BAM information)
 DN  --  drive number

*Resident Disk Format is based on whether required information is
 present in BAM/DIRECTORY track.

SECTOR SIZE
             00 ........ 128 BYTE SECTORS (NOT SUPPORTED)
             01 ........ 256 BYTE SECTORS
             10 ........ 512 BYTE SECTORS (DEFAULT)
             11 ........ 1024 BYTE SECTORS

CONTROLLER STATUS
             000X ...... OK
             0010 ...... CAN'T FIND HEADER BLOCK
             0011 ...... NO ADDRESS MARK
             0100 ...... DATA BLOCK NOT PRESENT
             0101 ...... DATA CRC ERROR
             0110 ...... FORMAT ERROR
             0111 ...... VERIFY ERROR
             1000 ...... WRITE PROTECT ERROR
             1001 ...... HEADER BLOCK CRC ERROR
             1010 ...... WRITE PROTECTED
             1011 ...... DISK CHANGE
             1100 ...... DISK FORMAT NOT LOGICAL
             1101 ...... RESERVED
             1110 ...... SYNTAX ERROR
             1111 ...... NO DRIVE PRESENT


9.11. BURST TRANSFER PROTOCOL

  Before  using  the following burst transfer routines,  you must
determine  whether  or  not the peripheral is a fast device.  The
Fast   Serial  (byte  mode)  protocol  makes  that  determination
internally  when  you  include a query routine (send-cmd-string).
This  routine  addresses the peripheral as a listener and thereby
determines its speed.


BURST READ

send-cmd-string;                      (*determine speed*)
if device-fast then
    serial-in;                        (*serial port input*)
    repeat                            (*repeat for all sectors*)
        read-error;                   (*retrieve error byte*)
    toggle-clock;                     (*wait for status*)
    wait-byte;                        (*wait for byte*)
    if status = ok then
        toggle-clock;                 (*start double buffer*)
        repeat                        (*repeat for sector-size*)
            wait-byte;                (*get data*)
            toggle-clock;             (*start next*)
            store-byte;               (*save data*)
        until last-byte;              (*last byte ?*)
    until last-sector;                (*until last sector*)
    set-clock-high;                   (*restore clock*)
else
    read-1581;                        (*send unit read*)


BURST WRITE

send-cmd-string;                      (*determine speed*)
if device-fast then
    repeat                            (*repeat for all sectors*)
        serial-out;                   (*serial port out*)
            repeat                    (*repeat for sector-size*)
                send-byte;            (*send byte*)
            until last-byte;          (*last byte ?*)
        serial-in;                    (*serial port in*)
        set-clock-low;                (*ready for status*)
        read-err;                     (*controller error ?*)
        set-clock-high;               (*restore clock*)
    until last-sector;                (*until last sector*)
else
    write-1581;                       (*send unit write*)


EXPLANATION OF PROCEDURES

send-cmd-string   sends  one  byte  of  the  command to determine
                  whether the drive is fast or slow.

toggle-clock      changes the state of the clock line.

set-clock-high    changes the state of the clock to logic 1.

set-clock-low     changes the state of the clock to logic 0.

wait-byte         polls the 8520 for a byte ready.

read-error        calls toggle-clock and wait-byte,  then returns
                  to the main if there are no errors.

store-data        stores data in a particular memory location.

last-byte         depending  on  sector size,  will increment and
                  compare value to sector size.

serial-in         sets the 8520 serial port and driver circuit to
                  input mode.

read-err          calls wait-byte and evaluates the status of the
                  previous controller job.

serial-out        sets the 8520 serial port and driver circuit to
                  output mode.

send-byte         sends a byte of data to the 1581.

read-1581         sends a typical unit read to a 1581.

write-1581        sends a typical unit write to a 1581.


HANDSHAKE

  The  figure  below  shows the burst transfer protocol.  It is a
state-dependent protocol (simple and fast).  As the clock line is
toggled,  a byte of data is sent.  Burst protocol is divided into
three parts.

   1. Send Command: send string using existing kernal routines.

   2. Query: determine whether the peripheral is fast.

   3. Handshake Code: follow handshake conventions.

         _____________       ______       ______       ______
   DATA         \\\\\\\      \\\\\\\      \\\\\\\      \\\\\\\
                 -----------------------------------------------

         -+            +------------+            +------------
   CLK    |            |            |            |
          +------------+    ARFD    +------------+
                            (Acknowledge and Ready For Data)
               RFD (Ready For Data)

         _____         ___         ___         ___         ___
   SRQ        |||||||||   |||||||||   |||||||||   |||||||||
              |||||||||   |||||||||   |||||||||   |||||||||


+---------------------------- NOTE -----------------------------+
|   An example of using the burst routines is on the  test/demo |
| diskette.  Print  those  files and use them as references for |
| creating your own programs that use burst protocol.           |
+---------------------------------------------------------------+



10. 1581 INTERNAL OPERATION


This  chapter  describes  some  of the internal operations of the
1581  --  how things work on the 'other side of the fence' of the
host computer.  Experienced programmers may find this information
useful.  The information learned in previous chapters (especially
Chapter 7)  combined with that presented in this chapter provides
a  wide  realm  of  possibilities for the creative and persistent
programmer. Please be reminded, however, of the NOTE presented at
the beginning of Chapter 7 regarding future compatibility.


10.1. LOGICAL VERSUS PHYSICAL FORMAT

  All  DOS  operations  of  the 1581 are done in 256 byte blocks.
These blocks appear as individually numbered sectors on the disk.
By  going  through the DOS interface via the commands outlined in
this manual, the logical disk format is as follows:

  single sided
  80 tracks (track 1 through track 80)
  40 x 256 byte sectors per track (sector 0 through sector 39)

  Internally,  however,  the 1581 has a different view of things.
The disk is actually formatted as follows:

  double sided (side 0 and side 1)
  80 tracks per side (track 0 through track 79)
  10 x 512 byte sectors per track (sector 1 through sector 10)

  That  is  the  physical  disk  format created whenever a HEADER
(NEW)  command  is  sent  to the 1581 from the host computer. The
physical  format  is different from the logical so that more data
can be squeezed onto each disk.

  All commands sent from the host computer are parsed through the
DOS  (except the BURST commands) and refer to the logical format.
Software  inside the 1581 automatically takes care of the logical
to  physical translations necessary to retrieve the data properly
from the disk.


10.2. TRACK CACHE BUFFER

  One  of  the  improvements  in  the  1581  design over previous
Commodore  disk  drives  which makes the device more efficient is
the Track Cache buffer. This buffer is located from $0C00 through
$1FFF.  All  disk  accesses involve an entire physical track at a
time.  If  a single sector is needed from a particular track, the
entire  track is read into RAM.  Consequently,  any more requests
for sectors from the same track require only a RAM data transfer,
rather  than  a  search  of  the  track on the disk again. Sector
writes  are also speeded up considerably,  since each consecutive
write  to  sectors  on  the same track requires only a RAM to RAM
data transfer. After data is written into the Track Cache Buffer,
it  is not written to the disk until one of the following occurs:
1) a request is made for access of a sector on a different track,
2) a  'dump  track  buffer'  command is issued,  or  3) after 250
milliseconds of no serial bus activity.


10.3. CONTROLLER JOB QUEUE

  The  software  in  the  1581's  ROM can be broken down into two
major  components  --  the DOS and the Controller.  The DOS (Disk
Operating  System)  is  the  software  interface between the host
computer  and  the  1581 system.  The DOS keeps track of the file
management details necessary to create,  modify and delete files.
It  monitors  the  amount of free space left on a disk, and keeps
track of the file names in the directory. It remembers where each
file starts, and ensures that none of them overlap. When the host
sends commands,  the DOS checks make sure that the syntax and the
parameters  are  valid.  The  DOS  is very complex,  and its code
occupies the majority of the ROM.

  The  Controller,  on  the  other hand,  knows nothing about the
concept of files. The Controller deals only in the physical world
of  the  disk  itself.  It is responsible for reading and writing
each of the individual sectors on the disk.

  The  DOS  and  Controller  communicate  to each other primarily
through  a  'mailbox',  known  as the Job Queue.  Because the DOS
deals more in the abstract, or logical, world, it does not access
the physical disk itself. If the DOS requires access to the disk,
it must ask the controller to do it.  The DOS places a Controller
Command  Code into the Job Queue and then waits for the requested
operation  to  be  completed.  The Controller polls the Job Queue
every 10 milliseconds  (the polling rate is determined by timer B
of  8520)  looking for something to do.  If there is a job in the
queue,  the Controller executes the job and returns a status byte
to the DOS.  To speed things up, the polling of the job queue can
be  bypassed  by  a  direct  jump  to JSTROBE_CONTROLLER at $FF54
(refer to the section describing the Vectored Jump Table). A call
to JSTROBE_CONTROLLER requires the command in the accumulator and
the job queue offset in the x register.

  Most  of  the tasks that the Controller can be asked to perform
require parameters. The parameters are also placed in a 'mailbox'
location  for  the  Controller  to  access  (prior to placing the
command byte into the queue, of course).  These parameters can be
either the physical or the logical parameters,  depending on what
the command expects to see. Logical parameters are placed in HDRS
as  two consecutive bytes of track,  sector.  Physical parameters
are  also  placed  in  HDRS,  but  in  addition  the side must be
specified  (in  SIDS).  Commands  that require logical parameters
must  translate  them  into  physical parameters at some point in
their  execution.  The  logical  parameters  are  translated into
physical parameters by a vectored routine called TRANSTS, and are
written into  HDRS2  and  SIDS.  The DOS will always pass logical
parameters, and uses only the Controller commands that allowed to
put  jobs  in  its  own  queue,  so  it  needs  to  pass physical
parameters as well as logical.

               Mailbox Locations of the Controller
-----------------------------------------------------------------
Name     Address  Purpose
-----------------------------------------------------------------
JOBS      $0002   JOB queue for Controller commands (JOBS 0-8).
            .     Each JOB uses 1 byte. The last 2 locations
            .     ($09,$0A) are reserved for BAM jobs only!
          $000A
HDRS      $000B   Logical or physical track, sector for each of
            .     the jobs in the JOB queue (2 bytes per job).
            .
          $001C
HDRS2     $01BC   Translated (physical) track, sector for each
            .     of the jobs in the JOB queue (2 bytes per job).
            .
          $01CD
SIDS      $01CE   Physical side for each of the jobs
            .     in the job queue (1 byte per job).
            .
          $01D6
CACHE     $008B   Pointer to BUFFCACHE below.
CACHEOFF  $009F   Offset into the track cache buffer.
            .     (1 byte per job).
            .
          $00A7
BUFFCACHE $0C00   20 pages for track cache.
            .
            .
          $1FFF

  Associated with each of the nine  Job Queue  locations  (Jobs 0
through 8) are nine 256 byte buffers (buffers 0-8),  beginning at
location  $0300.  Data passed from/to a particular Job during its
execution  is  located  in  the  buffer  which corresponds to the
position  of  the  Controller  Job  Code  in  the  Job Queue. For
example,  if the  Controller  Code  in  Job Queue  position 2 (at
location  $0004)  requests that a logical sector of data be read,
the data is put into Buffer 2 (at location $0500).

  Table 1 is a list of Controller Job Codes  that can be put into
the  Job Queue.  Table 2 is a list of the codes that are returned
by the Controller once the job has been executed. The return code
is  placed  into  the  Job Queue in the same memory location that
contained the Controller Job Code. Consequently, the procedure to
use the Controller is the following:

  1) Write  any  parameters  needed by the Job into the parameter
     variables (HDRS, HDRS2, SIDS).
  2) Write the Controller Code into the Job Queue (JOBS).
  3) Wait  for  the  job  to  be  completed by simply polling the
     location in JOBS where the Job code was put, and waiting for
     it to change (bit 7 will be reset to 0).

-----------------------------------------------------------------
              TABLE 1: Controller JOB Command Codes
-----------------------------------------------------------------

-----------------------------------------------------------------
Name          Code    Description
-----------------------------------------------------------------
READ_DV       $80     Reads  a particular logical sector into the
                      job queue buffer  (only if the disk has not
                      been  changed).  If  the  desired sector is
                      already in the track cache buffer,  then no
                      disk  activity  is  required  (the  data is
                      merely  transferred  from  the  track cache
                      memory to the job queue buffer memory).  If
                      the  desired  sector  is  not  in the track
                      cache,  then  the  current  track  cache is
                      dumped  to  disk   (only  if  it  has  been
                      modified),  the  desired track is read into
                      the track cache, and finally the particular
                      sector's data is transferred from the track
                      cache memory to the job queue buffer.
WRTSD_DV      $90     Writes  the  job  queue's  buffer data to a
                      particular  logical track,  sector.  If the
                      same  track  is already in the track cache,
                      then  this  involves  only transferring the
                      job  queue  buffer  data to the track cache
                      buffer.  If  a different track's data is in
                      the  disk  (only  if  it was modified), the
                      desired  track  read  into  the track cache
                      buffer,  and finally the job queue buffer's
                      data transferred to the track cache.
WRTVER_DV     $A0     Verifies  the  track  cache  buffer's  data
                      against the specified logical track's data.
SEEKHD_DV     $B0     Logs  in a disk by reading information from
                      the  first  header  encountered on the disk
                      into RAM so that it can be used by the DOS.
                      The track cache buffer is not updated.
SEEKPHD_DV    $B8     Seeks   to   a  particular  logical  track,
                      sector. The track cache is not updated.
RESTORE_DV    $C0     Restores  the  read/write  head  to track 0
                      ('bump').
JUMPC_DV      $D0     Executes  the code in the corresponding job
                      queue buffer.
EXBUF_DV      $E0     Executes  the code in the corresponding job
                      queue buffer after the motor is up to speed
                      and the head is on track.
RESET_DV      $82     Resets  the  disk controller and associated
                      variables.
MOTON_DV      $84     Turns on the spindle motor  (overlays a $01
                      in the Job Queue after the spin-up sequence
                      is complete).
MOTOFF_DV     $86     Turns the spindle motor off after the spin-
                      down sequence is complete.
MOTONI_DV     $88     Turns the spindle motor on immediately.
MOTOFFI_DV    $8A     Turns the spindle motor off immediately.
SEEK_DV       $8C     Seeks  to  a  particular   physical   track
                      (cylinder).   The  current  physical  track
                      position   should   be  put  in  the  track
                      parameter of HDRS.
FORMAT_DV     $8E     Formats  one  physical track (one half of a
                      cylinder).   The   head   must   be  placed
                      physically  over  the  proper cylinder, and
                      the  head  electronics must be selected for
                      the side desired.
DISKIN_DV     $92     Determines  if  there is a disk inserted in
                      the drive.
LEDACTON_DV   $94     Turns on the activity LED.
LEDACTOFF_DV  $96     Turns off the activity LED.
ERRLEDON_DV   $98     Enables error LED blinking.
ERRLEDOFF_DV  $9A     Disables error LED blinking.
SIDE_DV       $9C     Sets  up the side select electronics to the
                      value specified (in SIDS).
BUFMOVE_DV    $9E     Moves data between the job queue buffer and
                      the track cache buffer. The track parameter
                      in  the  job  queue denotes the position in
                      the track cache buffer to transfer to/from.
                      The sector parameter denotes the following:
                        Bit 7 :  Direction  (1 = to  track  cache
                                 buffer)
                        Bit 6 :  Mark Flag  (set/clear the 'track
                                 cache modified' flag)
                        Bit 5 :  Transfer (1 = do the transfer)
                        Bits 4-0:# of 256 byte blocks to transfer
                      With bit 7 set,  the corresponding physical
                      track  position  in  the  job queue (HDRS2)
                      must  be updated for the purpose of telling
                      the  controller  what  physical  track  the
                      track cache buffer belongs to.  In addition
                      the side var (SIDS) must also be updated.
TRKWRT_DV     $A2     Dumps  the  track  cache buffer to the disk
                      (only  if  the track cache modified flag is
                      set).
SP_READ       $A4     Reads   the   specified   physical   sector
                      directly  into  RAM starting at #0 ($0300).
                      It does not use the track cache buffer. The
                      sector   is   always  read  from  the  disk
                      regardless  of  the current contents of the
                      track cache.
SP_WRITE      $A6     Writes  to  the  specified  physical sector
                      directly.  It does not use the track cache.
                      Data  to  be  written  starts  at buffer #0
                      ($0300).
PSEEK_DV      $A8     Seeks to the specified physical track.
TREAD_DV      $AA     Reads  logical address without transferring
                      to the job queue buffer.
TWRT_DV       $AC     Writes    a    logical    address   without
                      transferring from the job queue buffer.
TPREAD_DV     $B2     Reads    a    physical    address   without
                      transferring to the job queue buffer.
TPWRT_DV      $B4     Writes    a    physical   address   without
                      transferring from the job queue buffer.
DETWP_DV      $B6     Checks   if  the  disk  inserted  is  write
                      protected.  Returns  $00  if  disk  is  not
                      protected, else $08.
FORMATDK_DV   $F0     Formats  the disk with the default physical
                      format.

-----------------------------------------------------------------
              TABLE 2: Controller JOB Return Codes
-----------------------------------------------------------------

-----------------------------------------------------------------
Name            Code  Description
-----------------------------------------------------------------
OK_DV            $0x  No error.
MISHD_DV_ER      $02  Can't find header block.
NOADAM_DV_ER     $03  No address mark detected.
MISDBLK_DV_ER    $04  Data block not present.
CRCDBLK_DV_ER    $05  CRC error encountered in data block.
FMT_DV_ER        $06  Format error.
VERERR_DV_ER     $07  Verify error.
WRTPR_DV_ER      $08  Attempt to write to a write protected disk.
CRCHD_DV_ER      $09  CRC error encountered in header block.
                 $0A  Reserved.
DSKCHG_DV_W      $0B  Disk was changed/disk ID mismatch.
DSKNTLOG_DV_ER   $0C  Disk format not logical.
CONTROLLER_DV_ER $0D  Floppy disk controller IC error.
SYNTAX_DV_ER     $0E  Syntax error. Invalid job number.
NODSKPRS_DV_ER   $0F  No disk is present in the drive.

  Here is an example BASIC program which will display the data on
any  sector of the 1581 disk.  It puts a READ SECTOR job directly
into the Controller Job Queue using MEMORY-WRITE,  and then reads
the  sector data directly from the Job Queue Buffer using MEMORY-
READ.

start tok64 /128 sector.prg
  10 open 1,8,15: rem open command channel to 1581
  20 open 2,8,2,"#": rem open buffer# 0 of the 1581 (at $0300)
  30 input"track, sector to read";t,s
  40 rem write track, sector parameters to hdrs in 1581 ram \
     (at $000b)
  50 print#1,"m-w"+chr$(11)+chr$(0)+chr$(2)+chr$(t)+chr$(s)
  60 rem put the read sector ($80) command into the job queue
  70 print#1,"m-w"+chr$(2)+chr$(0)+chr$(1)+chr$(128)
  80 rem read back the job queue where the command was just \
     written,
  90 rem waiting for the status to be written into it.
 100 print#1,"m-r"+chr$(2)+chr$(0)+chr$(1)
 110 get#1,a$:if asc(a$)>127 then 100
 120 print"status returned = ";asc(a$)
 125 rem read the translated track, sector values from hdrs2
 130 print#1,"m-r"+chr$(188)+chr$(1)+chr$(2)
 140 get#1,a$:pt=asc(a$)
 150 get#1,a$:ps=asc(a$)
 160 rem read the translated side value
 170 print#1,"m-r"+chr$(239)+chr$(0)+chr$(1)
 180 get#1,a$:side=asc(a$)
 190 print"translated track =";pt;" sector =";ps;" side= ";side
 200 print
 210 rem read the 256 bytes of data from 1581 job queue buffer \
     into cpu ram
 220 print#1,"m-r"+chr$(0)+chr$(3)+chr$(0)
 230 rem list the sector data
 240 print "{space*7}";
 245 print "0   1   2   3   4   5   6   7   8   9   a   b   c   \
     d   e   f"
 250 print "-------";
 255 print "----------------------------------------------------\
     ---------"
 260 for x=0 to 15
 270 print right$((x),1);tab(6);
 280 for y=1 to 16
 290 get#1,a$
 300 print using "####";right$(hex$(asc(a$)),2);
 310 next y
 320 print
 330 next x
stop tok64

begin 644 sector.prg
M`1PN'`H`GR`Q+#@L,34Z((\@3U!%3B!#3TU-04Y$($-(04Y.14P@5$\@,34X
M,0!G'!0`GR`R+#@L,BPB(R(Z((\@3U!%3B!"549&15(C(#`@3T8@5$A%(#$U
M.#$@*$%4("0P,S`P*0"('!X`A2)44D%#2RP@4T5#5$]2(%1/(%)%040B.U0L
M4P#,'"@`CR!74DE412!44D%#2RP@4T5#5$]2(%!!4D%-151%4E,@5$\@2$12
M4R!)3B`Q-3@Q(%)!32`H050@)#`P,$(I`/,<,@"8,2PB32U7(JK'*#$Q*:K'
M*#`IJL<H,BFJQRA4*:K'*%,I`"X=/`"/(%!55"!42$4@4D5!1"!314-43U(@
M*"0X,"D@0T]-34%.1"!)3E1/(%1(12!*3T(@455%544`41U&`)@Q+")-+5<B
MJL<H,BFJQR@P*:K'*#$IJL<H,3(X*0"3'5``CR!214%$($)!0TL@5$A%($I/
M0B!1545512!72$5212!42$4@0T]-34%.1"!705,@2E535"!74DE45$5.+`#'
M'5H`CR!704E424Y'($9/4B!42$4@4U1!5%53(%1/($)%(%=2251414X@24Y4
M3R!)5"X`XQUD`)@Q+")-+5(BJL<H,BFJQR@P*:K'*#$I```>;@"A(S$L020Z
MBR#&*$$D*;$Q,C<@IR`Q,#``(!YX`)DB4U1!5%53(%)%5%523D5$(#T@(CO&
M*$$D*0!:'GT`CR!214%$(%1(12!44D%.4TQ!5$5$(%1204-++"!314-43U(@
M5D%,5453($923TT@2$124S(`>!Z"`)@Q+")-+5(BJL<H,3@X*:K'*#$IJL<H
M,BD`C!Z,`*$C,2Q!)#I05++&*$$D*0"@'I8`H2,Q+$$D.E!3LL8H020I`,4>
MH`"/(%)%040@5$A%(%1204Y33$%4140@4TE$12!604Q510#C'JH`F#$L(DTM
M4B*JQR@R,SDIJL<H,"FJQR@Q*0#Y'K0`H2,Q+$$D.E-)1$6RQBA!)"D`-!^^
M`)DB5%)!3E-,051%1"!44D%#2R`](CM05#LB(%-%0U1/4B`](CM04SLB(%-)
M1$4]("([4TE$10`Z'\@`F0"#'](`CR!214%$(%1(12`R-38@0EE415,@3T8@
M1$%402!&4D]-(#$U.#$@2D]"(%%5155%($)51D9%4B!)3E1/($-052!204T`
MGQ_<`)@Q+")-+5(BJL<H,"FJQR@S*:K'*#`I`+H?Y@"/($Q)4U0@5$A%(%-%
M0U1/4B!$051!`,L?\`"9("(@("`@("`@(CL`$2#U`)D@(C`@("`Q("`@,B`@
M(#,@("`T("`@-2`@(#8@("`W("`@."`@(#D@("!!("`@0B`@($,@("!$("`@
M12`@($8B`"(@^@"9("(M+2TM+2TM(CL`:"#_`)D@(BTM+2TM+2TM+2TM+2TM
M+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM
M+2TB`'<@!`&!(%BR,""D(#$U`(P@#@&9(,DHTBA8*2PQ*3NC-BD[`)L@&`&!
M(%FR,2"D(#$V`*8@(@&A(S$L020`Q"`L`9D@^R`B(R,C(R([R2C2*,8H020I
>*2PR*3L`S"`V`8(@60#2($`!F0#:($H!@B!8````
`
end


10.4. VECTORED JUMP TABLE

  Each  of  the DOS commands that can be sent to the 1581 via the
serial  bus  are  vectored through indirect jumps in the ROM. The
indirect vectors are located in RAM, so the user can change these
vectors  for  the  purpose  of  providing a different routine, or
messaging  data  before  passing control to the original routine.
Each  of  these  vectors  are  their  locations are listed in the
table 3.

-----------------------------------------------------------------
              TABLE 3: Indirect Vector Jump Table
-----------------------------------------------------------------

-----------------------------------------------------------------
Name             Location  Description
-----------------------------------------------------------------
JIDLE              $FF00   Main  idle  loop.  When  a  Controller
                           command is completed  the IDLE routine
                           is executed. It first checks to see if
                           there are any more jobs pending in the
                           Job Queue. If so, it executes them. If
                           not,  it sits in the idle loop waiting
                           for  something  to  happen,   such  as
                           another  job being put into the queue,
                           ATN  line going low,  disk inserted or
                           removed, etc.
JIRQ               $FF03   Interrupt routine. Interrupts normally
                           occur  from  the following sources  --
                           ATN  line going low,  Fast Serial Byte
                           is   shifted   in,   timer  time  out,
                           execution of a BRK instruction.
JNMI               $FF06   Does  a  'soft'  reset  (UI  command).
                           Default   vectors  and  variables  are
                           restored.  Searches for "COPYRIGHT CBM
                           86"  USR  type  file  to  boot. No RAM
                           check or ROM checksum is done. Device#
                           switches are read.
JVERDIR            $FF09   VALIDATE command (collect).
JINTDRV            $FF0C   INITIALIZE command.
JPART              $FF0F   Routine to create or switch partitions
JMEM               $FF12   Memory  Read/Memory  Write  (M-R, M-W)
                           commands.
JBLOCK             $FF15   Performs all  BLOCK commands,  such as
                           ALLOCATE,  FREE, READ, WRITE, EXECUTE,
                           POINTER.
JUSER              $FF18   USER command.
JRECORD            $FF1B   RECORD   command   for  relative  file
                           positioning.
JUTLODR            $FF1E   Utility loader command (&).
JDSKCPY            $FF21   COPY command.
JRENAME            $FF24   RENAME command.
JSCRTCH            $FF27   SCRATCH command.
JNEW               $FF2A   NEW/Format command.
ERROR              $FF2D   Controller error handler routine.
JATNSRV            $FF30   Serial Bus attention (ATN) server.
JTALK              $FF33   Serial Bus talk routine.
JLISTEN            $FF36   Serial Bus listen routine.
JLCC               $FF39   Controller routine.
JTRANS_TS          $FF3C   Logical to physical sector translation
                           routine.
CMDERR             $FF3F   DOS error handler routine.

JSTROBE_CONTROLLER $FF54   Direct Controller call.
JCBMBOOT           $FF57   CBM autoloader routine.
JCBMBOOTRTN        $FF5A   Return   from   CBM   autoloader  with
                           autoloader disabled.
JSIGNATURE         $FF5D   Signature analysis routine.
JDEJAVU            $FF60   Switch    for   autoloader   boot   on
                           INITIALIZE   or   BURST INQUIRE/QUERY.
                           Enter   with   carry   set  to  enable
                           autoloader, carry clear to disable it.
JSPINOUT           $FF63   SPIN,  SPOUT.   Sets  up  fast  serial
                           direction  as  input or output.  Carry
                           set to do SPOUT, cleared to do SPIN.
JALLOCBUFF         $FF66   Allocates   RAM  buffers.   Call  with
                           buffer#  in  reg A  (1 = buffer 0, 2 =
                           buffer 1...).



APPENDIX A: CHANGING THE DEVICE NUMBER

  Two  switches  on the back of the 1581 enable you to change the
device#  of  the drive.  You can use a screwdriver,  pen,  or any
other  small tool to set the switches.  The following table shows
the settings required for each device number:

            +------------+------------+-------------+
            |    Left    |    Right   |   Device#   |
            +------------+------------+-------------+
            |     UP     |     UP     |      8      |
            |    DOWN    |     UP     |      9      |
            |     UP     |    DOWN    |      10     |
            |    DOWN    |    DOWN    |      11     |
            +------------+------------+-------------+

  Another  way  to temporarily change the device number of a disk
drive is via a program.  When power is first turned on, the drive
reads  an  I/O  location  whose  value  is  controlled by the two
switches  on  its circuit board,  and writes the device number it
reads  there  into  memory  locations  119  and  120.   Any  time
thereafter, you may write over that device number with a new one,
which will be effective until it is changed again, or the 1581 is
reset.

FORMAT FOR TEMPORARILY CHANGING THE DISK DEVICE NUMBER:

  PRINT#15,"U0>"+CHR$(n)

  Where n = 8 to 30

EXAMPLE:

  Here is a program that sets any device number:

   5 INPUT "OLD DEVICE NUMBER";ODV
  10 INPUT "NEW DEVICE NUMBER";DV
  20 IF DV<8 OR DV>30 THEN 10
  30 OPEN 15,ODV,15,"U0>"+CHR$(DV): CLOSE 15

+---------------------------- NOTE -----------------------------+
|   If  you  will  be  using  two  disk  drives,  and  want  to |
| temporarily change the device number of one, you will need to |
| run the above program with the disk drive whose device number |
| not to be changed turned off. After the program has been run, |
| you may turn that drive back on.  If you need to connect more |
| than  two  drives at once,  you will need to use the hardware |
| method of changing device numbers.                            |
+---------------------------------------------------------------+



APPENDIX B: DOS ERROR MESSAGES

Many commercial program diskettes  are intentionally created with
one or more of the following errors,  to keep programs from being
improperly  duplicated.  If  a  disk  error  occurs while you are
making  a  security copy of a commercial program diskette,  check
the program's manual.  If its copyright statement does not permit
purchasers to copy the program for their own use,  you may not be
able  to  duplicate  the diskette.  In some such cases,  a safety
spare  copy of the program diskette is available from your dealer
or directly from the company for a reasonable fee.

00: OK (not an error)
    This  is  the  message  that  usually  appears when the error
    channel is checked. It means there is no current error in the
    disk unit.

01: FILES SCRATCHED (not an error)
    This  is  the  message that appears when the error channel is
    checked  after  using  the SCRATCH command.  The track number
    tells how many files were erased.

02: PARTITION SELECTED (not an error)
    The disk partition requested has been selected.

+---------------------------- NOTE -----------------------------+
|   If  any  other  error  message  numbers  less  than 20 ever |
| appear, they may be ignored.  All true errors have numbers of |
| 20 or more.                                                   |
+---------------------------------------------------------------+

20: READ ERROR (block header not found)
    The  disk  controller  is  unable to locate the header of the
    requested data block.  Caused by an illegal block or a header
    that has been destroyed. Usually unrecoverable.

21: READ ERROR (drive not ready)
    The  disk  controller  is unable to detect a sync mark on the
    desired track.  Caused by misalignment, or a diskette that is
    absent,  unformatted or improperly seated.  Can also indicate
    hardware  failure.  Unless  caused by one of the above simple
    causes, this error is usually unrecoverable.

22: READ ERROR (data block not found)
    The  disk  controller  has been requested to read or verify a
    data   block  that  was  not  properly  written.   Occurs  in
    conjunction  with  BLOCK  commands  and  indicates an illegal
    track and/or sector request.

23: READ ERROR (CRC error in data block)
    There is an error in the data.  The sector has been read into
    disk memory, but its CRC is wrong.

24: READ ERROR (byte sector header)
    The  data  or  header  has  been read into disk memory, but a
    hardware  error has been created by an invalid bit pattern in
    the data byte.

25: WRITE ERROR (write-verify error)
    The  controller  has  detected  a  mismatch  between the data
    written  to  diskette  and  the same data in disk memory. May
    mean  the diskette is faulty.  If so,  try another.  Use only
    high-quality diskettes from reputable makers.

26: WRITE PROTECT ON
    The controller has been requested to write a data block while
    the  write-protect  sensor  is  uncovered.  Usually caused by
    writing  to  a  diskette  whose write protect notch is pushed
    back  to  expose  the hole to prevent changing the diskette's
    contents.

27: READ ERROR (CRC error in header)
    The  controller  detected an error in the header bytes of the
    requested  data  block.  The  block  was  not  read into disk
    memory.

30: SYNTAX ERROR (general syntax)
    The  DOS  cannot  interpret  the  command sent to the command
    channel.  Typically,  this  is caused by an illegal number of
    file  names or an illegal pattern.  Check your typing and try
    again.

31: SYNTAX ERROR (invalid command)
    The  DOS  does not recognize the command.  It must begin with
    the first character sent. Check your typing and try again.

32: SYNTAX ERROR (long line)
    The   command   sent  is  longer  than  58  characters.   Use
    abbreviated disk commands.

33: SYNTAX ERROR (invalid file name)
    Pattern  matching  characters  cannot  be  used  in  the SAVE
    command  or when Opening files for the purpose of Writing new
    data. Spell out the file name.

34: SYNTAX ERROR (no file given)
    The  file  name was left out of a command or the DOS does not
    recognize  it  as  such.  Typically,  a  colon (:)  has  been
    omitted. Try again.

39: SYNTAX ERROR (invalid command)
    The  DOS  does  not  recognize  a command sent to the command
    channel  (secondary  address  15).  Check your typing and try
    again.

50: RECORD NOT PRESENT
    The requested record number has not been created yet. This is
    not  an  error  in  a  new relative file or one that is being
    intentionally expanded. It results from reading past the last
    existing  record,  or  positioning  to  a non-existent record
    number with the RECORD# command.

51: OVERFLOW IN RECORD
    The  data  to  be  written  in the current record exceeds the
    record size. The excess has been truncated (cut off). Be sure
    to include all special characters  (such as carriage returns)
    in calculating record sizes.

52: FILE TOO LARGE
    There isn't room left on the diskette to create the requested
    relative record.  To avoid this error, create the last record
    number  that  will be needed as you first create the file. If
    the file is too large for the diskette,  either split it into
    two files on two diskettes,  or use abbreviations in the data
    to allow shorter records.

60: WRITE FILE OPEN
    A  write  file that has not been closed is being reopened for
    reading.  This file must be immediately rescued, as described
    in  BASIC  Hint #2  in  Chapter 2,  or it will become a splat
    (improperly closed) file and probably be lost.

61: FILE NOT OPEN
    A file is being accessed that has not been opened by the DOS.
    In some such cases no error message is generated.  Rather the
    request is simply ignored.

62: FILE NOT FOUND
    The  requested  file  does  not exist on the indicated drive.
    Check your spelling and try again.

63: FILE EXISTS
    A  file  with  the  same name as has been requested for a new
    file already exists on the diskette. Duplicate file names are
    not allowed. Select another name.

64: FILE TYPE MISMATCH
    The  requested file access is not possible using files of the
    type named. Reread the chapter covering that file type.

65: NO BLOCK
    Occurs  in  conjunction  with  B-A.  The  sector you tried to
    allocate  is already allocated.  The track and sector numbers
    returned  are  the next higher track and sector available. If
    the  track  number  returned is 0,  all remaining sectors are
    full. If the diskette is not full yet,  try a lower track and
    sector.

66: ILLEGAL TRACK AND SECTOR
    The  DOS has attempted to access a track or sector which does
    not  exist.  May  indicate  a faulty link pointer in the data
    block.

67: ILLEGAL SYSTEM T OR S
    This special error message indicates an illegal system  track
    or sector.

70: NO CHANNEL (available)
    The requested channel is not available or all channels are in
    use. A maximum of three sequential files or one relative file
    plus one sequential file may be opened at one time,  plus the
    command channel. Do not omit the drive number in a sequential
    OPEN command, or only two sequential files can be used. Close
    all files as soon as you no longer need them.

71: DIRECTORY ERROR
    The  BAM  (Block  Availability  Map) on the diskette does not
    match  the  copy in disk memory.  To correct,  Initialize the
    diskette.

72: DISK FULL
    Either  the  diskette or its directory is full.  DISK FULL is
    sent  when  two  blocks  are  still  available,  allowing the
    current  file  to be closed.  If you get this message and the
    directory  shows any blocks left,  you have too many separate
    files  in  your  directory,  and  will  need to combine some,
    delete any that are no longer needed, or copy some to another
    diskette.

73: DOS MISMATCH (COPYRIGHT CBM DOS V10 1581)
    If  the  disk-error status is checked when the drive is first
    turned  on,  before  a  directory  or  other command has been
    given,  this message will appear.  In that use,  it is not an
    error,  but rather an easy way to see which version of DOS is
    in use. If the message appears at other times, an attempt has
    been made to write to a diskette with an incompatible format.

74: DRIVE NOT READY
    An  attempt  has  been  made  to  access the 1581 single disk
    without a formatted diskette in place. Blank diskettes cannot
    be used until they have been formatted.

75: FORMAT ERROR

76: CONTROLLER ERROR
    The  floppy  disk controller  IC (WD177x)  is not functioning
    properly.

77: SELECTED PARTITION ILLEGAL
    An attempt has been made to select a partition  that does not
    meet the criteria of a directory partition.



APPENDIX C: DOS DISKETTE FORMAT

              DIRECTORY HEADER (Track 40 Sector 0)
+--------+------------------------------------------------------+
|  BYTE  |                      DEFINITION                      |
+--------+------------------------------------------------------+
| 00-01  | Track and Sector of first DIRECTORY block            |
| 02     | Disk Version Number                                  |
| 03     | $00                                                  |
| 04-21  | Disk Name                                            |
| 22-23  | Disk ID                                              |
| 24     | $A0                                                  |
| 25     | DOS Version Number                                   |
| 26     | Disk Version Number                                  |
| 27-28  | $A0                                                  |
| 29-255 | $00                                                  |
+--------+------------------------------------------------------+


    BAM for Logical Tracks 1-40 -- BAM 1 (Track 40 Sector 1)
+--------+------------------------------------------------------+
|  BYTE  |                      DEFINITION                      |
+--------+------------------------------------------------------+
| 00-01  | Track and Sector of next BAM block                   |
| 02     | Version Number                                       |
| 03     | Compliment Version Number                            |
| 04-05  | Disk Id                                              |
| 06     | I/O-byte (bit7-verify on/off, bit6-check header CRC) |
| 07     | Auto Loader Flag*                                    |
| 08-15  | Reserved for future use                              |
| 16-255 | BAM image for logical tracks 1-40 (6 bytes/track**)  |
+--------+------------------------------------------------------+


    BAM for Logical Tracks 41-80 -- BAM 2 (Track 40 Sector 2)
+--------+------------------------------------------------------+
|  BYTE  |                      DEFINITION                      |
+--------+------------------------------------------------------+
| 00     | $00                                                  |
| 01     | $FF                                                  |
| 02     | Version Number (copy)                                |
| 03     | Compliment Version Number (copy)                     |
| 04-05  | Disk Id (copy)                                       |
| 06     | I/O-byte (copy)                                      |
| 07     | Auto Loader Flag* (copy)                             |
| 08-15  | Reserved for future use                              |
| 16-255 | BAM image for logical tracks 41-80 (6 bytes/track**) |
+--------+------------------------------------------------------+

* When  the  drive  is  reset it will hold off the serial bus and
look  for  a  file called "COPYRIGHT CBM 86" of file type USR. It
will load and execute this file. The file must have the following
structure:  The  first two bytes of the file must contain the low
and  high  load  addresses  respectively.  The  third byte is the
amount  of characters to follow.  In addition a trailing checksum
byte must be included. The load address is the execution address.
The BAM contains a flag byte which will allow auto execution with
an Initialize, Burst, Inquire, and Burst Query commands.


             ** FORMAT OF 6 BAM BYTES FOR EACH TRACK
+--------+------------------------------------------------------+
|  BYTE  |                      DEFINITION                      |
| OFFSET |                                                      |
+--------+------------------------------------------------------+
|   0    | Number of free sectors on track                      |
|   1    | MSB -- flag for sector  7, LSB -- flag for sector  0 |
|   2    | MSB -- flag for sector 15, LSB -- flag for sector  8 |
|   3    | MSB -- flag for sector 23, LSB -- flag for sector 16 |
|   4    | MSB -- flag for sector 31, LSB -- flag for sector 24 |
|   5    | MSB -- flag for sector 39, LSB -- flag for sector 32 |
+--------+------------------------------------------------------+


          DIRECTORY FILE FORMAT (Track 40, Sectors 3-39)
+---------+-----------------------------------------------------+
|  BYTE   |                     DEFINITION                      |
+---------+-----------------------------------------------------+
| 0,1     | Track and sector of next directory block.           |
| 2-31    | File entry 1*                                       |
| 34-63   | File entry 2*                                       |
| 66-95   | File entry 3*                                       |
| 98-127  | File entry 4*                                       |
| 130-159 | File entry 5*                                       |
| 162-191 | File entry 6*                                       |
| 194-223 | File entry 7*                                       |
| 226-255 | File entry 8*                                       |
+---------+-----------------------------------------------------+


         * STRUCTURE OF EACH INDIVIDUAL DIRECTORY ENTRY
+--------+----------+-------------------------------------------+
|  BYTE  | CONTENTS |                DEFINITION                 |
| OFFSET |          |                                           |
+--------+----------+-------------------------------------------+
| 0      |   128    | File  type  OR'ed  with  $80  to indicate |
|        |    +     | properly closed file.  (If OR'ed with $C0 |
|        |   type   | instead, file is locked.)                 |
|        |          | TYPES: 0 = DELeted                        |
|        |          |        1 = SEQential                      |
|        |          |        2 = PRoGram                        |
|        |          |        3 = USeR                           |
|        |          |        4 = RELative                       |
|        |          |        5 = CBM                            |
| 1-2    |          | Track and sector of first data block.     |
| 3-18   |          | File name padded with shifted spaces.     |
| 19-20  |          | Relative file only:  track  and sector of |
|        |          | the super side sector block.              |
| 21     |          | Relative file only: record length.        |
| 22-25  |          | Unused.                                   |
| 26-27  |          | Track  and  sector  of  replacement  file |
|        |          | during an @SAVE or @OPEN.                 |
| 28-29  |          | Number of blocks in file:stored as a two- |
|        |          | byte integer,in low-byte,high-byte order. |
+--------+----------+-------------------------------------------+


                      PROGRAM FILE FORMAT
+---------------------------------------------------------------+
|  BYTE                          DEFINITION                     |
+---------------------------------------------------------------+
| FIRST SECTOR                                                  |
|                                                               |
| 0,1        Track and sector of next block in program file.    |
| 2,3        Load address of the program.                       |
| 4-255      Next 252 bytes of program information stored as in |
|            computer memory (with key words tokenized).        |
+---------------------------------------------------------------+
| REMAINING FULL SECTORS                                        |
|                                                               |
| 0,1        Track and sector of next block in program file.    |
| 2-255      Next 254 bytes of program information stored as in |
|            computer memory (with key words tokenized).        |
+---------------------------------------------------------------+
| FINAL SECTOR                                                  |
|                                                               |
| 0,1        Null ($00), followed by number of valid data bytes |
|            in sector.                                         |
| 2-???      Last bytes of the program information,  stored  as |
|            in computer memory (with key words tokenized). The |
|            end  of a BASIC file is marked by three zero bytes |
|            in  a  row.  Any remaining bytes in the sector are |
|            garbage and may be ignored.                        |
+---------------------------------------------------------------+


                        SEQUENTIAL FORMAT
+---------------------------------------------------------------+
|  BYTE                          DEFINITION                     |
+---------------------------------------------------------------+
| ALL BUT NOT FINAL SECTOR                                      |
|                                                               |
| 0,1        Track and sector of next sequential data block.    |
| 2-255      254 bytes of data.                                 |
+---------------------------------------------------------------+
| FINAL SECTOR                                                  |
|                                                               |
| 0,1        Null ($00), followed by number of valid data bytes |
|            in sector.                                         |
| 2-???      Last  bytes  of  data.  Any  remaining  bytes  are |
|            garbage and may be ignored.                        |
+---------------------------------------------------------------+


                      RELATIVE FILE FORMAT
+---------------------------------------------------------------+
|  BYTE                          DEFINITION                     |
+---------------------------------------------------------------+
| DATA BLOCK                                                    |
|                                                               |
| 0,1        Track and block of next data block.                |
| 2-255      254 bytes of data.  Empty records contain $FF (all |
|            binary ones)  in  the  first  byte followed by $00 |
|            (binary  all  zeros)  to  the  end  of the record. |
|            Partially  filled  records  are  padded with nulls |
|            ($00).                                             |
+---------------------------------------------------------------+
| SIDE SECTOR BLOCK                                             |
|                                                               |
| 0,1        Track and sector of next side sector block in this |
|            group.                                             |
| 2          Side sector number (0-5).                          |
| 3          Record length.                                     |
| 4,5        Track and sector of first side sector (number 0).  |
| 6,7        Track and sector of second side sector (number 1). |
| 8,9        Track and sector of third side sector (number 2).  |
| 10,11      Track and sector of fourth side sector (number 3). |
| 12,13      Track and sector of fifth side sector (number 4).  |
| 14,15      Track and sector of sixth side sector (number 5).  |
| 16-255     Track and sector pointers to 120 data blocks.      |
+---------------------------------------------------------------+
| SUPER SIDE SECTOR BLOCK                                       |
|                                                               |
| 0,1        Track and sector of first side sector in group 0.  |
| 2          $FE                                                |
| 3,4        Track and sector of first side sector in group 0.  |
| 5,6        Track and sector of first side sector in group 1.  |
| 253-254    Track and sector of first side sector in group 125.|
+---------------------------------------------------------------+

  The  super  side  sector  has  pointers  to 126  groups of side
sectors.  Each of these groups contains 6 side sectors. Each side
sector points to 120 data blocks, containing 254 bytes each. 126x
6x120x254=23,042,880 bytes (maximum relative file size).



APPENDIX D: DISK COMMAND QUICK REFERENCE CHART

General Format: OPEN15,8,15:PRINT#15,command:CLOSE15 (BASIC 2.0)

HOUSEKEEPING COMMANDS

BASIC 2.0   NEW               "N:diskette name,id"
            COPY              "C0:new file=0:old file"
            RENAME            "R0:new name=old name"
            SCRATCH           "S0:file name"
            VALIDATE          "V0"
            INITIALIZE        "I0"

BASIC 7.0/  NEW               HEADER "diskette name",Iid,D0
3.5         COPY              COPY "old file" TO "new file"
            RENAME            RENAME "old name" TO "new name"
            SCRATCH           SCRATCH "file name"
            VALIDATE          COLLECT
            INITIALIZE        DCLEAR

BOTH        SELECT PARTITION  "/0:partition name"
            CREATE PARTITION  "/0:partition,"CHR$(starting track)
                              CHR$(starting sector)CHR$(<# of
                              blocks)CHR$(># of blocks)",C"

FILE COMMANDS

BASIC 2.0   LOAD     LOAD"file name",8
            SAVE     SAVE"file name",8
            VERIFY   VERIFY"file name",8

BASIC 7.0/  LOAD     DLOAD"file name"
3.5         SAVE     DSAVE"file name"
            VERIFY   DVERIFY"file name"  (BASIC 7.0 only)

BASIC 7.0   BLOAD    BLOAD"filename",Bbank#,Pstart address
only        BSAVE    BSAVE"filename",Bbank#,Pst.add To Pen.add
            BOOT     BOOT"filename"

            OPEN     DOPEN#file#,"filename",[Lrecord length][,W]
            CLOSE    DCLOSE#file#
            RECORD#  RECORD#file#,record number[,offset]

BOTH        OPEN     OPEN file#,8,channel#,"0:filename,file
                     type,direction"
            CLOSE    CLOSE file#
            RECORD#  "P"+CHR$(channel#)+CHR$(<record#)
                     +CHR$(>record#)+CHR$(offset)

            PRINT#   PRINT#file#,data list
            GET#     GET#file#,variable list
            INPUT#   INPUT#file#,variable list

DIRECT ACCESS COMMANDS

BLOCK-ALLOCATE  "B-A";0;track#;sector#
BLOCK-EXECUTE   "B-E";channel#;0;track#;sector#
BLOCK-FREE      "B-F";0;track#;sector#
BUFFER-POINTER  "B-P";channel#;byte
BLOCK-READ      "U1";channel#;0;track#;sector#
BLOCK-WRITE     "U2";channel#;0;track#;sector#
MEMORY-EXECUTE  "M-E"CHR$(<address)CHR$(>address)
MEMORY-READ     "M-R"CHR$(<address)CHR$(>address)CHR$(# of bytes)
MEMORY-WRITE    "M-W"CHR$(<address)CHR$(>address)CHR$(# of bytes)
                CHR$(data byte)...
USER            "Ucharacter"
UTILITY LOADER  "&0:file name"

+---------------------------------------------------------------+
| FOR  MORE  DETAILED  DESCRIPTIONS  OF THESE COMMANDS, CONSULT |
| YOUR COMPUTER'S USER'S GUIDE.                                 |
+---------------------------------------------------------------+



APPENDIX E
SPECIFICATIONS OF THE 1581 DISK DRIVE

STORAGE
  Total unformatted capacity          1 Megabyte
  Total formatted capacity            808,960 bytes
  Maximum Sequential file size        802,640 bytes
  Maximum Relative file size          ~800K
  Records per file                    65535
  Files per diskette                  296
  Cylinders per diskette              80
  Logical sectors per cylinder        40 (0-39)
  Physical sectors per cylinder       20 (1-20)
  Free blocks per disk                3160
  Logical bytes per sector            256
  Physical bytes per sector           512

INTEGRATED CIRCUIT CHIPS USED
  6502A                               Microprocessor
  8520A                               I/O
  23256                               32K bytes ROM
  4364                                8K bytes RAM
  WD177x                              Floppy Disk Controller

PHYSICAL DIMENSIONS
  Height                               63 mm
  Width                               140 mm
  Depth                               230 mm
  Weight                              1.4 kg

ELECTRICAL REQUIREMENTS
  Voltage     North America           100-120 VAC
              Europe/Australia        220-240 VAC
  Frequency   North America           60 Hz
              Europe/Australia        50 Hz
  Power used                          10 Watts

MEDIA
  Any good quality 3.5 inch double-sided diskette may be used.



APPENDIX F: SERIAL INTERFACE INFORMATION

  The   Serial   Interface  consists  of  two  6-pin  DIN  Female
Connectors  on  each  drive.  The  second  connector is for daisy
chaining   to  other  drives  and/or  peripherals.   The  voltage
interface is a serial interface at TTL levels.
  There  are  three  types  of  operation  over  a  serial bus --
Control,  Talk,  and  Listen.  The  host  is  the  controller and
initiates  all protocol on the serial bus.  The host requests the
peripheral  to  listen  or  talk (if the peripheral is capable of
talking  as disk drive).  All devices connected to the serial bus
receive data transmitted over the bus. To allow the host to route
its  data  to  an  intended  destination,  each  device has a bus
address  (known as device number).  Disk drive's device addresses
are normally 8-11.
  Data and control signals as follows:

+---------------------------------------------------------------+
| Pin No  Signal     Direction            Description           |
+---------------------------------------------------------------+
| Pin 1   SRQ         in/out   Used  by  fast  serial  bus as a |
|         (Service             bi-direction  fast  clock  line. |
|         Request)             Unused by the slow serial bus.   |
|                                                               |
| Pin 2   GND                  Logic ground.                    |
|         (Ground)                                              |
+---------------------------------------------------------------+
| Pin 3   ATN           in     The  host brings this signal low |
|         (Attention)          which    then    generates    an |
|                              interrupt  on   the   controller |
|                              board.  The  attention  sequence |
|                              is followed by a device address. |
|                              If the device does  not  respond |
|                              within a preset  time  the  host |
|                              will assume the device addressed |
|                              is not on the bus.               |
|                                                               |
| Pin 4   CLK         in/out   This  signal  is used for timing |
|         (Clock)              the data sent on slow serial bus |
|                              (software clocked).              |
|                                                               |
| Pin 5   DATA        in/out   Data   on   the  serial  bus  is |
|                              transmitted  one  bit  at a time |
|                              (software  toggled in slow mode, |
|                              hardware toggled in fast mode).  |
|                                                               |
| Pin 6   RESET                This   line   will   reset   the |
|                              peripheral upon host reset.      |
+---------------------------------------------------------------+

  The 6-pin DIN connector looks like (from outside):

                              ++ ++
                             / +-+ \
                            /5     1\
                           +  O   O  +
                           |    6    |
                           |    O    |
                           |         |
                           +  O   O  +
                            \4  O  2/
                             \  3  /
                              +---+

  In  detail,  the 1581 serial bus supports the newer FAST serial
communication as well as standard (SLOW) serial communication.
  The  important  difference  between the FAST serial bus and the
SLOW  serial  bus is the incorporation of the hardware controlled
lines for the CLOCK and DATA lines.  Fast serial communication is
transparent  to  any  peripheral connected to the serial bus that
does  not  contain  the necessary hardware or software to talk at
fast speed.
  To  remain  compatible  with the SLOW serial bus all bytes sent
under attention are sent slow.



   _____
  /  ___|___
 |  /   |__/  C o m m o d o r e
 |  \___|__\  =================
  \_____|

Commodore Business Machines, Inc.
1200 Wilson Drive - West Chester - PA 19380

Commodore Business Machines, Ltd.
3470 Pharmacy Avenue, Agincourt, Ontario, M1W 3G3

Printed in Taiwan

P/N:319928-01

41A048-001

*********

End of the Project 64 etext of the Commodore 1581 Disk Drive User's
Guide.

*********
