💾 Archived View for spam.works › mirrors › textfiles › apple › ANATOMY › psnwrrng.txt captured on 2023-06-16 at 21:11:41.

View Raw

More Information

-=-=-=-=-=-=-





(AC70)                                                                 * WRITE subfunction entry point table.
FNWRITE  LDA FILTYPWA ;Check if file is locked.                        * (P.S.  Subfunctions with the position option
         BMI TOFILOCK ;Error - can't write to a locked file.           * are available to the user, but never
         LDA SUBCODFM ;Check if subcode is legal.                      * called by DOS.)
         CMP #5       ;(Must be < = 5.)                                (AAF1)                 ;Index to subfunction.
         BCS TOERRSUB ;Error - illegal subcode.                        WRSUBTBL DA GOODFMXT-1 ;(0), Exit.
         ASL          ;Subcode * 2, cause 2 bytes/address.                      DA WRITEONE-1 ;(1), Write one byte.
         TAX          ;Index table of subfunction addresses.                    DA WRITERNG-1 ;(2), Write a range of bytes.
         LDA WRSUBTBL+1,X ;Get address (minus 1) of subfunction                 DA PSNWRONE-1 ;(3), Position and write one byte.
         PHA          ;entry point and stick it on the stack                    DA PSNWRRNG-1 ;(4), Pos'n & write range of bytes.
         LDA WRSUBTBL,X ;(hi byte first).  Then do a "stack jump"       (AAFB)  DA GOODFMXT-1 ;(5), Exit.
         PHA          ;to execute the given WRITE subfunction.
(AC69)   RTS



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

(AC6D)   ------------
TOFILOCK JMP FILELOKD ;Go print file-locked message.
         ------------ ;(See dis'mbly of errors.)





(ACC7)
PSNWRRNG JSR CALCFPTR ;Using R-, L-, & B-parameters, calculate
                      ;the position of the file pointer.

                      * Calculate the exact position of the three-byte file pointer:
                      *        FILPTSEC = sector offset (low/hi format) into entire file (2 bytes).
                      *        FILPTBYT = byte offset into current sector (1 byte).
                      * All three bytes define the exact position of the file pointer
                      * via the following formula:
                      *        (record number * record length) + byte offset into record
                      *        where:  RECNMBFM = record number from R-parameter (set
                      *                           by user when using random access files
                      *                           or simply incremented when using other
                      *                           file types).
                      *                RECLENWA = record length parsed from L-parameter
                      *                           and assigned with open command (else
                      *                           defaulted to a size of 1).
                      *                BYTOFFFM = offset into the current record (set by
                      *                           user when using open command or
                      *                           occassionally used with sequential files
                      *                           as a B-parameter).
                      * Note that you can actually directly access any byte in any
                      * file by bypassing the command interpreter and setting the
                      * L-, B- & R-parameters however you want.

                      (B300)
                      CALCFPTR LDA RECNMBFM ;Put record # in multiplier and
                               STA FILPTBYT ;also save it in the work area.
                               STA RECNMBWA
                               LDA RECNMBFM+1
                               STA FILPTSEC
                               STA RECNMBWA+1
                               LDA #0       ;Zero out the hi order byte of the sector
                      (B314)   STA FILPTSEC+1 ;offset into the file.

                      * Calculate: Record number *  record length.
                      * This routine simply multilplies two 16-bit
                      * numbers together.  It may at first seem
                      * a bit confusing because FILPTSEC & FILPTBYT
                      * are used both for holding the multiplier
                      * (record #) and part of the product result.
                      * However, the bits of the product don't get mixed
                      * up with the bits of the multiplier because rolling
                      * in a product bit also rolls out the last-used
                      * multiplier bit (ie., there is no bit overlap).
                      (B317)   LDY #16      ;16 bits / one 2-byte number.
                      NMBXLEN  TAX          ;Save part of running product.
                                            ;(On first entry, set (x) = 0).
                               LDA FILPTBYT ;Set (a) = multiplier.
                               LSR          ;Put multiplier bit in carry.
                               BCS NMBXLEN1 ;If (c)=1, go add multiplicand to running product.
                               TXA          ;(a) = part of running product.
                               BCC NMBXLEN2 ;Always branch.  No use adding multiplicand cause
                                            ;bit in multiplier is a 0.  Therefore, just go shift
                                            ;running product.
                      NMBXLEN1 CLC          ;Add multiplicand to running version of shifted product.
                               LDA FILPTSEC+1
                               ADC RECLENWA
                               STA FILPTSEC+1
                               TXA          ;Set (a) = low byte of running product.
                               ADC RECLENWA+1
                      NMBXLEN2 ROR          ;Shift the running product (as a unit) 1 bit
                               ROR FILPTSEC+1 ;right for next time around.
                               ROR FILPTSEC ;Shift lower 2 bytes of running product and
                               ROR FILPTBYT ;at the same time throw out the last-used
                                            ;multiplier bit.
                               DEY          ;Reduce bit counter.
                      (B33C)   BNE NMBXLEN  ;Branch if haven't done all 16 bits yet.

                      * Copy byte offset into record from
                      * the FM parameter list to the work area.
                      (B33E)   CLC
                               LDA BYTOFFFM
                      (B342)   STA BYTOFFWA

                      * Calculate lowest order byte of file pointer
                      * BYTOFFWA =  offset into current record.
                      *          = byte offset into record
                      *            + (record length *  record  number).
                      (B345)   ADC FILPTBYT
                               STA FILPTBYT
                               LDA BYTOFFFM+1
                               STA BYTPFFWA+1
                               ADC FILPTSEC
                               STA FILPTSEC
                               BCC CALCRTS
                               INC FILPTSEC+1
                      CALCRTS  RTS
                      (B35C)





(ACCA)
WRITERNG JSR INCIOBUF

                      * Point A4L/H at the current data source
                      * memory location (CURIOBUF) for writing.
                      * Also increment the source location for
                      * next time around.
                      (B1A2)
                      INCIOBUF LDY CURIOBUF ;Get adr of source location.
                               LDX CURIOBUF+1 ;from the FM parameter list.
                               STY A4L
                               STX A4L+1
                               INC CURIOBUF ;Kick up address of source location.
                               BNE INCIORTN
                               INC CURIOBUF+1
                      INCIORTN RTS
                      (B1B4)

(ACCD)   LDY #0       ;Set (y) for indirect addressing of source buf.
         LDA (A4L),Y  ;Get byte to write.
(ACD1)   JSR WRTDATA  ;Put data byte in data sector buffer.
                      ;(Write data sector buffer to disk if necessary.)

                      * Subroutine which writes data.
                      (ACDA)
                      WRTDATA  PHA          ;Save byte to write on stack.
                      (ACDB)   JSR NXTDATRD ;Read next data sector into the data
                                            ;sector buffer if necessary.

                                            * Note:  The write data SUBFUNCTIONS may seem strange because
                                            * they don't necessarily write data bytes to the disk.  All they
                                            * really do is store data in the data sector buffer (in the DOS
                                            * buffer chain).  If single data bytes are added repeatedly, the
                                            * data sector buffer fills up (at which point FILPTSEC  < >
                                            * RELPREV).  If this happens, the data bit in the update flag
                                            * (UPDATFLG) will also be set.  When these two criteria are met,
                                            * the WRITDATA routine in the NXTDATRD subroutine is used to
                                            * write the data sector buffer to the disk.  If the subfunction is
                                            * exited when the data sector buffer is not full but the UPDATFLG
                                            * is on, the data sector buffer is written to the disk by the
                                            * CLOSE function.

                                            * Read data sector if necessary.
                                            *
                                            * Check if need to read next data sector
                                            * buffer into the data sector buffer.
                                            *
                                            * - Is data sector 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 & there4 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 forces reading
                                            *          of new data sector even if the correct
                                            *          sector is already in memory.
                                            (B0B6)
                                            NXTDATRD LDA FILPTSEC ;Last sector used versus sector wanted?
                                                     CMP RELPREV
                                            (B0BC)   BNE CKWCURDA ;Not same - will eventualy have to read in
                                                                  ;a new data sector.
                                            (B0BE)   LDA FILPTSEC+1 ;Maybe same - check hi bytes.
                                                     CMP RELPREV+1
                                            (B0C4)   BEQ XITNXDAT ;Same so go exit.

                                            * Write data sector if necessary.
                                            * Data sector we want is not presently
                                            * in memory.  Check if need to write
                                            * current data sector buffer before we
                                            * read in the wanted data sector.
                                            (B0C6)
                                            CKWCURDA JSR CKDATUP  ;Check 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 data sector buffer has changed
                                                                  * since the last read or write was done.
                                                                  (AF1D)
                                                                  CKDATUP  BIT UPDATFLG ;Check bit 6 to see if data sector
                                                                                        ;buffer requires updating.
                                                                  (AF20)   BVS WRITDATA ;Take branch if data requires updating.
                                                                  (AF22)   RTS
                                                                           ============

                                                                  * Write present data sector buffer to the disk.
                                                                  * Updates disk so can read in next data sector
                                                                  * without overwriting and therefore losing
                                                                  * previous data that hasn't yet been updated
                                                                  * on the  disk.
                                                                  (AF23)
                                                                  WRITDATA JSR PRPDAIOB

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

                                                                  (AF26)   LDA #2       ;Opcode for RWTS's write command.
                                                                  (AF28)   JSR RWTSDRVR ;Call driver to write data sector buf.

                                                                                        * Read/write track/sector driver.
                                                                                        (B052)
                                                                                        RWTSDRVR .
                                                                                                 .
                                                                                        (See dis'mbly of RWTSDRVR using WRITE.)
                                                                                                 .
                                                                                                 .
                                                                                                 (RTS)
         
                                                                  (AF2B)   LDA #%10111111 ;Shut bit 6 off in the update flag to
                                                                           AND UPDATFLG ;signal that the data sector buffer is
                                                                           STA UPDATFLG ;now up to date.
                                                                  (AF33)   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 
                                            * 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 into file associated with
                                            (B0CC)   CMP RELFIRST+1 ;the present data sector versus the
                                                                  ;relative sector number of the 1rst data
                                                                  ;sector that can be described in the present
                                                                  ;T/S list.
                                            (B0CF)   BCC NEEDNXTS ;Data sector wanted represents a SMALLER
                                                                  ;offset into file so need a different T/S list.
                                                                  ;(Start by reading file's first 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 file is LESS,
                                                                  ;so read in a different list.
                                                                  ;(Start by reading file's first T/S list.)
      
                                            * Sector offset associated with the data
                                            * sector wanted 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
                                                                  ;want 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.

                                                                  * Writes old T/S list to disk if necessary
                                                                  * & reads in next T/S list.  If there is no next
                                                                  * T/S list then a new trk/sec pair is allocated
                                                                  * & the old T/S list is linked to the new T/S list.
                                                                  * Also updates ASIGNTRK, UPDATFLG, CURTSTRK,
                                                                  * CURTSSEC, RELFIRST, RELASTP1, FM parameter list, etc.
                                                                  * 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 loose information when read the new
                                                                                        ;T/S list sector.)

                                                                                        * Check if T/S list requires updating.
                                                                                        * (i.e. Has T/S list buf changed since
                                                                                        * the last read or write?)
                                                                                        (AF34)
                                                                                        CKTSUPDT LDA UPDATFLG ;If bit 7 set,
                                                                                                 BMI WRITETS  ;updating required.
                                                                                        (AF39)   RTS
                                                                                                 ============

                                                                                        * Write the T/S list buffer.
                                                                                        (AF3A)
                                                                                        WRITETS  JSR SETTSIOB ;Prep 4 WRITING the
                                                                                                              ;T/S list buffer.

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

                                                                                        (AF3D)   LDA #2       ;Write opcode 4 RWTS.
                                                                                        (AF3F)   JSR RWTSDRVR ;Call driver to write
                                                                                                              ;the T/S list sector.

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

                                                                                        (AF42)   LDA #$7F     ;Clr bit7 of update
                                                                                                 AND UPDATFLG ;flag to signal that
                                                                                                 STA UPDATFLG ;T/S list sec is up
                                                                                        (AF4A)   RTS          ;to date.
                                                                                                 ============

                                                                  (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
                                                                                                 STA IBBUFP   ;list buf from the
                                                                                                 LDA TSBUFFM+1 ;FM parameter list
                                                                                        (AF54)   STA IBBUFP+1 ;& designate T/S list
                                                                                                              ;buf as the I/O buf in
                                                                                                              ;RWTS's IOB.
                                                                                        (AF57)   LDX CURTSTRK ;Set (x)/(y) = trk/sec
                                                                                                 LDY CURTSSEC ;of current T/S list.
                                                                                        (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       ;Ndx for T/S list buf.
                                                                                        (AF0E)   BNE PT2FMBUF ;ALWAYS.

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

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

                                                                  * Read the 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 the file.
                                                                  (AF7A)   TAX          ;(x) = track # of next T/S list sector.
                                                                           INY
                                                                           LDA (A4L),Y  ;Sector for link to next T/S list sector.
                                                                           TAY          ;(y) = sec # of next T/S list sector.
                                                                  (AF7F)   JMP RDTSLST  ;Go read in the 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
                                                                           CMP #4       ;to add another T/S list or not.
                                                                           BEQ UPDATETS ;WRITING, so go update link.
                                                                           SEC          ;We were READING & the link zeroed out, so
                                                                  (AF8A)   RTS          ;return with (c) = 1 to signal that an
                                                                           ============ ;error occurred.  (Remember, we previously
                                                                                        ;set the return code to a default value
                                                                                        ;corresponding to a file-not-found error.)

                                                                  * Writing and link zeroed out, so
                                                                  * must assign a new T/S list sector.
                                                                  (AF8B)
                                                                  UPDATETS JSR ASGNTKSC ;Find and reserve trk/sec values
                                                                                        ;for a new T/S list sector.

                                                                                        * Asign trk/sec vals for a new T/S list.
                                                                                        (B244)
                                                                                        ASGNTKSC .
                                                                                                 .
                                                                                        (See formatted disassembly given in
                                                                                        the open function handler (FNOPEN).)
                                                                                                 .
                                                                                                 .
                                                                                                 (RTS)

                                                                  * Link the new T/S list sector to
                                                                  * the last T/S list sector and then
                                                                  * write the updated version of the
                                                                  * last T/S list sector to the disk.
                                                                  (AF8E)
                                                                  LNKOLDNW LDY #2       ;Offset to sector portion of link.
                                                                           STA (A4L),Y  ;Put new sector value in link.
                                                                           PHA          ;Also save it on the stack.
                                                                           DEY          ;Offset to trk portion of link.
                                                                           LDA ASIGNTRK ;Put new trk value in link.
                                                                           STA (A4L),Y
                                                                           PHA          ;Also save trk value on the stack.
                                                                  (AF9A)   JSR WRITETS

                                                                                        * Write the T/S list buffer.
                                                                                        (AF3A)
                                                                                        WRITETS  JSR SETTSIOB ;Prep 4 WRITING the
                                                                                                              ;T/S list buffer.

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

                                                                                        (AF3D)   LDA #2       ;Write opcode 4 RWTS.
                                                                                        (AF3F)   JSR RWTSDRVR ;Call driver to write
                                                                                                              ;the T/S list sector.

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

                                                                                        (AF42)   LDA #$7F     ;Clr bit7 of update
                                                                                                 AND UPDATFLG ;flag to signal that
                                                                                                 STA UPDATFLG ;T/S list sec is up
                                                                                        (AF4A)   RTS          ;to date.

                                                                  * Set up a brand new T/S list sector
                                                                  * and write it to the disk.
                                                                  (AF9D)
                                                                  ZOUTTS   JSR ZCURBUF  ;Zero out the T/S list buffer.

                                                                                        * Zero out the current 256-byte buffer.
                                                                                        (B7D6)
                                                                                        ZCURBUF  LDA #0
                                                                                                 TAY
                                                                                        ZCURBUF1 STA (A4L),Y
                                                                                                 INY
                                                                                                 BNE ZCURBUF1
                                                                                        (B7DE)   RTS

                                                                  (AFA0)   LDY #5       ;At offsets 5 & 6 into the new T/S list
                                                                           LDA RELASTP1 ;put the relative sector number (in
                                                                           STA (A4L),Y  ;relation to the entire file) of the FIRST
                                                                           INY          ;data sector pair that will described in
                                                                           LDA RELASTP1+1 ;this new T/S list.  (Possible values:
                                                                           STA (A4L),Y  ;$007A, 2*$007A, 3*$007A and 4*$007A.)
                                                                           PLA          ;Get trk/sec values (x/y) of this new
                                                                           TAX          ;T/S list sector off of the stack.
                                                                           PLA
                                                                           TAY
                                                                           LDA #2       ;Write opcode for RWTS.
                                                                  (AFB3)   BNE RDWRTS   ;ALWAYS - go write the T/S list sector.

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

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

                                                                                        * Read or write the current T/S list.
                                                                                        (B052)
                                                                                        RWTSDRVR .
                                                                                                 .
                                                                                        (See formatted 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
                                                                  (AFC4)   STA RELFIRST ;of the first data sector that can be
                                                                                        ;described in this T/S list.  (Value
                                                                                        ;equals $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.
                                                                  ;ALWAYS TAKE THIS BRANCH WHEN WRITING.
                                            (B0F2)   RTS          ;Return with (c)=1 to signal potential error
                                                     ============ ;cause ran out of t/s lists while READING.

                                            * 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 in 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 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
                                                     BEQ NEWPAIR  ;ALWAYS BRANCH WHEN 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 potential error.

                                            * Since we ran out of data sector pairs
                                            * while writing, we must add a new data
                                            * pair to the T/S list.
                                            (B10E)
                                            NEWPAIR  JSR NWDATKSC ;Add a new data sector pair to the T/S list.
                                                                  ;Zero out the data sector buffer and set the
                                                                  ;update flag to signal that both the T/S
                                                                  ;list sector and data sector require updating.

                                                                  * Designate trk/sec values for new data
                                                                  * sector and add new data sector pair
                                                                  * to the T/S list.
                                                                  (B134)
                                                                  NWDATKSC STY SCRNSRCH ;Save offset to data pair in T/S list.
                                                                  (B137)   JSR ASGNTKSC ;Find and deisgnate an available sector.

                                                                                        (B244)
                                                                                        ASGNTKSC .
                                                                                                 .
                                                                                        (See complete formatted dis'mbly
                                                                                        given in the OPEN function.)
                                                                                                 .
                                                                                                 .
                                                                                                 (RTS)

                                                                  (B13A)   LDY SCRNSRCH ;Retrieve offset to data pair.
                                                                           INY
                                                                           STA (A4L),Y  ;Put sector value in the T/S list
                                                                           STA CURDATSC ;and in the work area.
                                                                           DEY
                                                                           LDA ASIGNTRK ;Put track value in the T/S list
                                                                           STA (A4L),Y  ;and in the work area.
                                                                           STA CURDATRK
                                                                  (B14C)   JSR SELDABUF ;Go select the data sector buffer.

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

                                                                  (B14F)
                                                                  ZOUTDAT  JSR ZCURBUF  ;Zero out the data sector buffer.

                                                                                        * Zero out all 256 bytes of the current
                                                                                        * buffer pointer to by the A4L/H pointer.
                                                                                        (B7D6)
                                                                                        ZCURBUF  LDA #0
                                                                                                 TAY
                                                                                        ZCURBUF1 STA (A4L),Y
                                                                                                 INY
                                                                                                 BNE ZCURBUF1
                                                                                        (B7DE)   RTS

                                                                  (B152)   LDA #%11000000 ;Set both bits 6 & 7 in flag to
                                                                           ORA UPDATFLG ;signal that both the data & T/S list
                                                                           STA UPDATFLG ;sectors require updating.
                                                                  (B15A)   RTS

                                            * Note:  If your follow this jump through,
                                            * you may realize that sometimes we eventually
                                            * exit the present function without writing
                                            * the T/S list and data sector buffers back
                                            * to the disk.  However, after the subfunction
                                            * is exited, the CLOSE function eventually tests the
                                            * status of the update flag (UPDATFLG, $B5D5) and then
                                            * writes the T/S list and data sector buffers back to
                                            * the disk.
                                            (B111)   JMP SETPREV
                                                     -----------


                                            * 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 (A4L),Y  ;Sector number of current data sector.
                                                     STA CURDATSC
                                            (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 addr of data
                                                                                                 LDA DATBUFFM+1 ;sec buf from
                                                                                                 STY IBBUFP   ;the FM parm list
                                                                                        (AFED)   STA IBBUFP+1 ;& designate it
                                                                                                              ;as the I/O buffer
                                                                                                              ;for RWTS's IOB.
                                                                                        (AFF0)   LDX CURDATRK ;Enter driver with
                                                                                                 LDY CURDATSC ;(x)/(y) = trk/sec
                                                                                        (AFF6)   RTS          ;vals corresponding
                                                                                                              ;to the data sector.

                                                                  (AFDF)   LDA #1       ;Read opcode for RWTS.
                                                                  (AFE1)   JMP RWTSDRVR ;Call RWTS driver to read the data sector.
                                                                           ------------

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

                      (ACDE)   PLA          ;Get data byte to write off the stack.
                               STA (A4L),Y  ;Put data byte in the data sector buffer.
                               LDA #%01000000 ;Set bit 6 to signal that the data sector
                               ORA UPDATFLG ;buffer has changed and therefore, the disk
                               STA UPDATFLG ;requires updating.
                      (ACE9)   JSR INCREC   ;Either increment the record number or
                                            ;increment the byte offset into the record.

                                            * Adjust record number or byte offset
                                            * into a given record.
                                            *
                                            * This routine is used both when reading
                                            * and writing.  The pattern of execution
                                            * varies with the structure of the file.
                                            * However, some files are treated as if
                                            * they have one type of structure when
                                            * they are read and another type of
                                            * structure when they are being written:
                                            * - random access text files have a fixed
                                            *   record length assigned by the user.
                                            * - sequential text & Applesoft files
                                            *   have a record length of one.
                                            * - during a LOAD or BLOAD, Applesoft or
                                            *   Binary files are considered to be 
                                            *   composed of a collection of one-byte
                                            *   long records.
                                            * - when SAVEing or BSAVEing however, these
                                            *   files are treated as if they consist of
                                            *   one long record.

                                            * Copy the record number from the work
                                            * area to the FM parameter list.
                                            (B15B)
                                            INCREC   LDX RECNMBWA ;Get the current record number.
                                                     STX RECNMBFM ;Store it in the FM parameter list.
                                                     LDX RECNMBWA+1
                                            (B164)   STX RECNMBFM+1

                                            * Copy the current byte offset into the record
                                            * from the work area to the FM parameter list.
                                            (B167)   LDX BYTOFFWA ;Get offset into record from work area.
                                                     LDY BYTOFFWA+1
                                                     STX BYTOFFFM ;Store it in the FM parameter list.
                                            (B170)   STY BYTOFFFM+1

                                            * Increment the byte offset into the record.
                                            * If it equals the record length, then reset
                                            * the offset to zero and kick up the record
                                            * number.
                                            (B173)   INX
                                                     BNE BYTVSREC
                                                     INY
                                            BYTVSREC CPY RECLENWA+1 ;Fixed value via OPEN command, else
                                            (B177)                ;L-parameter via SAVE or BSAVE command (from work area).
                                            (B17A)
                                            KIKOFF1  BNE SETBYTOF
                                                     CPX RECLENWA
                                            KIKOFF2  BNE SETBYTOF
                                                     LDX #0       ;Offset into record was the same as the
                                            (B183)   LDY #0       ;record length so prepare to reset the
                                                                  ;offset into the record to zero.
                                            (B185)   INC RECNMBWA
                                            NOKIKOFF BNE SETBYTOF
                                            (B18A)   INC RECNMBWA+1

                                            * On fall through or entry from NOKIKOFF,
                                            * reset the offset into the record to zero.
                                            * On branched entry from KIKOFF1 or KIKOFF2,
                                            * increment the offset into the record.
                                            (B18D)
                                            SETBYTOF STX BYTOFFWA
                                                     STY BYTOFFWA+1
                                            (B193)   RTS

                      (ACEC)   JMP INCFILPT
                               ------------

                      * Increment byte offset into current data
                      * sector.  If at the end of the sector,
                      * then increment the offset into the entire file.
                      (B194)
                      INCFILPT INC FILPTBYT ;Kick up offset into sector.
                               BNE INCPTRTN ;Branch if not at end of current sector.
                               INC FILPTSEC ;Offset into sector wrapped around cause
                      (B19C)   BNE INCPTRTN ;at end of sector, so kick up offset into
                                            ;entire file.
                      (B19E)   INC FILPTSEC+1 ;Increment hi byte if necessary.
                      INCPTRTN RTS
                      (B1A1)

(ACD4)   JSR DECRWLEN ;Check if done writing.
                      ;If not, reduce byte counter.

                      * Reduce count of number of bytes left to write.
                      * (When counter equals zero, exit the file manager.)
                      (B1B5)
                      DECRWLEN LDY LEN2RDWR ;Length to read or length-1 left to write
                                            ;(from FM parameter list).
                      (B1B8)   BNE DECLENRW ;More bytes to read or write.
                               LDX LEN2RDWR+1 ;Low byte was zero, check hi byte.
                               BEQ RWLEN0   ;Counter = 0, so done read/write.
                               DEC LEN2RDWR+1
                      DECLENRW DEC LEN2RDWR ;Reduce counter.
                      (B1C5)   RTS
                               =============

                      (B1C6)
                      RWLEN0   JMP GOODFMXT ;Done read/write so go exit the file manager.
                               ------------

(ACD7)   JMP WRITERNG ;Go back to write next data byte.
         ------------



(B367)
RNGERRSB LDA #3
(B369)   BNE BADFMXIT ;ALWAYS.

(B37B)
FILELOKD LDA #10
(B37D)   BNE BADFMXIT ;ALWAYS.

(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       ;Avoid that infamous $48 bug.
         STA STATUS
(B38E)   JSR CPYFMWA  ;Copy work area to the work buffer.

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

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

                                            (AF12)
                                            PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
                                                     STA A4L      ;FM parameter list and put it in the pointer.
                                                     LDA WRKBUFFM+1,X
                                                     STA A4L+1
                                            (AF1C)   RTS
     
                      (AE81)   LDY #0       ;Initialize index.
                      STORWRK  LDA FMWKAREA,Y ;Get byte from the FM work area.
                               STA (A4L),Y  ;Put it in the work buffer.
                               INY
                               CPY #45      ;45 bytes to copy (0 to 44).
                               BNE STORWRK
                      (AE8D)   RTS

(B391)   PLP          ;Retrieve status of success of operation
                      ;back from the stack.
(B392)   LDX STKSAV   ;Adjust the stack  pointer to force exit
         TXS          ;to the caller even if several subroutines
(B396)   RTS          ;deeper than original entry point. (That is,
         ============ ;normally returns to AFTRFUNC ($A6AB)
                      ;located in the FMDRIVER routine ($A6A8).)