home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol013 / sd-2-6.asm < prev    next >
Assembly Source File  |  1984-04-29  |  18KB  |  863 lines

  1. ;
  2. ;            SD.ASM
  3. ;          (revised 2/6/81)
  4. ;
  5. ;        SUPER DIRECTORY    PROGRAM
  6. ;          by Bruce R. Ratoff
  7. ;
  8. ;Displays the directory    of a CP/M disk,    sorted alphabetically,
  9. ;with the file size in K, rounded to the nearest CP/M block size.
  10. ;
  11. ;This latest variation on a common theme will automatically adjust
  12. ;itself    for any    block size and directory length    under CP/M 1.4 or 2.x
  13. ;or MP/M (any version).     If the    screen fills, program will pause until
  14. ;a key is struck (see NPL and LPS equates below).  Total space used
  15. ;and number of files are printed at end.
  16. ;
  17. ;Command: SD FILENAME.FILETYPE or just SD
  18. ;
  19. ;Allows    '*' or '?' type    specifications.     Drive name may    also be
  20. ;specified.  Ignores "SYS" files unless    SOPT is    TRUE and 'S' option
  21. ;is given (i.e., SD *.*    S will print all files).
  22. ;
  23. ;
  24. ;
  25. ;2/6/81      CHANGED SORT TO HAVE ODD GAP(K+P SAY ITS FASTER)
  26. ;
  27. ;1/6/80      CHANGED SORT FROM BUBBLE SORT    TO SHELL SHORT
  28. ;      FOR FASTER SPEED.
  29. ;
  30. ;12/24/80 CHANGED BIOS CONOUT TO BDOS CONOUT
  31. ;      TO ALLOW PRINTING OF DIRECTORY WITH
  32. ;      CONTROL P.
  33. ;      ALSO ADDED PRINT OF REMAINING    SPACE 
  34. ;      EVEN IF FILE NOT FOUND.(STEVE    NOSSEN)
  35. ;
  36. ;12/15/80 Added    space suppression when printing    file
  37. ;      totals.  (KBP)
  38. ;
  39. ;12/14/80 Added    logic to print space remaining on disk.
  40. ;      Changed ^C test so that interrupting character is
  41. ;      not echoed (makes remote use cleaner).  (BRR)
  42. ;
  43. ;12/02/80 Fixed    bug in print routine which compared last file
  44. ;      against garbage before printing. (BRR)
  45. ;
  46. ;11/29/80 Changed to allow printing 4 file names. (Ben Bronson
  47. ;      and Keith Petersen)
  48. ;
  49. ;11/22/80 Fixed    bug in handling    >256 files.  Changed abort test    in
  50. ;      print    routine    to only    abort on control-c.  (brr)
  51. ;
  52. ;Based on 'DIRS' by Keith Petersen, W8SDZ
  53. ;
  54. ;Set 'RMAC' TRUE to assemble with relocating assembler (requires
  55. ;link with PAGE    0 equates in separate file).
  56. ;
  57. FALSE    EQU    0        ;DEFINE    LOGICAL    FALSE
  58. TRUE    EQU    NOT FALSE    ;DEFINE    LOGICAL    TRUE
  59. ;
  60. ALTCPM    EQU    FALSE    ;PUT TRUE HERE FOR H8 OR TRS-80
  61. RMAC    EQU    FALSE    ;PUT TRUE HERE FOR ASSEMBLY BY RMAC
  62. SOPT    EQU    TRUE   ;PUT TRUE TO ALLOW 'DIR *.* S' FORM
  63. WIDE    EQU    TRUE    ;PUT TRUE TO ALLOW 4 NAMES ACROSS
  64. ;
  65.     IF    ALTCPM
  66. BASE    EQU    4200H
  67. TPA    EQU    4300H
  68.     ENDIF
  69. ;
  70.     IF    RMAC
  71.     EXTRN    BASE,FCB,BDOS    ;MAKE BASE EXTERNAL
  72.     ENDIF
  73. ;
  74.     IF    (NOT ALTCPM) AND (NOT RMAC)
  75. BASE    EQU    $    ;WILL DEFAULT TO 0 (OR 100H WITH MAC +R    OPTION)
  76. TPA    EQU    100H
  77.     ENDIF
  78. ;
  79.     IF    NOT RMAC
  80. FCB    EQU    BASE+5CH
  81. BDOS    EQU    BASE+5
  82.     ENDIF
  83. ;
  84.     IF    WIDE
  85. NPL    EQU    4    ;NUMBER    OF NAMES PER LINE
  86.     ENDIF
  87. ;
  88.     IF    NOT WIDE
  89. NPL    EQU    3    ;NUMBER    OF NAMES PER LINE
  90.     ENDIF
  91. ;
  92. LPS    EQU    23    ;NUMBER    OF LINES PER SCREEN
  93. DELIM    EQU    ':'    ;FENCE (DELIMITER) CHARACTER
  94. ;
  95.     IF    NOT RMAC
  96.     ORG    TPA
  97.     ENDIF
  98. ;
  99. ;Save the stack
  100. START:    LXI    H,0
  101.     DAD    SP    ;H=STACK
  102.     SHLD    STACK     ;SAVE IT
  103.     LXI    SP,STACK ;GET NEW STACK
  104. ;
  105.     IF    SOPT
  106.     LDA    FCB+17     ;SAVE S OPTION    FLAG
  107.     STA    SOPFLG     ;(BLANK OR LETTER S)
  108.     ENDIF
  109. ;
  110.     SUB    A
  111.     STA    USERNO     ;DEFAULT TO USER 0
  112.     STA    LINCNT     ;CLEAR    COUNT OF LINES ON SCREEN
  113.     MVI    C,12
  114.     CALL    BDOS     ;CHECK    CP/M VERSION
  115.     SHLD    VERFLG     ;LO ORD >0 IF 2.X, HI ORD>0 IF    MP/M
  116.     MOV    A,L     ;2.X?
  117.     ORA    A
  118.     JZ    CHKDRV     ;SKIP USER NUMBER STUFF IF 1.4
  119.     MVI    E,0FFH
  120.     MVI    C,CURUSR ;INTERROGATE USER NUMBER
  121.     CALL    BDOS
  122.     STA    USERNO
  123.     LDA    MPMFLG     ;MP/M?
  124.     ORA    A    ;IF SO,    TYPE HEADING LINE
  125.     JZ    CHKDRV     ; ELSE    SKIP IT
  126.     LXI    D,USRMSG ;DISPLAY IT
  127.     MVI    C,PRINT
  128.     CALL    BDOS     ;FIRST    PART OF    MESSAGE
  129.     LDA    USERNO
  130.     CPI    10    ;IF USER NO. > 9 PRINT LEADING 1
  131.     JC    DUX
  132.     MVI    A,'1'
  133.     CALL    TYPE
  134.     LDA    USERNO     ;PRINT    LOW DIGIT OF USER NO.
  135.     SUI    10
  136. ;
  137. DUX:    ADI    '0'
  138.     CALL    TYPE
  139.     LXI    D,USRMS2 ;PRINT    TAIL OF    MESSAGE
  140.     MVI    C,PRINT
  141.     CALL    BDOS
  142.     MVI    A,1
  143.     STA    LINCNT    ;WE USED A LINE
  144. ;
  145. CHKDRV:    LXI    H,FCB
  146.     MOV    A,M    ;GET DRIVE NAME
  147.     ORA    A    ;ANY SPECIFIED?
  148.     JNZ    START2    ;YES SKIP NEXT ROUTINE
  149.     MVI    C,CURDSK
  150.     CALL    BDOS    ;GET CURRENT DISK NR
  151.     INR    A    ;MAKE A:=1
  152.     STA    FCB
  153. ;
  154. START2:    ADI    'A'-1    ;MAKE IT PRINTABLE
  155.     STA    DRNAM    ;SAVE FOR LATER
  156.     LXI    H,FCB+1    ;POINT TO NAME
  157.     MOV    A,M    ;ANY SPECIFIED?
  158.     CPI    ' '
  159.     JNZ    GOTFCB
  160. ;No FCB    - make FCB all '?'
  161.     MVI    B,11    ;FN+FT COUNT
  162. ;
  163. QLOOP:    MVI    M,'?'    ;STORE '?' IN FCB
  164.     INX    H
  165.     DCR    B
  166.     JNZ    QLOOP
  167. ;
  168. GOTFCB:    MVI    A,'?'    ;FORCE WILD EXTENT
  169.     STA    FCB+12
  170.     LDA    FCB    ;CHECK FOR EXPLICIT DRIVE
  171.     DCR    A
  172.     MOV    E,A    ;SELECT    SPECIFIED DRIVE
  173.     MVI    C,SELDSK
  174.     CALL    BDOS
  175.     SUB    A    ;ZAP DRIVE NO. IN FCB SO SELECTED DRIVE    IS USED
  176.     STA    FCB
  177.     LDA    VERFLG    ;CHECK VERS.
  178.     ORA    A
  179.     JZ    V14    ;PRE-2.X...GET PARAMS THE 1.4 WAY
  180. ;
  181.     MVI    C,CURDPB;IT'S 2.X OR MP/M...REQUEST DPB
  182.     CALL    BDOS
  183.     INX    H
  184.     INX    H
  185.     MOV    A,M    ;GET BLOCK SHIFT
  186.     STA    BLKSHF
  187.     INX    H    ;BUMP TO BLOCK MASK
  188.     MOV    A,M
  189.     STA    BLKMSK    ;GET IT
  190.     INX    H
  191.     INX    H
  192.     MOV    E,M    ;GET MAX BLOCK #
  193.     INX    H
  194.     MOV    D,M
  195.     XCHG
  196.     SHLD    BLKMAX    ;SAVE IT
  197.     XCHG
  198.     INX    H
  199.     MOV    E,M    ;GET DIRECTORY SIZE
  200.     INX    H
  201.     MOV    D,M
  202.     XCHG
  203.     SHLD    DIRMAX    ;SAVE IT
  204.     JMP    SETTBL    ;DONE...GO SET UP ORDER    TABLE
  205. ;
  206. V14:    LHLD    BDOS+1    ;GET PARAMS 1.4    STYLE
  207.     MVI    L,3BH    ;POINT TO DIRECTORY SIZE
  208.     MOV    E,M    ;GET IT
  209.     MVI    D,0    ;FORCE HI ORD TO 0
  210.     PUSH    D    ;SAVE FOR LATER
  211.     INX    H    ;POINT TO BLOCK    SHIFT
  212.     MOV    A,M    ;FETCH
  213.     STA    BLKSHF    ;SAVE
  214.     INX    H    ;POINT TO BLOCK    MASK
  215.     MOV    A,M    ;FETCH IT
  216.     STA    BLKMSK    ;AND SAVE IT
  217.     INX    H
  218.     MOV    E,M    ;GET MAX. BLOCK    NO.
  219.     MVI    D,0
  220.     XCHG
  221.     SHLD    BLKMAX    ;SAVE IT
  222.     POP    H    ;RESTORE DIRECTORY SIZE
  223.     SHLD    DIRMAX    ;SAVE IT
  224. ;
  225. SETTBL:    INX    H    ;DIRECTORY SIZE    IS DIRMAX+1
  226.     DAD    H    ;DOUBLE    DIRECTORY SIZE
  227.     LXI    D,ORDER    ;TO GET    SIZE OF    ORDER TABLE
  228.     DAD    D    ;ALLOCATE ORDER    TABLE
  229.     SHLD    TBLOC    ;NAME TABLE BEGINS WHERE ORDER TABLE ENDS
  230.     SHLD    NEXTT
  231.     XCHG
  232.     LHLD    BDOS+1    ;MAKE SURE WE HAVE ROOM    TO CONTINUE
  233.     MOV    A,E
  234.     SUB    L
  235.     MOV    A,D
  236.     SBB    H
  237.     JNC    OUTMEM
  238. ;
  239. ;Look up the FCB in the    directory
  240. SFIRST:    MVI    C,FSRCHF ;GET 'SEARCH FIRST' FNC
  241.     LXI    D,FCB
  242.     CALL    BDOS    ;READ FIRST
  243.     INR    A    ;WERE THERE ANY?
  244.     JNZ    SOME    ;GOT SOME
  245. ;
  246. NONE:    LXI    D,FNF    ;PREPARE MP/M ERROR MESSAGE
  247.     LDA    MPMFLG
  248.     ORA    A    ;USE IT    IF REALLY MP/M
  249.     JNZ    ERXIT1
  250.     CALL    ERXIT    ;ELSE USE CP/M ERROR MESSAGE
  251.     DB    'NO FILE$'
  252. FNF:    DB    'File not found.$'
  253. ;
  254. USRMSG:    DB    'Directory for user $'
  255. USRMS2:    DB    ':',13,10,'$'
  256. ;
  257. ;Read more directory entries
  258. MORDIR:    MVI    C,FSRCHN ;SEARCH NEXT
  259.     LXI    D,FCB
  260.     CALL    BDOS    ;READ DIR ENTRY
  261.     INR    A    ;CHECK FOR END (0FFH)
  262.     JZ    SPRINT    ;NO MORE - SORT    & PRINT
  263. ;
  264. ;Point to directory entry 
  265. SOME:    DCR    A    ;UNDO PREV 'INR    A'
  266.     ANI    3    ;MAKE MODULUS 4
  267.     ADD    A    ;MULTIPLY...
  268.     ADD    A    ;..BY 32 BECAUSE
  269.     ADD    A    ;..EACH    DIRECTORY
  270.     ADD    A    ;..ENTRY IS 32
  271.     ADD    A    ;..BYTES LONG
  272.     LXI    H,BASE+81H ;POINT TO BUFFER
  273.             ;(SKIP TO FN/FT)
  274.     ADD    L    ;POINT TO ENTRY
  275.     ADI    9    ;POINT TO SYS BYTE
  276.     MOV    L,A    ;SAVE (CAN'T CARRY TO H)
  277. ;
  278.     IF    SOPT
  279.     LDA    SOPFLG    ;DID USER REQUEST SYS FILES?
  280.     CPI    'S'
  281.     JZ    SYSFOK
  282.     ENDIF
  283. ;
  284.     MOV    A,M    ;GET SYS BYTE
  285.     ANI    80H    ;CHECK BIT 7
  286.     JNZ    MORDIR    ;SKIP THAT FILE
  287. ;
  288. SYSFOK:    MOV    A,L    ;GO BACK NOW
  289.     SUI    10    ;BACK TO USER NUMBER (ALLOC FLAG)
  290.     MOV    L,A    ;HL POINTS TO ENTRY NOW
  291. ;
  292.     LDA    USERNO    ;GET CURRENT USER
  293.     CMP    M
  294.     JNZ    MORDIR    ;IGNORE    IF DIFFERENT
  295.     INX    H
  296. ;
  297. ;Move entry to table
  298.     XCHG        ;ENTRY TO DE
  299.     LHLD    NEXTT    ;NEXT TABLE ENTRY TO HL
  300.     MVI    B,12    ;ENTRY LENGTH (NAME, TYPE, EXTENT)
  301. ;
  302. TMOVE:    LDAX    D    ;GET ENTRY CHAR
  303.     ANI    7FH    ;REMOVE    ATTRIBUTES
  304.     MOV    M,A    ;STORE IN TABLE
  305.     INX    D
  306.     INX    H
  307.     DCR    B    ;MORE?
  308.     JNZ    TMOVE
  309.     INX    D
  310.     INX    D    ;POINT TO SECTOR COUNT
  311.     LDAX    D    ; GET IT
  312.     MOV    M,A    ;STORE IN TABLE
  313.     INX    H
  314.     SHLD    NEXTT    ;SAVE UPDATED TABLE ADDR
  315.     XCHG
  316.     LHLD    COUNT    ;GET PREV COUNT
  317.     INX    H
  318.     SHLD    COUNT
  319.     LXI    H,13    ;SIZE OF NEXT ENTRY
  320.     DAD    D
  321.     XCHG        ;FUTURE    NEXTT IS IN DE
  322.     LHLD    BDOS+1    ;PICK UP TPA END
  323.     MOV    A,E
  324.     SUB    L    ;COMPARE NEXTT-TPA END
  325.     MOV    A,D
  326.     SBB    H
  327.     JC    MORDIR    ;IF TPA    END>NEXTT THEN LOOP BACK FOR MORE
  328. ;
  329. OUTMEM:    CALL    ERXIT
  330.     DB    'Out of    memory.',13,10,'$'
  331. ;
  332. ;Sort and print
  333. SPRINT:    LHLD    COUNT    ;GET FILE NAME COUNT
  334.     MOV    A,L
  335.     ORA    H    ;ANY FOUND?
  336.     JZ    NONE    ;NO, EXIT
  337.     PUSH    H    ;SAVE FILE COUNT
  338. ;Init the order    table
  339.     LHLD    TBLOC    ;GET START OF NAME TABLE
  340.     XCHG        ;INTO DE
  341.     LXI    H,ORDER    ;POINT TO ORDER    TABLE
  342.     LXI    B,13    ;ENTRY LENGTH
  343. ;
  344. BLDORD:    MOV    M,E    ;SAVE LO ORD ADDR
  345.     INX    H
  346.     MOV    M,D    ;SAVE HI ORD ADDR
  347.     INX    H
  348.     XCHG        ;TABLE ADDR TO HL
  349.     DAD    B    ;POINT TO NEXT ENTRY
  350.     XCHG
  351.     XTHL        ;SAVE TBL ADDR,    FETCH LOOP COUNTER
  352.     DCX    H    ;COUNT DOWN LOOP
  353.     MOV    A,L
  354.     ORA    H    ;MORE?
  355.     XTHL        ;(RESTORE TBL ADDR, SAVE COUNTER)
  356.     JNZ    BLDORD    ;..YES,    GO DO ANOTHER ONE
  357.     POP    H    ;CLEAN LOOP COUHTER OFF    STACK
  358.     LHLD    COUNT    ;GET COUNT
  359.     SHLD    SCOUNT    ;SAVE AS # TO SORT
  360.     DCX    H    ;ONLY 1    ENTRY?
  361.     MOV    A,L
  362.     ORA    H
  363.     JZ    DONE    ;..YES,    SO SKIP    SORT
  364. ;
  365. ; THIS SORT ROUTINE IS ADAPTED FROM SOFTWARE TOOLS
  366. ; BY KERNIGAN AND PLAUGHER.
  367. ;
  368. SORT:    LHLD    SCOUNT    ;NUMBER    OF ENTRIES
  369. L0:    ORA    A    ;CLEAR CARRY
  370.     MOV    A,H    ;GAP=GAP/2
  371.     RAR
  372.     MOV    H,A
  373.     MOV    A,L
  374.     RAR
  375.     MOV    L,A
  376.     ORA    H    ;IS IT ZERO?
  377.     JZ    DONE    ;THEN NONE LEFT
  378.     MOV    A,L    ;MAKE GAP ODD
  379.     ORI    01
  380.     MOV    L,A
  381.     SHLD    GAP
  382.     INX    H    ;I=GAP+1
  383. L2:    SHLD    I
  384.     XCHG
  385.     LHLD    GAP
  386.     MOV    A,E    ;J=I-GAP
  387.     SUB    L
  388.     MOV    L,A
  389.     MOV    A,D
  390.     SBB    H
  391.     MOV    H,A
  392. L3:    SHLD    J
  393.     XCHG
  394.     LHLD    GAP    ;JG=J+GAP
  395.     DAD    D
  396.     SHLD    JG
  397.     MVI    A,12    ;COMPARE 12 CHARS
  398.     CALL    COMPARE    ;COMPARE (J) AND (JG)
  399.     JP    L5    ;IF A(J)<=A(JG)
  400.     LHLD    J
  401.     XCHG
  402.     LHLD    JG
  403.     CALL    SWAP    ;EXCH A(J) AND A(JG)
  404.     LHLD    J    ;J=J-GAP
  405.     XCHG
  406.     LHLD    GAP
  407.     MOV    A,E
  408.     SUB    L
  409.     MOV    L,A
  410.     MOV    A,D
  411.     SBB    H
  412.     MOV    H,A
  413.     JM    L5    ;IF J>0    GOTO L3
  414.     ORA    L    ;CHECK FOR ZERO
  415.     JZ    L5
  416.     JMP    L3
  417. L5:    LHLD    SCOUNT    ;FOR LATER
  418.     XCHG
  419.     LHLD    I    ;I=I+1
  420.     INX    H
  421.     MOV    A,E    ;IF I<=N GOTO L2
  422.     SUB    L
  423.     MOV    A,D
  424.     SBB    H
  425.     JP    L2
  426.     LHLD    GAP
  427.     JMP    L0
  428. ;
  429. ;Sort is all done - print entries
  430. DONE:    LXI    H,ORDER
  431.     SHLD    NEXTT
  432. ;
  433. ;Print an entry
  434.     IF    NOT WIDE
  435.     CALL    DRPRNT    ;PRINT DRIVE NAME
  436.     ENDIF
  437.     MVI    C,NPL    ;NR. OF    NAMES PER LINE
  438.     LXI    H,0    ;ZERO OUT
  439.     SHLD    TOTSIZ    ; TOTAL    K USED
  440.     SHLD    TOTFIL    ; AND TOTAL FILES
  441. ;
  442. ENTRY:    LHLD    COUNT    ; CHECK    COUNT OF REMAINING FILES
  443.     DCX    H    ;  1 LEFT?
  444.     MOV    A,L    ; IF ONLY 1 LEFT, SKIP COMPARE WITH NEXT
  445.     ORA    H    ;  (SINCE THERE    ISN'T ANY NEXT)
  446.     JZ    OKPRNT
  447.     PUSH    B
  448.     MVI    C,0BH    ;CHECK CONSOLE STATUS
  449.     CALL    BDOS
  450.     ORA    A
  451.     JZ     NOBRK   ;NO, CONTINUE
  452.     JMP    EXIT
  453. ;
  454. NOBRK:    LHLD    NEXTT
  455.     MVI    A,11
  456.     CALL    COMPR    ;DOES THIS ENTRY MATCH NEXT ONE?
  457.     POP    B
  458.     JNZ    OKPRNT    ;NO, PRINT IT
  459.     INX    H
  460.     INX    H    ;SKIP, SINCE HIGHEST EXTENT COMES LAST IN LIST
  461.     SHLD    NEXTT
  462.     LHLD    COUNT
  463.     DCX    H
  464.     SHLD    COUNT    ;COUNT DOWN
  465.     JMP    ENTRY    ;GO GET    NEXT
  466. ;
  467. GOHL:    PCHL        ;KLUDGE    TO ALLOW CALL TO ADDRESS IN HL
  468. ;
  469. OKPRNT:    IF    NOT WIDE
  470.     CALL    FENCE    ;PRINT FENCE CHAR AND SPACE
  471.     ENDIF
  472.     LHLD    NEXTT    ;GET ORDER TABLE POINTER
  473.     MOV    E,M    ;GET LO    ADDR
  474.     INX    H
  475.     MOV    D,M    ;GET HI    ADDR
  476.     INX    H
  477.     SHLD    NEXTT    ;SAVE UPDATED TABLE POINTER
  478.     XCHG        ;TABLE ENTRY TO    HL
  479.     MVI    B,8    ;FILE NAME LENGTH
  480.     CALL    TYPEIT    ;TYPE FILENAME
  481.     MVI    A,' '    ;SPACE AFTER FN
  482.     CALL    TYPE
  483.     MVI    B,3    ;GET THE FILETYPE
  484.     CALL    TYPEIT
  485.     MOV    E,M    ;GET EXTENT #
  486.     MVI    D,0
  487.     INX    H
  488.     MOV    A,M    ;GET SECTOR COUNT OF LAST EXTENT
  489.     XCHG
  490.     DAD    H    ;# OF EXTENTS TIMES 16K
  491.     DAD    H
  492.     DAD    H
  493.     DAD    H
  494.     XCHG        ;SAVE IN DE
  495.     LXI    H,BLKMSK
  496.     ADD    M    ;ROUND LAST EXTENT TO BLOCK SIZE
  497.     RRC
  498.     RRC        ;CONVERT FROM SECTORS TO K
  499.     RRC
  500.     ANI    1FH
  501.     MOV    L,A    ;ADD TO    TOTAL K
  502.     MVI    H,0
  503.     DAD    D
  504.     LDA    BLKMSK    ;GET SECTORS/BLK-1
  505.     RRC
  506.     RRC        ;CONVERT TO K/BLK
  507.     RRC
  508.     ANI    1FH
  509.     CMA        ;USE TO    FINISH ROUNDING
  510.     ANA    L
  511.     MOV    L,A
  512.     XCHG        ;SAVE FILE SIZE    IN DE
  513.     LHLD    TOTSIZ
  514.     DAD    D    ;ADD TO    TOTAL USED
  515.     SHLD    TOTSIZ
  516.     LHLD    TOTFIL    ;INCREMENT FILE    COUNT
  517.     INX    H
  518.     SHLD    TOTFIL
  519.     XCHG        ;GET BACK FILE SIZE
  520.     CALL    DECPRT    ; AND PRINT IT
  521.     MVI    A,'k'    ;FOLLOW    WITH K
  522.     CALL    TYPE
  523. ;
  524.     IF    NOT WIDE
  525.     CALL    SPACE
  526.     ENDIF
  527. ;
  528. ;See if    more entries
  529.     LHLD    COUNT    ;COUNT DOWN ENTRIES
  530.     DCX    H
  531.     MOV    A,L
  532.     ORA    H
  533.     JZ    PRTOTL    ;IF OUT    OF FILES, PRINT    TOTALS
  534.     SHLD    COUNT
  535.     DCR    C    ;ONE LESS ON THIS LINE
  536. ;
  537.     IF    WIDE
  538.     PUSH    PSW
  539.     CNZ    FENCE    ;NO CR-LF NEEDED, DO FENCE
  540.     POP    PSW
  541.     ENDIF
  542. ;
  543.     CZ    CRLF    ;CR-LF NEEDED
  544.     JMP    ENTRY
  545. ;
  546. ;Print HL in decimal with leading zero suppression
  547. DECPRT:    SUB    A    ;CLEAR LEADING ZERO FLAG
  548.     STA    LZFLG
  549.     LXI    D,-1000    ;PRINT 1000'S DIGIT
  550.     CALL    DIGIT
  551.     LXI    D,-100    ;ETC
  552.     CALL    DIGIT
  553.     LXI    D,-10
  554.     CALL    DIGIT
  555.     MVI    A,'0'    ;GET 1'S DIGIT
  556.     ADD    L
  557.     JMP    TYPE
  558. ;
  559. DIGIT:    MVI    B,'0'    ;START OFF WITH    ASCII 0
  560. ;
  561. DIGLP:    PUSH    H    ;SAVE CURRENT REMAINDER
  562.     DAD    D    ;SUBTRACT
  563.     JNC    DIGEX    ;QUIT ON OVERFLOW
  564.     POP    PSW    ;THROW AWAY REMAINDER
  565.     INR    B    ;BUMP DIGIT
  566.     JMP    DIGLP    ;LOOP BACK
  567. ;
  568. DIGEX:    POP    H    ;RESTORE POINTER
  569.     MOV    A,B
  570.     CPI    '0'    ;ZERO DIGIT?
  571.     JNZ    DIGNZ    ;NO, TYPE IT
  572.     LDA    LZFLG    ;LEADING ZERO?
  573.     ORA    A
  574.     MVI    A,'0'
  575.     JNZ    TYPE    ;PRINT DIGIT
  576.     LDA    SUPSPC    ;GET SPACE SUPPRESSION FLAG
  577.     ORA    A    ;SEE IF    PRINTING FILE TOTALS
  578.     RZ        ;YES, DON'T GIVE LEADING SPACES
  579.     JMP    SPACE    ;LEADING ZERO...PRINT SPACE
  580. ;
  581. DIGNZ:    STA    LZFLG    ;SET LEADING ZERO FLAG SO NEXT ZERO PRINTS
  582.     JMP    TYPE    ;AND PRINT DIGIT
  583. ;
  584. ;Show total space and files used
  585. PRTOTL:    XRA    A    ;GET A ZERO TO...
  586.     STA    SUPSPC    ;SUPPRESS LEADING SPACES IN TOTALS
  587.     CALL    CRLF    ;NEW LINE (WITH    PAUSE IF NECESSARY)
  588. ;
  589.     IF    WIDE
  590.     LXI    D,TOTMS1 ;PRINT    FIRST PART OF TOTAL MESSAGE
  591.     ENDIF
  592. ;
  593.     IF    NOT WIDE
  594.     LXI    D,TOTMS1+1 ;PRINT FIRST    PART OF    TOTAL MESSAGE
  595.     ENDIF
  596. ;
  597.     MVI    C,PRINT
  598.     CALL    BDOS
  599.     LHLD    TOTSIZ    ;PRINT TOTAL K USED
  600.     CALL    DECPRT
  601.     LXI    D,TOTMS2;NEXT PART OF MESSAGE
  602.     MVI    C,PRINT
  603.     CALL    BDOS
  604.     LHLD    TOTFIL    ;PRINT COUNT OF    FILES
  605.     CALL    DECPRT
  606.     LXI    D,TOTMS3;TAIL OF MESSAGE
  607.     MVI    C,PRINT
  608.     CALL    BDOS
  609. PRT1:    MVI    C,GALLOC    ;GET ADDRESS OF    ALLOCATION VECTOR
  610.     CALL    BDOS
  611.     XCHG
  612.     LHLD    BLKMAX    ;GET ITS LENGTH
  613.     INX    H
  614.     LXI    B,0    ;INIT BLOCK COUNT TO 0
  615. ;
  616. GSPBYT:    PUSH    D    ;SAVE ALLOC ADDRESS
  617.     LDAX    D
  618.     MVI    E,8    ;SET TO    PROCESS    8 BLOCKS
  619. ;
  620. GSPLUP:    RAL        ;TEST BIT
  621.     JC    NOTFRE
  622.     INX    B
  623. ;
  624. NOTFRE:    MOV    D,A    ;SAVE BITS
  625.     DCX    H    ;COUNT DOWN BLOCKS
  626.     MOV    A,L
  627.     ORA    H
  628.     JZ    ENDALC    ;QUIT IF OUT OF    BLOCKS
  629.     MOV    A,D    ;RESTORE BITS
  630.     DCR    E    ;COUNT DOWN 8 BITS
  631.     JNZ    GSPLUP    ;DO ANOTHER BIT
  632.     POP    D    ;BUMP TO NEXT BYTE
  633.     INX    D    ;OF ALLOC. VECTOR
  634.     JMP    GSPBYT    ;PROCESS IT
  635. ;
  636. ENDALC:    MOV    L,C    ;COPY BLOCKS TO    HL
  637.     MOV    H,B
  638.     LDA    BLKSHF    ;GET BLOCK SHIFT FACTOR
  639.     SUI    3    ;CONVERT FROM SECTORS TO K
  640.     JZ    PRTFRE    ;SKIP SHIFTS IF    1K BLOCKS
  641. ;
  642. FREKLP:    DAD    H    ;MULT BLKS BY K/BLK
  643.     DCR    A
  644.     JNZ    FREKLP
  645. ;
  646. PRTFRE:    CALL    DECPRT    ;PRINT K FREE
  647.     LXI    D,TOTMS4
  648.     MVI    C,PRINT
  649.     CALL    BDOS
  650.     JMP    EXIT    ;ALL DONE...RETURN TO CP/M
  651. ;
  652. DRNAM    EQU    $    ;SAVE DRIVE NAME HERE
  653. TOTMS1:    DB    ' : Total of $'
  654. TOTMS2: DB    'k in $'
  655. TOTMS3: DB    ' files with $'
  656. TOTMS4: DB    'k space remaining.$'
  657. ;
  658. FENCE:    IF    WIDE
  659.     CALL    SPACE
  660.     ENDIF
  661.     MVI    A,DELIM    ;FENCE CHARACTER
  662.     CALL    TYPE    ;PRINT IT, FALL    INTO SPACE
  663. ;
  664. SPACE:    MVI    A,' '
  665. ;
  666. ;Type character    in A
  667. TYPE:    PUSH    B
  668.     PUSH    D
  669.     PUSH    H
  670.     MOV    E,A
  671.     MVI    C,2        ;BDOS CONOUT
  672.     CALL    BDOS
  673.     POP    H
  674.     POP    D
  675.     POP    B
  676.     RET
  677. ;
  678. TYPEIT:    MOV    A,M
  679.     CALL    TYPE
  680.     INX    H
  681.     DCR    B
  682.     JNZ    TYPEIT
  683.     RET
  684. ;
  685. ;Fetch character from console (without echo)
  686. CINPUT:    LHLD    BASE+1
  687.     MVI    L,9
  688.     CALL    GOHL
  689.     ANI    7FH
  690.     RET
  691. ;
  692. CRLF:    LDA    LINCNT    ;CHECK FOR END OF SCREEN
  693.     INR    A
  694.     CPI    LPS
  695.     JC    NOTEOS    ;SKIP MESSAGE IF MORE LINES LEFT ON SCREEN
  696.     LXI    D,EOSMSG;SAY WE'RE PAUSING FOR INPUT
  697.     MVI    C,PRINT
  698.     CALL    BDOS
  699.     CALL    CINPUT    ;WAIT FOR CHAR.
  700.     SUB    A    ;SET UP    TO ZERO    LINE COUNT
  701. ;
  702. NOTEOS:    STA    LINCNT    ;SAVE NEW LINE COUNT
  703.     MVI    A,13    ;PRINT CR
  704.     CALL    TYPE
  705.     MVI    A,10    ;LF
  706.     CALL    TYPE
  707. ;
  708.     IF    NOT WIDE
  709.     CALL    DRPRNT    ;DRIVE NAME
  710.     ENDIF
  711. ;
  712.     MVI    C,NPL    ;RESET NUMBER OF NAMES PER LINE
  713.     RET
  714. ;
  715. EOSMSG:    DB    13,10,'(Strike any key to continue)$'
  716. ;
  717.     IF    NOT WIDE
  718. DRPRNT:    LDA    DRNAM
  719.     JMP    TYPE
  720.     ENDIF
  721. ;
  722. ;Compare routine for sort
  723. COMPR:    PUSH    H    ;SAVE TABLE ADDR
  724.     MOV    E,M    ;LOAD LO
  725.     INX    H
  726.     MOV    D,M    ;LOAD HI
  727.     INX    H
  728.     MOV    C,M
  729.     INX    H
  730.     MOV    B,M
  731. ;BC, DE    now point to entries to    be compared
  732.     XCHG
  733.     MOV    E,A    ;GET COUNT
  734. ;
  735. CMPLP:    LDAX    B
  736.     CMP    M
  737.     INX    H
  738.     INX    B
  739.     JNZ    NOTEQL    ;QUIT ON MISMATCH
  740.     DCR    E    ;OR END    OF COUNT
  741.     JNZ    CMPLP
  742. ;
  743. NOTEQL:    POP    H
  744.     RET        ;COND CODE TELLS ALL
  745. ;
  746. ;Swap entries in the order table
  747. SWAP:    LXI    B,ORDER-2    ;TABLE BASE
  748.     DAD    H    ;*2
  749.     DAD    B    ;+ BASE
  750.     XCHG
  751.     DAD    H    ;*2
  752.     DAD    B    ;+ BASE
  753.     MOV    C,M
  754.     LDAX    D
  755.     XCHG
  756.     MOV    M,C
  757.     STAX    D
  758.     INX    H
  759.     INX    D
  760.     MOV    C,M
  761.     LDAX    D
  762.     XCHG
  763.     MOV    M,C
  764.     STAX    D
  765.     RET
  766. ;
  767. ;
  768. ; NEW COMPARE ROUTINE
  769. ;
  770. COMPARE:    LXI    B,ORDER-2
  771.     DAD    H
  772.     DAD    B
  773.     XCHG
  774.     DAD    H
  775.     DAD    B
  776.     XCHG
  777.     MOV    C,M
  778.     INX    H
  779.     MOV    B,M
  780.     XCHG
  781.     MOV    E,M
  782.     INX    H
  783.     MOV    D,M
  784.     XCHG
  785.     MOV    E,A    ;COUNT
  786. CMPLPE:    LDAX    B
  787.     CMP    M
  788.     INX    B
  789.     INX    H
  790.     RNZ
  791.     DCR    E
  792.     JNZ    CMPLPE
  793.     RET
  794. ;
  795. ;Error exit
  796. ERXIT:    POP    D    ;GET MSG
  797. ;
  798. ERXIT1:    MVI    C,PRINT
  799. ;
  800. CALLB:    CALL    BDOS    ;PERFORM REQUESTED FUNCTION
  801.     CALL    CRLF
  802.     LXI    D,TOTMS1
  803.     MVI    C,PRINT
  804.     CALL    BDOS
  805.     XRA    A
  806.     STA    SUPSPC    ;SUPPRESS LEADING ZEROS
  807.     JMP    PRT1    ;PRINT SPACE REMAINING
  808. ;
  809. ;(fall into exit)
  810. ;Exit -    all done, restore stack
  811. EXIT:    LHLD    STACK    ;GET OLD STACK
  812.     SPHL        ;MOVE TO STACK
  813.     RET        ;..AND RETURN
  814. ;
  815. ;Temporary storage area
  816. ;
  817. I    DW    0
  818. J    DW    0
  819. JG    DW    0
  820. GAP    DW    0
  821. ;
  822. BLKSHF    DB    0    ;# SHIFTS TO MULT BY SEC/BLK
  823. BLKMSK    DB    0    ;SEC/BLK - 1
  824. BLKMAX    DW    0    ;HIGHEST BLOCK # ON DRIVE
  825. DIRMAX    DW    0    ;HIGHEST FILE #    IN DIRECTORY
  826. TOTSIZ    DW    0    ;TOTAL SIZE OF ALL FILES
  827. TOTFIL    DW    0    ;TOTAL NUMBER OF FILES
  828. LINCNT    DB    0    ;COUNT OF LINES    ON SCREEN
  829. TBLOC    DW    0    ;POINTER TO START OF NAME TABLE
  830. NEXTT    DW    0    ;NEXT TABLE ENTRY
  831. COUNT    DW    0    ;ENTRY COUNT
  832. SCOUNT    DW    0    ;# TO SORT
  833. SWITCH    DB    0    ;SWAP SWITCH FOR SORT
  834. SUPSPC    DB    0FFH    ;LEADING SPACE FLAG FOR    DECIMAL    RTN.
  835. BUFAD    DW    BASE+80H ;OUTPUT ADDR
  836.     DS    60    ;STACK AREA
  837. STACK    DS    2    ;SAVE OLD STACK    HERE
  838. SOPFLG    DS    1    ;SET TO    'S' TO ALLOW SYS FILES TO PRINT
  839. USERNO    DS    1    ;CONTAINS CURRENT USER NUMBER
  840. TEMP    DS    2    ;SAVE DIR ENTRY
  841. VERFLG    DS    1    ;VERSION FLAG
  842. MPMFLG    DS    1    ;MP/M FLAG
  843. LZFLG    DS    1    ;0 WHEN    PRINTING LEADING ZEROS
  844. ORDER    EQU    $    ;ORDER TABLE STARTS HERE
  845. ;
  846. ;BDOS equates
  847. ;
  848. RDCHR    EQU    1    ;READ CHAR FROM    CONSOLE
  849. WRCHR    EQU    2    ;WRITE CHR TO CONSOLE
  850. PRINT    EQU    9    ;PRINT CONSOLE BUFF
  851. CONST    EQU    11    ;CHECK CONS STAT
  852. SELDSK    EQU    14    ;SELECT    DISK
  853. FOPEN    EQU    15    ;0FFH=NOT FOUND
  854. FCLOSE    EQU    16    ;   "    "
  855. FSRCHF    EQU    17    ;   "    "
  856. FSRCHN    EQU    18    ;   "    "
  857. CURDSK    EQU    25    ;GET CURRENTLY LOGGED DISK NAME
  858. GALLOC    EQU    27    ;GET ADDRESS OF    ALLOCATION VECTOR
  859. CURDPB    EQU    31    ;GET CURRENT DISK PARAMETERS
  860. CURUSR    EQU    32    ;GET CURRENTLY LOGGED USER NUMBER (2.x ONLY)
  861. ;
  862.     END
  863.