****************************************************************** * * * READ Command Handler * * * *----------------------------------------------------------------* * * * The READ command prepares DOS to retrieve data from a * * file in response to subsequent INPUT or GET statements. The * * command can only be used in the deferred mode. A filename * * must be issued with the command or else DOS interprets the * * "READ" as an Applesoft statement which is used to assign * * values to variables via DATA statements. * * R(ecord number) and B(yte offset) parameters are optional.* * If an R-parameter is given, the file is treated as a random * * access file. The absence of a an R-parameter defines a * * sequential text file. Byte parameters can be used with either * * type of file. When used with random access files, the B- * * parameter defines the byte offset into a specific record. When* * used with sequential files, it supposedly defines an offset * * from the start of the file. However, because the R-value can * * sometimes be defaulted to an unexpected value, you should * * always specify a record value of zero if you use a B-parameter * * while reading a sequential file. * * * * Execution pattern: * * The CMDREAD routine ($A510) first calls the common read/ * * write routine (COMRDWR, $A526) to locate a DOS buffer whose * * name field contains the same name as the file wanted. If the * * named file can't be located, CMDOPEN ($A2A3) is used to open * * the file. If the file does not already exist on the disk, a * * file-not-found message is generated. Once a file is opened, a * * check is made to insure that the type code of the wanted file * * matches that of the file just opened. If the codes don't * * match, the file is closed and the command is exited via a * * file-type-mismatch error. * * Therefore, contrary to the information contained in THE * * DOS MANUAL, it is NOT necessary to OPEN a file before READing * * it. If the file is not already open, the READ command opens * * it for you. However, the READ command does not accept an L- * * parameter. Therefore, if you wish to use a record length * * greater than the default value of one, you must either use * * the OPEN command or, using assembly language, bypass the * * command parsing interpreter and set the input and parsed * * table accordingly. * * The COMRDWR routine eventually checks bits one and two of * * CUMLOPTN ($AA65) to see if R- or B-parameters were issued with * * the command. If either parameter was given, the file manager * * (FILEMGR, $AB06) is called to do the position function * * FNPOSN, $AD12). FNPOSN uses the L-, R- and B-parameters to * * calculate the desired position of the three-byte file pointer * * (FILPTSEC, $B5E4-$B5E5 and FILBYT, $B5E6) via the following * * formula: * * pointer position wanted = (record number * record length) * * + byte offset into record. * * Once the file pointer is adjusted, or if no positioning is * * required, execution branches back into the CMDREAD routine at * * $A51E. The output condition flag (OPUTCOND, $AA52) is then * * set to condition 1 and the READ command is exited after the * * I/O hooks are reset to point to DOS. * * Although the READ comand per se does not actually read * * anything from the file, it leaves the computer in the READ * * mode so that subsequent INPUT and GET statements take their * * input from the file. (Note, a PRINT statement containing * * DOS's control character (usually ctrl-D) cancels the READ * * mode.) * * When Applesoft eventually picks up a subsequent INPUT or * * GET statement, execution bounces back and forth between * * Applesoft, DOS and monitor ROM. DOS gets its mitts into the * * program because the READ command was exited with the I/O hooks * * pointing at DOS's input and output handlers. * * A somewhat simplified example of the execution pattern * * associated with the INPUT command when the read mode is still * * in effect is shown in the formatted disassembly titled * * "CMDREAD CONTINUED". Focus your attention on the RDTXTBYT * * routine ($A68C). After putting the read opcode ($03) and * * read-one-byte subcode ($01) in the FM parameter list, the * * FMDRIVER ($A6A8) is called to do the read. Therefore, * * execution eventually flows into the read function handler * * (FNREAD, $AC58). * * FNREAD uses the subcode (SUBCODFM, $B5BC) to index the * * table of read subfunction handlers (RDSUBTBL, $AAE5) and then * * does a stack jump to the read-one-byte subfunction handler * * (READONE, $AC8A). * * READONE first checks if the data sector wanted is * * presently in memory by comparing the highest two bytes (sector * * offset bytes) of the filepointer with the relative number of * * the last data sector read. If no data sector is currently in * * memory, or if the filepointer does not point to the data sector* * presently in memory, the correct data sector is read in. * * However, if the data sector wanted is not listed in the * * current T/S list, then the appropriate T/S list is first read * * in order to get the trk/sec values for the data sector * * wanted. Once the wanted data sector is in memory, the file * * pointer is used as an index to retrieve a single byte from * * the data buffer. After saving the single byte on the stack, * * the INCREC routine ($B15B) is called to increment the record * * number or the byte offset into the record in anticipation of * * reading another byte. Similarly, the file pointer is advanced * * by the INCFILPT routine ($B194). The byte wanted is retrieved * * from the stack and stored in the single-byte buffer (ONEIOBUF, * * $B5C3) in the FM parameter list. The read function and read- * * one-byte subfunction are then exited. * * Once back into the calling program, the byte just read is * * placed in the input buffer (BUF200, $200-$2FF) and * * conditionally displayed. If the byte was not an input- * * command-terminating carriage return, or if 249 characters were * * not yet read in response to the single INPUT statement, * * execution branches back to the NXTCHAR routine ($FD75) which * * eventually uses the RDTXTBYT routine to read another byte for * * the INPUT string. When a carriage return is encountered, * * byte retrieval stops, the I/O hooks are reset to point to DOS * * and execution eventually flows back into Applesoft's INPUT * * routine where the data are assigned to a variable. Finally, * * execution returns to the caller of the INPUT statement. * * * ****************************************************************** * Conditions on entry: * - If MON C was previously used, the Applesoft program line * containing the READ command has been printed on the screen. * - A valid filename has been parsed and copied into the primary * filename buffer (PRIMFNBF, $AA75). (If a valid filename was * not issued with the command, execution doesn't get this far * because DOS's command parsing routine (PARSECMD, $9FCD) * interprets the "READ" as an Applesoft statement.) * - If applicable, volume, drive, slot, record number and byte * offset values have been parsed, checked for validity and * stored in the parsed options table (VOLPRSD, DRVPRSD, * SLOTPRSD, RECPRSD & BYTPRSD respectively). * - Previous use of the OPEN command has also placed the record * length (RECPRSD) in the parsed options table. * - The appropriate DOS condition handler has copied an abbreviated * version of the original Applesot READ command line into the * input buffer (BUF200). Delimiters have been dropped and the * Applesoft end-of-line marker (eol, $00) has been replaced with a * return code ($8D). For example, if the original Applesoft line * was: 100 PRINT D$;"READ NAME", then the line was originally * coded in memory (in positive ASCII form) as follows: * 22 08 64 00 BA 44 24 3B 22 52 45 41 44 20 4E 41 4D 45 22 00 * . . . . . D $ ; " R E A D spc N A M E " eol marker * . . . . . * . . . . ---> PRINT token * . . . ----> line number (hi) * . . -----> line number (low) * . ------> ptr to next line (hi) (varies) * -------> ptr to next line (low) (varies) * * The abbreviated (negative ASCII) version placed in the keyboard * input buffer by DOS would be as follows: * 84 D2 C5 C1 C4 A0 CE C1 CD C5 8D * . R E A D spc N A M E rtn * . * ----> $84 = actual hex code for ctrl-D * * - The READ command is normally entered with OPUTCOND: 00, * CONDNFLG: 00, and the I/O hooks pointing to the true I/O * handlers (ex. CSW: COUT1 & KSW: KEYIN). (A51B) CMDREAD JSR COMRDWR ;Call common read/write routine. * Code common to read/write. (A526) COMRDWR JSR GETBUFF ;Locate a DOS buffer. * Locate buffer with same name. * If that fails, locate a free buffer. (A764) GETBUFF LDA #0 ;Default hi-byte of pointer to 0 STA A5L+1 ;(ie. assume no free buff available). (A768) JSR GETFNBF1 ;Get pointer to 1rst filename buffer in chain. (A792) GETFNBF1 LDA ADOSFNB1 ;First link to chain of DOS buffers LDX ADOSFNB1+1 ;(ie. pt 2 1rst name buf in chain). (A798) BNE SETNXPTR ;ALWAYS. (A7A4) SETNXPTR STX A3L+1 ;Put addr of 1rst filename buffer in ptr STA A3L ;(ie. highest name buffer in chain). TXA ;Get hi-byte of addr in back in (a). GETNXRTN RTS (A7A9) (A76B) JMP FNCHAR1 ;Get 1rst byte in DOS name buf. ------------ (A76E) GETFNLNK JSR GETNXBUF * Get addr of next DOS name buffer in chain * from chain pointers buffer offset 37 & 36 * bytes from 1rst char of present filename * buffer. (A79A) GETNXBUF LDY #37 ;Point the pointer at the chain buffer & LDA (A3L),Y ;get addr of the next filename buffer. BEQ GETNXRTN ;If hi-byte is 0, then lnk zeroed out. TAX ;Save hi-byte in (x). DEY ;Pick up low-byte. LDA (A3L),Y SETNXPTR STX A3L+1 ;Stick addr of filename buffer in ptr. STA A3L TXA ;Get hi-byte back in (a). GETNXRTN RTS (A7A9) (A771) BEQ NOFNMTCH ;Link zeroed out, end of chain. FNCHAR1 JSR GETFNBY1 ;Get the 1rst char of filename from buf in chain. (A773) * Get first byte in DOS name buffer. (A7AA) GETFNBY1 LDY #0 ;Buffer is free if 1rst byte = $00. LDA (A3L),Y ;If buf occuppied, the 1rst byte = 1rst (A7AE) RTS ;char of filename which owns buffer. (A776) BNE NXFNBUF ;Take branch if buffer wasn't free. LDA A3L ;Buffer was free, there4, point the A5L/H pointer STA A5L ;at the free buffer. LDA A3L+1 STA A5L+1 (A780) BNE GETFNLNK ;ALWAYS. (A782) NXFNBUF LDY #29 ;Buffer not free there4 compare name CMPFNCHR LDA (A3L),Y ;of owner with name of file in primary CMP PRIMFNBF,Y ;name buffer. (Start with last char first.) (A789) BNE GETFNLNK ;Char doesn't match, there4 look for another ;buffer that might have same name. (A78B) DEY ;That char matched, how bout rest of name? BPL CMPFNCHR ;30 chars in name (ie. 0 to 29). CLC ;Clr carry to signal match. (878F) RTS ============ (8790) NOFNMTCH SEC ;Link zeroed out. (A791) RTS ============ (A529) BCC BUFS4RW ;Branch if matching buffer was found ;(ie. file was already open). * FILE NOT ALREADY OPEN, SO GO OPEN IT. (A52B) JSR CMDOPEN (A2A3) CMDOPEN LDA #0 ;0 = code for text file. (A2A5) JMP OPNCKTYP ;Go open the file & chk its type. ------------ (A3D5) OPNCKTYP STA FILTYPFM ;Put code for file type in the (A3D8) PHA ;Fm parameter list & save it on stk. ;($00=Text, $01=Integer, $02=Applesoft, ;$04=Binary, $08=S-type, $10=Relocatable, ;$20=A-type and $40=B-type.) (A3D9) JSR HNDLCMD ;Use FM cmd handler to open file. * Common file manager command handler code. (A2A8) HNDLCMD LDA #1 ;1 = open opcode. HNDLCMD1 STA TEMPBYT ;Store opcode in temporary location. LDA LENPRSD ;Get L-parameter from parsed table. BNE SAVLENFM ;Was a non-zero L-parm issued with cmd? LDA LENPRSD+1 BNE SAVLENFM LDA #1 ;Length was 0 so make it 1 instead. STA LENPRSD SAVLENFM LDA LENPRSD ;Put length in FM parm list. STA RECLENFM LDA LENPRSD+1 STA RECLENFM+1 CLSLOCBF JSR CMDCLOSE ;Close file if it's already open. (A2C8) (A2EA) CMDCLOSE . . (See dis'mbly of CMDCLOSE.) . . - because a matching filename does not exist, only one pass is made through the CLOSE command. A5L/H is normally left pointing at the highest numbered (lowest in memory) free DOS buffer when CMDCLOSE is exited via EVENTXIT and CLOSERTS. If no free buffer is available, A5L/H contains a zero. . . (RTS) (A2CB) LDA A5L+1 ;Hi byte of A5L/H ptr which points at ;the highest numbered (lowest in memory) ;free DOS name buffer (in chain). (A2CD) BNE SAVFNPTR ;Branch if found a free buffer. (A2CF) JMP NOBUFERR ;Go issue an out-of-buffers error msg. ------------ ;(See dis'mbly of errors.) (A2D2) SAVFNPTR STA A3L+1 ;Reset A3L/H to point at DOS buffer that LDA A5L ;we will use for file name field buffer. STA A3L (A2D8) JSR CPYPFN * Assign DOS buffer to file we want to * open. Copy the name of the file wanted * from the primary file name buf to the * DOS buffer's filename field. (A743) CPYPFN LDY #29 ;30 bytes to copy (A745) ;(0 to 29). CPYPRIM LDA PRIMFNBF,Y ;Copy name of STA (A3L),Y ;file wanted from DEY ;primary name buf BPL CPYRIM ;into the DOS (A74D) RTS ;name buffer. (A2DB) JSR BUFS2PRM * Get addrs of the various DOS bufs * from the chain buf & put them in * the FM parameter list. (A74E) BUFS2PRM LDY #30 ;Get adr of FM work ADRINPRM LDA (A3L),Y ;buf, T/S list buf, STA WRKBUFFM-30,Y ;data sec buf INY ;& next DOS name buf CPY #38 ;from chain pointer BNE ADRINPRM ;buf & put them in (A75A) RTS ;FM parm list. ;(P.S. Adr of next ;DOS name buf is ;not used by DOS.) (A2DE) JSR CPY2PARM * Put volume, drive, & slot values plus * the address of the primary filename * buffer in the FM parameter list. (A71A) CPY2PARM LDA VOLPRSD ;From parsed table. STA VOLFM LDA DRVPRSD ;From parsed table. STA DRVFM LDA SLOTPRSD ;From parsed table. STA SLOTFM LDA ADRPFNBF ;Get adr of the STA FNAMBUFM ;primary name buf LDA ADRPFNBF+1 ;from constants (A735) STA FNAMBUFM+1 ;tbl and put it ;in FM parm list. (A738) LDA A3L ;Save the adr of STA CURFNADR ;current DOS name LDA A3L+1 ;buf in table of STA CURFNADR+1 ;DOS variables. (A742) RTS (A2E1) LDA TEMPBYT ;Get open opcode back from temporary buf STA OPCODEFM ;and put it in the FM parameter list. (A2E7) JMP FMDRIVER ;Do function via FM driver. ------------ * USE THE FILE MANAGER DRIVER * TO DO THE OPEN FUNCTION. (A6A8) FMDRIVER JSR FILEMGR ;Call the file manager to do function. * File manager proper. (AB06) FILEMGR TSX ;Save stk pointer (AB07) STX STKSAV ;so can later rtn ;to caller of FM. (AB0A) JSR RSTRFMWA * Copy FM work buf * (in DOS chain) to * FM work area (not * in DOS chain). (AE6A) RSTRFMWA JSR SELWKBUF l l ---------------------- l * Get adr of FM work l * buff from FM parm l * list & put it in l * A4L/H pointer. l (AF08) l SELWKBUF LDX #0 l (AF0A) BEQ PT2FMBUF l l (AF12) l PT2FMBUF LDA WRKBUFFM,X l STA A4L l LDA WRKBUFFM+1,X l STA A4L+1 l (AF1C) RTS l --------------------- l l * Zero out return * code in FM parm * 2 signal no errs. (AE6D) LDY #0 (AE6F) STY RTNCODFM * Copy FM work buf * to FM work area. (AE72) STORFMWK LDA (A4L),Y STA FMWKAREA,Y INY CPY #45 BNE STORFMWK CLC (AE7D) RTS * Check if opcode is legal. * (Must be less than 13.) (AB0D) LDA OPCODEFM CMP #13 (AB12) BCS TOERROP ;Opcode too large ;(got range err). (AB14) ASL ;Double val of (AB15) TAX ;opcode & put it ;in (x) so it ;indexes tbl of ;addresses. (AB16) LDA FMFUNCTB+1,X ;Stick adr of PHA ;the appropriate LDA FMFUNCTB,X ;function hndlr (AB1D) PHA ;on stack (hi byte ;first). (AB1E) RTS ;DO STACK JUMP TO ;FUNCTION ENTRY ;POINT. . . (AB22) . FNOPEN . . (See dis'mbly of OPEN function.) . . - uses part of COMNOPEN routine. - reads in VTOC to get link to 1rst directory. - reads directory secs in & looks for file description entry with matching filename. - if matching name found, reads in the 1rst T/S list sector belonging to the file. - if no match found, starts a new file: (1) creates new file description entry - copies name to 1rst available spc in direc sec (if can't find spc, then issues disk full error msg). - allocates secs for file. - writes updated VTOC to disk. - puts link to first T/S list, file size, etc in directory entry spc. - writes directory sector buffer to disk. (2) creates new T/S list & writes it to disk. - reads T/S list back into T/S list buffer. . . (RTS) ============ TOERROP JMP RNGERROP ;(See dis'mbly (AB1F) ------------ ;of errors. * Return here after doing the OPEN function. * (Cause after @ function is done, use stack * to get back to the original caller.) (A6AB) AFTRFUNC BCC FMDRVRTN ;(c) = 0 = no errors. LDA RTNCODFM ;Get error code from FM parameter list. CMP #$5 ;End-of-data error? (A6B2) BEQ TOAPPTCH ;Yes - Got a zeroed-out T/S link or a ;zeroed-out data pair listed in a ;T/S list. (Not applicable to the ;open function.) (A6B4) JMP OTHRERR ;No. (See dis'mbly of errors.) ------------ (A6C3) FMDRVRTN RTS (A3DC) PLA ;Get file type wanted off of stack. (A3DD)) JMP CHKFTYPE ;Go check if type wanted equals type found. ------------ * Check if file type wanted = file type found. * (If using open command to open a pre-exisiting file, * may get a type mismatch. However, a mismatch error * is not possible when opening a new file.) (A7C4) CHKFTYPE EOR FILTYPFM ;Type found (via open function). (A7C7) BEQ CKTYPRTN ;Branch if type wanted = type found. * File types didn't match. * Check if correct type but locked. (A7C9) AND #%01111111 ;Maybe matched - Check again ;but this time disregard lock bit. (A7CB) BEQ CKTYPRTN ;Branch if matched. * Type wanted < > type found!!!!! * So go close file & then issue a * type mismatch error message. (A7CD) JSR CMDCLOSE ;Wrong kind of file so go close it. * Because the file is already open, execution flows through * the close cmd twice. The first time thru, the matching * DOS filename buffer is located & then CLOSEONE is used to * close the file via the open FUNCTION. The 2nd time thru, a * matching filename buffer is not found because the DOS * buffer was released on the first pass. Therefore, A5L/H is * left pointing at the highest numbered (lowest in memory) * FREE DOS buffer when the close command is exited via EVENTXIT * and CLOSERTS. (A2EA) CMDCLOSE . . (See dis'mbly of CLOSE command.) . . (RTS) (A7D0) JMP TYPMISM ;Go handle type mismatch error. ------------ ;(Eventually exits into DOS's warmstart routine.) ;(See dis'mbly of errors.) CKTYPRTN RTS (A7D3) ============ (A52E) JMP CKRBOPTN ;Go chk if R- & B-parms were issued with cmd. ------------ BUFS4RW JSR BUFS2PRM (A531) * Copy addresses of the various DOS buffers * from the DOS chain buffer to the FM parameter list. (A74E) BUFS2PRM LDY #30 ;Get addr of FM work buf, T/S list ADRINPRM LDA (A3L),Y ;buf, data sector buf & next DOS STA WRKBUFFM-30,Y ;filename buf from chain INY ;pointer buffer & put them in FM parm list. CPY #38 ;(P.S. Adr of next DOS file name buf is BNE ADRINPRM ;not used by DOS.) (A75A) RTS * Check if R- or B-parameters were issued with command. (A534) CKRBOPTN LDA CUMLOPTN ;Chk if R- or B- parms issued. AND #%00000110 ;(R=$04, B=$02.) (A539) BEQ RDWRRTN ;NO - skip positioning of file pointer. * Copy B- and R-parameters from option * parsed table to FM parameter list. (A53B) LDX #3 CPYBPARM LDA RECPRSD,X ;Get value of parameter. STA RECNMBFM ;Store it in FM parameter list. DEX ;4 bytes to copy (3 to 0). (A544) BPL CPYBPARM ;More bytes to copy. * CALL THE FILE MANAGER WITH THE POSITION OPCODE. (A546) BK2APND LDA #$0A ;Opcode for position. STA OPCODEFM ;Put opcode in FM parm list. (A54B) JSR FMDRIVER ;Call file manager to do the position function. (A6A8) FMDRIVER JSR FILEMGR ;Call the file manager to do the function. * File manager proper. (AB06) FILEMGR TSX ;Save stk pointer so can later return STX STKSAV ;to the caller of the file manager. (AB07) JSR RSTRFMWA * Copy FM work buf (in DOS chain) 2 * FM work area (not in DOS chain). (AE6A) RSTRFMWA JSR SELWKBUF * Get addr of FM work * buf from FM parm * list & put it in * the A4L/H pointer. (AF08) SELWKBUF LDX #0 (AF0A) BEQ PT2FMBUF (AF12) PT2FMBUF LDA WRKBUFFM,X STA A4L LDA WRKBUFFM+1,X STA A4L+1 (AF1C) RTS (AE6D) LDY #0 ;Zero out return (AE6F) STY RTNCODFM ;code in FM parm ;to assume no errs (AE72) ;as default cond. STORFMWK LDA (A4L),Y ;Copy FM work buf STA FMWKAREA,Y ;to FM work area. INY CPY #45 ;45 bytes to copy. BNE STORFMWK ;(0 to 44). CLC ;WHY????? (AE7D) RTS (AB0D) LDA OPCODEFM ;Check if opcode is legal. CMP #13 ;(Must be less than 13.) BCS TOERROP ;Opcode too large so got range error. ASL ;Double val of opcode & put it in (x) TAX ;so it indexes tables of adrs. LDA FMFUNCTB+1,X ;Stick adr of appropriate function PHA ;handler on stack (hi byte first). LDA FMFUNCTB,X PHA (AB1E) RTS ;DO STACK JUMP TO FUNCTION ENTRY POINT. . . (AD12) . FNPOSN . . (See dis'mbly of POSITION function.) . . (RTS) ============ TOERROP JMP RNGERROP ;Go handle range error. (AB1F) ------------ * Return here after doing the POSITION FUNCTION. * (Cause after @ function is done, use stack * to get back to the original caller.) (A6AB) AFTRFUNC BCC FMDRVRTN ;(c) = 0 = no errors. LDA RTNCODFM ;Get error code from FM parameter list. CMP #$5 ;End-of-data error? (A6B2) BEQ TOAPPTCH ;Yes - Got a zeroed-out T/S link or a ;zeroed-out data pair listed in a T/S list. ;(Not applicable to the position function.) (A6B4) JMP OTHRERR ;No. (See dis'mbly of errors.) ------------ (A6C3) FMDRVRTN RTS (A54E) RDWRRTN RTS ============ (A51E) LDA #1 ;Set condition flag to designate reading status so (A520) STA CONDNFLG ;subsequent INPUT & GET statements will take ;data from the disk. (A523) JMP FINSHCMD ------------ * Finish off the DOS command. (9F83) FINSHCMD LDA BUF200 ;Get first char in buffer. (9F86) CMP DCTRLCHR ;Was command done via DOS's control char? ;(Normally ctrl-D.) (9F89) BEQ DSPLYCMD ;Yes - ALWAYS TAKE WHEN USING READ CMD ; (cause abbreviated NEG ASCII version of Applesoft ; program line containing the READ cmd is still ; in the keyboard input buffer, BUF200). (9F95) DSPLYCMD LDA #%01000000 ;Set bit 6 to see if using "MON C". (9F97) BNE DSPLYCHR ;ALWAYS. (9F9F) DSPLYCHR AND CIOCUMUL ;Test flag - see if should display. (9FA2) BEQ DOSEXIT ;No - so just exit DOS with condition 1 still ; set so file data will be read. * MON C flag was on, so display command-terminating * carriage return. (P.S. Applesoft detected the * end-of-line marker ($00) and changed it to a . * DOS then put the carriage return ($8D) as the last * character in the input buffer.) (9FA4) DSPLYALL JSR RESTOREG (9FBA) RESTOREG LDA ASAVED ;Restore (a), (y) & (x) registers. LDY YSAVED LDX XSAVED SEC ;Why????? (9FC4) RTS (9FA7) JSR GODSPLY ;Output char via true output handler. (9FC5) GODSPLY JMP (CSW) ------------ (FDF0) COUT1 . . (Print char thru true output handler.) (See dis'mbly of monitor in APPLE II REFERENCE MANUAL.) . . (RTS) ============ (9FAA) STA ASAVED ;Save (a), (y) and (x) registers. STY YSAVED (9FB0) STX XSAVED * Routine to exit DOS. (9FB3) DOSEXIT JSR INITIOHK ;Reset I/O hooks to point to DOS. * Initialize the I/O hooks so that DOS intercepts * all input & output. For instance, if a routine * encounters a "COUT JMP (CSW)", then execution will * actually flow to DOS's output routine (OPUTINCP, * $9EBD). Similarly, any routine that refers to * "RDKEY JMP (KSW)" will actually jump to DOS's * input routine (INPTINCP, $9E81). * * The true (ie. normal) hooks are saved, ex: * KSW: KEYIN --> KSWTRUE: KEYIN. * CSW: COUT1 --> CSWTRUE: COUT1. * The intercepts are then set as follows: * ADINPTCP: INPTINCP --> KSW: INPTINCP. * ADOPUTCP: OPUTINCP --> CSW: OPUTINCP. * Check if the input hook needs to be reset. (A851) INITIOHK LDA KSW+1 CMP ADINPTCP+1 (A856) BEQ CKOUTHK ;Input hook already points to DOS's ;input handler, so go check output hook. * Reset the input hook to point to DOS. (A858) STA KSWTRUE+1 ;KSW: KEYIN --> KSWTRUE: KEYIN. LDA KSW STA KSWTRUE LDA ADINPTCP ;ADINPTCP: INPTINCP --> KSW: INPTINCP. STA KSW LDA ADINPTCP+1 (A868) STA KSW+1 * Check if the output hook needs to be reset. (A86A) CKOUTHK LDA CSW+1 CMP ADOPUTCP+1 (A86F) BEQ SETHKRTN ;Output hook already points to DOS's ;output handler, so go exit. * Reset the output hook to point to DOS. (A871) STA CSWTRUE+1 ;CSW: COUT1 --> CSWTRUE: COUT1. LDA CSW STA CSWTRUE LDA ADOPUTCP ;ADOPUTCP: OPUTINCP --> CSW: OPUTINCP. STA CSW LDA ADOPUTCP+1 STA CSW+1 SETHKRTN RTS (A883) (9FB6) LDX STKSAVED ;Retrieve saved stack pointer. TXS ;(P.S. Don't confuse "STKSAVED" with "STKSAV".) RESTOREG LDA ASAVED ;Restore (a), (y) & (x) registers. LDY YSAVED LDX XSAVED SEC ;Why????? (9FC4) RTS ;Exit to caller of READ command. ============ ;(Normally returns to $D533 in Applesoft ;ROM -- part of INLINPL2 routine ($D52E).) ************************************ * * * NOTE: See formatted disassembly * * titled "CMDREAD CONTINUED". * * * ************************************