💾 Archived View for mirrors.apple2.org.za › archive › www.textfiles.com › apple › ANATOMY › cmdcatlg… captured on 2024-08-19 at 03:01:35.
View Raw
More Information
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
- *****************************************************************
- *
- CATALOG Command Hanlder *
- *
- ----------------------------------------------------------------*
- *
- The CATALOG command displays the volume number and a list *
- of file information. For each file on the disk, the following *
- data are printed: lock/unlock symbol, file type code, file *
- size in sectors and file name. Drive and slot parameters are *
- optional with the CATALOG command. *
- *
- Execution pattern: *
- The execution pattern is fairly straight forward. After *
- loading the accumulator with the catalog opcode, the common *
- file manager handler code (HNDLCMD1, $A2AA) is called to find *
- a free DOS buffer and customize the FM parameter list. The *
- file manager is then used to do the catalog function (FNCATLOG,*
- $AD98). FNCATLOG first sets up the FM work area. A volume *
- number of #$FF is stored in the work area to enable any volume *
- to be cataloged. (When RWTS is eventually entered, this value *
- is EORed with #$FF to simulate a complemented disk volume *
- number of zero (#$FF EOR #$FF = 0). After RWTS reads the *
- address checksum, it checks to see if the correct volume was *
- read off the disk. If the complement of the volume number *
- wanted is zero, or if it matches the number read off the disk, *
- execution proceeds as if the correct volume was found.) *
- After setting the complemented volume number, FNCATLOG *
- reads in the VTOC (so it can get the link bytes to the first *
- directory sector). Next, an index is set to allow up to 22 *
- screen lines to be displayed before the screen is frozen. *
- (This index is used in the CRCATLOG routine ($A2EF) to print a *
- carriage return and check if a pause is required.) After *
- CRCATLOG is called twice to print two carriage returns, the *
- words "DISK VOLUME " are displayed. The bug-ridden PRVOLNMB *
- routine ($AE42) is then called to print the volume number as a *
- 3-digit decimal number (with leading zeroes if applicable). *
- Next, the RDDIRECT routine is used to read in a directory *
- sector. If no more directory sectors are available, the carry *
- is set and the function handler is exited. A clear carry *
- signals that a directory sector was successfully read in. The *
- file information in the directory sector is subsequently *
- displayed. *
- Each directory sector can contain up to seven different *
- file descriptions. An example of the data contained in a *
- selected 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.) If the hi bit is set, *
- ;the files are considered to be locked. *
- ;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 *
- ;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 char position of the name field. The *
- original track # byte (FIL1TSK) was then overwritten with an *
- #$FF.) *
- After reading in a directory sector, the index to the *
- file description entries is initialized. The track number of *
- the file's first T/S list is then analyzed. If this byte is a *
- zero, no more file descriptions are present in the directory *
- sector and the catalog function is exited (BEQ TOFMXTOK). A *
- negative value denotes that the description entry pertains to *
- a deleted file. The "BMI NXDESCRP" instruction is then taken *
- to skip the deleted file. A positive non-zero value means *
- that the file information should be processed. *
- After the type code is checked to determine if the file *
- is locked (negative) or unlocked (positive), an asterisk *
- (locked) or a space (unlocked) is printed. The lock bit (bit *
- 7) is then dropped from the file type code and the remaining *
- six bits are shifted until the carry is set. The number of *
- shifts needed to set the carry is used to index the table of *
- file type character symbols (FTYPETBL, $B3A7). After printing *
- the type symbol and a trailing space, the file size (in *
- sectors) is read from the description entry. PRVOLNMB ($AE42) *
- is then used to print the size as a 3-digit decimal number *
- (with leading zeroes if applicable). Because this routine *
- does not process the high byte of the file size correctly, *
- files greater than 255 sectors are expressed as 256 modular. *
- Thus a file that is actually 256 bytes long will be displayed *
- in the catalog as being "000" sectors in length. (Special *
- note should be taken of files that appear to be "001" sectors *
- long. Either these files are actually 257 sectors long (or *
- some multiple thereof) or else they were written to the disk *
- incorrectly. All valid files must be at least two sectors *
- because each file requires at least one T/S list sector and *
- one data sector. A file that is only one sector long was *
- opened but never closed properly. Such files are useless and *
- should be deleted from the disk.) *
- A space and the file name are printed after the file size.*
- Next the CRCATLOG ($AE2F) is again called to print a carriage *
- return and test for a screen pause. Finally, the index into *
- the current directory is kicked up by 35 bytes to point to the *
- next potential entry in the directory sector. If the resulting*
- index is 245 or greater, the carry is set. A set carry means *
- that the index points beyond the end of the current directory. *
- As a result, the "BCS RDDIRSEC" instruction is taken to read *
- in the next directory sector. If there is enough space left *
- on the directory sector for another file entry, the "BCC *
- DESCRPTK" is executed to process the next potential file *
- description. *
- Because the catalog's command and function handlers are *
- easy to relate to, almost everybody and his dog has taken a *
- crack at customizing the catalog with certain enhancements or *
- protection schemes. Most major Apple-orientated magazines *
- have printed articles which explain how to patch a free-space- *
- left-on-disk utility to the catalog or how to repair the bugs *
- in the PRVOLNMB routine ($AE42). Many commercial programs put *
- the real catalog on a different track and supply a phony *
- catalog on track #$11 (dec 17). Other developers zap the *
- file name fields of the description entries with names *
- containing "illegal" characters. For instance, you can insert *
- backspaces into a name in order to hide preceeding characters. *
- You can even zap the name field with a return, ctrl-D and a *
- DOS command to trick the catalog routine into doing some other *
- function if a person gets past earlier defence techniques. *
- Some developers are even silly (or paranoid) enough to zap the *
- sector size bytes with enlarged values in the hope that you *
- will think you're getting more bytes/buck. Some programs, *
- such as the word processor I am presently using, make it a *
- policy to always set the file size bytes to 0. *
- Data files are often protected from user abuse by simply *
- zapping the first byte of the file's description entry with an *
- illegal track number that is negative but less than #$FF. *
- (Obviously the driver routines must modify this code before *
- and after each access.) The illegal track # prevents the file *
- from being displayed on the catalog (via the BMI NXDESCRP" *
- instruction at $ADD9). However because the byte is less than *
- $FF, the corresponding file entry space is not considered to *
- be available by the write subfunctions. (When a new file is *
- being added to the disk, the first available space in a *
- directory is used for the new file description. Only potential*
- entry spaces that start with a $00 or a $FF are considered fair*
- game.) *
- Other "enchancements" that are commonly used include *
- changing the "LDA #22" instruction at $ADA3 to set the screen *
- line counter to a different value, modifying the lock symbol *
- ("LDY "*", $AD2E), changing the file type character codes in *
- the FTYPETBL table at $B3A7, changing the contents of the *
- DSKVOLUM table at $B3AF to print something other than "DISK *
- VOLUME ", NOPing out the "BMI NXDESCRP" instruction at $ADD9 *
- to list both active and deleted files, or changing "BMI *
- NXDESCRP" to "BPL NXDESCRP" to force the catalog to display *
- deleted files only. *
- Protection techniques that rely on modified file *
- descriptions are easy to discover. If you suspect that the *
- file description entries have been tampered with, simply *
- catalog the disk and inspect the directory sector buffer. If *
- the disk contains more than 7 files, only the last few entries *
- will be listed in the buffer. However, whenever DOS performs *
- a specific operation of a file, the description of the file is *
- left in the directory sector buffer. Therefore, if the file *
- of interest does not appear in the buffer when you do a *
- catalog, simply lock, unlock or verify a file listed above or *
- below the particular file of interest. You can then inspect *
- the file description entry belonging to the file you are *
- interested in. *
- *
- *****************************************************************
- On entry - CUMLOPTN ($AA65) has been updated
- to reflect any parsed option words.
- - the validity of the options issued
- with the command (and their numeric
- values) have been checked. (Only
- drive and slot parameters are optional.)
- - the first byte of the primary file name
- buffer (PRIMFNBF, $AA75) has been zeroed
- out.
(A56E)
CMCATLG LDA #6 ;Catalog opcode.
(A570) JSR HNDLCMD1 ;Call command handler to do the catalog.
* Part of common file manager command handler code.
(A2AA)
HNDLCMD1 STA TEMPBYT ;Store catalog 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 parameter list.
STA RECLENFM
LDA LENPRSD+1
STA RECLENFM+1
CLSLOCBF JSR CMDCLOSE ;Use close cmd to find a free DOS buffer.
(A2C8)
* NOTE: ONLY A MINOR PORTION OF THE CLOSE
* COMMAND IS SHOWN BELOW because only part of
* it is applicable to the catalog command.
* When accessed from the catalog command,
* the close command is actually only used to
* find a free DOS buffer.
(A2EA)
CMDCLOSE LDA PRIMFNBF ;Get 1rst char from primary name buffer.
CMP #" " ;Don't allow leading <spc> in name.
(A2EF) BEQ CLOSEALL ;Leading <spc> = signal to close all files.
;(A close cmd was issued with no
;accompanying file name.)
(A2F1) JSR GETBUFF ;Locate a DOS file buffer.
* Attempt to locate highest numbered (lowest
* in memory) free DOS name buffer.
*
* NOTE: Because a filename field is not
* applicable to the catalog command, earlier
* processing by DOS (at FNOTAPPL, $A0A0) has
* stuck a $00 in the first byte of the primary
* filename field buffer (PRIMFNBF, $AA75).
* This insures that:
* 1) Execution falls thru to the GETBUFF
* routine.
* 2) The GETBUFF routine never finds a DOS
* filename buffer with a filename that
* matches the "name" in the primary
* filename buffer. Instead, the GETBUFF
* routine is exited with A5L/H pointing to
* the filename field of the highest numbered
* (lowest in memory) free DOS buffer. If a
* free buffer can't be found, A5L+1 is left
* containing a default value of $00.
(A764)
GETBUFF LDA #0 ;Default hi-byte of pointer to 0
STA A5L+1 ;(ie. assume no free buff available).
(A768) JSR GETFNBF1 ;Get ptr to 1rst name buffer in chain.
* Point A3L/H at 1rst (ie. lowest numbered,
* highest in memory) DOS filename buffer.
* (Addr of this buf is kept in ADOSFNB1
* which occupies the 1rst two bytes of the
* table of relocatable address constants.)
(A792)
GETFNBF1 LDA ADOSFNB1 ;First link to chain
LDX ADOSFNB1+1 ;of DOS buffers.
(A798) BNE SETNXPTR ;ALWAYS.
(A7A4)
SETNXPTR STX A3L+1 ;Put addr of 1rst
STA A3L ;buffer in ptr.
TXA ;(a)= hi-byte of adr.
GETNXRTN RTS
(A7A9)
(A76B) JMP FNCHAR1 ;Get first byte of DOS name buffer.
------------
(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 at chain buf
(A79C) LDA (A3L),Y ;Pick up addr of nxt
;filename buffer.
(A79E) BEQ GETNXRTN ;If hi byte = 0 then
;link zeroed out.
(A7A0) TAX ;Save hi-byte in (x).
DEY ;Pick up low-byte.
LDA (A3L),Y
SETNXPTR STX A3L+1 ;Put adr of filename
STA A3L ;buf in pointer.
TXA ;Put hi-byte in (a).
GETNXRTN RTS
(A7A9)
(A771) BEQ NOFNMTCH ;Link zeroed out, end of chain.
FNCHAR1 JSR GETFNBY1 ;Get 1rst char of name from buf in chain.
(A773)
* Get 1rst char of name from current
* filename buffer in DOS buffer chain.
* (If first byte is $00, then buffer is
* free. Otherwise, it is the 1rst char
* in the name of the file which owns the
* DOS buffer.)
(A7AA)
GETFNBY1 LDY #0
LDA (A3L),Y
(A7AE) RTS
(A776) BNE NXFNBUF ;Take branch if buffer wasn't free.
LDA A3L ;Buffer was free, there4 put ptrs to free
STA A5L ;buffer in A5L/H.
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 buf. (Start with last char 1rst.)
(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. ALWAYS TAKE THIS
(A791) RTS ;ROUTE WITH CATALOG CMD.
============
(A2F4)
EVENTXIT BCS CLOSERTS ;ALWAYS TAKE WITH CATALOG CMD.
CLOSERTS RTS
(A330) ============
(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 ROUTINE IS ACTUALLY SUPERFULOUS TO
* THE CATALOG COMMAND because the first byte of
* the primary name buf (PRIMFNBF, $AA75) was
* previously zeroed out.
(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 catalog opcode back from the temporary
STA OPCODEFM ;buffer and put it in the FM parameter list.
(A2E7) JMP FMDRIVER
-------------
* Use the file manager driver
* to do the CATALOG 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.
.
.
(AD98)
FNCATLOG .
.
(See dis'mbly of CATALOG function.)
.
.
- initializes the FM work area (non chain)
& then copies volume #, etc from the FM
parameter list into the FM work area.
(The vol # is set to 0 so any vol of disk
can be cataloged.)
- reads in the VTOC.
- sets SCRNSRCH ($B39D) to allow 22 screen
lines before pause & subsequent scrolling.
- reads in all necessary directory secs
- for @ non-deleted file description entry
in @ directory sec, prints the following
file information: locked or unlocked, file
type code, file size in sectors & file name.
.
.
(RTS)
============
TOERROP JMP RNGERROP ;Go handle range error.
(AB1F) ------------ ;(See dis'mbly of errors.)
* Return here after doing the CATALOG 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 - Encountered a zeroed-out T/S link or
;a zeroed-out data pair (trk/sec vals)
;listed in the T/S list. (Not applicable to
;the catalog function.)
(A6B4) JMP OTHRERR ;No. See dis'mbly of errors.
------------
(A6C3)
FMDRVRTN RTS
(A573) LDA VOLFM ;Get volume # from FM parm list.
STA VOLPRSD ;Put it in the parsed table.
(A579) RTS ;Return to caller of the catalog command.
============ ;(Normally returns to AFTRCMD ($A17D)
;located in the command parsing and
;processing routines.)