home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol009 / sd-12-15.asm < prev    next >
Assembly Source File  |  1984-04-29  |  17KB  |  782 lines

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