home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol146 / sd-48b.a86 < prev    next >
Encoding:
Text File  |  1984-04-29  |  56.3 KB  |  2,128 lines

  1. ; DATE 10/07/83  09:43   last revision
  2. ;
  3. ; SIG/M release REVIDEO set TRUE & INTOREV & OUTAREV set for ADM-31
  4. ;
  5.     TITLE    'SD Version 4.8B for CP/M-86'
  6. ;
  7. ; DATE 10/03/83  14:32
  8. ; by: H.M. Van Tassell 120 Hill Hollow Rd, Watchung, NJ 07060 (201)755-5372
  9. ;
  10. ; This is an XLT86 translation of SD-4.8B the original of which was released
  11. ; on SIG/M vol 145, see the original release for history and author credits.
  12. ;
  13. ; The "usual" minor changes have been made to enable the translation. 
  14. ; References to CP/M ver 2.2 and lower have been deleted, segment override
  15. ; added where required, and the version notice updated.
  16. ;
  17. ; NOTE: XLT86 deletes all conditional statements so this version is setup
  18. ; as shown in the USER OPTION SPECIFICATIONS. None of these options will
  19. ; work and are included here as reference for those who wish to add back
  20. ; any of the OPTIONS.
  21. ; I did add the REVIDEO option for those who dont wish to use enhanced video.
  22. ;
  23. ; This version should work with CP/M-86 ver 1.1, Concurrent 3.0, and Plus 3.1
  24. ; It works with my beta test copy of PLUS 3.1 but I have not tested Concurrent.
  25. ;
  26. ;         To generate program:
  27. ;         ASM86 SD $SZPZ
  28. ;         GENCMD SD 8080 CODE[M3FF]
  29. ;
  30. ;
  31. ;>>>> The following notes appeared in the preamble to CP/M-80 SD-4.8B. <<<<
  32. ;
  33. ; Made several changes to make SD more useful and friendly to me and maybe
  34. ; to others. Added HELP if // is filename or if a bad option specified.
  35. ; Changed so will always start with drive A: if D option choosen and no
  36. ; drive is specified in command line, user = 0 if A option choosen and no
  37. ; user was specified as an option,-see the new STARTZ, ZUSR & ZDRV.
  38. ; Added STSKIP & SKIPTO to skip over drives that dont exist but are in
  39. ; drive table. Useful for some of us that use M: to specify memory drive.
  40. ; To more closely conform to Digial Research notation used in CP/M PLUS,
  41. ; changed from "$" to "[]" to indicate options and eliminated need for a
  42. ; leading space and allow the use of either space or comma between options.
  43. ; Added code for 3 byte INTO/OUTA reverse video so can use esc,G,x code to
  44. ; indicate file attributes. Since directorys can be long, added a message 
  45. ; at start of each section, see STMSG equate. Added option 'T' which is
  46. ; a sort by filetype and then by filename, TOPREV reverses 'T' option.
  47. ; NOTE: Edit help message at start of code to match your choice of options
  48. ;             SD.ASM Ver 4.8A
  49. ;              (Rev 14 MAY 83)
  50. ;
  51. ;            SUPER DIRECTORY PROGRAM
  52. ;               by Bruce    R. Ratoff
  53. ;
  54. ;        Based on 'DIRS' by Keith Petersen, W8SDZ
  55. ;
  56. ; Displays the directory of a CP/M disk, sorted    alphabetically,
  57. ; with the file    size in    K, rounded to the nearest CP/M block size.
  58. ;
  59. ; This latest variation    on a common theme will automatically adjust
  60. ; itself for any block size and    directory length under CP/M 1.4    or 2.x
  61. ; or MP/M (any version).  Provisions are made for (1) automatic    pauses
  62. ; when the screen fills    up; (2)    searching individual or    multiple drives
  63. ; and/or user areas; (3) unconditional or optionally resetting the disk
  64. ; system before    execution begins; (4) directing    output to a disk file
  65. ; and appending    to it on subsequent runs; (5) summary line output giving
  66. ; drive    and user information, #    of files matched and how much space they
  67. ; consume, and the amount of free space    remaining on the disk; (6) displaying
  68. ; or suppressing CP/M 2    "system" files;    (7) accepting ambiguous    filenames
  69. ; with or without a drive name;    and (8)    printer    output.
  70. ; See SD.DOC for detailed instructions on configuring and running SD.ASM
  71. ;
  72.         ;******************************
  73.         ;*                  *
  74.         ;* USER OPTION SPECIFICATIONS *
  75.         ;*                  *
  76.         ;******************************
  77. ;
  78. ;****** NOTE: none of these work - they are here for reference only *****
  79. ;
  80. ;ALTCPM    EQU    FALSE        ;True for H8 or    TRS-80
  81. ;DIRCON    EQU    FALSE        ;True for direct console output
  82. ;LOWCCP    EQU    FALSE        ;True only if you are running with BYELOW
  83. ;BDOSPG    EQU    0CCh        ;Set properly if LOWCCP is true
  84. ;OPTION    EQU    TRUE        ;True if allowing ANY command line options
  85. ;AOPT    EQU    TRUE        ;True to allow searching all user areas
  86. ;DOPT    EQU    TRUE        ;True to allow searching all drives on-line
  87. ;STARTZ    EQU    TRUE        ;True to start with zero dr & user in none spec
  88. ;FOPT    EQU    TRUE        ;True to allow file output option
  89. ;NOPT    EQU    TRUE        ;True to allow disabling page pause option
  90. ;PGPAWZ    EQU    TRUE        ;True for pause after each page
  91. ;POPT    EQU    TRUE        ;True to allow printer option
  92. ;REPERR    EQU    TRUE        ;True to report command line option errors
  93. ;REPSIZ    EQU    TRUE        ;True to report file sizes
  94. ;REPUSR    EQU    TRUE        ;True to report user numbers
  95. ;RMAC    EQU    FALSE        ;True for RMAC assembly and external def link
  96. ;ROPT    EQU    TRUE        ;True to allow reset option
  97. ;SOPT    EQU    TRUE        ;True to allow system file option
  98. ;TOPT    EQU    TRUE        ;True for sort by filetype & filename
  99. ;TOPREV    EQU    FALSE        ;False to reverse "T" opt for normal sort
  100. ;UOPT    EQU    TRUE        ;True to allow user number option
  101. ;VOPT    EQU    TRUE        ;True to allow version number display
  102. ;LOPT    EQU    TRUE        ;True to allow Library file member printing
  103. ;LOPREV    EQU    FALSE        ;False to reverse the "L" option and not print
  104. ;************ See above NOTE in reference to above equates **************
  105.  
  106. ;===========================================================================
  107. M    EQU    Byte Ptr 0[BX]
  108. FALSE    EQU    0
  109. TRUE    EQU    NOT FALSE
  110.  
  111. REVIDEO    EQU    TRUE        ;Use reverse video sequences
  112. LEADIN    EQU    27        ;Esc. leadin for ADM-31 & Z19
  113. ; INTOREV EQU    3847H        ;Seq. to enter underline mode (for WYSE-200)
  114. ; OUTAREV EQU    3047H        ;and to get out ((note digits are reversed))
  115. ; NOTE: use a 2 digit INTO/OUTA sequence &  set one to 00 if only one needed
  116. INTOREV    EQU    0029H        ;Dim video for ADM-31 type terminals
  117. OUTAREV    EQU    0028H        ; "    "    "   "      "     "
  118. ; INTOREV    EQU    0070H        ;Sequence to enter reverse video (Z19)
  119. ; OUTAREV    EQU    0071H        ;And to get out
  120. ; LEADIN    EQU    '~'        ;Tilda leadin for hazeltine 1500
  121. ; INTOREV    EQU    0019H        ;Background mode on Hazeltine 1500
  122. ; OUTAREV    EQU    001FH        ;Foreground mode on Hazeltine 1500
  123. DELIM    EQU    7CH        ;Fence (delimiter) character (vertical bar)
  124. ;DELIM    EQU    20H        ;Space
  125. NPL    EQU    4        ;# of names per line (max of 3 for 64x16)
  126. ;                             (max of 4 for 80x24)
  127. LPS    EQU    23        ;# of lines per screen (max of 14 for 64x16)
  128. ;                               (max of 23 for 80x24)
  129. STMSG    EQU    TRUE        ;true to start each directory with message
  130. ;
  131. STSKIP    EQU    3        ;Start skipping at this drive number
  132. SKIPTO    EQU    13        ;and skip to this drive number
  133. ;
  134. ; BDOS equates
  135. ;
  136. RDCHR    EQU    1        ;Read char from    console
  137. WRCHR    EQU    2        ;Write char to console
  138. CONST    EQU    11        ;Check cons stat
  139. RESET    EQU    13        ;Reset disk system
  140. SELDSK    EQU    14        ;Select    disk
  141. OPEN    EQU    15        ;0FFH=not found
  142. CLOSE    EQU    16        ;   "    "
  143. SEARCH    EQU    17        ;   "    "
  144. NEXT    EQU    18        ;   "    "
  145. READ    EQU    20        ;not 0 = EOF
  146. WRITE    EQU    21        ;not 0 = disk full
  147. MAKE    EQU    22        ;0FFH =    directory full
  148. CURDSK    EQU    25        ;Get currently logged disk name
  149. SETDMA    EQU    26        ;Set current DMA
  150. GALLOC    EQU    27        ;Get address of    allocation vector
  151. CURDPB    EQU    31        ;Get current disk parameters
  152. CURUSR    EQU    32        ;Get currently logged user number 
  153.  
  154. BASE    EQU    0        ;Default to 0 (or 100H with MAC    +R option)
  155. TPA    EQU    100H
  156. FCB    EQU    BASE+5CH
  157. BDOS    EQU    BASE+5
  158.     
  159.     ORG    TPA
  160. ;********************************
  161. ;                *
  162. ; BEGIN    EXECUTABLE PROGRAM CODE    *
  163. ;                *
  164. ;********************************
  165.     JMP    START
  166. L_1    EQU    $
  167.     DSEG
  168.     ORG    Offset L_1
  169. MLEADIN    DB    LEADIN        ;leadin char for hilite sequences
  170. MINTOREV DW    INTOREV        ;code to enter hilite mode
  171. MOUTAREV DW    OUTAREV        ;code to return to normal mode
  172. MDELIM    DB    DELIM        ;char to delimit columns on display
  173. MNPL    DB    NPL        ;names per line (# of columns)
  174. MLPS    DB    LPS        ;lines per screen (between pauses)
  175.  
  176. VERNAME    RS    0
  177.     DB    'SD 4.8B-86  03Oct83/HMVT          ',0
  178.  
  179. HLPMES    DB    13,10,10
  180.     DB    'Useage: SD dr:FILENAME.TYP [option,option...]'
  181.     DB    13,10,10,'Drive and/or filespec are optional'
  182.     DB    13,10,'Wildcards * and ? allowed'
  183.     DB    13,10,'SD // for help'
  184.     DB    13,10,10,'Options Are:'
  185.     DB    13,10,09,'A=All Users'
  186.     DB    13,10,09,'D=All Disks'
  187.     DB    13,10,09,'F=Make File'
  188.     DB    13,10,09,'L=Library'
  189.     DB    13,10,09,'N=No Paging'
  190.     DB    13,10,09,'P=Printer'
  191.     DB    13,10,09,'R=Reset'
  192.     DB    13,10,09,'S=System'
  193.     DB    13,10,09,'T=Sort by Type'
  194.     DB    13,10,09,'Un=User No.'
  195.     DB    13,10,09,'V=Version',0
  196. L_2    EQU    $
  197.     CSEG
  198.     ORG    Offset L_2
  199. START:
  200.     MOV    CL,12            ;Get and save the CP/M version #
  201.     INT    224
  202.     MOV    AL,BL
  203.     MOV    Byte Ptr VERFLG,AL
  204.     MOV    DL,0FFH            ;Get current user number
  205.     MOV    CL,CURUSR        
  206.     CALL    CPM
  207.     MOV    Byte Ptr OLDUSR,AL    ;Initialize startup user number
  208.     MOV    Byte Ptr NEWUSR,AL    ;..and make new    user match it
  209.     MOV    Byte Ptr BASUSR,AL    ;Save extra copy for multi-disk    directories
  210.     MOV    CL,CURDSK
  211.     CALL    CPM            ;Get current disk nr
  212.     MOV    Byte Ptr OLDDSK,AL    ;Save for reset    if needed
  213.     INC    AL
  214.     MOV    Byte Ptr OUTFCB,AL    ;Set directory output file drive
  215. ; If at    least one option is allowed, scan the command line for the
  216. ; option field delimiter.  The option field delimiter is considered
  217. ; valid    only if    it is preceded by at least 1 space (otherwise, it
  218. ; may be part of the directory filename).  Any unrecognized options
  219. ; or illegal user numbers will be flagged or ignored (see REPERR).
  220. ; (We scan the command line buffer rather than the 2nd default FCB
  221. ; because all 8    options    plus a 2 digit user number won't fit in
  222. ; the FCB name field).
  223.     MOV    BX,80H            ;Set command line buffer+2 pointer
  224.     MOV    CH,M            ;Get length of command line buffer
  225. ; Check for a help request
  226.     INC    BX
  227.     INC    BX
  228.     MOV    AL,M
  229.     CMP    AL,'/'
  230.     JNZ    L_4    
  231.     CALL    HELP
  232. L_4:
  233.     LAHF
  234.     DEC    BX
  235.     SAHF
  236.     LAHF
  237.     DEC    BX
  238.     SAHF
  239. ; Search for the command line delimiter.  If not found, assume no options.
  240. SCNDOL:    LAHF
  241.     INC    BX
  242.     SAHF
  243.     DEC    CH
  244.     JNS    L_5    
  245.     JMP    CKREST            ;Exit if command line buffer empty
  246. L_5:
  247.     MOV    AL,M
  248.     CMP    AL,'['            ;Digital Research changing to "["
  249.     JNZ    SCNDOL
  250. ;    DCX    H        ;'$' found - make sure space precedes it
  251. ;    MOV    A,M
  252. ;    INX    H
  253. ;    CPI    ' '
  254. ;    JNZ    SCNDOL        ;No space - ignore "$" and search again
  255. ; Valid    delimiter found.  Scan the rest    of the buffer for options.  Errors
  256. ; past this point will cause an    abort if the command line error    option is
  257. ; enabled.  Otherwise, the dud option will be ignored and SD will attempt
  258. ; to continue stumbling    through    the rest of the    field.
  259.     XCHG    BX,DX            ;Get option field pointer to DE
  260. SCNOPT:    LAHF                ;Bump to next option field character
  261.     INC    DX
  262.     SAHF
  263.     DEC    CH            ;Dock characters left in option    field
  264.     JNS    L_6    
  265.     JMP    CKREST            ;If option field exhausted, exit
  266. L_6:
  267. SCNAGN:    MOV    SI,DX            ;Get the next option character
  268.     MOV    AL,[SI]
  269.     CMP    AL,' '            ;Do we have a space?
  270.     JZ    SCNOPT            ;Ignore    it if so
  271.     CMP    AL,','            ;Same for comma
  272.     JZ    SCNOPT
  273.     CMP    AL,']'            ;End of option list
  274.     JNZ    L_7    
  275.     JMP    CKREST
  276. L_7:
  277.     MOV    BX,(Offset OTBL)-1    ;Get base of option lookup table
  278.     MOV    CL,(Offset OEND)-(Offset OTBL)+1    ;Get length of option lookup table
  279. NOMACH:    INC    BX            ;Bump to next option table character
  280.     DEC    CL            ;Are we    out of the table?
  281.     JZ    CK4USR            ;If so, check for user option
  282.     CMP    AL,M            ;Compare our character with option table
  283.     JNZ    NOMACH            ;Exit if no match
  284.     MOV    M,0            ;Otherwise, activate the flag
  285.     JMPS    SCNOPT            ;..and go get the next option character
  286. ; If option character doesn't match the table, see if we have a User
  287. ; option.
  288. CK4USR:                ;Check for user    number option
  289.     CMP    AL,'U'
  290.     JNZ    CLERR            ;Last option, so bad deal if that ain't it
  291. UAGN:    LAHF                ;Bump to user number digit
  292.     INC    DX
  293.     SAHF
  294.     DEC    CH
  295.     JS    CLERR            ;Error if nothing left
  296.     MOV    SI,DX            ;Get decimal digit
  297.     MOV    AL,[SI]
  298.     CMP    AL,' '            ;Ignore    leading    spaces
  299.     JZ    UAGN
  300.     SUB    AL,30H            ;Subtract ASCII    BIAS
  301.     JB    CLERR            ;Error if < 0
  302.     CMP    AL,10
  303.     JNB    CLERR            ;Error if > 9
  304.     MOV    Byte Ptr NEWUSR,AL    ;Save user number as it    may be only 1 digit
  305.     MOV    Byte Ptr BASUSR,AL    ;Duplicate it if multi-disk mode
  306.     LAHF
  307.     XCHG    AL,AH
  308.     PUSH    AX
  309.     MOV    AL,0FFH            ;Set got user flag
  310.     MOV    Byte Ptr GOTUSR,AL
  311.     POP    AX
  312.     XCHG    AL,AH
  313.     SAHF
  314.     LAHF                ;Bump to possible 2nd digit of user number
  315.     INC    DX
  316.     SAHF
  317.     DEC    CH
  318.     JS    CKREST            ;If no more buffer, exit with complete user #
  319.     MOV    SI,DX            ;Else, check for another digit
  320.     MOV    AL,[SI]
  321.     SUB    AL,30H
  322.     JNB    L_8    
  323.     JMP    SCNAGN            ;If next char not numeric, its not part    of
  324. L_8:
  325.     CMP    AL,10            ;..user    number so go check for another option
  326.     JNAE    L_9    
  327.     JMP    SCNAGN
  328. L_9:
  329.     MOV    BL,AL            ;Save units digit
  330.     MOV    AL,Byte Ptr NEWUSR    ;Get tens digit
  331.     ADD    AL,AL            ;Multiply by 10
  332.     MOV    BH,AL
  333.     ADD    AL,AL
  334.     ADD    AL,AL
  335.     ADD    AL,BH
  336.     ADD    AL,BL            ;Combine with units digit
  337.     MOV    Byte Ptr NEWUSR,AL    ;Save the total    user number
  338.     MOV    Byte Ptr BASUSR,AL    ;Duplicate it if multi-disk mode
  339.     JMP    SCNOPT            ;Continue scanning
  340. ;Balance UOPT
  341. ; If command line error    option enabled,    playback the command line up
  342. ; to the character that    we gagged on and exit.    If REPERR is not enabled,
  343. ; then continue    as if nothing were amiss to avoid acknowledging    that
  344. ; some options are available.
  345. CLERR:
  346.     XOR    AL,AL
  347.     LAHF                ;Tag end of command line with terminator
  348.     INC    DX
  349.     SAHF
  350.     MOV    SI,DX
  351.     MOV    [SI],AL
  352.     CALL    CRLF
  353.     MOV    DX,(Offset ERRMS2)
  354.     CALL    PRINT
  355.     MOV    DX,(Offset ERRTAG)
  356.     CALL    PRINT
  357.     MOV    BX,81H            ;Playback bad command line to error point
  358. CLELP:    MOV    AL,M
  359.     OR    AL,AL
  360.     JZ    CLEX
  361.     CALL    TTYPE
  362.     INC    BX
  363.     JMPS    CLELP
  364. CLEX:    MOV    AL,'?'            ;Tag line with a '?' field
  365.     CALL    TTYPE
  366.     JMP    HELP1            ;..and tell how to do it
  367. ;Balance OPTION
  368. ; Options input or not specified.  If reset option specified, reset
  369. ; the disk system now.    Its important that the reset be done OUTSIDE
  370. ; the multiple drive loop if the file output option is enabled because
  371. ; CP/M 1.4 clobbers the DMA buffer on reset.
  372. CKREST:
  373.     MOV    AL,Byte Ptr ROPFLG    ;If reset flag set, reset disk system before
  374.     OR    AL,AL            ;..starting to update allocation vectors
  375.     MOV    CL,RESET
  376.     JNZ    L_10    
  377.     CALL    CPM
  378. L_10:
  379. ;Balance ROPT
  380.     MOV    AL,Byte Ptr VOPFLG    ;If version display flag set, print it
  381.     OR    AL,AL
  382.     JNZ    NOVOPT
  383.     MOV    DX,(Offset VERNAME)
  384.     CALL    PRINT
  385.     CALL    CRLF
  386. NOVOPT:
  387.     MOV    AL,Byte Ptr DOPFLG    ;If multi-disk flag set, 
  388.     OR    AL,AL            ;..need to set error traps
  389.     JNZ    L_11    
  390.     CALL    SWAPEM            ;Swap BDOS error vector    tables
  391. L_11:
  392. ; If "A" option choosen and no user number specified
  393. ; set user to zero
  394. ZUSR:    MOV    AL,Byte Ptr GOTUSR    ;Was a user specified?
  395.     OR    AL,AL
  396.     JNZ    ZDRV            ;YES-quit now
  397.     MOV    AL,Byte Ptr AOPFLG    ;Was D option specified?
  398.     OR    AL,AL
  399.     JNZ    ZDRV            ;JMP if NO
  400.     XOR    AL,AL
  401.     MOV    Byte Ptr NEWUSR,AL    ;ZERO NEWUSR for all users
  402.     MOV    Byte Ptr BASUSR,AL    ;ZERO BASUSR for all users
  403. ; If "D" option choosen and no drive specified
  404. ; set drive to physical zero
  405. ZDRV:    MOV    BX,FCB
  406.     MOV    AL,M            ;Get drive name    for directory search
  407.     OR    AL,AL            ;Any specified?
  408.     JNZ    NOOPT            ;Yes skip next routine
  409.     MOV    AL,Byte Ptr DOPFLG    ;else if DOPT then
  410.     OR    AL,AL
  411.     JNZ    ZDRV1
  412.     INC    AL            ;always start with A
  413.     MOV    M,AL
  414.     JMPS    NOOPT
  415. ZDRV1:    MOV    AL,Byte Ptr OLDDSK    ;Otherwise, get    default    disk
  416.     INC    AL
  417.     MOV    M,AL            ;Put the absolute drive    code in    directory FCB
  418. ; Validate drive code and user area numbers from the drive table.
  419. NOOPT:    MOV    DX,(Offset DREMSG)    ;Get the drive/user error message
  420.     PUSH    DX
  421.     MOV    AL,Byte Ptr .FCB    ;Get directory drive code
  422.     DEC    AL            ;Normalize to range of 0-15
  423.     CMP    AL,(Offset HIDRV)-(Offset LODRV)    ;Compare with maximum drives on-line
  424.     JNAE    L_12    
  425.     JMP    ERXIT            ;Take drive error exit if out of range
  426. L_12:
  427.     MOV    BX,(Offset USRMSG)    ;Switch    to user    # error    message
  428.     MOV    BP,SP
  429.     XCHG    BX,[BP]
  430.     MOV    DL,AL            ;Use drive code    as index into table
  431.     MOV    DH,0
  432.     MOV    BX,(Offset LODRV)    ;Point to base of drive/user table
  433.     ADD    BX,DX
  434.     MOV    AL,M            ;Get the maximum user #    for this drive
  435.     AND    AL,0FH            ;Make sure its in range    0 - 15
  436.     MOV    Byte Ptr MAXUSR,AL    ;Save it for later
  437.     MOV    BX,(Offset NEWUSR)    ;Point to the directory    user area
  438.     CMP    AL,M            ;Compare it with the maximum
  439.     JNB    L_13    
  440.     JMP    ERXIT            ;Take error exit if user number    illegal
  441. L_13:
  442.     POP    DX            ;Destroy error message pointer
  443.     MOV    BX,FCB+1        ;Point to name
  444.     MOV    AL,M            ;Any specified?
  445.     CMP    AL,'['
  446.     JZ    GOTDL
  447.     CMP    AL,' '
  448.     JNZ    GOTFCB
  449. ; No FCB - make    FCB all    '?'
  450. GOTDL:    MOV    CH,11            ;FN+FT count
  451. QLOOP:    MOV    M,'?'            ;Store '?' IN FCB
  452.     INC    BX
  453.     DEC    CH
  454.     JNZ    QLOOP
  455. GOTFCB:    MOV    AL,'?'            ;Force wild extent
  456.     MOV    Byte Ptr .FCB+12,AL
  457.     CALL    SETSRC            ;Set DMA for BDOS media change check
  458.     MOV    BX,FCB            ;Point to FCB drive code for directory
  459.     MOV    DL,M            ;Get the drive code out of the FCB
  460.     DEC    DL            ;Normalize drive code for SELECT
  461.     MOV    CL,SELDSK        ;Select the directory drive to retrieve
  462.     CALL    CPM            ;..the proper allocation vector
  463.     MOV    CL,CURDPB        ;request DPB
  464.     INT    224
  465.     INC    BX
  466.     INC    BX
  467.     MOV    AL,ES:M            ;Get block shift
  468.     MOV    Byte Ptr BLKSHF,AL
  469.     INC    BX            ;Bump to block mask
  470.     MOV    AL,ES:M
  471.     MOV    Byte Ptr BLKMSK,AL    ;Get it
  472.     INC    BX
  473.     INC    BX
  474.     MOV    DL,ES:M            ;Get max block #
  475.     INC    BX
  476.     MOV    DH,ES:M
  477.     XCHG    BX,DX
  478.     MOV    Word Ptr BLKMAX,BX    ;Save it
  479.     XCHG    BX,DX
  480.     INC    BX
  481.     MOV    DL,ES:M            ;Get directory size
  482.     INC    BX
  483.     MOV    DH,ES:M
  484.     XCHG    BX,DX
  485.  
  486. ; Calculate # of K free    on selected drive now so that the FREE figure
  487. ; will not reflect either the creation or additions to the SD.DIR
  488. ; file (which we would probably    erase or move anyway).
  489. FREE:    MOV    Word Ptr DIRMAX,BX    ;Save max # of entries in directory
  490.     MOV    AL,Byte Ptr VERFLG    ;check version #
  491.     CMP    AL,30H            ;3.0 or higher?
  492.     JB    FREE20            ;use old method if not
  493.     MOV    AL,Byte Ptr .FCB    ;get drive #
  494.     DEC    AL
  495.     MOV    DL,AL            ;Use new Compute Free Space BDOS call
  496.     MOV    CL,46
  497.     CALL    CPM
  498.     MOV    CL,3            ;answer is a 24-bit integer
  499. FRE3L1:
  500.     MOV    BX,BASE+82H        ;answer is in 1st 3 bytes of DMA adr
  501.     MOV    CH,3            ;convert it from sectors to K
  502.     OR    AL,AL            ;by dividing by 8
  503. FRE3L2:
  504.     MOV    AL,M
  505.     RCR    AL,1
  506.     MOV    M,AL
  507.     DEC    BX
  508.     DEC    CH
  509.     JNZ    FRE3L2            ;Loop for 3 bytes
  510.     DEC    CL
  511.     JNZ    FRE3L1            ;Shift 3 times
  512.     MOV    BX,Word Ptr .BASE+80H    ;Now get result in K
  513.     JMPS    SAVFRE            ;Go store it
  514. FREE20:
  515.     MOV    CL,GALLOC        ;Get address of    allocation vector
  516.     INT    224            ;address ret as ES:BX
  517.     XCHG    BX,DX            
  518.     MOV    BX,Word Ptr BLKMAX    ;Get its length
  519.     INC    BX
  520.     MOV    CX,0            ;Init block count to 0
  521. GSPBYT:    PUSH    DX            ;Save alloc address
  522.     MOV    SI,DX            ;offset in SI
  523.     MOV    AL,ES:[SI]        ;seg in ES
  524.     MOV    DL,8            ;Set to    process    8 blocks
  525. GSPLUP:    RCL    AL,1            ;Test bit
  526.     JB    NOTFRE
  527.     INC    CX
  528. NOTFRE:    MOV    DH,AL            ;Save bits
  529.     DEC    BX            ;Count down blocks
  530.     MOV    AL,BL
  531.     OR    AL,BH
  532.     JZ    ENDALC            ;Quit if out of    blocks
  533.     MOV    AL,DH            ;Restore bits
  534.     DEC    DL            ;Count down 8 bits
  535.     JNZ    GSPLUP            ;Do another bit
  536.     POP    DX            ;Bump to next byte..
  537.     INC    DX            ;..of alloc. vector
  538.     JMPS    GSPBYT            ;Process it
  539. ENDALC:    POP    DX            ;Clear allocation vector pointer from stack
  540.     MOV    BL,CL            ;Copy blocks to    hl
  541.     MOV    BH,CH
  542.     MOV    AL,Byte Ptr BLKSHF    ;Get block shift factor
  543.     SUB    AL,3            ;Convert from sectors to K
  544.     JZ    SAVFRE            ;Skip shifts if 1K blocks - return free in HL
  545. FREKLP:    SHL    BX,1            ;Multiply blocks by K/BLK
  546.     DEC    AL
  547.     JNZ    FREKLP
  548. SAVFRE:    MOV    Word Ptr FREEBY,BX    ;Save the free space for output later
  549. ; Reenter here on subsequent passes while in the all-users mode
  550. SETTBL:    MOV    BX,Word Ptr DIRMAX    ;Get directory maximum again
  551.     INC    BX            ;Directory size    is DIRMAX+1
  552.     SHL    BX,1            ;Double    directory size
  553.     MOV    DX,(Offset ORDER)    ;To get    size of    order table
  554.     ADD    BX,DX            ;Allocate order    table
  555.     MOV    Word Ptr TBLOC,BX    ;Name table begins where order table ends
  556.     MOV    Word Ptr NEXTT,BX
  557.     XCHG    BX,DX
  558.     MOV    BX,Word Ptr .BDOS+1    ;Make sure we have room    to continue
  559.     MOV    AL,DL
  560.     SUB    AL,BL
  561.     MOV    AL,DH
  562.     SBB    AL,BH
  563.     JNAE    L_14    
  564.     JMP    OUTMEM
  565. L_14:
  566.     MOV    AL,Byte Ptr NEWUSR    ;Get user area for directory
  567.     MOV    DL,AL
  568.     MOV    CL,CURUSR        ;Get the user function
  569.     CALL    CPM            ;..and set new user number
  570.  
  571. ; Look up the FCB in the directory
  572. SFIRST:    MOV    BX,0
  573.     MOV    Word Ptr COUNT,BX    ;Initialize match counter
  574.     MOV    Word Ptr TOTFIL,BX    ;     "        total file counter
  575.     MOV    Word Ptr TOTSIZ,BX    ;     "        total size counter
  576.     CALL    SETSRC            ;Set DMA for directory search
  577.     MOV    CL,SEARCH        ;Get 'search first' function
  578.     JMPS    LOOK            ;..and go search for 1st match
  579. ; Read more directory entries
  580. MORDIR:    MOV    CL,NEXT            ;Search    next
  581. LOOK:    MOV    DX,FCB
  582.     CALL    CPM            ;Read directory    entry
  583.     INC    AL            ;Check for end (0FFH)
  584.     JNZ    L_16    
  585.     JMP    SPRINT            ;If no more, sort & print what we have
  586. L_16:
  587. ; Point    to directory entry
  588. SOME:    DEC    AL            ;Undo prev 'INR A'
  589.     AND    AL,3            ;Make modulus 4
  590.     ADD    AL,AL            ;Multiply...
  591.     ADD    AL,AL            ;..by 32 because
  592.     ADD    AL,AL            ;..each    directory
  593.     ADD    AL,AL            ;..entry is 32
  594.     ADD    AL,AL            ;..bytes long
  595.     MOV    BX,BASE+81H        ;Point to buffer
  596. ;(skip to FN/FT)
  597.     ADD    AL,BL            ;Point to entry
  598.     ADD    AL,9            ;Point to SYS byte
  599.     MOV    BL,AL            ;Save (can't carry to H)
  600.     MOV    AL,Byte Ptr SOPFLG    ;Did user request SYS files?
  601.     OR    AL,AL
  602.     JZ    SYSFOK
  603.     MOV    AL,M            ;Get SYS byte
  604.     OR    AL,AL            ;Check bit 7
  605.     JS    MORDIR            ;Skip that file
  606. SYSFOK:    MOV    AL,BL            ;Go back now
  607.     SUB    AL,10            ;Back to user number (alloc flag)
  608.     MOV    BL,AL            ;HL points to entry now
  609.     MOV    AL,Byte Ptr NEWUSR    ;Get current user
  610.     CMP    AL,M
  611.     JNZ    MORDIR            ;Ignore    if different
  612.     INC    BX
  613. ; Move entry to    table
  614.     XCHG    BX,DX            ;Entry to DE
  615.     MOV    BX,Word Ptr NEXTT    ;Next table entry to HL
  616.     MOV    CH,12            ;Entry length (name, type, extent)
  617. TMOVE:    MOV    SI,DX            ;Get entry char
  618.     MOV    AL,[SI]
  619.     MOV    M,AL            ;Store in table
  620.     INC    DX
  621.     INC    BX
  622.     DEC    CH            ;More?
  623.     JNZ    TMOVE
  624.     INC    DX
  625.     INC    DX            ;Point to sector count
  626.     MOV    SI,DX            ;Get it
  627.     MOV    AL,[SI]
  628.     MOV    M,AL            ;Store in table
  629.     INC    BX
  630.     MOV    Word Ptr NEXTT,BX    ;Save updated table addr
  631.     XCHG    BX,DX
  632.     MOV    BX,Word Ptr COUNT    ;Bump the # of matches made
  633.     INC    BX
  634.     MOV    Word Ptr COUNT,BX
  635.     MOV    BX,13            ;Size of next entry
  636.     ADD    BX,DX
  637.     XCHG    BX,DX            ;Future    NEXTT is in DE
  638.     MOV    BX,Word Ptr .BDOS+1    ;Pick up TPA end
  639.     MOV    AL,DL
  640.     SUB    AL,BL            ;Compare NEXTT-TPA end
  641.     MOV    AL,DH
  642.     SBB    AL,BH
  643.     JNB    L_17    
  644.     JMP    MORDIR            ;If TPA    END > NEXTT then loop back for more
  645. L_17:
  646. OUTMEM:    CALL    ERXIT            ;Exit if directory too large
  647.     DB    'Memor','y',0
  648. ; Sort and print
  649. SPRINT:
  650.     CALL    SETFOP            ;Return to file output DMA & user #
  651.     MOV    BX,Word Ptr COUNT    ;Get file name count
  652.     MOV    AL,BL
  653.     OR    AL,BH            ;Any found?
  654.     JNZ    L_18    
  655.     JMP    PRTOTL            ;Exit if no files found
  656. L_18:
  657.     PUSH    BX            ;Save file count
  658.     MOV    Byte Ptr SUPSPC,AL    ;Enable    leading    zero suppression
  659. ; Initialize the order table
  660.     MOV    BX,Word Ptr TBLOC    ;Get start of name table
  661.     XCHG    BX,DX            ;Into DE
  662.     MOV    BX,(Offset ORDER)    ;Point to order    table
  663.     MOV    CX,13            ;Entry length
  664. BLDORD:    MOV    M,DL            ;Save low order    address
  665.     INC    BX
  666.     MOV    M,DH            ;Save high order address
  667.     INC    BX
  668.     XCHG    BX,DX            ;Table addr to HL
  669.     ADD    BX,CX            ;Point to next entry
  670.     XCHG    BX,DX
  671.     MOV    BP,SP            ;Save tbl addr,    fetch loop counter
  672.     XCHG    BX,[BP]
  673.     DEC    BX            ;Count down loop
  674.     MOV    AL,BL
  675.     OR    AL,BH            ;More?
  676.     MOV    BP,SP            ;(restore tbl addr, save counter)
  677.     XCHG    BX,[BP]
  678.     JNZ    BLDORD            ;Yes, go do another one
  679.     POP    BX            ;Clean loop counter off    stack
  680.     MOV    BX,Word Ptr COUNT    ;Get count
  681.     MOV    Word Ptr SCOUNT,BX    ;Save as # to sort
  682.     DEC    BX            ;Only 1    entry?
  683.     MOV    AL,BL
  684.     OR    AL,BH
  685.     JNZ    L_19    
  686.     JMP    DONE            ;Yes, so skip sort
  687. L_19:
  688. ; This sort routine is adapted from SOFTWARE TOOLS
  689. ; by Kernigan and Plaugher.
  690. SORT:    MOV    BX,Word Ptr SCOUNT    ;Number    of entries
  691. L0:    OR    AL,AL            ;Clear carry
  692.     MOV    AL,BH            ;GAP=GAP/2
  693.     RCR    AL,1
  694.     MOV    BH,AL
  695.     MOV    AL,BL
  696.     RCR    AL,1
  697.     MOV    BL,AL
  698.     OR    AL,BH            ;Is it zero?
  699.     JNZ    L_20    
  700.     JMP    DONE            ;Then none left
  701. L_20:
  702.     MOV    AL,BL            ;Make gap odd
  703.     OR    AL,01
  704.     MOV    BL,AL
  705.     MOV    Word Ptr GAP,BX
  706.     INC    BX            ;I=GAP+1
  707. SL2:    MOV    Word Ptr I,BX
  708.     XCHG    BX,DX
  709.     MOV    BX,Word Ptr GAP
  710.     MOV    AL,DL            ;J=I-GAP
  711.     SUB    AL,BL
  712.     MOV    BL,AL
  713.     MOV    AL,DH
  714.     SBB    AL,BH
  715.     MOV    BH,AL
  716. SL3:    MOV    Word Ptr J,BX
  717.     XCHG    BX,DX
  718.     MOV    BX,Word Ptr GAP        ;JIG=J+GAP
  719.     LAHF
  720.     ADD    BX,DX
  721.     SAHF
  722.     MOV    Word Ptr JIG,BX
  723.     CALL    COMPARE            ;Compare (J) and (JIG)
  724.     JNS    SL5            ;If A(J)<=A(JIG)
  725.     MOV    BX,Word Ptr J
  726.     XCHG    BX,DX
  727.     MOV    BX,Word Ptr JIG
  728.     CALL    SWAP            ;Exchange A(J) and A(JIG)
  729.     MOV    BX,Word Ptr J        ;J=J-GAP
  730.     XCHG    BX,DX
  731.     MOV    BX,Word Ptr GAP
  732.     MOV    AL,DL
  733.     SUB    AL,BL
  734.     MOV    BL,AL
  735.     MOV    AL,DH
  736.     SBB    AL,BH
  737.     MOV    BH,AL
  738.     JS    SL5            ;If J>0    GOTO SL3
  739.     OR    AL,BL            ;Check for zero
  740.     JZ    SL5
  741.     JMPS    SL3
  742. SL5:    MOV    BX,Word Ptr SCOUNT    ;For later
  743.     XCHG    BX,DX
  744.     MOV    BX,Word Ptr I        ;I=I+1
  745.     INC    BX
  746.     MOV    AL,DL            ;IF I<=N GOTO SL2
  747.     SUB    AL,BL
  748.     MOV    AL,DH
  749.     SBB    AL,BH
  750.     JS    L_21    
  751.     JMP    SL2
  752. L_21:
  753.     MOV    BX,Word Ptr GAP
  754.     JMP    L0
  755. ; Sort is all done - print entries
  756. DONE:                    ;If output option wanted, prepare file
  757.     MOV    AL,Byte Ptr FOPFLG
  758.     OR    AL,AL
  759.     JZ    L_22    
  760.     JMP    NOOUT            ;If file output, fall through with A=0
  761. L_22:
  762. ; If all user option enabled, and we're not on the first pass, then the
  763. ; output file is already open and positioned, so we can skip the open.
  764. ;    IF    AOPT
  765.     MOV    BX,(Offset OPNFLG)    ;point to output file open flag
  766.     CMP    AL,M            ;a=0, set z if opnflg=0 also
  767.     JZ    L_23    
  768.     JMP    NOOUT            ;if opnflg not zero, skip open
  769. L_23:
  770.     DEC    M            ;else, make opnflg not zero and open
  771. ;    ENDIF            ;Balance AOPT
  772. ; First pass on file append - prepare SD.DIR to receive new or appended
  773. ; output.
  774.     MOV    DX,(Offset OUTFCB)    ;Does output file already exist?
  775.     MOV    CL,SEARCH
  776.     CALL    CPM
  777.     INC    AL
  778.     JNZ    OPENIT            ;If it does, then open it for processing
  779.     MOV    CL,MAKE            ;Otherwise, create the output file
  780.     CALL    CPM
  781.     INC    AL
  782.     JZ    L_24    
  783.     JMP    NOOUT            ;Continue if open successful
  784. L_24:
  785. ; If make or open fails, declare error
  786. OPNERR:    CALL    ERXIT
  787.     DB    'Ope','n',0
  788. WRTERR:    CALL    ERXIT
  789.     DB    'Writ','e',0
  790. ; Output file already exists - open it and position to the last
  791. ; record of the    last extent.
  792. OPENIT:    MOV    CL,OPEN            ;Open 1st extent of output file
  793.     CALL    CPM
  794.     INC    AL
  795.     JZ    OPNERR            ;Bad deal if 1st won't open
  796. OPNMOR:    MOV    AL,Byte Ptr OUTFCB+15
  797.     CMP    AL,128
  798.     JB    LSTEXT            ;If RC<128, this is last extent
  799.     MOV    BX,(Offset OUTFCB)+12
  800.     INC    M            ;Else, bump to next extent
  801.     MOV    CL,OPEN            ;..and try to open it
  802.     CALL    CPM
  803.     INC    AL
  804.     JNZ    OPNMOR            ;Continue opening extents til no more
  805.     DEC    M            ;Then, reopen preceding    extent
  806.     MOV    CL,OPEN
  807.     CALL    CPM
  808.     MOV    AL,Byte Ptr OUTFCB+15    ;Get RC    for the    last extent
  809. ; At this point, OUTFCB is opened to the last extent of the file,
  810. ; so read in the last record in the last extent.
  811. LSTEXT:    OR    AL,AL            ;Is this extent    empty?
  812.     JZ    NOOUT            ;If so, then we're starting a clean slate
  813.     DEC    AL            ;Normalize record count
  814.     MOV    Byte Ptr OUTFCB+32,AL    ;Set record number to read
  815.     MOV    CL,READ            ;..and read last record    of file
  816.     CALL    CPM
  817.     OR    AL,AL            ;Was read successful?
  818.     JZ    RDOK            ;If so,    proceed    to scan    for EOF    mark
  819. APERR:    CALL    ERXIT
  820.     DB    'Appen','d',0
  821. ; We now have the last record in the file in our buffer.
  822. ; Scan the last    record for the EOF mark, indicating where
  823. ; we can start adding data.
  824. RDOK:    MOV    BX,(Offset OUTBUF)    ;Point to start of output buffer
  825.     MOV    CH,128            ;Get length of output buffer
  826. SCAN:    MOV    AL,M
  827.     CMP    AL,'Z'-40H        ;Have we found end of file?
  828.     JZ    RESCR            ;If so, save pointers and reset CR
  829.     LAHF
  830.     INC    BX
  831.     SAHF
  832.     DEC    CH
  833.     JNZ    SCAN            ;Otherwise, keep looking til end of buffer
  834. ; If we find an explicit EOF mark in the last buffer (or an implied EOF
  835. ; if the last record is full), move the FCB record and extent pointers
  836. ; back to correct for the read operation so that our first write operation
  837. ; will effectively replace the last record of the SD.DIR file.
  838. RESCR:    PUSH    BX            ;Save EOF buffer pointer
  839.     PUSH    CX            ;Save EOF buffer remaining
  840.     MOV    BX,(Offset OUTFCB)+32    ;Get current record again
  841.     DEC    M            ;Dock it
  842.     JNS    SAMEXT            ;If CR >=0, we're still in same extent
  843.     MOV    BX,(Offset OUTFCB)+12    ;Else, move to previous    extent
  844.     DEC    M
  845.     MOV    CL,OPEN            ;Then, reopen the previous extent
  846.     CALL    CPM
  847.     INC    AL
  848.     JZ    APERR            ;Append position error if we can't reopen
  849.     MOV    AL,Byte Ptr OUTFCB+15    ;Else, position to last record of extent
  850.     DEC    AL
  851.     MOV    Byte Ptr OUTFCB+32,AL
  852. SAMEXT:    POP    AX            ;Recall where EOF is in buffer
  853.     XCHG    AL,AH
  854.     SAHF
  855.     MOV    Byte Ptr BUFCNT,AL    ;..and set buffer counter
  856.     POP    BX            ;Recall next buffer pointer
  857.     MOV    Word Ptr BUFPNT,BX    ;.. and set pointer for first addition
  858. ;Balance FOPT
  859. NOOUT:
  860.     MOV    BX,Word Ptr COUNT
  861.     MOV    Word Ptr LCOUNT,BX
  862.     MOV    BX,0
  863.     MOV    Word Ptr LBTOTL,BX
  864.     MOV    Word Ptr LMTOTL,BX
  865.     MOV    BX,(Offset ORDER)    ;Initialize order table    pointer
  866.     MOV    Word Ptr NEXTL,BX
  867.     MOV    Word Ptr NEXTT,BX
  868. ;Print "Driectory for...
  869. XXX:    MOV    DX,(Offset DIRMS1)    ;at start of each section
  870.     CALL    PRINT
  871.     CALL    PRDIR            ;Print " Drive, x User, y"
  872.     MOV    AL,Byte Ptr LINCNT
  873.     INC    AL            ;Bump line count
  874.     MOV    Byte Ptr LINCNT,AL
  875.     JMP    NEWLIN            ;Start new line    and output the files
  876. ; Output the directory files we've matched.
  877. ENTRY:    MOV    BX,Word Ptr COUNT
  878.     DEC    BX            ;Dock file count
  879.     MOV    Word Ptr COUNT,BX
  880.     MOV    AL,BH            ;Is this the last file?
  881.     OR    AL,BL
  882.     JZ    OKPRNT            ;If COUNT=0, last file so skip compare
  883. ; Compare each entry to    make sure that it isn't part of a multiple
  884. ; extent file.    Go only    when we    have the last extent of    the file.
  885.     PUSH    CX            ;Save NPL
  886.     CALL    CKABRT            ;Check for abort code from keyboard
  887.     MOV    BX,Word Ptr NEXTT
  888.     MOV    AL,11
  889.     CALL    COMPR            ;Does this entry match next one?
  890.     POP    CX            ;Recall    NPL
  891.     JNZ    OKPRNT            ;No, print it
  892.     INC    BX
  893.     INC    BX            ;Skip since highest extent comes last in list
  894.     MOV    Word Ptr NEXTT,BX
  895.     JMPS    ENTRY            ;Loop back for next lowest extent
  896. ; Valid    entry obtained - spit it out.
  897. OKPRNT:    MOV    BX,Word Ptr NEXTT    ;Get order table pointer
  898.     MOV    DL,M            ;Get low order address
  899.     INC    BX
  900.     MOV    DH,M            ;Get high order    address
  901.     INC    BX
  902.     MOV    Word Ptr NEXTT,BX    ;Save updated table pointer
  903.     XCHG    BX,DX            ;Table entry to    HL
  904.     MOV    CH,8            ;File name length
  905.     CALL    TYPEIT            ;Type filename
  906.     MOV    AL,'.'            ;Period    after FN
  907.     CALL    TTYPE
  908.     MOV    CH,3            ;Display 3 characters of filetype
  909.     CALL    TYPEIT
  910. ; Compute the size of the file and update our summary datum.
  911.     MOV    DL,M            ;Get extent #
  912.     MOV    DH,0
  913.     INC    BX
  914.     MOV    AL,M            ;Get sector count of last extent
  915.     XCHG    BX,DX
  916.     SHL    BX,1            ;# of extents times 16k
  917.     SHL    BX,1
  918.     SHL    BX,1
  919.     SHL    BX,1
  920.     XCHG    BX,DX            ;Save in DE
  921.     MOV    BX,(Offset BLKMSK)
  922.     ADD    AL,M            ;Round last extent to block size
  923.     ROR    AL,1
  924.     ROR    AL,1            ;Convert from sectors to K
  925.     ROR    AL,1
  926.     AND    AL,1FH
  927.     MOV    BL,AL            ;Add to    total K
  928.     MOV    BH,0
  929.     ADD    BX,DX
  930.     MOV    AL,Byte Ptr BLKMSK    ;Get SECTORS/BLK-1
  931.     ROR    AL,1
  932.     ROR    AL,1            ;Convert to K/BLK
  933.     ROR    AL,1
  934.     AND    AL,1FH
  935.     NOT    AL            ;Use to    finish rounding
  936.     AND    AL,BL
  937.     MOV    BL,AL
  938.     XCHG    BX,DX            ;Save file size    in DE
  939.     MOV    BX,Word Ptr TOTSIZ
  940.     LAHF                ;Add to    total used
  941.     ADD    BX,DX
  942.     RCR    SI,1
  943.     SAHF
  944.     RCL    SI,1
  945.     MOV    Word Ptr TOTSIZ,BX
  946.     MOV    BX,Word Ptr TOTFIL    ;Increment file    count
  947.     LAHF
  948.     INC    BX
  949.     SAHF
  950.     MOV    Word Ptr TOTFIL,BX
  951.     XCHG    BX,DX            ;Get back file size
  952. ; If report size enabled, output the size of the individual file.
  953. ;If file size report wanted
  954.     CALL    DECPRT            ;..go print it
  955.     MOV    AL,'k'            ;..and follow with K size
  956.     CALL    TTYPE
  957. ; One file output - test to see    if we have to output another one.
  958.     MOV    BX,Word Ptr COUNT    ;Get current file counter and test it
  959.     MOV    AL,BH
  960.     OR    AL,BL
  961.     JNZ    L_25    
  962.     JMP    PRTOTL            ;If no more files, exit    to summary output
  963. L_25:
  964. ; At least one more file to output - can we put    it on the current line?
  965.     DEC    CL
  966.     LAHF
  967.     XCHG    AL,AH
  968.     PUSH    AX
  969.     JZ    L_26    
  970.     CALL    FENCE            ;If room left, output the fence    character
  971. L_26:
  972.     POP    AX
  973.     XCHG    AL,AH
  974.     SAHF
  975.     JZ    L_27    
  976.     JMP    ENTRY            ;.. and    go output another file
  977. L_27:
  978. ; Current line full, start a new one.
  979. NEWLIN:    MOV    AL,Byte Ptr MNPL
  980.     MOV    CL,AL            ;Reset names per line counter
  981.     CALL    CRLF            ;Space down to next line
  982.     MOV    AL,3            ;If printing less than 4 wide
  983.     CMP    AL,CL
  984.     JB    NWLA
  985.     MOV    AL,Byte Ptr .FCB    ;.. precede new    line with drive    name
  986.     ADD    AL,'A'-1
  987.     CALL    TTYPE
  988. ;If reporting user numbers 
  989.     CALL    TYPUSR
  990.  
  991. ;Balance REPUSR
  992.     MOV    AL,':'            ;Tag header with a colon and a space
  993.     CALL    FPAD            ;..and exit back to ENTRY
  994. NWLA:
  995.     JMP    ENTRY            ;Go back and output another file
  996. ; Print    HL in decimal with leading zero    suppression
  997. DECPRT:    SUB    AL,AL            ;Clear leading zero flag
  998.     MOV    Byte Ptr LZFLG,AL
  999.     MOV    DX,-1000        ;Print 1000's digit
  1000.     CALL    DIGIT
  1001.     MOV    DX,-100            ;Etc.
  1002.     CALL    DIGIT
  1003.     MOV    DX,-10
  1004.     CALL    DIGIT
  1005.     MOV    AL,'0'            ;Get 1's digit
  1006.     ADD    AL,BL
  1007.     JMP    TTYPE
  1008. DIGIT:    MOV    CH,'0'            ;Start off with    ASCII 0
  1009. DIGLP:    PUSH    BX            ;Save current remainder
  1010.     ADD    BX,DX            ;Subtract
  1011.     JNB    DIGEX            ;Quit on overflow
  1012.     POP    AX            ;Throw away remainder
  1013.     INC    CH            ;Bump digit
  1014.     JMPS    DIGLP            ;Loop back
  1015. DIGEX:    POP    BX            ;Restore pointer
  1016.     MOV    AL,CH
  1017.     CMP    AL,'0'            ;Zero digit?
  1018.     JNZ    DIGNZ            ;No, type it
  1019.     MOV    AL,Byte Ptr LZFLG    ;Leading zero?
  1020.     OR    AL,AL
  1021.     MOV    AL,'0'
  1022.     JZ    L_29    
  1023.     JMP    TTYPE            ;Print digit
  1024. L_29:
  1025.     MOV    AL,Byte Ptr SUPSPC    ;Get space suppression flag
  1026.     OR    AL,AL            ;See if    printing file totals
  1027.     JNZ    L_30    
  1028.     RET                ;Yes, don't give leading spaces
  1029. L_30:
  1030.     JMP    SPACE            ;Leading zero...print space
  1031. DIGNZ:    MOV    Byte Ptr LZFLG,AL    ;Set leading zero flag so next zero prints
  1032.     JMP    TTYPE            ;And print digit
  1033. ; Show total space and files used
  1034. PRTOTL:
  1035.     MOV    AL,Byte Ptr LOPFLG
  1036.     OR    AL,AL
  1037.     JNZ    L_31
  1038.     MOV    BX,Word Ptr TOTFIL    ;How many files    did we match?
  1039.     MOV    AL,BH
  1040.     OR    AL,BL
  1041.     JZ    L_32    
  1042.     CALL    PRTLMEM            ;Skip the Library check if we didn't find any
  1043. L_32:
  1044. L_31:
  1045. PRTOT1    EQU    (Offset $)
  1046.     XOR    AL,AL            ;Get a zero to...
  1047.     MOV    Byte Ptr SUPSPC,AL    ;Suppress leading spaces in totals
  1048.     MOV    BX,Word Ptr TOTFIL    ;How many files    did we match?
  1049.     MOV    AL,BH
  1050.     OR    AL,BL
  1051.     JZ    NXTUSR            ;Skip the summary if we    didn't find any
  1052.     PUSH    BX            ;Save TOTFIL
  1053.     MOV    Byte Ptr FNDFLG,AL    ;Set file found flag
  1054.     CALL    CRLF
  1055.     CALL    PRDIR            ;Print "  Drive, x User, y"
  1056. NOUSER:    MOV    DX,(Offset TOTMS3)    ;Print " CONTAINS "
  1057.     CALL    PRINT
  1058.     MOV    BX,Word Ptr TOTSIZ    ;Print total K used by files matched
  1059.     CALL    DECPRT
  1060.     MOV    DX,(Offset TOTMS4)    ;PRINT "K IN "
  1061.     CALL    PRINT
  1062.     POP    BX            ;Recall    TOTFIL
  1063.     CALL    DECPRT            ;Print number of files matched
  1064.     MOV    DX,(Offset TOTMS5)    ;Print " FILES WITH "
  1065.     CALL    PRINT
  1066.     CALL    PRTFRE            ;Output    free space remaining & " FREE."
  1067. ; Directory for    one user area completed.  If all users option is
  1068. ; selected, then go do another directory on the    next user number
  1069. ; until    we exceed the maximum user # for the selected drive.
  1070. NXTUSR:                ;If all    users option enabled
  1071.     MOV    AL,Byte Ptr AOPFLG    ;If not    all users mode - skip next
  1072.     OR    AL,AL
  1073.     JNZ    GOCLZ
  1074.     CALL    CKABRT            ;Check for user    abort first
  1075.     MOV    AL,Byte Ptr MAXUSR    ;No abort - get    maximum    user number
  1076.     MOV    BX,(Offset NEWUSR)    ;Bump directory    user number
  1077.     INC    M
  1078.     CMP    AL,M            ;Does next user    # exceed maximum?
  1079.     JNAE    L_33    
  1080.     JMP    SETTBL            ;Continue if more user areas to    go
  1081. L_33:
  1082. ;AOPT
  1083. ;If multi-disk option enabled
  1084.     MOV    AL,Byte Ptr BASUSR    ;Reset base user number    for the
  1085.     MOV    M,AL            ;..next    directory search
  1086. ;Balance DOPT and AOPT
  1087. ; We've finished all of our outputting.  Flush the remainder of the
  1088. ; output buffer and close the file before going to exit routine.
  1089. GOCLZ:
  1090. ;    LDA    FOPFLG        ;Is file output mode active?
  1091. ;    ORA    A
  1092. ;    JNZ    NXTDSK        ;If not, move to next drive, otherwise ..
  1093. ;    STA    PASS1        ;Make PASS1=0 to force reopen on next drive
  1094.     MOV    BX,(Offset OPNFLG)    ;get file open status then reset flag to
  1095.     MOV    AL,M            ;..force reopen on next pass
  1096.     MOV    M,0
  1097.     OR    AL,AL
  1098.     JZ    NXTDSK            ;skip closing sd.dir if it wasn't opened
  1099.     MOV    BX,(Offset BUFCNT)
  1100.     MOV    AL,M            ;RETRIEVE # OF UNFLUSHED CHARACTERS IN BUFFER
  1101.     MOV    M,128            ;FORCE BUFCNT TO EMPTY STATUS FOR NEXT DRIVE
  1102.     OR    AL,AL            ;IF BUFCNT=128, BUFFER EMPTY SO SET SIGN BIT
  1103.     JS    CLOZE            ;close sd.dir if buffer is empty
  1104.     JZ    FLUSH            ;write last record to sd.dir if buffer full
  1105.     MOV    BX,Word Ptr BUFPNT    ;OTHERWISE, PAD UNUSED BUFFER WITH CTRL-ZS
  1106. PUTAGN:    MOV    M,'Z'-40H
  1107.     INC    BX
  1108.     DEC    AL
  1109.     JNZ    PUTAGN            ;CONTINUE PADDING TIL BUFFER FILLED OUT
  1110. ;    MVI    A,128
  1111. ;    STA    BUFCNT        ;Force buffer to empty status
  1112. FLUSH:    MOV    DX,(Offset OUTFCB)    ;FLUSH THE LAST OUTPUT BUFFER
  1113.     MOV    CL,WRITE
  1114.     CALL    CPM
  1115.     OR    AL,AL
  1116.     JZ    L_34    
  1117.     JMP    WRTERR
  1118. L_34:
  1119. CLOZE:    MOV    DX,(Offset OUTFCB)    ;CLOSE THE OUTPUT FILE
  1120.     MOV    CL,CLOSE
  1121.     CALL    CPM
  1122. ;BALANCE FOPT
  1123. ; Directory for    all user areas completed.  If the multi-disk option
  1124. ; is enabled and selected, reset to the    base user area and repeat
  1125. ; the directory    for next drive on-line until we    either exceed the
  1126. ; drives in our    LODRV-HIDRV table, or the BDOS shuts us    down with
  1127. ; a select or bad sector error,    which will be intercepted back to
  1128. ; the EXIT module.
  1129. NXTDSK:    MOV    BX,(Offset FNDFLG)    ;Get file found flag
  1130.     MOV    AL,M
  1131.     MOV    M,0            ;Clear file found flag for next drive
  1132.     OR    AL,AL
  1133.     JNZ    NDSK            ;Continue if at least 1 file found
  1134. ;If file output enabled, disable temporarily
  1135.     MOV    BX,(Offset FOPFLG)
  1136.     DEC    M
  1137.     PUSH    BX
  1138.     MOV    AL,Byte Ptr .FCB    ;Stash ASCII directory drive in NO FILE msg
  1139.     ADD    AL,'A'-1
  1140.     MOV    Byte Ptr NOFMS2,AL
  1141.     MOV    DX,(Offset NOFMS1)    ;Print "No file on ? - "
  1142.     CALL    PRINT
  1143.     CALL    PRTFRE            ;Tag with free message
  1144. ;Restore original file output mode
  1145.     POP    BX
  1146.     INC    M
  1147. NDSK:                    ;If multi-disk option enabled
  1148.     MOV    AL,Byte Ptr DOPFLG    ;If multi-disk not selected - skip next
  1149.     OR    AL,AL
  1150.     JNZ    NPRT
  1151.     CALL    CKABRT            ;Check for user    abort first
  1152.     MOV    AL,STSKIP        ;Skip if STart SKIP
  1153.     MOV    BX,FCB            ;Bump directory    FCB drive code
  1154.     INC    M
  1155.     CMP    AL,M
  1156.     JNZ    NEXT1
  1157.     MOV    AL,SKIPTO        ;If STSKIP then SKIPTO
  1158.     MOV    M,AL
  1159. NEXT1:    MOV    AL,(Offset HIDRV)-(Offset LODRV)    ;Get maximum drive code    to search
  1160.     CMP    AL,M            ;Does next disk    exceed maximum?
  1161.     JNAE    L_35    
  1162.     JMP    NOOPT            ;Search    next disk if not
  1163. L_35:
  1164. ;Balance DOPT
  1165. NPRT:                    ;if no printer, fall through to EXIT
  1166. ;now, check if printer is in use
  1167.     MOV    AL,Byte Ptr POPFLG
  1168.     OR    AL,AL            ;printer active?
  1169.     JZ    L_36    
  1170.     JMP    EXIT            ;no, just exit...
  1171. L_36:
  1172.     MOV    CL,5
  1173.     MOV    DL,13            ;print a CRLF
  1174.     CALL    CPM
  1175.     MOV    DL,10            ;line feed
  1176.     CALL    CPM
  1177. ;POPT
  1178.     JMP    EXIT            ;All done - exit to CCP
  1179. ; Print "Directory for....
  1180. PRDIR:    MOV    DX,(Offset TOTMS1)    ;Print [CR,LF]  " Drive    "
  1181.     CALL    PRINT
  1182.     MOV    AL,Byte Ptr .FCB
  1183.     ADD    AL,'A'-1
  1184.     CALL    TTYPE            ;Output    the drive code
  1185.     MOV    DX,(Offset TOTMS2)    ;Print ", USER "
  1186.     CALL    PRINT
  1187.     CALL    TYPUSR            ;Output    the user number
  1188.     RET
  1189. ; Print    the user number    of the directory in decimal
  1190. TYPUSR:
  1191.     MOV    AL,Byte Ptr NEWUSR
  1192.     CMP    AL,10            ;If user no. > 9 print leading 1
  1193.     JB    DUX
  1194.     MOV    AL,'1'
  1195.     CALL    TTYPE
  1196.     MOV    AL,Byte Ptr NEWUSR    ;Print low digit of user no.
  1197.     SUB    AL,10
  1198. DUX:    ADD    AL,'0'
  1199.     JMPS    TTYPE
  1200. ; Force    new line on video and check for    page pause
  1201. CRLF:    MOV    AL,0DH            ;Send CR
  1202.     CALL    TTYPE
  1203.     MOV    AL,0AH            ;Send LF
  1204.     JMPS    TTYPE            ;Exit to caller    from TTYPE
  1205. ; Separate the directory output    on a line with a space,    the delimiter,
  1206. ; followed by another space.
  1207. FENCE:    CALL    SPACE
  1208.     MOV    AL,Byte Ptr MDELIM    ;Fence character
  1209. FPAD:    CALL    TTYPE            ;Print it, fall    into space
  1210. SPACE:    MOV    AL,' '            ;Fall through to TTYPE
  1211. ; Output character in A to console, and optionally to printer and/or
  1212. ; the output file.
  1213. TTYPE:    PUSH    CX
  1214.     PUSH    DX
  1215.     PUSH    BX
  1216.     PUSH    AX            ;Save the character to output
  1217.     CALL    TYPE2            ;Send it to console
  1218.     POP    AX            ;Restore the output character
  1219.     AND    AL,7FH            ;Strip parity bit on character
  1220. ; Test file output mode and skip to page pause test if not active.
  1221.     MOV    CH,AL            ;Save stripped character to B
  1222.     MOV    AL,Byte Ptr FOPFLG    ;Is file output    active?
  1223.     OR    AL,AL
  1224.     JNZ    NOWRIT            ;Go check for page pause if not
  1225. ; File output mode active - make sure we have room in buffer to add
  1226. ; next character.  If buffer full, write out current record first
  1227. ; and then start a new record with current character.
  1228.     MOV    BX,Word Ptr BUFPNT    ;Get current buffer pointer
  1229.     MOV    AL,Byte Ptr BUFCNT    ;Get buffer capacity remaining
  1230.     OR    AL,AL
  1231.     JNZ    PUTBUF            ;Continue if buffer not full
  1232.     CALL    SETFOP            ;Set the DMA address
  1233.     MOV    DX,(Offset OUTFCB)    ;Otherwise, write the current buffer out
  1234.     MOV    CL,WRITE
  1235.     CALL    CPM            ;(Note call must save character    in B)
  1236.     OR    AL,AL
  1237.     JZ    L_37    
  1238.     JMP    WRTERR            ;Take write error exit if disk full or R/O
  1239. L_37:
  1240.     MOV    BX,(Offset OUTBUF)    ;Reset buffer pointer
  1241.     MOV    AL,128            ;Reset buffer capacity
  1242. PUTBUF:    MOV    M,CH            ;Shove character to next buffer position
  1243.     INC    BX            ;Bump buffer pointer
  1244.     MOV    Word Ptr BUFPNT,BX    ;.. and save it
  1245.     DEC    AL            ;Dock count of characters left in buffer
  1246.     MOV    Byte Ptr BUFCNT,AL    ;..and save it
  1247. NOWRIT:    MOV    AL,CH            ;Recall    stripped character
  1248. ;Balance FOPT
  1249. ;If printer option
  1250.     AND    AL,7FH            ;Strip parity bit on character
  1251.     MOV    DL,AL            ;Setup list output call
  1252.     MOV    CL,5
  1253.     MOV    AL,Byte Ptr POPFLG    ;Test printer flag
  1254.     OR    AL,AL
  1255.     JNZ    L_38    
  1256.     CALL    CPM            ;Print character if flag true
  1257. L_38:
  1258.     MOV    AL,DL            ;Recall    character
  1259.     CMP    AL,0AH            ;Do we have a LF?
  1260.     JNZ    TYPRET            ;Exit if not
  1261.     MOV    AL,Byte Ptr NOPFLG    ;Is the    page pause function disabled?
  1262.     OR    AL,AL
  1263.     JZ    TYPRET            ;Exit if so
  1264.     MOV    AL,Byte Ptr LINCNT    ;Get line count
  1265.     INC    AL            ;Bump it
  1266.     MOV    BX,(Offset MLPS)
  1267.     CMP    AL,M            ;Are we    at the end of the screen?
  1268.     JB    NOTEOS            ;Skip if not
  1269.     MOV    DX,(Offset EOSMSG)    ;Else, display pause message
  1270.     MOV    CL,9            ;..without checking for    LFs
  1271.     INT    224
  1272.     CALL    CINPUT            ;Wait for character
  1273.     CMP    AL,'C'-40H
  1274.     JNZ    L_39    
  1275.     JMP    EXIT            ;Abort on CTRL-C
  1276. L_39:
  1277.     XOR    AL,AL            ;Reset line count
  1278. NOTEOS:    MOV    Byte Ptr LINCNT,AL    ;Save new line count
  1279. TYPRET:    POP    BX            ;Exit from TTYPE
  1280.     POP    DX
  1281.     POP    CX
  1282.     RET
  1283. ; Output character
  1284. TYPE2:
  1285.     IF    REVIDEO
  1286.     TEST    AL,80H            ;is high bit set?
  1287.     JZ    TYPE99            ;jmp if not
  1288.     PUSH    AX            ;save char.
  1289.     MOV    AL,Byte Ptr MLEADIN    ;Send ESC char first
  1290.     CALL    TYPE99
  1291.     MOV    AL,Byte Ptr MINTOREV    ;INTO REV VIDEO
  1292.     CALL    TYPE99
  1293.     MOV    AL,Byte Ptr MINTOREV+1
  1294.     CALL    TYPE99
  1295.     POP    AX            ;Retrieve character
  1296.     AND    AL,7FH
  1297.     CALL    TYPE99
  1298.     MOV    AL,Byte Ptr MLEADIN    ;Send ESC first
  1299.     CALL    TYPE99
  1300.     MOV    AL,Byte Ptr MOUTAREV    ;The out of reverse video character
  1301.     CALL    TYPE99
  1302.     MOV    AL,Byte Ptr MOUTAREV+1    ;The out of reverse video character
  1303. TYPE99:
  1304.     ENDIF                ;Balance REVIDEO
  1305.     MOV    DL,AL            ;Get character into BDOS entry register
  1306.     MOV    CL,WRCHR
  1307.     INT    224            ;Call CONOUT via the BDOS
  1308.     RET
  1309. ;Balance DIRCON
  1310. ; Print    a string at HL of length B
  1311. TYPEIT:    MOV    AL,M
  1312.     CALL    TTYPE
  1313.     LAHF
  1314.     INC    BX
  1315.     SAHF
  1316.     DEC    CH
  1317.     JNZ    TYPEIT
  1318.     RET
  1319. ; Print    string terminated with binary 0 on console.
  1320. PRINT:    MOV    SI,DX
  1321.     MOV    AL,[SI]
  1322.     CMP    AL,0
  1323.     JNZ    L_40
  1324.     RET
  1325. L_40:
  1326.     CALL    TTYPE
  1327.     INC    DX
  1328.     JMPS    PRINT
  1329. ; Fetch    character from console (without    echo)
  1330. CINPUT:    MOV    DL,0FFH
  1331.     MOV    CL,6
  1332.     INT    224
  1333.     CMP    AL,0
  1334.     JZ    CINPUT            ;wait for char.
  1335.     AND    AL,7FH
  1336.     RET
  1337. ; Check    for a CTRL-C or    CTRL-S entered from the    keyboard.  Jump    to
  1338. ; exit if CTRL-C, pause    on CTRL-S.
  1339. CKABRT:    MOV    DL,0FEH
  1340.     MOV    CL,6            ;Check status of keyboard
  1341.     INT     224            ;Any key pressed?
  1342.     OR    AL,AL
  1343.     JNZ    L_41    
  1344.     RET                ;No, return to caller
  1345. L_41:
  1346.     CALL    CINPUT            ;Get character
  1347.     CMP    AL,'C'-40H        ;CTRL-C?
  1348.     JNZ    L_42    
  1349.     JMP    EXIT            ;If CTRL-C then    quit
  1350. L_42:
  1351.     CMP    AL,'S'-40H        ;CTRL-S?
  1352.     JZ    L_43    
  1353.     RET                ;No, return to caller
  1354. L_43:
  1355.     CALL    CINPUT            ;Yes, wait for another char.
  1356.     CMP    AL,'C'-40H        ;Might be CTRL-C
  1357.     JNZ    L_44    
  1358.     JMP    EXIT            ;Exit if CTRL-C, else fall thru    and continue
  1359. L_44:
  1360.     RET
  1361. ; Kludge to allow call to address in HL
  1362. GOHL:    JMP    BX
  1363. ; Entry    to BDOS    saving all extended registers
  1364. CPM:    PUSH    CX
  1365.     PUSH    DX
  1366.     PUSH    BX
  1367.     INT    224
  1368.     MOV    CH,AL            ; Save return code
  1369.     MOV    AL,Byte Ptr VERFLG    ; Is this 3.0 or higher?
  1370.     CMP    AL,30H
  1371.     MOV    AL,CH
  1372.     JB    CPM20            ; No, exit normally
  1373.     CMP    AL,0FFH            ; It is 3.0 - was return code FF?
  1374.     JNZ    CPM20            ; No, exit normally
  1375.     MOV    AL,BH            ; 3.0 and A=FF - check for extended error code
  1376.     OR    AL,AL
  1377.     JZ    L_45    
  1378.     JMP    DSKERR            ; Trap out if we got a physical error
  1379. L_45:
  1380.     MOV    AL,CH            ; Else continue normally
  1381. CPM20:
  1382.     POP    BX
  1383.     POP    DX
  1384.     POP    CX
  1385.     RET
  1386. ; For file output mode,    return to old user area    and set    DMA for
  1387. ; the file output buffer.
  1388. SETFOP:
  1389.     MOV    AL,Byte Ptr OLDUSR    ;Get user number at startup
  1390.     MOV    DL,AL
  1391.     MOV    CL,CURUSR
  1392.     CALL    CPM            ;Reset the old user number
  1393.  
  1394.     MOV    DX,(Offset OUTBUF)    ;Move DMA from search buffer into the
  1395.     JMPS    SET2            ;..output buffer
  1396.     RET
  1397. ; Move disk buffer DMA to default buffer for directory search operations
  1398. ; and BDOS media change routines (necessary for pre-CP/M 2 systems while
  1399. ; in file output mode with an active buffer).
  1400. SETSRC:    MOV    DX,BASE+80H
  1401. SET2:    MOV    CL,SETDMA
  1402.     JMPS    CPM
  1403. ; Print    the amount of free space remaining on the selected drive
  1404. PRTFRE:    MOV    BX,Word Ptr FREEBY    ;Get space left before adding to MASTER.DIR
  1405.     CALL    DECPRT            ;Print K free
  1406.     MOV    DX,(Offset TOTMS6)    ;Print " FREE."
  1407.     JMP    PRINT
  1408. ; Compare routine for sort
  1409. COMPR:    PUSH    BX            ;Save table addr
  1410.     MOV    DL,M            ;Load low order
  1411.     INC    BX
  1412.     MOV    DH,M            ;Load high order
  1413.     INC    BX
  1414.     MOV    CL,M
  1415.     INC    BX
  1416.     MOV    CH,M
  1417. ; BC, DE now point to entries to be compared
  1418.     XCHG    BX,DX
  1419.     MOV    DL,AL            ;Get count
  1420. CMPLP:    MOV    AL,M
  1421.     AND    AL,7FH
  1422.     MOV    DH,AL
  1423.     MOV    SI,CX
  1424.     MOV    AL,[SI]
  1425.     AND    AL,7FH
  1426.     CMP    AL,DH
  1427.     LAHF
  1428.     INC    BX
  1429.     SAHF
  1430.     LAHF
  1431.     INC    CX
  1432.     SAHF
  1433.     JNZ    NOTEQL            ;Quit on mismatch
  1434.     DEC    DL            ;Or end    of count
  1435.     JNZ    CMPLP
  1436. NOTEQL:    POP    BX
  1437.     RET                ;Cond code tells all
  1438. ; Swap entries in the order table
  1439. SWAP:    MOV    CX,(Offset ORDER)-2    ;Table base
  1440.     SHL    BX,1            ;*2
  1441.     LAHF                ;+ base
  1442.     ADD    BX,CX
  1443.     SAHF
  1444.     XCHG    BX,DX
  1445.     SHL    BX,1            ;*2
  1446.     LAHF                ;+ base
  1447.     ADD    BX,CX
  1448.     RCR    SI,1
  1449.     SAHF
  1450.     RCL    SI,1
  1451.     MOV    CL,M
  1452.     MOV    SI,DX
  1453.     MOV    AL,[SI]
  1454.     XCHG    BX,DX
  1455.     MOV    M,CL
  1456.     MOV    SI,DX
  1457.     MOV    [SI],AL
  1458.     LAHF
  1459.     INC    BX
  1460.     SAHF
  1461.     LAHF
  1462.     INC    DX
  1463.     SAHF
  1464.     MOV    CL,M
  1465.     MOV    SI,DX
  1466.     MOV    AL,[SI]
  1467.     XCHG    BX,DX
  1468.     MOV    M,CL
  1469.     MOV    SI,DX
  1470.     MOV    [SI],AL
  1471.     RET
  1472. ; New compare routine - modified for filetype sort
  1473. COMPARE:
  1474.     MOV    CX,(Offset ORDER)-2
  1475.     SHL    BX,1
  1476.     ADD    BX,CX
  1477.     XCHG    BX,DX
  1478.     SHL    BX,1
  1479.     ADD    BX,CX
  1480.     XCHG    BX,DX
  1481.     MOV    CL,M
  1482.     INC    BX
  1483.     MOV    CH,M
  1484.     XCHG    BX,DX
  1485.     MOV    DL,M
  1486.     INC    BX
  1487.     MOV    DH,M
  1488.     XCHG    BX,DX
  1489. ;If T option true
  1490.     MOV    AL,Byte Ptr TOPFLG    ;Get option flag
  1491.     OR    AL,AL            ;test for zero
  1492.     JNZ    CMPFNFT
  1493. ;
  1494. ; Compare by Filename, Filetype, and Extent - in that order
  1495. ;
  1496.     PUSH    BX
  1497.     PUSH    CX
  1498.     MOV    DX,8            ;Pt to FT
  1499.     CALL    ADDEM
  1500.     MOV    DL,3            ; 3 bytes in type
  1501.     CALL    CMPLPE            ;compare FT'S
  1502.     POP    CX
  1503.     POP    BX
  1504.     JZ    L_47    
  1505.     RET                ;Continue if match
  1506. L_47:
  1507.     PUSH    BX
  1508.     PUSH    CX
  1509.     MOV    DL,8            ;8 bytes in name
  1510.     CALL    CMPLPE            ;Compare FN'S
  1511.     POP    CX
  1512.     POP    BX
  1513.     JZ    L_48    
  1514.     RET                ;Continue if match
  1515. L_48:
  1516.     MOV    DX,11            ;Pt to EXT
  1517.     CALL    ADDEM
  1518.     MOV    SI,CX            ;Compare EXT'S
  1519.     MOV    AL,[SI]
  1520.     CMP    AL,M
  1521.     RET
  1522. ADDEM:    PUSH    BX            ;Adds DE to HL & BC
  1523.     MOV    BH,CH
  1524.     MOV    BL,CL
  1525.     LAHF
  1526.     ADD    BX,DX
  1527.     SAHF
  1528.     MOV    CH,BH
  1529.     MOV    CL,BL
  1530.     POP    BX
  1531.     LAHF
  1532.     ADD    BX,DX
  1533.     RCR    SI,1
  1534.     SAHF
  1535.     RCL    SI,1
  1536.     RET
  1537. ;
  1538. ;  Compare by Filename, Filetype, Extent - in that order
  1539. ;
  1540. CMPFNFT:
  1541.     MOV    DL,12            ;Compare FN, FT, EX
  1542. ; and fall into routine
  1543. CMPLPE:
  1544.     MOV    AL,M
  1545.     AND    AL,7FH
  1546.     MOV    DH,AL
  1547.     MOV    SI,CX
  1548.     MOV    AL,[SI]
  1549.     AND    AL,7FH
  1550.     CMP    AL,DH
  1551.     LAHF
  1552.     INC    CX
  1553.     SAHF
  1554.     LAHF
  1555.     INC    BX
  1556.     SAHF
  1557.     JZ    L_49
  1558.     RET
  1559. L_49:
  1560.     DEC    DL
  1561.     JNZ    CMPLPE
  1562.     RET
  1563. HELP:    INC    BX            ;Make sure there is a 
  1564.     CMP    AL,M            ;second "/" else return
  1565.     LAHF                ;since some people use / 
  1566.     DEC    BX
  1567.     SAHF
  1568.     JZ    L_50    
  1569.     RET                ;for a file name
  1570. L_50:
  1571. HELP1:    MOV    DX,(Offset HLPMES)    ;Print a short HELP message
  1572.     CALL    PRINT
  1573.     CALL    CRLF
  1574.     JMPS    EXIT
  1575. ; Error    exit
  1576. ERXIT:
  1577.     MOV    AL,-1
  1578.     MOV    Byte Ptr FOPFLG,AL    ;Disable file output mode on error
  1579.     CALL    CRLF            ;Space down
  1580.     POP    DX            ;Get pointer to    message    string
  1581.     CALL    PRINT            ;Print it
  1582.     MOV    DX,(Offset ERRMS1)    ;Print " Error"
  1583.     CALL    PRINT
  1584.     CALL    CRLF            ;Space down
  1585. ; Exit - all done, restore stack
  1586. EXIT:    MOV    CL,CONST        ;Check console status
  1587.     CALL    CPM
  1588.     OR    AL,AL            ;Char waiting?
  1589.     MOV    CL,RDCHR
  1590.     JZ    L_51    
  1591.     CALL    CPM            ;Gobble    up char
  1592. L_51:
  1593. ;Restore BDOS intercept    vectors
  1594.     MOV    AL,Byte Ptr VERFLG    ;Or error mode, depending on version
  1595.     CMP    AL,30H
  1596.     JB    EXIT0
  1597.     MOV    CL,45
  1598.     MOV    DL,0            ;Set error mode back to default
  1599.     CALL    CPM
  1600.     JMPS    EXIT1
  1601. EXIT0:
  1602.     MOV    AL,Byte Ptr DOPFLG    ;..if they were swapped
  1603.     OR    AL,AL
  1604.     JNZ    L_52    
  1605.     CALL    SWAPEM
  1606. L_52:
  1607. EXIT1:
  1608.     MOV    AL,Byte Ptr ROPFLG    ;If disk system    was reset
  1609.     OR    AL,AL
  1610.     MOV    AL,Byte Ptr OLDDSK    ;Get default disk at startup
  1611.     MOV    DL,AL
  1612.     MOV    CL,SELDSK        ;Reselect it
  1613.     JNZ    L_53    
  1614.     CALL    CPM
  1615. L_53:
  1616. ;Balance ROPT
  1617.     MOV    CL,0            ;EXIT PROGRAM
  1618.     MOV    DL,0
  1619.     INT    224
  1620.  
  1621.  
  1622. ; Trap BDOS select and sector error vectors to our own intercept
  1623. ; routine so we    can catch a reference to an illegal drive.
  1624. SWAPEM:    MOV    AL,Byte Ptr VERFLG    ;Check version
  1625.     CMP    AL,30H            ;see if error mode call is available
  1626.     JB    SWAP20            ;If not, use BDOS error vectors
  1627.     MOV    CL,45
  1628.     MOV    DL,0FFH            ;Use Set Error Mode call
  1629.     CALL    CPM            ;set "return code only" mode
  1630. SWAP20:    RET                ;this doesn't make sense in CP/M-86
  1631.                     ;...version 1.1
  1632. ; Check    CP/M version number.  Return carry flag    set if pre-CP/M    2.
  1633. ; If CP/M 2 or later or    MP/M (any version), return carry clear.
  1634. CKVER:    MOV    AL,Byte Ptr VERFLG
  1635.     CMP    AL,20H
  1636.     RET
  1637. ; Recovery point from intercepted BDOS select and bad sector errors.
  1638. DSKERR:
  1639.     JMP    EXIT            ;..and exit back to CCP
  1640. ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1641. ;
  1642. ;    SUBROUTINES to read library file directory
  1643. ;
  1644. ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1645. ;
  1646. PRTLMEM:MOV    BX,(Offset ORDER)    ;Initialize order table    pointer
  1647.     MOV    Word Ptr NEXTL,BX
  1648.     XOR    AL,AL
  1649.     MOV    Byte Ptr LNCNT,AL
  1650. ENTRYL:    MOV    BX,Word Ptr LCOUNT
  1651.     MOV    AL,BH            ;Is this the last file?
  1652.     OR    AL,BL
  1653.     JZ    LBEXIT            ;If COUNT=0, last file so RETURN
  1654.     LAHF                ;Dock file count
  1655.     DEC    BX
  1656.     SAHF
  1657.     MOV    Word Ptr LCOUNT,BX
  1658.     PUSH    CX
  1659.     CALL    CKABRT            ;Check for abort code from keyboard
  1660.     MOV    BX,Word Ptr NEXTL
  1661.     MOV    AL,11
  1662.     CALL    COMPR            ;Does this entry match next one?
  1663.     POP    CX
  1664.     JNZ    LBRTST            ;No, print it
  1665.     INC    BX
  1666.     INC    BX            ;Skip since highest extent comes last in list
  1667.     MOV    Word Ptr NEXTL,BX
  1668.     JMPS    ENTRYL            ;Loop back for next lowest extent
  1669. ;
  1670. ;    Exit Library member printing
  1671. ;
  1672. LBEXIT:    MOV    BX,Word Ptr LMTOTL
  1673.     MOV    AL,BH
  1674.     OR    AL,BL
  1675.     JNZ    L_54
  1676.     RET
  1677. L_54:
  1678.     PUSH    BX            ;Save Member count
  1679.     XOR    AL,AL            ;Get a zero to...
  1680.     MOV    Byte Ptr SUPSPC,AL    ;Suppress leading spaces in totals
  1681.     MOV    BX,(Offset MNPL)
  1682.     MOV    AL,Byte Ptr LNCNT
  1683.     CMP    AL,M
  1684.     JZ    L_55    
  1685.     CALL    CRLF
  1686. L_55:
  1687.     MOV    DX,(Offset CONTM)    ;Print "There are "
  1688.     CALL    PRINT
  1689.     POP    BX            ;GET TOTAL MEMBER COUNT BACK
  1690.     CALL    DECPRT
  1691.     MOV    DX,(Offset MFILES)    ;PRINT "Members in "
  1692.     CALL    PRINT
  1693.     MOV    BX,Word Ptr LBTOTL
  1694.     CALL    DECPRT
  1695.     MOV    DX,(Offset LIBR)
  1696.     CALL    PRINT
  1697.     RET
  1698. ; Valid    entry obtained - spit it out.
  1699. LBRTST:    MOV    BX,Word Ptr NEXTL    ;Get order table pointer
  1700.     MOV    DL,M            ;Get low order address
  1701.     LAHF
  1702.     INC    BX
  1703.     SAHF
  1704.     MOV    DH,M            ;Get high order    address
  1705.     LAHF
  1706.     INC    BX
  1707.     SAHF
  1708.     MOV    Word Ptr NEXTL,BX    ;Save updated table pointer
  1709.     MOV    BX,8
  1710.     LAHF
  1711.     ADD    BX,DX
  1712.     SAHF
  1713.     CALL    CKLBR
  1714.     JZ    L_56    
  1715.     JMP    ENTRYL
  1716. L_56:
  1717.     PUSH    DX
  1718.     MOV    BX,(Offset MNPL)
  1719.     MOV    AL,Byte Ptr LNCNT
  1720.     CMP    AL,M
  1721.     JZ    L_57    
  1722.     CALL    CRLF
  1723. L_57:
  1724.     MOV    BX,(Offset LFMSEP)
  1725.     MOV    CH,31
  1726.     CALL    TYPEIT
  1727.     POP    BX
  1728.     PUSH    BX
  1729.     MOV    CH,8            ;File name length
  1730.     CALL    TYPEIT
  1731.     MOV    AL,'.'            ;Period    after FN
  1732.     CALL    TTYPE
  1733.     MOV    CH,3            ;Display 3 characters of filetype
  1734.     CALL    TYPEIT
  1735.     CALL    CRLF
  1736.     POP    BX
  1737. ;
  1738. ; Saves the library file name into LBRFCB
  1739. ;
  1740.     MOV    AL,Byte Ptr .FCB
  1741.     MOV    DX,(Offset LBRFCB)    ;TO
  1742.     MOV    SI,DX
  1743.     MOV    [SI],AL
  1744.     LAHF
  1745.     INC    DX
  1746.     SAHF
  1747.     MOV    CH,11            ;LEN
  1748.     CALL    MOVE            ;DO THE MOVE
  1749.     XCHG    BX,DX
  1750.     MOV    CH,25
  1751. CLMFCB:    MOV    M,0
  1752.     LAHF
  1753.     INC    BX
  1754.     SAHF
  1755.     DEC    CH
  1756.     JNZ    CLMFCB
  1757.     CALL    SETLDMA
  1758.     MOV    DX,(Offset LBRFCB)    ;POINT TO FILE
  1759.     MOV    CL,OPEN            ;GET FUNCTION
  1760.     CALL    CPM            ;OPEN IT
  1761.     MOV    CL,READ
  1762.     MOV    DX,(Offset LBRFCB)
  1763.     CALL    CPM
  1764.     CALL    SETFOP
  1765.     MOV    BX,(Offset LBBUF)
  1766.     MOV    AL,M
  1767.     OR    AL,AL
  1768.     JZ    CKLDIR            ;check directory present?
  1769. BADLBR:    MOV    BX,(Offset NLBRF)
  1770.     MOV    CH,25
  1771.     CALL    TYPEIT
  1772. LMLEXI:    CALL    LBCLOSE
  1773.     JMP    ENTRYL
  1774. L_58    EQU    $
  1775.     DSEG
  1776.     ORG    Offset L_58
  1777. NLBRF    DB    '++Not a LIBRARY file.++',13,10
  1778. L_59    EQU    $
  1779.     CSEG
  1780.     ORG    Offset L_59
  1781. ;
  1782. ;    Close the library file
  1783. ;
  1784. LBCLOSE:MOV    DX,(Offset LBRFCB)
  1785.     MOV    CL,CLOSE
  1786.     CALL    CPM
  1787.     RET
  1788. ;
  1789. ; SETLDMA - Set the Library file DMA adderss
  1790. ;
  1791. SETLDMA:
  1792.     MOV    AL,Byte Ptr NEWUSR    ;Get user area for directory
  1793.     MOV    DL,AL
  1794.     MOV    CL,CURUSR        ;Get the user function
  1795.     CALL    CPM            ;..and set new user number
  1796.  
  1797.     MOV    DX,(Offset LBBUF)
  1798.     MOV    CL,SETDMA
  1799.     CALL    CPM
  1800.     RET
  1801. ;
  1802. ; CKLDIR - check to see if there indeed is a LBR file
  1803. ;      directory and barf if not
  1804. ;
  1805. CKLDIR:    MOV    CH,11            ;len of file name
  1806.     MOV    AL,' '            ;space
  1807.     INC    BX
  1808. CKDLP:    CMP    AL,M
  1809.     JNZ    BADLBR
  1810.     DEC    CH
  1811.     LAHF
  1812.     INC    BX
  1813.     SAHF
  1814.     JNZ    CKDLP
  1815. ;
  1816. ; The first entry in the LBR directory is indeed blank.
  1817. ; Now see if the directory size is >0
  1818. ;
  1819.     MOV    DL,M            ;file starting location low
  1820.     INC    BX            ;must be zero here
  1821.     MOV    AL,M            ;file starting location high
  1822.     OR    AL,DL            ;must be zero here also
  1823.     JNZ    BADLBR
  1824.     INC    BX
  1825.     MOV    DL,M            ;get library size low
  1826.     INC    BX            ;point to library size high
  1827.     MOV    DH,M            ;get library size high
  1828.     MOV    AL,DH
  1829.     OR    AL,DL            ;library must have some size
  1830.     JNZ    L_61    
  1831.     JMP    BADLBR
  1832. L_61:
  1833.     DEC    DX
  1834.     XCHG    BX,DX
  1835.     MOV    Word Ptr SLFILE,BX
  1836.     MOV    BX,Word Ptr LBTOTL
  1837.     INC    BX
  1838.     MOV    Word Ptr LBTOTL,BX
  1839.     MOV    AL,Byte Ptr MNPL
  1840.     MOV    Byte Ptr LNCNT,AL    ;Reset names per line counter
  1841.     MOV    CH,3
  1842.     MOV    BX,17
  1843.     ADD    BX,DX
  1844.     MOV    AL,Byte Ptr MNPL
  1845.     MOV    Byte Ptr LNCNT,AL    ;Reset names per line counter
  1846.     JMPS    LMTEST
  1847. LFMLOP:    MOV    BX,Word Ptr SLFILE    ;GET
  1848.     MOV    AL,BL
  1849.     OR    AL,BH
  1850.     JNZ    L_62    
  1851.     JMP    LMLEXI
  1852. L_62:
  1853.     LAHF
  1854.     DEC    BX
  1855.     SAHF
  1856.     MOV    Word Ptr SLFILE,BX
  1857.     CALL    SETLDMA
  1858.     MOV    CL,READ
  1859.     MOV    DX,(Offset LBRFCB)
  1860.     CALL    CPM
  1861.     CALL    SETFOP
  1862.     MOV    CH,4            ;GET FILE COUNT PER SECTOR
  1863.     MOV    BX,(Offset LBBUF)    ;GET BUFFER STARTING ADDRESS
  1864. LMTEST:    MOV    AL,M            ;Get member open flag
  1865.     OR    AL,AL            ;TEST FOR OPEN
  1866.     JZ    PRMNAM
  1867. LMTESA:    MOV    DX,32            ;Member not open get offset
  1868.     ADD    BX,DX            ;to next and add it in.
  1869.     DEC    CH            ;is buffer empty ?
  1870.     JNZ    LMTEST            ;No so test next entry
  1871.     JMPS    LFMLOP            ;Yes get next buffer...
  1872. PRMNAM:    PUSH    BX            ;Print member NAME and SIZE
  1873.     PUSH    CX
  1874.     CALL    CKABRT            ;Check for abort code from keyboard
  1875.     MOV    BX,(Offset LNCNT)
  1876.     MOV    AL,Byte Ptr MNPL
  1877.     CMP    AL,M
  1878.     JNZ    PRMNA1
  1879.     MOV    AL,3            ;If printing less than 4 wide
  1880.     CMP    AL,M
  1881.     JB    PRMNA1
  1882.     MOV    AL,Byte Ptr LBRFCB    ;.. precede new    line with drive    name
  1883.     ADD    AL,'A'-1
  1884.     CALL    TTYPE
  1885. ;If reporting user numbers
  1886.     CALL    TYPUSR
  1887.  
  1888.     MOV    AL,':'            ;Tag header with a colon and a space
  1889.     CALL    FPAD            ;..and exit back to ENTRY
  1890. PRMNA1:    POP    CX
  1891.     POP    BX
  1892.     PUSH    BX
  1893.     PUSH    CX
  1894.     LAHF
  1895.     INC    BX
  1896.     SAHF
  1897.     MOV    CH,8            ;File name length
  1898.     CALL    TYPEIT
  1899.     MOV    AL,'.'            ;Period    after FN
  1900.     CALL    TTYPE
  1901.     MOV    CH,3            ;Display 3 characters of filetype
  1902.     CALL    TYPEIT
  1903.     LAHF
  1904.     INC    BX
  1905.     SAHF
  1906.     LAHF
  1907.     INC    BX
  1908.     SAHF
  1909.     MOV    DL,M
  1910.     LAHF
  1911.     INC    BX
  1912.     SAHF
  1913.     MOV    DH,M
  1914.     XCHG    BX,DX
  1915. ; If report size enabled, output the size of the individual file.
  1916. ;If file size report wanted
  1917.     CALL    DECPRT            ;..go print it
  1918.     MOV    AL,'s'            ;..and follow with S size
  1919.     CALL    TTYPE
  1920. ; At least one more file to output - can we put    it on the current line?
  1921.     MOV    BX,Word Ptr LMTOTL
  1922.     LAHF
  1923.     INC    BX
  1924.     SAHF
  1925.     MOV    Word Ptr LMTOTL,BX
  1926.     MOV    AL,Byte Ptr LNCNT
  1927.     DEC    AL
  1928.     MOV    Byte Ptr LNCNT,AL
  1929.     LAHF
  1930.     XCHG    AL,AH
  1931.     PUSH    AX
  1932.     JZ    L_64    
  1933.     CALL    FENCE            ;If room left, output the fence    character
  1934. L_64:
  1935.     POP    AX
  1936.     XCHG    AL,AH
  1937.     SAHF
  1938.     POP    CX
  1939.     POP    BX
  1940.     JZ    L_65    
  1941.     JMP    LMTESA            ;.. and    go output another file
  1942. L_65:
  1943. ; Current line full, start a new one.
  1944.     MOV    AL,Byte Ptr MNPL
  1945.     MOV    Byte Ptr LNCNT,AL    ;Reset names per line counter
  1946.     CALL    CRLF            ;Space down to next line
  1947.     JMP    LMTESA
  1948. ;
  1949. ; Move characters from 'HL' to 'DE' length in 'B'
  1950. ;
  1951. MOVE:    MOV    AL,M            ;GET A CHAR
  1952.     MOV    SI,DX            ;STORE IT
  1953.     MOV    [SI],AL
  1954.     LAHF                ;TO NEXT "FROM"
  1955.     INC    BX
  1956.     SAHF
  1957.     LAHF                ;TO NEXT "TO"
  1958.     INC    DX
  1959.     SAHF
  1960.     DEC    CH            ;MORE?
  1961.     JNZ    MOVE            ;   YES, LOOP
  1962.     RET                ;   NO, RETURN
  1963. ;
  1964. ; cklbr -- test file extent for LBR
  1965. ;
  1966. CKLBR:    PUSH    BX
  1967.     PUSH    DX
  1968.     PUSH    CX
  1969.     XCHG    BX,DX
  1970.     MOV    BX,(Offset LBRTYP)
  1971.     MOV    CL,3
  1972. CKLBL:    MOV    SI,DX
  1973.     MOV    AL,[SI]
  1974.     AND    AL,7FH
  1975.     CMP    AL,M
  1976.     JNZ    CKLBX
  1977.     LAHF
  1978.     INC    BX
  1979.     SAHF
  1980.     LAHF
  1981.     INC    DX
  1982.     SAHF
  1983.     DEC    CL
  1984.     JNZ    CKLBL
  1985. CKLBX:    POP    CX
  1986.     POP    DX
  1987.     POP    BX
  1988.     RET
  1989. L_66    EQU    $
  1990.     DSEG
  1991.     ORG    Offset L_66
  1992. ;
  1993. LFMSEP    DB    '    Library file members for : '
  1994. LBRTYP    DB    'LBR'
  1995. L_67    EQU    $
  1996.     CSEG
  1997.     ORG    Offset L_67
  1998. ;LOPT
  1999. ;**********************
  2000. ;              *
  2001. ; End of Program Code *
  2002. ;              *
  2003. ;**********************
  2004. ; Initialized data area
  2005. DREMSG    DB    'Driv','e',0
  2006. EOSMSG    DB    '    [More]',0DH,'$'
  2007. ERRMS1    DB    ' '
  2008. ERRMS2    DB    'Erro','r',0
  2009. ERRTAG    DB    ' -','>',0
  2010. NOFMS1    DB    0DH,0AH,'No file on '
  2011. NOFMS2    DB    '  -',' ',0
  2012. DIRMS1    DB    0DH,0AH,'  Directory fo','r',0
  2013. TOTMS1    DB    '  Drive',' ',0
  2014. TOTMS2    DB    ', user',' ',0
  2015. TOTMS3    DB    ' contains',' ',0
  2016. TOTMS4    DB    'k in',' ',0
  2017. TOTMS5    DB    ' files with',' ',0
  2018. TOTMS6    DB    'k free','.',0DH,0AH,0    ;,0DH,0AH ,0
  2019. USRMSG    DB    'User ','#',0
  2020. CONTM    DB    '    There are',' ',0
  2021. MFILES    DB    ' Member Files in',' ',0
  2022. LIBR    DB    ' Library(s)','.',0
  2023. FNDFLG    DB    0            ;Flag whether any files matched
  2024. LINCNT    DB    0            ;Count of lines    printed    on screen
  2025. ; Drive    code/user area lookup table
  2026. ; Note that the    LODRV-HIDRV table is included here fully configured.
  2027. ; For your own use, you    should change the maximum user areas as
  2028. ; appropriate for each drive on    your system, and then delete any
  2029. ; DBs referencing drives that don't exist.  Note also that there
  2030. ; are only 16 user areas available under CP/M 2, so the highest
  2031. ; legal user area you can specify is 15 (range 0-15 = 16 areas).
  2032. ; The program will convert anything over 15 into mod 15.
  2033. ; NOTE: If some drives in active table are unused then skip these
  2034. ; drives by using STSKIP and SKIPTO equates.
  2035. LODRV    EQU    (Offset $)        ;Mark beginning    of drive/user table
  2036.     DB    15            ;Maximum user area for Drive A
  2037.     DB    15            ;   "      "    "    "     "   B
  2038.     DB    00            ;   "      "    "    "     "   C
  2039.     DB    00            ;   "      "    "    "     "   D
  2040.     DB    00            ;   "      "    "    "     "   E
  2041.     DB    00            ;   "      "    "    "     "   F
  2042.     DB    00            ;   "      "    "    "     "   G
  2043.     DB    00            ;   "      "    "    "     "   H
  2044.     DB    00            ;   "      "    "    "     "   I
  2045.     DB    00            ;   "      "    "    "     "   J
  2046.     DB    00            ;   "      "    "    "     "   K
  2047.     DB    00            ;   "      "    "    "     "   L
  2048.     DB    15            ;   "      "    "    "     "   M
  2049. ;    DB    15        ;   "      "    "    "     "   N
  2050. ;    DB    15        ;   "      "    "    "     "   O
  2051. ;    DB    15        ;   "      "    "    "     "   P
  2052. HIDRV    EQU    (Offset $)        ;Mark end of drive/user    table
  2053. ; Option field lookup table.
  2054. ; Note that you    can force any of these options as a DEFAULT by
  2055. ; changing the letter for the option into a zero (assuming that
  2056. ; its enabling equate is true).     Each option that you hard-wire    in
  2057. ; this manner will no longer be    recognized as a    command    line OPTION,
  2058. ; and if you redundantly key it in, SD will flag it as unrecognized.
  2059. OTBL    EQU    (Offset $)        ;Mark start of option table
  2060. ;All users-option flag
  2061. AOPFLG    DB    'A'
  2062. ;Multi-disk-option flag
  2063. DOPFLG    DB    'D'
  2064. ;File-output-option flag
  2065. FOPFLG    DB    'F'
  2066. ;Display Library members flag
  2067. LOPFLG    DB    'L'
  2068. ;No page-pause option flag
  2069. NOPFLG    DB    'N'
  2070. ;Printer option    flag
  2071. POPFLG    DB    'P'
  2072. ;Reset option flag
  2073. ROPFLG    DB    'R'
  2074. ;System    file option flag
  2075. SOPFLG    DB    'S'
  2076. TOPFLG    DB    'T'            ;Type sort option flag
  2077. ;Display version number flag
  2078. VOPFLG    DB    'V'
  2079. OEND    EQU    (Offset $)        ;Mark end of option table
  2080. ; End of option    lookup table
  2081. ;    IF    AOPT
  2082. ;PASS1: DB    0        ;First pass flag for all user file output
  2083. ;    ENDIF
  2084. VECTBL    DW    (Offset DSKERR)        ;BDOS SECTOR ERROR INTERCEPT VECTOR
  2085.     DW    (Offset DSKERR)        ;BDOS SELECT ERROR INTERCEPT VECTOR
  2086. BUFPNT    DW    (Offset OUTBUF)        ;POINTER TO NEXT LOCATION IN OUTPUT BUFFER
  2087. BUFCNT    DB    128            ;NUMBER OF BYTES LEFT IN OUTPUT BUFFER
  2088. opnflg    DB    0            ;file open flag for all user file output
  2089. OUTFCB    DB    0,'SD      DIR'
  2090.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2091. OUTBUF    RS    128            ;OUTPUT FILE BUFFER
  2092. GOTUSR    DB    0
  2093. ; Uninitialized    data area
  2094. BASUSR    RS    1            ;Dupe of original directory user # to search
  2095. BLKMAX    RS    2            ;Highest block # on drive
  2096. BLKMSK    RS    1            ;SEC/BLK - 1
  2097. BLKSHF    RS    1            ;# shifts to mult by SEC/BLK
  2098. COUNT    RS    2            ;Entry count
  2099. DIRMAX    RS    2            ;Highest file #    in directory
  2100. FREEBY    RS    2            ;Contains number of K left on directory    drive
  2101. GAP    RS    2            ;Sort routine storage
  2102. I    RS    2            ; ditto
  2103. J    RS    2            ; ditto
  2104. JIG    RS    2            ; ditto
  2105. LZFLG    RS    1            ;Zero when printing leading zeros
  2106. MAXUSR    RS    1            ;Maximum user #    for drive from lookup table
  2107. NEWUSR    RS    1            ;Contains user number selected by "$U" option
  2108. NEXTT    RS    2            ;Next table entry
  2109. OLDDSK    RS    1            ;Holder    for currently logged-in    drive
  2110. OLDUSR    RS    1            ;Contains user number upon invocation
  2111. SCOUNT    RS    2            ;# to sort
  2112. SUPSPC    RS    1            ;Leading space flag for    decimal    routine
  2113. TBLOC    RS    2            ;Pointer to start of name table
  2114. TEMP    RS    2            ;Save dir entry
  2115. TOTFIL    RS    2            ;Total number of files
  2116. TOTSIZ    RS    2            ;Total size of all files
  2117. VERFLG    RS    1            ;CP/M version number (0=pre-CP/M 2)
  2118. LMTOTL    DW    0
  2119. LBTOTL    DW    0
  2120. LNCNT    DB    0
  2121. LCOUNT    DW    0
  2122. NEXTL    DW    0
  2123. SLFILE    DW    0
  2124. LBRFCB    RS    36
  2125. LBBUF    RS    80H
  2126. ORDER    EQU    (Offset $)        ;Order table starts here
  2127.     END
  2128.