*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::* * * * VERIFY function handler * * * *----------------------------------------------------------------* * * * The verify function simply opens & then "reads" a file. * * Actual verification occurs deep within RWTS. As the data are * * read, a checksum is calculated. If the calculated checksum * * agrees with the checksum byte read off the disk, the integrity * * of the data are verified. Failure to verify yeilds an I/O * * error. * * * * Execution pattern: * * FNVERIFY ($AD18) first calls the common open routine * * COMNOPEN ($AB28) to locate and then open the named file. * * COMNOPEN configures the FM work area, reads in a fresh VTOC * * and then searches the directory sectors for the file * * description entry of the wanted file. (The links to the first * * directory sector are stored as the 2nd and 3rd bytes (offsets * * $01 and $02) of the VTOC. The 2nd and 3rd bytes of each * * subsequent directory sector contain the trk and sec values of * * the next directory sector. The link bytes of the last * * directory sector are zeroed out.) * * As each directory sector is read in, an attempt is made * * to locate a file description which contains the name of the * * file wanted. If the name can't be located after searching all * * the directories and if the VERIFY command was used by itself, * * a second search is made to locate the first available space in * * a directory sector where a new file description can be placed * * (in case the command can create a new file). If no free space * * is located, a disk-full error message is printed. (When the * * VERIFY command is accessed via the INIT, SAVE or BSAVE * * commands, no second search is done because these previous * * commands would have already created a new file entry if * * necessary.) * * If an available space is located, NWDESCRP ($B21C) copies * * the name of the wanted file from the primary file name buffer * * (PRIMFNBF, $AA75) into the new entry space. A check is then * * made to see if the command can legally create a new file. The * * identifying command byte (NDX2CMD, $AA5F) is used to index a * * table of command attributes (CMDATTRB, $A909). Because bit 0 * * of the first attribute byte associated with the VERIFY command * * is clear, a new file cannot legally be created. As a result, * * the VERIFY command is exited with a file-not-found message. * * If a (non-deleted) description entry containing the name * * of the wanted file is located, execution branches to the * * FILLINWA routine ($ABA6). FILLINWA uses the information * * contained in the description entry to customize the FM work * * area. After the carry is cleared execution jumps to the * * READTS routine ($AF5E). Because the carry was just cleared, * * READTS reads in the file's first T/S list sector. * * Execution then returns to the FNVERIFY routine at * * VRFYREAD ($AD1B). VRFYREAD in turn calls NXTDATRD ($BOB6) to * * read the file's data sectors into the data sector buffer. * * The execution patterns associated with NXTDATRD and its * * associated subroutines can be difficult to trace because so * * many flags are envolved. Unfortunately these flags are an * * evil necessity because NXTDATRD is called by almost any DOS * * command that reads or writes disk data. A description of the * * flags and possible execution patterns that can be taken by * * NXTDTRD when called from the VERIFY command are shown below: * * * * Major decisions and flags used: * * Use current data sector? * * - yes = FILPTSEC/+1 = RELPREV/+1 * * - no = FILPTSEC/+1 < > RELPREV/+1 * * - when a file is first opened, the common open * * routine (COMNOPEN, $AB28) sets FILPTSEC: $0000 * * and RELPREV: $007A. This forces the computer * * to try to use the file's first data sector. * * - when a data sector is filled by successively * * adding data byte, FILPTSEC/+1 > RELPREV/+1. * * - if the position function was used to adjust * * the filepointer out of the range of RELPREV, * * then FILPTSEC/+1 < > RELPREV/+1. * * Use current T/S list ? * * - yes = FILPTSEC/+1 > RELFIRST/+1 * * and FILPTSEC/+1 < RELASTP1/+1. * * - no = FILPTSEC/+1 < RELFIRST/+1 * * or FILPTSEC/+1 > = RELASTP1/+1. * * Update current data or T/S list sectors? * * - yes = bit 6 (data) or bit 7 (T/S list) of UPDATFLG * * ($B5D5) are set. * * - no = bits 6 and 7 of UPDATFLG are clear. * * Read first T/S list? * * - yes = (c) = 0 - carry cleared if file was just * * opened. File pointer was previously * * backed up by CALCFPTR ($B300). * * - no = (c) = 1 - file is long enough that another T/S * * list must be used. * * Writing data? * * - yes = OPCODEFM ($B105) = 4. * * - no = OPCODEFM < > 4. * * Any more data pairs listed in current T/S list? * * - yes = trk byte portion of data pair < > $00. * * - no = trk byte portion of data pair = $00. * * Any more T/S lists in file? * * - yes = trk byte portion of link < > $00. * * - no = trk byte portion of link = $00. * * (Link to first T/S list is contained in the first two * * bytes of the file description entry in the directory sec. * * Link to subsequent T/S lists are contained in 2nd and 3rd * * bytes (offsets $01 and $02) of previous T/S lists.) * * * * Note: RELPREV ($B5E0, $B5E1) * * = the relative sector number (in relation to * * the entire file) of the last data sector that * * was read or written. (Possible values are: * * $0000, $007A, 2*$007A, 3*$007A, 4*$007A.) * * RELFIRST ($B5DC, $B5DD) * * = the relative sector number (in relation to * * the entire file) of the first data sector * * that is (or can be) listed in the current * * T/S list. * * RELASTP1 ($B5DE, $B5DF) * * = one greater than the maximum relative sector * * number (in relation to the entire file) of * * the last data sector that can possibly be * * listed in the current T/S list. (Possible * * values are: $007A, 2*$007A, 3*$007A, 4*$007A * * and 5*$007A.) * * NXTDATRD execution patterns: * * Pattern 1: = FILPTSEC/+1 = RELPREV/+1 * * - select the current data sector. * * - exit NXTDATRD routine via XITNXDAT. * * Pattern 2: = FILPTSEC/+1 < > RELPREV/+1 * * = FILPTSEC/+1 > = NDXFIRST/+1 * * and FILPTSEC/+1 < RELASTP1/+1 * * = trk portion of data pair < > 0 * * - update the current data sector if necessary. * * 2a: - get valid link byte to the next data sector from * * the current T/S list. * * - read in the next data sector. * * - update RELPREV. * * - exit the NXTDATRD routine via XITNXDAT. * * Pattern 3: = FILPTSEC/+1 < > RELPREV/+1 * * = FILPTSEC/+1 > = RELFIRST/+1 * * and FILPTSEC/+1 < RELASTP1/+1 * * = trk portion of data pair = 0 * * = OPCODEFM < > 4 * * - update the current data sector if necessary. * * 3a: - detect zeroed out data pair in the current T/S * * list. * * - test OPCODEFM to determine that we are NOT * * writing and set the carry flag to signal just * * read all the data. * * - exit the NXTDATRD routine via XITNXDAT. * * Pattern 4: = FILPTSEC/+1 < > RELPREV/+1 * * = FILPTSEC/+1 < = RELFIRST/+1 * * = carry clear at $AF69 * * = trk portion of link byte to next T/S list < > 0 * * - update current data and/or T/S list secs if * * necessary. * * - get link to file's first T/S list from the file * * description entry in the current directory sec. * * - read in the first T/S list. * * - loop back to do 2a, 3a or 5. * * Pattern 5: = FILPTSEC/+1 < > RELPREV/+1 * * = FILPTSEC/+1 > = RELASTP1/+1 * * = carry set at $AF69 * * = trk portion of link to next T/S list < > 0 * * - update current data and/or current T/S list * * sectors if necessary. * * - get valid link bytes to the next T/S list from * * the current T/S list. * * - loop back to do 2a, 3a or repeat 5. * * Pattern 6: = FILPTSEC/+1 < > RELPREV/+1 * * = FILPTSEC/+1 > = RELASTP1/+1 * * = carry set at $AF69 * * = trk portion of link to next T/S list < > 0 * * = OPCODEFM < > 4 * * - update current data and/or current T/S list * * sectors if necessary. * * - get zeroed out link bytes to the next T/S list * * from the current T/S list. * * - test OPCODEFM to determine that we are NOT * * writing and set the carry flag to signal that * * we have just read all the data. * * - exit NXTDATRD the routine via XITNXDAT. * * * * If no errors are encountered, the NXTDATRD routine * * ($B0B6) is exited via XITNXDAT ($B12C). XITNXDAT points the * * A4L pointer ($42, $43) at the DOS data sector buffer and sets * * (y) to index that buffer. When an "RTS" is encountered, * * execution returns to $AD1E in the VRFYREAD routine. * * If this return is made with a set carry, all the data * * have been read and the verify function is exited via a branch * * to the TOOKFMXT ($AD0F). Otherwise, the file pointer is * * incremented and execution jumps back to the VRFYREAD routine * * ($AD1B) to "read" the next data sector. * * * *----------------------------------------------------------------* (AD18) FNVERIFY JSR COMNOPEN ;Locate file with the same name and open it. * Common open routine. (AB28) COMNOPEN JSR ZWRKAREA ;Initialize the work area. * Zero out the FM work area so it can be customized * in accordance with the calling function. * (Although some work bytes may not be subsequently * altered, don't be lulled into thinking that they * are not important. Zero values can be just as relevant * as non-zero values.) * (P.S. Don't confuse FM work area with its image * (FM work buffer) that is housed in the chain of * DOS buffers.) (ABDC) ZWRKAREA LDA #0 TAX ;Initialize the x-index. ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area. INX CPX #45 ;Work area is 45 bytes long. (ABE5) BNE ZEROWRKA * Begin customizing the work area. * Get volume, drive, slot & catalog track * values from the FM parameter list. Put * drive, slot*16, catalog track and * complemented volume number in the work area. (ABE7) LDA VOLFM ;Volume number. EOR #$FF ;Calculate 1's complement of volume #. STA VOLWA LDA DRVFM ;Drive #. STA DRVWA LDA SLOTFM ;Get slot #. ASL ;Calculate slot * 16. ASL ASL ASL TAX ;Set (x) = slot * 16. STX SLOT16WA LDA #$11 ;Normal catalog trk = #17. STA TRKWA (AC05) RTS (AB2B) LDA #1 ;Describe sector length as 256 bytes (AB2D) STA SECSIZWA+1 ;(in the FM work area). * Get record length from the FM parameter * list & put it in the FM work area. * (Don't allow a zero length. If zero, * change it to one.) (AB30) LDX RECLENFM+1 LDA RECLENFM BNE STRECLEN ;Non-zero record length is ok. CPX #0 BNE STRECLEN INX ;Was zero, make it one instead. STRECLEN STA RECLENWA ;Put length in FM work area. STX RECLENWA+1 (AB43) JSR GETFNTRY ;Try to find a directory sector for the file. * Locate or create a file entry in the * directory buffer. * Make two searches if necessary: * - Search1 - try to locate entry with same name as file wanted. * - Search2 - couldn't locate entry corresponding to file * wanted so create a new entry in first available * space in the directory sector. * Two searches are never required if the VERIFY cmd is * accessed via the INIT, SAVE, or BSAVE commands. * These calling commands would have previously * created a new file description if necessary. (B1C9) GETFNTRY JSR READVTOC ;Read in the VTOC so we can get the link to ;TRKMAPS & to the first directory sector. * Read the Volume Table of Contents (VTOC). (AFF7) READVTOC LDA #1 ;Read opcode for RWTS. (AFF9) BNE RDWRVTOC ;ALWAYS. * Code common to read/write VTOC. (AFFD) RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the STY IBBUFP ;FM constants table & designate it LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB. STY IBBUFP+1 LDX TRKWA ;Enter RWTS driver with (x)/(y) equal LDY #0 ;to the trk/sec values of the VTOC. (B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC. ------------ * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dism'bly of RWTS driver using READ.) . . (RTS) * Point A4L/H at the primary file name buffer. (B1CC) LDA FNAMBUFM ;Get address of the name buffer from the STA A4L ;FM parameter list & put it in the A4L/H LDA FNAMBUFM+1 ;pointer. (B1D4) STA A4L+1 * Try to find the directory sector with the * wanted file name & read it into the directory * sector buffer. Make two searches if necessary. * On the first search, try to find a matching name. * If that doesn't work, do a second search to store * the description in the first available file * description field in a directory sector. (B1D6) LDA #1 ;Initialize the search counter (SCRNSRCH) SETSRCH STA SCRNSRCH ;in the FM scratch space for two searches. (B1D8) ;(1 = search1, 0 = search2) (B1DB) LDA #0 ;Initialize offset of file description from STA SECNXDIR ;the very first directory sector. CLC ;(c)=0=signal to read first directory sec. GETDIRSC INC SECNXDIR ;Kick up offset from first directory. (B1E1) ;(On first entry, $00 --> $01.) (B1E4) JSR RDDIRECT ;Go read directory sector into buffer. * Read a directory sector. (B011) RDDIRECT PHP ;Save (c) on stack: ; (c) = 0 = read 1rst directory sector. ; (c) = 1 = read next directory sector. (B012) JSR PT2DIRBF * Designate the directory sector buffer * as I/O buffer in RWTS's IOB. (B045) PT2DIRBF LDA ADRDIRBF ;Get addr of direc STA IBBUFP ;sec buf from the LDA ADRDIRBF+1 ;FM constants tbl STA IBBUFP+1 ;& designate it as (B051) RTS ;as the I/O buffer. (B015) PLP ;Check if 1rst directory sec or not. (B016) BCS RDNXTDIR ;Go read next directory sector. * Read the first directory sector. * (Carry = 0.) (B018) RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory LDX FIRDIRTK ;sector (from the VTOC buffer). (B01E) BNE DODIRRD ;ALWAYS - go read in directory sector. * Read the next directory sector. * (Carry = 1.) (B020) RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the ;link in the current directory sector. (B023) BNE GETDIRLK ;Link not zeroed out. SEC ;Link zeroed out - exit with (c) = 1 to (B026) RTS ;signal there are no more directory secs. ============ (B027) GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the ;link in the current directory sector. * Call to read in the directory sector. (B02A) DODIRRD STX CURDIRTK ;Save trk/sec vals of directory sec that (B02D) STY CURDIRSC ;we are about to read so they will be ;the current directory sec values for the ;next time around. (B030) LDA #1 ;Read opcode for RWTS. (B032) JSR RWTSDRVR ;Call RWTS driver to do the read. * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using READ.) . . (RTS) (B035) CLC ;Link didn't zero out so signal that there (B036) RTS ;are more directory secs to read & exit. ============ (B1E7) BCS CHNGSRCH ;Link zeroed out, no more directory secs, ;so go switch searches. (B1E9) LDX #0 CKDIRTRK STX CURDIRNX ;Offset of file description into the current (B1EB) ;directory sector. (B1EE) LDA FIL1TSTK,X ;Get track number of first T/S list ;for a particular file from the file ;description entry in the directory sector. (B1F1) BEQ CHRSRCHA ;If trk=0, no more files in this direc sec. (B1F3) BMI CHRSRCHB ;Skip deleted file. (When a file is ;deleted, #$FF is put in byte where trk # ;of first T/S list is usually kept. * Compare the name found in the file * description entry portion of the * directory sector with the file name * wanted. (On entry, A4L/H points at * the primary file name buffer.) (B1F5) LDY #0 ;Initialize index to file name buffer. INX ;Point (x) at the first char position INX ;in the name field of description entry. CMPNAMES INX LDA (A4L),Y ;Get char of name from primary. CMP FIL1TSTRK,X ;Compare to char in name of description. BNE DONTMTCH ;Chars (and therefore names) don't match. INY CPY #30 ;Done all chars yet (0 to 29)? BNE CMPNAMES ;Chars matched, branch if more to check. LDX CURDIRNX ;All chars matched, so names matched. CLC ;Return with (x) = index to file (B20A) RTS ;description in current directory sector ============ ;and with (c) = 0 to signal that the ;correct file description was found. * Advance index to point at the next * potential file description entry. (B20B) DONTMTCH JSR NXPLUS35 ;Names didn't match, so adjust index ;to point at the next entry. * Add 35 to the offset to point the index * at the next file description entry. * (Check to make sure that we don't index * right off the end of the directory sec.) (B230) NXPLUS35 CLC LDA CURDIRNX (B234) ADC #35 ;Add 35 to index. (Each file description ;entry is 35 bytes long.) (B236) TAX ;Check if there is more space for entries CPX #245 ;in the current directory sector. (B239) RTS ;Exit with (c) conditioned: ; (c) = 0 = more space in directory. ; (c) = 1 = ran off end of directory. (B20E) BCC CKDIRTRK ;More potential file descriptions to check ;in this directory sector. (B210) BCS GETDIRSC ;Go get next directory sector. ------------ * If we just completed the first seach, * go back to do the second search. (B212) CHRSRCHA LDY SCRNSRCH ;(1 = search1, 0 = search2) (B215) BNE SETSRCH ;Go switch to second search. * If first search, skip deleted files. * If second search, fall through to store * the description in the first unused * space in the directory. (B217) CHRSRCHB LDY SCRNSRCH ;(1 = search1, 0 = search2) (B21A) BNE DONTMTCH * Couldn't locate the named file in the * directory description entries, so begin * creating a new description in the first available * space in a directory (in case command can * legally create a new file). (B21C) NWDESCRP LDY #0 ;Initialize index to primary file name buffer. INX ;Set index to first char position in the INX ;name field of the file description entry SETNWNAM INX ;space in the directory sector. LDA (A4L),Y ;Copy char from primary file name buffer STA FIL1TSTK,X ;to the directory description space. INY CPY #30 ;30 chars in name (0 to 29). BNE SETNWNAM ;Branch if more chars to copy. LDX CURDIRNX ;Return with (x) = index to file SEC ;description space in current directory (B22F) RTS ;sector & with (c)=1 to signal new entry ============ ;was just created. * If first search, switch to second search. * If second search, link zeroed out because * there isn't enough room left on the * disk for a new entry. Therefore, * exit with a disk-full error message. (B23A) CHNGSRCH LDA #0 ;Used to reset search counter if ;we go back to start a second search. (B23C) LDY SCRNSRCH ;(1 = search1, 0 = search2) BNE SETSRCH ;Just did search1 so go start search2. (B241) JMP DISKFULL ;Even second search was unsuccesful ------------ ;so go handle a disk-full error. (AB46) BCC FILLINWA ;Branch if found a directory sector with ;name wanted in the file description entry. ;Will always find name if using verify in association ;with INIT, SAVE or BSAVE commands because these commands ;would have previously provided a new name if necessary. * Named file wasn't found in directory, * so prepare a new file entry in case * command can legally create a new file. (AB48) STX CURDIRNX ;Offset to new description entry in ;case want to create a new file. * Check to see if command can * legally create a new file. (AB4B) LDX NDX2CMD ;(x) = index representing command. (AB4E) LDA CMDATTRB,X ;Get first byte containing description ;of the given command's attributes. (AB51) LDX CURDIRNX ;(x) = index for new file description ;entry into the directory sector. (AB54) LSR ;(c) = bit 0 of 1rst attribute byte. (AB55) BCS CREATNEW ;If (c) = 1, command can create a new file. ;ALWAYS FALL THRU WHEN VERIFYING. * Command can't create a new file. * See which language we are using and * exit with the appropriate error msg. (AB57) NEWILLGL LDA CONDNFLG ;$00=warmstart, $01=reading, $40=A(RAM), ;$80=coldstart & $C0=integer. (AB5A) CMP #$C0 ;Integer in ROM? BNE TOFILNOT ;No. (AB5E) JMP LNGNOTAV ;Yes - handle language-not-available error. ------------ TOFILNOT JMP FILENOT ;Handle file-not-found error. (AB61) ------------ * Fill in the FM work area buffer. * (Routine common to opening a new * or pre-existing file.) (ABA6) FILLINWA LDA FIL1TSTK,X ;T/S list trk val (from directory sec). STA FIRSTSTK LDA FIL1TSSC,X ;T/S list sec val (from directory sec). STA FIRTSSEC LDA FIL1TYPE,X ;File type (from directory sec). STA FILTYPFM STA FILTYPWA LDA FIL1SIZE,X ;File size (from directory sec). STA FILENSEC LDA FIL1SIZE+1,X STA FILENSEC+1 STX BYTNXDIR ;Index into directory sec to description. LDA #$FF ;Pretend that the last data sector used had STA RELPREV ;a relative sector number (in relation to (ABCF) STA RELPREV+1 ;the entire file) of $FFFF. NOTE: This ;value is later used to trick the read and ;write subfunctions into ignoring the data ;sector currently in memory. (ABD2) LDA MXIN1TSL ;Dicatate that a T/S list can only describe $7A (ABD5) STA MXSCURTS ;(#122) data sectors. Note: This value is later ;used by the read and write subfunctions to decide ;whether or not the T/S list currently in memory ;should be used. * Read first T/S list sector * to the T/S list buffer. (ABD8) CLC ;(c) = 0 = signal 1rst T/S list sector. (ABD9) JMP READTS ;Go read in the T/S list sector. ------------ * Read T/S list sector. (AF5E) READTS . . (See dis'mbly given below.) . . (RTS) (AD1B) VRFYREAD JSR NXTDATRD ;Read the next data sector in. (Assume ;the data sector we want is not presently ;in memory.) * Check if we need to read the next data * sector into the data sector buffer. * * - Is the data sec we want already in memory? * - If so, does it require updating? * If sector offset into file (FILPTSEC) equals * the relative sector number of the last sector * read or written (RELPREV), then sector we want * is presently in memory. If it is not in memory, * read in the data sector wanted. However, first * check if the data sector has changed since the * last read or write. If it has, the disk must * be updated before we read in the new data * sector so we don't overwrite the data * sector buffer and loose information. * NOTE: - if this subroutine is called from a * write subfunction and FILPTSEC is not * equal to RELPREV, then the data sector * buffer must be full & therefore should * be written to the disk before any more * information is read in. * - if the file was just opened, the open * subfunction set FILPTSEC = $0000 and * RELPREV = #$FFFF so always force reading * of a new data sector even if the correct * sector is already in memory. * NOTE: Not all of the NXTDATRD routine is listed * because not all of it applies to the * VERIFY function. (B0B6) NXTDATRD LDA FILPTSEC ;Last sector used versus sector wanted? CMP RELPREV (B0BC) BNE CKWCURDA ;Not same - will eventually have to read in ;a new data sector. ;Note: THIS BRANCH IS ALWAYS TAKEN ON FIRST ; ENTRY FROM THE VERIFY FUNCTION ; because RELPREV was set to #$FFFF ; in the FILLINWA section of the ; common open routine. In other ; words, program flow in the VERIFY ; function is such that a new data ; read is forced even if the correct ; data sector is already resident in ; the data sector buffer. (B0BE) LDA FILPTSEC+1 ;Maybe same - check hi bytes. CMP RELPREV+1 (B0C4) BEQ XITNXDAT ;Same, so go exit. * Write the data sector if necessary. * Data sector we want is not presently * in memory. Check if we need to write * the current data sector buffer before * we read in the wanted data sector. (B0C6) CKWCURDA JSR CKDATUP ;Check the update flag to see if the data ;sector buffer has changed since the last ;read or write. If it has, write the data ;sector buffer to the disk. * Check if the data sector has changed * since the last read or write was done. (AF1D) CKDATUP BIT UPDATFLG ;Check bit 6 to see if data sec requires ;updating or not. (AF20) BVS WRITDATA ;Take branch if data requires updating. ;ALWAYS FALL THRU WHEN USING VERIFY. (AF22) RTS * Should current T/S list be used? * (That is, should the data sector be listed in * the present T/S list sector? If not, then * will need to read in the correct T/S list.) * Is the sector offset into the file of the present * data sector less than the relative sector number * of the FIRST data sector that can be described in * the T/S list presently in memory? (If less, * then need to read in a different T/S list sector.) (B0C9) CKCURTS LDA FILPTSEC+1 ;Sector offset in file associated with (B0CC) CMP RELFIRST+1 ;the present data sector versus the ;relative sector number of the first data ;sector that can be described in the present ;T/S list. (B0CF) BCC NEEDNXTS ;Data sector wanted represents a SMALLER offset ;into the file so need a different T/S list. (B0D1) BNE CKCURTS1 ;Sector offset of wanted data sector is ;LARGER than that of the first data sector that ;can be described in the present T/S list so it ;may still belong to this T/S list. (B0D3) LDA FILPTSEC ;Hi bytes same - so compare low bytes. CMP RELFIRST (B0D9) BCC NEEDNXTS ;Sector offset of wanted files is LESS, ;so read in a different T/S list. ;(Start by reading the file's first T/S list.) * Sector offset associated with the data * sector we want is either GREATER THAN OR * EQUAL TO the relative sector offset * associated with the first data sector that can * be described in this T/S list. Therefore, * compare the sector offset of the sector * wanted with the relative sector number * (plus 1) of the LAST sector that can be * described in the present T/S list. (B0DB) CKCURTS1 LDA FILPTSEC+1 ;Sector offset associated with data sector (B0DE) CMP RELASTP1+1 ;we want versus the relative sector number ;(plus 1) of the LAST data sector that can possibly ;be described in the present T/S list. (B0E1) BCC GETDATPR ;Sector offset assoc with data sector we ;wanted IS described in the present T/S list. (B0E3) BNE NEEDNXTS ;Sector offset of present data sector is ;LARGER than that of the LAST data sector ;(plus 1) that can possibly be described in the ;present T/S list, so we need a new T/S list sector. (B0E5) LDA FILPTSEC ;Hi bytes same - so compare low bytes. CMP RELASTP1 (B0EB) BCC GETDATPR ;Sector offset associated with data sector ;we want is LESS than the relative sector ;number (plus 1) of the last data sector that ;can possibly be listed in the present T/S list. ;There4, data sector wanted should be described ;in the present T/S list. * The data sector we want is NOT listed * in the present T/S list, so we must * read a different T/S list sector. * (NOTE: Routine is entered with (c) = 1 if need a * higher numbered T/S list. If (c) = 0, then the file * pointer was backed up and we need a smaller numbered * T/S list.) (B0ED) NEEDNXTS JSR READTS ;Read in the next (or first) T/S list. However, ;first check the update flag to see if the T/S list ;presently in memory requires updating before ;we read in the next (or first) T/S list sector. ;If updating is required, write the present ;T/S list. * Read T/S list sector. (AF5E) READTS PHP ;Save (c) denoting if 1rst T/S list or not. ;(c) = 0 = read 1rst T/S list sec. ;(c) = 1 = read next T/S list sec. (AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is ;required. (If T/S list buf has changed ;since last read or write, then write it ;back to the disk so don't overwrite buf ;and lose information when read the new ;T/S list sector.) * Check if T/S list requires updating. * (ie. Has T/S list buf changed since * the last read or write?) (AF34) CKTSUPDT LDA UPDATFLG (AF36) BMI WRITETS ;If bit 7 set, updating is required. ;ALWAYS FALL THRU FOR VERIFY FUNCTION. (AF37) RTS ============ (AF62) JSR SETTSIOB ;Prepare RWTS's IOB for READING a T/S list. * Prepare RWTS's IOB for reading * or writing the T/S list sector. (AF4B) SETTSIOB LDA TSBUFFM ;Get adr of the T/S list buf from the FM STA IBBUFP ;parameter list & designate T/S list buf LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB. STA IBBUFP+1 LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list. LDY CURTSSEC (AF5D) RTS (AF65) JSR SELTSBUF ;Select the T/S list buffer. * Point A4L/H at the T/S list sector buffer. (AF0C) SELTSBUF LDX #2 ;Index for T/S list buf. (AF0E) BNE PT2FMBUF ;ALWAYS. (AF12) PT2FMBUF LDA WRKBUFFM,X ;Get address of the desired buffer from STA A4L ;the FM parameter list & put it in the LDA WRKBUFFM+1,X ;A4L/H pointer. STA A4L+1 (AF1C) RTS (AF68) PLP ;Get saved (c) back from stack. (AF69) BCS RDNXTTS ;If (c) = 1, already read first T/S list ;sec, so go read next one. * Read first T/S list sector. * (Carry was clear.) (AF6B) RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec. LDY FIRTSSEC (AF71) JMP RDTSLST ;Go read T/S list sector into buffer. ------------ * Read next T/S list sector. * (Carry was set.) (AF74) RDNXTTS LDY #1 ;Index into T/S list buffer. LDA (A4L),Y ;Trk for link to next T/S list sector. (AF78) BEQ TSLNKZRO ;Link zeroed out, so there are no more ;T/S list sectors for file. (AF7A) TAX ;(x) = next T/S list trk. INY LDA (A4L),Y ;Sector for link to next T/S list sector. TAY ;(y) = next T/S list sector. (AF7F) JMP RDTSLST ;Go read in next T/S list sector. ------------ * T/S link zeroed out so now must * decide if got an error or not. (AF82) TSLNKZRO LDA OPCODEFM ;Check read/write status to see if want to CMP #4 ;add another T/S list or not. BEQ UPDATETS ;Writing, so go update link. (AF89) SEC ;Set (c) = 1 to signal no more data. ;(Causes out-of-data error when reading. ;Signals verification completed when verifying.) (AF8A) RTS ========= * Subroutine to read T/S list sector. (AFB5) RDTSLST LDA #1 ;READ opcode for RWTS. * Code common to read/write T/S list. (AFB7) RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y) STY CURTSSEC ;become current T/S list trk/sec values. (AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write current T/S ;list. * Read or write the current T/S list. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using READ or WRITE.) . . (RTS) * Update the FM work area * (not in DOS buffer chain). (AFC0) LDY #5 ;Offset into current T/S list buffer. LDA (A4L),Y ;Get & save the relative sector number of (AFC4) STA RELFIRST ;the first data sector that can be ;described in this T/S list. (Possible ;values are: $0000, $007A, 2*$007A, ;3*$007A or 4*$007A.) (AFC7) CLC ;Add the maximum number of secs that ADC MXSCURTS ;can be described in this T/S list. (AFCB) STA RELASTP1 ;Store the maximum relative sector number ;(plus 1) that can possibly be described ;in this particular T/S list. (That is, ;reset RELASTP1.) (AFCE) INY LDA (A4L),Y STA RELFIRST+1 ADC MXSCURTS+1 STA RELASTP1+1 ;Value equals $0000, $007A CLC ;2*$007A, 3*$007A, 4*$007A or 5*$007A. (AFDB) RTS ============ (B0F0) BCC CKCURTS ;Go back and check if this is ;the correct T/S list. (B0F2) RTS ;RETURN WITH (c)=1 TO SIGNAL RAN OUT OF DATA. ============ * We know that the data sector wanted * should be described in the present T/S * list so now calculate the offset into * the T/S list sector where the data * sector pair should be described. (B0F3) GETDATPR SEC ;Calculate offset to the data pair: LDA FILPTSEC ; Sector offset of data sector into file (B0F7) SBC RELFIRST ; minus the relative index of first data ; sector pair described in present T/S list. (B0FA) ASL ;Times 2, cause 2 bytes used to describe a data pair. ADC #12 ;Add 12 cause 1rst data pair is always listed TAY ;12 bytes from the start of the T/S list buf. (B0FE) JSR SELTSBUF ;Point A4L/H at the T/S list buffer. * Point the A4L/H pointer at the * T/S list sector buffer. (AF0C) SELTSBUF LDX #2 ;Index to select T/S list sector buffer. (AF0E) BNE PT2FMBUF ;ALWAYS. (AF12) PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from STA A4L ;the FM parm list & put it in the pointer. LDA WRKBUFFM+1,X STA A4L+1 (AF1C) RTS (B101) LDA (A4L),Y ;Get trk number part of data sector pair. (B103) BNE RDDATSEC ;Go read in the data sector. * The track number part of the data sector * pair listed in the T/S list was zero. * Therefore, there are no more data sector * pairs described in this T/S list. (B105) LDA OPCODEFM ;Check to see if writing or not. CMP #4 ;Opcode for write. BEQ NEWPAIR ;Branch if writing. SEC ;Not writing and ran out of data sector pairs (B10D) RTS ;in the present T/S list, so go exit with ============ ;carry set to signal no more data. * The data sector pair associated with the * data sector wanted was contained in the * current T/S list, so now read in the data * sector wanted. (B114) RDDATSEC STA CURDATRK ;Save trk/sec values of current data sector INY ;in the work area. LDA (A4),Y ;Sector number of current data sector. STA CURDATSEC (B11D) JSR READDATA ;Go read in the data sector. * Read data sector from disk * to the data sector buffer. (AFDC) READDATA JSR PRPDAIOB ;Set up RWTS's IOB to read a data sector. * Prepare RWTS'S IOB to read/write * the data sector. (AFE4) PRPDAIOB LDY DATBUFFM ;Get the addr of the LDA DATBUFFM+1 ;data sec buf from STY IBBUFP ;the FM parm list and (AFED) STA IBBUFP+1 ;designate it as the I/O ;buffer for RWTS's IOB. (AFF0) LDX CURDATRK ;Enter RWTS driver with (x)/(y) LDY CURDATSC ;= trk/sec vals corresponding (AFF6) RTS ;to the data sector. (AFDF) LDA #1 ;Opcode for RWTS's read command. (AFE1) JMP RWTSDRVR ;Call RWTS driver to read the data sec buf. ------------ * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dis'mbly of RWTSDRVR using READ.) . . (RTS) * Save sector-offset-into-file value * associated with the data sector just read. (B120) SETPREV LDA FILPTSEC ;Current sector offset into file. STA RELPREV ;Offset into file of last data sector read. LDA FILPTSEC+1 (B129) STA RELPREV+1 * Exit the read-next-data-sector routine. (B12C) XITNXDAT JSR SELDABUF ;Select the data sector buffer. * Point A4L/H at the data sector buffer. (AF10) SELDABUF LDX #4 ;Index to select data sector buffer. PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from STA A4L ;the FM parameter list & put it in the LDA WRKBUFFM+1,X ;A4L/H pointer. STA A4L+1 (AF1C) RTS (B12F) LDY FILPTBYT ;(y) = offset into current data sector. CLC ;Exit cleanly. (B133) RTS ============ (AD1E) BCS TOOKFMXT ;END OF FILE DETECTED - exit file manager. INC FILPTSEC ;Kick up the file pointer position and then BNE VRFYREAD ;go back to read in the next data sector INC FILPTSEC+1 ;until an end-of-file marker is detected. (AD28) JMP VRFYREAD ------------- (AD0F) TOOKFMXT JMP GOODFMXT ;Exit the file manager cleanly. ------------ * Exit the file manager with or without errors. (B35F) LNGNOTAV LDA #1 (B361) BNE BADFMXIT ;ALWAYS. (B373) FILENOT LDA #6 (B375) BNE BADFMXIT ;ALWAYS. (B377) DISKFULL JMP FULLPTCH ;(See dis'mbly of errors.) ------------ (B37F) GOODFMXT LDA RTNCODFM CLC ;(c) = 0 to signal good operation. BCC FMEXIT BADFMXIT SEC ;(c) = 1 to signal unsuccessful. FMEXIT PHP ;Save status on stack. STA RTNCODFM ;Store return code in FM parameter list. LDA #0 STA STATUS (B38E) JSR CPYFMWA ;Copy the work area to the work buffer. * Copy the FM work area (non-chain) to * the FM work buffer (in DOS chain). (AE7E) CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain). * Point the A4L/H pointer at the FM work buffer. (AF08) SELWKBUF LDX #0 ;Set index to select work buffer. (AF0A) BEQ PT2FMBUF ;ALWAYS. (AF12) PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the STA A4L ;FM parameter list & put it in the pointer. LDA WRKBUFFM+1,X STA A4L+1 (AF1C) RTS (AE81) LDY #0 ;Initialize index. STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area. STA (A4L),Y ;Put it in the work buffer. INY CPY #45 ;45 bytes to copy (0 to 44). BNE STORWRK (AE8D) RTS (B391) PLP ;Retrieve status of success of operation ;from the stack. (B392) LDX STKSAV ;Adjust stack pointer to force exit to the TXS ;caller of the function (even if we are (B396) RTS ;presently several subroutines deeper than ============ ;the original entry point). (Returns to ;AFTRFUNC ($A6AB) in the FMDRIVER routine ;($A6A8).)