 Function 15: Open File      -- File I/O Functions --
 Function 16: Close File
 Function 20: Read Sequential 
 Function 21: Write Sequential
 Function 22: Make File
 Function 33: Read Random
 Function 34: Write Random
 Function 36: Set Random Record
 Function 40: Write Random Zero Fill
 Extended Error Codes
 Directory Codes
 Read/Write Codes
:

     +---------------------------------------------------------------+
     |                   FUNCTION 15 -- OPEN FILE                    |
     +--------------------------------+------------------------------+
     | Entry:  C = 15 (0Fh)           | Exit:  A = Directory code    |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Opens the file specified in the file control block (FCB).  ZSDOS can use 
the public attribute of the filename and the path to locate the file.  On 
return, if the open is successful, the user number at FCB+13 will be set to 
the user in which the file was found.  The user number is OR'd with 80h, 
which sets its high bit.

Bytes in the file control block through FCB+14 should be initialized.  To 
get ZSDOS to use the user number byte at FCB+13 set this byte to the user 
number OR'd with 80h and set the error mode to non-zero using Function 45.

If the path or public attribute was used to find the file, the seventh 
character of the filename (F7) will have its high bit set on return.
:

     +---------------------------------------------------------------+
     |                   FUNCTION 16 -- CLOSE FILE                   |
     +--------------------------------+------------------------------+
     | Entry:  C = 16 (10h)           | Exit:  A = Directory code    |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Closes the file specified in the file control block (FCB), if it exists.

Internal buffers are flushed to the disk and the directory entry of the 
file is updated, if it was written to.  It is good practice to close a 
file, even it was only open for reading.
:

     +---------------------------------------------------------------+
     |                FUNCTION 20 -- READ SEQUENTIAL                 |
     +--------------------------------+------------------------------+
     | Entry:  C = 20 (14h)           | Exit:  A = Read/Write code   |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Reads from the next record of a file opened with Function 15, transferring 
128 bytes to the current DMA buffer.

Repeated calls will read successive records from the file sequentially.
:

     +---------------------------------------------------------------+
     |                FUNCTION 21 -- WRITE SEQUENTIAL                |
     +--------------------------------+------------------------------+
     | Entry:  C = 21 (15h)           | Exit:  A = Read/Write code   |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Writes to the next record of a file opened with Function 15, transferring 
128 bytes from the current DMA buffer.

Repeated call will write to successive records of the file sequentially.  
New allocation blocks are allocated and new file extents are opened or 
created as necessary.

The archive attribute  of the first directory extent of a file will be 
reset if it is written to by this function.

Incomplete files should always be closed via Function 16 before they are 
deleted via Function 19, to prevent unused blocks for remaining allocated.
:

     +---------------------------------------------------------------+
     |                   FUNCTION 22 -- MAKE FILE                    |
     +--------------------------------+------------------------------+
     | Entry:  C = 22 (16h)           | Exit:  A = Directory code    |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Create a file with the filename specified in the file control block (FCB).  
No disk data space is allocated, but a directory entry is written and the 
file is open for writing after this call.

The program should check for a pre-existing file before calling this 
function; otherwise, a duplicate directory entry could be created.
:

     +---------------------------------------------------------------+
     |                  FUNCTION 33 -- READ RANDOM                   |
     +--------------------------------+------------------------------+
     | Entry:  C = 33 (21h)           | Exit:  A = Read/Write code   |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Reads a random record from the file in the file control block (FCB).

Before each call initialize the FCB for the record to read by placing the 
three-byte record number in FCB+33, FCB+34, and FCB+35, with the least 
significant byte in FCB+33 and the most significant byte in FCB+35.

Unlike a sequential read, the record number is not advanced after each 
read.  The random record number must be set before each call.  Since each 
random read operation automatically sets the extent and record values into 
the specified FCB, however, the file can then be sequentially read or 
written, starting from the currently accessed position.
:

     +---------------------------------------------------------------+
     |                  FUNCTION 34 -- WRITE RANDOM                  |
     +--------------------------------+------------------------------+
     | Entry:  C = 34 (22h)           | Exit:  A = Read/Write code   |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Writes a random record to the file in the file control block (FCB).

Before each call initialize the FCB for the record to write by placing the 
three-byte record number in FCB+33, FCB+34, and FCB+35, with the least 
significant byte in FCB+33 and the most significant byte in FCB+35.

Unlike a sequential write, the record number is not advanced after each 
write.  The random record number must be set before each call.  Since each 
random write operation automatically sets the extent and record values into 
the specified FCB, however, the file can then be sequentially read or 
written, starting from the currently accessed position.
:

     +---------------------------------------------------------------+
     |               FUNCTION 36 -- SET RANDOM RECORD                |
     +--------------------------------+------------------------------+
     | Entry:  C = 36 (24h)           | Exit:  A = 00h               |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Sets random record number in the file control block (FCB) to the current 
position in a file after it has been read or written sequentially.

Repeatedly calling this function while writing sequentially allows the 
building of an index of the file's records for later random access.
:

     +---------------------------------------------------------------+
     |          FUNCTION 40 -- WRITE RANDOM WITH ZERO FILL           |
     +--------------------------------+------------------------------+
     | Entry:  C = 40 (28h)           | Exit:  A = Read/Write code   |
     |        DE = Address of FCB     |                              |
     |                                |                              |
     +--------------------------------+------------------------------+

Writes a random record to the file in the file control block (FCB), like 
Function 34, but unwritten records are filled with zeros, instead of 
remaining as missing extents or "holes" filled with garbage.

Before each call initialize the FCB for the record to write by placing the 
three-byte record number in FCB+33, FCB+34, and FCB+35, with the least 
significant byte in FCB+33 and the most significant byte in FCB+35.

The record number is not advanced after each write, so the random record 
number must be set before each call.  Each random write operation 
automatically sets the extent and record values into the specified FCB, 
however, so the file can be sequentially read or written, starting from the 
currently accessed position.
:

                           EXTENDED ERROR CODES

These codes are returned by disk and file functions when Return Error mode 
is set using Function 45.  If FFh is returned in A, then H contains an 
extended error code.  These codes are not compatible with the extended 
codes returned by CP/M Plus.

                   A = FFh   extended error flag
                   H = 0     no error
                   H = 1     disk I/O error (bad sector)
                   H = 2     read-only disk
                   H = 3     write-protected file
                   H = 4     invalid drive (Select)
:

                              DIRECTORY CODES

              (Returned by Functions 15, 16, 17, 18, and 22)

                            A = 0-3   no error
                            A = FFh   error

Directory codes 0 to 3 are actually multipliers used to find the directory 
entry of the desired file in the current DMA buffer.  The buffer will 
contain a sector (128 bytes) of four 32-byte directory entries.  The return 
code points to one of the entries, which can be found by multiplying the 
code by 32 and adding the resulting offset to the buffer address:
          rrca                ; multiply return code by 32
          rrca
          rrca
          ld   l,a            ; put offset in HL
          ld   h,0
          ld   de,buffaddr    ; add offset to DMA buffer address
          add  hl,de
Now HL contains the address of the directory record for the desired file.
:

                             READ/WRITE CODES

              (Returned by Functions 20, 21, 33, 34, and 40)

       A = 0     no error

       A = 1     for read:  end of file
                 for write:  directory full

       A = 2     disk full

       A = 3     for random read or write:  close error
       A = 4     for random read:  reading empty record
       A = 5     for random write:  directory full
       A = 6     for random read or write:  random record too large
