home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol096 / xdir.a86 < prev   
Text File  |  1984-04-29  |  38KB  |  1,626 lines

  1.     TITLE    'XDIR Ver 1.0 for CP/M-86'
  2. ;
  3. ; XDIR.A86 for CP/M-86, as of February 18, 1981: Kelly Smith
  4. ;
  5. FALSE    EQU    0
  6. TRUE    EQU    NOT FALSE
  7. ;
  8. ;USER OPTION SPECIFICATIONS
  9. ;
  10. AOPT    EQU    TRUE            ;TRUE TO ALLOW SEARCHING ALL USER AREAS
  11. DOPT    EQU    TRUE            ;TRUE TO ALLOW SEARCHING ALL DRIVES ON-LINE
  12. FOPT    EQU    TRUE            ;TRUE TO ALLOW FILE OUTPUT OPTION
  13. NOPT    EQU    TRUE            ;TRUE TO ALLOW DISABLING PAGE PAUSE OPTION
  14. PGPAWZ    EQU    TRUE            ;TRUE FOR PAUSE AFTER EACH PAGE
  15. POPT    EQU    TRUE            ;TRUE TO ALLOW PRINTER OPTION
  16. REPERR    EQU    TRUE            ;TRUE TO REPORT COMMAND LINE OPTION ERRORS
  17. REPSIZ    EQU    TRUE            ;TRUE TO REPORT FILE SIZES
  18. SOPT    EQU    TRUE            ;TRUE TO ALLOW SYSTEM FILE OPTION
  19. UOPT    EQU    TRUE            ;TRUE TO ALLOW USER NUMBER OPTION
  20. DELIM    EQU    7CH            ;FENCE (DELIMITER) CHARACTER (VERTICAL BAR)
  21. BIGCRT    EQU    TRUE            ;TRUE = 24/80 DISPLAY, FALSE = 16/64 DISPLAY
  22. NPL    EQU    4            ;# OF NAMES PER LINE (MAX OF 3 FOR 64X16)
  23. ;                             (MAX OF 4 FOR 80X24)
  24. LPS    EQU    20            ;# OF LINES PER SCREEN (MAX OF 12 FOR 64X16)
  25. ;                               (MAX OF 20 FOR 80X24)
  26. ;
  27. ; BDOS EQUATES
  28. ;
  29. RDCHR    EQU    1            ;READ CHAR FROM    CONSOLE
  30. WRCHR    EQU    2            ;WRITE CHAR TO CONSOLE
  31. CONST    EQU    11            ;CHECK CONS STAT
  32. RESET    EQU    13            ;RESET DISK SYSTEM
  33. SELDSK    EQU    14            ;SELECT    DISK
  34. OPEN    EQU    15            ;0FFH=NOT FOUND
  35. CLOSE    EQU    16            ;   "    "
  36. SEARCH    EQU    17            ;   "    "
  37. NEXT    EQU    18            ;   "    "
  38. READ    EQU    20            ;NOT 0 = EOF
  39. WRITE    EQU    21            ;NOT 0 = DISK FULL
  40. MAKE    EQU    22            ;0FFH =    DIRECTORY FULL
  41. CURDSK    EQU    25            ;GET CURRENTLY LOGGED DISK NAME
  42. SETDMA    EQU    26            ;SET CURRENT DMA
  43. GALLOC    EQU    27            ;GET ADDRESS OF    ALLOCATION VECTOR
  44. CURDPB    EQU    31            ;GET CURRENT DISK PARAMETERS
  45. CURUSR    EQU    32            ;GET CURRENTLY LOGGED USER NUMBER
  46. BASE    EQU    0
  47. TPA    EQU    100H
  48. FCB    EQU    BASE+5CH
  49. ;
  50. M    EQU    Byte Ptr 0[BX]
  51. ;
  52. ; BEGIN    EXECUTABLE PROGRAM CODE
  53. ;
  54.     ORG    TPA
  55. START:    MOV    DL,0FFH            ;GET CURRENT USER NUMBER
  56.     MOV    CL,CURUSR
  57.     CALL    CPM
  58.     MOV    Byte Ptr OLDUSR,AL    ;INITIALIZE STARTUP USER NUMBER
  59.     MOV    Byte Ptr NEWUSR,AL    ;..AND MAKE NEW    USER MATCH IT
  60.     MOV    Byte Ptr BASUSR,AL    ;SAVE EXTRA COPY FOR MULTI-DISK    DIRECTORIES
  61.     MOV    CL,CURDSK
  62.     CALL    CPM            ;GET CURRENT DISK NR
  63.     MOV    Byte Ptr OLDDSK,AL    ;SAVE FOR RESET    IF NEEDED
  64.     INC    AL
  65.     MOV    Byte Ptr OUTFCB,AL    ;SET DIRECTORY OUTPUT FILE DRIVE
  66.     MOV    BX,FCB
  67.     MOV    AL,M            ;GET DRIVE NAME    FOR DIRECTORY SEARCH
  68.     OR    AL,AL            ;ANY SPECIFIED?
  69.     JNZ    START2            ;YES SKIP NEXT ROUTINE
  70.     MOV    AL,Byte Ptr OLDDSK    ;OTHERWISE, GET    DEFAULT    DISK
  71.     INC    AL
  72. START2:    MOV    M,AL            ;PUT THE ABSOLUTE DRIVE    CODE IN    DIRECTORY FCB
  73. ;
  74. ; IF AT    LEAST ONE OPTION IS ALLOWED, SCAN THE COMMAND LINE FOR THE
  75. ; OPTION FIELD DELIMITER.  THE OPTION FIELD DELIMITER IS CONSIDERED
  76. ; VALID    ONLY IF    IT IS PRECEDED BY AT LEAST 1 SPACE (OTHERWISE, IT
  77. ; MAY BE PART OF THE DIRECTORY FILENAME).  ANY UNRECOGNIZED OPTIONS
  78. ; OR ILLEGAL USER NUMBERS WILL BE FLAGGED OR IGNORED (SEE REPERR).
  79. ; (WE SCAN THE COMMAND LINE BUFFER RATHER THAN THE 2ND DEFAULT FCB
  80. ; BECAUSE ALL 8    OPTIONS    PLUS A 2 DIGIT USER NUMBER WON'T FIT IN
  81. ; THE FCB NAME FIELD).
  82. ;
  83.     MOV    BX,80H            ;SET COMMAND LINE BUFFER POINTER
  84.     MOV    CH,M            ;GET LENGTH OF COMMAND LINE BUFFER
  85. ;
  86. ; SEARCH FOR THE COMMAND LINE DELIMITER.  IF NOT FOUND, ASSUME NO OPTIONS.
  87. ;
  88. SCNDOL:    LAHF
  89.     INC    BX
  90.     SAHF
  91.     DEC    CH
  92.     JNS    L_1    
  93.     JMP    CKREST            ;EXIT IF COMMAND LINE BUFFER EMPTY
  94. L_1:
  95.     MOV    AL,M
  96.     CMP    AL,'$'
  97.     JNZ    SCNDOL
  98.     DEC    BX            ;'$' FOUND - MAKE SURE SPACE PRECEDES IT
  99.     MOV    AL,M
  100.     INC    BX
  101.     CMP    AL,' '
  102.     JNZ    SCNDOL            ;NO SPACE - IGNORE "$" AND SEARCH AGAIN
  103. ;
  104. ; VALID    DELIMITER FOUND.  SCAN THE REST    OF THE BUFFER FOR OPTIONS.  ERRORS
  105. ; PAST THIS POINT WILL CAUSE AN    ABORT IF THE COMMAND LINE ERROR    OPTION IS
  106. ; ENABLED.  OTHERWISE, THE DUD OPTION WILL BE IGNORED AND SD WILL ATTEMPT
  107. ; TO CONTINUE STUMBLING    THROUGH    THE REST OF THE    FIELD.
  108. ;
  109.     XCHG    BX,DX            ;GET OPTION FIELD POINTER TO DE
  110. SCNOPT:    LAHF                ;BUMP TO NEXT OPTION FIELD CHARACTER
  111.     INC    DX
  112.     SAHF
  113.     DEC    CH            ;DOCK CHARACTERS LEFT IN OPTION    FIELD
  114.     JNS    L_2    
  115.     JMP    CKREST            ;IF OPTION FIELD EXHAUSTED, EXIT
  116. L_2:
  117. SCNAGN:    MOV    SI,DX            ;GET THE NEXT OPTION CHARACTER
  118.     MOV    AL,[SI]
  119.     CMP    AL,' '            ;DO WE HAVE A SPACE?
  120.     JZ    SCNOPT            ;IGNORE    IT IF SO
  121.     MOV    BX,(Offset OTBL)-1    ;GET BASE OF OPTION LOOKUP TABLE
  122.     MOV    CL,(Offset OEND)-(Offset OTBL)+1    ;GET LENGTH OF OPTION LOOKUP TABLE
  123. NOMACH:    INC    BX            ;BUMP TO NEXT OPTION TABLE CHARACTER
  124.     DEC    CL            ;ARE WE    OUT OF THE TABLE?
  125.     JZ    CK4USR            ;IF SO, CHECK FOR USER OPTION
  126.     CMP    AL,M            ;COMPARE OUR CHARACTER WITH OPTION TABLE
  127.     JNZ    NOMACH            ;EXIT IF NO MATCH
  128.     MOV    M,0            ;OTHERWISE, ACTIVATE THE FLAG
  129.     JMPS    SCNOPT            ;..AND GO GET THE NEXT OPTION CHARACTER
  130. ;
  131. ; IF OPTION CHARACTER DOESN'T MATCH THE TABLE, SEE IF WE HAVE A USER
  132. ; OPTION.
  133. ;
  134.  
  135.     IF    UOPT
  136. CK4USR:                ;CHECK FOR USER    NUMBER OPTION
  137.     CMP    AL,'U'
  138.     JNZ    CLERR            ;LAST OPTION, SO BAD DEAL IF THAT AIN'T IT
  139. UAGN:    LAHF                ;BUMP TO USER NUMBER DIGIT
  140.     INC    DX
  141.     SAHF
  142.     DEC    CH
  143.     JS    CLERR            ;ERROR IF NOTHING LEFT
  144.     MOV    SI,DX            ;GET DECIMAL DIGIT
  145.     MOV    AL,[SI]
  146.     CMP    AL,' '            ;IGNORE    LEADING    SPACES
  147.     JZ    UAGN
  148.     SUB    AL,30H            ;SUBTRACT ASCII    BIAS
  149.     JB    CLERR            ;ERROR IF < 0
  150.     CMP    AL,10
  151.     JNB    CLERR            ;ERROR IF > 9
  152.     MOV    Byte Ptr NEWUSR,AL    ;SAVE USER NUMBER AS IT    MAY BE ONLY 1 DIGIT
  153.     MOV    Byte Ptr BASUSR,AL    ;DUPLICATE IT IF MULTI-DISK MODE
  154.     LAHF                ;BUMP TO POSSIBLE 2ND DIGIT OF USER NUMBER
  155.     INC    DX
  156.     SAHF
  157.     DEC    CH
  158.     JS    CKREST            ;IF NO MORE BUFFER, EXIT WITH COMPLETE USER #
  159.     MOV    SI,DX            ;ELSE, CHECK FOR ANOTHER DIGIT
  160.     MOV    AL,[SI]
  161.     SUB    AL,30H
  162.     JB    SCNAGN            ;IF NEXT CHAR NOT NUMERIC, ITS NOT PART    OF
  163.     CMP    AL,10            ;..USER    NUMBER SO GO CHECK FOR ANOTHER OPTION
  164.     JNB    SCNAGN
  165.     MOV    BL,AL            ;SAVE UNITS DIGIT
  166.     MOV    AL,Byte Ptr NEWUSR    ;GET TENS DIGIT
  167.     ADD    AL,AL            ;MULTIPLY BY 10
  168.     MOV    BH,AL
  169.     ADD    AL,AL
  170.     ADD    AL,AL
  171.     ADD    AL,BH
  172.     ADD    AL,BL            ;COMBINE WITH UNITS DIGIT
  173.     MOV    Byte Ptr NEWUSR,AL    ;SAVE THE TOTAL    USER NUMBER
  174.     MOV    Byte Ptr BASUSR,AL    ;DUPLICATE IT IF MULTI-DISK MODE
  175.     JMP    SCNOPT            ;CONTINUE SCANNING
  176.     ENDIF
  177.  
  178. ;
  179. ; IF COMMAND LINE ERROR    OPTION ENABLED,    PLAYBACK THE COMMAND LINE UP
  180. ; TO THE CHARACTER THAT    WE GAGGED ON AND EXIT.    IF REPERR IS NOT ENABLED,
  181. ; THEN CONTINUE    AS IF NOTHING WERE AMISS TO AVOID ACKNOWLEDGING    THAT
  182. ; SOME OPTIONS ARE AVAILABLE.
  183. ;
  184.  
  185.     IF    REPERR
  186. CLERR:
  187.     XOR    AL,AL
  188.     LAHF                ;TAG END OF COMMAND LINE WITH TERMINATOR
  189.     INC    DX
  190.     SAHF
  191.     MOV    SI,DX
  192.     MOV    [SI],AL
  193.     CALL    CRLF
  194.     MOV    DX,(Offset ERRMS2)
  195.     CALL    PRINT
  196.     MOV    DX,(Offset ERRTAG)
  197.     CALL    PRINT
  198.     MOV    BX,81H            ;PLAYBACK BAD COMMAND LINE TO ERROR POINT
  199. CLELP:    MOV    AL,M
  200.     OR    AL,AL
  201.     JZ    CLEX
  202.     CALL    SEND_CHAR
  203.     INC    BX
  204.     JMPS    CLELP
  205. CLEX:    MOV    AL,'?'            ;TAG LINE WITH A '?' FIELD
  206.     CALL    SEND_CHAR
  207.     CALL    CRLF            ;SPACE DOWN 1 MORE LINE
  208.     JMP    EXIT            ;..AND RETURN TO CP/M
  209.     ENDIF
  210.  
  211. ;
  212. ; OPTIONS INPUT OR NOT SPECIFIED.  IF RESET OPTION SPECIFIED, DO IT NOW.
  213. ;
  214. CKREST:
  215.     MOV    AL,Byte Ptr ROPFLG    ;IF RESET FLAG SET, RESET DISK SYSTEM BEFORE
  216.     OR    AL,AL            ;..STARTING TO UPDATE ALLOCATION VECTORS
  217.     MOV    CL,RESET
  218.     JNZ    L_3    
  219.     CALL    CPM
  220. L_3:
  221. ;
  222. ; VALIDATE DRIVE CODE AND USER AREA NUMBERS FROM THE DRIVE TABLE.
  223. ;
  224. NOOPT:    MOV    DX,(Offset DREMSG)    ;GET THE DRIVE/USER ERROR MESSAGE
  225.     PUSH    DX
  226.     MOV    AL,Byte Ptr .FCB    ;GET DIRECTORY DRIVE CODE
  227.     DEC    AL            ;NORMALIZE TO RANGE OF 0-15
  228.     CMP    AL,(Offset HIDRV)-(Offset LODRV)    ;COMPARE WITH MAXIMUM DRIVES ON-LINE
  229.     JNAE    L_4    
  230.     JMP    ERXIT            ;TAKE DRIVE ERROR EXIT IF OUT OF RANGE
  231. L_4:
  232.     MOV    BX,(Offset USRMSG)    ;SWITCH    TO USER    # ERROR    MESSAGE
  233.     MOV    BP,SP
  234.     XCHG    BX,[BP]
  235.     MOV    DL,AL            ;USE DRIVE CODE    AS INDEX INTO TABLE
  236.     MOV    DH,0
  237.     MOV    BX,(Offset LODRV)    ;POINT TO BASE OF DRIVE/USER TABLE
  238.     ADD    BX,DX
  239.     MOV    AL,M            ;GET THE MAXIMUM USER #    FOR THIS DRIVE
  240.     AND    AL,0FH            ;MAKE SURE ITS IN RANGE    0 - 15
  241.     MOV    Byte Ptr MAXUSR,AL    ;SAVE IT FOR LATER
  242.     MOV    BX,(Offset NEWUSR)    ;POINT TO THE DIRECTORY    USER AREA
  243.     CMP    AL,M            ;COMPARE IT WITH THE MAXIMUM
  244.     JNB    L_5    
  245.     JMP    ERXIT            ;TAKE ERROR EXIT IF USER NUMBER    ILLEGAL
  246. L_5:
  247.     POP    DX            ;DESTROY ERROR MESSAGE POINTER
  248.     MOV    BX,FCB+1        ;POINT TO NAME
  249.     MOV    AL,M            ;ANY SPECIFIED?
  250.     CMP    AL,' '
  251.     JNZ    GOTFCB
  252. ;
  253. ; NO FCB - MAKE    FCB ALL    '?'
  254. ;
  255.     MOV    CH,11            ;FN+FT COUNT
  256. QLOOP:    MOV    M,'?'            ;STORE '?' IN FCB
  257.     LAHF
  258.     INC    BX
  259.     SAHF
  260.     DEC    CH
  261.     JNZ    QLOOP
  262. GOTFCB:    MOV    AL,'?'            ;FORCE WILD EXTENT
  263.     MOV    Byte Ptr .FCB+12,AL
  264.     CALL    SETSRC            ;SET DMA FOR BDOS MEDIA CHANGE CHECK
  265.     MOV    BX,FCB            ;POINT TO FCB DRIVE CODE FOR DIRECTORY
  266.     MOV    DL,M            ;GET THE DRIVE CODE OUT OF THE FCB
  267.     DEC    DL            ;NORMALIZE DRIVE CODE FOR SELECT
  268.     MOV    CL,SELDSK        ;SELECT THE DIRECTORY DRIVE TO RETRIEVE
  269.     CALL    CPM            ;..THE PROPER ALLOCATION VECTOR
  270.     MOV    CL,curdpb        ;get disk parameter block
  271.     INT    224
  272.     INC    BX            ;point to block shift
  273.     INC    BX
  274.     MOV    AL,ES: M        ;[AL]  =  block shift  =  log2(records/block)
  275.     SUB    AL,3            ;[AL] = log2(kbytes/block)
  276.     MOV    Byte Ptr blkshf,AL
  277.     INC    BX            ;point to disk size
  278.     mov    al,es: m        ;get block mask, and save it
  279.     mov    Byte Ptr blkmsk,al
  280.     INC    BX
  281.     INC    BX
  282.     MOV    DL,ES: M
  283.     INC    BX
  284.     MOV    DH,ES: M
  285.     MOV    Word Ptr dsksiz,DX    ;dsksiz = blocks/dsk
  286. ;
  287. ;
  288. ; Now get amount used on disk
  289. ;
  290. allctd:    MOV    CL,galloc        ;get allocation vector address
  291.     INT    224
  292. ;
  293.     push    ds            ;save the data segment at all cost...
  294.     MOV    DX,Word Ptr dsksiz    ;get blocks/disk
  295.     mov    si,bx            ;make indirect pointer
  296.     test    dl,7            ;big blocks or little blocks?
  297.     jz    divlp1
  298.     add    dx,8
  299. divlp1:    mov    cl,3            ;the great divide...
  300.     shr    dx,cl
  301.     mov    cx,dx
  302.     mov    dl,0
  303.     push    es            ;trick to get to proper data segment
  304.     pop    ds
  305. cntit:    lods    ds: m    ;nice way to get data to [AL] pointed by 0[BX] from [SI]
  306.             ;...with nifty increment of pointer at [SI]
  307.     mov    bx,cx
  308.     mov    cx,8            ;scan thru 8 bits for 1's set
  309. try1:    shr    al,1
  310.     jnb    not1
  311.     inc    dx            ;got a live one, bump 'used' counter
  312. not1:    loop    try1
  313.     mov    cx,bx
  314.     loop    cntit
  315.     pop    ds            ;restore to orginal data segment
  316. ;
  317.     MOV    BX,Word Ptr dsksiz    ;[BX] = blocks/disk-1, [DX] = blocks used
  318.     inc    bx            ;bump for actual disk size
  319.     MOV    AL,BL            ;do a sixteen bit subtract
  320.     SUB    AL,DL
  321.     MOV    BL,AL
  322.     MOV    AL,BH
  323.     SBB    AL,DH
  324.     MOV    BH,AL            ;[BX] = unused blocks
  325.     MOV    AL,Byte Ptr blkshf    ;now convert from blocks to kilobytes
  326.     OR    AL,AL
  327. shftit:    JZ    savit
  328.     SHL    BX,1
  329.     DEC    AL
  330.     JMPS    shftit
  331. ;
  332. savit:    MOV    Word Ptr freeby,BX    ;[BX] = kbytes unused
  333. ;
  334. ;
  335. ; REENTER HERE ON SUBSEQUENT PASSES WHILE IN THE ALL-USERS MODE
  336. ;
  337. SETTBL:    MOV    BX,Word Ptr dsksiz    ;GET DIRECTORY MAXIMUM AGAIN
  338.     LAHF                ;DIRECTORY SIZE    IS dsksiz+1
  339.     INC    BX
  340.     SAHF
  341.     SHL    BX,1            ;DOUBLE    DIRECTORY SIZE
  342.     MOV    DX,(Offset ORDER)    ;TO GET    SIZE OF    ORDER TABLE
  343.     LAHF                ;ALLOCATE ORDER    TABLE
  344.     ADD    BX,DX
  345.     RCR    SI,1
  346.     SAHF
  347.     RCL    SI,1
  348.     MOV    Word Ptr TBLOC,BX    ;NAME TABLE BEGINS WHERE ORDER TABLE ENDS
  349.     MOV    Word Ptr NEXTT,BX
  350.     XCHG    BX,DX
  351. ;
  352. ;+++ MAY HAVE TO CHECK FOR AVAILABLE MEMORY HERE +++
  353. ;
  354.  
  355.     IF    UOPT
  356.     MOV    AL,Byte Ptr NEWUSR    ;GET USER AREA FOR DIRECTORY
  357.     MOV    DL,AL
  358.     MOV    CL,CURUSR        ;GET THE USER FUNCTION
  359.     CALL    CPM            ;..AND SET NEW USER NUMBER
  360.     ENDIF
  361.  
  362. ;
  363. ; LOOK UP THE FCB IN THE DIRECTORY
  364. ;
  365. SFIRST:    MOV    BX,0
  366.     MOV    Word Ptr COUNT,BX    ;INITIALIZE MATCH COUNTER
  367.     MOV    Word Ptr TOTFIL,BX    ;     "        TOTAL FILE COUNTER
  368.     MOV    Word Ptr TOTSIZ,BX    ;     "        TOTAL SIZE COUNTER
  369.     CALL    SETSRC            ;SET DMA FOR DIRECTORY SEARCH
  370.     MOV    CL,SEARCH        ;GET 'SEARCH FIRST' FUNCTION
  371.     JMPS    LOOK            ;..AND GO SEARCH FOR 1ST MATCH
  372. ;
  373. ; READ MORE DIRECTORY ENTRIES
  374. ;
  375. MORDIR:    MOV    CL,NEXT            ;SEARCH    NEXT
  376. LOOK:    MOV    DX,FCB
  377.     CALL    CPM            ;READ DIRECTORY    ENTRY
  378.     INC    AL            ;CHECK FOR END (0FFH)
  379.     JNZ    L_6    
  380.     JMP    SPRINT            ;IF NO MORE, SORT & PRINT WHAT WE HAVE
  381. L_6:
  382. ;
  383. ; POINT    TO DIRECTORY ENTRY
  384. ;
  385. SOME:    DEC    AL            ;UNDO PREV 'INR A'
  386.     AND    AL,3            ;MAKE MODULUS 4
  387.     ADD    AL,AL            ;MULTIPLY...
  388.     ADD    AL,AL            ;..BY 32 BECAUSE
  389.     ADD    AL,AL            ;..EACH    DIRECTORY
  390.     ADD    AL,AL            ;..ENTRY IS 32
  391.     ADD    AL,AL            ;..BYTES LONG
  392.     MOV    BX,BASE+81H        ;POINT TO BUFFER
  393. ;
  394. ;SKIP TO FN/FT
  395. ;
  396.     ADD    AL,BL            ;POINT TO ENTRY
  397.     ADD    AL,9            ;POINT TO SYS BYTE
  398.     MOV    BL,AL            ;SAVE (CAN'T CARRY TO H)
  399.  
  400.     IF    SOPT
  401.     MOV    AL,Byte Ptr SOPFLG    ;DID USER REQUEST SYS FILES?
  402.     OR    AL,AL
  403.     JZ    SYSFOK
  404.     ENDIF
  405.  
  406.     MOV    AL,M            ;GET SYS BYTE
  407.     OR    AL,AL            ;CHECK BIT 7
  408.     JS    MORDIR            ;SKIP THAT FILE
  409. SYSFOK:    MOV    AL,BL            ;GO BACK NOW
  410.     SUB    AL,10            ;BACK TO USER NUMBER (ALLOC FLAG)
  411.     MOV    BL,AL            ;HL POINTS TO ENTRY NOW
  412.     MOV    AL,Byte Ptr NEWUSR    ;GET CURRENT USER
  413.     CMP    AL,M
  414.     JNZ    MORDIR            ;IGNORE    IF DIFFERENT
  415.     INC    BX
  416. ;
  417. ; MOVE ENTRY TO    TABLE
  418. ;
  419.     XCHG    BX,DX            ;ENTRY TO DE
  420.     MOV    BX,Word Ptr NEXTT    ;NEXT TABLE ENTRY TO HL
  421.     MOV    CH,12            ;ENTRY LENGTH (NAME, TYPE, EXTENT)
  422. TMOVE:    MOV    SI,DX            ;GET ENTRY CHAR
  423.     MOV    AL,[SI]
  424.     AND    AL,7FH            ;REMOVE    ATTRIBUTES
  425.     MOV    M,AL            ;STORE IN TABLE
  426.     LAHF
  427.     INC    DX
  428.     SAHF
  429.     LAHF
  430.     INC    BX
  431.     SAHF
  432.     DEC    CH            ;MORE?
  433.     JNZ    TMOVE
  434.     LAHF
  435.     INC    DX
  436.     SAHF
  437.     LAHF                ;POINT TO SECTOR COUNT
  438.     INC    DX
  439.     SAHF
  440.     MOV    SI,DX            ;GET IT
  441.     MOV    AL,[SI]
  442.     MOV    M,AL            ;STORE IN TABLE
  443.     LAHF
  444.     INC    BX
  445.     SAHF
  446.     MOV    Word Ptr NEXTT,BX    ;SAVE UPDATED TABLE ADDR
  447.     XCHG    BX,DX
  448.     MOV    BX,Word Ptr COUNT    ;BUMP THE # OF MATCHES MADE
  449.     LAHF
  450.     INC    BX
  451.     SAHF
  452.     MOV    Word Ptr COUNT,BX
  453.     MOV    BX,13            ;SIZE OF NEXT ENTRY
  454.     LAHF
  455.     ADD    BX,DX
  456.     RCR    SI,1
  457.     SAHF
  458.     RCL    SI,1
  459.     XCHG    BX,DX            ;FUTURE    NEXTT IS IN DE
  460.     JMP    MORDIR            ;ATTEMPT TO GET NEXT DIRECTORY ENTRY
  461. ;
  462. ; SORT AND PRINT
  463. ;
  464. SPRINT:
  465.     CALL    SETFOP            ;RETURN TO FILE OUTPUT DMA & USER #
  466.     MOV    BX,Word Ptr COUNT    ;GET FILE NAME COUNT
  467.     MOV    AL,BL
  468.     OR    AL,BH            ;ANY FOUND?
  469.     JNZ    L_7    
  470.     JMP    PRTOTL            ;EXIT IF NO FILES FOUND
  471. L_7:
  472.     PUSH    BX            ;SAVE FILE COUNT
  473.     MOV    Byte Ptr SUPSPC,AL    ;ENABLE    LEADING    ZERO SUPPRESSION
  474. ;
  475. ; INITIALIZE THE ORDER TABLE
  476. ;
  477.     MOV    BX,Word Ptr TBLOC    ;GET START OF NAME TABLE
  478.     XCHG    BX,DX            ;INTO DE
  479.     MOV    BX,(Offset ORDER)    ;POINT TO ORDER    TABLE
  480.     MOV    CX,13            ;ENTRY LENGTH
  481. BLDORD:    MOV    M,DL            ;SAVE LOW ORDER    ADDRESS
  482.     INC    BX
  483.     MOV    M,DH            ;SAVE HIGH ORDER ADDRESS
  484.     INC    BX
  485.     XCHG    BX,DX            ;TABLE ADDR TO HL
  486.     ADD    BX,CX            ;POINT TO NEXT ENTRY
  487.     XCHG    BX,DX
  488.     MOV    BP,SP            ;SAVE TBL ADDR,    FETCH LOOP COUNTER
  489.     XCHG    BX,[BP]
  490.     DEC    BX            ;COUNT DOWN LOOP
  491.     MOV    AL,BL
  492.     OR    AL,BH            ;MORE?
  493.     MOV    BP,SP            ;(RESTORE TBL ADDR, SAVE COUNTER)
  494.     XCHG    BX,[BP]
  495.     JNZ    BLDORD            ;YES, GO DO ANOTHER ONE
  496.     POP    BX            ;CLEAN LOOP COUNTER OFF    STACK
  497.     MOV    BX,Word Ptr COUNT    ;GET COUNT
  498.     MOV    Word Ptr SCOUNT,BX    ;SAVE AS # TO SORT
  499.     DEC    BX            ;ONLY 1    ENTRY?
  500.     MOV    AL,BL
  501.     OR    AL,BH
  502.     JNZ    L_8    
  503.     JMP    DONE            ;YES, SO SKIP SORT
  504. L_8:
  505. ;
  506. ; THIS SORT ROUTINE IS ADAPTED FROM SOFTWARE TOOLS
  507. ; BY KERNIGAN AND PLAUGHER.
  508. ;
  509. SORT:    MOV    BX,Word Ptr SCOUNT    ;NUMBER    OF ENTRIES
  510. SORT0:    OR    AL,AL            ;CLEAR CARRY
  511.     MOV    AL,BH            ;GAP=GAP/2
  512.     RCR    AL,1
  513.     MOV    BH,AL
  514.     MOV    AL,BL
  515.     RCR    AL,1
  516.     MOV    BL,AL
  517.     OR    AL,BH            ;IS IT ZERO?
  518.     JNZ    L_9    
  519.     JMP    DONE            ;THEN NONE LEFT
  520. L_9:
  521.     MOV    AL,BL            ;MAKE GAP ODD
  522.     OR    AL,01
  523.     MOV    BL,AL
  524.     MOV    Word Ptr GAP,BX
  525.     INC    BX            ;I=GAP+1
  526. SORT2:    MOV    Word Ptr I,BX
  527.     XCHG    BX,DX
  528.     MOV    BX,Word Ptr GAP
  529.     MOV    AL,DL            ;J=I-GAP
  530.     SUB    AL,BL
  531.     MOV    BL,AL
  532.     MOV    AL,DH
  533.     SBB    AL,BH
  534.     MOV    BH,AL
  535. SORT3:    MOV    Word Ptr J,BX
  536.     XCHG    BX,DX
  537.     MOV    BX,Word Ptr GAP        ;JGAP=J+GAP
  538.     LAHF
  539.     ADD    BX,DX
  540.     SAHF
  541.     MOV    Word Ptr JGAP,BX
  542.     MOV    AL,12            ;COMPARE 12 CHARS
  543.     CALL    COMPARE            ;COMPARE (J) AND (JG)
  544.     JNS    SORT5            ;IF A(J)<=A(JG)
  545.     MOV    BX,Word Ptr J
  546.     XCHG    BX,DX
  547.     MOV    BX,Word Ptr JGAP
  548.     CALL    SWAP            ;EXCHANGE A(J) AND A(JG)
  549.     MOV    BX,Word Ptr J        ;J=J-GAP
  550.     XCHG    BX,DX
  551.     MOV    BX,Word Ptr GAP
  552.     MOV    AL,DL
  553.     SUB    AL,BL
  554.     MOV    BL,AL
  555.     MOV    AL,DH
  556.     SBB    AL,BH
  557.     MOV    BH,AL
  558.     JS    SORT5            ;IF J>0    GOTO SORT3
  559.     OR    AL,BL            ;CHECK FOR ZERO
  560.     JZ    SORT5
  561.     JMPS    SORT3
  562. SORT5:    MOV    BX,Word Ptr SCOUNT    ;FOR LATER
  563.     XCHG    BX,DX
  564.     MOV    BX,Word Ptr I        ;I=I+1
  565.     INC    BX
  566.     MOV    AL,DL            ;IF I<=N GOTO SORT2
  567.     SUB    AL,BL
  568.     MOV    AL,DH
  569.     SBB    AL,BH
  570.     JS    L_10    
  571.     JMP    SORT2
  572. L_10:
  573.     MOV    BX,Word Ptr GAP
  574.     JMP    SORT0
  575. ;
  576. ; SORT IS ALL DONE - PRINT ENTRIES
  577. ;
  578. DONE:    MOV    AL,Byte Ptr FOPFLG
  579.     OR    AL,AL
  580.     JZ    L_11    
  581.     JMP    NOOUT            ;IF FILE OUTPUT, FALL THROUGH WITH A=0
  582. L_11:
  583. ;
  584. ; IF ALL USER OPTION ENABLED, AND WE'RE NOT ON THE FIRST PASS, THEN THE
  585. ; OUTPUT FILE IS ALREADY OPEN AND POSITIONED, SO WE CAN SKIP THE OPEN.
  586. ;
  587.     MOV    BX,(Offset OPNFLG)    ;POINT TO OUTPUT FILE OPEN FLAG
  588.     CMP    AL,M            ;A=0, SET Z IF OPNFLG=0 ALSO
  589.     JZ    L_12    
  590.     JMP    NOOUT            ;IF OPNFLG NOT ZERO, SKIP OPEN
  591. L_12:
  592.     DEC    M            ;ELSE, MAKE OPNFLG NOT ZERO AND OPEN
  593. ;
  594. ; FIRST PASS ON FILE APPEND - PREPARE XDIR.DIR TO RECEIVE NEW OR APPENDED
  595. ; OUTPUT.
  596. ;
  597.     MOV    DX,(Offset OUTFCB)    ;DOES OUTPUT FILE ALREADY EXIST?
  598.     MOV    CL,SEARCH
  599.     CALL    CPM
  600.     INC    AL
  601.     JNZ    OPENIT            ;IF IT DOES, THEN OPEN IT FOR PROCESSING
  602.     MOV    CL,MAKE            ;OTHERWISE, CREATE THE OUTPUT FILE
  603.     CALL    CPM
  604.     INC    AL
  605.     JZ    L_13    
  606.     JMP    NOOUT            ;CONTINUE IF OPEN SUCCESSFUL
  607. L_13:
  608. ;
  609. ; IF MAKE OR OPEN FAILS, DECLARE ERROR
  610. ;
  611. OPNERR:    CALL    ERXIT
  612.     DB    'OPE','N' OR 80H
  613. ;
  614. WRTERR:    CALL    ERXIT
  615.     DB    'WRIT','E' OR 80H
  616. ;
  617. ; OUTPUT FILE ALREADY EXISTS - OPEN IT AND POSITION TO THE LAST
  618. ; RECORD OF THE    LAST EXTENT.
  619. ;
  620. OPENIT:    MOV    CL,OPEN            ;OPEN 1ST EXTENT OF OUTPUT FILE
  621.     CALL    CPM
  622.     INC    AL
  623.     JZ    OPNERR            ;BAD DEAL IF 1ST WON'T OPEN
  624. OPNMOR:    MOV    AL,Byte Ptr OUTFCB+15
  625.     CMP    AL,128
  626.     JB    LSTEXT            ;IF RC<128, THIS IS LAST EXTENT
  627.     MOV    BX,(Offset OUTFCB)+12
  628.     INC    M            ;ELSE, BUMP TO NEXT EXTENT
  629.     MOV    CL,OPEN            ;..AND TRY TO OPEN IT
  630.     CALL    CPM
  631.     INC    AL
  632.     JNZ    OPNMOR            ;CONTINUE OPENING EXTENTS TIL NO MORE
  633.     DEC    M            ;THEN, REOPEN PRECEDING    EXTENT
  634.     MOV    CL,OPEN
  635.     CALL    CPM
  636.     MOV    AL,Byte Ptr OUTFCB+15    ;GET RC    FOR THE    LAST EXTENT
  637. ;
  638. ; AT THIS POINT, OUTFCB IS OPENED TO THE LAST EXTENT OF THE FILE,
  639. ; SO READ IN THE LAST RECORD IN THE LAST EXTENT.
  640. ;
  641. LSTEXT:    OR    AL,AL            ;IS THIS EXTENT    EMPTY?
  642.     JZ    NOOUT            ;IF SO, THEN WE'RE STARTING A CLEAN SLATE
  643.     DEC    AL            ;NORMALIZE RECORD COUNT
  644.     MOV    Byte Ptr OUTFCB+32,AL    ;SET RECORD NUMBER TO READ
  645.     MOV    CL,READ            ;..AND READ LAST RECORD    OF FILE
  646.     CALL    CPM
  647.     OR    AL,AL            ;WAS READ SUCCESSFUL?
  648.     JZ    RDOK            ;IF SO,    PROCEED    TO SCAN    FOR EOF    MARK
  649. APERR:    CALL    ERXIT
  650.     DB    'APPEN','D' OR 80H
  651. ;
  652. ; WE NOW HAVE THE LAST RECORD IN THE FILE IN OUR BUFFER.
  653. ; SCAN THE LAST    RECORD FOR THE EOF MARK, INDICATING WHERE
  654. ; WE CAN START ADDING DATA.
  655. ;
  656. RDOK:    MOV    BX,(Offset OUTBUF)    ;POINT TO START OF OUTPUT BUFFER
  657.     MOV    CH,128            ;GET LENGTH OF OUTPUT BUFFER
  658. SCAN:    MOV    AL,M
  659.     CMP    AL,'Z'-40H        ;HAVE WE FOUND END OF FILE?
  660.     JZ    RESCR            ;IF SO, SAVE POINTERS AND RESET CR
  661.     LAHF
  662.     INC    BX
  663.     SAHF
  664.     DEC    CH
  665.     JNZ    SCAN            ;OTHERWISE, KEEP LOOKING TIL END OF BUFFER
  666. ;
  667. ; IF WE FIND AN EXPLICIT EOF MARK IN THE LAST BUFFER (OR AN IMPLIED EOF
  668. ; IF THE LAST RECORD IS FULL), MOVE THE FCB RECORD AND EXTENT POINTERS
  669. ; BACK TO CORRECT FOR THE READ OPERATION SO THAT OUR FIRST WRITE OPERATION
  670. ; WILL EFFECTIVELY REPLACE THE LAST RECORD OF THE XDIR.DIR FILE.
  671. ;
  672. RESCR:    PUSH    BX            ;SAVE EOF BUFFER POINTER
  673.     PUSH    CX            ;SAVE EOF BUFFER REMAINING
  674.     MOV    BX,(Offset OUTFCB)+32    ;GET CURRENT RECORD AGAIN
  675.     DEC    M            ;DOCK IT
  676.     JNS    SAMEXT            ;IF CR >=0, WE'RE STILL IN SAME EXTENT
  677.     MOV    BX,(Offset OUTFCB)+12    ;ELSE, MOVE TO PREVIOUS    EXTENT
  678.     DEC    M
  679.     MOV    CL,OPEN            ;THEN, REOPEN THE PREVIOUS EXTENT
  680.     CALL    CPM
  681.     INC    AL
  682.     JZ    APERR            ;APPEND POSITION ERROR IF WE CAN'T REOPEN
  683.     MOV    AL,Byte Ptr OUTFCB+15    ;ELSE, POSITION TO LAST RECORD OF EXTENT
  684.     DEC    AL
  685.     MOV    Byte Ptr OUTFCB+32,AL
  686. SAMEXT:    POP    AX            ;RECALL WHERE EOF IS IN BUFFER
  687.     XCHG    AL,AH
  688.     SAHF
  689.     MOV    Byte Ptr BUFCNT,AL    ;..AND SET BUFFER COUNTER
  690.     POP    BX            ;RECALL NEXT BUFFER POINTER
  691.     MOV    Word Ptr BUFPNT,BX    ;.. AND SET POINTER FOR FIRST ADDITION
  692. NOOUT:    MOV    BX,(Offset ORDER)    ;INITIALIZE ORDER TABLE    POINTER
  693.     MOV    Word Ptr NEXTT,BX
  694.     JMP    NEWLIN            ;START NEW LINE    AND OUTPUT THE FILES
  695. ;
  696. ; OUTPUT THE DIRECTORY FILES WE'VE MATCHED.
  697. ;
  698. ENTRY:    MOV    BX,Word Ptr COUNT
  699.     DEC    BX            ;DOCK FILE COUNT
  700.     MOV    Word Ptr COUNT,BX
  701.     MOV    AL,BH            ;IS THIS THE LAST FILE?
  702.     OR    AL,BL
  703.     JZ    OKPRNT            ;IF COUNT=0, LAST FILE SO SKIP COMPARE
  704. ;
  705. ; COMPARE EACH ENTRY TO    MAKE SURE THAT IT ISN'T PART OF A MULTIPLE
  706. ; EXTENT FILE.    GO ONLY    WHEN WE    HAVE THE LAST EXTENT OF    THE FILE.
  707. ;
  708.     PUSH    CX            ;SAVE NPL
  709.     CALL    CKABRT            ;CHECK FOR ABORT CODE FROM KEYBOARD
  710.     MOV    BX,Word Ptr NEXTT
  711.     MOV    AL,11
  712.     CALL    COMPR            ;DOES THIS ENTRY MATCH NEXT ONE?
  713.     POP    CX            ;RECALL    NPL
  714.     JNZ    OKPRNT            ;NO, PRINT IT
  715.     INC    BX
  716.     INC    BX            ;SKIP SINCE HIGHEST EXTENT COMES LAST IN LIST
  717.     MOV    Word Ptr NEXTT,BX
  718.     JMPS    ENTRY            ;LOOP BACK FOR NEXT LOWEST EXTENT
  719. ;
  720. ; VALID    ENTRY OBTAINED - SPIT IT OUT.
  721. ;
  722. OKPRNT:    MOV    BX,Word Ptr NEXTT    ;GET ORDER TABLE POINTER
  723.     MOV    DL,M            ;GET LOW ORDER ADDRESS
  724.     LAHF
  725.     INC    BX
  726.     SAHF
  727.     MOV    DH,M            ;GET HIGH ORDER    ADDRESS
  728.     LAHF
  729.     INC    BX
  730.     SAHF
  731.     MOV    Word Ptr NEXTT,BX    ;SAVE UPDATED TABLE POINTER
  732.     XCHG    BX,DX            ;TABLE ENTRY TO    HL
  733.     MOV    CH,8            ;FILE NAME LENGTH
  734.     CALL    TYPEIT            ;TYPE FILENAME
  735.     MOV    AL,'.'            ;PERIOD    AFTER FN
  736.     CALL    SEND_CHAR
  737.     MOV    CH,3            ;DISPLAY 3 CHARACTERS OF FILETYPE
  738.     CALL    TYPEIT
  739. ;
  740. ; COMPUTE THE SIZE OF THE FILE AND UPDATE OUR SUMMARY DATUM.
  741. ;
  742.     MOV    DL,M            ;GET EXTENT #
  743.     MOV    DH,0
  744.     INC    BX
  745.     MOV    AL,M            ;GET SECTOR COUNT OF LAST EXTENT
  746.     XCHG    BX,DX
  747.     SHL    BX,1            ;# OF EXTENTS TIMES 16K
  748.     SHL    BX,1
  749.     SHL    BX,1
  750.     SHL    BX,1
  751.     XCHG    BX,DX            ;SAVE IN DE
  752.     MOV    BX,(Offset BLKMSK)
  753.     ADD    AL,M            ;ROUND LAST EXTENT TO BLOCK SIZE
  754.     ROR    AL,1
  755.     ROR    AL,1            ;CONVERT FROM SECTORS TO K
  756.     ROR    AL,1
  757.     AND    AL,1FH
  758.     MOV    BL,AL            ;ADD TO    TOTAL K
  759.     MOV    BH,0
  760.     ADD    BX,DX
  761.     MOV    AL,Byte Ptr BLKMSK    ;GET SECTORS/BLK-1
  762.     ROR    AL,1
  763.     ROR    AL,1            ;CONVERT TO K/BLK
  764.     ROR    AL,1
  765.     AND    AL,1FH
  766.     NOT    AL            ;USE TO    FINISH ROUNDING
  767.     AND    AL,BL
  768.     MOV    BL,AL
  769.     XCHG    BX,DX            ;SAVE FILE SIZE    IN DE
  770.     MOV    BX,Word Ptr TOTSIZ
  771.     LAHF                ;ADD TO    TOTAL USED
  772.     ADD    BX,DX
  773.     RCR    SI,1
  774.     SAHF
  775.     RCL    SI,1
  776.     MOV    Word Ptr TOTSIZ,BX
  777.     MOV    BX,Word Ptr TOTFIL    ;INCREMENT FILE    COUNT
  778.     LAHF
  779.     INC    BX
  780.     SAHF
  781.     MOV    Word Ptr TOTFIL,BX
  782.     XCHG    BX,DX            ;GET BACK FILE SIZE
  783. ;
  784. ; IF REPORT SIZE ENABLED, OUTPUT THE SIZE OF THE INDIVIDUAL FILE.
  785. ;IF FILE SIZE REPORT WANTED
  786. ;
  787.     CALL    DECPRT            ;..GO PRINT IT
  788.     MOV    AL,'k'            ;..AND FOLLOW WITH K SIZE
  789.     CALL    SEND_CHAR
  790. ;
  791. ; ONE FILE OUTPUT - TEST TO SEE    IF WE HAVE TO OUTPUT ANOTHER ONE.
  792. ;
  793.     MOV    BX,Word Ptr COUNT    ;GET CURRENT FILE COUNTER AND TEST IT
  794.     MOV    AL,BH
  795.     OR    AL,BL
  796.     JNZ    L_14    
  797.     JMP    PRTOTL            ;IF NO MORE FILES, EXIT    TO SUMMARY OUTPUT
  798. L_14:
  799. ;
  800. ; AT LEAST ONE MORE FILE TO OUTPUT - CAN WE PUT    IT ON THE CURRENT LINE?
  801. ;
  802.     DEC    CL
  803.     LAHF
  804.     XCHG    AL,AH
  805.     PUSH    AX
  806.     JZ    L_15    
  807.     CALL    FENCE            ;IF ROOM LEFT, OUTPUT THE FENCE    CHARACTER
  808. L_15:
  809.     POP    AX
  810.     XCHG    AL,AH
  811.     SAHF
  812.     JZ    L_16    
  813.     JMP    ENTRY            ;.. AND    GO OUTPUT ANOTHER FILE
  814. L_16:
  815. ;
  816. ; CURRENT LINE FULL, START A NEW ONE.
  817. ;
  818. NEWLIN:    MOV    CL,NPL            ;RESET NAMES PER LINE COUNTER
  819.     CALL    CRLF            ;SPACE DOWN TO NEXT LINE
  820.     MOV    AL,Byte Ptr .FCB    ;.. PRECEDE NEW    LINE WITH DRIVE    NAME
  821.     ADD    AL,'A'-1
  822.     CALL    SEND_CHAR
  823.     MOV    AL,':'            ;TAG DRIVE LETTER WITH A COLON AND SPACE
  824.     CALL    SEND_CHAR
  825.     JMP    ENTRY            ;GO BACK AND OUTPUT ANOTHER FILE
  826. ;
  827. ;IF REPORTING USER NUMBERS
  828. ;
  829. ; PRINT    HL IN DECIMAL WITH LEADING ZERO    SUPPRESSION
  830. ;
  831. DECPRT:    SUB    AL,AL            ;CLEAR LEADING ZERO FLAG
  832.     MOV    Byte Ptr LZFLG,AL
  833.     MOV    DX,-1000        ;PRINT 1000'S DIGIT
  834.     CALL    DIGIT
  835.     MOV    DX,-100            ;ETC.
  836.     CALL    DIGIT
  837.     MOV    DX,-10
  838.     CALL    DIGIT
  839.     MOV    AL,'0'            ;GET 1'S DIGIT
  840.     ADD    AL,BL
  841.     JMP    SEND_CHAR
  842. ;
  843. DIGIT:    MOV    CH,'0'            ;START OFF WITH    ASCII 0
  844. DIGLP:    PUSH    BX            ;SAVE CURRENT REMAINDER
  845.     ADD    BX,DX            ;SUBTRACT
  846.     JNB    DIGEX            ;QUIT ON OVERFLOW
  847.     POP    AX            ;THROW AWAY REMAINDER
  848.     INC    CH            ;BUMP DIGIT
  849.     JMPS    DIGLP            ;LOOP BACK
  850. DIGEX:    POP    BX            ;RESTORE POINTER
  851.     MOV    AL,CH
  852.     CMP    AL,'0'            ;ZERO DIGIT?
  853.     JNZ    DIGNZ            ;NO, TYPE IT
  854.     MOV    AL,Byte Ptr LZFLG    ;LEADING ZERO?
  855.     OR    AL,AL
  856.     MOV    AL,'0'
  857.     JZ    L_17    
  858.     JMP    SEND_CHAR            ;PRINT DIGIT
  859. L_17:
  860.     MOV    AL,Byte Ptr SUPSPC    ;GET SPACE SUPPRESSION FLAG
  861.     OR    AL,AL            ;SEE IF    PRINTING FILE TOTALS
  862.     JNZ    L_18    
  863.     RET                ;YES, DON'T GIVE LEADING SPACES
  864. L_18:
  865.     JMP    SPACE            ;LEADING ZERO...PRINT SPACE
  866. DIGNZ:    MOV    Byte Ptr LZFLG,AL    ;SET LEADING ZERO FLAG SO NEXT ZERO PRINTS
  867.     JMP    SEND_CHAR            ;AND PRINT DIGIT
  868. ;
  869. ; SHOW TOTAL SPACE AND FILES USED
  870. ;
  871. PRTOTL:    XOR    AL,AL            ;GET A ZERO TO...
  872.     MOV    Byte Ptr SUPSPC,AL    ;SUPPRESS LEADING SPACES IN TOTALS
  873.     MOV    BX,Word Ptr TOTFIL    ;HOW MANY FILES    DID WE MATCH?
  874.     MOV    AL,BH
  875.     OR    AL,BL
  876.     JZ    NXTUSR            ;SKIP THE SUMMARY IF WE    DIDN'T FIND ANY
  877.     PUSH    BX            ;SAVE TOTFIL
  878.     MOV    Byte Ptr FNDFLG,AL    ;SET FILE FOUND FLAG
  879.     MOV    DX,(Offset TOTMS1)    ;PRINT [CR,LF,LF]"DRIVE    "
  880.     CALL    PRINT
  881.     MOV    AL,Byte Ptr .FCB
  882.     ADD    AL,'A'-1
  883.     CALL    SEND_CHAR            ;OUTPUT    THE DRIVE CODE
  884.     MOV    DX,(Offset TOTMS2)    ;PRINT ", USER "
  885.     CALL    PRINT
  886.     CALL    TYPUSR            ;OUTPUT    THE USER NUMBER
  887.     MOV    DX,(Offset TOTMS3)    ;PRINT " CONTAINS "
  888.     CALL    PRINT
  889.     MOV    BX,Word Ptr TOTSIZ    ;PRINT TOTAL K USED BY FILES MATCHED
  890.     CALL    DECPRT
  891.     MOV    DX,(Offset TOTMS4)    ;PRINT "K IN "
  892.     CALL    PRINT
  893.     POP    BX            ;RECALL    TOTFIL
  894.     CALL    DECPRT            ;PRINT NUMBER OF FILES MATCHED
  895.     MOV    DX,(Offset TOTMS5)    ;PRINT " FILES WITH "
  896.     CALL    PRINT
  897.     CALL    PRTFRE            ;OUTPUT    FREE SPACE REMAINING & " FREE."
  898. ;
  899. ; DIRECTORY FOR    ONE USER AREA COMPLETED.  IF ALL USERS OPTION IS
  900. ; SELECTED, THEN GO DO ANOTHER DIRECTORY ON THE    NEXT USER NUMBER
  901. ; UNTIL    WE EXCEED THE MAXIMUM USER # FOR THE SELECTED DRIVE.
  902. ;
  903.  
  904.     IF    AOPT
  905. NXTUSR:                ;IF ALL    USERS OPTION ENABLED
  906.     MOV    AL,Byte Ptr AOPFLG    ;IF NOT    ALL USERS MODE - SKIP NEXT
  907.     OR    AL,AL
  908.     JNZ    GOCLZ
  909.     CALL    CKABRT            ;CHECK FOR USER    ABORT FIRST
  910.     MOV    AL,Byte Ptr MAXUSR    ;NO ABORT - GET    MAXIMUM    USER NUMBER
  911.     MOV    BX,(Offset NEWUSR)    ;BUMP DIRECTORY    USER NUMBER
  912.     INC    M
  913.     CMP    AL,M            ;DOES NEXT USER    # EXCEED MAXIMUM?
  914.     JNAE    L_19    
  915.     JMP    SETTBL            ;CONTINUE IF MORE USER AREAS TO    GO
  916. L_19:
  917.     ENDIF
  918.  
  919. ;
  920. ;IF MULTI-DISK OPTION ENABLED
  921.  
  922.     IF    AOPT AND DOPT
  923.     MOV    AL,Byte Ptr BASUSR    ;RESET BASE USER NUMBER    FOR THE
  924.     MOV    M,AL            ;..NEXT    DIRECTORY SEARCH
  925.     ENDIF
  926.  
  927. ;
  928. ; WE'VE FINISHED ALL OF OUR OUTPUTTING.  FLUSH THE REMAINDER OF THE
  929. ; OUTPUT BUFFER AND CLOSE THE FILE BEFORE GOING TO EXIT ROUTINE.
  930. ;
  931.  
  932.     IF    FOPT
  933. GOCLZ:
  934.     MOV    BX,(Offset OPNFLG)    ;GET FILE OPEN STATUS THEN RESET FLAG TO
  935.     MOV    AL,M            ;..FORCE REOPEN ON NEXT PASS
  936.     MOV    M,0
  937.     OR    AL,AL
  938.     JZ    NXTDSK            ;SKIP CLOSING XDIR.DIR IF IT WASN'T OPENED
  939.     MOV    BX,(Offset BUFCNT)
  940.     MOV    AL,M            ;RETRIEVE # OF UNFLUSHED CHARACTERS IN BUFFER
  941.     MOV    M,128            ;FORCE BUFCNT TO EMPTY STATUS FOR NEXT DRIVE
  942.     OR    AL,AL            ;IF BUFCNT=128, BUFFER EMPTY SO SET SIGN BIT
  943.     JS    CLOZE            ;CLOSE XDIR.DIR IF BUFFER IS EMPTY
  944.     JZ    FLUSH            ;WRITE LAST RECORD TO XDIR.DIR IF BUFFER FULL
  945.     MOV    BX,Word Ptr BUFPNT    ;OTHERWISE, PAD    UNUSED BUFFER WITH CTRL-ZS
  946. PUTAGN:    MOV    M,'Z'-40H
  947.     LAHF
  948.     INC    BX
  949.     SAHF
  950.     DEC    AL
  951.     JNZ    PUTAGN            ;CONTINUE PADDING TIL BUFFER FILLED OUT
  952. FLUSH:    MOV    DX,(Offset OUTFCB)    ;FLUSH THE LAST    OUTPUT BUFFER
  953.     MOV    CL,WRITE
  954.     CALL    CPM
  955.     OR    AL,AL
  956.     JZ    L_20    
  957.     JMP    WRTERR
  958. L_20:
  959. CLOZE:    MOV    DX,(Offset OUTFCB)    ;CLOSE THE OUTPUT FILE
  960.     MOV    CL,CLOSE
  961.     CALL    CPM
  962.     ENDIF
  963.  
  964. ;
  965. ; DIRECTORY FOR    ALL USER AREAS COMPLETED.  IF THE MULTI-DISK OPTION
  966. ; IS ENABLED AND SELECTED, RESET TO THE    BASE USER AREA AND REPEAT
  967. ; THE DIRECTORY    FOR NEXT DRIVE ON-LINE UNTIL WE    EITHER EXCEED THE
  968. ; DRIVES IN OUR    LODRV-HIDRV TABLE, OR THE BDOS SHUTS US    DOWN WITH
  969. ; A SELECT OR BAD SECTOR ERROR,    WHICH WILL BE INTERCEPTED BACK TO
  970. ; THE EXIT MODULE.
  971. ;
  972. NXTDSK:    MOV    BX,(Offset FNDFLG)    ;GET FILE FOUND FLAG
  973.     MOV    AL,M
  974.     MOV    M,0            ;CLEAR FILE FOUND FLAG FOR NEXT DRIVE
  975.     OR    AL,AL
  976.     JNZ    NDSK            ;CONTINUE IF AT LEAST 1 FILE FOUND
  977. ;
  978. ;IF FILE OUTPUT ENABLED, DISABLE TEMPORARILY
  979. ;
  980.  
  981.     IF    FOPT
  982.     MOV    BX,(Offset FOPFLG)
  983.     DEC    M
  984.     PUSH    BX
  985.     ENDIF
  986.  
  987.     MOV    AL,Byte Ptr .FCB    ;STASH ASCII DIRECTORY DRIVE IN NO FILE MSG
  988.     ADD    AL,'A'-1
  989.     MOV    Byte Ptr NOFMS2,AL
  990.     MOV    DX,(Offset NOFMS1)    ;PRINT "NO FILE ON ? - "
  991.     CALL    PRINT
  992.     CALL    PRTFRE            ;TAG WITH FREE MESSAGE
  993. ;
  994. ;RESTORE ORIGINAL FILE OUTPUT MODE
  995. ;
  996.  
  997.     IF    FOPT
  998.     POP    BX
  999.     INC    M
  1000.     ENDIF
  1001.  
  1002.     IF    DOPT
  1003. NDSK:                    ;IF MULTI-DISK OPTION ENABLED
  1004.     MOV    AL,Byte Ptr DOPFLG    ;IF MULTI-DISK NOT SELECTED - SKIP NEXT
  1005.     OR    AL,AL
  1006.     JZ    L_21    
  1007.     JMP    EXIT
  1008. L_21:
  1009.     CALL    CKABRT            ;CHECK FOR USER    ABORT FIRST
  1010.     MOV    AL,(Offset HIDRV)-(Offset LODRV)    ;GET MAXIMUM DRIVE CODE    TO SEARCH
  1011.     MOV    BX,FCB            ;BUMP DIRECTORY    FCB DRIVE CODE
  1012.     INC    M
  1013.     CMP    AL,M            ;DOES NEXT DISK    EXCEED MAXIMUM?
  1014.     JNAE    L_22    
  1015.     JMP    NOOPT            ;SEARCH    NEXT DISK IF NOT
  1016. L_22:
  1017.     ENDIF
  1018.  
  1019.     JMP    EXIT            ;ALL DONE - EXIT TO CCP
  1020. ;
  1021. ; PRINT    THE USER NUMBER    OF THE DIRECTORY IN DECIMAL
  1022. ;
  1023. TYPUSR:
  1024.     MOV    AL,Byte Ptr NEWUSR
  1025.     CMP    AL,10            ;IF USER NO. > 9 PRINT LEADING 1
  1026.     JB    DUX
  1027.     MOV    AL,'1'
  1028.     CALL    SEND_CHAR
  1029.     MOV    AL,Byte Ptr NEWUSR    ;PRINT LOW DIGIT OF USER NO.
  1030.     SUB    AL,10
  1031. DUX:    ADD    AL,'0'
  1032.     JMPS    SEND_CHAR
  1033. ;
  1034. ; FORCE    NEW LINE ON VIDEO AND CHECK FOR    PAGE PAUSE
  1035. ;
  1036. CRLF:    MOV    AL,0DH            ;SEND CR
  1037.     CALL    SEND_CHAR
  1038.     MOV    AL,0AH            ;SEND LF
  1039.     JMPS    SEND_CHAR            ;EXIT TO CALLER    FROM TYPE
  1040. ;
  1041. ; SEPARATE THE DIRECTORY OUTPUT    ON A LINE WITH A SPACE,    THE DELIMITER,
  1042. ; FOLLOWED BY ANOTHER SPACE.
  1043. ;
  1044. FENCE:    CALL    SPACE
  1045.     MOV    AL,DELIM        ;FENCE CHARACTER
  1046. FPAD:    CALL    SEND_CHAR            ;PRINT IT, FALL    INTO SPACE
  1047. SPACE:    MOV    AL,' '            ;FALL THROUGH TO TYPE
  1048. ;
  1049. ; OUTPUT CHARACTER IN A TO CONSOLE, AND OPTIONALLY TO PRINTER AND/OR
  1050. ; THE OUTPUT FILE.
  1051. ;
  1052. SEND_CHAR:
  1053.     PUSH    CX
  1054.     PUSH    DX
  1055.     PUSH    BX
  1056.  
  1057.     IF    FOPT OR POPT OR PGPAWZ
  1058.     LAHF                ;SAVE THE CHARACTER TO OUTPUT
  1059.     XCHG    AL,AH
  1060.     PUSH    AX
  1061.     XCHG    AL,AH
  1062.     ENDIF
  1063.  
  1064.     CALL    TYPE1            ;SEND IT TO CONSOLE
  1065.  
  1066.     IF    FOPT OR POPT OR PGPAWZ
  1067.     POP    AX            ;RESTORE THE OUTPUT CHARACTER
  1068.     XCHG    AL,AH
  1069.     AND    AL,7FH            ;STRIP PARITY BIT ON CHARACTER
  1070.     ENDIF
  1071.  
  1072. ;
  1073. ; TEST FILE OUTPUT MODE AND SKIP TO PAGE PAUSE TEST IF NOT ACTIVE.
  1074. ;
  1075.  
  1076.     IF    FOPT
  1077.     MOV    CH,AL            ;SAVE STRIPPED CHARACTER TO B
  1078.     MOV    AL,Byte Ptr FOPFLG    ;IS FILE OUTPUT    ACTIVE?
  1079.     OR    AL,AL
  1080.     JNZ    NOWRIT            ;GO CHECK FOR PAGE PAUSE IF NOT
  1081. ;
  1082. ; FILE OUTPUT MODE ACTIVE - MAKE SURE WE HAVE ROOM IN BUFFER TO ADD
  1083. ; NEXT CHARACTER.  IF BUFFER FULL, WRITE OUT CURRENT RECORD FIRST
  1084. ; AND THEN START A NEW RECORD WITH CURRENT CHARACTER.
  1085. ;
  1086.     MOV    BX,Word Ptr BUFPNT    ;GET CURRENT BUFFER POINTER
  1087.     MOV    AL,Byte Ptr BUFCNT    ;GET BUFFER CAPACITY REMAINING
  1088.     OR    AL,AL
  1089.     JNZ    PUTBUF            ;CONTINUE IF BUFFER NOT FULL
  1090.     MOV    DX,(Offset OUTFCB)    ;OTHERWISE, WRITE THE CURRENT BUFFER OUT
  1091.     MOV    CL,WRITE
  1092.     CALL    CPM            ;(NOTE CALL MUST SAVE CHARACTER    IN B)
  1093.     OR    AL,AL
  1094.     JZ    L_23    
  1095.     JMP    WRTERR            ;TAKE WRITE ERROR EXIT IF DISK FULL OR R/O
  1096. L_23:
  1097.     MOV    BX,(Offset OUTBUF)    ;RESET BUFFER POINTER
  1098.     MOV    AL,128            ;RESET BUFFER CAPACITY
  1099. PUTBUF:    MOV    M,CH            ;SHOVE CHARACTER TO NEXT BUFFER POSITION
  1100.     INC    BX            ;BUMP BUFFER POINTER
  1101.     MOV    Word Ptr BUFPNT,BX    ;.. AND SAVE IT
  1102.     DEC    AL            ;DOCK COUNT OF CHARACTERS LEFT IN BUFFER
  1103.     MOV    Byte Ptr BUFCNT,AL    ;..AND SAVE IT
  1104. NOWRIT:    MOV    AL,CH            ;RECALL    STRIPPED CHARACTER
  1105.     ENDIF
  1106.  
  1107. ;
  1108. ;IF PRINTER OPTION
  1109. ;
  1110.  
  1111.     IF    POPT
  1112.     MOV    DL,AL            ;SETUP LIST OUTPUT CALL
  1113.     MOV    CL,5
  1114.     MOV    AL,Byte Ptr POPFLG    ;TEST PRINTER FLAG
  1115.     OR    AL,AL
  1116.     JNZ    L_24    
  1117.     CALL    CPM            ;PRINT CHARACTER IF FLAG TRUE
  1118. L_24:
  1119.     MOV    AL,DL            ;RECALL    CHARACTER
  1120.     ENDIF
  1121.  
  1122.  
  1123.     IF    PGPAWZ
  1124.     CMP    AL,0AH            ;DO WE HAVE A LF?
  1125.     JNZ    TYPRET            ;EXIT IF NOT
  1126.     ENDIF
  1127.  
  1128.     IF    NOPT AND PGPAWZ
  1129.     MOV    AL,Byte Ptr NOPFLG    ;IS THE    PAGE PAUSE FUNCTION DISABLED?
  1130.     OR    AL,AL
  1131.     JZ    TYPRET            ;EXIT IF SO
  1132.     ENDIF
  1133.  
  1134.     IF    PGPAWZ
  1135.     MOV    AL,Byte Ptr LINCNT    ;GET LINE COUNT
  1136.     INC    AL            ;BUMP IT
  1137.     CMP    AL,LPS            ;ARE WE    AT THE END OF THE SCREEN?
  1138.     JB    NOTEOS            ;SKIP IF NOT
  1139.     MOV    DX,(Offset EOSMSG)    ;ELSE, DISPLAY PAUSE MESSAGE
  1140.     MOV    CL,9            ;..WITHOUT CHECKING FOR    LFS
  1141.     INT    224
  1142.     CALL    CINPUT            ;WAIT FOR CHARACTER
  1143.     CMP    AL,'C'-40H
  1144.     JNZ    L_25    
  1145.     JMP    EXIT            ;ABORT ON CTRL-C
  1146. L_25:
  1147.     XOR    AL,AL            ;RESET LINE COUNT
  1148. NOTEOS:    MOV    Byte Ptr LINCNT,AL    ;SAVE NEW LINE COUNT
  1149.     ENDIF
  1150.  
  1151. TYPRET:    POP    BX            ;EXIT FROM TYPE
  1152.     POP    DX
  1153.     POP    CX
  1154.     RET
  1155. ;
  1156. ; OUTPUT CHARACTER
  1157. ;
  1158. TYPE1:    MOV    DL,AL            ;GET CHARACTER INTO BDOS ENTRY REGISTER
  1159.     MOV    CL,WRCHR
  1160.     INT    224            ;CALL CONOUT VIA THE BDOS
  1161.     RET
  1162. ;
  1163. ; PRINT    A STRING AT HL OF LENGTH B
  1164. ;
  1165. TYPEIT:    MOV    AL,M
  1166.     CALL    SEND_CHAR
  1167.     LAHF
  1168.     INC    BX
  1169.     SAHF
  1170.     DEC    CH
  1171.     JNZ    TYPEIT
  1172.     RET
  1173. ;
  1174. ; PRINT    STRING TERMINATED WITH LAST BYTE HIGH ON CONSOLE.
  1175. ;
  1176. PRINT:    MOV    SI,DX
  1177.     MOV    AL,[SI]
  1178.     LAHF
  1179.     XCHG    AL,AH
  1180.     PUSH    AX
  1181.     XCHG    AL,AH
  1182.     AND    AL,7FH
  1183.     CALL    SEND_CHAR
  1184.     POP    AX
  1185.     XCHG    AL,AH
  1186.     OR    AL,AL
  1187.     JNS    L_26
  1188.     RET
  1189. L_26:
  1190.     LAHF
  1191.     INC    DX
  1192.     SAHF
  1193.     JMPS    PRINT
  1194. ;
  1195. ; FETCH    CHARACTER FROM CONSOLE (WITHOUT    ECHO)
  1196. ;
  1197. CINPUT:    MOV    Byte Ptr FUNC,3        ;bios console input function
  1198.     MOV    Word Ptr BIOS_DESC,CX    ;pass disk number to bios descriptor
  1199.     MOV    Word Ptr BIOS_DESC+2,0    ;fill remaining descriptor (DX) zero
  1200.     MOV    DX,(Offset FUNC)    ;point to function parameter block
  1201.     MOV    CL,50            ;direct bios call
  1202.     INT    224            ;do it, to it...
  1203.     AND    AL,7FH
  1204.     RET
  1205. ;
  1206. ; CHECK    FOR A CTRL-C OR    CTRL-S ENTERED FROM THE    KEYBOARD.  JUMP    TO
  1207. ; EXIT IF CTRL-C, PAUSE    ON CTRL-S.
  1208. ;
  1209. CKABRT:    MOV    Byte Ptr FUNC,2        ;bios console status function
  1210.     MOV    Word Ptr BIOS_DESC,CX    ;pass disk number to bios descriptor
  1211.     MOV    Word Ptr BIOS_DESC+2,0    ;fill remaining descriptor (DX) zero
  1212.     MOV    DX,(Offset FUNC)    ;point to function parameter block
  1213.     MOV    CL,50            ;direct bios call
  1214.     INT    224            ;do it, to it...
  1215.     OR    AL,AL
  1216.     JNZ    L_27    
  1217.     RET                ;NO, RETURN TO CALLER
  1218. L_27:
  1219.     CALL    CINPUT            ;GET CHARACTER
  1220.     CMP    AL,'C'-40H        ;CTRL-C?
  1221.     JNZ    L_28    
  1222.     JMP    EXIT            ;IF CTRL-C THEN    QUIT
  1223. L_28:
  1224.     CMP    AL,'S'-40H        ;CTRL-S?
  1225.     JZ    L_29    
  1226.     RET                ;NO, RETURN TO CALLER
  1227. L_29:
  1228.     CALL    CINPUT            ;YES, WAIT FOR ANOTHER CHAR.
  1229.     CMP    AL,'C'-40H        ;MIGHT BE CTRL-C
  1230.     JNZ    L_30    
  1231.     JMP    EXIT            ;EXIT IF CTRL-C, ELSE FALL THRU    AND CONTINUE
  1232. L_30:
  1233.     RET
  1234. ;
  1235. ; ENTRY    TO BDOS    SAVING ALL EXTENDED REGISTERS
  1236. ;
  1237. CPM:    PUSH    CX
  1238.     PUSH    DX
  1239.     PUSH    BX
  1240.     INT    224
  1241.     POP    BX
  1242.     POP    DX
  1243.     POP    CX
  1244.     RET
  1245. ;
  1246. ; FOR FILE OUTPUT MODE,    RETURN TO OLD USER AREA    AND SET    DMA FOR
  1247. ; THE FILE OUTPUT BUFFER.
  1248. ;
  1249.  
  1250.     IF    UOPT OR AOPT
  1251. SETFOP:
  1252.     MOV    AL,Byte Ptr OLDUSR    ;GET USER NUMBER AT STARTUP
  1253.     MOV    DL,AL
  1254.     MOV    CL,CURUSR
  1255.     CALL    CPM            ;RESET THE OLD USER NUMBER IF CP/M 2
  1256.     ENDIF
  1257.  
  1258.     IF    FOPT
  1259.     MOV    DX,(Offset OUTBUF)    ;MOVE DMA FROM SEARCH BUFFER INTO THE
  1260.     JMPS    SET2            ;..OUTPUT BUFFER
  1261.     ENDIF
  1262.  
  1263.     RET
  1264. ;
  1265. ; MOVE DISK BUFFER DMA TO DEFAULT BUFFER FOR DIRECTORY SEARCH OPERATIONS
  1266. ; AND BDOS MEDIA CHANGE ROUTINES.
  1267. ;
  1268. SETSRC:    MOV    DX,BASE+80H
  1269. SET2:    MOV    CL,SETDMA
  1270.     JMPS    CPM
  1271. ;
  1272. ; PRINT    THE AMOUNT OF FREE SPACE REMAINING ON THE SELECTED DRIVE
  1273. ;
  1274. PRTFRE:    MOV    BX,Word Ptr FREEBY    ;GET SPACE LEFT BEFORE ADDING TO MASTER.DIR
  1275.     CALL    DECPRT            ;PRINT K FREE
  1276.     MOV    DX,(Offset TOTMS6)    ;PRINT " FREE."
  1277.     JMP    PRINT
  1278. ;
  1279. ; COMPARE ROUTINE FOR SORT
  1280. ;
  1281. COMPR:    PUSH    BX            ;SAVE TABLE ADDR
  1282.     MOV    DL,M            ;LOAD LOW ORDER
  1283.     INC    BX
  1284.     MOV    DH,M            ;LOAD HIGH ORDER
  1285.     INC    BX
  1286.     MOV    CL,M
  1287.     INC    BX
  1288.     MOV    CH,M
  1289. ;
  1290. ; BC, DE NOW POINT TO ENTRIES TO BE COMPARED
  1291. ;
  1292.     XCHG    BX,DX
  1293.     MOV    DL,AL            ;GET COUNT
  1294. CMPLP:    MOV    SI,CX
  1295.     MOV    AL,[SI]
  1296.     CMP    AL,M
  1297.     LAHF
  1298.     INC    BX
  1299.     SAHF
  1300.     LAHF
  1301.     INC    CX
  1302.     SAHF
  1303.     JNZ    NOTEQL            ;QUIT ON MISMATCH
  1304.     DEC    DL            ;OR END    OF COUNT
  1305.     JNZ    CMPLP
  1306. NOTEQL:    POP    BX
  1307.     RET                ;COND CODE TELLS ALL
  1308. ;
  1309. ; SWAP ENTRIES IN THE ORDER TABLE
  1310. ;
  1311. SWAP:    MOV    CX,(Offset ORDER)-2    ;TABLE BASE
  1312.     SHL    BX,1            ;*2
  1313.     LAHF                ;+ BASE
  1314.     ADD    BX,CX
  1315.     SAHF
  1316.     XCHG    BX,DX
  1317.     SHL    BX,1            ;*2
  1318.     LAHF                ;+ BASE
  1319.     ADD    BX,CX
  1320.     RCR    SI,1
  1321.     SAHF
  1322.     RCL    SI,1
  1323.     MOV    CL,M
  1324.     MOV    SI,DX
  1325.     MOV    AL,[SI]
  1326.     XCHG    BX,DX
  1327.     MOV    M,CL
  1328.     MOV    SI,DX
  1329.     MOV    [SI],AL
  1330.     LAHF
  1331.     INC    BX
  1332.     SAHF
  1333.     LAHF
  1334.     INC    DX
  1335.     SAHF
  1336.     MOV    CL,M
  1337.     MOV    SI,DX
  1338.     MOV    AL,[SI]
  1339.     XCHG    BX,DX
  1340.     MOV    M,CL
  1341.     MOV    SI,DX
  1342.     MOV    [SI],AL
  1343.     RET
  1344. ;
  1345. ; NEW COMPARE ROUTINE
  1346. ;
  1347. COMPARE:MOV    CX,(Offset ORDER)-2
  1348.     SHL    BX,1
  1349.     ADD    BX,CX
  1350.     XCHG    BX,DX
  1351.     SHL    BX,1
  1352.     ADD    BX,CX
  1353.     XCHG    BX,DX
  1354.     MOV    CL,M
  1355.     INC    BX
  1356.     MOV    CH,M
  1357.     XCHG    BX,DX
  1358.     MOV    DL,M
  1359.     INC    BX
  1360.     MOV    DH,M
  1361.     XCHG    BX,DX
  1362.     MOV    DL,AL            ;COUNT
  1363. CMPLPE:    MOV    SI,CX
  1364.     MOV    AL,[SI]
  1365.     CMP    AL,M
  1366.     LAHF
  1367.     INC    CX
  1368.     SAHF
  1369.     LAHF
  1370.     INC    BX
  1371.     SAHF
  1372.     JZ    L_31
  1373.     RET
  1374. L_31:
  1375.     DEC    DL
  1376.     JNZ    CMPLPE
  1377.     RET
  1378. ;
  1379. ; ERROR    EXIT
  1380. ;
  1381.  
  1382.     IF    FOPT
  1383. ERXIT:
  1384.     MOV    AL,0FFH
  1385.     MOV    Byte Ptr FOPFLG,AL    ;DISABLE FILE OUTPUT MODE ON ERROR
  1386.     ENDIF
  1387.  
  1388.     CALL    CRLF            ;SPACE DOWN
  1389.     POP    DX            ;GET POINTER TO    MESSAGE    STRING
  1390.     CALL    PRINT            ;PRINT IT
  1391.     MOV    DX,(Offset ERRMS1)    ;PRINT " ERROR"
  1392.     CALL    PRINT
  1393.     CALL    CRLF            ;SPACE DOWN
  1394. ;
  1395. ; EXIT - ALL DONE, RESTORE STACK
  1396. ;
  1397. EXIT:    MOV    CL,CONST        ;CHECK CONSOLE STATUS
  1398.     CALL    CPM
  1399.     OR    AL,AL            ;CHAR WAITING?
  1400.     MOV    CL,RDCHR
  1401.     JZ    L_32    
  1402.     CALL    CPM            ;GOBBLE    UP CHAR
  1403. L_32:
  1404.     MOV    AL,Byte Ptr ROPFLG    ;IF DISK SYSTEM    WAS RESET
  1405.     OR    AL,AL
  1406.     MOV    AL,Byte Ptr OLDDSK    ;GET DEFAULT DISK AT STARTUP
  1407.     MOV    DL,AL
  1408.     MOV    CL,SELDSK        ;RESELECT IT
  1409.     JNZ    L_33    
  1410.     CALL    CPM
  1411. L_33:
  1412. ;
  1413.     MOV    CL,0        ;BDOS FUNCTION, WARM BOOT
  1414.     MOV    DL,0
  1415.     INT    224        ;RETURN TO CP/M-86
  1416. ;
  1417. ; END OF PROGRAM CODE
  1418. ;
  1419. ; INITIALIZED DATA AREA
  1420. ;
  1421. DREMSG    DB    'Driv','e' OR 80H
  1422. ;
  1423.  
  1424.     IF    PGPAWZ
  1425. EOSMSG    DB    0AH,'Press any key to continue, or CTRL-C to exit',0DH,0AH,0AH,'$'  
  1426.     ENDIF
  1427.  
  1428. ;
  1429. ERRMS1    DB    ' '
  1430. ;
  1431. ERRMS2    DB    'Erro','r' OR 80H
  1432. ;
  1433.  
  1434.     IF    REPERR
  1435. ERRTAG    DB    ' -','>' OR 80H
  1436.     ENDIF
  1437.  
  1438. ;
  1439. NOFMS1    DB    0DH,0AH,'No such file on Drive '
  1440. ;
  1441. NOFMS2    DB    '  -',' ' OR 80H
  1442. ;
  1443. TOTMS1    DB    0DH,0AH,0DH,0AH,'Drive',' ' OR 80H
  1444. ;
  1445. TOTMS2    DB    ', User',' ' OR    80H
  1446. ;
  1447. TOTMS3    DB    ' contains',' '    OR 80H
  1448. ;
  1449. TOTMS4    DB    'K in',' ' OR 80H
  1450. ;
  1451. TOTMS5    DB    ' files with',' ' OR 80H
  1452. ;
  1453. TOTMS6    DB    'K free',0DH,0AH OR 80H
  1454. ;
  1455. USRMSG    DB    'User ','#' OR 80H
  1456. ;
  1457. FNDFLG    DB    0            ;FLAG WHETHER ANY FILES MATCHED
  1458. ;
  1459.  
  1460.     IF    PGPAWZ
  1461. LINCNT    DB    0            ;COUNT OF LINES    PRINTED    ON SCREEN
  1462.     ENDIF
  1463.  
  1464. ;
  1465. ; DRIVE    CODE/USER AREA LOOKUP TABLE
  1466. ; NOTE THAT THE    LODRV-HIDRV TABLE IS INCLUDED HERE FULLY CONFIGURED.
  1467. ; FOR YOUR OWN USE, YOU    SHOULD CHANGE THE MAXIMUM USER AREAS AS
  1468. ; APPROPRIATE FOR EACH DRIVE ON    YOUR SYSTEM, AND THEN DELETE ANY
  1469. ; DBS REFERENCING DRIVES THAT DON'T EXIST.
  1470. ;
  1471. LODRV    EQU    (Offset $)        ;MARK BEGINNING    OF DRIVE/USER TABLE
  1472.     DB    15            ;MAXIMUM USER AREA FOR DRIVE A
  1473.     DB    15            ;   "      "    "    "     "   B
  1474.     DB    15            ;   "      "    "    "     "   C
  1475.     DB    15            ;   "      "    "    "     "   D
  1476.     DB    15            ;   "      "    "    "     "   E
  1477.     DB    15            ;   "      "    "    "     "   F
  1478.     DB    15            ;   "      "    "    "     "   G
  1479.     DB    15            ;   "      "    "    "     "   H
  1480. ;    DB    15            ;   "      "    "    "     "   I
  1481. ;    DB    15            ;   "      "    "    "     "   J
  1482. ;    DB    15            ;   "      "    "    "     "   K
  1483. ;    DB    15            ;   "      "    "    "     "   L
  1484. ;    DB    15            ;   "      "    "    "     "   M
  1485. ;    DB    15            ;   "      "    "    "     "   N
  1486. ;    DB    15            ;   "      "    "    "     "   O
  1487. ;    DB    15            ;   "      "    "    "     "   P
  1488. ;
  1489. HIDRV    EQU    (Offset $)        ;MARK END OF DRIVE/USER    TABLE
  1490. ;
  1491. ; OPTION FIELD LOOKUP TABLE.
  1492. ; NOTE THAT YOU    CAN FORCE ANY OF THESE OPTIONS AS A DEFAULT BY
  1493. ; CHANGING THE LETTER FOR THE OPTION INTO A ZERO (ASSUMING THAT
  1494. ; ITS ENABLING EQUATE IS TRUE).     EACH OPTION THAT YOU HARD-WIRE    IN
  1495. ; THIS MANNER WILL NO LONGER BE    RECOGNIZED AS A    COMMAND    LINE OPTION,
  1496. ; AND IF YOU REDUNDANTLY KEY IT IN, XDIR WILL FLAG IT AS UNRECOGNIZED.
  1497. ;
  1498. OTBL    EQU    (Offset $)        ;MARK START OF OPTION TABLE
  1499. ;
  1500. ;ALL USERS-OPTION FLAG
  1501. ;
  1502.  
  1503.     IF    AOPT
  1504. AOPFLG    DB    'A'
  1505.     ENDIF
  1506.  
  1507. ;
  1508. ;MULTI-DISK-OPTION FLAG
  1509. ;
  1510.  
  1511.     IF    DOPT
  1512. DOPFLG    DB    'D'
  1513.     ENDIF
  1514.  
  1515. ;
  1516. ;FILE-OUTPUT-OPTION FLAG
  1517. ;
  1518.  
  1519.     IF    FOPT
  1520. FOPFLG    DB    'F'
  1521.     ENDIF
  1522.  
  1523. ;
  1524. ;NO PAGE-PAUSE OPTION FLAG
  1525. ;
  1526.  
  1527.     IF    NOPT AND PGPAWZ
  1528. NOPFLG    DB    'N'
  1529.     ENDIF
  1530.  
  1531. ;
  1532. ;PRINTER OPTION    FLAG
  1533. ;
  1534.  
  1535.     IF    POPT
  1536. POPFLG    DB    'P'
  1537.     ENDIF
  1538.  
  1539. ;
  1540. ;RESET OPTION FLAG
  1541. ;
  1542. ROPFLG    DB    'R'
  1543. ;
  1544. ;SYSTEM    FILE OPTION FLAG
  1545. ;
  1546.  
  1547.     IF    SOPT
  1548. SOPFLG    DB    'S'
  1549. ;
  1550.     ENDIF
  1551.  
  1552. OEND    EQU    (Offset $)        ;MARK END OF OPTION TABLE
  1553. ;
  1554. ; END OF OPTION    LOOKUP TABLE
  1555. ;
  1556.  
  1557.     IF    FOPT
  1558. BUFPNT    DW    (Offset OUTBUF)        ;POINTER TO NEXT LOCATION IN OUTPUT BUFFER
  1559. BUFCNT    DB    128            ;NUMBER OF BYTES LEFT IN OUTPUT BUFFER
  1560. OPNFLG    DB    0            ;FILE OPEN FLAG FOR ALL USER FILE OUTPUT
  1561. ;
  1562. OUTFCB    DB    0,'XDIR    DIR'
  1563.     DB    0            ;REST OF XDIR.DIR FILE CONTROL BLOCK
  1564.     DB    0
  1565.     DB    0
  1566.     DB    0
  1567.     DB    0
  1568.     DB    0
  1569.     DB    0
  1570.     DB    0
  1571.     DB    0
  1572.     DB    0
  1573.     DB    0
  1574.     DB    0
  1575.     DB    0
  1576.     DB    0
  1577.     DB    0
  1578.     DB    0
  1579.     DB    0
  1580.     DB    0
  1581.     DB    0
  1582.     DB    0
  1583.     DB    0
  1584. ;
  1585. OUTBUF    RS    128            ;OUTPUT    FILE BUFFER
  1586.     ENDIF
  1587.  
  1588. ;
  1589. ; UNINITIALIZED    DATA AREA
  1590. ;
  1591. ;storage for 5 byte BIOS function descriptor
  1592. ;
  1593. FUNC        RS    1        ;bios function code goes here
  1594. BIOS_DESC    RS    2        ;[CX] data goes here
  1595.         RS    2        ;[DX] data goes here
  1596. ;
  1597. BASUSR    RS    1            ;DUPE OF ORIGINAL DIRECTORY USER # TO SEARCH
  1598. BLKMAX    RS    2            ;HIGHEST BLOCK # ON DRIVE
  1599. BLKMSK    RS    1            ;SEC/BLK - 1
  1600. BLKSHF    RS    1            ;# SHIFTS TO MULT BY SEC/BLK
  1601. COUNT    RS    2            ;ENTRY COUNT
  1602. dsksiz    RS    2            ;HIGHEST FILE #    IN DIRECTORY
  1603. FREEBY    RS    2            ;CONTAINS NUMBER OF K LEFT ON DIRECTORY    DRIVE
  1604. GAP    RS    2            ;SORT ROUTINE STORAGE
  1605. I    RS    2            ;SORT ROUTINE STORAGE
  1606. J    RS    2            ;SORT ROUTINE STORAGE
  1607. JGAP    RS    2            ;SORT ROUTINE STORAGE
  1608. LZFLG    RS    1            ;0 WHEN    PRINTING LEADING ZEROS
  1609. MAXUSR    RS    1            ;MAXIMUM USER #    FOR DRIVE FROM LOOKUP TABLE
  1610. NEWUSR    RS    1            ;CONTAINS USER NUMBER SELECTED BY "$U" OPTION
  1611. NEXTT    RS    2            ;NEXT TABLE ENTRY
  1612. OLDDSK    RS    1            ;HOLDER    FOR CURRENTLY LOGGED-IN    DRIVE
  1613. OLDUSR    RS    1            ;CONTAINS USER NUMBER UPON INVOCATION
  1614. SCOUNT    RS    2            ;# TO SORT
  1615. SUPSPC    RS    1            ;LEADING SPACE FLAG FOR    DECIMAL    ROUTINE
  1616. TBLOC    RS    2            ;POINTER TO START OF NAME TABLE
  1617. TEMP    RS    2            ;SAVE DIR ENTRY
  1618. TOTFIL    RS    2            ;TOTAL NUMBER OF FILES
  1619. TOTSIZ    RS    2            ;TOTAL SIZE OF ALL FILES
  1620. ORDER    EQU    (Offset $)        ;ORDER TABLE STARTS HERE
  1621. ;
  1622.     RS    4000H
  1623.     DB    0
  1624. ;
  1625.     END
  1626.