353 lines
23 KiB
Plaintext
353 lines
23 KiB
Plaintext
******************************************************************
|
|
* *
|
|
* DELETE Command Handler *
|
|
* *
|
|
*----------------------------------------------------------------*
|
|
* *
|
|
* The DELETE command erases a named file from the disk. *
|
|
* Volume, drive and slot parameters are optional. If the named *
|
|
* file is locked or not present on the disk, an error message *
|
|
* is generated. The following sequence of instruction can be *
|
|
* used to safely delete a TEXT file while running an Applesoft *
|
|
* program: 10 D$ = CHR$(13) + CHR$ (4): REM <Rtn> & ctrl-D *
|
|
* 20 PRINT D$; "OPEN NAMEDFILE" *
|
|
* 30 PRINT D$; "UNLOCK NAMEDFILE" *
|
|
* 40 PRINT D$; "DELETE NAMEDFILE" *
|
|
* *
|
|
* The delete command appears to have a slightly confusing *
|
|
* execution pattern which is summarized below: *
|
|
* 1) close the file & release its DOS buffer. *
|
|
* 2) reassign a DOS buffer to the file. *
|
|
* 3) delete the file: *
|
|
* - Alter the file's description entry in the *
|
|
* directory sector buffer by (a) overwriting *
|
|
* the last byte in the name field with the track *
|
|
* number of the first T/S list and (b) putting *
|
|
* an $FF in the byte where the track number of *
|
|
* the first T/S list sector is usually stored. *
|
|
* (See formatted disassembly of the delete function *
|
|
* handler for an explanation of the structure *
|
|
* of file description entries.) *
|
|
* - release the data and T/S list sectors in the *
|
|
* VTOC. *
|
|
* - write the updated directory and VTOC back to *
|
|
* the disk. *
|
|
* 4) find the DOS buffer associated with the file. *
|
|
* 5) release the DOS buffer associated with the file. *
|
|
* (NOTE: To reincarnate a deleted file which hasn't been over- *
|
|
* written, you simply reverse the process given in step 3 above.)*
|
|
* *
|
|
******************************************************************
|
|
|
|
|
|
* On entry - CUMLOPTN ($AA65) has been updated
|
|
* to reflect any option words that
|
|
* were parsed with the command (V,D,S).
|
|
* - the validity of the options issued
|
|
* with the command (and their numeric
|
|
* values) have been checked.
|
|
* - a legal file name has been parsed and
|
|
* stored in the primary file name buffer
|
|
* (PRIMFNBF, $AA75).
|
|
|
|
|
|
(A263)
|
|
CMDELETE LDA #5 ;Opcode for delete.
|
|
(A265) JSR HNDLCMD1 ;Close the file & release its buf.
|
|
;Reassign a DOS buf to file.
|
|
;Change file description in directory
|
|
;sector buffer & then write updated
|
|
;directory sec back to disk.
|
|
;Free up data & T/S list sectors.
|
|
;Write updated VTOC.
|
|
|
|
* Part of common file manager command handler code.
|
|
(A2AA)
|
|
HNDLCMD1 STA TEMPBYT ;Store opcode in temporary location.
|
|
LDA LENPRSD ;Get L-parameter from parsed table.
|
|
BNE SAVLENFM ;Was a non-zero L-parm issued with cmd?
|
|
LDA LENPRSD+1
|
|
BNE SAVLENFM
|
|
LDA #1 ;Length was 0 so make it 1 instead.
|
|
STA LENPRSD
|
|
SAVLENFM LDA LENPRSD ;Put length in FM parm list.
|
|
STA RECLENFM
|
|
LDA LENPRSD+1
|
|
STA RECLENFM+1
|
|
CLSLOCBF JSR CMDCLOSE ;Close file if it's already open.
|
|
(A2C8)
|
|
|
|
(A2EA)
|
|
CMDCLOSE .
|
|
.
|
|
(See dis'mbly of CMDCLOSE given below.)
|
|
.
|
|
.
|
|
- Note that execution flows thru CMDCLOSE twice if the
|
|
file is already open.
|
|
- The first time thru, the matching DOS filename buffer is
|
|
located & then CLOSEONE is used to close the file.
|
|
- Execution then jumps back to the start of CMDCLOSE.
|
|
- On this second pass, a matching filename is not found
|
|
because the DOS filename buffer was released on the
|
|
first pass. Therefore, A5L/H is left pointing at the
|
|
highest numbered (lowest in memory) FREE DOS buffer
|
|
when CMCLOSE is exited via EVENTXIT and CLOSERTS.
|
|
- If the file is not already open on the first entry to
|
|
CMDCLOSE, only one pass is made. This single pass
|
|
resembles the second pass mentioned above.
|
|
.
|
|
.
|
|
- If necessary, the CLOSE FUNCTION updates the data
|
|
sector, T/S list sector & the VTOC. It also fixes
|
|
up links in the directory sectors and updates the
|
|
file size if needed.
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
(A2CB) LDA A5L+1 ;Hi byte of A5L/H pointer which points at the highest
|
|
;numbered (lowest in memory) free DOS name buffer (in chain).
|
|
(A2CD) BNE SAVFNPTR ;Branch if found a free buffer.
|
|
(A2CF) JMP NOBUFERR ;Go issue an out-of-buffers message.
|
|
------------ ;(See dis'mbly of errors.)
|
|
(A2D2)
|
|
SAVFNPTR STA A3L+1 ;Reset A3L/H to point at DOS buffer that we
|
|
LDA A5L ;will use for file name field buffer (chain).
|
|
STA A3L
|
|
(A2D8) JSR CPYPFN
|
|
|
|
* NOTE: This (re)assigns a DOS buffer to the
|
|
* file we want to delete. The buffer may or may not
|
|
* be the same one that was just released by the CLOSE cmd
|
|
* above. The highest numbered (lowest in memory) free
|
|
* DOS buffer is used.
|
|
(A743)
|
|
CPYPFN LDY #29 ;30 bytes to copy (0 to 29).
|
|
CPYPRIM LDA PRIMFNBF,Y ;Copy the name of the file wanted from
|
|
STA (A3L),Y ;the primary filename buffer into the
|
|
DEY ;filename field buffer (in DOS chain).
|
|
BPL CPYRIM ;More chars to get.
|
|
(A74D) RTS
|
|
|
|
(A2DB) JSR BUFS2PRM
|
|
|
|
* Get addresses of the various DOS buffers from the
|
|
* chain buffer & put them in the FM parameter list.
|
|
(A74E)
|
|
BUFS2PRM LDY #30 ;Get addr of FM work buf, T/S list
|
|
ADRINPRM LDA (A3L),Y ;buf, data sector buf & next DOS
|
|
STA WRKBUFFM-30,Y ;filename buf from chain
|
|
INY ;pointer buffer & put them in FM parm list.
|
|
CPY #38 ;(P.S. Adr of next DOS file name buf is
|
|
BNE ADRINPRM ;not used by DOS.)
|
|
(A75A) RTS
|
|
|
|
(A2DE) JSR CPY2PARM
|
|
|
|
* Put volume, drive, & slot values plus the
|
|
* address of the primary filename buffer
|
|
* in the FM parameter list.
|
|
(A71A)
|
|
CPY2PARM LDA VOLPRSD ;From parsed table.
|
|
STA VOLFM
|
|
LDA DRVPRSD ;From parsed table.
|
|
STA DRVFM
|
|
LDA SLOTPRSD ;From parsed table.
|
|
STA SLOTFM
|
|
LDA ADRPFNBF ;Get the adr of the primary file
|
|
STA FNAMBUFM ;name buf from the constants tbl
|
|
LDA ADRPFNBF+1 ;and put it in the FM parm list.
|
|
STA FNAMBUFM+1
|
|
LDA A3L ;Save adr of current DOS file name
|
|
STA CURFNADR ;buf in table of DOS variables.
|
|
LDA A3L+1
|
|
STA CURFNADR+1
|
|
(A742) RTS
|
|
|
|
(A2E1) LDA TEMPBYT ;Get delete opcode back from temporary buffer
|
|
STA OPCODEFM ;and put it in the FM parameter list.
|
|
(A2E7) JMP FMDRIVER
|
|
------------
|
|
|
|
* Use the file manager driver
|
|
* to do the DELETE FUNCTION.
|
|
(A6A8)
|
|
FMDRIVER JSR FILEMGR ;Call the file manager to do the function.
|
|
|
|
* File manager proper.
|
|
(AB06)
|
|
FILEMGR TSX ;Save stk pointer so can later rtn to caller of FM.
|
|
STX STKSAV
|
|
(AB0A) JSR RSTRFMWA
|
|
|
|
* Copy FM work buf (in DOS chain) to
|
|
* FM work area (not in DOS chain).
|
|
(AE6A)
|
|
RSTRFMWA JSR SELWKBUF ;Point A4L/H at FM work buf.
|
|
|
|
* Get addr of FM work buff from
|
|
* the FM parm list & put it in
|
|
* the A4L/H pointer.
|
|
(AF08)
|
|
SELWKBUF LDX #0 ;Offset to select
|
|
;work buffer.
|
|
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
|
|
|
(AF12)
|
|
PT2FMBUF LDA WRKBUFFM,X
|
|
STA A4L
|
|
LDA WRKBUFFM+1,X
|
|
STA A4L+1
|
|
(AF1C) RTS
|
|
|
|
(AE6D) LDY #0 ;Zero out return code in FM parm list to
|
|
STY RTNCODFM ;signal no errors as default condition.
|
|
STORFMWK LDA (A4L),Y ;Copy FM work buf to FM work area.
|
|
STA FMWKAREA,Y
|
|
INY
|
|
CPY #45 ;45 bytes to copy (0 to 44).
|
|
BNE STORFMWK
|
|
CLC ;WHY?????
|
|
(AE7D) RTS
|
|
|
|
(AB0D) LDA OPCODEFM ;Check if opcode is legal.
|
|
CMP #13 ;(Must be less than 13.)
|
|
BCS TOERROP ;Opcode too large so got range error.
|
|
ASL ;Double val of opcode & put it in (x)
|
|
TAX ;so it indexes tables of adrs.
|
|
LDA FMFUNCTB+1,X ;Stick adr of appropriate function
|
|
PHA ;handler on stack (hi byte first).
|
|
LDA FMFUNCTB,X
|
|
PHA
|
|
(AB1E) RTS ;DO STACK JUMP TO FUNCTION ENTRY POINT.
|
|
|
|
.
|
|
.
|
|
(AD2B) .
|
|
FNDELETE .
|
|
.
|
|
(See dis'mbly of DELETE function.)
|
|
.
|
|
.
|
|
Modify file description in directory sec:
|
|
- transpose orig trk # of 1rst T/S list sector to
|
|
the last char pos'n in the filename description.
|
|
- put an $FF in byte where trk # of 1rst T/S list
|
|
sec was originally stored.
|
|
Write updated directory sec to disk.
|
|
Free up data & T/S list sectors.
|
|
Write VTOC back to disk.
|
|
.
|
|
.
|
|
(RTS)
|
|
============
|
|
|
|
TOERROP JMP RNGERROP ;Go handle range error.
|
|
(AB1F) ------------ ;(See dis'mbly of errors.)
|
|
|
|
* Return here after doing the DELETE FUNCTION.
|
|
* (Cause after @ function is done, use stack
|
|
* to get back to the original caller.)
|
|
(A6AB)
|
|
AFTRFUNC BCC FMDRVRTN ;(c) = 0 = no errors.
|
|
LDA RTNCODFM ;Get error code from FM parameter list.
|
|
CMP #$5 ;End-of-data error?
|
|
(A6B2) BEQ TOAPPTCH ;Yes. Got a zeroed-out T/S link or a
|
|
;zeroed-out data pair listed in a T/S list.
|
|
;(Not applicable to the delete function.)
|
|
(A6B4) JMP OTHRERR ;No. See dis'mbly of errors.
|
|
------------
|
|
|
|
(A6C3)
|
|
FMDRVRTN RTS
|
|
|
|
(A268) JSR GETBUFF ;Locate DOS buff belonging to file so we
|
|
;can free it up.
|
|
|
|
* Locate DOS buffer with same name as file
|
|
* just partially deleted.
|
|
(A764)
|
|
GETBUFF LDA #0 ;Default hi-byte of pointer to 0
|
|
STA A5L+1 ;(ie. assume no free buff available).
|
|
(A768) JSR GETFNBF1 ;Get pointer to 1rst filename buffer in chain.
|
|
|
|
* Put addr of name buffer (located in chain
|
|
* of DOS buffers) in the A3L/H pointer.
|
|
(A792)
|
|
GETFNBF1 LDA ADOSFNB1 ;First link to chain of DOS buffers
|
|
LDX ADOSFNB1+1 ;(ie. pt 2 1rst name buf in chain).
|
|
(A798) BNE SETNXPTR ;ALWAYS.
|
|
|
|
(A7A4)
|
|
SETNXPTR STX A3L+1 ;Put addr of 1rst filename buffer in ptr
|
|
STA A3L ;(ie. highest name buffer in chain).
|
|
TXA ;Get hi-byte of addr in back in (a).
|
|
GETNXRTN RTS
|
|
(A7A9)
|
|
|
|
(A76B) JMP FNCHAR1 ;Go get first byte of DOS name buf.
|
|
------------
|
|
|
|
(A76E)
|
|
GETFNLNK JSR GETNXBUF
|
|
|
|
* Get addr of next filename buffer in chain
|
|
* from chain pointers buffer offset 37 & 36
|
|
* bytes from 1rst char of present filename
|
|
* buffer.
|
|
(A79A)
|
|
GETNXBUF LDY #37 ;Point the pointer at the chain buffer &
|
|
LDA (A3L),Y ;get addr of the next filename buffer.
|
|
BEQ GETNXRTN ;If hi-byte is 0, then lnk zeroed out.
|
|
TAX ;Save hi-byte in (x).
|
|
DEY ;Pick up low-byte.
|
|
LDA (A3L),Y
|
|
SETNXPTR STX A3L+1 ;Stick addr of filename buffer in ptr.
|
|
STA A3L
|
|
TXA ;Get hi-byte back in (a).
|
|
GETNXRTN RTS
|
|
(A7A9)
|
|
|
|
(A771) BEQ NOFNMTCH ;Lnk zeroed out, end of chain.
|
|
FNCHAR1 JSR GETFNBY1 ;Get the 1rst char of filename from buf in chain.
|
|
(A773)
|
|
|
|
* Get first byte from DOS name buffer.
|
|
(A7AA)
|
|
GETFNBY1 LDY #0 ;Buffer is free if 1rst byte = $00.
|
|
LDA (A3L),Y ;If buf occuppied, the 1rst byte = 1rst
|
|
(A7AE) RTS ;char of filename which owns buffer.
|
|
|
|
(A776) BNE NXFNBUF ;Take branch if buffer wasn't free.
|
|
LDA A3L ;Buffer was free, there4, point the A5L/H pointer
|
|
STA A5L ;at the free buffer.
|
|
LDA A3L+1
|
|
STA A5L+1
|
|
(A780) BNE GETFNLNK ;ALWAYS.
|
|
|
|
(A782)
|
|
NXFNBUF LDY #29 ;Buffer not free there4 compare name
|
|
CMPFNCHR LDA (A3L),Y ;of owner with name of file in primary
|
|
CMP PRIMFNBF,Y ;name buffer. (Start with last char first.)
|
|
(A789) BNE GETFNLNK ;Char doesn't match, there4 look for another
|
|
;buffer that might have same name.
|
|
(A78B) DEY ;That char matched, how bout rest of name?
|
|
BPL CMPFNCHR ;30 chars in name (ie. 0 to 29).
|
|
CLC ;Clr carry to signal match.
|
|
(A78F) RTS
|
|
============
|
|
|
|
(A790)
|
|
NOFNMTCH SEC ;Link zeroed out.
|
|
(A791) RTS
|
|
============
|
|
|
|
(A26B) LDY #0 ;Free up the DOS name buffer associated with
|
|
TYA ;file by storing a $00 in the first byte of
|
|
STA (A3L),Y ;its filename field.
|
|
(A270) RTS ;Return to caller of DELETE commandl
|
|
============ ;(Normally returns to AFTRCMD ($A17D)
|
|
;located in the command parsing and
|
|
;processing routines.)
|