CALLING THE DOS FILE MANAGER 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. 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 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 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 Given below are several pieces of code which are used when working with DOS: .sp1 .ne5 LOCATE A FREE DOS BUFFER 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? 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? 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? 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 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