home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / dirutl / sdd102.lbr / SDD.AQM / SDD.ASM
Encoding:
Assembly Source File  |  1985-08-07  |  19.4 KB  |  997 lines

  1. ; SDD - Super Duper Directory program
  2. ; Version 1.02 by "ESKAY"
  3. ;
  4. ; NOTE:
  5. ;    This program is not meant to be competition for the SDxxx
  6. ;    series.  Rather, it is intended to be what SD was before it
  7. ;    got out of hand --- a small, fast directory display program
  8. ;    for everyone using CP/M.
  9. ;    I have decided to write this program in such a way that
  10. ;    anyone with MAC (maybe even ASM -- I don't know) can modify,
  11. ;    edit and reassemble it.  The code is very well commented
  12. ;    except for some "canned" routines out of my software library.
  13. ;
  14. ; A WORD AS TO CODE SIZE...
  15. ;    One of SD's original authors mentioned the fact that it was
  16. ;    meant to be less than 2k (look where it's now...), so SDD will
  17. ;    be kept below 2k and will be coded to have only a minimum
  18. ;    of "frills". If you in any way modify this program, PLEASE
  19. ;    keep the code size below 2k.
  20. ;    In a CP/M environment, SDD will always preserve the resident
  21. ;    CCP by returning to the caller's stacked return address.
  22. ;    Users of large CP/M directories should not be concerned about
  23. ;    overflowing the TPA; even in a small 32k TPA, over 3000
  24. ;    file names can be processed.
  25. ;
  26. ;    +------------------+
  27. ;    | REVISION HISTORY |
  28. ;    +------------------+
  29. ;
  30. ; 07/28/85 v1.00 Created (Big Bang)
  31. ; 08/03/85 v1.01 Sent out into the world to conquer...
  32. ; 08/04/85 V1.02 Added check for option only (as in SDD $K)
  33. ;
  34. ;    +-----------------+
  35. ;    | GENERAL EQUATES |
  36. ;    +-----------------+
  37. ;
  38. CR    EQU    0DH
  39. LF    EQU    0AH
  40. ODELIM    EQU    '$'            ; option delimiter
  41. COLS    EQU    4            ; number of columns per screen
  42. ROWS    EQU    24            ; number of lines per screen
  43. ;
  44. ;    +--------------------------+
  45. ;    | OPERATING SYSTEM EQUATES |
  46. ;    +--------------------------+
  47. ;
  48.     ORG    100H
  49. ;
  50. BDOS    EQU    5            ; function entry point
  51. DFCB    EQU    5CH            ; default FCB
  52. DBUF    EQU    80H            ; default buffer
  53. ;
  54. COUT    EQU    2            ; console output
  55. LOUT    EQU    5            ; list output
  56. DCIO    EQU    6            ; direct console IO
  57. PSTR    EQU    9            ; print string
  58. VERSN    EQU    12            ; version number
  59. SELDK    EQU    14            ; select disk
  60. SEARF    EQU    17            ; search for first
  61. SEARN    EQU    18            ; search for next
  62. CURDK    EQU    25            ; return current disk
  63. GETDPB    EQU    31            ; get disk parameter block
  64. GSUSR    EQU    32            ; get/set user number
  65. FSIZE    EQU    35            ; compute file size
  66. ;
  67. ;    +----------------------+
  68. ;    | START OF THE PROGRAM |
  69. ;    +----------------------+
  70. ;
  71. SDD:    LXI    H,0            ; clear HL
  72.     DAD    SP            ; get stack pointer
  73.     SHLD    STKSAV            ; save it
  74.     LXI    SP,STACK        ; set up new stack pointer
  75.     CALL    INIT            ; initialize
  76.     CALL    PREPFN            ; prepare optional filename
  77.     CALL    SETOPT            ; set options
  78.     CALL    LODBUF            ; load buffer with directory data
  79.     CALL    SORTBF            ; sort the buffer
  80.     CALL    DSPBUF            ; display the buffer
  81.     CALL    DSPSTA            ; display statistics
  82. QUIT:    LHLD    STKSAV            ; get caller stack back
  83.     SPHL                ; set up entry stack
  84.     RET                ; and return to caller
  85. ;
  86. ;    +--------------------+
  87. ;    | INITIALIZE PROGRAM |
  88. ;    +--------------------+
  89. ;
  90. INIT:    MVI    A,0FFH
  91.     STA    BUFFER
  92.     MVI    C,CURDK            ; get current drive
  93.     CALL    BDOS
  94.     STA    CDRIV            ; save it
  95.     MVI    C,GSUSR            ; get current user
  96.     MVI    E,0FFH
  97.     CALL    BDOS
  98.     STA    CUSER            ; save it
  99.     MVI    C,VERSN            ; get CP/M version
  100.     CALL    BDOS
  101.     MOV    A,H            ; get MP/M flag
  102.     ORA    A            ; test for MP/M
  103.     MOV    A,L            ; get BDOS version
  104.     JZ    NMPM            ; skip if not MP/M
  105.     MVI    A,30H            ; set flag
  106. NMPM:    STA    CPMV            ; store CP/M version
  107.     RET                ; and return
  108. ;
  109. ;    +---------------------------------+
  110. ;    | PREPARE INPUT FILENAME FOR SCAN |
  111. ;    +---------------------------------+
  112. ;
  113. PREPFN:    MVI    A,0FFH            ; Set default disk and user
  114.     STA    DISK
  115.     STA    USER
  116.     LXI    H,DBUF            ; point to command line
  117.     MOV    A,M            ; get length
  118.     INX    H            ; point to first char of cl
  119.     SHLD    TEMP1            ; save cl pointer
  120.     ORA    A            ; anything typed at all?
  121.     JZ    NTYPD            ; nothing typed
  122. SKLB:    MOV    A,M            ; get char
  123.     CPI    ' '            ; blank?
  124.     JNZ    NBL            ;   no
  125.     INX    H
  126.     JMP    SKLB
  127. ;
  128. NBL:    LXI    D,DFCB            ; point to default fcb
  129.     CALL    FNAME            ; parse the file name
  130.     MVI    A,1            ; set error code
  131.     JZ    ERROR
  132.     LDA    DFCB+1            ; check for empty fn
  133.     CPI    '$'            ; option only?
  134.     JZ    NTYPD            ;   yes (ignore rare case of fn with $)
  135.     SHLD    TEMP1            ; save cl pointer
  136.     CPI    ' '            ; blank?
  137.     RNZ                ;   no, all ok
  138. NTYPD:    LXI    H,DFCB+1        ; fill with "?"
  139.     MVI    B,11
  140. MKWLD:    MVI    M,'?'
  141.     INX    H
  142.     DCR    B
  143.     JNZ    MKWLD
  144.     RET
  145. ;
  146. ;    +---------------------+
  147. ;    | GET AND SET OPTIONS |
  148. ;    +---------------------+
  149. ;
  150. SETOPT:    LHLD    TEMP1            ; get cl pointer
  151.     MVI    B,ODELIM        ; get delimiter
  152. SRHOPT:    MOV    A,M            ; get byte
  153.     INX    H
  154.     ORA    A            ; end of line?
  155.     RZ                ;   yes, return
  156.     CMP    B            ; delimiter?
  157.     JZ    FNDDEL            ;   yes
  158.     JMP    SRHOPT
  159. ;
  160. FNDDEL:    LXI    D,OPTNS            ; DE points to options list
  161. GNOPT:    LDAX    D            ; get an option
  162.     CPI    0FFH            ; all options checked?
  163.     JZ    NXTBOP            ;   yes, check next byte
  164.     CMP    M            ; match?
  165.     JZ    GOPTN            ;   yes
  166.     INX    D            ; get next option
  167.     JMP    GNOPT
  168. ;
  169. GOPTN:    XRA    A            ; else mark that option
  170.     STAX    D
  171. NXTBOP:    MOV    A,M            ; get byte
  172.     ORA    A            ; end of line?
  173.     RZ                ;   yes
  174.     INX    H
  175.     JMP    FNDDEL            ; go check next byte
  176. ;
  177. ;    +-----------------------------+
  178. ;    | LOAD BUFFER WITH FILE NAMES |
  179. ;    +-----------------------------+
  180. ;
  181. LODBUF:    LDA    DISK            ; get target drive
  182.     DCR    A            ; make 0..15
  183.     JM    SAMEDR            ; skip if same drive
  184.     MOV    E,A
  185.     MVI    C,SELDK
  186.     CALL    BDOS
  187. ;
  188. ; WHILE WE'RE AT IT, GET DPB
  189. ;
  190. SAMEDR:    MVI    C,GETDPB
  191.     CALL    BDOS
  192.     INX    H
  193.     INX    H
  194.     MOV    A,M            ; get BSH
  195.     STA    BLSHFT
  196.     INX    H
  197.     MOV    A,M            ; get BLM
  198.     STA    BLMASK
  199.     INX    H
  200.     INX    H
  201.     MOV    E,M
  202.     INX    H
  203.     MOV    D,M
  204.     XCHG
  205.     SHLD    NUMBLK            ; store disk size
  206.     XCHG
  207.     INX    H
  208.     MOV    E,M
  209.     INX    H
  210.     MOV    D,M
  211.     XCHG
  212.     SHLD    DIRSZ            ; store directory size
  213.     LDA    USER            ; get target user
  214.     MOV    E,A
  215.     INR    A
  216.     JZ    SAMEUS            ; skip if no change
  217.     MVI    C,GSUSR
  218.     CALL    BDOS
  219. SAMEUS:    LXI    D,DFCB            ; point to filename
  220.     MVI    C,SEARF            ; search for first
  221.     CALL    BDOS
  222.     CPI    0FFH            ; if first fails, then no file
  223.     JNZ    FRSTOK            ;   else ok
  224.     MVI    A,2            ; error code
  225.     JMP    ERROR
  226. ;
  227. FRSTOK:    CALL    MOVEFN            ; move filename
  228.     LXI    D,DFCB            ; point to filename
  229.     MVI    C,SEARN            ; search for next
  230.     CALL    BDOS
  231.     CPI    0FFH
  232.     RZ                ; done!
  233.     JMP    FRSTOK            ; else loop
  234. ;
  235. MOVEFN:    LXI    H,DBUF
  236.     LXI    D,20H
  237. CPL:    DCR    A
  238.     JM    CPLE
  239.     DAD    D
  240.     JMP    CPL
  241. ;
  242. CPLE:    PUSH    H
  243.     MVI    B,12
  244. SHBL:    MOV    A,M
  245.     ANI    7FH
  246.     MOV    M,A
  247.     INX    H
  248.     DCR    B
  249.     JNZ    SHBL
  250.     POP    D            ; get filename ptr
  251.     LHLD    BUFPTR            ; get buffer ptr
  252.     MOV    A,M            ; get a byte
  253.     LXI    H,BUFFER
  254. SRHBFL:    CPI    0FFH            ; end of buffer?
  255.     JZ    MOVNOW            ;   yes
  256.     CALL    CPDEHL            ; duplicate?
  257.     RZ                ;   yes, go get next
  258.     LXI    B,12            ; advance ptr
  259.     DAD    B
  260.     MOV    A,M
  261.     JMP    SRHBFL
  262. ;
  263. MOVNOW:    LHLD    BUFPTR
  264.     MVI    B,12
  265. MOVLP:    LDAX    D
  266.     MOV    M,A
  267.     INX    D
  268.     INX    H
  269.     DCR    B
  270.     JNZ    MOVLP
  271.     SHLD    BUFPTR
  272.     MVI    M,0FFH
  273.     LHLD    NMBFLS
  274.     INX    H
  275.     SHLD    NMBFLS
  276.     RET
  277. ;
  278. ;    +-----------------------+
  279. ;    | SORT FILE NAME BUFFER |
  280. ;    +-----------------------+
  281. ;
  282. SORTBF:    LDA    SOPT            ; sort off?
  283.     ORA    A
  284.     RZ                ; do not sort
  285.     LHLD    NMBFLS            ; get number of files
  286.     MOV    B,H            ;   into BC
  287.     MOV    C,L
  288.     LXI    D,12            ; 12 characters per field
  289.     LXI    H,BUFFER        ; point to buffer
  290. ;
  291. ; SHELL-METZNER SORT
  292. ; Call with the following information:
  293. ;
  294. ; BC  =  Number of records to be sorted
  295. ; DE  =  Record length
  296. ; HL  =  Buffer address
  297. ;
  298. SORT:    SHLD    SSTADR
  299.     PUSH    H
  300.     XCHG
  301.     SHLD    SRECLEN
  302.     PUSH    H
  303.     MOV    H,B
  304.     MOV    L,C
  305.     SHLD    SNUMRT
  306.     SHLD    SNUMRW
  307. ;
  308. ; NOW DIVIDE # OF FIELDS BY 2
  309. ;
  310. DIVIDE:    LHLD    SNUMRW            ; GET VALUE
  311.     CALL    DIVBY2            ; DIVIDE BY 2
  312.     SHLD    SNUMRW            ;SAVE RESULT
  313.     MOV    A,L            ;IF SNUMRW<>0
  314.     ORA    H            ;  THEN
  315.     JNZ    NOTDONE            ;    NOT DONE
  316. ;
  317. ; ALL FIELDS SORTED
  318. ;
  319.     POP    B            ;CLEAN UP STACK
  320.     POP    D
  321.     RET
  322. ;
  323. NOTDONE:XCHG
  324.     LHLD    SNUMRT
  325.     MOV    A,L
  326.     SUB    E
  327.     MOV    L,A
  328.     MOV    A,H
  329.     SBB    D
  330.     MOV    H,A
  331.     SHLD    SRECLEN
  332.     LXI    H,1
  333.     SHLD    SORTV1
  334.     SHLD    SSTADR
  335.     DCR    L
  336.     POP    B
  337.     PUSH    B
  338. NDONE1:    DAD    D
  339.     DCX    B
  340.     MOV    A,B
  341.     ORA    C
  342.     JNZ    NDONE1
  343.     SHLD    SORTV2
  344.     XCHG
  345.     POP    B
  346.     POP    H
  347.     PUSH    H
  348.     PUSH    B
  349. NDONE2:    SHLD    SORTV4
  350.     SHLD    SORTV3
  351.     XCHG
  352.     DAD    D
  353.     XCHG
  354. COMPRE:    POP    B
  355.     PUSH    B
  356. COMPR1:    LDAX    D
  357.     SUB    M
  358.     JNZ    NOTEQU
  359.     INX    H
  360.     INX    D
  361.     DCX    B
  362.     MOV    A,B
  363.     ORA    C
  364.     JNZ    COMPR1
  365.     JMP    NOSWITCH
  366. ;
  367. NOTEQU:    JNC    NOSWITCH
  368. SWITCH:    PUSH    B
  369.     MOV    B,M
  370.     LDAX    D
  371.     MOV    M,A
  372.     MOV    A,B
  373.     STAX    D
  374.     INX    H
  375.     INX    D
  376.     POP    B
  377.     DCX    B
  378.     MOV    A,B
  379.     ORA    C
  380.     JNZ    SWITCH
  381.     LHLD    SNUMRW
  382.     MOV    A,H
  383.     CMA
  384.     MOV    D,A
  385.     MOV    A,L
  386.     CMA
  387.     MOV    E,A
  388.     LHLD    SORTV1
  389.     DAD    D
  390.     JNC    NOSWITCH
  391.     INX    H
  392.     SHLD    SORTV1
  393.     LHLD    SORTV3
  394.     XCHG
  395.     LHLD    SORTV2
  396.     MOV    A,E
  397.     SUB    L
  398.     MOV    L,A
  399.     MOV    A,D
  400.     SBB    H
  401.     MOV    H,A
  402.     SHLD    SORTV3
  403.     JMP    COMPRE
  404. ;
  405. NOSWITCH:
  406.     LHLD    SSTADR
  407.     INX    H
  408.     SHLD    SSTADR
  409.     SHLD    SORTV1
  410.     XCHG
  411.     LHLD    SRECLEN
  412.     MOV    A,L
  413.     SUB    E
  414.     MOV    A,H
  415.     SBB    D
  416.     JC    DIVIDE
  417.     LHLD    SORTV4
  418.     POP    D
  419.     PUSH    D
  420.     DAD    D
  421.     XCHG
  422.     LHLD    SORTV2
  423.     XCHG
  424.     JMP    NDONE2
  425. ;
  426. ; UTILITY SUBTRACTION SUBROUTINE...
  427. ; HL=HL-DE
  428. ;
  429. SUBDE:    MOV    A,L
  430.     SUB    E
  431.     MOV    L,A
  432.     MOV    A,H
  433.     SBB    D
  434.     MOV    H,A
  435.     RET
  436. ;
  437. ;    +-------------------------+
  438. ;    | DISPLAY BUFFER CONTENTS |
  439. ;    +-------------------------+
  440. ;
  441. DSPBUF:    CALL    CRLF            ; new line
  442.     LXI    H,BUFFER        ; load buffer ptr
  443.     SHLD    BUFPTR
  444. DSPBL1:    MVI    A,ROWS-1        ; get lines/page
  445.     STA    CURROW            ; save it
  446. DSPBL2:    MVI    A,COLS            ; get number of columns
  447.     STA    CURCOL            ; save it
  448. DSPBLP:    LHLD    BUFPTR            ; get buffer pointer
  449.     MOV    A,M            ; get byte
  450.     CPI    0FFH            ; end of buffer?
  451.     RZ                ;   yes, return
  452.     CALL    PUTFN            ; display filename
  453.     SHLD    BUFPTR            ; save advanced pointer
  454.     CALL    DSPSZ            ; display size
  455.     LDA    CURCOL            ; get column
  456.     DCR    A            ; count down
  457.     STA    CURCOL
  458.     JNZ    DSPBLP            ; loop till done
  459.     CALL    CRLF            ; new line
  460.     LDA    LOPT            ; check if print
  461.     ORA    A
  462.     JZ    DSPBL2            ; yes, no paging
  463.     LDA    CURROW
  464.     DCR    A
  465.     STA    CURROW
  466.     JNZ    DSPBL2            ; keep on looping
  467.     CALL    CONTLP            ;   else get a character (any)
  468.     JMP    DSPBL1
  469. ;
  470. PUTFN:    INX    H
  471.     MVI    B,8            ; display file name
  472.     CALL    PUTFC
  473.     MVI    A,'.'
  474.     CALL    PUTCH
  475.     MVI    B,3
  476. PUTFC:    MOV    A,M
  477.     CALL    PUTCH
  478.     INX    H
  479.     DCR    B
  480.     JNZ    PUTFC
  481.     RET
  482. ;
  483. DSPSZ:    LDA    KOPT            ; check size option
  484.     ORA    A            ; display without size?
  485.     JZ    NOSIZE            ;   yes, go display blanks
  486.     LHLD    BUFPTR            ; point to next filename
  487.     LXI    D,-12            ; set up this filename's addr
  488.     DAD    D
  489.     LXI    D,DFCB            ; destination = default FCB
  490.     MVI    B,12            ; 12 chars to move
  491. MVFNSZ:    MOV    A,M
  492.     STAX    D
  493.     INX    H
  494.     INX    D
  495.     DCR    B
  496.     JNZ    MVFNSZ            ; loop till all moved
  497.     LXI    H,DFCB            ; point to FCB
  498.     MVI    M,0            ; zero drive byte
  499.     XCHG                ; get FCB to DE
  500.     MVI    C,FSIZE            ; get file size
  501.     CALL    BDOS
  502.     LHLD    DFCB+33            ; get sector count
  503.     CALL    SECTOK            ; translate into 'k'
  504.     XCHG                ; move out of the way
  505.     LHLD    CUMSIZ            ; get cumulative file size
  506.     DAD    D            ; add this file
  507.     SHLD    CUMSIZ            ; save it
  508.     XCHG                ; get this size back to HL
  509.     CALL    HEXDC1            ; convert to decimal
  510.     MVI    A,'k'            ; print 'k'
  511.     CALL    PUTCH
  512.     MVI    B,2
  513.     JMP    DSPBNK
  514. ;
  515. NOSIZE:    MVI    B,7            ; number of blanks
  516. DSPBNK:    MVI    A,' '            ; a blank
  517.     CALL    PUTCH            ; print it
  518.     DCR    B            ; countdown
  519.     JNZ    DSPBNK            ; do more
  520.     MVI    C,DCIO            ; see if something typed
  521.     MVI    E,0FFH
  522.     CALL    BDOS
  523.     CPI    3            ; a ^C?
  524.     JZ    EXIT            ;   yep, quit!
  525.     CPI    'S'-40H            ; A ^S?
  526.     RNZ                ;   no, return
  527. ;
  528. ; wait for character
  529. ;
  530. CONTLP:    MVI    C,DCIO            ; wait for any char
  531.     MVI    E,0FFH
  532.     CALL    BDOS
  533.     ORA    A            ; anything typed?
  534.     JZ    CONTLP            ;   no, wait more
  535.     CPI    3            ; abort now?
  536.     RNZ                ;   no
  537.     JMP    EXIT
  538. ;
  539. SECTOK:    LDA    BLMASK            ; get block mask
  540.     MOV    E,A            ; set up DE...
  541.     MVI    D,0
  542.     DAD    D            ; ..to add to HL
  543.     CMA
  544.     ANA    L
  545.     MOV    L,A            ; round off
  546.     CALL    DIVBY2            ; SEC/2
  547.     CALL    DIVBY2            ; SEC/4
  548.     JMP    DIVBY2            ; SEC/8 (K)
  549. ;
  550. ;    +--------------------+
  551. ;    | DISPLAY STATISTICS |
  552. ;    +--------------------+
  553. ;
  554. DSPSTA:    LDA    CURCOL            ; see if at end of line
  555.     CPI    4
  556.     CNZ    CRLF            ; new line if not
  557.     LDA    KOPT            ; any sizes wanted?
  558.     ORA    A
  559.     RZ                ; no, return
  560.     LHLD    NMBFLS            ; see if no files
  561.     MOV    A,H
  562.     ORA    L
  563.     RZ                ; no files, no message
  564.     LXI    D,SUMM1            ; send message
  565.     CALL    PRINTM
  566.     MVI    C,CURDK
  567.     CALL    BDOS
  568.     ADI    'A'
  569.     CALL    PUTCH            ; print drive
  570.     MVI    C,GSUSR
  571.     MVI    E,0FFH
  572.     CALL    BDOS            ; get user
  573.     MOV    L,A
  574.     MVI    H,0
  575.     CALL    HEXDC2            ; print user
  576.     LXI    D,SUMM2
  577.     CALL    PRINTM
  578.     LHLD    NMBFLS            ; get number of files
  579.     CALL    HEXDC1
  580.     LXI    D,SUMM3
  581.     CALL    PRINTM
  582.     LHLD    CUMSIZ            ; get cumulative size
  583.     CALL    HEXDEC
  584.     LXI    D,SUMM4
  585.     JMP    PRINTM
  586. ;
  587. ;    +-------------+
  588. ;    | SUBROUTINES |
  589. ;    +-------------+
  590. ;
  591. ;    +-----------------------------+
  592. ;    | CARRIAGE RETURN / LINE FEED |
  593. ;    +-----------------------------+
  594. ;
  595. CRLF:    MVI    A,CR
  596.     CALL    PUTCH
  597.     MVI    A,LF
  598. ;
  599. ;    +----------------------+
  600. ;    | PRINT CHARACTER IN A |
  601. ;    +----------------------+
  602. ;
  603. PUTCH:    PUSH    PSW
  604.     PUSH    B            ; save registers
  605.     PUSH    D
  606.     PUSH    H
  607.     MOV    E,A            ; character to E
  608.     MVI    C,COUT            ; preload console out
  609.     LDA    LOPT            ; test if list out
  610.     ORA    A
  611.     JNZ    PCH            ; not list out - skip
  612.     MVI    C,LOUT            ; load list out
  613. PCH:    CALL    BDOS            ; do it
  614.     POP    H
  615.     POP    D
  616.     POP    B
  617.     POP    PSW
  618.     RET
  619. ;
  620. ;    THE FOLLOWING ROUTINE WAS WRITTEN BY RICHARD L CONN
  621. ;
  622. MAXDISK    EQU    16        ; Maximum number of disks
  623. MAXUSER    EQU    31        ; Maximum user number
  624. ;
  625. ;    ON ENTRY, DE PTS TO FCB TO BE FILLED AND HL PTS TO FIRST BYTE OF
  626. ;        TARGET STRING; FCB IS 36 BYTES LONG
  627. ;    ON EXIT, B=DISK NUMBER (1 FOR A, ETC) AND C=USER NUMBER
  628. ;        HL PTS TO TERMINATING CHAR
  629. ;        A=0 AND Z SET IF ERROR IN DISK OR USER NUMBERS,
  630. ;        A=0FFH AND NZ
  631. ;    IF OK
  632. ;
  633. FNAME:    PUSH    D        ; Save de
  634.     MVI    B,36        ; Initialize fcb
  635.     PUSH    D        ; Save pointer
  636.     XRA    A        ; A=0
  637. ;
  638. FNINI:    STAX    D        ; Store zero
  639.     INX    D        ; Point to next
  640.     DCR    B        ; Count down
  641.     JNZ    FNINI
  642.     POP    D        ; Get pointer back
  643. ;
  644. ; Scan for colon in string
  645. ;
  646.     PUSH    H        ; Save pointer
  647. ;
  648. COLON:    MOV    A,M        ; Scan fora colon or space
  649.     INX    H        ; Point to next
  650.     CPI    ':'        ; Colon found?
  651.     JZ    COLON1
  652.     CPI    ','        ; Comma found?
  653.     JZ    GETF1
  654.     CPI    ' '+1        ; Delimiter?
  655.     JC    GETF1
  656.     JMP    COLON        ; Continue if not end of line
  657. ;
  658. COLON1:    POP    H        ; Clear stack
  659.     MOV    A,M        ; Save possible drive specification
  660.     CALL    CAPS        ; Capitalize
  661.     CPI    'A'        ; Digit if less than 'a'
  662.     JC    USERCK        ; Process user number
  663.     SUI    'A'        ; Convert to 0-31
  664.     CPI    MAXDISK        ; Within bounds?
  665.     JC    SVDISK
  666. ;
  667. ERREXIT:XRA    A        ; Error indicator
  668.     POP    D        ; Restore 'de'
  669.     RET
  670. ;
  671. ; Log in specified disk
  672. ;
  673. SVDISK:    INR    A        ; Adjust to 1 for 'a'
  674.     STA    DISK        ; Save flag
  675.     INX    H        ; Point to next character
  676. ;
  677. ; Check for user
  678. ;
  679. USERCK:    MOV    A,M        ; Get possible user number
  680.     CPI    ':'        ; No user number
  681.     JZ    GETFILE
  682.     CPI    '?'        ; All user numbers?
  683.     JNZ    USERC1
  684.     STA    USER        ; Set value
  685.     INX    H        ; Point to after
  686.     MOV    A,M        ; Must be colon
  687.     CPI    ':'
  688.     JZ    GETFILE
  689.     JMP    ERREXIT        ; Fatal error if not colon after ?
  690. ;
  691. USERC1:    XRA    A        ; Zero user number
  692.     MOV    B,A        ; 'b' = accumulator for user number
  693. ;
  694. USRLOOP:MOV    A,M        ; Get digit
  695.     INX    H        ; Point to next
  696.     CPI    ':'        ; Done?
  697.     JZ    USRDN
  698.     SUI    '0'        ; Convert to binary
  699.     JC    ERREXIT        ; User number error?
  700.     CPI    10
  701.     JNC    ERREXIT
  702.     MOV    C,A        ; Next digit in 'c'
  703.     MOV    A,B        ; Old number in 'a'
  704.     ADD    A        ; *2
  705.     ADD    A        ; *4
  706.     ADD    B        ; *5
  707.     ADD    A        ; *10
  708.     ADD    C        ; *10+new digit
  709.     MOV    B,A        ; Result in 'b'
  710.     JMP    USRLOOP
  711. ;
  712. USRDN:    MOV    A,B        ; Get nuer user number
  713.     CPI    MAXUSER+1    ; Within range?
  714.     JNC    ERREXIT
  715.     STA    USER        ; Save in flag
  716.     JMP    GETFILE
  717. ;
  718. ; Extract file name
  719. ;
  720. GETF1:    POP    H        ; Get pointer to byte
  721. ;
  722. GETFILE:MOV    A,M        ; Pointing to colon?
  723.     CPI    ':'
  724.     JNZ    GFILE1
  725.     INX    H        ; Skip over colon
  726. ;
  727. GFILE1:    MOV    A,M        ; Get next character
  728.     CPI    ','        ; Delimiter?
  729.     JZ    GFQUES
  730.     CPI    ' '+1        ; Not a delimiter?
  731.     JNC    GFILE2
  732. ;
  733. GFQUES:    INX    D        ; Fill with ???
  734.     MVI    B,11        ; 11 bytes
  735.     MVI    A,'?'
  736. ;
  737. GFFILL:    STAX    D        ; Put?
  738.     INX    D        ; Point to next
  739.     DCR    B        ; Count down
  740.     JNZ    GFFILL
  741. ;
  742. FNDONE:    LDA    DISK        ; Get disk number
  743.     MOV    B,A        ; In 'b'
  744.     LDA    USER        ; Get user number
  745.     MOV    C,A        ; In 'c'
  746.     POP    D        ; Restore registers
  747.     MVI    A,0FFH        ; No error
  748.     ORA    A        ; Set flags
  749.     RET
  750. ;
  751. ; Get file name fields
  752. ;
  753. GFILE2:    MVI    B,8        ; At most, 8 bytes for filename
  754.     CALL    SCANF        ; Scan and fill
  755.     MVI    B,3        ; At most, 3 bytes for filetype
  756.     MOV    A,M        ; Get delimiter
  757.     CPI    '.'        ; Filename ending in '.'?
  758.     JNZ    GFILE3
  759.     INX    H        ; Point to character after '.'
  760.     CALL    SCANF        ; Scan and fill
  761.     JMP    FNDONE        ; Done...return to 'args'
  762. ;
  763. GFILE3:    CALL    SCANF4        ; Fill with spaces
  764.     JMP    FNDONE
  765. ;
  766. ; Scanner routine
  767. ;
  768. SCANF:    CALL    DELCK        ; Check for delimiter
  769.     JZ    SCANF4        ; Fill with spaces if found
  770.     INX    D        ; Point to next byte in filename
  771.     CPI    '*'        ; Question mark fill ?
  772.     JNZ    SCANF1
  773.     MVI    A,'?'        ; Place '?'
  774.     STAX    D
  775.     JMP    SCANF2
  776. ;
  777. SCANF1:    STAX    D        ; Place character
  778.     INX    H        ; Point to next position
  779. ;
  780. SCANF2:    DCR    B        ; Count down
  781.     JNZ    SCANF        ; Continue loop
  782. ;
  783. SCANF3:    CALL    DELCK        ; "b" chars or more - skip to delimiter
  784.     RZ
  785.     INX    H        ; Point to next
  786.     JMP    SCANF3
  787. ;
  788. SCANF4:    INX    D        ; Point to next filename or filetype
  789.     MVI    A,' '        ; Fill with spaces
  790.     STAX    D
  791.     DCR    B        ; Count down
  792.     JNZ    SCANF4
  793.     RET
  794. ;
  795. ; Check character pointed to by 'HL' for a delimiter, return with Zero
  796. ; flage set if the character is a delimiter
  797. ;
  798. DELCK:    MOV    A,M        ; Get the character
  799.     CALL    CAPS        ; Capitalize
  800.     ORA    A        ; 0=delimiter
  801.     RZ
  802.     CPI    ' '+1        ; Space character+1
  803.     JC    DELCK1        ; Space character or less
  804.     CPI    '='
  805.     RZ
  806.     CPI    5FH        ; Underscore
  807.     RZ
  808.     CPI    '.'
  809.     RZ
  810.     CPI    ':'
  811.     RZ
  812.     CPI    ';'
  813.     RZ
  814.     CPI    ','
  815.     RZ
  816.     CPI    '<'
  817.     RZ
  818.     CPI    '>'
  819.     RET
  820. ;
  821. DELCK1:    CMP    M        ; Compare with self for ok
  822.     RET
  823. ;
  824. CAPS:    CPI    'a'
  825.     RC
  826.     CPI    'z'+1
  827.     RNC
  828.     SUI    20H
  829.     RET            ; END OF RICK CONN'S "FNAME"
  830. ;
  831. ;    +----------------+
  832. ;    | DIVIDE HL BY 2 |
  833. ;    +----------------+
  834. ;
  835. DIVBY2:    ORA    A
  836.     MOV    A,H
  837.     RAR
  838.     MOV    H,A
  839.     MOV    A,L
  840.     RAR
  841.     MOV    L,A
  842.     RET
  843. ;
  844. ;    +----------------------------------+
  845. ;    | HEX TO DECIMAL CONVERT AND PRINT |
  846. ;    +----------------------------------+
  847. ;
  848. HEXDC1:    XRA    A
  849.     STA    LZF
  850.     JMP    HD1
  851. ;
  852. HEXDEC:    XRA    A        ;SET ACC
  853.     STA    LZF
  854.     LXI    B,-10000    ;10-THOUSANDS
  855.     CALL    MAKEDEC        ;MAKE THEM
  856. HD1:    LXI    B,-1000        ;THOUSANDS
  857.     CALL    MAKEDEC        ;MAKE THEM
  858.     LXI    B,-100        ;HUNDREDS
  859.     CALL    MAKEDEC        ;MAKE THEM
  860. HEXDC2:    LXI    B,-10        ;TENS
  861.     CALL    MAKEDEC        ;MAKE THEM
  862.     LXI    B,-1        ;UNITS
  863.     MVI    A,1
  864.     STA    LZF
  865. ;
  866. MAKEDEC:
  867.     MVI    D,-1        ;SET COUNTER
  868. MDECLP:    SHLD    TEMP1        ;SAVE HEX
  869.     INR    D        ;INC DE
  870.     DAD    B        ;ADD BC TO HEX
  871.     JC    MDECLP        ;LOOP IF CY
  872.     LHLD    TEMP1        ;GET HEX
  873.     MOV    B,D        ;DIGIT TO B
  874.     MVI    A,'0'        ;SET ASCII
  875.     ADD    B        ;ADD DIGIT
  876.     CPI    '0'
  877.     JNZ    NLZ
  878.     MOV    B,A        ;SAVE
  879.     LDA    LZF        ;GET LZ FLAG
  880.     ORA    A        ;SUPPRESS?
  881.     JZ    LZS        ;YES
  882.     MOV    A,B
  883. NLZ:    STA    LZF
  884.     JMP    PUTCH
  885. ;
  886. LZS:    MVI    A,' '
  887.     JMP    PUTCH
  888. ;
  889. ;    +-----------------------+
  890. ;    | COMPARE [DE] AND [HL] |
  891. ;    +-----------------------+
  892. ;
  893. CPDEHL:    PUSH    H
  894.     PUSH    D
  895.     MVI    B,12            ; test 12 characters
  896. CPDL:    LDAX    D
  897.     CMP    M
  898.     JNZ    CPDX
  899.     INX    D
  900.     INX    H
  901.     DCR    B
  902.     JNZ    CPDL
  903. CPDX:    POP    D
  904.     POP    H
  905.     RET
  906. ;
  907. ;    +--------------------------+
  908. ;    | PRINT [DX] AT CON OR LST |
  909. ;    +--------------------------+
  910. ;
  911. PRINTM:    LDAX    D            ; get character
  912.     CPI    '$'            ; delimiter?
  913.     RZ                ;   yes, exit
  914.     CALL    PUTCH
  915.     INX    D
  916.     JMP    PRINTM
  917. ;
  918. ;    +-----------------------+
  919. ;    | ERROR MESSAGE DISPLAY |
  920. ;    +-----------------------+
  921. ;
  922. ERROR:    DCR    A            ; error 1?
  923.     LXI    D,ERR1
  924.     JZ    PRERR
  925.     DCR    A
  926.     LXI    D,ERR2
  927. PRERR:    MVI    C,PSTR
  928.     JMP    BDOS
  929. ;
  930. ;    +-----------------------------+
  931. ;    | SNEAKY WAY OUT OF THIS MESS |
  932. ;    +-----------------------------+
  933. ;
  934. EXIT:    CALL    CRLF            ; new line
  935.     JMP    QUIT            ; spaghetti code
  936. ;
  937. ;    +--------------+
  938. ;    | DATA STORAGE |
  939. ;    +--------------+
  940. ;
  941. CDRIV:    DB    0            ; current drive
  942. CUSER:    DB    0            ; current user #
  943. CPMV:    DB    0            ; CP/M version
  944. STKSAV:    DW    0
  945. ;
  946. DISK:    DB    0
  947. USER:    DB    0
  948. TEMP1:    DW    0
  949. ;
  950. OPTNS:
  951. KOPT:    DB    'K'            ; K-option (size display)
  952. LOPT:    DB    'L'            ; L-option (printer)
  953. SOPT:    DB    'S'            ; S-option (sort)
  954.     DB    0FFH
  955. ;
  956. BLSHFT:    DB    0
  957. BLMASK:    DB    0
  958. DIRSZ:    DW    0
  959. NUMBLK:    DW    0
  960. LZF:    DB    0
  961. ;
  962. NMBFLS:    DW    0            ; number of files
  963. ;
  964. SSTADR:    DW    0
  965. SRECLEN:DW    0
  966. SNUMRT:    DW    0
  967. SNUMRW:    DW    0
  968. SORTV1:    DW    0
  969. SORTV2:    DW    0
  970. SORTV3:    DW    0
  971. SORTV4:    DW    0
  972. ;
  973. BUFPTR:    DW    BUFFER
  974. CURROW:    DB    0
  975. CURCOL:    DB    0
  976. CUMSIZ:    DW    0            ; cumulative filesizes
  977. ;
  978. ;    +----------+
  979. ;    | MESSAGES |
  980. ;    +----------+
  981. ;
  982. SUMM1:    DB    9,'DRIVE/USER $'
  983. SUMM2:    DB    ': DISPLAYED$'
  984. SUMM3:    DB    ' FILES IN$'
  985. SUMM4:    DB    'k TOTAL',CR,LF,'$'
  986. ;
  987. ERR1:    DB    CR,LF,'Invalid drive or user',CR,LF,'$'
  988. ERR2:    DB    CR,LF,'No file(s)',CR,LF,'$'
  989. ;
  990.     ORG    $+80
  991. STACK    EQU    $
  992.     ORG    (($/100H)*100H)+100H
  993. BUFFER    EQU    $
  994.     END
  995. w line
  996.     JMP    QUIT            ; spaghetti code
  997. ;
  998.