.ec^ .na .ll60 .m11 .m22 .m48 .fo ''-%- .pn5 .pi0 .br .np .ce CHAPTER 8 - DOS PROGRAM LOGIC .sp1 This chapter will take a detailed look at the operation of the DOS program itself to aid the APPLE user in understanding it and to help him to make intelligent use of its facilities. Each subroutine and group of variables or constants will be covered separately by storage address. The enterprising programmer may wish to create a disassembly of DOS on his printer and transfer the annotations given here directly to such a listing. Addresses used will be for DOS 3.3 and for a 48K master diskette version of DOS. Slot 6 is assumed. Unless specifically indicated by a $ character, lengths are given in decimal, addresses in hexadecimal (base 16). .sp1 DISK II CONTROLLER CARD ROM - BOOT 0 .sp1 .pi0 .ul ADDRESS .np C600-C65B This routine is the first code executed when a disk is to be booted. It receives control via PR#6 or C600G or 6 control-P. Dynamically build a translate table for converting disk codes to six bit hex at location $356-$3FF. Call an RTS instruction in the monitor ROM and extract the return address from the stack to find out the address of this controller card ROM. Use this address to determine the slot number of this drive by shifting $Csxx. Save the slot number times 16 ($s0) Clear disk I/O latches, set read mode, select drive 1, turn disk drive on. Pull disk arm back over 80 tracks to recalibrate the arm to track zero. Set up parms to read sector zero on track zero to location $800. Execution falls through into a general sector read subroutine at C65C. .np C65C-C6FA This subroutine reads the sector number stored at $3D on the track indicated by $41 to the address stored at $26,$27. Look for D5/AA/96 sector address header on the disk. If D5/AA/AD is found and sector data was wanted, go to C6A6. C683 Handle a sector address block. Read three double bytes from the disk and combine them to obtain the volume, track, and sector number of the sector being read from the disk at this time. Store the track at $40. Compare the sector found to the sector wanted and the track found to the track wanted. If no match, go back to C65C. Otherwise, if sector is correct, go to C65D to find the sector data itself. C6A6 Handle sector data block. Read the 85 bytes of secondary data to $300-$355. Read 256 bytes of primary data to the address stored at $26,$27. Verify that the data checksum is valid. If not, start over at C65C. "Nibbilize" the primary and secondary data together into the primary data buffer ($26,$27). Increment $27 (address page of read data) and $3D (sector number to be read) and check against $800 to see if additional sectors need to be read. If so, reload slot*16 and go back to C65C to read next sector. (This feature is not used when loading DOS but is used when loading from a BASICS diskette.) Otherwise, go to $801 to begin executing the second stage of the bootstrap. .sp1 FIRST RAM BOOTSTRAP LOADER - BOOT 1 .sp1 .ul ADDRESS .np 0801-084C This routine loads the second RAM loader, Boot 2, including RWTS, into memory and jumps to it. If this is not the first entry to Boot 1, go to $81F. Get slot*16 and shift down to slot number. Create the address of the ROM sector read subroutine (C65C in our case) and store it at $3E,$3F. Pick up the first memory page in which to read Boot 2 from location $8FE, add the length of Boot 2 in sectors from $8FF, and set that value as the first address to which to read (read last page first). 081F Get sector to read, if zero, go to $839. Translate theoretical sector number into physical sector number by indexing into skewing table at $84D. Decrement theoretical sector number (8FF) for next iteration through. Set up parameters for ROM subroutine (C65C) and jump to it. It will return to $801 when the sector has been read. 0839 Adjust page number at 8FE to locate entry point of Boot 2. Perform a PR#0 and IN#0 by calling the monitor. Initialize the monitor (TEXT mode, standard window, etc.) Get slot*16 again and go to Boot 2 ($3700 for a master disk, $B700 in its final relocated location). .sp1 DOS 3.3 MAIN ROUTINES .sp1 .ul ADDRESS .np 9D00-9D0F Relocatable address constants 9D00 Address of first DOS buffer at its file name field. 9D02 Address of the DOS keyboard intercept routine. 9D04 Address of the DOS video intercept routine. 9D06 Address of the primary file name buffer. 9D08 Address of the secondary (RENAME) file name buffer. 9D0A Address of the range length parameter used for LOAD. 9D0C Address of the DOS load address ($9D00). 9D0E Address of the file manager parameter list. .np 9D10-9D1C DOS video (CSWL) intercept's state handler address table. States are used to drive the handling of DOS commands as they appear as output of PRINT statements and this table contains the address of the routine which handles each state from state 0 to state 6. .np 9D1E-9D55 Command handler entry point table. This table contains the address of a command handler subroutine for each DOS command in the following standard order: INIT A54F LOAD A413 SAVE A397 RUN A4D1 CHAIN A4F0 DELETE A263 LOCK A271 UNLOCK A275 CLOSE A2EA READ A51B EXEC A5C6 WRITE A510 POSITION A5DD OPEN A2A3 APPEND A298 RENAME A281 CATALOG A56E MON A233 NOMON A23D PR# A229 IN# A22E MAXFILES A251 FP A57A INT A59E BSAVE A331 BLOAD A35D BRUN A38E VERIFY A27D .np 9D56-9D61 Active BASIC entry point vector table. The addresses stored here are maintained by DOS such that they apply to the current version of BASIC running. 9D56 Address of CHAIN entry point to BASIC. 9D58 Address of RUN. 9D5A Address of error handler. 9D5C Address of BASIC coldstart. 9D5E Address of BASIC warmstart. 9D60 Address of BASIC relocate (APPLESOFT only). .np 9D62-9D6B Image of the entry point vector for INTEGER BASIC. This image is copied to 9D56 if INTEGER BASIC is made active. .np 9D6C-9D77 Image of the entry point vector for the ROM version of APPLESOFT. .np 9D78-9D83 Image of the entry point vector for the RAM version of APPLESOFT. .np 9D84-9DBE DOS coldstart entry routine. Get the slot and drive numbers and store as default values for command keywords. Copy APPLESOFT ROM or INTEGER BASIC entry point vector into current BASIC entry point vector. Remember which BASIC is active. Go to 9DD1. .np 9DBF-9DE9 DOS warmstart entry routine. Get the remembered BASIC type and set the ROM card as necessary (calls A5B2). 9DD1 Remember whether entry is coldstart or warmstart Call A851 to replace DOS keyboard and video intercepts. Set NOMON C,I,O. Set video intercept handler state to 0. Coldstart or warmstart the current BASIC (exit DOS). (DOS will next gain control when BASIC prints its input prompt character) .np 9DEA-9E50 First entry processing for DOS. This routine is called by the keyboard intercept handler when the first keyboard input request is made by BASIC after a DOS coldstart. If RAM APPLESOFT is active, copy its entry point vector to the active BASIC entry point vector and blank out the primary file name buffer so that no HELLO file will be run. Set MAXFILES to 3 by default. Call A7D4 to build the DOS file buffers. If an EXEC was active, close the EXEC file Set the video intercept state to 0 and indicate warmstart status by calling A75B. If the last command executed was not INIT (this DOS was not just booted), go to 9E45. Otherwise, copy an image of the DOS jump vector to $3D0-$3FF. Point $3F2,$3F3 to DOS warmstart routine. Set the AUTOSTART ROM power-up byte since the RESET handler address was changed. Set the command index for RUN (to run the HELLO file) and go to A180 to execute it. 9E45 See if there is a pending command. If so, go to A180 to execute it. Otherwise, return to caller. .np 9E51-9E7F An image of the DOS 3-page jump vector which the above routine copies to $3D0-$3FF. See Chapter 5 for a description of its contents. .np 9E81-9EB9 DOS keyboard intercept routine. Call 9ED1 to save the registers at entry to DOS. If not coldstarting or reading a disk file, go to 9E9E. Get value in A register at entry and echo it on the screen (erases flashing cursor). If in read state (reading a file) go to A626 to get next byte from disk file. Otherwise, call 9DEA to do first entry processing. Put cursor on screen in next position. If EXECing, call A682 to get the next byte from the EXEC file. Set the video intercept state to 3 (input echo). Call 9FBA to restore the registers at entry to DOS. Call the true keyboard input routine. Save the input character so that it will be restored with the registers in the A register. Do the same with the new X register value. Exit DOS via 9FB3. .np 9EBA-9EBC A jump to the true KSWL handler routine. .np 9EBD-9ED0 DOS video intercept routine. Call 9ED1 to save the registers at entry to DOS. Get the video intercept state and, using it as an index into the state handler table (9D11), go to the proper handler routine, passing it the character being printed. .np 9ED1-9EEA Common intercept save registers routine. Save the A, X, Y, and S registers at AA59-AA5C. While in DOS, restore the true I/O handlers (KSWL and CSWL) to $36-$39. Return to caller. .np 9EEB-9F11 State 0 output handler. --start of line-- If a RUN command was interrupted (by loading RAM APPLESOFT) go to 9F78 to complete it. If read flag is on (file being read) and output is a "?" character (BASIC INPUT), go to state 6 to skip it. If read flag is on and output is prompt character ($33) go to state 2 to ignore the line. Set state to 2 (ignore non-DOS command) just in case. If output character is not a control-D, go to state 2. Otherwise, set state to 1 (collect possible DOS command), set line index to zero, and fall through to state 1. .np 9F12-9F22 State 1 output handler. --collect DOS command-- Using line index, store character in input buffer at $200. Increment line index. If character is not a carriage return, exit DOS via 9F95 (echo character on screen if MON I). Otherwise, go to command scanner at 9FCD. .np 9F23-9F2E State 2 output handler. --non-DOS command ignore-- If the character is not a carriage return, exit DOS via 9FA4 (echo character on screen). Otherwise, set state back to 0 and exit DOS via 9FA4. .np 9F2F-9F51 State 3 output handler. --INPUT statement handler-- Set state to 0 in case INPUT ends. If character is not a carriage return, echo it on screen as long as EXEC is not in effect with NOMON I but exit DOS in any case. (KSWL will set state=3) Otherwise, call A65E to see if BASIC is executing a program or is in immediate mode. If EXEC is running or if BASIC is in immediate mode, go to state 1 to collect the possible DOS command. Otherwise, exit DOS, echoing the character as appropriate. .np 9F52-9F60 State 4 output handler. --WRITE data to a file-- If the character is a carriage return, set state to 5 (start of write data line). Call A60E to write the byte to the disk file. Exit DOS with echo on screen if MON O. .np 9F61-9F70 State 5 output handler. --Start of WRITE data line-- If the character is a control-D, go to state 0 to immediately exit write mode. If the character is a line feed, write it and exit, staying in state 5. Otherwise, set the state to 4 and go to state 4. .np 9F71-9F77 State 6 output handler. --Skip prompt character-- Set state to 0. Exit DOS via 9F9D (echo if MON I). .np 9F78-9F82 Finish RUN command, interrupted by APPLESOFT RAM LOAD Reset the "RUN interrupted" flag. Call A851 to replace the DOS CSWL/KSWL intercepts. Go to A4DC to complete the RUN command. .np 9F83-9F94 DOS command scanner exit to BASIC routine. If first character of command line is control-D, go to echo exit (9F95). Otherwise, set things up so BASIC won't see the DOS command by passing a zero length line (only a carriage return). Fall through to echo exit. .np 9F95-9FB0 Echo character on screen (conditionally) and exit DOS 9F95 Echo only if MON C set, otherwise, go to 9FB3. 9F99 Echo only if MON O set, otherwise, go to 9FB3. 9F9D Echo only if MON I set, otherwise, go to 9FB3. 9FA4 Always echo character. Call 9FBA to restore registers at entry to DOS. Call 9FC5 to echo character on screen. Save contents of the registers after echoing. Fall through to DOS exit routine. .np 9FB3-9FC4 DOS exit routine and register restore. Call A851 to put back DOS KSWL/CSWL intercepts. Restore S (stack) register from entry to DOS. 9FBA DOS register restore subroutine. Restore registers from first entry to DOS and return to caller. .np 9FC5-9FC7 A jump to the true CSWL routine. .np 9FC8-9FCC Skip a line on the screen. Load a carriage return into the A register and call 9FC5 to print it. .np 9FCD-A179 DOS command parse routine. .br .nx ch8.1