*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
*                                                                *
*                    VERIFY function handler                     *
*                                                                *
*----------------------------------------------------------------*
*                                                                *
*      The verify function simply opens & then "reads" a file.   *
* Actual verification occurs deep within RWTS.  As the data are  *
* read, a checksum is calculated.  If the calculated checksum    *
* agrees with the checksum byte read off the disk, the integrity *
* of the data are verified.  Failure to verify yeilds an I/O     *
* error.                                                         *
*                                                                *
* Execution pattern:                                             *
*      FNVERIFY ($AD18) first calls the common open routine      *
* COMNOPEN ($AB28) to locate and then open the named file.       *
* COMNOPEN configures the FM work area, reads in a fresh VTOC    *
* and then searches the directory sectors for the file           *
* description entry of the wanted file.  (The links to the first *
* directory sector are stored as the 2nd and 3rd bytes (offsets  *
* $01 and $02) of the VTOC.  The 2nd and 3rd bytes of each       *
* subsequent directory sector contain the trk and sec values of  *
* the next directory sector.  The link bytes of the last         *
* directory sector are zeroed out.)                              *
*      As each directory sector is read in, an attempt is made   *
* to locate a file description which contains the name of the    *
* file wanted.  If the name can't be located after searching all *
* the directories and if the VERIFY command was used by itself,  *
* a second search is made to locate the first available space in *
* a directory sector where a new file description can be placed  *
* (in case the command can create a new file).  If no free space *
* is located, a disk-full error message is printed.  (When the   *
* VERIFY command is accessed via the INIT, SAVE or BSAVE         *
* commands, no second search is done because these previous      *
* commands would have already created a new file entry if        *
* necessary.)                                                    *
*      If an available space is located, NWDESCRP ($B21C) copies *
* the name of the wanted file from the primary file name buffer  *
* (PRIMFNBF, $AA75) into the new entry space.  A check is then   *
* made to see if the command can legally create a new file.  The *
* identifying command byte (NDX2CMD, $AA5F) is used to index a   *
* table of command attributes (CMDATTRB, $A909).  Because bit 0  *
* of the first attribute byte associated with the VERIFY command *
* is clear, a new file cannot legally be created.  As a result,  *
* the VERIFY command is exited with a file-not-found message.    *
*      If a (non-deleted) description entry containing the name  *
* of the wanted file is located, execution branches to the       *
* FILLINWA routine ($ABA6).  FILLINWA uses the information       *
* contained in the description entry to customize the FM work    *
* area.  After the carry is cleared execution jumps to the       *
* READTS routine ($AF5E). Because the carry was just cleared,    *
* READTS reads in the file's first T/S list sector.              *
*      Execution then returns to the FNVERIFY routine at         *
* VRFYREAD ($AD1B).  VRFYREAD in turn calls NXTDATRD ($BOB6) to  *
* read the file's data sectors into the data sector buffer.      *
*      The execution patterns associated with NXTDATRD and its   *
* associated subroutines can be difficult to trace because so    *
* many flags are envolved.  Unfortunately these flags are an     *
* evil necessity because NXTDATRD is called by almost any DOS    *
* command that reads or writes disk data.  A description of the  *
* flags and possible execution patterns that can be taken by     *
* NXTDTRD when called from the VERIFY command are shown below:   *
*                                                                *
* Major decisions and flags used:                                *
* Use current data sector?                                       *
*      - yes  = FILPTSEC/+1 = RELPREV/+1                         *
*      - no   = FILPTSEC/+1 < > RELPREV/+1                       *
*               - when a file is first opened, the common open   *
*                 routine (COMNOPEN, $AB28) sets FILPTSEC: $0000 *
*                 and RELPREV: $007A.  This forces the computer  *
*                 to try to use the file's first data sector.    *
*               - when a data sector is filled by successively   *
*                 adding data byte, FILPTSEC/+1 > RELPREV/+1.    *
*               - if the position function was used to adjust    *
*                 the filepointer out of the range of RELPREV,   *
*                 then FILPTSEC/+1 < > RELPREV/+1.               *
* Use current T/S list ?                                         *
*      - yes    = FILPTSEC/+1 > RELFIRST/+1                      *
*                 and FILPTSEC/+1 < RELASTP1/+1.                 *
*      - no     = FILPTSEC/+1 < RELFIRST/+1                      *
*                 or FILPTSEC/+1 > = RELASTP1/+1.                *
* Update current data or T/S list sectors?                       *
*      - yes    = bit 6 (data) or bit 7 (T/S list) of UPDATFLG   *
*                 ($B5D5) are set.                               *
*      - no     = bits 6 and 7 of UPDATFLG are clear.            *
* Read first T/S list?                                           *
*      - yes    = (c) = 0 - carry cleared if file was just       *
*                           opened.  File pointer was previously *
*                           backed up by CALCFPTR ($B300).       *
*      - no     = (c) = 1 - file is long enough that another T/S *
*                           list must be used.                   *
* Writing data?                                                  *
*      - yes = OPCODEFM ($B105) = 4.                             *
*      - no  = OPCODEFM < > 4.                                   *
* Any more data pairs listed in current T/S list?                *
*      - yes = trk byte portion of data pair < > $00.            *
*      - no  = trk byte portion of data pair = $00.              *
* Any more T/S lists in file?                                    *
*      - yes = trk byte portion of link < > $00.                 *
*      - no  = trk byte portion of link = $00.                   *
*      (Link to first T/S list is contained in the first two     *
*      bytes of the file description entry in the directory sec. *
*      Link to subsequent T/S lists are contained in 2nd and 3rd *
*      bytes (offsets $01 and $02) of previous T/S lists.)       *
*                                                                *
* Note:  RELPREV ($B5E0, $B5E1)                                  *
*                = the relative sector number (in relation to    *
*                  the entire file) of the last data sector that *
*                  was read or written.  (Possible values are:   *
*                  $0000, $007A, 2*$007A, 3*$007A, 4*$007A.)     *
*       RELFIRST ($B5DC, $B5DD)                                  *
*                = the relative sector number (in relation to    *
*                  the entire file) of the first data sector     *
*                  that is (or can be) listed in the current     *
*                  T/S list.                                     *
*       RELASTP1 ($B5DE, $B5DF)                                  *
*                = one greater than the maximum relative sector  *
*                  number (in relation to the entire file) of    *
*                  the last data sector that can possibly be     *
*                  listed in the current T/S list.  (Possible    *
*                  values are:  $007A, 2*$007A, 3*$007A, 4*$007A *
*                  and 5*$007A.)                                 *
* NXTDATRD execution patterns:                                   *
* Pattern 1:  = FILPTSEC/+1 = RELPREV/+1                         *
*             - select the current data sector.                  *
*             - exit NXTDATRD routine via XITNXDAT.              *
* Pattern 2:  = FILPTSEC/+1 < > RELPREV/+1                       *
*             = FILPTSEC/+1 > = NDXFIRST/+1                      *
*               and FILPTSEC/+1 < RELASTP1/+1                    *
*             = trk portion of data pair < > 0                   *
*             - update the current data sector if necessary.     *
*        2a:  - get valid link byte to the next data sector from *
*               the current T/S list.                            *
*             - read in the next data sector.                    *
*             - update RELPREV.                                  *
*             - exit the NXTDATRD routine via XITNXDAT.          *
* Pattern 3:  = FILPTSEC/+1 < > RELPREV/+1                       *
*             = FILPTSEC/+1 > = RELFIRST/+1                      *
*               and FILPTSEC/+1 < RELASTP1/+1                    *
*             = trk portion of data pair = 0                     *
*             = OPCODEFM < > 4                                   *
*             - update the current data sector if necessary.     *
*        3a:  - detect zeroed out data pair in the current T/S   *
*               list.                                            *
*             - test OPCODEFM to determine that we are NOT       *
*               writing and set the carry flag to signal just    *
*               read all the data.                               *
*             - exit the NXTDATRD routine via XITNXDAT.          *
* Pattern 4:  = FILPTSEC/+1 < > RELPREV/+1                       *
*             = FILPTSEC/+1 < = RELFIRST/+1                      *
*             = carry clear at $AF69                             *
*             = trk portion of link byte to next T/S list < > 0  *
*             - update current data and/or T/S list secs if      *
*               necessary.                                       *
*             - get link to file's first T/S list from the file  *
*               description entry in the current directory sec.  *
*             - read in the first T/S list.                      *
*             - loop back to do 2a, 3a or 5.                     *
* Pattern 5:  = FILPTSEC/+1 < > RELPREV/+1                       *
*             = FILPTSEC/+1 > = RELASTP1/+1                      *
*             = carry set at $AF69                               *
*             = trk portion of link to next T/S list < > 0       *
*             - update current data and/or current T/S list      *
*               sectors if necessary.                            *
*             - get valid link bytes to the next T/S list from   *
*               the current T/S list.                            *
*             - loop back to do 2a, 3a or repeat 5.              *
* Pattern 6:  = FILPTSEC/+1 < > RELPREV/+1                       *
*             = FILPTSEC/+1 > = RELASTP1/+1                      *
*             = carry set at $AF69                               *
*             = trk portion of link to next T/S list < > 0       *
*             = OPCODEFM < > 4                                   *
*             - update current data and/or current T/S list      *
*               sectors if necessary.                            *
*             - get zeroed out link bytes to the next T/S list   *
*               from the current T/S list.                       *
*             - test OPCODEFM to determine that we are NOT       *
*               writing and set the carry flag to signal that    *
*               we have just read all the data.                  *
*             - exit NXTDATRD the routine via XITNXDAT.          *
*                                                                *
*      If no errors are encountered, the NXTDATRD routine        *
* ($B0B6) is exited via XITNXDAT ($B12C).  XITNXDAT points the   *
* A4L pointer ($42, $43) at the DOS data sector buffer and sets  *
* (y) to index that buffer.  When an "RTS" is encountered,       *
* execution returns to $AD1E in the VRFYREAD routine.            *
*      If this return is made with a set carry, all the data     *
* have been read and the verify function is exited via a branch  *
* to the TOOKFMXT ($AD0F).  Otherwise, the file pointer is       *
* incremented and execution jumps back to the VRFYREAD routine   *
* ($AD1B) to "read" the next data sector.                        *
*                                                                *
*----------------------------------------------------------------*


(AD18)
FNVERIFY JSR COMNOPEN ;Locate file with the same name and open it.

                      * Common open routine.
                      (AB28)
                      COMNOPEN JSR ZWRKAREA ;Initialize the work area.


                                            * Zero out the FM work area so it can be customized
                                            * in accordance with the calling function.
                                            * (Although some work bytes may not be subsequently
                                            * altered, don't be lulled into thinking that they
                                            * are not important.  Zero values can be just as relevant
                                            * as non-zero values.)
                                            * (P.S.  Don't confuse FM work area with its image
                                            * (FM work buffer) that is housed in the chain of
                                            * DOS buffers.)
                                            (ABDC)
                                            ZWRKAREA LDA #0
                                                     TAX          ;Initialize the x-index.
                                            ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area.
                                                     INX
                                                     CPX #45      ;Work area is 45 bytes long.
                                            (ABE5)   BNE ZEROWRKA

                                            * Begin customizing the work area.
                                            * Get volume, drive, slot  & catalog track
                                            * values from the FM parameter list.  Put
                                            * drive, slot*16, catalog track and
                                            * complemented volume number in the work area.
                                            (ABE7)   LDA VOLFM    ;Volume number.
                                                     EOR #$FF     ;Calculate 1's complement of volume #.
                                                     STA VOLWA
                                                     LDA DRVFM    ;Drive #.
                                                     STA DRVWA
                                                     LDA SLOTFM   ;Get slot #.
                                                     ASL          ;Calculate slot * 16.
                                                     ASL
                                                     ASL
                                                     ASL
                                                     TAX          ;Set (x) = slot * 16.
                                                     STX SLOT16WA
                                                     LDA #$11     ;Normal catalog trk = #17.
                                                     STA TRKWA
                                            (AC05)   RTS

                      (AB2B)   LDA #1      ;Describe sector length as 256 bytes
                      (AB2D)   STA SECSIZWA+1 ;(in the FM work area).

                      * Get record length from the FM parameter
                      * list & put it in the FM work area.
                      * (Don't allow a zero length.  If zero,
                      * change it to one.)
                      (AB30)   LDX RECLENFM+1
                               LDA RECLENFM
                               BNE STRECLEN ;Non-zero record length is ok.
                               CPX #0
                               BNE STRECLEN
                               INX          ;Was zero, make it one instead.
                      STRECLEN STA RECLENWA ;Put length in FM work area.
                               STX RECLENWA+1
                      (AB43)   JSR GETFNTRY ;Try to find a directory sector for the file.

                                            * Locate or create a file entry in the
                                            * directory buffer.
                                            * Make two searches if necessary:
                                            *    - Search1 - try to locate entry with same name as file wanted.
                                            *    - Search2 - couldn't locate entry corresponding to file
                                            *                 wanted so create a new entry in first available
                                            *                 space in the directory sector.
                                            * Two searches are never required if the VERIFY cmd is
                                            * accessed via the INIT, SAVE, or BSAVE commands.
                                            * These calling commands would have previously
                                            * created a new file description if necessary.
                                            (B1C9)
                                            GETFNTRY JSR READVTOC ;Read in the VTOC so we can get the link to
                                                                  ;TRKMAPS & to the first directory sector.

                                                                  * Read the Volume Table of Contents (VTOC).
                                                                  (AFF7)
                                                                  READVTOC LDA #1       ;Read opcode for RWTS.
                                                                  (AFF9)   BNE RDWRVTOC ;ALWAYS.

                                                                  * Code common to read/write VTOC.
                                                                  (AFFD)
                                                                  RDWRVTOC LDY ADRVTOC  ;Get address of VTOC from the
                                                                           STY IBBUFP   ;FM constants table & designate it
                                                                           LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
                                                                           STY IBBUFP+1
                                                                           LDX TRKWA    ;Enter RWTS driver with (x)/(y) equal
                                                                           LDY #0       ;to the trk/sec values of the VTOC.
                                                                  (B00E)   JMP RWTSDRVR ;Call driver to read/write the VTOC.
                                                                           ------------

                                                                  * Read/Write Track/Sector driver.
                                                                  (B052)
                                                                  RWTSDRVR .
                                                                           .
                                                                  (See dism'bly of RWTS driver using READ.)
                                                                           .
                                                                           .
                                                                           (RTS)

                                            * Point A4L/H at the primary file name buffer.
                                            (B1CC)   LDA FNAMBUFM ;Get address of the name buffer from the
                                                     STA A4L       ;FM parameter list & put it in the  A4L/H
                                                     LDA FNAMBUFM+1 ;pointer.
                                            (B1D4)   STA A4L+1

                                            * Try to find the directory sector with the
                                            * wanted file name & read it into the directory
                                            * sector buffer.  Make two searches if necessary.
                                            * On the first search, try to find a matching name.
                                            * If that doesn't work, do a second search to store
                                            * the description in the first available file
                                            * description field in a directory sector.
                                            (B1D6)   LDA #1       ;Initialize the search counter (SCRNSRCH)
                                            SETSRCH  STA SCRNSRCH ;in the FM scratch space for two searches.
                                            (B1D8)                ;(1 = search1, 0 = search2)
                                            (B1DB)   LDA #0       ;Initialize offset of file description from
                                                     STA SECNXDIR ;the very first directory sector.
                                                     CLC          ;(c)=0=signal to read first directory sec.
                                            GETDIRSC INC SECNXDIR ;Kick up offset from first directory.
                                            (B1E1)                ;(On first entry, $00 --> $01.)
                                            (B1E4)   JSR RDDIRECT ;Go read directory sector into buffer.

                                                                  * Read a directory sector.
                                                                  (B011)
                                                                  RDDIRECT PHP          ;Save (c) on stack:
                                                                                        ;  (c) = 0 = read 1rst directory sector.
                                                                                        ;  (c) = 1 = read next directory sector.
                                                                  (B012)   JSR PT2DIRBF

                                                                                        * Designate the directory sector buffer
                                                                                        * as I/O buffer in RWTS's IOB.
                                                                                        (B045)
                                                                                        PT2DIRBF LDA ADRDIRBF ;Get addr of direc
                                                                                                 STA IBBUFP   ;sec buf from the
                                                                                                 LDA ADRDIRBF+1 ;FM constants tbl
                                                                                                 STA IBBUFP+1 ;& designate it as
                                                                                        (B051)   RTS          ;as the I/O buffer.

                                                                  (B015)   PLP          ;Check if 1rst directory sec or not.
                                                                  (B016)   BCS RDNXTDIR ;Go read next directory sector.

                                                                  * Read the first directory sector.
                                                                  * (Carry = 0.)
                                                                  (B018)
                                                                  RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory
                                                                           LDX FIRDIRTK ;sector (from the VTOC buffer).
                                                                  (B01E)   BNE DODIRRD  ;ALWAYS - go read in directory sector.

                                                                  * Read the next directory sector.
                                                                  * (Carry = 1.)
                                                                  (B020)
                                                                  RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the
                                                                                        ;link in the current directory sector.
                                                                  (B023)   BNE GETDIRLK ;Link not zeroed out.
                                                                           SEC          ;Link zeroed out - exit with (c) = 1 to
                                                                  (B026)   RTS          ;signal there are no more directory secs.
                                                                           ============

                                                                  (B027)
                                                                  GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the
                                                                                        ;link in the current directory sector.

                                                                  * Call to read in the directory sector.
                                                                  (B02A)
                                                                  DODIRRD  STX CURDIRTK ;Save trk/sec vals of directory sec that
                                                                  (B02D)   STY CURDIRSC ;we are about to read so they will be
                                                                                        ;the current directory sec values for the
                                                                                        ;next time around.
                                                                  (B030)   LDA #1       ;Read opcode for RWTS.
                                                                  (B032)   JSR RWTSDRVR ;Call RWTS driver to do the read.

                                                                                        * Read/Write Track/Sector driver.
                                                                                        (B052)
                                                                                        RWTSDRVR .
                                                                                                 .
                                                                                        (See dis'mbly of RWTS driver using READ.)
                                                                                                 .
                                                                                                 .
                                                                                                 (RTS)

                                                                  (B035)   CLC          ;Link didn't zero out so signal that there
                                                                  (B036)   RTS          ;are more directory secs to read & exit.
                                                                           ============

                                            (B1E7)   BCS CHNGSRCH ;Link zeroed out, no more directory secs,
                                                                  ;so go switch searches.
                                            (B1E9)   LDX #0
                                            CKDIRTRK STX CURDIRNX ;Offset of file description into the current
                                            (B1EB)                ;directory sector.
                                            (B1EE)   LDA FIL1TSTK,X ;Get track number of first T/S list
                                                                  ;for a particular file from the file
                                                                  ;description entry in the directory sector.
                                            (B1F1)   BEQ CHRSRCHA ;If trk=0, no more files in this direc sec.
                                            (B1F3)   BMI CHRSRCHB ;Skip deleted file.  (When a file is
                                                                  ;deleted, #$FF is put in byte where trk #
                                                                  ;of first T/S list is usually kept.

                                            * Compare the name found in the file
                                            * description entry portion of the
                                            * directory sector with the file name
                                            * wanted.  (On entry, A4L/H points at
                                            * the primary file name buffer.)
                                            (B1F5)   LDY #0       ;Initialize index to file name buffer.
                                                     INX          ;Point (x) at the first char position
                                                     INX          ;in the name field of description entry.
                                            CMPNAMES INX
                                                     LDA (A4L),Y  ;Get char of name from primary.
                                                     CMP FIL1TSTRK,X ;Compare to char in name of description.
                                                     BNE DONTMTCH ;Chars (and therefore names) don't match.
                                                     INY
                                                     CPY #30      ;Done all chars yet (0 to 29)?
                                                     BNE CMPNAMES ;Chars matched, branch if more to check.
                                                     LDX CURDIRNX ;All chars matched, so names matched.
                                                     CLC          ;Return with (x) = index to file
                                            (B20A)   RTS          ;description in current directory sector
                                                     ============ ;and with (c) = 0 to signal that the
                                                                  ;correct file description was found.

                                            * Advance index to point at the next
                                            * potential file description entry.
                                            (B20B)
                                            DONTMTCH JSR NXPLUS35 ;Names didn't match, so adjust index
                                                                  ;to point at the next entry.

                                                                  * Add 35 to the offset to point the index
                                                                  * at the next file description entry.
                                                                  * (Check to make sure that we don't index
                                                                  * right off the end of the directory sec.)
                                                                  (B230)
                                                                  NXPLUS35 CLC
                                                                           LDA CURDIRNX
                                                                  (B234)   ADC #35      ;Add 35 to index.  (Each file description
                                                                                        ;entry is 35 bytes long.)
                                                                  (B236)   TAX          ;Check if there is more space for entries
                                                                           CPX #245     ;in the current directory sector.
                                                                  (B239)   RTS          ;Exit with (c) conditioned:
                                                                                        ; (c) = 0 = more space in directory.
                                                                                        ; (c) = 1 = ran off end of directory.

                                            (B20E)   BCC CKDIRTRK ;More potential file descriptions to check
                                                                  ;in this directory sector.
                                            (B210)   BCS GETDIRSC ;Go get next directory sector.
                                                     ------------

                                            * If we just completed the first seach,
                                            * go back to do the second search.
                                            (B212)
                                            CHRSRCHA LDY SCRNSRCH ;(1 = search1, 0 = search2)
                                            (B215)   BNE SETSRCH  ;Go switch to second search.

                                            * If first search, skip deleted files.
                                            * If second search, fall through to store
                                            * the description in the first unused
                                            * space in the directory.
                                            (B217)
                                            CHRSRCHB LDY SCRNSRCH ;(1 = search1, 0 = search2)
                                            (B21A)   BNE DONTMTCH

                                            * Couldn't locate the named file in the
                                            * directory description entries, so begin
                                            * creating a new description in the first available
                                            * space in a directory (in case command can
                                            * legally create a new file).
                                            (B21C)
                                            NWDESCRP LDY #0       ;Initialize index to primary file name buffer.
                                                     INX          ;Set index to first char position in the
                                                     INX          ;name field of the file description entry
                                            SETNWNAM INX          ;space in the directory sector.
                                                     LDA (A4L),Y  ;Copy char from primary file name buffer
                                                     STA FIL1TSTK,X ;to the directory description space.
                                                     INY
                                                     CPY #30      ;30 chars in name (0 to 29).
                                                     BNE SETNWNAM ;Branch if more chars to copy.
                                                     LDX CURDIRNX ;Return with (x) = index to file
                                                     SEC          ;description space in current directory
                                            (B22F)   RTS          ;sector & with (c)=1 to signal new entry
                                                     ============ ;was just created.

                                            * If first search, switch to second search.
                                            * If second search, link zeroed out because
                                            * there isn't enough room left on the
                                            * disk for a new entry.  Therefore,
                                            * exit with a disk-full error message.
                                            (B23A)
                                            CHNGSRCH LDA #0       ;Used to reset search counter if
                                                                  ;we go back to start a second search.
                                            (B23C)   LDY SCRNSRCH ;(1 = search1, 0 = search2)
                                                     BNE SETSRCH  ;Just did search1 so go start search2.
                                            (B241)   JMP DISKFULL ;Even second search was unsuccesful
                                                     ------------ ;so go handle a disk-full error.

                      (AB46)   BCC FILLINWA ;Branch if found a directory sector with
                                            ;name wanted in the file description entry.
                                            ;Will always find name if using verify in association
                                            ;with INIT, SAVE or BSAVE commands because these commands
                                            ;would have previously provided a new name if necessary.

                      * Named file wasn't found in directory,
                      * so prepare a new file entry in case
                      * command can legally create a new file.
                      (AB48)   STX CURDIRNX ;Offset to new description entry in
                                            ;case want to create a new file.

                      * Check to  see if command can
                      * legally create a new file.
                      (AB4B)   LDX NDX2CMD  ;(x) = index representing command.
                      (AB4E)   LDA CMDATTRB,X ;Get first byte containing description
                                            ;of the given command's attributes.
                      (AB51)   LDX CURDIRNX ;(x) = index for new file description
                                            ;entry into the directory sector.
                      (AB54)   LSR          ;(c) = bit 0 of 1rst attribute byte.
                      (AB55)   BCS CREATNEW ;If (c) = 1, command can create a new file.
                                            ;ALWAYS FALL THRU WHEN VERIFYING.

                      * Command can't create a new file.
                      * See which language we are using and
                      * exit with the appropriate error msg.
                      (AB57)
                      NEWILLGL LDA CONDNFLG ;$00=warmstart, $01=reading, $40=A(RAM),
                                            ;$80=coldstart & $C0=integer.
                      (AB5A)   CMP #$C0     ;Integer in ROM?
                               BNE TOFILNOT ;No.
                      (AB5E)   JMP LNGNOTAV ;Yes - handle language-not-available error.
                               ------------
                      TOFILNOT JMP FILENOT  ;Handle file-not-found error.
                      (AB61)   ------------

                      * Fill in the FM work area buffer.
                      * (Routine common to opening a new
                      * or pre-existing file.)
                      (ABA6)
                      FILLINWA LDA FIL1TSTK,X ;T/S list trk val (from directory sec).
                               STA FIRSTSTK
                               LDA FIL1TSSC,X ;T/S list sec val (from directory sec).
                               STA FIRTSSEC
                               LDA FIL1TYPE,X ;File type (from directory sec).
                               STA FILTYPFM
                               STA FILTYPWA
                               LDA FIL1SIZE,X ;File size (from directory sec).
                               STA FILENSEC
                               LDA FIL1SIZE+1,X
                               STA FILENSEC+1
                               STX BYTNXDIR ;Index into directory sec to description.
                               LDA #$FF     ;Pretend that the last data sector used had
                               STA RELPREV  ;a relative sector number (in relation to
                      (ABCF)   STA RELPREV+1 ;the entire file) of $FFFF.  NOTE:  This
                                            ;value is later used to trick the read and
                                            ;write subfunctions into ignoring the data
                                            ;sector currently in memory.
                      (ABD2)   LDA MXIN1TSL ;Dicatate that a T/S list can only describe $7A
                      (ABD5)   STA MXSCURTS ;(#122) data sectors.  Note:  This value is later
                                            ;used by the read and write subfunctions to decide
                                            ;whether or not the T/S list currently in memory
                                            ;should be used.

                      * Read first T/S list sector
                      * to the T/S list buffer.
                      (ABD8)   CLC          ;(c) = 0 = signal 1rst T/S list sector.
                      (ABD9)   JMP READTS   ;Go read in the T/S list sector.
                               ------------
     
                      * Read T/S list sector.
                      (AF5E)
                      READTS   .
                               .
                      (See dis'mbly given below.)
                               .
                               .
                               (RTS)

(AD1B)
VRFYREAD JSR NXTDATRD ;Read the next data sector in.  (Assume
                      ;the data sector we want is not presently
                      ;in memory.)

                      * Check if we need to read the next data
                      * sector into the data sector buffer.
                      *
                      * - Is the data sec we want already in memory?
                      * - If so, does it require updating?

                      * If sector offset into file (FILPTSEC) equals
                      * the relative sector number of the last sector
                      * read or written (RELPREV), then sector we want
                      * is presently in memory.  If it is not in memory,
                      * read in the data sector wanted.  However, first
                      * check if the data sector has changed since the
                      * last read or write.  If it has, the disk must
                      * be updated before we read in the new data
                      * sector so we don't overwrite the data
                      * sector buffer and loose information.
                      * NOTE:  - if this subroutine is called from a
                      *          write subfunction and FILPTSEC is not
                      *          equal to RELPREV, then the data sector
                      *          buffer must be full & therefore should
                      *          be written to the disk before any more
                      *          information is read in.
                      *        - if the file was just opened, the open
                      *          subfunction set FILPTSEC = $0000 and
                      *          RELPREV = #$FFFF so always force reading
                      *          of a new data sector even if the correct
                      *          sector is already in memory.

                      * NOTE:  Not all of the NXTDATRD routine is listed
                      *        because not all of it applies to the
                      *        VERIFY function.
                      (B0B6)
                      NXTDATRD LDA FILPTSEC ;Last sector used versus sector wanted?
                               CMP RELPREV
                      (B0BC)   BNE CKWCURDA ;Not same - will eventually have to read in
                                            ;a new data sector.
                                            ;Note:  THIS BRANCH IS ALWAYS TAKEN ON FIRST
                                            ;       ENTRY FROM THE VERIFY FUNCTION
                                            ;       because RELPREV was set to #$FFFF
                                            ;       in the FILLINWA section of the 
                                            ;       common open routine.  In other
                                            ;       words, program flow in the VERIFY
                                            ;       function is such that a new data
                                            ;       read is forced even if the correct
                                            ;       data sector is already resident in
                                            ;       the data sector buffer.
                      (B0BE)   LDA FILPTSEC+1 ;Maybe same - check hi bytes.
                               CMP RELPREV+1
                      (B0C4)   BEQ XITNXDAT ;Same, so go exit.

                      * Write the data sector if necessary.
                      * Data sector we want is not presently
                      * in memory.  Check if we need to write
                      * the current data sector buffer before
                      * we read in the wanted data sector.
                      (B0C6)
                      CKWCURDA JSR CKDATUP  ;Check the update flag to see if the data
                                            ;sector buffer has changed since the last
                                            ;read or write.  If it has, write the data
                                            ;sector buffer to the disk.

                                            * Check if the data sector has changed
                                            * since the last read or write was done.
                                            (AF1D)
                                            CKDATUP  BIT UPDATFLG ;Check bit 6 to see if data sec requires
                                                                  ;updating or not.
                                            (AF20)   BVS WRITDATA ;Take branch if data requires updating.
                                                                  ;ALWAYS FALL THRU WHEN USING VERIFY.
                                            (AF22)   RTS

                      * Should current T/S list be used?
                      * (That is, should the data sector be listed in
                      * the present T/S list sector?  If not, then
                      * will need to read in the correct T/S list.)

                      * Is the sector offset into the file of the present
                      * data sector less than the relative sector number
                      * of the FIRST data sector that can be described in
                      * the T/S list presently in memory?  (If less,
                      * then need to read in a different T/S list sector.)
                      (B0C9)
                      CKCURTS  LDA FILPTSEC+1 ;Sector offset in file associated with
                      (B0CC)   CMP RELFIRST+1 ;the present data sector versus the
                                            ;relative sector number of the first data
                                            ;sector that can be described in the present
                                            ;T/S list.
                      (B0CF)   BCC NEEDNXTS ;Data sector wanted represents a SMALLER offset
                                            ;into the file so need a different T/S list.
                      (B0D1)   BNE CKCURTS1 ;Sector offset of wanted data sector is
                                            ;LARGER than that of the first data sector that
                                            ;can be described in the present T/S list so it
                                            ;may still belong to this T/S list.
                      (B0D3)   LDA FILPTSEC ;Hi bytes same - so compare low bytes.
                               CMP RELFIRST
                      (B0D9)   BCC NEEDNXTS ;Sector offset of wanted files is LESS,
                                            ;so read in a different T/S list.
                                            ;(Start by reading the file's first T/S list.)

                      * Sector offset associated with the data
                      * sector we want is either GREATER THAN OR
                      * EQUAL TO the relative sector offset
                      * associated with the first data sector that can
                      * be described in this T/S list.  Therefore,
                      * compare the sector offset of the sector
                      * wanted with the relative sector number
                      * (plus 1) of the LAST sector that can be
                      * described in the present T/S list.
                      (B0DB)
                      CKCURTS1 LDA FILPTSEC+1 ;Sector offset associated with data sector
                      (B0DE)   CMP RELASTP1+1 ;we want versus the relative sector number
                                            ;(plus 1) of the LAST data sector that can possibly
                                            ;be described in the present T/S list.
                      (B0E1)   BCC GETDATPR ;Sector offset assoc with data sector we
                                            ;wanted IS described in the present T/S list.
                      (B0E3)   BNE NEEDNXTS ;Sector offset of present data sector is
                                            ;LARGER than that of the LAST data sector
                                            ;(plus 1) that can possibly be described in the
                                            ;present T/S list, so we need a new T/S list sector.
                      (B0E5)   LDA FILPTSEC ;Hi bytes same - so compare low bytes.
                               CMP RELASTP1
                      (B0EB)   BCC GETDATPR ;Sector offset associated with data sector
                                            ;we want is LESS than the relative sector
                                            ;number (plus 1) of the last data sector that
                                            ;can possibly be listed in the present T/S list.
                                            ;There4, data sector wanted should be described
                                            ;in the present T/S list.

                      * The data sector we want is NOT listed
                      * in the present T/S list, so we must
                      * read a different T/S list sector.
                      * (NOTE:  Routine is entered with (c) = 1 if need a
                      * higher numbered T/S list.  If (c) = 0, then the file
                      * pointer was backed up and we need a smaller numbered
                      * T/S list.)
                      (B0ED)
                      NEEDNXTS JSR READTS   ;Read in the next (or first) T/S list.  However,
                                            ;first check the update flag to see if the T/S list
                                            ;presently in memory requires updating before
                                            ;we read in the next (or first) T/S list sector.
                                            ;If updating is required, write the present
                                            ;T/S list.

                                            * Read T/S list sector.
                                            (AF5E)
                                            READTS   PHP          ;Save (c) denoting if 1rst T/S list or not.
                                                                  ;(c) = 0 = read 1rst T/S list sec.
                                                                  ;(c) = 1 = read next T/S list sec.
                                            (AF5F)   JSR CKTSUPDT ;Write T/S list sec buf if updating is
                                                                  ;required.  (If T/S list buf has changed
                                                                  ;since last read or write, then write it
                                                                  ;back to the disk so don't overwrite buf
                                                                  ;and lose information when read the new
                                                                  ;T/S list sector.)

                                                                  * Check if T/S list requires updating.
                                                                  * (ie. Has T/S list buf changed since
                                                                  * the last read or write?)
                                                                  (AF34)
                                                                  CKTSUPDT LDA UPDATFLG
                                                                  (AF36)   BMI WRITETS  ;If bit 7 set, updating is required.
                                                                                        ;ALWAYS FALL THRU FOR VERIFY FUNCTION.
                                                                  (AF37)   RTS
                                                                           ============

                                            (AF62)   JSR SETTSIOB ;Prepare RWTS's IOB for READING a T/S list.

                                                                  * Prepare RWTS's IOB for reading
                                                                  * or writing the T/S list sector.
                                                                  (AF4B)
                                                                  SETTSIOB LDA TSBUFFM  ;Get adr of the T/S list buf from the FM
                                                                           STA IBBUFP   ;parameter list & designate T/S list buf
                                                                           LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB.
                                                                           STA IBBUFP+1
                                                                           LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list.
                                                                           LDY CURTSSEC
                                                                  (AF5D)   RTS

                                            (AF65)   JSR SELTSBUF ;Select the T/S list buffer.

                                                                  * Point A4L/H at the T/S list sector buffer.
                                                                  (AF0C)
                                                                  SELTSBUF LDX #2       ;Index for T/S list buf.
                                                                  (AF0E)   BNE PT2FMBUF ;ALWAYS.

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

                                            (AF68)   PLP          ;Get saved (c) back from stack.
                                            (AF69)   BCS RDNXTTS  ;If (c) = 1, already read first T/S list
                                                                  ;sec, so go read next one.

                                            * Read first T/S list sector.
                                            * (Carry was clear.)
                                            (AF6B)
                                            RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec.
                                                     LDY FIRTSSEC
                                            (AF71)   JMP RDTSLST  ;Go read T/S list sector into buffer.
                                                     ------------

                                            * Read next T/S list sector.
                                            * (Carry was set.)
                                            (AF74)
                                            RDNXTTS  LDY  #1      ;Index into T/S list buffer.
                                                     LDA (A4L),Y  ;Trk for link to next T/S list sector.
                                            (AF78)   BEQ TSLNKZRO ;Link zeroed out, so there are no more
                                                                  ;T/S list sectors for file.
                                            (AF7A)   TAX          ;(x) = next T/S list trk.
                                                     INY
                                                     LDA (A4L),Y  ;Sector for link to next T/S list sector.
                                                     TAY          ;(y) = next T/S list sector.
                                            (AF7F)   JMP  RDTSLST ;Go read in next T/S list sector.
                                                     ------------

                                            * T/S link zeroed out so now must
                                            * decide if got an error or not.
                                            (AF82)
                                            TSLNKZRO LDA OPCODEFM ;Check read/write status to see if want to
                                                     CMP #4       ;add another T/S list or not.
                                                     BEQ UPDATETS ;Writing, so go update link.
                                            (AF89)   SEC          ;Set (c) = 1 to signal no more data.
                                                                  ;(Causes out-of-data error when reading.
                                                                  ;Signals verification completed when verifying.)
                                            (AF8A)   RTS
                                                     =========

                                            * Subroutine to read T/S list sector.
                                            (AFB5)
                                            RDTSLST  LDA #1       ;READ opcode for RWTS.

                                            * Code common to read/write T/S list.
                                            (AFB7)
                                            RDWRTS   STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y)
                                                     STY CURTSSEC ;become current T/S list trk/sec values.
                                            (AFBD)   JSR RWTSDRVR ;Call RWTS driver to read/write current T/S
                                                                  ;list.

                                                                  * Read or write the current T/S list.
                                                                  (B052)
                                                                  RWTSDRVR .
                                                                           .
                                                                  (See dis'mbly of RWTS driver using READ or WRITE.)
                                                                           .
                                                                           .
                                                                           (RTS)

                                            * Update the FM work area
                                            * (not in DOS buffer chain).
                                            (AFC0)   LDY  #5      ;Offset into current T/S list buffer.
                                                     LDA (A4L),Y  ;Get & save the relative sector number of
                                            (AFC4)   STA RELFIRST ;the first data sector that can be
                                                                  ;described in this T/S list.  (Possible
                                                                  ;values are:  $0000, $007A, 2*$007A,
                                                                  ;3*$007A or 4*$007A.)
                                            (AFC7)   CLC          ;Add the maximum number of secs that
                                                     ADC MXSCURTS ;can be described in this T/S list.
                                            (AFCB)   STA RELASTP1 ;Store the maximum relative sector number
                                                                  ;(plus 1) that can possibly be described
                                                                  ;in this particular T/S list.  (That is,
                                                                  ;reset RELASTP1.)
                                            (AFCE)   INY
                                                     LDA (A4L),Y
                                                     STA RELFIRST+1
                                                     ADC MXSCURTS+1
                                                     STA RELASTP1+1 ;Value equals $0000, $007A
                                                     CLC          ;2*$007A, 3*$007A, 4*$007A or 5*$007A.
                                            (AFDB)   RTS
                                                     ============

                      (B0F0)   BCC CKCURTS  ;Go back and check if this is
                                            ;the correct T/S list.
                      (B0F2)   RTS          ;RETURN WITH (c)=1 TO SIGNAL RAN OUT OF DATA.
                               ============

                      * We know that the data sector wanted
                      * should be described in the present T/S
                      * list so now calculate the offset into
                      * the T/S list sector where the data
                      * sector pair should be described.
                      (B0F3)
                      GETDATPR SEC          ;Calculate offset to the data pair:
                               LDA FILPTSEC ;   Sector offset of data sector into file
                      (B0F7)   SBC RELFIRST ;   minus the relative index of first data
                                            ;   sector pair described in present T/S list.
                      (B0FA)   ASL          ;Times 2, cause 2 bytes used to describe a data pair.
                               ADC #12      ;Add 12 cause 1rst data pair is always listed
                               TAY          ;12 bytes from the start of the T/S list buf.
                      (B0FE)   JSR SELTSBUF ;Point A4L/H at the T/S list buffer.

                                            * Point the A4L/H pointer at the
                                            * T/S list sector buffer.
                                            (AF0C)
                                            SELTSBUF LDX #2       ;Index to select T/S list sector buffer.
                                            (AF0E)   BNE PT2FMBUF ;ALWAYS.

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

                      (B101)   LDA (A4L),Y  ;Get trk number part of data sector pair.
                      (B103)   BNE RDDATSEC ;Go read in the data sector.
          
                      * The track number part of the data sector
                      * pair listed in the T/S list was zero.
                      * Therefore, there are no more data sector
                      * pairs described in this T/S list.
                      (B105)   LDA OPCODEFM ;Check to see if writing or not.
                               CMP #4       ;Opcode for write.
                               BEQ NEWPAIR  ;Branch if writing.
                               SEC          ;Not writing and ran out of data sector pairs
                      (B10D)   RTS          ;in the present T/S list, so go exit with
                               ============ ;carry set to signal no more data.

                      * The data sector pair associated with the
                      * data sector wanted was contained in the
                      * current T/S list, so now read in the data
                      * sector wanted.
                      (B114)
                      RDDATSEC STA CURDATRK ;Save trk/sec values of current data sector
                               INY          ;in the work area.
                               LDA (A4),Y   ;Sector number of current data sector.
                               STA CURDATSEC
                      (B11D)   JSR READDATA ;Go read in the data sector.

                                            * Read data sector from disk
                                            * to the data sector buffer.
                                            (AFDC)
                                            READDATA JSR PRPDAIOB ;Set up RWTS's IOB to read a data sector.

                                                                  * Prepare RWTS'S IOB to read/write
                                                                  * the data sector.
                                                                  (AFE4)
                                                                  PRPDAIOB LDY DATBUFFM ;Get the addr of the
                                                                           LDA DATBUFFM+1 ;data sec buf from
                                                                           STY IBBUFP   ;the FM parm list and
                                                                  (AFED)   STA IBBUFP+1 ;designate it as the I/O
                                                                                        ;buffer for RWTS's IOB.
                                                                  (AFF0)   LDX CURDATRK ;Enter RWTS driver with (x)/(y)
                                                                           LDY CURDATSC ;= trk/sec vals corresponding
                                                                  (AFF6)   RTS          ;to the data sector.

                                            (AFDF)   LDA #1       ;Opcode for RWTS's read command.
                                            (AFE1)   JMP RWTSDRVR ;Call RWTS driver to read the data sec buf.
                                                     ------------

                                            * Read/Write Track/Sector driver.
                                            (B052)
                                            RWTSDRVR .
                                                     .
                                            (See dis'mbly of RWTSDRVR using READ.)
                                                     .
                                                     .
                                                     (RTS)

                      * Save sector-offset-into-file value
                      * associated with the data sector just read.
                      (B120)
                      SETPREV  LDA FILPTSEC ;Current sector offset into file.
                               STA RELPREV  ;Offset into file of last data sector read.
                               LDA FILPTSEC+1
                      (B129)   STA RELPREV+1

                      * Exit the read-next-data-sector routine.
                      (B12C)
                      XITNXDAT JSR SELDABUF ;Select the data sector buffer.

                                            * Point A4L/H at the data sector buffer.
                                            (AF10)
                                            SELDABUF LDX #4       ;Index to select data sector buffer.
                                            PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from
                                                     STA A4L      ;the FM parameter list & put it in the
                                                     LDA WRKBUFFM+1,X ;A4L/H pointer.
                                                     STA A4L+1
                                            (AF1C)   RTS

                      (B12F)   LDY FILPTBYT ;(y) = offset into current data sector.
                               CLC          ;Exit cleanly.
                      (B133)   RTS
                               ============

(AD1E)   BCS TOOKFMXT ;END OF FILE DETECTED - exit file manager.
         INC FILPTSEC ;Kick up the file pointer position and then
         BNE VRFYREAD ;go back to read in the next data sector
         INC FILPTSEC+1 ;until an end-of-file marker is detected.
(AD28)   JMP VRFYREAD
         -------------

(AD0F)
TOOKFMXT JMP GOODFMXT ;Exit the file manager cleanly.
         ------------


* Exit the file manager with or without errors.
(B35F)
LNGNOTAV LDA #1
(B361)   BNE BADFMXIT ;ALWAYS.

(B373)
FILENOT  LDA #6
(B375)   BNE BADFMXIT ;ALWAYS.

(B377)
DISKFULL JMP FULLPTCH ;(See dis'mbly of errors.)
         ------------

(B37F)
GOODFMXT LDA RTNCODFM
         CLC          ;(c) =  0 to signal good operation.
         BCC FMEXIT
BADFMXIT SEC          ;(c) = 1 to signal unsuccessful.
FMEXIT   PHP          ;Save status on stack.
         STA RTNCODFM ;Store return code in FM parameter list.
         LDA #0
         STA STATUS
(B38E)   JSR CPYFMWA  ;Copy the work area to the work buffer.

                      * Copy the FM work area (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 select work buffer.
                                            (AF0A)   BEQ PT2FMBUF ;ALWAYS.

                                            (AF12)
                                            PT2FMBUF LDA WRKBUFFM,X ;Get address 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
                      ;from the stack.
(B392)   LDX STKSAV   ;Adjust stack pointer to force exit to the
         TXS          ;caller of the function (even if we are
(B396)   RTS          ;presently several subroutines deeper than
         ============ ;the original entry point).  (Returns to
                      ;AFTRFUNC ($A6AB) in the FMDRIVER routine
                      ;($A6A8).)
