*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
*                                                                *
*                        LOCK AND UNLOCK                         *
*                       Function Handlers                        *
*                                                                *
*----------------------------------------------------------------*
*                                                                *
*      The LOCK and UNLOCK function handlers ($ACEF & $ACF6)     *
* set the lock/unlock mask (LOKUNMSK, $B39E) with $80 (lock)     *
* or $00 (unlock) and the call the COMNOPEN routine ($AB28)      *
* to locate the desired file.  COMNOPEN configures the FM work   *
* area and then searches the directory sectors for a file        *
* description containing the name of the wanted file.  (The      *
* links to the first directory sector are housed in the VTOC.    *
* Each subsequent directory contains the links to the next       *
* directory sector.  The link bytes of the last directory sector *
* are zeroed out.)                                               *
*      Each directory contains up to seven different file        *
* descriptions.  An example of the information contained in a    *
* file description is shown below:                               *
* FIL1TSTK  DS 1      ;Track # of first T/S list for file 1.     *
* FIL1TSSC  DS 1      ;Sector # of first T/S list for file 1.    *
* FIL1TYPE  DS 1      ;File type code for file 1.  ($00=Text,    *
*                     ;$01=Integer, $02=Applesoft, $04=Binary,   *
*                     ;$08=S-type, $10=Relocatable, $20=A-type   *
*                     ;and $40=B-type.)  The hi bit is set on    *
*                     ;locked files.  For example, $02=unlocked  *
*                     ;Applesoft and $82=locked Applesoft.       *
* FIL1NAME  DS 30     ;Name of file 1.  If a file name less than *
*                     ;30 bytes is used, trailing spaces are     *
*                     ;added to the name to fill the buffer.     *
* FIL1SIZE  DS 2      ;Size of file 1 in terms of the number of  *
*                     ;sectors used.                             *
* (If a file was deleted, the track # of the file's first T/S    *
* list was copied to the last byte position of the name field.   *
* The original track # byte (FIL1TSTK) was then overwritten with *
* an #$FF.)                                                      *
*      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, 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.                                            *
*      If an available space is located, NEWDSCRP ($B2C1) 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 bit0   *
* of the first attribute bytes of both the LOCK and UNLOCK       *
* commands are clear, neither command can create a new file.  As *
* a result, the LOCK or UNLOCK commands are exited with a file-  *
* not-found error.                                               *
*      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.  Eventhough it is not needed for either the LOCK or      *
* UNLOCK functions, the first T/S list belonging to the wanted   *
* file is read in (READTS, $A5FE).                               *
*      Next, the accumulator is loaded with the file type code   *
* from the file description.  The hi bit of the code is dropped  *
* by ANDing the accumulator with #$7F.  The result is then       *
* merged with the LOKUNMSK to set (lock) or clear (unlock) the   *
* hi bit.  Finally, the updated file type code is put back into  *
* the file description.                                          *
*      After WRDIRECT ($B037) is called to write the modified    *
* directory sector back to the disk, execution returns to the    *
* LOCK or UNLOCK command handler.                                *
*                                                                *
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*


* Lock Function Handler.
(ACEF)
FNLOCK   LDA #$80     ;Set hi bit in lock/unlock mask.
         STA LOKUNMSK
(ACF4)   BNE COMNLOCK ;ALWAYS.

Unlock Function Handler.
(ACF6)
FNUNLOCK LDA #0       ;Make sure hi bit is clear in the LOKUNMSK.
(ACF8)   STA LOKUNMSK

* Routine common to lock/unlock functions.
(ACFB)
COMNLOCK JSR COMNOPEN ;Locate a file with the same name & open it.

                      *** NOTE ***
                      * Not all of the common open routine is
                      * listed below because not all of it
                      * applies to the lock/unlock functions.

                      * 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 are just as relevant
                                            * as non-zero values.)
                                            * (P.S.  Don't confuse the 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.
                                            (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.
                                            (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.
                                            (B1EF)   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 in 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 first search,
                                            * go back to do 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 the search counter if
                                                                  ;go back to start a second search.
                                            (B23C)   LDY SCRNSRCH ;(1 = search1, 0 = search2)
                                                     BNE SETSRCH  ;Just did 1rst search so go start 2nd search.
                                            (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.

                      * 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 FOR LOCK/UNLOCK FUNCTIONS (cause (c) = 0).

                      * 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)   ------------

                      **************** NOTE *************************
                      * Although it is not needed for the lock/unlock
                      * functions, the first T/S list sector is automatically
                      * read into the T/S list buffer (in chain) if the
                      * file was found.

                      * 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
                               STX 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 ;Dictate 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   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
                                                     BMI WRITETS  ;If bit 7 set, updating is required.
                                            (AF39)   RTS          ;BRANCH NOT APPLICABLE TO THE LOCK/UNLOCK FUNCTIONS.
     

                      (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.
                                            ;ALWAYS FALL THRU WITH LOCK/UNLOCK FUNCTIONS (cause (c)=0).

                      * 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.
                               ------------

                      * Subroutine to read/write 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.)
                                                     .
                                                     .
                                                     (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 described in this
                                            ;T/S list.
                      (AFC7)   CLC          ;Add the maximum # of data secs that
                               ADC MXSCURTS ;can be described in this T/S list ($7A, #122).
                               STA RELASTP1 ;Store relative sector number (plus 1) of
                               INY          ;the last data sector described in list.
                               LDA (A4L),Y
                               STA RELFIRST+1
                               ADC MXSCURTS+1
                               STA RELASTP1+1 ;(RELASTP1/+1 is always set to $007A by FNOPEN.)
                               CLC          ;Return with "no error" signal.
                      (AFDB)   RTS
                               ============

(ACFE)   LDX CURDIRNX ;(x) = index to file description entry
                      ;in the directory sector buffer.
(AD01)   LDA FIL1TYPE,X ;Get old file type.
         AND #$7F     ;Shut hi bit off.
(AD06)   ORA LOKUNMSK ;Merge with LOKUNMSK to set (lock) or clear
                      ;(unlock) the hi bit.
(AD09)   STA FIL1TYPE,X ;Stick modified file type back into the
                      ;file description part of the directory
                      ;sector buffer.
(AD0C)   JSR WRDIRECT ;Write the updated directory sec buf to disk.

                      * Write the directory buffer.
                      (B037)
                      WRDIRECT JSR PT2DIRBF

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

                      (B03A)   LDX CURDIRTK ;Enter RWTS driver with (x)/(y) = trk/sec vals.
                               LDY CURDIRSC
                               LDA #2       ;Write opcode for RWTS.
                      (B042)   JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer.
                               ------------

                      (B052)
                      RWTSDRVR .
                               .
                      (See dis'mbly of RWTS driver using WRITE.)
                               .
                               .
                               (RTS)

(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 handler even if we
(B396)   RTS          ;are several subroutines deeper than the
         ============ ;original entry point.  (That is, return
                      ;to AFTRFUNC ($A6AB) in the FMDRIVER routine
                      ;($A6A8).)
