******************************************************************
*                                                                *
*                     CHAIN Command Handler                      *
*                                                                *
*----------------------------------------------------------------*
*                                                                *
*      The CHAIN command LOADs and RUNs an INTEGER basic program *
* without first clearing variables and arrays.  It is most often *
* used to execute as series of programs that can't all fit into  *
* the free memory space at once.  Unlike the LOAD and RUN        *
* commands, all previous variable and arrays are preserved and   *
* passed along to subsequently loaded programs.                  *
*      A file name must be issued with the command.  Volume,     *
* drive and slot parameters are optional.                        *
*                                                                *
* Execution pattern:                                             *
*      After assigning a DOS buffer to the named file and        *
* customizing the FM parameter list, the file manager (FILEMGR,  *
* $AB06) is called to open the file by reading its first track-  *
* sector list into the T/S list buffer.  (Failure to locate the  *
* named file results in a file-not-found error message.)         *
*      If the file just opened is NOT an Integer ($01),          *
* Applesoft ($02) or A-type ($20) file, a type-mismatch error    *
* message is printed.  Otherwise, the active basic flag          *
* (ACTBSFLG, $AAB6) is checked to see which basic is active.     *
* When Integer is in effect, a branch is made to integer basic's *
* load routine (LODINTGR, $A450).                                *
*      LOADINTGR checks if an Integer file was found.  If a      *
* different file type was located, the computer assumes that the *
* Applesoft language is required and it tries to switch          *
* languages.  The contents of the primary file name buffer       *
* (PRIMFNBF, $AA75) are copied into the secondary file name      *
* buffer in case A(RAM) needs to be loaded from the System Master*
* disk.  A jump is then made to execute the FP command (CMDFP,   *
* $A57A).  If the FP command is successful, an attempt is made to*
* CHAIN the non-integer file by loading the file.  However,      *
* because an Applesoft program that is loaded via the CHAIN      *
* command is not closed correctly and because Applesoft's version*
* of the LOAD command does not preserve variables and arrays, all*
* is for naught.  It therefore appears that the authors of DOS   *
* forgot to provide adequate error trapping for the CHAIN        *
* command.  Although the CHAIN command only works with Integer   *
* basic, page 106 of the THE DOS MANUAL (APPLE Computer Inc.,    *
* 1980) describes a method of passing variables from one         *
* Applesoft program to another via the use of a program on the   *
* System Master disk.                                            *
*      If the file found was indeed an Integer program, RDADRLEN *
* ($A47A) is called to read the length of the file and store it  *
* in the FM parameter list at LENADRBF ($AA60).  Next a check is *
* made to see if enough free space is available to accommodate   *
* the program.  If (HIMEM - length) < = LOMEM, the program       *
* impinges on the free memory space and a program-too-large error*
* message is generated.  (Remember that Integer files occupy the *
* top end of free memory whereas Applesoft files are usually     *
* loaded into the lower end of the free memory space.)  If all   *
* is well, the start-of-program pointer (INTPGMST, $CA-$CB) is   *
* set and then the file manager driver (FMDRIVER, $A6A8) is      *
* called to read in the rest of the file.  As the program is     *
* read in, LENADRBF is used as a byte counter and variable and   *
* array values are left intact.                                  *
*      After loading the file, a carriage return is printed via  *
* DOS (CRVIADOS, $9FC8) and the I/O hooks are reset (INITIOHK,   *
* $A851) to point to DOS's input and output handler routines.    *
*  Finally, execution branches into integer basic to execute     *
* (ie. RUN) the file.                                            *
*                                                                *
******************************************************************


* On entry - CUMLOPTN ($AA65) has been updated
*            to reflect parsed option words.
*            (Only volume (VOLPRSD), drive (DRVPRSD)
*            and slot (SLOTPRSD) parameters are
*            allowed with the CHAIN command.)
*          - the validity of the options issued with
*            the command (and their numeric operands)
*            have been checked.
*          - a legal file name has been parsed and
*            placed in the primary file name buffer
*            (PRIMFNBF, $AA75).


(A4F0)
CMDCHAIN JSR OPENLOAD ;Go load the INTEGER program.

                      (A416)
                      OPENLOAD JSR HNDLCMD  ;Go open the file.

                                            * OPEN THE FILE.
                                            * On entry from LOAD command, LENPRSD = 0.
                                            *
                                            * 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 CLOSEALL was just used to close all
                                                                    open files, this call to CMDCLOSE is only
                                                                    used for its reference to GETBUFF to
                                                                    locate a free DOS buffer.
                                                                           .
                                                                           .
                                                                  - If necessary, the CLOSE FUNCTION updates the data
                                                                    sector, T/S list sector & the VTOC.  It also fixes
                                                                    up links in the directory sectors and updates the
                                                                    file size if needed.
                                                                           .
                                                                           .
                                                                           (RTS)

                                            (A2CB)   LDA A5L+1    ;Hi byte of A5L/H pointer 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 message.
                                                     ------------ ;(See dis'mbly of errors.)
     
                                            (A2D2)
                                            SAVFNPTR STA A3L+1    ;Reset A3L/H to point at DOS buffer that we
                                                     LDA A5L      ;will use for file name field buffer (chain).
                                                     STA A3L
                                            (A2D8)   JSR CPYPFN

                                                                  * NOTE:  This (re)assigns a DOS buffer to the
                                                                  * file we want to OPEN/LOAD.  The buffer may
                                                                  * or may not be the same one that was just
                                                                  * released by the CLOSE cmd above.  The highest
                                                                  * numbered (lowest in memory) free DOS buffer
                                                                  * is used.
                                                                  (A743)
                                                                  CPYPFN   LDY #29      ;30 bytes to copy (0 to 29).
                                                                  CPYPRIM  LDA PRIMFNBF,Y ;Copy the name of the file wanted from
                                                                           STA (A3L),Y  ;the primary filename buffer into the
                                                                           DEY          ;filename field buffer (in DOS chain).
                                                                           BPL CPYRIM   ;More chars to get.
                                                                  (A74D)   RTS
                                            
                                            (A2DB)   JSR BUFS2PRM

                                                                  * Get addresses of the various DOS buffers from the
                                                                  * chain buffer & put them in 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

                                            (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 the adr of the primary file
                                                                           STA FNAMBUFM ;name buf from the constants tbl
                                                                           LDA ADRPFNBF+1 ;and put it in the FM parm list.
                                                                           STA FNAMBUFM+1
                                                                           LDA A3L      ;Save adr of current DOS file name
                                                                           STA CURFNADR ;buf in table of DOS variables.
                                                                           LDA A3L+1
                                                                           STA CURFNADR+1
                                                                  (A742)   RTS

                                            (A2E1)   LDA TEMPBYT  ;Get open opcode back from temporary buffer
                                                     STA OPCODEFM ;and put it in the FM parameter list.
                                            (A2E7)   JMP FMDRIVER
                                                     ------------

                                            * USE THE FILE MANAGER DRIVER
                                            * TO DO THE OPEN 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 rtn
                                                                           STX STKSAV   ;to caller of FM. (That is, will return
                                                                  (AB0A)   JSR RSTRFMWA ;back into the FMDRIVER at AFTRFUNC
                                                                                        ;($A6A8).)

                                                                                        * Copy FM work buf (in DOS chain) to
                                                                                        * FM work area (not in DOS chain).
                                                                                        (AE6A)
                                                                                        RSTRFMWA JSR SELWKBUF

                                                                                                          * Get adr of FM
                                                                                                          * work buff from
                                                                                                          * the FM parm list
                                                                                                          * & put it in the
                                                                                                          * A4L/H pointer.
                                                                                                          (AF08)
                                                                                                          SELWKBUF LDX #0
                                                                                                          (AFOA)   BEQ PT2FMBUF

                                                                                                          (AF12)
                                                                                                          PT2FMBUF LDA WRKBUFFM,X
                                                                                                                   STA A4L
                                                                                                                   LDA WRKBUFFM+1,X
                                                                                                                   STA A4L+1
                                                                                                          (AF1C)   RTS

                                                                                        (AE6D)   LDY #0       ;Zero out rtn code
                                                                                        (AE6F)   STY RTNCODFM ;in FM parm list
                                                                                                              ;to signal no errs
                                                                                                              ;as the default
                                                                                        (AE72)                ;condition.
                                                                                        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.

                                                                           .
                                                                           .
                                                                  (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, issues a file-not-found
                                                                    message cause LOAD cmd can't create a new file.
                                                                  - reads T/S list back into T/S list buf.
                                                                           .
                                                                           .
                                                                           (RTS)
                                                                           ============

                                                                  TOERROP  JMP RNGERROP ;Go handle range error.
                                                                  (AB1F)   ------------ ;(See dis'mbly 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 ;If (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 (trk/sec vals in T/S list).
                                                                  ;(Not applicable to the open function.)
                                            (A6B4)   JMP OTHRERR  ;No - see dis'mbly of errors.
                                                     ------------

                                            (A6C3)
                                            FMDRVRTN RTS

                      * Restrict LOAD command to Applesoft ($02),
                      * Integer ($01) or A-type ($20) files.
                      (A419)   LDA #$23     ;Set bits 0, 1 and 5 as per above file types.
                               AND FILTYPFM ;Type found (via OPEN function).
                               BEQ TOTYPMIS ;Err - not one of the above file types.
                               STA FILTYPFM ;Save type wanted in FM parameter list.
                      (A423)   LDA ACTBSFLG ;Check which basic is active:
                                            ;        INT=$00, FP=$40 & A(RAM)=$80.
                      (A426)   BEQ LODINTGR ;Branch if Integer is active language.

                      * Load an integer program.
                      (A450)
                      LODINTGR LDA #1       ;(1 = code for integer file.)
                      (A452)   JSR SELCTBSC

                                            * Check if desired basic is up or not.
                                            * Switch basic if necessary.
                                            (A4B1)
                                            SELCTBSC CMP FILTYPFM ;Basic wanted = basic found?
                                            (A4B4)   BEQ SELBSRTN ;Yes - basic wanted is active.

                                            * Type of file wanted is not compatible
                                            * with current active language.
                                            (A4B6)   LDX NDX2CMD  ;Save index to current command in case
                                            (A4B9)   STX NEXTCMD  ;we are using integer & must load integer
                                                                  ;file called "APPLESOFT" in order to load A(RAM).
                                            (A4BC)   LSR          ;Shift type wanted to see which basic to switch into.
                                                     BEQ SWTCH2FP ;Branch if switching from Integer to Applesoft.
                                            (A4BF)   JMP CMDINT   ;Switch from Applesoft to integer.
                                                     ------------ ;(See dis'mbly of INT command.)
     
                                            * Type of basic required (ie. compatible
                                            * with file type wanted) is currently active.
                                            (A4D0)
                                            SELBSRTN RTS          ;Desired basic was active.
                                                     ============

                      (A455)   JSR RDADRLEN

                                            * READ THE LENGTH OF THE FP PRGM
                                            * FROM THE FIRST TWO BYTES OF THE FILE.
                                            (A47A)
                                            RDADRLEN LDA ADLENADR ;Get adr of two-byte input buffer (LENADRBF,
                                                     STA CURIOBUF ;$AA60) from relocatable constants table and
                                                     LDA ADLENADR+1 ;designate it as the I/O buffer in the FM
                                                     STA CURIOBUF+1 ;parameter list.
                                                     LDA #0       ;Designate length to read as 2 bytes
                                                     STA LEN2RDWR+1 ;(ie. want to read load length which is
                                                     LDA #2       ;stored as the 1rst 2 bytes of the file).
                                                     STA LEN2RDWR
                                                     LDA #3       ;Set FM parm list to READ A RANGE of bytes.
                                                     STA OPCODEFM
                                                     LDA #2
                                                     STA SUBCODFM
                                            (A49A)   JSR FMDRIVER

                                                                  * USE THE FILE MANAGER DRIVER
                                                                  * TO READ IN THE LOAD LENGTH.
                                                                  (A6A8)
                                                                  FMDRIVER JSR FILEMGR  ;Call the file manager to do the function.

                                                                                        * File manager proper.
                                                                                        (AB06)
                                                                                        FILEMGR  TSX          ;Save the stack
                                                                                        (AB07)   STX STKSAV   ;pointer so can
                                                                                                              ;later return to
                                                                                                              ;caller of FM.
                                                                                        (AB0A)   JSR RSTRFMWA

                                                                                                              * Copy FM work buf
                                                                                                              * (in DOS chain) to
                                                                                                              * FM work area (not
                                                                                                              * in DOS chain).
                                                                                                              *
                                                                                                              * Find FM work buf.
                                                                                                              (AE6A)
                                                                                                              RSTRFMWA JSR SELWKBUF

                                                                                                                       .
                                                                                                                       .
                                                                                                                       .
                                                                                                   .....................
                                                                                                   .
                                                                                                   .      * Get addr of FM 
                                                                                                   .      * work buff from
                                                                                                   .      * the 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
                                                                                                   .
                                                                                                   .....................
                                                                                                                       .
                                                                                                                       .
                                                                                                                       .
                                                                                                          * Zero out return 
                                                                                                          * code in FM parm
                                                                                                          * list to assume
                                                                                                          * no errors as
                                                                                                          * default condition.
                                                                                                          * Copy FM work buf
                                                                                                          * to FM work area.
                                                                                                          (AE6D)   LDY #0
                                                                                                                   STY RTNCODFM
                                                                                                          STORFMWK LDA (A4L),Y
                                                                                                                   STA FMWKAREA,Y
                                                                                                                   INY
                                                                                                                   CPY #45
                                                                                                                   BNE STORFMWK
                                                                                                                   CLC
                                                                                                          (AE7D)   RTS

                                                                                        (AB0D)   LDA OPCODEFM ;Check if opcode
                                                                                        (AB10)   CMP #13      ;is legal.  (Must
                                                                                                              ;be less than 13.)
                                                                                        (AB12)   BCS TOERROP  ;Opcode too large
                                                                                                              ;so got range err.
                                                                                        (AB14)   ASL          ;Double val of opcode
                                                                                                              ;& put it in (x) so
                                                                                        (AB15)   TAX          ;it indexes tables of
                                                                                                              ;addresses.
                                                                                        (AB16)   LDA FMFUNCTB+1,X ;Stick adr of
                                                                                                 PHA          ;appropriate function
                                                                                                 LDA FMFUNCTB,X ;handler on stack
                                                                                                 PHA          ;(hi byte first).
                                                                                        (AB1E)   RTS          ;DO STACK JUMP TO
                                                                                                 .            ;FUNCTION ENTRY
                                                                                                 .            ;POINT.
                                                                                                 .
                                                                                        (AC58)   .
                                                                                        FNREAD   .
                                                                                                 .
                                                                                        (See dis'mbly of READ function
                                                                                        and read-a-range (READRNG, $AC96)
                                                                                        subfunction.)
                                                                                                 .
                                                                                                 .
                                                                                        - reads in first two bytes of file to
                                                                                          get length of file in bytes.
                                                                                        - On entry:  LEN2RDWR: 2, FILPTSEC: $FFFF,
                                                                                                     RELFIRST: 0, RELASTP1: $7A,
                                                                                                     RELPREV: 0, RECNMBWA:0,
                                                                                                     RECNMBFM: 0, BYTOFFWA: 0,
                                                                                                     BYTOFFFM: 0, RECLENFM: 1,
                                                                                                     RECLENWA 1 and
                                                                                                     CURIOBUF = LENADRBF addr
                                                                                                 .              (normally $AA62).
                                                                                                 .
                                                                                                 (RTS)
                                                                                                 ============

                                                                                        TOERROP  JMP RNGERROP ;Go hndl range err.
                                                                                        (AB1F)   ------------ ;(See dis'mbly
                                                                                                              ;of errors.)

                                                                  * Return here after doing the READ FUNCTION.
                                                                  * (Cause after @ function is done, use stack
                                                                  * to get back to the original caller.)
                                                                  * (On entry, (c) = 0 if just read a byte from a
                                                                  * data sector -- regardless if that byte was 
                                                                  * a $00 or not.)
                                                                  (A6AB)
                                                                  AFTRFUNC BCC FMDRVRTN ;If (c) = 0 = no errors.
                                                                           LDA RTNCODFM ;Get error code from FM parameter list.
                                                                           CMP #5       ;End-of-data error?
                                                                  (A6B2)   BEQ TOAPPTCH ;Yes - file ends at a full data sec and so
                                                                                        ;we encountered a zeroed-out T/S link or
                                                                                        ;zeroed-out data pair (trk/sec values
                                                                                        ;listed in a T/S list).
                                                                  (A6B4)   JMP OTHRERR  ;No - see dis'mbly of errors.)
                                                                  TOAPPTCH JMP APNDPTCH ;(See dis'mbly of errors.)
                                                                           NOP
                                                                  BK2FMDRV JSR CKIFAPND ;<----- NOTE:  APNDPTCH returns here.
                                                                  (A6BB)

                                                                                        * Check status of append flag.
                                                                                        (BA69)
                                                                                        CKIFAPND LDX CMDINDEX ;Get command index.
                                                                                                 CPX #$1C     ;Are we APPENDing?
                                                                                                 BEQ RTNCKAPN ;Yes.
                                                                                                 LDX #0       ;No -turn off flag.
                                                                                                 STX APPNDFLG
                                                                                        RTNCKAPN RTS
                                                                                        (BA75)

                                                                  (A6BE)   LDX #0       ;Zero out the one-data-byte buffer.
                                                                           STX ONEIOBUF ;(Also referred to as low byte of CURIOBUF.)
                                                                  FMDRVRTN RTS
                                                                  (A6C3)

                                            * Prepare to read in file.
                                            (A49D)   LDA LENADRBF+1 ;Get hi byte of length just read from disk.
                                            (A4A0)   STA LEN2RDWR+1 ;Put val just read in param list so know how
                                                                  ;much to read when read in main body of file.
                                            (A4A3)   TAY          ;Save hi byte in (y).
                                                     LDA LENADRBF ;Do likewise with low byte.
                                                     STA LEN2RDWR
                                            (A4AA)   RTS

                      * Calculate start of program
                      * (HIMEM - LENADRBF).
                      (A458)   SEC
                               LDA HIMEM
                               SBC LENADRBF
                               TAX
                               LDA HIMEM+1
                               SBC LENADRBF+1
                               BCC TOTOOLRG ;Length > HIMEM so issue error message.
                               TAY
                               CPY LOMEM+1  ;Check if program < = LOMEM.
                               BCC TOTOOLRG ;Start of program too low, so go
                               BEQ TOTOOLRG ;issue a program-too-large error message.
                               STY INTPGMST+1 ;Set start of program pointer.
                      (A46F)   STX INTPGMST

                      * GO DO THE ACTUAL LOAD.
                      * (Code common to both FP
                      * and Integer load commands.)
                      (A471)
                      LODINTFP STX CURIOBUF ;Designate load addr as I/O buffer
                               STY CURIOBUF+1 ;in the FM parameter list.
                      (A477)   JMP CLOSEFM  ;Use file manager to load the program
                               ------------ ;and then close the file.

                      * Load the program & then close the file.
                      (A40A)
                      CLOSEFM  JSR FMDRIVER ;Use file manager to load main body of file.

                                            * USE THE FILE MANAGER DRIVER
                                            * TO READ IN THE FILE.
                                            (A6A8)
                                            FMDRIVER JSR FILEMGR  ;Call the file manager to do the function.

                                                                  * File manager proper.
                                                                  (AB06)
                                                                  FILEMGR  TSX          ;Save the stack pointer so can later
                                                                           STX STKSAV   ;return to the caller of the FM.
                                                                  (AB0A)   JSR RSTRFMWA ;(That is, for a rtn to AFTRFUNC, $A6AB.)

                                                                                        * Copy FM work buf (in DOS chain) to
                                                                                        * FM work area (not in DOS chain).
                                                                                        (AE6A)
                                                                                        RSTRFMWA JSR SELWKBUF ;Find FM work buf.

                                                                                                          * Get addr of FM 
                                                                                                          * work buff from
                                                                                                          * the 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
                                                                                                              ;list to assume
                                                                                                              ;no errors as
                                                                                        (AE72)                ;default condition.
                                                                                        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.

                                                                           .
                                                                           .
                                                                  (AC58)   .
                                                                  FNREAD   .
                                                                           .
                                                                  (See dis'mbly of READ function
                                                                  and read-a-range (READRNG, $AC96)
                                                                  subfunction.)
                                                                           .
                                                                           .
                                                                  - reads file into free memory starting
                                                                    at address designated in TXTTAB (normally $801).
                                                                  - On entry:  LEN2RDWR: contents of LENADRBF (val read off disk).
                                                                               FILPTSEC: 0, RELPREV:0, FILPTBYT:2,
                                                                               RECNMBWA: 2, RECNMBFM: 1, BYTOFFWA: 0,
                                                                               BYTOFFFM: 0 and CURIOBUF = TXTTAB
                                                                                                        = free memory target
                                                                           .                              addr (normally $801).
                                                                           .
                                                                           (RTS)
                                                                           ============

                                                                  TOERROP  JMP RNGERROP ;Go handle range error.
                                                                  (AB1F)   ------------ ;(See dis'mbly of errors.)

                                            * Return here after doing the READ FUNCTION.
                                            * (Cause after @ function is done, use stack
                                            * to get back to the original caller.)
                                            * (On entry, (c) = 0 if just read a byte from a
                                            * data sector, irregardless if that byte was 
                                            * a $00 or not.)
                                            (A6AB)
                                            AFTRFUNC BCC FMDRVRTN ;If (c) = 0 = no errors.
                                                     LDA RTNCODFM ;Get error code from FM parameter list.
                                                     CMP #5       ;End-of-data error?
                                            (A6B2)   BEQ TOAPPTCH ;Yes - file ends at a full data sec and so
                                                                  ;we encountered a zeroed-out T/S link or
                                                                  ;zeroed-out data pair (trk/sec values
                                                                  ;listed in a T/S list).
                                            (A6B4)   JMP OTHRERR  ;No - see dis'mbly of errors.)
                                            TOAPPTCH JMP APNDPTCH ;(See dis'mbly of errors.)
                                                     NOP
                                            BK2FMDRV JSR CKIFAPND ;<----- NOTE:  APNDPTCH returns here.
                                            (A6BB)

                                                                  * Check status of append flag.
                                                                  (BA69)
                                                                  CKIFAPND LDX CMDINDEX ;Get command index.
                                                                           CPX #$1C     ;Are we APPENDing?
                                                                           BEQ RTNCKAPN ;Yes.
                                                                           LDX #0       ;No -turn off the append flag.
                                                                           STX APPNDFLG
                                                                  RTNCKAPN RTS
                                                                  (BA75)

                                            (A6BE)   LDX #0       ;Zero out the one-data-byte buffer.
                                                     STX ONEIOBUF ;(Also referred to as low byte of CURIOBUF.)
                                            FMDRVRTN RTS
                                            (A6C3)

                      (A40D)   JMP CMDCLOSE ;Go close the file.
                               ------------

                      (A2EA)
                      CMDCLOSE .
                               .
                      (See dis'mly of CLOSE command.)
                               .
                               .
                               (RTS)

(A4F3)   JSR CRVIADOS

                      * Print a carriage return via DOS and the monitor.
                      (9FC8)
                      CRVIADOS LDA #$8D     ;Carriage return.
                      (9FCA)   JMP GODSPLY  ;Print char thru true output handler.
                               ------------

                      (9FC5)
                      GODSPLY  JMP (CSW)    ;CSW points to the true output handler (normally COUT1).
                               ------------

                      (FDF0)
                      COUT1    .
                               .
                      (Monitor ROM's screen output routine.)
                      (See dis'mbly in APPLE II REFERENCE MANUAL.)
                               .
                               .
                               (RTS)
                               ============

(A4F6)   JSR INITIOHK

                      * Initialize the I/O hooks so that DOS
                      * intercepts all input and output.  For
                      * instance, if a routine encounters a
                      * "COUT  JMP (CSW)" then execution will
                      * actually flow to DOS's output handler
                      * 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:
                      *    ADINCPTCP: 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 routine, so 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)

(A4F9)   JMP (CHAINTRY) ;GO INTO INTEGER BASIC TO EXECUTE PRGM.
         --------------


* Go issue a file-type-mismatch error msg.
(A410)
TOTYPMIS JMP TYPMISM  ;(See dis'mbly of errors.)
         ------------

* Close file & issue a program-too-large error msg.
(A4AB)
TOTOOLRG JSR CMDCLOSE

                      (A2EA)
                      CMDCLOSE .
                               .
                      (See dis'mbly of CLOSE command.)
                               .
                               .
                               (RTS)

(A4AE)   JMP TOOLARGE ;(See dis'mbly of errors.)
         ------------
