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
Any and all trademarks, registered and otherwise, are properties of their owners.