💾 Archived View for spam.works › mirrors › textfiles › apple › ANATOMY › fndelete.txt captured on 2023-06-16 at 21:11:29.
View Raw
More Information
-=-=-=-=-=-=-
- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
- *
- 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).)