*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::* * * * DELETE Funtion Handler * * * *----------------------------------------------------------------* * * * The DELETE function handler (FNDELETE, $AD2B) uses the * * COMNOPEN routine ($AB28) to locate the desired 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 housed in the VTOC. Each subsequent directory sector * * contains the links to the next directory sector. The link * * bytes of the last directory sector are zeroed out.) * * Each directory contains up to seven different file * * descriptions. An example of the data contained in a file * * description is shown below: * * FIL1TSTK DS 1 ;Track # of first T/S list for file 1. * * FIL1TSSC DS 1 ;Sector # of first T/S list for file 1. * * FIL1TYPE DS 1 ;File type code for file 1. ($00=Text, * * ;$01=Integer, $02=Applesoft, $04=Binary, * * ;$08=S-type, $10=Relocatable, $20=A-type * * ;and $40=B-type.) The hi bit is set on * * ;locked files. For example, $02=unlocked * * ;Applesoft and $82=locked Applesoft. * * FIL1NAME DS 30 ;Name of file 1. If a file name less than * * ;30 bytes is used, trailing spaces are * * ;added to the name to fill the buffer. * * FIL1SIZE DS 2 ;Size of file 1 in terms of the number of * * ;sectors used. * * (If a file was deleted, the track # of the first T/S list sec * * was copied to the last byte position of the name field. The * * original track # byte (FIL1TSTK) was then overwritten with * * an #$FF.) * * As each directory sector is read in, an attempt is made * * to locate a file description which contains the name of the * * file wanted. If, after searching all directories, the name of * * the wanted file is not found, a second search is made to * * locate the first available space in a directory where a new * * file description can be placed (in case the command can * * legally create a new file). If no free space is located, a * * disk-full error message is printed. * * If a free space is found, NEWDESCRP ($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 bit0 * * of the first attribute byte associated with the delete * * command is clear, a new file cannot legally be created. As a * * result, the delete command is exited with a file-not-found * * error 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. The first T/S list belonging to the wanted file is then * * read in (READTS, $A5FE). Next, the file type code is checked. * * The delete command is aborted with a file-locked message if * * the file is locked. * * If the file is not locked, the track value of the file's * * first T/S list is copied to the last character position of the * * name field in the description. The original track number byte * * is then replaced with an #$FF to mark the file as deleted. * * WRDIRECT ($B037) is used to write the updated directory sector * * to the disk. After re-reading the file's first T/S list into * * the T/S list buffer, execution returns to the delete function * * handler at $AD5C. * * The DELFREE routine ($AD5E) is used to free up all the * * data sectors that are listed in the T/S list. Sectors are * * released by setting the appropriate bit in the TRKMAP bytes of * * the VTOC. (See the linear disassembly of the VTOC and the * * SUB2FREE routine ($B2DD) listed below for further explanation.)* * After all data sectors listed in the T/S list are * * freed, the sector belonging to the T/S list is also released * * ($ADD7). Execution then branches back to the RDTS4DEL routine * * ($AD54) to read in the next T/S list and repeat the freeing up * * process (if necessary). Once all the sectors associated with * * the file are released, a forced branch is made to the DONEDEL * * routine ($AD83). DONEDEL writes the updated VTOC and then * * returns to delete command handler. * * * *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::* (AD2B) FNDELETE JSR COMNOPEN ;Locate a file with the same name & open it. *** NOTE *** * Not all of the common open routine is * listed below because not all of it * applies to the DELETE function. * 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 * alterd, don't be lulled into thinking that they * are not important. Zero values are just as relevant * as non-zero values.) * (P.S. Don't confuse the FM work area with its image * (FM work buffer) that is housed in the chain of * DOS buffers.) (ABDC) ZWRKAREA LDA #0 TAX ;Initialize the x-index. ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area. INX CPX #45 ;Work area is 45 bytes long. (ABE5) BNE ZEROWRKA * Begin customizing the work area. * Get volume, drive, slot & catalog track * values from the FM parameter list. Put * drive, slot*16, catalog track and * complemented volume number in the work area. (ABE7) LDA VOLFM ;Volume number. EOR #$FF ;Calculate 1's complement of volume #. STA VOLWA LDA DRVFM ;Drive #. STA DRVWA LDA SLOTFM ;Get slot #. ASL ;Calculate slot * 16. ASL ASL ASL TAX ;Set (x) = slot * 16. STX SLOT16WA LDA #$11 ;Normal catalog trk = #17. STA TRKWA (AC05) RTS (AB2B) LDA #1 ;Describe sector length as 256 bytes (AB2D) STA SECSIZWA+1 ;(in the FM work area). * Get record length from the FM parameter * list & put it in the FM work area. * (Don't allow a zero length. If zero, * change it to one.) (AB30) LDX RECLENFM+1 LDA RECLENFM BNE STRECLEN ;Non-zero record length is ok. CPX #0 BNE STRECLEN INX ;Was zero, make it one instead. STRECLEN STA RECLENWA ;Put length in FM work area. STX RECLENWA+1 (AB43) JSR GETFNTRY ;Try to find a directory sector for the file. * Locate or create a file entry in the * directory buffer. * Make two searches if necessary: * - Search1 - try to locate entry with same name as file wanted. * - Search2 - couldn't locate entry corresponding to file * wanted so create a new entry in first available * space in the directory sector. (B1C9) GETFNTRY JSR READVTOC ;Read in the VTOC so we can get the link to ;TRKMAPS & to the first directory sector. * Read the Volume Table of Contents (VTOC). (AFF7) READVTOC LDA #1 ;Read opcode for RWTS. (AFF9) BNE RDWRVTOC ;ALWAYS. * Code common to read/write VTOC. (AFFD) RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the STY IBBUFP ;FM constants table & designate it LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB. STY IBBUFP+1 LDX TRKWA ;Enter RWTS driver with (x)/(y) equal LDY #0 ;to the trk/sec values of the VTOC. (B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC. ------------ * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dism'bly of RWTS driver using READ.) . . (RTS) * Point A4L/H at the primary file name buffer. (B1CC) LDA FNAMBUFM ;Get address of the name buffer from the STA A4L ;FM parameter list & put it in the A4L/H LDA FNAMBUFM+1 ;pointer. (B1D4) STA A4L+1 * Try to find the directory sector with the * wanted file name & read it into the directory * sector buffer. Make two searches if necessary. * On the first search, try to find a matching name. * If that doesn't work, do a second search to store * the description in the first available file * description field in a directory sector. (B1D6) LDA #1 ;Initialize the search counter (SCRNSRCH) SETSRCH STA SCRNSRCH ;in the FM scratch space for two searches. (B1D8) ;(1 = search1, 0 = search2) (B1DB) LDA #0 ;Initialize offset of file description from STA SECNXDIR ;the very first directory sector. CLC ;(c)=0=signal to read first directory sec. GETDIRSC INC SECNXDIR ;Kick up offset from first directory. (B1E4) JSR RDDIRECT ;Go read directory sector into buffer. * Read a directory sector. (B011) RDDIRECT PHP ;Save (c) on stack: ; (c) = 0 = read 1rst directory sector. ; (c) = 1 = read next directory sector. (B012) JSR PT2DIRBF * Designate the directory sector buffer * as I/O buffer in RWTS's IOB. (B045) PT2DIRBF LDA ADRDIRBF ;Get addr of direc STA IBBUFP ;sec buf from the LDA ADRDIRBF+1 ;FM constants tbl STA IBBUFP+1 ;& designate it as (B051) RTS ;as the I/O buffer. (B015) PLP ;Check if 1rst directory sec or not. (B016) BCS RDNXTDIR ;Go read next directory sector. * Read the first directory sector. * (Carry = 0.) (B018) RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory LDX FIRDIRTK ;sector (from the VTOC buffer). (B01E) BNE DODIRRD ;ALWAYS - go read in directory sector. * Read the next directory sector. * (Carry = 1.) (B020) RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the ;link in the current directory sector. (B023) BNE GETDIRLK ;Link not zeroed out. SEC ;Link zeroed out - exit with (c) = 1 to (B026) RTS ;signal there are no more directory secs. ============ (B027) GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the ;link in the current directory sector. * Call to read in the directory sector. (B02A) DODIRRD STX CURDIRTK ;Save trk/sec vals of directory sec that (B02D) STY CURDIRSC ;we are about to read so they will be ;the current directory sec values for the ;next time around. (B030) LDA #1 ;Read opcode for RWTS. (B032) JSR RWTSDRVR ;Call RWTS driver to do the read. * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using READ.) . . (RTS) (B035) CLC ;Link didn't zero out so signal that there (B036) RTS ;are more directory secs to read & exit. ============ (B1E7) BCS CHNGSRCH ;Link zeroed out, no more directory secs, ;so go switch searches. (B1E9) LDX #0 CKDIRTRK STX CURDIRNX ;Offset of file description into the current (B1EB) ;directory sector. (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 search, * 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 ;go back to start second search. (B23C) LDY SCRNSRCH ;(1 = search1, 0 = search2) (B23F) BNE SETSRCH ;Just did first search, so go start ;the second search. (B241) JMP DISKFULL ;Even second search was unsuccesful ------------ ;so go handle a disk-full error. (AB46) BCC FILLINWA ;Branch if found a directory sector with ;name wanted in the file description entry. * Named file wasn't found in directory, * so prepare a new file entry in case * command can legally create a new file. (AB48) STX CURDIRNX ;Offset to new description entry in ;case want to create a new file. * Check to see if command can * legally create a new file. (AB4B) LDX NDX2CMD ;(x) = index representing command. (AB4E) LDA CMDATTRB,X ;Get first byte containing description ;of the given command's attributes. (AB51) LDX CURDIRNX ;(x) = index for new file description ;entry into the directory sector. (AB54) LSR ;(c) = bit 0 of 1rst attribute byte. (AB55) BCS CREATNEW ;If (c) = 1, command can create a new file. ;ALWAYS FALL THRU FOR DELETE FUNCTION (cause (c) = 0). * Command can't create a new file. * See which language we are using and * exit with the appropriate error msg. (AB57) NEWILLGL LDA CONDNFLG ;$00=warmstart, $01=reading, $40=A(RAM), ;$80=coldstart & $C0=integer. (AB5A) CMP #$C0 ;Integer in ROM? BNE TOFILNOT ;No. (AB5E) JMP LNGNOTAV ;Yes - handle language-not-available error. ------------- TOFILNOT JMP FILENOT ;Handle file-not-found error. (AB61) ------------ * Fill in the FM work area buffer. * (Routine common to opening a new * or pre-existing file.) (ABA6) FILLINWA LDA FIL1TSTK,X ;T/S list trk val (from directory sec). STA FIRSTSTK LDA FIL1TSSC,X ;T/S list sec val (from directory sec). STA FIRTSSEC LDA FIL1TYPE,X ;File type (from directory sec). STA FILTYPFM STA FILTYPWA LDA FIL1SIZE,X ;File size (from directory sec). STA FILENSEC LDA FIL1SIZE+1,X STA FILENSEC+1 STX BYTNXDIR ;Index into directory sec to description. LDA #$FF ;Pretend that the last data sector used had STX RELPREV ;a relative sector number (in relation to (ABCF) STA RELPREV+1 ;the entire file) of #$FFFF. NOTE: This ;value is later used to trick the read and ;write subfunctions into ignoring the data ;sector currently in memory. (ABD2) LDA MXIN1TSL ;Dictate that a T/S list can only describe $7A (ABD5) STA MXSCURTS ;(#122) data sectors. Note: This value is later ;used by the read and write subfunctions to decide ;whether or not the T/S list currently in memory ;should be used. * Read first T/S list sector * to the T/S list buffer. (ABD8) CLC ;(c) = 0 = signal 1rst T/S list sector. (ABD9) JMP READTS ;Go read in the T/S list sector. ------------ * Read T/S list sector. (AF5E) READTS PHP ;Save (c) denoting if 1rst T/S list or not. ;(c) = 0 = read 1rst T/S list sec. ;(c) = 1 = read next T/S list sec. (AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is ;required. (If T/S list buf has changed ;since last read or write, then write it ;back to the disk so don't overwrite buf ;and lose information when read the new ;T/S list sector.) * Check if T/S list requires updating. * (ie. Has T/S list buf changed since * the last read or write?) (AF34) CKTSUPDT LDA UPDATFLG BMI WRITETS ;If bit 7 set, updating is required. (AF39) RTS ;NOT APPLICABLE TO THE DELETE FUNCTION. ============ (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. ;(Not applicable at this point in time cause (c) = 0.) * Read first T/S list sector. * (Carry was clear.) (AF6B) RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec. LDY FIRTSSEC (AF71) JMP RDTSLST ;Go read T/S list sector into buffer. ------------ * Subroutine to read/write T/S list sector. (AFB5) RDTSLST LDA #1 ;Read opcode for RWTS. * Code common to read/write T/S list. (AFB7) RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y) STY CURTSSEC ;become current T/S list trk/sec values. (AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write current T/S list. * Read or write the current T/S list. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using READ.) . . (RTS) * Update the FM work area * (not in DOS buffer chain). (AFC0) LDY #5 ;Offset into current T/S list buffer. LDA (A4L),Y ;Get & save the relative sector number of (AFC4) STA RELFIRST ;the first data sector described in this ;T/S list. (AFC7) CLC ;Add maximum # of data secs that can be described ADC MXSCURTS ;in this T/S list ($7A or #122). STA RELASTP1 ;Store relative sector number (plus 1) of INY ;the last data sector that can be described in list. LDA (A4L),Y STA REFIRST+1 ADC MXSCURTS+1 STA RELASTP1+1 CLC ;Return with "no error" signal. (AFDB) RTS ============ (AD2E) LDX CURDIRNX ;(x) = index to file description entry in ;the directory sector buffer. (AD31) LDA FIL1TYPE,X ;Get file type from the directory sec buf. BPL ALTRNTRY ;Branch if file is not locked. (AD36) JMP FILELOKD ;Err - can't DELETE a locked file so go ------------ ;handle error and exit. * Get the track number of the file's first * T/S list from the file description entry * in the directory sec buf. Put it in the * work area and write it over the last char * position in the appropriate file name field * in the directory sector. (AD39) ALTRNTRY LDX CURDIRNX ;(x) = index to the file description entry ;in the directory sector buffer. (AD3C) LDA FIL1TSTK,X ;Get the trk # of the first T/S list sec. STA FIRSTSTK ;Copy it into the work area and into the (AD42) STA FIL1NAME+29,X ;last character position of the file ;name field description. (AD45) LDA #$FF ;Replace the original track # of the T/S STA FIL1TSTK,X ;list with #$FF to signal file is deleted. LDY FIL1TSSC,X ;Put the sector # of the file's first T/S STY FIRTSSEC ;list sec in the work area. (AD50) JSR WRDIRECT ;Write the modified directory sector. * Write the directory buffer. (B037) WRDIRECT JSR PT2DIRBF * Designate the directory sector buffer * as the I/O buffer in RWTS's IOB. (B045) PT2DIRBF LDA ADRDIRBF ;Get the addr of the directory sec buf STA IBBUFP ;in the FM constants table. LDA ADRDIRBF+1 ;Store it in RWTS's IOB. STA IBBUFP+1 (B051) RTS (B03A) LDX CURDIRTK ;Enter RWTS driver with (x)/(y) = trk/sec vals. LDY CURDIRSC LDA #2 ;Write opcode for RWTS. (B042) JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer. ------------ (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using WRITE.) . . (RTS) * Read the T/S list sector into the * T/S list buffer. (Need this info * so know what sectors to release.) (AD53) CLC ;(c) = 0 = 1rst T/S list sec. (AD54) ;(c) = 1 = 2nd T/S list sec. RDTS4DEL JSR READTS ;Go read in a T/S list sector. * Read T/S list sector. (AF5E) READTS PHP ;Save (c) denoting if 1rst T/S list or not. ;(c) = 0 = read 1rst T/S list sec. ;(c) = 1 = read next T/S list sec. (AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is ;required. (If T/S list buf has changed ;since last read or write, then write it ;back to the disk so don't overwrite buf ;and lose information when read the new ;T/S list sector.) * Check if T/S list requires updating. * (ie. Has T/S list buf changed since * the last read or write?) (AF34) CKTSUPDT LDA UPDATFLG (AF37) BMI WRITETS ;If bit 7 set, updating is required. ;NOT APPLICABLE TO THE DELETE FUNCTION. (AF39) 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. ;(Not applicable on first entry cause (c) = 0). * Read first T/S list sector. * (Carry was clear.) (AF6B) RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec. LDY FIRTSSEC (AF71) JMP RDTSLST ;Go read T/S list sector into buffer. ------------ * Read the next T/S list sector. * (Carry was set.) (AF74) RDNXTTS LDY #1 ;Index into the 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 secs for this file. (AF7A) TAX ;(x) = next T/S list sec number. INY LDA (A4L),Y ;Sector # for link to next T/S list sec. TAY ;(y) = next T/S list sector number. (AF7F) JMP RDTSLST ;Go read in the next T/S list. ------------- * The T/S link zeroed out so we must decide * if we got an error or not. (That is, do * we want to create another T/S list?) (AF82) TSLNKZRO LDA OPCODEFM ;Check if reading or writing to see CMP #4 ;if we want to add another T/S list. (AF87) BEQ UPDATETS ;Writing - so go update link. ;(Never take with DELETE function.) (AF89) SEC ;We were reading and the link zeroed out, (AF8A) RTS ;so return with (c) = 1 to generate an error. ============ ;(Remember, we previously set the return ;code to a default value for a file-not-found ;error.) * Subroutine to read/write T/S list sector. (AFB5) RDTSLST LDA #1 ;Read opcode for RWTS. * Code common to read/write T/S list. (AFB7) RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y) STY CURTSSEC ;become current T/S list trk/sec values. (AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write current T/S ;list. * Read or write the current T/S list. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using READ.) . . (RTS) * Update the FM work area * (not in DOS buffer chain). (AFC0) LDY #5 ;Offset into current T/S list buffer. LDA (A4L),Y ;Get & save the relative sector number of (AFC4) STA RELFIRST ;the first data sector 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 # of data secs that can be described ADC MXSCURTS ;in this T/S list. STA RELASTP1 ;Store maximum relative sector number (plus 1) of INY ;the last data sector that can be described in this list. LDA (A4L),Y STA RELFIRST+1 ADC MXSCURTS+1 (AFD7) STA RELASTP1+1 ;(RELASTP1/+1 = $0000, $007A, 2*$007A, ;4*$007A or 5*$007A.) (AFDA) CLC ;Return with "no error" signal. (AFDB) RTS (AD57) BCS DONEDEL ;Branch if just read the last T/S list ;sector associated with this file. (AD59) JSR SELTSBUF ;Point A4L/H at the T/S list sector * 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 * Free all the sectors that are listed in * the T/S list sector that currently occupies * the T/S list sector buffer. (AD5C) LDY #12 ;First data sector pair listed is offset 12 ;bytes from the start of the T/S list buf. DELFREE STY CURDIRNX ;Set (y) = index to data pair in the (AD5E) ;T/S list buffer. (AD61) LDA (A4L),Y ;Get trk # of the data sector. (AD63) BMI BYPASDEL ;Neg track # is illegal (usually denotes ;a deleted file). (Can use neg track # as a ;protection scheme.) (AD65) BEQ BYPASDEL ;Trk # of 0 = no more data secs listed in ;the current T/S list sector. (AD67) PHA ;Save trk # of data sector on the stack. INY ;Get sec # of data sector. LDA (A4L),Y TAY ;Condition (y) = sec & (a) = trk for entry PLA ;into routines to free up sectors. (AD6D) JSR FREESEC ;Free up sectors for the deleted file. * Subroutine to free up a sector * in the VTOC TRKMAP. (AD89) FREESEC SEC ;(c) = 1 so free up present sector when ;start rotating the assignment map. (AD8A) JSR SUB2FREE ;Adjust assignment map to FREE UP SECTORS ;BY SETTING BIT corresponding to the sector ;number. Next, merge ASIGNMAP with the ;appropriate bit map in the VTOC. * Subroutine to free up sectors that were * deleted or prematurely assigned but not used. * * This tricky little routine is easy to * understand once you realize that: * 1) Unlike the VTOC, ASIGNMAP does not * contain any unnecessarily assigned * sectors. * 2) If the disk was just written to, * ASIGNMAP does not house any newly * assigned sectors (even if those sectors * are necessary or not). * 3) Sectors are normally assigned in * descending order. * 4) The number of ROR's done = number * of sectors that need to be assigned. * For example: If the last track had never * been assigned and only sectors $0F and * $0E were needed, then on entry to SUB2FREE, * the first two bytes would appear as follows: * Sector numbers: CBA98765 43210FED * Bit values: 11111111 11111... * After the first ROR, the status of sector * $0D is determined by the entry status of * the carry (c): * Sector numbers: DCBA9876 543210FE * Bit values: c1111111 111111.. * On the next ROR, the "CPY SECPERTK" * instruction conditions (c) to clear for * sector $0E: * Sector numbers: EDCBA987 6543210F * Bit values: 0c111111 1111111. * On the next ROR, the "CPY SECPERTK" * instruction conditions (c) to clear for * sector $0F: * Sector numbers: FEDCBA98 76543210 * Bit values: 00c11111 11111111 * When ASIGNMAP is merged with the corresponding * TRKMAP in the VTOC, the sectors that were * unnecessarily assigned in the VTOC are * freed. (Note: When used in the DELETE * function, SUB2FREE is repeatedly called * up by FREESEC to free one sector at a time.) (B2DD) SUB2FREE LDX #$FC ;Set index to shift 4 bytes as a unit (B2DF) ;(#$FC --> #$FF). STNDARD ROR ASIGNMAP-$FC,X ;4 bytes = map for 1 track. INX BNE STNDARD (B2E5) INY ;When (y) = 16, ASIGNMAP is back in ;standard position. (B2E6) CPY SECPERTK ;Condition (c) for next shift. BNE SUB2FREE ASL ;Trk*4 to index TRKMAP. ASL TAY (B2EE) BEQ SUB2RTN ;Track value of 0 not allowed. * ASIGNMAP now reflects the true sector assignment * and is in standard position. Therefore, merge it * with the appropriate TRKMAP in the VTOC to free up * extra sectors. (B2F0) LDX #4 MERGMAPS LDA ASIGNMAP-1,X ORA TRKMAP0+3,Y ;Do the merge. STA TRKMAP0+3,Y DEY ;Reduce indices. DEX BNE MERGMAPS SUB2RTN RTS (B2FF) (AD8D) LDA #0 ;Zero out ASIGNSEC, ASIGNTRK & ASIGNMAP LDX #5 ;(6 bytes) in the work area. RELEASEC STA ASIGNSEC,X DEX BPL RELEASEC (AD97) RTS (AD70) BYPASDEL LDY CURDIRNX ;Set (y) to index the first data pair. INY ;Kick up (y) to point at next data pair. INY (AD75) BNE DELFREE ;If (y) < > 0, then never ran off the end of ;the T/S list buff yet, so go check if more ;data pairs to do. * Free up the sector that contains * the T/S list sector. (AD77) LDA CURTSTRK ;Trk # of current T/S list sec. LDY CURTSSEC ;Sec # of current T/S list sec. (AD7D) JSR FREESEC ;Go free up the T/S list sec. * Subroutine to free up a sector * in the VTOC TRKMAP. (AD89) FREESEC SEC ;(c) = 1 so free up present sector when ;start rotating the assignment map. (AD8A) JSR SUB2FREE ;Adjust assignment map to FREE UP SECTORS ;BY SETTING BIT corresponding to the sector ;number. Next, merge ASIGNMAP with the ;appropriate bit map in the VTOC. (B2DD) SUB2FREE . . (See dis'mbly above.) . . (RTS) (AD8D) LDA #0 ;Zero out ASIGNSEC, ASIGNTRK & ASIGNMAP LDX #5 ;(6 bytes) in the work area. RELEASEC STA ASIGNSEC,X DEX BPL RELEASEC (AD97) RTS (AD80) SEC (AD81) BCS RDTS4DEL ;ALWAYS. * Done freeing up all the sectors associated * with this file, so now write the modified * VTOC back to the disk. (AD83) DONEDEL JSR WRITVTOC * Write the updated VTOC to the disk. (AFFB) WRITVTOC LDA #2 ;Write opcode for RWTS. * Common to read/write VTOC. (AFFD) RDWRVTOC LDY ADRVTOC ;Get the address of the VTOC from the STY IBBUFP ;FM constants table and designate it as LDY ADRVTOC+1 ;the I/O buffer in RWTS's IOB. STY IBBUFP+1 LDX TRKWA ;Enter RWTS driver with (x)/(y) equal to the LDY #0 ;trk/sec values of the VTOC. (B00E) JMP RWTSDRVR ;Call RWTS driver to write the directory sector buffer. ------------ (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using WRITE.) . . (RTS) (AD86) JMP GOODFMXT ;Go exit file manager cleanly. ----------- * Exit the file manager with or without errors. (B35F) LNGNOTAV LDA #1 (B361) BNE BADFMXIT ;ALWAYS. (B373) FILENOT LDA #6 BNE BADFMXIT ;ALWAYS. DISKFULL JMP FULLPTCH ;(See dis'mbly of errors.) NOP FILELOKD LDA #10 BNE BADFMXIT ;ALWAYS. 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 RTS ;several subroutines deeper than the ============ ;original entry point. (That is, return to ;AFTRFUNC ($A6AB) in the FMDRIVER routine ;($A6A8).)