******************************************************************
*                                                                *
*                    APPEND Command Handler                      *
*                                                                *
*----------------------------------------------------------------*
*                                                                *
*      The APPEND command is intended to help you lengthen a     *
* pre-exsiting SEQUENTIAL text file.  This command opens the     *
* specified file and then locates the end of the file so that a  *
* subsequent WRITE command can add new data contiguous to old    *
* data.  A file name must be issued with the command.  Volume,   *
* drive and slot parameters are optional.                        *
*      Unfortunately, the append command does not always adjust  *
* the file pointer correctly eventhough Apple Computer Inc. has  *
* repeatedly attempted to fix this routine.  Because patches     *
* have been added to repair previous patches and because         *
* execution fails on occassion, the append command has evolved   *
* into a classic case of spaghetti programming.                  *
*                                                                *
* Execution pattern and bugs:                                    *
*      The APPEND command (CMDAPPND, $A298) calls the open       *
* command (CMDOPEN, $A2A3) to locate the named file, read in its *
* first T/S list and aim the three-byte file pointer (FILPTSEC,  *
* $B5E4; FILPTSEC+1, $B5E5; FILPTBYT, $B5E6) at the first byte   *
* of the file.  If the named file cannot be located, a file-not- *
* found message is generated.                                    *
*      After opening the file, the append command repeatedly     *
* calls RDTXTBYT ($A68C) to read the file byte-by-byte until the *
* end of the file is located.  RDTXTBYT uses the read function   *
* (FNREAD, $AC58) and read-one-byte subfunction (READONE,        *
* $AC8A).  READONE in turn calls RDDATA ($ACA8) to do the actual *
* reading and examination of the bytes.  (Only a very minor      *
* portion of the RDDATA routine is shown below.  See the         *
* formatted disassembly titled "PSNRDONE" for more details.)     *
*      The first $00 byte encountered denotes the end of the     *
* file.  This end-of-file marker (eof) can be located in a data  *
* or T/S list sector.  The eof is found in the last DATA sector  *
* if that sector is not completely full.  However, if the file   *
* ends on a sector boundary (ie. the last data sector is full),  *
* then the eof marker is detected in a T/S list sector.  If the  *
* last T/S list of the file describes less than 122 ($7A) data   *
* sectors, the RDDATA routine encounters a zero byte when it     *
* looks in the T/S list for the trk/sec values of the next data  *
* sector.  However, if the file has a multiple of 122 data       *
* sectors, the last T/S list is full of valid data pairs.  In    *
* this case, the end-of-file marker is detected as a zeroed-out  *
* T/S link when the RDDATA routine looks for the next T/S list   *
* sector.                                                        *
*      The location of the eof marker dictates the subsequent    *
* execution pattern.  When the first $00 byte is discovered in a *
* DATA sector, the carry is cleared and the RDDATA routine is    *
* exited with the filepointer and record numbers adjusted as     *
* follows:                                                       *
*          $XX <------ last valid data byte.                     *
*          $00 <------ RECNMBFM points here.                     *
*          $00 <------ RECNMBWA & filepointer aimed here.        *
* Because we eventually want to enter the subsequent WRITE       *
* command with the record numbers and filepointer aimed at the   *
* the byte to be overwritten, RECNMBWA and the filepointer need  *
* to backed up one byte.  However, if an eof is located in a T/S *
* list, the RDDATA routine is eventually exited with the carry   *
* clear and the record numbers and filepointer set as follows:   *
*        $XX <------- last valid data byte                       *
*                     & target of RECNMBFM.                      *
*        $00 <------- RECNMBWA & filepointer aimed here.         *
* RECNMBWA and the filepointer don't require adjusting before    *
* doing the subsequent write because they already point to the   *
* byte to be overwritten.                                        *
*      Actual adjustment of the record numbers and the file-     *
* pointer occur in the CKAPFLG ($B671) and RSETPTRS ($B6B3)      *
* routines.  If the end-of-file marker was found in a T/S list   *
* sector (and the file is not an empty file), the CKAPFLG        *
* routine is entered with the append flag (APPNDFLG, $B65D) set. *
* A set append flag forces RECNMBFM ($B5BD)to be incremented.    *
* By the time the RSETPTRS routine is entered, the append flag   *
* has been turned off and RECNMBFM corresponds to the eof.       *
* RSETPTRS copies the contents of RECNMBFM ($B5BD) into RECNMBWA *
* ($B5FA) and the lower two bytes of the filepointer (FILPTSEC,  *
* $B5E4 and FILPTBYT, $B5E6).  The append command is then exited *
* via GOODFMXIT ($B37F.                                          *
*       Normally, the append command is exited with the record   *
* numbers and filepointer correctly aimed at the byte to be      *
* overwritten.  However, because RSETPTRS only adjusts the lower *
* two bytes of the filepointer, the append command can fail if   *
* the high byte of the pointer (FILPTSEC+1, $B5E4) needs to be   *
* backed up.  This situation only occurs if a file contains      *
* exactly $FFFF (65535) or 2 * $FFFF (131070) data bytes.        *
* (A file 2 * $FFFF bytes long can only be created if DOS is     *
* altered to free up some extra sectors.)  The chances of the    *
* append command failing are therefore very small indeed.  No    *
* wonder some bugs seem to take forever to surface!              *
*                                                                *
******************************************************************


* On entry - CUMLOPTN ($AA65) has been updated
*            to reflect parsed option words.
*          - the validity of the options issued
*            with the command (and their numeric
*            values) have been checked.
*          - a legal file name has been parsed and
*            stored in the primary file name buffer
*            (PRIMFNBUF, $AA75).
*          - confirmation has been made that the
*            computer is working in the deferred mode.


(A298)
CMDAPPND JSR CMDOPEN  ;Go open the file to be appended.

                      (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 ;(Note:  Record length = 1 for sequential files
                                                     LDA LENPRSD+1 ;else parsed length for random access files.)
                                                     STA RECLENFM+1
                                            CLSLOCBF JSR CMDCLOSE ;Close file if it's already open.
                                            (A2C8)

                                                                  (A2EA)
                                                                  CMDCLOSE .
                                                                           .
                                                                  (See dis'mbly of CMDCLOSE.)
                                                                           .
                                                                           .
                                                                  - Note that execution flows thru CMDCLOSE twice if the
                                                                    file is already open.
                                                                  - The first time thru, the matching DOS filename buffer is
                                                                    located & then CLOSEONE is used to close the file.
                                                                  - Execution then jumps back to the start of CMDCLOSE.
                                                                  - On this second pass, a matching filename is not found
                                                                    because the DOS filename buffer was released on the
                                                                    first pass.  Therefore, A5L/H is left pointing at the
                                                                    highest numbered (lowest in memory) FREE DOS buffer
                                                                    when CMCLOSE is exited via EVENTXIT and CLOSERTS.
                                                                  - If the file is not already open on the first entry to
                                                                    CMDCLOSE, only one pass is made.  This single pass
                                                                    resembles the second pass mentioned above.
                                                                           .
                                                                           .
                                                                  - 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.  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 ptr so can later rtn 2 caller.
                                                                           STX STKSAV
                                                                  (AB0A)   JSR RSTRFMWA

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

                                                                                                           * Get adr 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 code
                                                                                        (AE6F)   STY RTNCODFM ;in FM parm list to
                                                                                                              ;signal 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.

                                                                  (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 by:
                                                                    (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 message).
                                                                        - allocates secs for file.
                                                                        - writes updated VTOC to disk.
                                                                        - puts link to first T/S list, file size, etc
                                                                          in directory entry space.
                                                                        - 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 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 ;(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 in 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 - 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.
                                            ;(See dis'mbly of close command.)
                      (A7D0)   JMP TYPMISM  ;See dis'mbly of errors.
                               ------------ ;(Eventually goes into DOS's warm start routine.)

                      CKTYPRTN RTS
                      (A7D3)   ========

(A29B)
READ2END JSR RDTXTBYT

                      (A68C)
                      RDTXTBYT LDA #3       ;Set read opcode.
                               STA OPCODEFM
                               LDA #1       ;Set one-byte subcode.
                               STA SUBCODFM
                      (A696)   JSR FMDRIVER ;Call FM driver to read a data byte.

                                            (A6A8)
                                            FMDRIVER JSR FILEMGR  ;Call the file manager to do the function.
         
                                                                  (AB06)
                                                                  FILEMGR  TSX          ;Save stk ptr so we can rtn to caller.
                                                                           STX STKSAV
                                                                  (AB0A)   JSR RSTRFMWA ;Copy contents of FM work buffer (in DOS
                                                                                        ;chain) to FM work area (not in chain).
     
                                                                                        (AE6A)
                                                                                        RSTRFMWA JSR SELWKBUF ;Find FM work buffer.

                                                                                                           * Get address of FM
                                                                                                           * work buf from FM
                                                                                                           * parm list & stick
                                                                                                           * it in the A4L/H
                                                                                                           * pointer.
                                                                                                           (AF08)
                                                                                                           SELWKBUF LDA #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 rtn code in
                                                                                                 STY RTNCODFM ;lst 2 signal no errs.
                                                                                        STORFMWK LDA (A4L),Y  ;Copy FM work buf
                                                                                                 STA FMWKAREA,Y ;(in chain) to FM
                                                                                                 INY          ;wrk area (not in
                                                                                                 CPY #45      ;DOS buf chain).
                                                                                                 BNE STORFMWK
                                                                                                 CLC          ;Why?????
                                                                                        (AE7D)   RTS
 
                                                                  (AB0D)   LDA OPCODEFM ;Chk if opcode is legal.
                                                                           CMP #13      ;(Must be less than 13.)
                                                                           BCS TOERROP  ;Opcode too large, got range error.
                                                                           ASL          ;Double val of opcode & get addr of
                                                                           TAX          ;appropriate function handler from tbl.
                                                                           LDA FMFUNCTB+1,X ;Put the adr on stack (hi byte first)
                                                                           PHA          ;& then do a "stack jump" to the appropriate
                                                                           LDA FMFUNCTB,X ;function handler.
                                                                           PHA
                                                                  (AB1E)   RTS

                                                                           .
                                                                           .
                                                                  (AC58)   .
                                                                  FNREAD   LDA SUBCODFM ;Check if subcode is legal.
                                                                           CMP #5       ;(Must be < = 5.)
                                                                  (AC5D)   BCS TOERRSUB ;Error - illegal subcode.
                                                                                        ;(Not applicable to append command.)
                                                                  (AC5F)   ASL          ;Subcode * 2, cause 2 bytes/address.
                                                                           TAX          ;Index table of subfunction addresses.
                                                                           LDA RDSUBTBL+1,X ;Get address (minus 1) of subfuction
                                                                           PHA          ;entry point & stick it on the stack
                                                                           LDA RDSUBTBL,X ;(hi byte first).  Then do a "stack
                                                                           PHA          ;jump" to execute the given READ sub-
                                                                  (AC69)   RTS          ;function.  (APPEND COMMAND ALWAYS USES
                                                                                        ;THE READ-ONE-BYTE SUBFUNCTION.)


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

                                                                  (AC6A)   ------------
                                                                  TOERRSUB JMP RNGERRSB ;Go handle range error.
                                                                           ------------ ;(See dis'mbly of errors.)


                                                                           .
                                                                           .
                                                                  (AC8A)   .
                                                                  READONE  JSR RDDATA

                                                                                        (ACA8)
                                                                                        RDDATA   .
                                                                                                 .
                                                                                        - Read in the file byte-by-byte by
                                                                                          reading in the data and T/S list
                                                                                          sectors as required.
                                                                                        - If an end-of-file marker (eof) is
                                                                                          detected in a T/S list, SET the carry.
                                                                                          An eof marker only resides in the T/S
                                                                                          list if the last data sector is full-
                                                                                          to-the-brim.  The $00 byte may be 
                                                                                          picked up as a zeroed-out data pair or
                                                                                          T/S list link (depending on the length
                                                                                          of the file).
                                                                                        - If a DATA sector byte is being read,
                                                                                          CLEAR the carry (irregardless if the data
                                                                                          byte is valid or an eof).
                                                                                        - See formatted disassembly of the read
                                                                                          function for more details.
                                                                                                 .
                                                                                                 .
                                                                                        (ACAB)   BCS NDATERR
                                                                                                 -----------
                                                                                        (ACAD)   LDA (A4L),Y  ;Get single byte read
                                                                                                              ;from data sector buf.
                                                                                        (ACAF)   PHA          ;Save it on the stack.
                                                                                        (ACB0)   JSR INCREC   ;Inc the record #
                                                                                                              ;or the offset into
                                                                                                              ;the record.
                                                                                        (ACB3)   JSR INCFILPT ;Inc the file ptr.
                                                                                                 PLA          ;Get byte just read.
                                                                                        (ACB7)   RTS
                                                                                                 =============

                                                                  (AC8D)   STA ONEIOBUF ;Put byte just read in the one-byte buffer
                                                                                        ;contained in the FM parameter list.
                                                                  (AC90)   JMP GOODFMXT ;Exit the file manager.
                                                                           -------------

                                                                  (B37F)
                                                                  GOODFMXT LDA RTNCODFM
                                                                           CLC          ;(c) = 0 to signal good operation.
                                                                  (B383)   BCC FMEXIT

                                                                  (B386)
                                                                  FMEXIT   PHP          ;Save status on stack.
                                                                           STA RTNCODFM ;Store return code in FM parameter list.
                                                                           LDA #0       ;Avoid that infamous $48 bug.
                                                                           STA STATUS
                                                                  (B38E)   JSR CPYFMWA

                                                                               * Copy the FM work area buffer (non-chain)
                                                                               * to the FM work buffer (in DOS chain).
                                                                               (AE7E)
                                                                               CPYFMWA  JSR SELWKBUF ;Select the FM work
                                                                                                     ;buf (in DOS chain).

                                                                                                     * Point the A4L/H ptr
                                                                                                     * at work buffer.
                                                                                                     (AF08)
                                                                                                     SELWKBUF LDX #0
                                                                                                    (AF0A)    BEQ PT2FMBUF

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

                                                                               (AE81)   LDY #0       ;Initialize index.
                                                                               STORWRK  LDA FMWKAREA,Y ;Get byte from work
                                                                                        STA (A4L),Y  ;area & put it in
                                                                                        INY          ;the work buffer.
                                                                                        CPY #45      ;45 bytes to copy
                                                                                        BNE STORWRK  ;(0 to 44).
                                                                                (AE8D)  RTS

                                                                  (B391)   PLP          ;Retrieve status of success of operation
                                                                                        ;back from the stack.
                                                                  (B392)   LDX STKSAV   ;Adjust the stack pointer to force exit
                                                                           TXS          ;to the caller even if several subroutines
                                                                  (B396)   RTS          ;deeper than original entry.  In this
                                                                           ============ ;particular case, return to AFTRFUNC.

                                                                                        * This routine is entered only if a
                                                                                        * end-of-file marker was found in
                                                                                        * a T/S list.
                                                                                        (ACB8)
                                                                                        NDATERR  JMP ENDOFDAT ;Ran out of data while
                                                                                                 ------------ ;reading or appending.

                                                                                        (B36F)
                                                                                        ENDOFDAT LDA #5       ;Out of data code.
                                                                                        (B371)   BNE BADFMXIT ;ALWAYS.

                                                                                        (B385)
                                                                                        BADFMXIT SEC          ;(c)=1=unsuccessful.
                                                                                        FMEXIT   PHP          ;Save status on stack.
                                                                                                 STA RTNCODFM ;Save return code.
                                                                                                 LDA #0       ;Avoid $48 bug.
                                                                                                 STA STATUS
                                                                                        (B38E)   JSR CPYFMWA

                                                                                                     * Copy work area
                                                                                                     * to work buffer.
                                                                                                     (AE7E)
                                                                                                     CPYFMWA  JSR SELWKBUF

                                                                                                              * Point A4L/H ptr
                                                                                                              * at work buffer.
                                                                                                              (AF08)
                                                                                                              SELWKBUF LDX #0
                                                                                                              (AF0A)   BEQ PT2FMBUF

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

                                                                                                     * Do the copying.
                                                                                                     (AE81)   LDY #0
                                                                                                     STORWRK  LDA FMWKAREA,Y
                                                                                                              STA (A4L),Y
                                                                                                              INY
                                                                                                              CPY #45
                                                                                                              BNE STORWRK
                                                                                                     (AE8D)   RTS

                                                                                        (B391)   PLP          ;Get success of oper-
                                                                                                              ;ation from stk.
                                                                                        (B392)   LDX STKSAV   ;Adjust stack ptr
                                                                                                 TXS          ;to force exit
                                                                                        (B396)   RTS          ;to the caller even 
                                                                                                 ============ ;when several sub-
                                                                                                              ;routines deeper 
                                                                                                              ;than orig entry.
                                                                                                              ;In this case,
                                                                                                              ;return to AFTRFUNC.

                                            * Return here after doing the READ function
                                            * (Cause after @ function is done, use stack
                                            * to get back to original caller.)
                                            *
                                            * = If dealing with a byte from a data sector
                                            *   (even if that byte is a $00) enter with:
                                            *   - RECNMBFM = record # corresponding to byte just read.
                                            *   - RECNMBWA = record # associated with next potential
                                            *                byte situated after byte just read.
                                            *                (ie.  RECNMBWA = 1 greater than contents 
                                            *                of RECNMBFM.)
                                            *   - Filepointer aimed 1 byte past byte just read.
                                            *     (ie. lower two bytes of filepointer contain
                                            *     the same values as RECNMBWA.)
                                            *   - Carry is CLEAR.
                                            *
                                            * = If dealing with a $00 byte read from the T/S list
                                            *   then either got a zeroed-out T/S link or a 
                                            *   zeroed out data pair .  In either case, enter with:
                                            *   - RECNMBFM = record # of last valid data byte.
                                            *   - RECNMBWA = record # of next potential data byte.
                                            *                (ie. RECNMBWA is always 1 > RECNMBFM).
                                            *   - Filepointer aimed at next potential data byte
                                            *     byte position. Lowest two bytes of filpointer
                                            *     (FILPTSEC and FILPTBYT) are same as RECNMBWA and
                                            *     RECNMBWA+1.
                                            *   - Carry is SET.

                                            (A6AB)
                                            AFTRFUNC BCC FMDRVRTN ;Branch if dealing with byte from
                                                                  ;a data sector (as opposed to byte
                                                                  ;from a T/S list).
                                            (A6AD)   LDA RTNCODFM ;Get error code from FM parameter list.
                                                     CMP #5       ;End-of-data error?
                                            (A6B2)   BEQ TOAPPTCH ;Yes - not handled like other errors!!!.
                                                                  ;File ends at a full data sec and so we
                                                                  ;encountered a zeroed out T/S link or a
                                                                  ;zeroed out data pair (trk/sec vals for
                                                                  ;next data sec listed in T/S list).
                                            (A6B4)   JMP OTHRERR  ;Only take if got an error other than
                                                     ------------ ;an end-of-data error.  (See dis'mbly
                                                                  ;of errors.)
                                            TOAPPTCH JMP APNDPTCH
                                            (A6B7)   ------------

                                            * Note:  You are now entering an almost
                                            * undecipherable mess of spaghetti programming.
                                            * Parts of the following routines seem useless.
                                            * They may just be residual (but innocuous)
                                            * instructions that are left over from an
                                            * earlier version of DOS.

                                            * Check if file pointer and WASTEBYT are zeroes.
                                            (B692)
                                            APNDPTCH LDY #$13
                                            CK4ZEROS LDA (A4L),Y
                                            (B696)   BNE SETAPFLG ;Unless we are dealing with a 
                                                                  ;useless file that was previously
                                                                  ;opened, but never closed, this
                                                                  ;instruction is always taken.
                                            (B698)   INY
                                                     CPY #$17
                                            (B69B)   BNE CK4ZEROS
     
                                            * The purpose of the following instructions is not
                                            * understood.  This section of code may have been
                                            * designed to deal with useless files that were
                                            * opened but never closed.  Whatever the original
                                            * purpose was, the following code appears to keep
                                            * the file pointer at #$000000 when a file with no 
                                            * data is encountered.
                                            (B69D)   LDY #$19
                                            COPYRECS LDA (A4L),Y  ;Copy image of RECNMBWA/+1 and BYTOFFWA/+1
                                                     STA RECNMBFM-$19,Y ;that were just stored in the work
                                                     INY          ;buffer to RECNMBFM/+1 and BYTOFFFM/+1
                                                     CPY #$1D     ;in the FM parm list.
                                                     BNE COPYRECS
                                            FMDVRTN  JMP BK2FMDRV
                                            (B6A9)   ------------

                                            * Set the append flag.
                                            * (Never entered if dealing
                                            * with an empty file.)
                                            (B6AC)
                                            SETAPFLG LDX #$FF
                                                     STX APPNDFLG ;Set the append flag.
                                            (B6B1)   BNE FMDVRTN  ;ALWAYS.
                                                     ------------

                                            (A6BA)   NOP
                                            BK2FMDRV JSR CKIFAPND
                                            (A6BB)

                                                                  * Check if using APPEND command.
                                                                  (BA69)
                                                                  CKIFAPND LDX NDX2CMD  ;Get command index.
                                                                           CPX #$1C     ;Are we APPENDing?
                                                                           BEQ RTNCKAPN ;Yes - leave flag on.
                                                                           LDX #0       ;No - turn off append flag.
                                                                           STX APPNDFLG
                                                                  RTNCKAPN RTS
                                                                  (BA75)

                                            (A6BE)   LDX #0       ;Zero out the one-data byte parameter in FM parm list.
                                                     STX ONEIOBUF ;(Also referred to as low byte of CURIOBUF.)
                                            FMDRVRTN RTS          ;Return to caller of FMDRIVER.
                                            (A6C3)

                      (A699)   LDA ONEIOBUF ;Get byte just read.
                      (A69C)   RTS

(A29E)   BNE READ2END ;Take branch if dealing with a valid
                      ;data byte.  Haven't encountered an end-
                      ;of-file marker yet, so go back to read
                      ;rest of file.
(A2A0)   JMP CKAPFLG  ;Detected an end-of-file marker (a $00 byte).
         ------------

* Prepare to manually back up file pointer
* if necessary.  Need to back it up one byte
* if a $00 byte was encountered in a data sector.
* However, if a zeroed-out data pair (listed
* in the T/S list) or a zeroed out T/S link was
* read, then the filepointer is positioned 
* correctly.  (P.S.  At one time in the history
* of DOS 3.3, the position function was used to
* back up the file pointer.)
* Enter with append flag set if a $00 was detected
* in a (non-empty) file's T/S list.
(B671)
CKAPFLG  LDA APPNDFLG ;Is append flag on?
         BEQ CLRAPFLG ;No - flag is off.
         INC RECNMBFM ;Yes - so increment the file manager's
         BNE CLRAPFLG ;version of the record number cause
(B67B)   INC RECNMBFM+1 ;RECNMBFM is pointing at the last
                      ;valid data byte and we want it to point
                      ;at the next potential record number.
                      ;(P.S. Remember that RECNMBFM always lags
                      ;RECNMBWA by one byte.)
(B67E)
CLRAPFLG LDA #0       ;Don't need append flag any more, so
         STA APPNDFLG ;turn it off.
(B683)   JMP RSETPTRS ;Go back up the file pointer.
         ------------

* Buggy routine used to back up the file pointer.
* If a file is $FFFF (65535) bytes long (or some
* some multiple thereof), the append will fail
* because this routine neglects to back up the
* hi byte of the file pointer (FILPTSEC+1).
(B6B3)
RSETPTRS LDA RECNMBFM ;Reconcile record number versions
         STA FILPTBYT ;and lowest 2 bytes of file pointer.
         STA RECNMBWA
         LDA RECNMBFM+1
(B6BF)   STA WASTEBYT ;Appears to be irrevelvant.  Obviously
                      ;has something to do with the CK4ZEROS
                      ;routine described above.
(B6C2)   STA RECNMBWA+1
         STA FILPTSEC
         TSX          ;Reset the stack pointer so we can use the
(B6C9)   STX STKSAV   ;FMEXIT routine to return to the caller
                      ;of the append command.  (Note:  This will
                      ;be an exceptional exit route for FMEXIT.)
(B6CC)   JMP GOODFMXT ;Exit cleanly.
         ------------
(B37F)
GOODFMXT LDA RTNCODFM
         CLC          ;(c) = 0 to signal good operation.
(B383)   BCC FMEXIT   ;ALWAYS.

(B386)
FMEXIT   PHP          ;Save status on stack.
         STA RTNCODFM ;Store return code in FM parameter list.
         LDA #0       ;Avoid that infamous $48 bug.
         STA STATUS
(B38E)   JSR CPYFMWA

                      * Copy the FM work area buffer (non-chain)
                      * to the FM work buffer (in DOS chain).
                      (AE7E)
                      CPYFMWA  JSR SELWKBUF ;Select the FM work buffer (in DOS chain).

                                            * Point the A4L/H pointer at the FM work buffer.
                                            (AF08)
                                            SELWKBUF LDX #0       ;Set index to selct FM work buffer.
                                            (AF0A)   BEQ PT2FMBUF ;ALWAYS.

                                            (AF12)
                                            PT2FMBUF LDA WRKBUFFM,X ;Get addr of selected buffer from the
                                                     STA A4L      ;FM parameter list & put it in the pointer.
                                                     LDA WRKBUFFM+1,X
                                                     STA A4L+1
                                            (AF1C)   RTS

                      (AE81)   LDY #0       ;Initialize index.
                      STORWRK  LDA FMWKAREA,Y ;Get byte from the FM work area.
                               STA (A4L),Y  ;Put it in the work buffer.
                               INY
                               CPY #45      ;45 bytes to copy (0 to 44).
                               BNE STORWRK
                      (AE8D)   RTS

(B391)   PLP          ;Retrieve status of success of operation
                      ;back from the stack.
(B392)   LDX STKSAV   ;NOTE:   The contents of STKSAV ($B39B) were
         TXS          ;altered above (at $B6C9).  Therefore, the
(B396)   RTS          ;stack is now reset to return to the caller
         ============ ;of the append command handler.  Execution
                      ;actually returns to AFTRCMD ($A17D) located
                      ;in the command parsing and processing
                      ;routines.  Note that this is an exceptional
                      ;route for FMEXIT to take.
