Latest release of ProDOS is 2.4.2

ProDOS 2.5 has been announced but is not available yet.

ProDOS 8 Technical Note #17

Recursive ProDOS Catalog Routine

Revised by Dave Lyons, Keith Rollin, & Matt Deatherage (November 1989)
Written by Greg Seitz (December 1983)

This Technical Note presents an assembly language example of a recursive directory reading routine which is AppleShare compatible.

Changes since November 1988: The routine now ignores the file_count field in a directory, and it properly increments ThisBlock. More discussion of AppleShare volumes is included.


This Note presents a routine in assembly language for recursively cataloging a ProDOS directory. If you apply this technique to the volume directory of a disk, it will display the name of every file stored on the disk. The routine displays the contents of a given directory (the volume directory in this case), displays the contents of each subdirectory as it is encountered.

READ_BLOCK is not used, since it does not work with AppleShare servers. READ is used instead, since it works for AppleShare volumes as well as local disks. Instead of using directory pointers to decide which block to read next, we simply read the directory and display filenames as we go, until we reach a subdirectory file. When we reach a subdirectory, the routine saves our place, plunges down one level of the tree structure, and catalogs the subdirectory. You repeat the process if you find a subdirectory at the current level. When you reach the EOF of any directory, the routine closes the current directory and pops back up one level, and when it reaches the EOF of the initial directory, the routine is finished.

This routine is generally compatible with AppleShare volumes, but it is impossible to guarantee a complete traversal of all the accessible files on an AppleShare volume: another user on the same volume can add or remove files or directories at any time. If entries are added or removed, some filenames may be displayed twice or missed completely. Be sure that your programs deal with this sort of situation adequately.

We assume that AppleShare is in short naming mode (as it is by default under ProDOS 8). If you enable long naming mode, then illegal characters in filenames will not be translated into question marks. In this case, the code would need to be modified to deal with non-ASCII characters. Also, the ChopName routine would need to be aware that a slash (/) character could be contained inside the name of a directory that had been added to the pathname. (As the code stands, such directories fail to open, but their names are still temporarily added to the pathname.)

When the catalog routine encounters an error, it displays a brief message and continues. It is important not to abort on an error, since AppleShare volumes generally contain files and folders with names that are inaccessible to ProDOS, as well as folders that are inaccessible to your program's user (error $4E, access error).

The code example includes a simple test of the ReadDir routine, which is the actual recursive catalog routine. Note that the simple test relies upon the GETBUFR routine in BASIC.SYSTEM to allocate a buffer; therefore, as presented, the routine requires the presence of BASIC.SYSTEM. The actual ReadDir routine requires nothing outside of the ProDOS 8 MLI.


----- NEXT OBJECT FILE NAME IS CATALOG.0                     
0800:        0800    2           org   $800
0800:                3 *******************************************************
0800:                4 *
0800:                5 * Recursive ProDOS Catalog Routine
0800:                6 *
0800:                7 * by: Greg Seitz 12/83
0800:                8 *     Pete McDonald 1/86
0800:                9 *     Keith Rollin 7/88
0800:               10 *     Dave Lyons 11/89
0800:               11 *
0800:               12 * This program shows the latest "Apple Approved"
0800:               13 * method for reading a directory under ProDOS 8.
0800:               14 * READ_BLOCK is not used, since it is incompatible
0800:               15 * with AppleShare file servers.
0800:               16 *
0800:               17 * November 1989: The file_count field is no longer
0800:               18 * used (all references to ThisEntry were removed).
0800:               19 * This is because the file count can change on the fly
0800:               20 * on AppleShare volumes.  (Note that the old code was
0800:               21 * accidentally decrementing the file count when it
0800:               22 * found an entry for a deleted file, so some files
0800:               23 * could be left off the end of the list.)
0800:               24 *
0800:               25 * Also, ThisBlock now gets incremented when a chunk
0800:               26 * of data is read from a directory.  Previously, this
0800:               27 * routine could get stuck in an endless loop when
0800:               28 * a subdirectory was found outside the first block of
0800:               29 * its parent directory.
0800:               30 *
0800:               31 * Limitations:  This routine cannot reach any
0800:               32 * subdirectory whose pathname is longer than 64
0800:               33 * characters, and it will not operate correctly if
0800:               34 * any subdirectory is more than 255 blocks long
0800:               35 * (because ThisBlock is only one byte).
0800:               36 *
0800:               37 *******************************************************
0800:               38 *
0800:               39 * Equates
0800:               40 *
0800:               41 * Zero page locations
0800:               42 *
0800:        0080   43 dirName   equ   $80           ; pointer to directory name
0800:        0082   44 entPtr    equ   $82           ; ptr to current entry
0800:               45 *
0800:               46 * ProDOS command numbers
0800:               47 *
0800:        BF00   48 MLI       equ   $BF00         ; MLI entry point
0800:        00C7   49 mliGetPfx equ   $C7           ; GET_PREFIX
0800:        00C8   50 mliOpen   equ   $C8           ; Open a file command
0800:        00CA   51 mliRead   equ   $CA           ; Read a file command
0800:        00CC   52 mliClose  equ   $CC           ; Close a file command
0800:        00CE   53 mliSetMark equ  $CE           ; SET_MARK command
0800:        004C   54 EndOfFile equ   $4C           ; EndOfFile error
0800:               55 *
0800:               56 * BASIC.SYSTEM stuff
0800:               57 *
0800:        BEF5   58 GetBufr   equ   $BEF5         ; BASIC.SYSTEM get buffer routine

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 3
 
0800:               59 *
0800:               60 * Offsets into the directory
0800:               61 *
0800:        0000   62 oType     equ   $0            ; offset to file type byte
0800:        0023   63 oEntLen   equ   $23           ; length of each dir. entry
0800:        0024   64 oEntBlk   equ   $24           ; entries in each block
0800:               65 *
0800:               66 * Monitor routines
0800:               67 *
0800:        FDED   68 cout      equ   $FDED         ; output a character
0800:        FD8E   69 crout     equ   $FD8E         ; output a RETURN
0800:        FDDA   70 prbyte    equ   $FDDA         ; print byte in hex
0800:        00A0   71 space     equ   $A0           ; a space character
0800:               72 *
0800:               73 *******************************************************
0800:               74 *
0800:        0800   75 Start     equ   *
0800:               76 *
0800:               77 * Simple routine to test the recursive ReadDir
0800:               78 * routine. It gets an I/O buffer for ReadDir, gets
0800:               79 * the current prefix, sets the depth of recursion
0800:               80 * to zero, and calls ReadDir to process all of the
0800:               81 * entries in the directory.
0800:               82 *
0800:A9 04          83           lda   #4            ; get an I/O buffer
0802:20 F5 BE       84           jsr   GetBufr
0805:B0 17   081E   85           bcs   exit          ; didn't get it
0807:8D D7 09       86           sta   ioBuf+1
080A:               87 *
080A:               88 * Use the current prefix for the name of the
080A:               89 * directory to display.  Note that the string we
080A:               90 * pass to ReadDir has to end with a "/", and that
080A:               91 * the result of GET_PREFIX does.
080A:               92 *
080A:20 00 BF       93           jsr   MLI
080D:C7             94           db    mliGetPfx
080E:E8 09          95           dw    GetPParms
0810:B0 0C   081E   96           bcs   exit
0812:               97 *
0812:A9 00          98           lda   #0
0814:8D CE 09       99           sta   Depth
0817:              100 *
0817:A9 EB         101           lda   #nameBuffer
0819:A2 0B         102           ldx   #<nameBuffer
081B:20 1F 08      103           jsr   ReadDir
081E:              104 *
081E:        081E  105 exit      equ   *
081E:60            106           rts
081F:              107 *
081F:              108 *******************************************************
081F:              109 *******************************************************
081F:              110 *
081F:        081F  111 ReadDir   equ   *
081F:              112 *
081F:              113 *  This is the actual recursive routine. It takes as
081F:              114 *  input a pointer to the directory name to read in
081F:              115 *  A,X (lo,hi), opens it, and starts to read the
081F:              116 *  entries. When it encounters a filename, it calls

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 4
 
081F:              117 *  the routine "VisitFile". When it encounters a
081F:              118 *  directory name, it calls "VisitDir".
081F:              119 *
081F:              120 *  The directory pathname string must end with a "/"
081F:              121 *  character.
081F:              122 *
081F:              123 *******************************************************
081F:              124 *
081F:85 80         125           sta   dirName       ; save a pointer to name
0821:86 81         126           stx   dirName+1
0823:              127 *
0823:8D D4 09      128           sta   openName      ; set up OpenFile params
0826:8E D5 09      129           stx   openName+1
0829:              130 *
0829:        0829  131 ReadDir1  equ   *             ; recursive entry point
0829:20 79 08      132           jsr   OpenDir       ; open the directory as a file
082C:B0 1F   084D  133           bcs   done
082E:              134 *
082E:4C 48 08      135           jmp   nextEntry     ; jump to the end of the loop
0831:              136 *
0831:        0831  137 loop      equ   *
0831:A0 00         138           ldy   #oType        ; get type of current entry
0833:B1 82         139           lda   (entPtr),y
0835:29 F0         140           and   #$F0          ; look at 4 high bits
0837:C9 00         141           cmp   #0            ; inactive entry?
0839:F0 0D   0848  142           beq   nextEntry     ; yes - bump to next one
083B:C9 D0         143           cmp   #$D0          ; is it a directory?
083D:F0 06   0845  144           beq   ItsADir       ; yes, so call VisitDir
083F:20 B3 08      145           jsr   VisitFile     ; no, it's a file
0842:4C 48 08      146           jmp   nextEntry
0845:              147 *
0845:20 BA 08      148 ItsADir   jsr   VisitDir
0848:        0848  149 nextEntry equ   *
0848:20 77 09      150           jsr   GetNext       ; get pointer to next entry
084B:90 E4   0831  151           bcc   loop          ; Carry set means we're done
084D:        084D  152 done      equ   *             ; moved before PHA (11/89 DAL)
084D:48            153           pha                 ; save error code
084E:              154 *
084E:20 00 BF      155           jsr   MLI           ; close the directory
0851:CC            156           db    mliClose
0852:E1 09         157           dw    CloseParms
0854:              158 *
0854:68            159           pla                 ;we're expecting EndOfFile error
0855:C9 4C         160           cmp   #EndOfFile
0857:F0 1F   0878  161           beq   hitDirEnd
0859:              162 *
0859:              163 * We got an error other than EndOfFile -- report the
0859:              164 * error clumsily ("ERR=$xx").
0859:              165 *
0859:48            166           pha
085A:A9 C5         167           lda   #'E'|$80
085C:20 ED FD      168           jsr   cout
085F:A9 D2         169           lda   #'R'|$80
0861:20 ED FD      170           jsr   cout
0864:20 ED FD      171           jsr   cout
0867:A9 BD         172           lda   #'='|$80
0869:20 ED FD      173           jsr   cout
086C:A9 A4         174           lda   #'$'|$80

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 5
 
086E:20 ED FD      175           jsr   cout
0871:68            176           pla
0872:20 DA FD      177           jsr   prbyte
0875:20 8E FD      178           jsr   crout
0878:              179 *
0878:        0878  180 hitDirEnd equ   *
0878:60            181           rts
0879:              182 *
0879:              183 *******************************************************
0879:              184 *
0879:        0879  185 OpenDir   equ   *
0879:              186 *
0879:              187 *  Opens the directory pointed to by OpenParms
0879:              188 *  parameter block. This pointer should be init-
0879:              189 *  ialized BEFORE this routine is called. If the
0879:              190 *  file is successfully opened, the following
0879:              191 *  variables are set:
0879:              192 *
0879:              193 *     xRefNum     ; all the refnums
0879:              194 *     entryLen    ; size of directory entries
0879:              195 *     entPtr     ; pointer to current entry
0879:              196 *     ThisBEntry  ; entry number within this block
0879:              197 *     ThisBlock   ; offset (in blocks) into dir.
0879:              198 *
0879:20 00 BF      199           jsr   MLI           ; open dir as a file
087C:C8            200           db    mliOpen
087D:D3 09         201           dw    OpenParms
087F:B0 31   08B2  202           bcs   OpenDone
0881:              203 *
0881:AD D8 09      204           lda   oRefNum       ; copy the refnum return-
0884:8D DA 09      205           sta   rRefNum       ; ed by Open into the
0887:8D E2 09      206           sta   cRefNum       ; other param blocks.
088A:8D E4 09      207           sta   sRefNum
088D:              208 *
088D:20 00 BF      209           jsr   MLI           ; read the first block
0890:CA            210           db    mliRead
0891:D9 09         211           dw    ReadParms
0893:B0 1D   08B2  212           bcs   OpenDone
0895:              213 *
0895:AD 0E 0A      214           lda   buffer+oEntLen ; init 'entryLen'
0898:8D D1 09      215           sta   entryLen
089B:              216 *
089B:A9 EF         217           lda   #buffer+4     ; init ptr to first entry
089D:85 82         218           sta   entPtr
089F:A9 09         219           lda   #<buffer+4
08A1:85 83         220           sta   entPtr+1
08A3:              221 *
08A3:AD 0F 0A      222           lda   buffer+oEntblk ; init these values based on
08A6:8D CF 09      223           sta   ThisBEntry    ; values in the dir header
08A9:8D D2 09      224           sta   entPerBlk
08AC:              225 *
08AC:A9 00         226           lda   #0            ; init block offset into dir.
08AE:8D D0 09      227           sta   ThisBlock
08B1:              228 *
08B1:18            229           clc                 ; say that open was OK
08B2:              230 *
08B2:        08B2  231 OpenDone  equ   *
08B2:60            232           rts

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 6
 
08B3:              233 *
08B3:              234 *******************************************************
08B3:              235 *
08B3:        08B3  236 VisitFile equ   *
08B3:              237 *
08B3:              238 * Do whatever is necessary when we encounter a
08B3:              239 * file entry in the directory. In this case, we
08B3:              240 * print the name of the file.
08B3:              241 *
08B3:20 AC 09      242           jsr   PrintEntry
08B6:20 8E FD      243           jsr   crout
08B9:60            244           rts
08BA:              245 *
08BA:              246 *******************************************************
08BA:              247 *
08BA:        08BA  248 VisitDir  equ   *
08BA:              249 *
08BA:              250 * Print the name of the subdirectory we are looking
08BA:              251 * at, appending a "/" to it (to indicate that it's
08BA:              252 * a directory), and then calling RecursDir to list
08BA:              253 * everything in that directory.
08BA:              254 *
08BA:20 AC 09      255           jsr   PrintEntry    ; print dir's name
08BD:A9 AF         256           lda   #'/'|$80      ; tack on / at end
08BF:20 ED FD      257           jsr   cout
08C2:20 8E FD      258           jsr   crout
08C5:              259 *
08C5:20 C9 08      260           jsr   RecursDir     ; enumerate all entries in sub-dir.
08C8:              261 *
08C8:60            262           rts
08C9:              263 *
08C9:              264 *******************************************************
08C9:              265 *
08C9:        08C9  266 RecursDir equ   *
08C9:              267 *
08C9:              268 * This routine calls ReadDir recursively. It
08C9:              269 *
08C9:              270 * - increments the recursion depth counter,
08C9:              271 * - saves certain variables onto the stack
08C9:              272 * - closes the current directory
08C9:              273 * - creates the name of the new directory
08C9:              274 * - calls ReadDir (recursively)
08C9:              275 * - restores the variables from the stack
08C9:              276 * - restores directory name to original value
08C9:              277 * - re-opens the old directory
08C9:              278 * - moves to our last position within it
08C9:              279 * - decrements the recursion depth counter
08C9:              280 *
08C9:EE CE 09      281           inc   Depth         ; bump this for recursive call
08CC:              282 *
08CC:              283 * Save everything we can think of (the women,
08CC:              284 * the children, the beer, etc.).
08CC:              285 *
08CC:A5 83         286           lda   entPtr+1
08CE:48            287           pha
08CF:A5 82         288           lda   entPtr
08D1:48            289           pha
08D2:AD CF 09      290           lda   ThisBEntry

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 7
 
08D5:48            291           pha
08D6:AD D0 09      292           lda   ThisBlock
08D9:48            293           pha
08DA:AD D1 09      294           lda   entryLen
08DD:48            295           pha
08DE:AD D2 09      296           lda   entPerblk
08E1:48            297           pha
08E2:              298 *
08E2:              299 * Close the current directory, as ReadDir will
08E2:              300 * open files of its own, and we don't want to 
08E2:              301 * have a bunch of open files lying around.
08E2:              302 *
08E2:20 00 BF      303           jsr   MLI
08E5:CC            304           db    mliClose
08E6:E1 09         305           dw    CloseParms
08E8:              306 *
08E8:20 2F 09      307           jsr   ExtendName    ; make new dir name
08EB:              308 *
08EB:20 29 08      309           jsr   ReadDir1      ; enumerate the subdirectory
08EE:              310 *
08EE:20 65 09      311           jsr   ChopName      ; restore old directory name
08F1:              312 *
08F1:20 79 08      313           jsr   OpenDir       ; re-open it back up
08F4:90 01   08F7  314           bcc   reOpened
08F6:              315 *
08F6:              316 * Can't continue from this point -- exit in
08F6:              317 * whatever way is appropriate for your
08F6:              318 * program.
08F6:              319 *
08F6:00            320           brk
08F7:              321 *
08F7:        08F7  322 reOpened  equ   *
08F7:              323 *
08F7:              324 * Restore everything that we saved before
08F7:              325 *
08F7:68            326           pla
08F8:8D D2 09      327           sta   entPerBlk
08FB:68            328           pla
08FC:8D D1 09      329           sta   entryLen
08FF:68            330           pla
0900:8D D0 09      331           sta   ThisBlock
0903:68            332           pla
0904:8D CF 09      333           sta   ThisBEntry
0907:68            334           pla
0908:85 82         335           sta   entPtr
090A:68            336           pla
090B:85 83         337           sta   entPtr+1
090D:              338 *
090D:A9 00         339           lda   #0
090F:8D E5 09      340           sta   Mark
0912:8D E7 09      341           sta   Mark+2
0915:AD D0 09      342           lda   ThisBlock     ; reset last position in dir
0918:0A            343           asl   a             ; = to block # times 512
0919:8D E6 09      344           sta   Mark+1
091C:2E E7 09      345           rol   Mark+2
091F:              346 *
091F:20 00 BF      347           jsr   MLI           ; reset the file marker
0922:CE            348           db    mliSetMark

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 8
 
0923:E3 09         349           dw    SetMParms
0925:              350 *
0925:20 00 BF      351           jsr   MLI           ; now read in the block we
0928:CA            352           db    mliRead       ; were on last.
0929:D9 09         353           dw    ReadParms
092B:              354 *
092B:CE CE 09      355           dec   Depth
092E:60            356           rts
092F:              357 *
092F:              358 *******************************************************
092F:              359 *
092F:        092F  360 ExtendName equ  *
092F:              361 *
092F:              362 * Append the name in the current directory entry
092F:              363 * to the name in the directory name buffer. This
092F:              364 * will allow us to descend another level into the
092F:              365 * disk hierarchy when we call ReadDir.
092F:              366 *
092F:A0 00         367           ldy   #0            ; get length of string to copy
0931:B1 82         368           lda   (entPtr),y    
0933:29 0F         369           and   #$0F
0935:8D 62 09      370           sta   extCnt        ; save the length here
0938:8C 63 09      371           sty   srcPtr        ; init src ptr to zero
093B:              372 *
093B:A0 00         373           ldy   #0            ; init dest ptr to end of
093D:B1 80         374           lda   (dirName),y   ; the current directory name
093F:8D 64 09      375           sta   destPtr
0942:              376 *
0942:        0942  377 extloop   equ   *
0942:EE 63 09      378           inc   srcPtr        ; bump to next char to read
0945:EE 64 09      379           inc   destPtr       ; bump to next empty location
0948:AC 63 09      380           ldy   srcPtr        ; get char of sub-dir name
094B:B1 82         381           lda   (entPtr),y
094D:AC 64 09      382           ldy   destPtr       ; tack on to end of cur. dir.
0950:91 80         383           sta   (dirName),y
0952:CE 62 09      384           dec   extCnt        ; done all chars?
0955:D0 EB   0942  385           bne   extloop       ; no - so do more
0957:              386 *
0957:C8            387           iny
0958:A9 2F         388           lda   #'/'          ; tack "/" on to the end
095A:91 80         389           sta   (dirName),y
095C:              390 *
095C:98            391           tya                 ; fix length of filename to open
095D:A0 00         392           ldy   #0
095F:91 80         393           sta   (dirName),y
0961:              394 *
0961:60            395           rts
0962:              396 *
0962:        0001  397 extCnt    ds    1
0963:        0001  398 srcPtr    ds    1
0964:        0001  399 destPtr   ds    1
0965:              400 *
0965:              401 *
0965:              402 *******************************************************
0965:              403 *
0965:        0965  404 ChopName  equ   *
0965:              405 *
0965:              406 * Scans the current directory name, and chops

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 9
 
0965:              407 * off characters until it gets to a /.
0965:              408 *
0965:A0 00         409           ldy   #0            ; get len of current dir.
0967:B1 80         410           lda   (dirName),y
0969:A8            411           tay
096A:        096A  412 ChopLoop  equ   *
096A:88            413           dey                 ; bump to previous char
096B:B1 80         414           lda   (dirName),y
096D:C9 2F         415           cmp   #'/'
096F:D0 F9   096A  416           bne   ChopLoop
0971:98            417           tya
0972:A0 00         418           ldy   #0
0974:91 80         419           sta   (dirName),y
0976:60            420           rts
0977:              421 *
0977:              422 *******************************************************
0977:              423 *
0977:        0977  424 GetNext   equ   *
0977:              425 *
0977:              426 * This routine is responsible for making a pointer
0977:              427 * to the next entry in the directory. If there are
0977:              428 * still entries to be processed in this block, then
0977:              429 * we simply bump the pointer by the size of the
0977:              430 * directory entry. If we have finished with this
0977:              431 * block, then we read in the next block, point to
0977:              432 * the first entry, and increment our block counter.
0977:              433 *
0977:CE CF 09      434           dec   ThisBEntry    ; dec count for this block
097A:F0 10   098C  435           beq   ReadNext      ; done w/this block, get next one
097C:              436 *
097C:18            437           clc                 ; else bump up index
097D:A5 82         438           lda   entPtr
097F:6D D1 09      439           adc   entryLen
0982:85 82         440           sta   entPtr
0984:A5 83         441           lda   entPtr+1
0986:69 00         442           adc   #0
0988:85 83         443           sta   entPtr+1
098A:18            444           clc                 ; say that the buffer's good
098B:60            445           rts
098C:              446 *
098C:        098C  447 ReadNext  equ   *
098C:20 00 BF      448           jsr   MLI           ; get the next block
098F:CA            449           db    mliRead
0990:D9 09         450           dw    ReadParms
0992:B0 16   09AA  451           bcs   DirDone
0994:              452 *
0994:EE D0 09      453           inc   ThisBlock
0997:              454 *
0997:A9 EF         455           lda   #buffer+4     ; set entry pointer to beginning
0999:85 82         456           sta   entPtr        ; of first entry in block
099B:A9 09         457           lda   #<buffer+4
099D:85 83         458           sta   entPtr+1
099F:              459 *
099F:AD D2 09      460           lda   entPerBlk     ; re-init 'entries in this block'
09A2:8D CF 09      461           sta   ThisBEntry
09A5:CE CF 09      462           dec   ThisBEntry
09A8:18            463           clc                 ; return 'No error'
09A9:60            464           rts

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 10
 
09AA:              465 *
09AA:        09AA  466 DirDone   equ   *
09AA:38            467           sec               ; return 'an error occurred' (error in A)
09AB:60            468           rts
09AC:              469 *
09AC:              470 *******************************************************
09AC:              471 *
09AC:        09AC  472 PrintEntry equ  *
09AC:              473 *
09AC:              474 * Using the pointer to the current entry, this 
09AC:              475 * routine prints the entry name. It also pays
09AC:              476 * attention to the recursion depth, and indents
09AC:              477 * by 2 spaces for every level.
09AC:              478 *
09AC:AD CE 09      479           lda   Depth         ; indent two blanks for each level
09AF:0A            480           asl   a             ; of directory nesting
09B0:AA            481           tax
09B1:F0 08   09BB  482           beq   spcDone
09B3:A9 A0         483 spcloop   lda   #space
09B5:20 ED FD      484           jsr   cout
09B8:CA            485           dex
09B9:D0 F8   09B3  486           bne   spcloop
09BB:        09BB  487 spcDone   equ   *
09BB:              488 *
09BB:A0 00         489           ldy   #0            ; get byte that has the length byte
09BD:B1 82         490           lda   (entPtr),y
09BF:29 0F         491           and   #$0F          ; get just the length
09C1:AA            492           tax
09C2:        09C2  493 PrntLoop  equ   *
09C2:C8            494           iny                 ; bump to the next char.
09C3:B1 82         495           lda   (entPtr),y    ; get next char
09C5:09 80         496           ora   #$80          ; COUT likes high bit set
09C7:20 ED FD      497           jsr   cout          ; print it
09CA:CA            498           dex                 ; printed all chars?
09CB:D0 F5   09C2  499           bne   PrntLoop      ; no - keep going
09CD:60            500           rts
09CE:              501 *
09CE:              502 *******************************************************
09CE:              503 *
09CE:              504 * Some global variables
09CE:              505 *
09CE:        0001  506 Depth     ds    1             ; amount of recursion
09CF:        0001  507 ThisBEntry ds   1             ; entry in this block
09D0:        0001  508 ThisBlock ds    1             ; block with dir
09D1:        0001  509 entryLen  ds    1             ; length of each directory entry
09D2:        0001  510 entPerBlk ds    1             ; entries per block
09D3:              511 *
09D3:              512 *******************************************************
09D3:              513 *
09D3:              514 * ProDOS command parameter blocks
09D3:              515 *
09D3:        09D3  516 OpenParms equ   *
09D3:03            517           db    3             ; number of parms
09D4:        0002  518 OpenName  ds    2             ; pointer to filename
09D6:00 00         519 ioBuf     dw    $0000         ; I/O buffer
09D8:        0001  520 oRefNum   ds    1             ; returned refnum
09D9:              521 *
09D9:        09D9  522 ReadParms equ   *

01 CATALOG         ProDOS Catalog Routine              14-OCT-89  16:20 PAGE 11
 
09D9:04            523           db    4             ; number of parms
09DA:        0001  524 rRefNum   ds    1             ; refnum from Open
09DB:EB 09         525           dw    buffer        ; pointer to buffer
09DD:00 02         526 reqAmt    dw    512           ; amount to read
09DF:        0002  527 retAmt    ds    2             ; amount actually read
09E1:              528 *
09E1:        09E1  529 CloseParms equ  *
09E1:01            530           db    1             ; number of parms
09E2:        0001  531 cRefNum   ds    1             ; refnum from Open
09E3:              532 *
09E3:        09E3  533 SetMParms equ   *
09E3:02            534           db    2             ; number of parms
09E4:        0001  535 sRefNum   ds    1             ; refnum from Open
09E5:        0003  536 Mark      ds    3             ; file position
09E8:              537 *
09E8:        09E8  538 GetPParms equ   *
09E8:01            539           db    1             ; number of parms
09E9:EB 0B         540           dw    nameBuffer    ; pointer to buffer
09EB:              541 *
09EB:        0200  542 buffer    ds    512           ; enough for whole block
0BEB:              543 *
0BEB:        0040  544 nameBuffer ds   64            ; space for directory name

01 SYMBOL TABLE    SORTED BY SYMBOL                    14-OCT-89  16:20 PAGE 12
 
 09EB BUFFER         096A CHOPLOOP       0965 CHOPNAME       09E1 CLOSEPARMS    
 FDED COUT           09E2 CREFNUM        FD8E CROUT          09CE DEPTH         
 0964 DESTPTR        09AA DIRDONE          80 DIRNAME        084D DONE          
   4C ENDOFFILE      09D2 ENTPERBLK        82 ENTPTR         09D1 ENTRYLEN      
 081E EXIT           0962 EXTCNT         092F EXTENDNAME     0942 EXTLOOP       
 BEF5 GETBUFR        0977 GETNEXT        09E8 GETPPARMS      0878 HITDIREND     
 09D6 IOBUF          0845 ITSADIR        0831 LOOP           09E5 MARK          
   CC MLICLOSE         C7 MLIGETPFX        C8 MLIOPEN        BF00 MLI           
   CA MLIREAD          CE MLISETMARK     0BEB NAMEBUFFER     0848 NEXTENTRY     
   24 OENTBLK          23 OENTLEN        0879 OPENDIR        08B2 OPENDONE      
 09D4 OPENNAME       09D3 OPENPARMS      09D8 OREFNUM          00 OTYPE         
 FDDA PRBYTE         09AC PRINTENTRY     09C2 PRNTLOOP       0829 READDIR1      
 081F READDIR        098C READNEXT       09D9 READPARMS      08C9 RECURSDIR     
 08F7 REOPENED      ?09DD REQAMT        ?09DF RETAMT         09DA RREFNUM       
 09E3 SETMPARMS        A0 SPACE          09BB SPCDONE        09B3 SPCLOOP       
 0963 SRCPTR         09E4 SREFNUM       ?0800 START          09CF THISBENTRY    
 09D0 THISBLOCK      08BA VISITDIR       08B3 VISITFILE     
** SUCCESSFUL ASSEMBLY := NO ERRORS
** ASSEMBLER CREATED ON 15-JAN-84 21:28
** TOTAL LINES ASSEMBLED   544
** FREE SPACE PAGE COUNT   81

Further Reference


The Apple II Technical Notes have been converted to HTML by Aaron Heiss as a public service to the Apple II community, with permission by Apple Computer, Inc.

 

Any and all trademarks, registered and otherwise, are properties of their owners.