mirror of
https://github.com/iKarith/beneath-apple-dos.git
synced 2024-12-22 22:30:22 +00:00
522 lines
18 KiB
Plaintext
522 lines
18 KiB
Plaintext
|
CALLING THE DOS FILE MANAGER
|
||
|
.pp
|
||
|
The DOS file manager exists in every
|
||
|
version of DOS as a collection of
|
||
|
subroutines occupying approximately
|
||
|
the central third of the DOS program.
|
||
|
The interface to these routines is
|
||
|
generalized in such a way that they
|
||
|
may be called by a program running
|
||
|
outside of DOS. The definition of
|
||
|
this interface has
|
||
|
never been published by APPLE (or
|
||
|
anyone else, for that manner) but
|
||
|
since the calls can be made through
|
||
|
fixed vectors, and, the format of the
|
||
|
parameter lists passed have not
|
||
|
changed in all the versions of DOS,
|
||
|
these routines may be relied upon as
|
||
|
"safe". Indeed, the new FID utility
|
||
|
program
|
||
|
uses these routines to process files
|
||
|
on the diskette.
|
||
|
.pp
|
||
|
There are
|
||
|
two subroutines which must be called
|
||
|
in order to access the file manager.
|
||
|
.sp1
|
||
|
JSR $3DC - When this subroutine is
|
||
|
called, the Y and A registers are
|
||
|
loaded with the address of the file
|
||
|
manager parameter list. The low order
|
||
|
part of the address is in Y and the
|
||
|
high order part in A. This subroutine
|
||
|
must be called at least once to
|
||
|
locate this parameter list and the
|
||
|
results may be stored in two zero page
|
||
|
locations to allow the programmer to
|
||
|
set input values in the parameter
|
||
|
list and to locate output values
|
||
|
there after file manager calls.
|
||
|
.sp1
|
||
|
JSR $3D6 - This is the main entry to
|
||
|
the file manager. Prior to making
|
||
|
this call the parameter list, located
|
||
|
using the call described
|
||
|
above, must be completed
|
||
|
appropriately, depending upon the
|
||
|
type of call, and the X register must
|
||
|
be set to either zero or non-zero as
|
||
|
follows:
|
||
|
.sp1
|
||
|
X = 0 - If file is not found, allocate it
|
||
|
X # 0 - If file is not found, do not allocate one
|
||
|
.sp1
|
||
|
Normally,
|
||
|
X should be zero on an OPEN call for a
|
||
|
new file and non-zero for all other
|
||
|
call types.
|
||
|
.bp
|
||
|
Three buffers must be provided to the
|
||
|
file manager by the programmer,
|
||
|
allocated by him in his memory. These
|
||
|
buffers, together, occupy 557 bytes
|
||
|
of RAM, and must be passed to the
|
||
|
file manager each time their
|
||
|
associated file is used. A separate
|
||
|
set of these buffers must be
|
||
|
maintained for each open file.
|
||
|
DOS maintains buffers for this
|
||
|
purpose, as described in earlier
|
||
|
chapters, in high RAM. These buffers
|
||
|
may be "borrowed" from DOS if care is
|
||
|
taken to let DOS know about it. A
|
||
|
method for doing this will be
|
||
|
outlined later.
|
||
|
.sp1
|
||
|
A chart giving the required inputs
|
||
|
for each call type to the file
|
||
|
manager is given in Figure 6.2.
|
||
|
The general format of the file
|
||
|
manager parameter list is as follows:
|
||
|
.bp
|
||
|
FILE MANAGER PARAMETER LIST - GENERAL FORMAT
|
||
|
.NP
|
||
|
BYTE DESCRIPTION
|
||
|
00 Call type: 01=OPEN 05=DELETE 09=RENAME
|
||
|
02=CLOSE 06=CATALOG 0A=POSITION
|
||
|
03=READ 07=LOCK 0B=INIT
|
||
|
04=WRITE 08=UNLOCK 0C=VERIFY
|
||
|
01 Sub-call type for READ or WRITE:
|
||
|
00=No operation (ignore call entirely)
|
||
|
01=READ or WRITE one byte
|
||
|
02=READ or WRITE a range of bytes
|
||
|
03=POSITION then READ or WRITE one byte
|
||
|
04=POSITION then READ/WRITE a range
|
||
|
02-09 Parameters specific to the call type used. See
|
||
|
FILE MANAGER PARAMETER LIST BY CALL TYPE below.
|
||
|
0A Return code (note: not all return codes can occur
|
||
|
for any call type). The processor CARRY
|
||
|
flag is set upon return from the file
|
||
|
manager if there is a non-zero return code:
|
||
|
00=No errors
|
||
|
01=Not used ("LANGUAGE NOT AVAILABLE")
|
||
|
02=Bad call type
|
||
|
03=Bad sub-call type (greater than four)
|
||
|
04=WRITE PROTECTED
|
||
|
05=END OF DATA
|
||
|
06=FILE NOT FOUND (was allocated if X=0)
|
||
|
07=VOLUME MISMATCH
|
||
|
08=DISK I/O ERROR
|
||
|
09=DISK FULL
|
||
|
0A=FILE LOCKED
|
||
|
0B Not used
|
||
|
0C-0D Address of a 45 byte buffer which will be used by the
|
||
|
file manager to save its status between calls. This
|
||
|
area is called the file manager workarea and need not
|
||
|
be initialized by the caller but the space must be
|
||
|
provided and this two byte address field initialized.
|
||
|
(addresses are in low/high order format)
|
||
|
0E-0F Address of a 256 byte buffer which will be used by the
|
||
|
file manager to maintain the current Track/Sector List
|
||
|
sector for the open file. Buffer itself need not be
|
||
|
initialized by the caller.
|
||
|
10-11 Address of a 256 byte buffer which will be used by the
|
||
|
file manager to maintain the data sector buffer.
|
||
|
Buffer need not be initialized by the caller.
|
||
|
.SP1
|
||
|
*** INSERT FIGURE 6.2 ***
|
||
|
.bp
|
||
|
FILE MANAGER PARAMETER LIST BY CALL TYPE
|
||
|
.NP
|
||
|
OPEN Locates or creates a file. A call to POSITION should
|
||
|
follow every OPEN.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 01
|
||
|
02/03 - Fixed record length or 0000 if variable
|
||
|
04 - Volume number or 00 for any volume
|
||
|
05 - Drive number to be used (01 or 02)
|
||
|
06 - Slot number to be used (01-07)
|
||
|
07 - File type (used only for new files)
|
||
|
$00 = TEXT
|
||
|
$01 = INTEGER BASIC
|
||
|
$02 = APPLESOFT BASIC
|
||
|
$04 = BINARY
|
||
|
$08 = RELOCATABLE
|
||
|
$10 = S TYPE FILE
|
||
|
$20 = A TYPE FILE
|
||
|
$40 = B TYPE FILE
|
||
|
08/09 - Address of file name (30 characters)
|
||
|
(Low/high format)
|
||
|
0C/0D - Address of file manager workarea buffer
|
||
|
0E/0F - Address of T/S List sector buffer
|
||
|
10/11 - Address of data sector buffer
|
||
|
.sp1
|
||
|
Output: Byte 07 - File type of file which was OPENed
|
||
|
0A - Return code (see previous definitions)
|
||
|
.sp2
|
||
|
.ne5
|
||
|
CLOSE Write out final sectors, update the Catalog.
|
||
|
A CLOSE call is required eventually for every OPEN.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 02
|
||
|
0C/0D - Address of file manager workarea buffer
|
||
|
0E/0F - Address of T/S List sector buffer
|
||
|
10/11 - Address of data sector buffer
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.bp
|
||
|
READ Read one or a range of bytes from the file to memory.
|
||
|
WRITE Write one or a range of bytes from memory to the file.
|
||
|
|
||
|
Input: Byte 00 - 03 (READ) 04 (WRITE)
|
||
|
01 - Subcode:
|
||
|
00 = No operation
|
||
|
01 = READ or WRITE one byte only
|
||
|
02 = READ or WRITE a range of bytes
|
||
|
03 = POSITION then READ/WRITE one byte
|
||
|
04 = POSITION then READ/WRITE range
|
||
|
02/03 - (Subcodes 03 or 04) Record number
|
||
|
04/05 - (Subcodes 03 or 04) Byte offset
|
||
|
06/07 - (Subcodes 02 or 04) Number of bytes in
|
||
|
range to be read or written. (Note: for
|
||
|
WRITE, this length must be one less
|
||
|
than the actual length to be written)
|
||
|
08/09 - (Subcodes 02 or 04) Address of range of
|
||
|
bytes to be written or address of
|
||
|
buffer to which bytes are to be read.
|
||
|
08 - (WRITE, Subcodes 01 or 03) Single byte
|
||
|
to be written.
|
||
|
0C/0D - Address of file manager workarea buffer
|
||
|
0E/0F - Address of T/S List sector buffer
|
||
|
10/11 - Address of data sector buffer
|
||
|
.sp1
|
||
|
Output: Byte 02/03 - Record number of current file position
|
||
|
04/05 - Byte offset of current position in file
|
||
|
08 - (READ, Subcodes 01 or 03) Byte read
|
||
|
0A - Return code
|
||
|
.sp2
|
||
|
.ne5
|
||
|
DELETE Locate and delete a file, freeing its sectors.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 05
|
||
|
(remainder are the same as with OPEN call type)
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.bp
|
||
|
CATALOG Produce a catalog listing on the output device.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 06
|
||
|
05 - Drive
|
||
|
06 - Slot
|
||
|
0C/0D - Address of file manager workarea buffer
|
||
|
0E/0F - Address of T/S List sector buffer
|
||
|
10/11 - Address of data sector buffer
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.sp2
|
||
|
.ne5
|
||
|
LOCK Lock a file.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 07
|
||
|
(remainder are the same as with OPEN call type)
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.sp2
|
||
|
.ne5
|
||
|
UNLOCK Unlock a file.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 08
|
||
|
(remainder are the same as with OPEN call type)
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.sp2
|
||
|
.ne5
|
||
|
RENAME Rename a file.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 09
|
||
|
02/03 - Address of new file name (30 bytes)
|
||
|
(remainder are the same as with OPEN call type)
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.bp
|
||
|
POSITION Calculate the location of a record and/or byte
|
||
|
offset in the file. Position such that next READ or
|
||
|
WRITE will be at that location in the file. A call
|
||
|
to POSITION (either explicitly or implictly using
|
||
|
subcodes of READ or WRITE) is required prior to the
|
||
|
first READ or WRITE. Bytes 02 through 05 should be
|
||
|
set to zeros for a normal position to the beginning
|
||
|
of the file.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 0A
|
||
|
02/03 - Relative record number for files with a
|
||
|
fixed length record size or zero. First
|
||
|
record of file is record 0000.
|
||
|
04/05 - Relative byte offset into record or of
|
||
|
entire file if record number is zero.
|
||
|
0C/0D - Address of file manager workarea buffer.
|
||
|
0E/0F - Address of T/S List sector buffer.
|
||
|
10/11 - Address of data sector buffer.
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.sp2
|
||
|
.ne5
|
||
|
INIT Initialize a slave diskette. This function formats a
|
||
|
diskette and writes a copy of DOS onto tracks 0-2.
|
||
|
A VTOC and Catalog are also created. A HELLO program
|
||
|
is not stored, however.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 0B
|
||
|
01 - First page of DOS image to be copied to
|
||
|
the diskette. Normally $9D for a 48K
|
||
|
machine.
|
||
|
04 - Volume number of new diskette.
|
||
|
05 - Drive number (01 or 02)
|
||
|
06 - Slot number (01-07)
|
||
|
0C/0D - Address of file manager workarea buffer.
|
||
|
0E/0F - Address of T/S List sector buffer.
|
||
|
10/11 - Address of data sector buffer.
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.sp2
|
||
|
VERIFY Verify that there are no bad sectors in a file by
|
||
|
reading every sector.
|
||
|
.sp1
|
||
|
Input: Byte 00 - 0C
|
||
|
(remainder are the same as the OPEN call type)
|
||
|
.sp1
|
||
|
Output: Byte 0A - Return code
|
||
|
.bp
|
||
|
DOS BUFFERS
|
||
|
.pp
|
||
|
Usually it is desirable to use one of DOS's buffers when
|
||
|
calling the file manager to save memory. DOS buffers consist of
|
||
|
each of the three buffers used by the file manager (file
|
||
|
manager workarea, T/S List sector, and data sector) as well as
|
||
|
a 30 byte file name buffer and some link pointers. All together
|
||
|
a DOS buffer occupies 595 bytes of memory. The address of the
|
||
|
first DOS buffer is stored in the first two bytes of DOS ($9D00
|
||
|
on a 48K APPLE II). The address of the next buffer is stored in
|
||
|
the first and so on in a chain of linked elements. The link
|
||
|
address to the next buffer in the last buffer is zeros. If the
|
||
|
buffer is not being used by DOS, the first byte of the file
|
||
|
name field is a hex 00. Otherwise, it contains the first
|
||
|
character of the name of the open file. The assembly language
|
||
|
programmer should follow these conventions to avoid having DOS
|
||
|
reuse the buffer while he is using it. This means that the
|
||
|
name of the file should be stored in the buffer to reserve it
|
||
|
for exclusive use (or at least a non-zero byte stored on the
|
||
|
first character) and later, when the user is through with the
|
||
|
buffer, a 00 should be stored on the file name to return it
|
||
|
to DOS's use. If the later is not done, DOS will eventually
|
||
|
run out of available buffers and will refuse even to do a
|
||
|
CATALOG command. A diagram of the DOS
|
||
|
buffers for MAXFILES 3 is given in
|
||
|
Figure 6.3 and
|
||
|
the format of a DOS buffer is given below.
|
||
|
.SP1
|
||
|
*** INSERT FIGURE 6.3 ***
|
||
|
.sp1
|
||
|
.ne10
|
||
|
DOS BUFFER FORMAT
|
||
|
.NP
|
||
|
BYTE DESCRIPTION
|
||
|
000/0FF Data sector buffer (256 bytes in length)
|
||
|
100/1FF T/S List sector buffer (256 bytes in length)
|
||
|
200/22C File manager workarea buffer (45 bytes in length)
|
||
|
22D/24A File name buffer (30 bytes in length)
|
||
|
First byte indicates whether this DOS buffer is
|
||
|
being used. If hex 00, buffer is free for use.
|
||
|
24B/24C Address (Lo/High) of file manager workarea buffer
|
||
|
24D/24E Address of T/S List sector buffer
|
||
|
24F/250 Address of data sector buffer
|
||
|
251/252 Address of the file name field of the next buffer on
|
||
|
the chain of buffers. If this is the last buffer on
|
||
|
the chain then this field contains zeros.
|
||
|
.bp
|
||
|
THE FILE MANAGER WORKAREA
|
||
|
.pp
|
||
|
The file manager workarea contains
|
||
|
the variables which, taken together,
|
||
|
constitute all of the information the
|
||
|
file manager needs to deal with an
|
||
|
open file. Each time the file manager
|
||
|
finishes processing a call, it copies
|
||
|
all of its important variables into
|
||
|
the file manager workarea buffer
|
||
|
provided by the caller. Each
|
||
|
subsequent time the file manager is
|
||
|
called, the first thing it does is to
|
||
|
copy the contents of the file manager
|
||
|
workarea buffer back into its
|
||
|
variables so that it may resume
|
||
|
processing for the file where it left
|
||
|
off on the previous call.
|
||
|
Ordinarily, the programmer will have
|
||
|
no need to worry about the contents
|
||
|
of this workarea, since most of the
|
||
|
useful information is present in the
|
||
|
parameter list anyway. Occasionally,
|
||
|
it is handy to know more about the
|
||
|
open file. For these cases, the
|
||
|
format of the file manager workarea
|
||
|
is given below:
|
||
|
.sp1
|
||
|
FILE MANAGER WORKAREA FORMAT
|
||
|
.np
|
||
|
BYTE DESCRIPTION
|
||
|
00/01 Track/Sector of first T/S List for file
|
||
|
02/03 Track/Sector of current T/S List for file
|
||
|
04 Flags:
|
||
|
80=T/S List buffer changed and needs writing
|
||
|
40=Data buffer has been changed and needs writing
|
||
|
02=Volume freespace map changed and needs writing
|
||
|
05/06 Track/Sector of current data sector
|
||
|
07 Sector offset into catalog to entry for this file
|
||
|
08 Byte offset into catalog sector to entry for file
|
||
|
09/0A Maximum data sectors represented by one T/S List
|
||
|
0B/0C Offset of first sector in current T/S List
|
||
|
0D/0E Offset of last sector in current T/S List
|
||
|
0F/10 Relative sector number last read
|
||
|
11/12 Sector size in bytes (256)
|
||
|
13/14 Current position in sectors (relative)
|
||
|
15 Current byte offset in this sector
|
||
|
16 Not used
|
||
|
17/18 Fixed record length
|
||
|
19/1A Current record number
|
||
|
1B/1C Byte offset into current record
|
||
|
1D/1E Length of file in sectors
|
||
|
1F Next sector to allocate on this track
|
||
|
20 Current track being allocated
|
||
|
21/24 Bit map of available sectors on this track (rotated)
|
||
|
25 File type (80=locked) 0,1,2,4=T,I,A,B
|
||
|
26 Slot number times 16 (example: $60=slot 6)
|
||
|
27 Drive number (01 or 02)
|
||
|
28 Volume number (complemented)
|
||
|
29 Track
|
||
|
2A/2C Not used
|
||
|
.bp
|
||
|
COMMON ALGORITHMS
|
||
|
.PP
|
||
|
Given below are several pieces of code
|
||
|
which are used when working with DOS:
|
||
|
.SP1
|
||
|
.ne5
|
||
|
LOCATE A FREE DOS BUFFER
|
||
|
.PP
|
||
|
The following subroutine may be used
|
||
|
to locate an unallocated DOS buffer
|
||
|
for use with the DOS file manager.
|
||
|
.SP1
|
||
|
.NP
|
||
|
FBUFF LDA $3D2 LOCATE DOS LOAD POINT
|
||
|
STA $1
|
||
|
LDY #0
|
||
|
STY $0
|
||
|
*
|
||
|
GBUF0 LDA ($0),Y LOCATE NEXT DOS BUFFER
|
||
|
PHA
|
||
|
INY
|
||
|
LDA ($0),Y
|
||
|
STA $1
|
||
|
PLA
|
||
|
STA $0
|
||
|
BNE GBUF GOT ONE
|
||
|
LDA $1
|
||
|
BEQ NBUF NO BUFFERS FREE
|
||
|
*
|
||
|
GBUF LDY #0 GET FILENAME
|
||
|
LDA ($0),Y
|
||
|
BEQ GOTBUF ITS FREE
|
||
|
LDY #36 ITS NOT FREE
|
||
|
BNE GBUF0 GO GET NEXT BUFFER
|
||
|
*
|
||
|
GOTBUF CLC INDICATE-GOT A FREE BUFFER
|
||
|
RTS RETURN TO CALLER
|
||
|
NBUF SEC INDICATE-NO FREE BUFFERS
|
||
|
RTS RETURN TO CALLER
|
||
|
.bp
|
||
|
IS DOS IN THE MACHINE?
|
||
|
.PP
|
||
|
The following series of instructions
|
||
|
should be used prior to attempting to
|
||
|
call RWTS or the file manager to
|
||
|
insure that DOS is present on this
|
||
|
machine.
|
||
|
.sp1
|
||
|
.NP
|
||
|
LDA $3D0 GET VECTOR JMP
|
||
|
CMP #$4C IS IT A JUMP?
|
||
|
BNE NODOS NO, DOS NOT LOADED
|
||
|
.SP2
|
||
|
.ne5
|
||
|
WHICH VERSION OF DOS IS ACTIVE?
|
||
|
.pp
|
||
|
In case the program has version dependent code, a check of
|
||
|
the DOS version may be required:
|
||
|
.sp1
|
||
|
.np
|
||
|
CLC
|
||
|
LDA #0 ADD $16BE TO DOS LOAD POINT
|
||
|
ADC #$BE
|
||
|
STA $0
|
||
|
LDA $3D2
|
||
|
ADC #$16
|
||
|
STA $1
|
||
|
LDY #0
|
||
|
LDA ($0),Y GET DOS VERSION NUMBER (2 OR 3)
|
||
|
.sp2
|
||
|
.ne5
|
||
|
WHICH BASIC IS SELECTED?
|
||
|
.PP
|
||
|
Some programs depend upon either the
|
||
|
INTEGER BASIC ROM or the APPLESOFT
|
||
|
ROM. To find out which is active and
|
||
|
select the one desired, the following
|
||
|
subroutine can be called. First the A
|
||
|
register is loaded with a code to
|
||
|
indicate which BASIC is desired. $20
|
||
|
is used for INTEGER BASIC and $4C is
|
||
|
used for APPLESOFT. To set up for
|
||
|
APPLESOFT, for example:
|
||
|
.sp1
|
||
|
.NP
|
||
|
LDA #$4C CODE FOR APPLESOFT
|
||
|
JSR SETBSC CALL SUBROUTINE
|
||
|
BNE ERROR LANGUAGE NOT AVAILABLE
|
||
|
.
|
||
|
.
|
||
|
.
|
||
|
SETBSC CMP $E000 CORRECT BASIC ALREADY THERE?
|
||
|
BEQ RTS YES
|
||
|
STA $C080 NO, SELECT ROM CARD
|
||
|
CMP $E000 NOW DO WE HAVE IT?
|
||
|
BEQ RTS YES
|
||
|
STA $C\x3f\x4f\x47\x57\x57\x57\x3b\x3b\x5b\x57\x23\x27Y ROM CARD OUT
|
||
|
\x8cL\x8cL\x8cL\x88/\x19g_\x20_\x20_[\x8b\x8b\x8b\x9b\x9b\x9b\xffwo\x9bs
|
||
|
\x2c\x40\x42\x5b\x33\x03\x61\x9fTS RTS IN ANY CASE, EXIT TO CALLER
|
||
|
.bp
|
||
|
SEE IF A BASIC PROGRAM IS IN EXECUTION
|
||
|
.PP
|
||
|
To determine if there is a BASIC program running or
|
||
|
if BASIC is in immediate command mode, use the following
|
||
|
statements:
|
||
|
.np
|
||
|
.sp1
|
||
|
..IF INTEGER BASIC IS ACTIVE...
|
||
|
LDA $D9
|
||
|
BMI EXEC PROGRAM EXECUTING
|
||
|
BPL NOEXEC PROGRAM NOT EXECUTING
|
||
|
.sp1
|
||
|
..IF APPLESOFT BASIC IS ACTIVE...
|
||
|
LDX $76 GET LINE NUMBER
|
||
|
INX
|
||
|
BEQ NOEXEC PROGRAM NOT EXECUTING
|
||
|
LDX $33 GET PROMPT CHARACTER
|
||
|
CPX #$DD PROMPT IS A "]"?
|
||
|
BEQ NOEXEC YES, NOT EXECUTING
|
||
|
BNE EXEC ELSE, PROGRAM IS EXECUTING
|
||
|
.br
|
||
|
.nx ch7
|
||
|
\x00
|