home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / p / sff12.lbr / SFF.AZM / SFF.ASM
Encoding:
Assembly Source File  |  1993-10-25  |  32.1 KB  |  1,497 lines

  1. ;             Super File Find Version 1.2
  2. ;                 06/20/84
  3. ;
  4. ;                by
  5. ;            G.B. Shaffstall SYSOP
  6. ;            Lakewood RCP/M System
  7. ;
  8. ;    To write Super File Find I started with SD-81 so let me give some
  9. ;    credit that is due to the many people that worked on it in the past.
  10. ;
  11. ;    This utility only works with CP/M 2.0 and upwards.
  12. ;
  13. ;    Super File Find allows full wildcard searches of the DIRECTORYS and
  14. ;    ALL LIBRARY files on your system for a requested file, starting at A:
  15. ;    User 0 working it's way up and across all users and drives until
  16. ;    a trapped I/O error causes exit just as SD does.
  17. ;
  18. ;    If you prefer you can specify a single drive to be searched by
  19. ;    including the drive name as a prefix to the search file.
  20. ;
  21. ;    Entering SFF<cr> will display a brief help message.
  22. ;
  23. ;    The USER AREA PATCH TABLE is the same as in SD with one exception,
  24. ;    If you put a 0FFH in a user location that drive will be skipped.
  25. ;
  26. ;    If you have a large system with many .LBR files on it you can patch
  27. ;    lable QUIET to a 0 to provide the message "Searching <dn>: User <num>"
  28. ;    so the user will know that the program is still running. With any
  29. ;    other value in this location the message "+++ NO FILE ON <dn>:" will
  30. ;    be printed as the program switches drives and no files were found.
  31. ;    At the current time there is no PAGE PAUSE in it but unless something
  32. ;    like SFF *.* is used this should be no problem..
  33. ;
  34. ;    If you are running BYELOW enter the address of your BDOS into BDOLOC.
  35. ;
  36. CR:    EQU    0DH
  37. LF:    EQU    0AH
  38. ESC:    EQU    1BH
  39. ;
  40. ; BDOS EQUATES
  41. ;
  42. RDCHR:    EQU    1    ;READ CHAR FROM CONSOLE
  43. WRCHR:    EQU    2    ;WRITE CHAR TO CONSOLE
  44. PRINTS:    EQU    9    ;PRINT STRING
  45. CONST:    EQU    11    ;CHECK CONS STAT
  46. RESET:    EQU    13    ;RESET DISK SYSTEM
  47. SELDSK:    EQU    14    ;SELECT DISK
  48. OPEN:    EQU    15    ;0FFH=NOT FOUND
  49. CLOSE:    EQU    16    ;   "   "
  50. SEARCH:    EQU    17    ;   "   "
  51. NEXT:    EQU    18    ;   "   "
  52. READ:    EQU    20    ;NOT 0 = EOF
  53. WRITE:    EQU    21    ;NOT 0 = DISK FULL
  54. MAKE:    EQU    22    ;0FFH = DIRECTORY FULL
  55. CURDSK:    EQU    25    ;GET CURRENTLY LOGGED DISK NAME
  56. SETDMA:    EQU    26    ;SET CURRENT DMA
  57. GALLOC:    EQU    27    ;GET ADDRESS OF ALLOCATION VECTOR
  58. CURDPB:    EQU    31    ;GET CURRENT DISK PARAMETERS
  59. CURUSR:    EQU    32    ;GET CURRENTLY LOGGED USER NUMBER (2.X ONLY)
  60. ;
  61. ;
  62. BASE    EQU    0    ;DEFAULT TO 0
  63. TPA    EQU    100H
  64. FCB    EQU    BASE+5CH
  65. BDOS    EQU    BASE+5
  66. ;
  67.     ORG    TPA
  68. ;
  69. ;
  70. ;
  71. ;***********************************************************************
  72. ;
  73. ;        BEGIN EXECUTABLE PROGRAM CODE *
  74. ;
  75. ;***********************************************************************
  76. ;
  77. ;
  78.     JMP    START
  79. ;
  80. ;
  81. ; DRIVE CODE/USER AREA LOOKUP TABLE
  82. ;
  83. ; NOTE THAT THE LODRV-HIDRV TABLE IS INCLUDED HERE FULLY CONFIGURED.
  84. ; FOR YOUR OWN USE, YOU SHOULD CHANGE THE MAXIMUM USER AREAS AS APPRO-
  85. ; PRIATE FOR EACH DRIVE ON YOUR SYSTEM.  NOTE THAT THERE ARE ONLY 16
  86. ; USER AREAS AVAILABLE UNDER CP/M 2, SO THE HIGHEST LEGAL USER AREA YOU
  87. ; CAN SPECIFY IS 15 (RANGE 0-15 = 16 AREAS).  THE PROGRAM WILL CONVERT
  88. ; ANYTHING OVER 15 INTO MOD 15. ENTER AN 0FFH TO CAUSE A DRIVE TO BE
  89. ; SKIPPED ON SEARCH.
  90. ;
  91. LODRV:    EQU    $        ;MARK BEGINNING OF DRIVE/USER TABLE
  92. ;
  93.     DB    15         ;MAXIMUM USER AREA FOR DRIVE A
  94.     DB    15        ;   "     "    "    "     "   B
  95.     DB    0FFH        ;   "     "    "    "     "   C
  96.     DB    0FFH         ;   "     "    "    "     "   D
  97.     DB    0FFH         ;   "     "    "    "     "   E
  98.     DB    0FFH         ;   "     "    "    "     "   F
  99.     DB    0FFH         ;   "     "    "    "     "   G
  100.     DB    0FFH         ;   "     "    "    "     "   H
  101.     DB    0FFH         ;   "     "    "    "     "   I
  102.     DB    0FFH         ;   "     "    "    "     "   J
  103.     DB    0FFH         ;   "     "    "    "     "   K
  104.     DB    0FFH         ;   "     "    "    "     "   L
  105.     DB    0FFH         ;   "     "    "    "     "   M
  106.     DB    0FFH         ;   "     "    "    "     "   N
  107.     DB    0FFH         ;   "     "    "    "     "   O
  108.     DB    0FFH         ;   "     "    "    "     "   P
  109. ;
  110. HIDRV:    EQU    $        ;MARK END OF DRIVE/USER TABLE
  111. QUIET    DB    0FFH        ;PATCH TO NON ZERO FOR QUIET MODE
  112. ;
  113. ;    IF RUNNING BYELOW ENTER ADDRESS THE OF YOUR BDOS INTO BDOLOC.
  114. ;    (NOTE THE SWAP SUBROUTINE WILL CURRENTLY SET THE L REG TO 9.)
  115. ;
  116. BDOLOC    DW 0
  117. ;
  118. VERNAME    DB    CR,LF,'Super File Find v1.2 - 06/20/84'
  119.     db    cr,lf,'A Total Wild-Card FILEFIND including Libraries.'
  120.     db    cr,lf,'Syntax to search all Drives and User Areas'
  121.     db    cr,lf,'is SFF <Filename.type>'
  122.     db    cr,lf,'Examples:'
  123.     db    cr,lf,'A0>SFF *.AQ6     or    A0>SFF MBOOT*.*',cr,lf
  124.     db    cr,lf,'To search a single drive and all User Areas'
  125.     db    cr,lf,'Use SFF <Driveneme:Filename.type>'
  126.     db    cr,lf,'Examples:'
  127.     db    cr,lf,'A0>SFF B:MDM???.*  or  A0>SFF D:KP*.*',cr,lf+80h
  128. PROCES    db    cr,lf,'Searching '
  129. PROC1    db    ' : User',' '+80H
  130. SIGNON    db    'Use Ctrl/C to Abor','t'+80H
  131. ;
  132. START:    LXI    H,0
  133.     DAD    SP        ;HL=OLD STACK
  134.     SHLD    STACK        ;SAVE IT
  135.     LXI    SP,STACK    ;GET NEW STACK
  136.     XRA    A
  137.     STA    FNDFLG        ;CLEAR file found flag
  138.     STA    NEWUSR        ;MAKE NEW USER = 0
  139.     STA    BASUSR        ;DUPLICATE IT IF MULTI-DISK MODE
  140.     MVI    C,12        ;GET AND SAVE THE CP/M VERSION #
  141.     CALL    BDOS
  142.     MOV    A,L
  143.     STA    VERFLG
  144.     STA    DOPFLG        ;DO NOT ALLOW MULTI-DRIVE YET
  145.     CPI    20H        ;SET CARRY IF CP/M 1.4
  146.     JC    VERERR        ;EXIT ON EARLIER THAN 2.0
  147.     LXI    H,FCB+1     ;POINT TO NAME
  148.     MOV    A,M        ;ANY SPECIFIED?
  149.     CPI    ' '
  150.     JZ    NONERR        ;so print help info
  151.     PUSH    H        ;SAVE FCB ADDRESS
  152.     LXI    D,SEARN        ;POINT TO SEARCH NAME HOLDING AREA
  153.     MVI    B,11        ;SIZE OF FILE NAME, TYPE
  154.     CALL    MOVE        ;MOVE IT
  155.     POP    H        ;RESTORE FCB ADDRESS
  156.     MVI    E,0FFH        ;GET CURRENT USER NUMBER
  157.     MVI    C,CURUSR
  158.     CALL    CPM
  159.     STA    OLDUSR        ;INITIALIZE STARTUP USER NUMBER
  160. CLNON:    MVI    C,CURDSK
  161.     CALL    CPM        ;GET CURRENT DISK NR
  162.     STA    OLDDSK        ;SAVE FOR RESET IF NEEDED
  163.     LXI    H,FCB
  164.     MOV    A,M        ;GET DRIVE NAME FOR DIRECTORY SEARCH
  165.     ORA    A        ;ANY SPECIFIED?
  166.     JNZ    START2        ;YES SKIP NEXT ROUTINE
  167.     XRA    A
  168.     STA    DOPFLG        ;OK LET MULTI-DRIVE IN
  169.     MVI    A,1        ;OTHERWISE, GET DISK "A"
  170. START2: MOV    M,A        ;PUT THE ABSOLUTE DRIVE CODE IN
  171.                 ;..DIRECTORY FCB
  172. CKREST:    LXI    D,SIGNON
  173.     CALL    PRINT
  174.     LDA    DOPFLG
  175.     ORA    A
  176.     CZ    SWAPEM        ;SWAP BDOS ERROR VECTOR TABLES
  177. ;
  178. ;
  179. ; VALIDATE DRIVE CODE AND USER AREA NUMBERS FROM THE DRIVE TABLE.
  180. ;
  181. NOOPT:    LXI    D,DREMSG    ;GET THE DRIVE/USER ERROR MESSAGE
  182.     PUSH    D
  183.     LDA    FCB        ;GET DIRECTORY DRIVE CODE
  184.     DCR    A        ;NORMALIZE TO RANGE OF 0-15
  185.     CPI    HIDRV-LODRV    ;COMPARE WITH MAXIMUM DRIVES ON-LINE
  186.     JNC    ERXIT        ;TAKE DRIVE ERROR EXIT IF OUT OF RANGE
  187.     LXI    H,USRMSG    ;SWITCH TO USER # ERROR MESSAGE
  188.     XTHL
  189.     MOV    E,A        ;USE DRIVE CODE AS INDEX INTO TABLE
  190.     MVI    D,0
  191. USRCK:    LXI    H,LODRV     ;POINT TO BASE OF DRIVE/USER TABLE
  192.     DAD    D
  193.     MOV    A,M        ;GET THE MAXIMUM USER # FOR THIS DRIVE
  194.     CPI    0FFH        ;CHECK FOR SKIP DRIVE
  195.     JZ    ERXIT        ;EXIT IF NOT WANTED
  196. USRCK2:    ANI    0FH        ;MAKE SURE ITS IN RANGE 0 - 15
  197.     STA    MAXUSR        ;SAVE IT FOR LATER
  198.     LXI    H,NEWUSR    ;POINT TO THE DIRECTORY USER AREA
  199.     CMP    M        ;COMPARE IT WITH THE MAXIMUM
  200.     JC    ERXIT        ;TAKE ERROR EXIT IF USER NUMBER ILLEGAL
  201.     POP    D        ;DESTROY ERROR MESSAGE POINTER
  202.     LXI    H,FCB+1     ;POINT TO NAME
  203. ;
  204. ; MAKE FCB ALL '?' TO SEARCH FOR EVERY FILE
  205. ;
  206. WCD:    MVI    B,11        ;FN+FT COUNT
  207. QLOOP:    MVI    M,'?'        ;STORE '?' IN FCB
  208.     INX    H
  209.     DCR    B
  210.     JNZ    QLOOP
  211. ;
  212. GOTFCB: MVI    A,'?'        ;FORCE WILD EXTENT
  213.     STA    FCB+12
  214.     CALL    SETSRC        ;SET DMA FOR BDOS MEDIA CHANGE CHECK
  215.     LXI    H,FCB        ;POINT TO FCB DRIVE CODE FOR DIRECTORY
  216.     MOV    E,M        ;GET THE DRIVE CODE OUT OF THE FCB
  217.     DCR    E        ;NORMALIZE DRIVE CODE FOR SELECT
  218.     MVI    C,SELDSK    ;SELECT THE DIRECTORY DRIVE TO RETRIEVE
  219.     CALL    CPM        ;..THE PROPER ALLOCATION VECTOR
  220.     MVI    C,CURDPB    ;IT IS 2.X OR MP/M...REQUEST DPB
  221.     CALL    BDOS
  222.     INX    H
  223.     INX    H
  224.     MOV    A,M        ;GET BLOCK SHIFT
  225.     STA    BLKSHF
  226.     INX    H        ;BUMP TO BLOCK MASK
  227.     MOV    A,M
  228.     STA    BLKMSK        ;GET IT
  229.     INX    H
  230.     INX    H
  231.     MOV    E,M        ;GET MAX BLOCK #
  232.     INX    H
  233.     MOV    D,M
  234.     XCHG
  235.     SHLD    BLKMAX        ;SAVE IT
  236.     XCHG
  237.     INX    H
  238.     MOV    E,M        ;GET DIRECTORY SIZE
  239.     INX    H
  240.     MOV    D,M
  241.     XCHG
  242.     SHLD    DIRMAX        ;SAVE MAX # OF ENTRIES IN DIRECTORY
  243. ;
  244. ; REENTER HERE ON SUBSEQUENT PASSES WHILE IN THE ALL-USERS MODE
  245. ;
  246. SETTBL:    LDA    QUIET        ;check if in quiet mode
  247.     ORA    A
  248.     JNZ    SETTB1        ;yes so skip printout
  249.     LDA    FCB
  250.     ADI    'A'-1
  251.     STA    PROC1
  252.     LXI    D,PROCES    ;show the user what area is being
  253.     CALL    PRINT        ;worked on.
  254.     CALL    TYPUSR
  255. SETTB1:    LHLD    DIRMAX        ;GET DIRECTORY MAXIMUM AGAIN
  256.     INX    H        ;DIRECTORY SIZE IS DIRMAX+1
  257.     DAD    H        ;DOUBLE DIRECTORY SIZE
  258.     LXI    D,ORDER     ;TO GET SIZE OF ORDER TABLE
  259.     DAD    D        ;ALLOCATE ORDER TABLE
  260.     SHLD    TBLOC        ;NAME TBL BEGINS WHERE ORDER TBL ENDS
  261.     SHLD    NEXTT
  262.     XCHG
  263.     LHLD    BDOS+1        ;MAKE SURE WE HAVE ROOM TO CONTINUE
  264.     MOV    A,E
  265.     SUB    L
  266.     MOV    A,D
  267.     SBB    H
  268.     JNC    OUTMEM
  269.     LDA    NEWUSR        ;GET USER AREA FOR DIRECTORY
  270.     MOV    E,A
  271.     MVI    C,CURUSR    ;GET THE USER FUNCTION
  272.     CALL    CPM        ;..AND SET NEW USER NUMBER
  273. ;
  274. ;
  275. ; LOOK UP THE FCB IN THE DIRECTORY
  276. ;
  277.     MVI    A,'?'
  278.     LXI    H,FCB+12
  279.     MOV    M,A        ;MATCH ALL EXTENTS
  280.     INX    H
  281.     MOV    M,A        ;MATCH ALL S1 BYTES
  282.     INX    H
  283.     MOV    M,A        ;MATCH ALL S2 BYTES
  284.     LXI    H,0
  285.     SHLD    COUNT        ;INITIALIZE MATCH COUNTER
  286.     CALL    SETSRC        ;SET DMA FOR DIRECTORY SEARCH
  287.     MVI    C,SEARCH    ;GET 'SEARCH FIRST' FUNCTION
  288.     JMP    LOOK        ;..AND GO SEARCH FOR 1ST MATCH
  289. ;
  290. ; READ MORE DIRECTORY ENTRIES
  291. ;
  292. MORDIR: MVI    C,NEXT        ;SEARCH NEXT
  293. ;
  294. LOOK:    LXI    D,FCB
  295.     CALL    CPM        ;READ DIRECTORY ENTRY
  296.     INR    A        ;CHECK FOR END (0FFH)
  297.     JZ    SPRINT        ;IF NO MORE, SORT & PRINT WHAT WE HAVE
  298. ;
  299. ; POINT TO DIRECTORY ENTRY
  300. ;
  301. SOME:    DCR    A        ;UNDO PREV 'INR A'
  302.     ANI    3        ;MAKE MODULUS 4
  303.     ADD    A        ;MULTIPLY...
  304.     ADD    A        ;..BY 32 BECAUSE
  305.     ADD    A        ;..EACH DIRECTORY
  306.     ADD    A        ;..ENTRY IS 32
  307.     ADD    A        ;..BYTES LONG
  308.     LXI    H,BASE+81H    ;POINT TO BUFFER (SKIP TO FN/FT)
  309.     ADD    L        ;POINT TO ENTRY
  310.     ADI    9        ;POINT TO SYS BYTE
  311.     MOV    L,A        ;SAVE (CAN'T CARRY TO H)
  312.     MOV    A,M        ;GET SYS BYTE
  313.     ORA    A        ;CHECK BIT 7
  314.     JM    MORDIR        ;SKIP THAT FILE
  315. ;
  316. SYSFOK: MOV    A,L        ;GO BACK NOW
  317.     SUI    10        ;BACK TO USER NUMBER (ALLOC FLAG)
  318.     MOV    L,A        ;HL POINTS TO ENTRY NOW
  319.     LDA    NEWUSR        ;GET CURRENT USER
  320.     CMP    M
  321.     JNZ    MORDIR        ;IGNORE IF DIFFERENT
  322.     INX    H
  323. ;
  324. ; MOVE ENTRY TO TABLE
  325. ;
  326.     XCHG            ;ENTRY TO DE
  327.     LHLD    NEXTT        ;NEXT TABLE ENTRY TO HL
  328.     MVI    B,11        ;ENTRY LENGTH (NAME, TYPE, EXTENT)
  329. ;
  330. TMOVE:    LDAX    D        ;GET ENTRY CHAR
  331.     ANI    7FH        ;REMOVE ATTRIBUTES
  332.     MOV    M,A        ;STORE IN TABLE
  333.     INX    D
  334.     INX    H
  335.     DCR    B        ;MORE?
  336.     JNZ    TMOVE
  337.     INX    D        ;DE->> S1
  338.     INX    D        ;DE->> S2
  339.     LDAX    D        ;GET S2 BYTE, OVERFLOW=INT(EXTENTS/32)
  340.     PUSH    H        ;SAVE HL
  341.     MOV    L,A        ;SET UP 16-BIT MULTIPLY
  342.     MVI    H,0
  343.     MVI    B,5
  344.     CALL    SHLL        ;HL IS NOW # OF OVERFLOW EXTENTS
  345.     DCX    D        ;DE->> S1
  346.     DCX    D        ;DE->> EXTENT
  347.     LDAX    D        ;GET EXTENT
  348.     ADD    L
  349.     MOV    L,A
  350.     MOV    A,H
  351.     ACI    0
  352.     MOV    H,A        ;HL NOW HAS TOTAL EXTENTS
  353.     MVI    B,7
  354.     CALL    SHLL        ;HL NOW HAS TOTAL SECTORS LESS LAST EXT
  355.     INX    D        ;DE->> S1
  356.     INX    D        ;DE->> S2
  357.     INX    D        ;POINT TO SECTOR COUNT
  358.     LDAX    D        ;GET IT
  359.     ADD    L
  360.     MOV    L,A
  361.     MOV    A,H
  362.     ACI    0
  363.     MOV    H,A        ;HL NOW HAS TOTAL SECTORS
  364.     XTHL            ;DO SOME FANCY SHUFFLING
  365.     XCHG
  366.     XTHL
  367.     XCHG
  368.     MOV    M,D
  369.     INX    H
  370.     MOV    M,E
  371.     POP    D        ;ALL BACK TO NORMAL...
  372.     INX    H
  373.     SHLD    NEXTT        ;SAVE UPDATED TABLE ADDRESS
  374.     XCHG
  375.     LHLD    COUNT        ;BUMP THE # OF MATCHES MADE
  376.     INX    H
  377.     SHLD    COUNT
  378.     LXI    H,13        ;SIZE OF NEXT ENTRY
  379.     DAD    D
  380.     XCHG            ;FUTURE NEXTT IS IN DE
  381.     LHLD    BDOS+1        ;PICK UP TPA END
  382.     MOV    A,E
  383.     SUB    L        ;COMPARE NEXTT-TPA END
  384.     MOV    A,D
  385.     SBB    H
  386.     JC    MORDIR        ;IF TPA END > NEXTT, LOOP BACK FOR MORE
  387. ;
  388. OUTMEM: CALL    ERXIT        ;EXIT IF DIRECTORY TOO LARGE
  389.     DB    'Memor','y' OR 80H
  390. ;
  391. ; SHIFT HL LEFT BY B BITS
  392. ;
  393. SHLL:    DAD    H
  394.     DCR    B
  395.     RZ
  396.     JMP    SHLL
  397. ;
  398. ; SORT
  399. ;
  400. SPRINT:    CALL    SETFOP        ;RETURN TO FILE OUTPUT DMA & USER #
  401.     LHLD    COUNT        ;GET FILE NAME COUNT
  402.     MOV    A,L
  403.     ORA    H        ;ANY FOUND?
  404.     JZ    PRTOTL        ;EXIT IF NO FILES FOUND
  405.     PUSH    H        ;SAVE FILE COUNT
  406.     STA    SUPSPC        ;ENABLE LEADING ZERO SUPPRESSION
  407. ;
  408. ; INITIALIZE THE ORDER TABLE
  409. ;
  410.     LHLD    TBLOC        ;GET START OF NAME TABLE
  411.     XCHG            ;INTO DE
  412.     LXI    H,ORDER     ;POINT TO ORDER TABLE
  413.     LXI    B,13        ;ENTRY LENGTH
  414. BLDORD: MOV    M,E        ;SAVE LOW ORDER ADDRESS
  415.     INX    H
  416.     MOV    M,D        ;SAVE HIGH ORDER ADDRESS
  417.     INX    H
  418.     XCHG            ;TABLE ADDR TO HL
  419.     DAD    B        ;POINT TO NEXT ENTRY
  420.     XCHG
  421.     XTHL            ;SAVE TBL ADDR, FETCH LOOP COUNTER
  422.     DCX    H        ;COUNT DOWN LOOP
  423.     MOV    A,L
  424.     ORA    H        ;MORE?
  425.     XTHL            ;(RESTORE TBL ADDR, SAVE COUNTER)
  426.     JNZ    BLDORD        ;YES, GO DO ANOTHER ONE
  427.     POP    H        ;CLEAN LOOP COUNTER OFF STACK
  428.     LHLD    COUNT        ;GET COUNT
  429.     SHLD    SCOUNT        ;SAVE AS # TO SORT
  430.     DCX    H        ;ONLY 1 ENTRY?
  431.     MOV    A,L
  432.     ORA    H
  433.     JZ    NOOUT        ;YES, SO SKIP SORT
  434. ;
  435. ; THIS SORT ROUTINE IS ADAPTED FROM SOFTWARE TOOLS BY KERNIGAN AND
  436. ; PLAUGHER.
  437. ;
  438. SORT:    LHLD    SCOUNT        ;NUMBER OF ENTRIES
  439. L0:    ORA    A        ;CLEAR CARRY
  440.     MOV    A,H        ;GAP=GAP/2
  441.     RAR
  442.     MOV    H,A
  443.     MOV    A,L
  444.     RAR
  445.     MOV    L,A
  446.     ORA    H        ;IS IT ZERO?
  447.     JZ    NOOUT        ;THEN NONE LEFT
  448.     MOV    A,L        ;MAKE GAP ODD
  449.     ORI    1
  450.     MOV    L,A
  451.     SHLD    GAP
  452.     INX    H        ;I=GAP+1
  453. ;
  454. L2:    SHLD    I
  455.     XCHG
  456.     LHLD    GAP
  457.     MOV    A,E        ;J=I-GAP
  458.     SUB    L
  459.     MOV    L,A
  460.     MOV    A,D
  461.     SBB    H
  462.     MOV    H,A
  463. ;
  464. L3:    SHLD    J
  465.     XCHG
  466.     LHLD    GAP        ;JG=J+GAP
  467.     DAD    D
  468.     SHLD    JG
  469.     MVI    A,13        ;COMPARE 13 CHARS    {SFK}
  470.     CALL    COMPARE     ;COMPARE (J) AND (JG)
  471.     JP    L5        ;IF A(J)<=A(JG)
  472.     LHLD    J
  473.     XCHG
  474.     LHLD    JG
  475.     CALL    SWAP        ;EXCHANGE A(J) AND A(JG)
  476.     LHLD    J        ;J=J-GAP
  477.     XCHG
  478.     LHLD    GAP
  479.     MOV    A,E
  480.     SUB    L
  481.     MOV    L,A
  482.     MOV    A,D
  483.     SBB    H
  484.     MOV    H,A
  485.     JM    L5        ;IF J>0 GOTO L3
  486.     ORA    L        ;CHECK FOR ZERO
  487.     JZ    L5
  488.     JMP    L3
  489. ;
  490. L5:    LHLD    SCOUNT        ;FOR LATER
  491.     XCHG
  492.     LHLD    I        ;I=I+1
  493.     INX    H
  494.     MOV    A,E        ;IF I<=N GOTO L2
  495.     SUB    L
  496.     MOV    A,D
  497.     SBB    H
  498.     JP    L2
  499.     LHLD    GAP
  500.     JMP    L0
  501. ;
  502. ; SORT IS ALL DONE - PRINT ENTRIES THAT COMPARE
  503. ;
  504. NOOUT:    LHLD    COUNT
  505.     SHLD    LCOUNT
  506.     LXI    H,ORDER     ;INITIALIZE ORDER TABLE POINTER
  507.     SHLD    NEXTL
  508.     SHLD    NEXTT
  509. ;
  510. ; OUTPUT THE DIRECTORY FILES WE'VE MATCHED.
  511. ;
  512. ENTRY:    LHLD    COUNT
  513.     DCX    H        ;DOCK FILE COUNT
  514.     SHLD    COUNT
  515.     MOV    A,H        ;IS THIS THE LAST FILE?
  516.     ORA    L
  517.     JZ    OKPRNT        ;IF COUNT=0, LAST FILE SO SKIP COMPARE
  518. ;
  519. ;
  520. ; COMPARE EACH ENTRY TO MAKE SURE THAT IT ISN'T PART OF A MULTIPLE EX-
  521. ; TENT FILE.    GO ONLY WHEN WE HAVE THE LAST EXTENT OF THE FILE.
  522. ;
  523.     CALL    CKABRT        ;CHECK FOR ABORT CODE FROM KEYBOARD
  524.     LHLD    NEXTT
  525.     MVI    A,11
  526.     CALL    COMPR        ;DOES THIS ENTRY MATCH NEXT ONE?
  527.     JNZ    OKPRNT        ;NO, PRINT IT
  528.     INX    H
  529.     INX    H        ;SKIP SINCE HIGHEST EXTENT LAST IN LIST
  530.     SHLD    NEXTT
  531.     JMP    ENTRY        ;LOOP BACK FOR NEXT LOWEST EXTENT
  532. ;
  533. OKPRNT:    LHLD    NEXTT        ;GET ORDER TABLE POINTER
  534.     MOV    E,M        ;GET LOW ORDER ADDRESS
  535.     INX    H
  536.     MOV    D,M        ;GET HIGH ORDER ADDRESS
  537.     INX    H
  538.     SHLD    NEXTT        ;SAVE UPDATED TABLE POINTER
  539.     XCHG            ;TABLE ENTRY TO HL
  540. ;
  541. ;    PUT IN USER & DRIVE PRINTOUT HERE
  542. ;
  543.     PUSH    H
  544.     LHLD    TFILES
  545.     INX    H
  546.     SHLD    TFILES
  547.     POP    H
  548.     CALL    COMPS        ;MATCH WHAT WE ARE LOOKING FOR ?
  549.     JNZ    OKEXIT        ;NO SO DON'T PRINT IT
  550.     PUSH    H
  551.     LHLD    TMATCH
  552.     INX    H
  553.     SHLD    TMATCH
  554.     POP    H
  555.     CALL    CRLF
  556.     LDA    FCB        ;..precede new line with drive name
  557.     ADI    'A'-1
  558.     CALL    TYPE
  559.     CALL    TYPUSR
  560.     MVI    A,':'        ;tag header with a colon and a space
  561.     CALL    TYPE        ;..and exit back to ENTRY
  562.     MVI    A,' '
  563.     CALL    TYPE
  564.     MVI    B,8        ;FILE NAME LENGTH
  565.     CALL    TYPEIT        ;TYPE FILENAME
  566.     MVI    A,'.'        ;PERIOD AFTER FN
  567.     CALL    TYPE
  568.     MVI    B,3        ;DISPLAY 3 CHARACTERS OF FILETYPE
  569.     CALL    TYPEIT
  570.     MOV    D,M
  571.     INX    H
  572.     MOV    E,M        ;SIZE IN DE (SECTORS)
  573.     LDA    BLKMSK
  574.     PUSH    PSW
  575.     ADD    E
  576.     MOV    E,A
  577.     MOV    A,D
  578.     ACI    0
  579.     MOV    D,A
  580.     POP    PSW
  581.     CMA
  582.     ANA    E
  583.     MOV    E,A        ;SIZE IN DE (SECTORS ROUNDED TO BLOCKSIZE)
  584.     MVI    B,3
  585. SHRR:    MOV    A,D
  586.     ORA    A
  587.     RAR
  588.     MOV    D,A
  589.     MOV    A,E
  590.     RAR
  591.     MOV    E,A
  592.     DCR    B
  593.     JNZ    SHRR
  594.     XCHG            ;GET FILE SIZE
  595. ;
  596. ; OUTPUT THE SIZE OF THE INDIVIDUAL FILE.
  597. ;
  598.     CALL    DECPRT        ;..GO PRINT IT
  599.     MVI    A,'k'        ;..AND FOLLOW WITH K SIZE
  600.     CALL    TYPE
  601.     MVI    A,0FFH
  602.     STA    FNDFLG        ;Set file found flag
  603. ;
  604. ; ONE FILE OUTPUT - TEST TO SEE IF WE HAVE TO OUTPUT ANOTHER ONE.
  605. ;
  606. OKEXIT    LHLD    COUNT        ;GET CURRENT FILE COUNTER AND TEST IT
  607.     MOV    A,H
  608.     ORA    L
  609.     JZ    PRTOTL        ;IF NO MORE FILES EXIT TO SUMMARY OUTPUT
  610.     JMP    ENTRY
  611. ;
  612. ; COMPUTE THE SIZE OF THE FILE/LIBRARY AND UPDATE OUR SUMMARY DATUM.
  613. ; THIS HAS BEEN CHANGED INTO A SUBROUTINE SO THAT BOTH THE FILE SIZE
  614. ; COMPUTATION AND A LIBRARY SIZE (WHEN PRINTING OUT LIBRARY MEMBERS) 
  615. ; CAN BE COMPUTED IN K.
  616. ;
  617. DOIT:    MOV    E,M        ;GET EXTENT #
  618.     MVI    D,0
  619.     INX    H
  620.     MOV    A,M        ;GET SECTOR COUNT OF LAST EXTENT
  621.     XCHG
  622.     DAD    H        ;# OF EXTENTS TIMES 16K
  623.     DAD    H
  624.     DAD    H
  625.     DAD    H
  626.     XCHG            ;SAVE IN DE
  627.     LXI    H,BLKMSK
  628.     ADD    M        ;ROUND LAST EXTENT TO BLOCK SIZE
  629.     RRC
  630.     RRC            ;CONVERT FROM SECTORS TO K
  631.     RRC
  632.     ANI    1FH
  633.     MOV    L,A        ;ADD TO TOTAL K
  634.     MVI    H,0
  635.     DAD    D
  636.     LDA    BLKMSK        ;GET SECTORS/BLK-1
  637.     RRC
  638.     RRC            ;CONVERT TO K/BLK
  639.     RRC
  640.     ANI    1FH
  641.     CMA            ;USE TO FINISH ROUNDING
  642.     ANA    L
  643.     MOV    L,A
  644.     RET
  645. ;.....
  646. ;
  647. ; PRINT HL IN DECIMAL WITH LEADING ZERO SUPPRESSION
  648. ;
  649. DECPRT:    XRA    A        ;CLEAR LEADING ZERO FLAG
  650.     STA    LZFLG
  651.     LXI    D,-1000     ;PRINT 1000'S DIGIT
  652.     CALL    DIGIT
  653.     LXI    D,-100        ;ETC.
  654.     CALL    DIGIT
  655.     LXI    D,-10
  656.     CALL    DIGIT
  657.     MVI    A,'0'        ;GET 1'S DIGIT
  658.     ADD    L
  659.     JMP    TYPE
  660. ;
  661. DIGIT:    MVI    B,'0'        ;START OFF WITH ASCII 0
  662. ;
  663. DIGLP:    PUSH    H        ;SAVE CURRENT REMAINDER
  664.     DAD    D        ;SUBTRACT
  665.     JNC    DIGEX        ;QUIT ON OVERFLOW
  666.     POP    PSW        ;THROW AWAY REMAINDER
  667.     INR    B        ;BUMP DIGIT
  668.     JMP    DIGLP        ;LOOP BACK
  669. ;
  670. DIGEX:    POP    H        ;RESTORE POINTER
  671.     MOV    A,B
  672.     CPI    '0'        ;ZERO DIGIT?
  673.     JNZ    DIGNZ        ;NO, TYPE IT
  674.     LDA    LZFLG        ;LEADING ZERO?
  675.     ORA    A
  676.     MVI    A,'0'
  677.     JNZ    TYPE        ;PRINT DIGIT
  678.     LDA    SUPSPC        ;GET SPACE SUPPRESSION FLAG
  679.     ORA    A        ;SEE IF PRINTING FILE TOTALS
  680.     RZ            ;YES, DON'T GIVE LEADING SPACES
  681.     MVI    A,' '
  682.     JMP    TYPE        ;LEADING ZERO...PRINT SPACE
  683. ;
  684. DIGNZ:    STA    LZFLG        ;LEADING ZERO FLAG SO NEXT ZERO PRINTS
  685.     JMP    TYPE        ;AND PRINT DIGIT
  686. ;
  687. ; NOW CHECK FOR LIBRARIES
  688. ;
  689. PRTOTL:    LHLD    LCOUNT        ;HOW MANY FILES DID WE SEE?
  690.     MOV    A,H
  691.     ORA    L
  692.     CNZ    PRTLMEM        ;SKIP THE .LBR CHECK IF NONE FOUND
  693.     XRA    A        ;GET A ZERO TO...
  694.     STA    SUPSPC        ;SUPPRESS LEADING SPACES IN TOTALS
  695. ;
  696. ; DIRECTORY FOR ONE USER AREA COMPLETED.  IF 'ALL USERS' OPTION IS SE-
  697. ; LECTED, THEN GO DO ANOTHER DIRECTORY ON THE NEXT USER NUMBER UNTIL WE
  698. ; EXCEED THE MAXIMUM USER # FOR THE SELECTED DRIVE.
  699. ;
  700. NXTUSR:    CALL    CKABRT        ;CHECK FOR USER ABORT FIRST
  701.     LDA    MAXUSR        ;NO ABORT - GET MAXIMUM USER NUMBER
  702.     LXI    H,NEWUSR    ;BUMP DIRECTORY USER NUMBER
  703.     INR    M
  704.     CMP    M        ;DOES NEXT USER # EXCEED MAXIMUM?
  705.     JNC    SETTBL        ;CONTINUE IF MORE USER AREAS TO GO
  706.     LDA    BASUSR        ;RESET BASE USER NUMBER FOR THE
  707.     MOV    M,A        ;..NEXT DIRECTORY SEARCH
  708. ;
  709. ; DIRECTORY FOR ALL USER AREAS COMPLETED.  IF THE MULTI-DISK OPTION IS
  710. ; ENABLED AND SELECTED, RESET TO THE BASE USER AREA AND REPEAT THE DI-
  711. ; RECTORY FOR NEXT DRIVE ON-LINE UNTIL WE EITHER EXCEED THE DRIVES IN
  712. ; OUR LODRV-HIDRV TABLE, OR THE BDOS SHUTS US DOWN WITH A SELECT OR BAD
  713. ; SECTOR ERROR, WHICH WILL BE INTERCEPTED BACK TO THE EXIT MODULE.
  714. ;
  715. NXTDSK: LXI    H,FNDFLG    ;get file found flag
  716.     MOV    A,M
  717.     MVI    M,0        ;clear file found flag for next drive
  718.     ORA    A
  719.     JNZ    NDSK        ;continue if at least 1 file found
  720.     LDA    QUIET        ;CHECK OUTPUT MODE
  721.     ORA    A
  722.     JZ    NDSK
  723.     CALL    CRLF
  724.     LDA    FCB        ;stash ASCII dir. drive in NO FILE msg
  725.     ADI    'A'-1
  726.     STA    NOFMS2
  727.     LXI    D,NOFMS1    ;print "No file on ? - "
  728.     CALL    PRINT
  729. NDSK:    LDA    DOPFLG
  730.     ORA    A
  731.     JNZ    EXIT
  732.     CALL    CKABRT        ;CHECK FOR USER ABORT FIRST
  733.     MVI    A,HIDRV-LODRV    ;GET MAXIMUM DRIVE CODE TO SEARCH
  734.     LXI    H,FCB        ;BUMP DIRECTORY FCB DRIVE CODE
  735.     INR    M
  736.     CMP    M        ;DOES NEXT DISK EXCEED MAXIMUM?
  737.     JC    EXIT
  738.     MOV    E,M
  739.     MVI    D,0
  740.     DCR    E
  741.     LXI    H,LODRV
  742.     DAD    D
  743.     MOV    A,M
  744.     CPI    0FFH
  745.     JZ    NDSK        ;SEARCH NEXT DISK IF MAXDR NOT TRUE
  746.     JMP    NOOPT
  747. ;
  748. ; Print the user number of the directory in decimal
  749. ;
  750. TYPUSR:    LDA    NEWUSR
  751.     CPI    10        ;if user no. > 9 print leading 1
  752.     JC    DUX
  753.     MVI    A,'1'
  754.     CALL    TYPE
  755.     LDA    NEWUSR        ;print low digit of user #
  756.     SUI    10
  757. ;
  758. DUX:    ADI    '0'
  759.     JMP    TYPE
  760. ;
  761. CRLF:    MVI    A,CR        ;SEND CR
  762.     CALL    TYPE
  763.     MVI    A,LF        ;SEND LF
  764.     JMP    TYPE
  765. ;.....                ;EXIT TO CALLER FROM TYPE
  766. ;
  767. ; OUTPUT CHARACTER IN A TO CONSOLE, AND OPTIONALLY TO PRINTER AND/OR THE
  768. ; OUTPUT FILE.
  769. ;
  770. TYPE:    PUSH    B
  771.     PUSH    D
  772.     PUSH    H
  773.     PUSH    PSW        ;SAVE THE CHARACTER TO OUTPUT
  774.     CALL    TYPE1        ;SEND IT TO CONSOLE
  775.     POP    PSW        ;RESTORE THE OUTPUT CHARACTER
  776. TYPRET: POP    H        ;EXIT FROM TYPE
  777.     POP    D
  778.     POP    B
  779.     RET
  780. ;.....
  781. ;
  782. ;
  783. ; OUTPUT CHARACTER
  784. ;
  785. TYPE1    MOV    E,A        ;GET CHARACTER INTO BDOS ENTRY REGISTER
  786.     MVI    C,WRCHR
  787.     JMP    BDOS        ;CALL CONOUT VIA THE BDOS
  788. ;.....
  789. ;
  790. ;
  791. ; PRINT A STRING AT HL OF LENGTH B
  792. ;
  793. TYPEIT: MOV    A,M
  794.     CALL    TYPE
  795.     INX    H
  796.     DCR    B
  797.     JNZ    TYPEIT
  798.     RET
  799. ;.....
  800. ;
  801. ;
  802. ; PRINT STRING TERMINATED WITH LAST BYTE HIGH ON CONSOLE
  803. ;
  804. PRINT:    LDAX    D
  805.     PUSH    PSW
  806.     ANI    7FH
  807.     CALL    TYPE
  808.     POP    PSW
  809.     ORA    A
  810.     RM
  811.     INX    D
  812.     JMP    PRINT
  813. ;.....
  814. ;
  815. ;
  816. ; FETCH CHARACTER FROM CONSOLE (WITHOUT ECHO)
  817. ;
  818. CINPUT: LHLD    BASE+1
  819.     MVI    L,9
  820.     CALL    GOHL
  821.     ANI    7FH
  822.     RET
  823. ;.....
  824. ;
  825. ; CHECK FOR A CTRL-C OR CTRL-S ENTERED FROM THE KEYBOARD.  JUMP TO EXIT
  826. ; IF CTRL-C, PAUSE ON CTRL-S.
  827. ;
  828. CKABRT: LHLD    BASE+1
  829.     MVI    L,6        ;CHECK STATUS OF KEYBOARD
  830.     CALL    GOHL        ;ANY KEY PRESSED?
  831.     ORA    A
  832.     RZ            ;NO, RETURN TO CALLER
  833.     CALL    CINPUT        ;GET CHARACTER
  834.     CPI    'C'-40H     ;CTL-C?
  835.     JZ    EX0        ;IF CTL-C THEN QUIT
  836.     CPI    'S'-40H     ;CTL-S?
  837.     RNZ            ;NO, RETURN TO CALLER
  838.     CALL    CINPUT        ;YES, WAIT FOR ANOTHER CHAR.
  839.     CPI    'C'-40H     ;MIGHT BE CTL-C
  840.     JZ    EX0        ;IF CTL-C, ELSE FALL THRU AND CONTINUE
  841.     RET
  842. ;.....
  843. ;
  844. ; KLUDGE TO ALLOW CALL TO ADDRESS IN HL
  845. ;
  846. GOHL:    PCHL
  847. ;
  848. ; ENTRY TO BDOS SAVING ALL EXTENDED REGISTERS
  849. ;
  850. CPM:    PUSH    B
  851.     PUSH    D
  852.     PUSH    H
  853.     CALL    BDOS
  854.     MOV    B,A        ;SAVE RETURN CODE
  855.     LDA    VERFLG        ;IS THIS 3.0?
  856.     CPI    30H
  857.     MOV    A,B
  858.     JC    CPM20        ;NO, EXIT NORMALLY
  859.     CPI    0FFH        ;IT IS 3.0 - WAS RETURN CODE FF?
  860.     JNZ    CPM20        ;NO, EXIT NORMALLY
  861.     MOV    A,H        ;3.0 AND A=FF - CHECK FOR ERROR CODE
  862.     ORA    A
  863.     JNZ    DSKERR        ;TRAP OUT IF WE GOT A PHYSICAL ERROR
  864.     MOV    A,B        ; ELSE CONTINUE NORMALLY
  865. ;
  866. CPM20:    POP    H
  867.     POP    D
  868.     POP    B
  869.     RET
  870. ;.....
  871. ;
  872. ;
  873. ; FOR FILE OUTPUT MODE, RETURN TO OLD USER AREA AND SET DMA FOR THE FILE
  874. ; OUTPUT BUFFER.
  875. ;
  876. SETFOP:    LDA    OLDUSR        ;GET USER NUMBER AT STARTUP
  877.     MOV    E,A
  878.     MVI    C,CURUSR
  879.     CALL    CPM        ;RESET THE OLD USER NUMBER
  880.     RET
  881. ;.....
  882. ;
  883. ;
  884. ; MOVE DISK BUFFER DMA TO DEFAULT BUFFER FOR DIRECTORY SEARCH OPERATIONS
  885. ; AND BDOS MEDIA CHANGE ROUTINES (NECESSARY FOR PRE-CP/M 2 SYSTEMS WHILE
  886. ; IN FILE OUTPUT MODE WITH AN ACTIVE BUFFER).
  887. ;
  888. SETSRC: LXI    D,BASE+80H
  889. ;
  890. SET2:    MVI    C,SETDMA
  891.     JMP    CPM
  892. ;.....
  893. ;
  894. ; COMPARE ROUTINE FOR SORT
  895. ;
  896. COMPR:    PUSH    H        ;SAVE TABLE ADDR
  897.     MOV    E,M        ;LOAD LOW ORDER
  898.     INX    H
  899.     MOV    D,M        ;LOAD HIGH ORDER
  900.     INX    H
  901.     MOV    C,M
  902.     INX    H
  903.     MOV    B,M
  904. ;
  905. ;
  906. ; BC, DE NOW POINT TO ENTRIES TO BE COMPARED
  907. ;
  908.     XCHG
  909.     MOV    E,A        ;GET COUNT
  910. ;
  911. CMPLP:    MOV    A,M
  912.     ANI    7FH
  913.     MOV    D,A
  914.     LDAX    B
  915.     ANI    7FH
  916.     CMP    D
  917.     INX    H
  918.     INX    B
  919.     JNZ    NOTEQL        ;QUIT ON MISMATCH
  920.     DCR    E        ;OR END OF COUNT
  921.     JNZ    CMPLP
  922. ;
  923. NOTEQL: POP    H
  924.     RET            ;COND CODE TELLS ALL
  925. ;.....
  926. ;
  927. ;
  928. ; SWAP ENTRIES IN THE ORDER TABLE
  929. ;
  930. SWAP:    LXI    B,ORDER-2    ;TABLE BASE
  931.     DAD    H        ;*2
  932.     DAD    B        ;+ BASE
  933.     XCHG
  934.     DAD    H        ;*2
  935.     DAD    B        ;+ BASE
  936.     MOV    C,M
  937.     LDAX    D
  938.     XCHG
  939.     MOV    M,C
  940.     STAX    D
  941.     INX    H
  942.     INX    D
  943.     MOV    C,M
  944.     LDAX    D
  945.     XCHG
  946.     MOV    M,C
  947.     STAX    D
  948.     RET
  949. ;.....
  950. ;
  951. ; NEW COMPARE ROUTINE
  952. ;
  953. COMPARE:LXI    B,ORDER-2
  954.     DAD    H
  955.     DAD    B
  956.     XCHG
  957.     DAD    H
  958.     DAD    B
  959.     XCHG
  960.     MOV    C,M
  961.     INX    H
  962.     MOV    B,M
  963.     XCHG
  964.     MOV    E,M
  965.     INX    H
  966.     MOV    D,M
  967.     XCHG
  968.     MOV    E,A        ;COUNT
  969. ;
  970. CMPLPE: MOV    A,M
  971.     ANI    7FH
  972.     MOV    D,A
  973.     LDAX    B
  974.     ANI    7FH
  975.     CMP    D
  976.     INX    B
  977.     INX    H
  978.     RNZ
  979.     DCR    E
  980.     JNZ    CMPLPE
  981.     RET
  982. ;.....
  983. ;
  984. ; ERROR EXIT
  985. ;
  986. ERXIT:    CALL    CRLF        ;SPACE DOWN
  987.     POP    D        ;GET POINTER TO MESSAGE STRING
  988.     CALL    PRINT        ;PRINT IT
  989.     LXI    D,ERRMS1    ;PRINT " ERROR"
  990.     CALL    PRINT
  991.     CALL    CRLF        ;SPACE DOWN
  992. ;
  993. ; EXIT - ALL DONE RESTORE STACK
  994. ;
  995. EXIT:    LDA    DOPFLG        ;CHECK MULTI DISK MODE
  996.     ORA    A
  997.     JNZ    EX0
  998.     CALL    CKABRT        ;CHECK FOR USER ABORT FIRST
  999.     MVI    A,HIDRV-LODRV    ;GET MAXIMUM DRIVE CODE TO SEARCH
  1000.     LXI    H,FCB        ;BUMP DIRECTORY FCB DRIVE CODE
  1001.     INR    M
  1002.     CMP    M        ;DOES NEXT DISK EXCEED MAXIMUM?
  1003.     JC    EX0
  1004.     JMP    NOOPT        ;SEARCH NEXT DISK IF MAXDR NOT TRUE
  1005. TMMSG    DB    CR,LF,LF,'Files Matched -',' '+80H
  1006. TCMSG:    DB    CR,LF,'Files Checked -',' '+80H
  1007. TLMSG:    DB    CR,LF,'Libraries Searched -',' '+80H
  1008. TFILES    DW    0
  1009. TLIBRA    DW    0
  1010. TMATCH    DW    0
  1011. ;
  1012. EX0:    LXI    D,TMMSG
  1013.     CALL    PRINT
  1014.     LHLD    TMATCH
  1015.     CALL    DECPRT
  1016.     LXI    D,TCMSG
  1017.     CALL    PRINT
  1018.     LHLD    TFILES
  1019.     CALL    DECPRT
  1020.     LXI    D,TLMSG
  1021.     CALL    PRINT
  1022.     LHLD    TLIBRA
  1023.     CALL    DECPRT
  1024.     MVI    C,CONST     ;CHECK CONSOLE STATUS
  1025.     CALL    CPM
  1026.     ORA    A        ;CHAR WAITING?
  1027.     MVI    C,RDCHR
  1028.     CNZ    CPM        ;GOBBLE UP CHAR
  1029.     LDA    VERFLG        ;OR ERROR MODE, DEPENDING ON VERSION
  1030.     CPI    30H
  1031.     JC    EXIT0
  1032.     MVI    C,45
  1033.     MVI    E,0        ;SET ERROR MODE BACK TO DEFAULT
  1034.     CALL    CPM
  1035.     JMP    EXIT1
  1036. ;
  1037. EXIT0:    LDA    DOPFLG        ;..if they were swapped
  1038.     ORA    A
  1039.     CZ    SWAPEM
  1040. ;
  1041. EXIT1:    LHLD    STACK        ;GET OLD STACK POINTER
  1042.     SPHL            ;MOVE BACK TO OLD STACK
  1043.     RET            ;..AND RETURN TO CCP
  1044. ;
  1045. VERERR    LXI    D,VERBAD    ;ABORT CP/M IS VERSION 1.?
  1046. VERER1    CALL    PRINT
  1047.     JMP    EXIT1
  1048. ;
  1049. NONERR    LXI    D,VERNAME    ;PRINT HELP INFO
  1050.     JMP    VERER1
  1051. ;.....
  1052. ;
  1053. ; TRAP BDOS SELECT AND SECTOR ERROR VECTORS TO OUR OWN INTERCEPT ROUTINE
  1054. ; SO WE CAN CATCH A REFERENCE TO AN ILLEGAL DRIVE.
  1055.  
  1056. SWAPEM: LDA    VERFLG        ;CHECK VERSION
  1057.     CPI    30H        ;SEE IF ERROR MODE CALL IS AVAILABLE
  1058.     JC    SWAP20        ;IF NOT, USE BDOS ERROR VECTORS
  1059.     MVI    C,45
  1060.     MVI    E,0FFH        ;USE SET ERROR MODE CALL
  1061.     CALL    CPM        ;SET "RETURN CODE ONLY" MODE
  1062.     RET
  1063. ;.....
  1064. ;
  1065. SWAP20: LHLD    BDOLOC        ;GET POINTER TO BASE OF BIOS
  1066.     MOV    A,L
  1067.     ORA    H
  1068.     JNZ    SWAPO0
  1069.     LXI    H,BASE+6    ;GET BDOS ADDRESS
  1070. SWAPO0:    MVI    L,9        ;SET POINTER TO ERROR VECTORS
  1071. ;
  1072. SWAPOK:    LXI    D,VECTBL    ;EXCHANGING WITH OUR OWN VECTOR TABLE
  1073.     MVI    A,4        ;4 BYTES TO SWAP
  1074. ;
  1075. SWAPLP: MOV    B,M        ;GET BYTE FROM HL
  1076.     XCHG
  1077.     MOV    C,M        ;GET BYTE FROM DE
  1078.     MOV    M,B        ;PUT BYTE FROM HL
  1079.     XCHG
  1080.     MOV    M,C        ;PUT BYTE FROM DE
  1081.     INX    H        ;BUMP EXCHANGE POINTERS
  1082.     INX    D
  1083.     DCR    A        ;DOCK COUNTER
  1084.     JNZ    SWAPLP        ;CONTINUE SWAPPING TIL DONE
  1085.     RET
  1086. ;.....
  1087. ;
  1088. ; RECOVERY POINT FROM INTERCEPTED BDOS SELECT AND BAD SECTOR ERRORS.
  1089. ;
  1090. DSKERR:    LXI    SP,STACK    ;GET OUT OF BDOS' STACK
  1091.     JMP    EXIT        ;..AND EXIT BACK TO CCP
  1092. ;
  1093. ;=======================================================================
  1094. ;
  1095. ;         SUBROUTINES TO READ LIBRARY FILE DIRECTORY
  1096. ;
  1097. ;=======================================================================
  1098. ;
  1099. PRTLMEM    LXI    H,SEARN+8
  1100.     CALL    CKLBR
  1101.     RZ
  1102.     LXI    H,ORDER     ;INITIALIZE ORDER TABLE POINTER
  1103.     SHLD    NEXTL
  1104. ;
  1105. ENTRYL:    LHLD    LCOUNT        ;GET FCB COUNT
  1106.     DCX    H        ;DECREMENT IT
  1107.     SHLD    LCOUNT
  1108.     MOV    A,H        ;IS THIS THE LAST FILE?
  1109.     ORA    L
  1110.     JZ    LBRTST        ;IF COUNT=0, LAST FILE SKIP COMPARE
  1111.     PUSH    B
  1112.     CALL    CKABRT        ;CHECK FOR ABORT CODE FROM KEYBOARD
  1113.     LHLD    NEXTL
  1114.     MVI    A,11
  1115.     CALL    COMPR        ;DOES THIS ENTRY MATCH NEXT ONE?
  1116.     POP    B
  1117.     JNZ    LBRTST        ;NO, PRINT IT
  1118.     INX    H
  1119.     INX    H        ;SKIP, HIGHEST EXTENT COMES LAST IN LIST
  1120.     SHLD    NEXTL
  1121.     JMP    ENTRYL        ;LOOP BACK FOR NEXT LOWEST EXTENT
  1122. ;
  1123. ; EXIT LIBRARY MEMBER PRINTING
  1124. ;
  1125. LBEXIT:    XRA    A        ;GET A ZERO TO...
  1126.     STA    SUPSPC        ;SUPPRESS LEADING SPACES IN TOTALS
  1127.     RET
  1128. ;.....
  1129. ;
  1130. ; VALID ENTRY OBTAINED - SPIT IT OUT.
  1131. ;
  1132. LBRTST: LHLD    NEXTL        ;GET ORDER TABLE POINTER
  1133.     MOV    E,M        ;GET LOW ORDER ADDRESS
  1134.     INX    H
  1135.     MOV    D,M        ;GET HIGH ORDER ADDRESS
  1136.     INX    H
  1137.     SHLD    NEXTL        ;SAVE UPDATED TABLE POINTER
  1138.     LXI    H,8
  1139.     DAD    D
  1140.     CALL    CKLBR
  1141.     JNZ    LBRNEX
  1142.     PUSH    D
  1143.     POP    H
  1144. ;
  1145. ; SAVES THE LIBRARY FILE NAME INTO LBRFCB
  1146. ;
  1147.     LDA    FCB
  1148.     LXI    D,LBRFCB    ;TO
  1149.     STAX    D
  1150.     INX    D
  1151.     MVI    B,11        ;LEN
  1152.     CALL    MOVE        ;DO THE MOVE
  1153.     XCHG
  1154.     MVI    B,25
  1155. ;
  1156. CLMFCB:    MVI    M,0
  1157.     INX    H
  1158.     DCR    B
  1159.     JNZ    CLMFCB
  1160.     CALL    SETLDMA
  1161.     LXI    D,LBRFCB    ;POINT TO FILE
  1162.     MVI    C,OPEN        ;GET FUNCTION
  1163.     CALL    CPM        ;OPEN IT
  1164.     MVI    C,READ
  1165.     LXI    D,LBRFCB
  1166.     CALL    CPM
  1167.     CALL    SETFOP
  1168.     LXI    H,LBBUF
  1169.     MOV    A,M
  1170.     ORA    A
  1171.     JZ    CKLDIR        ;CHECK DIRECTORY PRESENT?
  1172. ;
  1173. LMLEXI:    CALL    LBCLOSE
  1174. ;
  1175. ; DO NEXT LIBRARY FILE
  1176. ;
  1177. LBRNEX:    LHLD    LCOUNT        ;CHECK COUNT
  1178.     MOV    A,H
  1179.     ORA    L
  1180.     JZ    LBEXIT        ;NO MORE, ALL DONE
  1181.     JMP    ENTRYL        ;ELSE, GET NEXT .LBR FILE
  1182. ;
  1183. ; CLOSE THE LIBRARY FILE
  1184. ;
  1185. LBCLOSE:LXI    D,LBRFCB
  1186.     MVI    C,CLOSE
  1187.     CALL    CPM
  1188.     RET
  1189. ;.....
  1190. ;
  1191. ;
  1192. ; SET THE LIBRARY FILE DMA ADDERSS
  1193. ;
  1194. SETLDMA    LDA    NEWUSR        ;GET USER AREA FOR DIRECTORY
  1195.     MOV    E,A
  1196.     MVI    C,CURUSR    ;GET THE USER FUNCTION
  1197.     CALL    CPM        ;..AND SET NEW USER NUMBER
  1198.     LXI    D,LBBUF
  1199.     MVI    C,SETDMA
  1200.     CALL    CPM
  1201.     RET
  1202. ;.....
  1203. ;
  1204. ; CHECK TO SEE IF THERE INDEED IS A LBR FILE DIRECTORY AND BARF IF NOT!
  1205. ;
  1206. CKLDIR: MVI    B,11        ;LENGTH OF FILE NAME
  1207.     MVI    A,' '        ;SPACE
  1208.     INX    H
  1209. CKDLP:    CMP    M
  1210.     JNZ    LMLEXI
  1211.     DCR    B
  1212.     INX    H
  1213.     JNZ    CKDLP
  1214. ;
  1215. ; THE FIRST ENTRY IN THE LBR DIRECTORY IS INDEED BLANK.  NOW SEE IF THE
  1216. ; DIRECTORY SIZE IS >0
  1217. ;
  1218.     MOV    E,M        ;FILE STARTING LOCATION LOW
  1219.     INX    H        ;MUST BE ZERO HERE
  1220.     MOV    A,M        ;FILE STARTING LOCATION HIGH
  1221.     ORA    E        ;MUST BE ZERO HERE ALSO
  1222.     JNZ    LMLEXI
  1223.     INX    H
  1224.     MOV    E,M        ;GET LIBRARY SIZE LOW
  1225.     INX    H        ;POINT TO LIBRARY SIZE HIGH
  1226.     MOV    D,M        ;GET LIBRARY SIZE HIGH
  1227.     MOV    A,D
  1228.     ORA    E        ;LIBRARY MUST HAVE SOME SIZE
  1229.     JZ    LMLEXI
  1230.     DCX    D
  1231.     XCHG
  1232.     SHLD    SLFILE
  1233.     MVI    B,3
  1234.     LXI    H,17
  1235.     DAD    D
  1236.     PUSH    H
  1237.     LHLD    TLIBRA
  1238.     INX    H
  1239.     SHLD    TLIBRA
  1240.     POP    H
  1241.     JMP    LMTEST
  1242. ;
  1243. LFMLOP:    LHLD    SLFILE        ;GET
  1244.     MOV    A,L
  1245.     ORA    H
  1246.     JZ    LMLEXI
  1247.     DCX    H
  1248.     SHLD    SLFILE
  1249.     CALL    SETLDMA
  1250.     MVI    C,READ
  1251.     LXI    D,LBRFCB
  1252.     CALL    CPM
  1253.     CALL    SETFOP
  1254.     MVI    B,4        ;GET FILE COUNT PER SECTOR
  1255.     LXI    H,LBBUF     ;GET BUFFER STARTING ADDRESS
  1256. ;
  1257. LMTEST:    MOV    A,M        ;GET MEMBER OPEN FLAG
  1258.     ORA    A        ;TEST FOR OPEN
  1259.     JZ    PRMNAM
  1260. ;
  1261. LMTESA:    LXI    D,32        ;MEMBER NOT OPEN GET OFFSET
  1262.     DAD    D        ;TO NEXT AND ADD IT IN.
  1263.     DCR    B        ;IS BUFFER EMPTY ?
  1264.     JNZ    LMTEST        ;NO SO TEST NEXT ENTRY
  1265.     JMP    LFMLOP        ;YES GET NEXT BUFFER...
  1266. ;
  1267. PRMNAM:    PUSH    H        ;PRINT MEMBER NAME AND SIZE
  1268.     PUSH    B
  1269.     CALL    CKABRT        ;CHECK FOR ABORT CODE FROM KEYBOARD
  1270. PRMNA1:    POP    B
  1271.     POP    H
  1272.     PUSH    H
  1273.     PUSH    B
  1274.     INX    H
  1275.     PUSH    H
  1276.     LHLD    TFILES
  1277.     INX    H
  1278.     SHLD    TFILES
  1279.     POP    H
  1280.     CALL    COMPS        ;MATCH WHAT WE ARE LOOKING FOR ?
  1281.     JNZ    LBGNXT
  1282.     PUSH    H
  1283.     LHLD    TMATCH
  1284.     INX    H
  1285.     SHLD    TMATCH
  1286.     POP    H
  1287.     CALL    CRLF
  1288.     LDA    FCB        ;..precede new line with drive name
  1289.     ADI    'A'-1
  1290.     CALL    TYPE
  1291.     CALL    TYPUSR
  1292.     MVI    A,':'        ;tag header with a colon and a space
  1293.     CALL    TYPE        ;..and exit back to ENTRY
  1294.     MVI    A,' '
  1295.     CALL    TYPE
  1296.     MVI    B,8        ;FILE NAME LENGTH
  1297.     CALL    TYPEIT
  1298.     MVI    A,'.'        ;PERIOD AFTER FN
  1299.     CALL    TYPE
  1300.     MVI    B,3        ;DISPLAY 3 CHARACTERS OF FILETYPE
  1301.     CALL    TYPEIT
  1302.     INX    H
  1303.     INX    H
  1304.     MOV    E,M
  1305.     INX    H
  1306.     MOV    D,M
  1307.     XCHG
  1308. ;
  1309. ;
  1310. ; OUTPUT THE SIZE OF THE INDIVIDUAL FILE.
  1311. ;
  1312.     PUSH    D
  1313.     PUSH    H
  1314.     PUSH    H
  1315.     LHLD    LLENLOC
  1316.     PUSH    H 
  1317.     POP     D
  1318.     POP    H
  1319.     DAD    D
  1320.     SHLD    LLENLOC
  1321.     POP    H
  1322. ;
  1323. ; NEW CODE ADDED TO CONVERT LIB MEMBERS FROM SECTORS TO 'K'
  1324. ;
  1325. ; UPON ENTRY MEMBER'S SIZE IN SECTORS IS IN HL
  1326. ;
  1327.     XCHG            ;PUT IT IN DE
  1328.     LXI    H,0        ;ZERO OUT HL
  1329.     MOV    A,E        ;PUT LOW BYTE OF SECTOR COUNT IN A
  1330.     ADI    7        ;ADD SEVEN TO ALWAYS ROUND UP 1K
  1331.     RRC            ;CONVERT IT TO K
  1332.     RRC
  1333.     RRC
  1334.     ANI    1FH
  1335.     MOV    E,A        ;AND PUT IT BACK
  1336.     MOV    L,D        ;GET THE HIGH BYTE IF ANY
  1337.     MVI    D,0        ;CLEAN OUT THE OLD RESTING PLACE
  1338.     DAD    H        ;MULTIPLY IT BY 32 TO CONVERT TO
  1339.     DAD    H        ;NUMBER
  1340.     DAD    H        ;OF
  1341.     DAD    H        ;K
  1342.     DAD    H        ;BYTES
  1343.     DAD    D        ;AND ADD IN THE LOW BYTE 
  1344.     POP    D
  1345.     CALL    DECPRT        ;..GO PRINT IT
  1346.     MVI    A,'k'        ;..AND FOLLOW WITH SIZE
  1347.     CALL    TYPE
  1348.     LXI    H,INLBF
  1349.     MVI    B,4
  1350.     CALL    TYPEIT
  1351.     LXI    H,LBRFCB+1
  1352.     MVI    B,8        ;FILE NAME LENGTH
  1353.     CALL    TYPEIT
  1354.     MVI    A,'.'        ;PERIOD AFTER FN
  1355.     CALL    TYPE
  1356.     MVI    B,3        ;DISPLAY 3 CHARACTERS OF FILETYPE
  1357.     CALL    TYPEIT
  1358.     MVI    A,0FFH
  1359.     STA    FNDFLG        ;Set file found flag
  1360. ;
  1361. ;
  1362. ; AT LEAST ONE MORE FILE TO OUTPUT - CAN WE PUT IT ON THE CURRENT LINE?
  1363. ;
  1364. LBGNXT:    POP    B
  1365.     POP    H
  1366.     JMP    LMTESA        ;.. AND GO OUTPUT ANOTHER FILE
  1367. ;
  1368. COMPS    PUSH    H
  1369.     PUSH    D
  1370.     PUSH    B
  1371.     LXI    B,SEARN
  1372.     MVI    E,11
  1373. COMPS1    MOV    A,M
  1374.     ANI    7FH
  1375.     MOV    D,A
  1376.     LDAX    B
  1377.     INX    B
  1378.     INX    H
  1379.     ANI    7FH
  1380.     CPI    '?'
  1381.     JZ    COMPS2
  1382.     CMP    D
  1383.     JNZ    COMPS3
  1384. COMPS2    DCR    E
  1385.     JNZ    COMPS1
  1386. COMPS3    POP    B
  1387.     POP    D
  1388.     POP    H
  1389.     RET
  1390. ;
  1391. INLBF    DB    ' IN '
  1392. ;.....
  1393. ;
  1394. ;
  1395. ; MOVE CHARACTERS FROM 'HL' TO 'DE' LENGTH IN 'B'
  1396. ;
  1397. MOVE:    MOV    A,M        ;GET A CHARACTER
  1398.     STAX    D        ;STORE IT
  1399.     INX    H        ;TO NEXT 'FROM'
  1400.     INX    D        ;TO NEXT 'TO'
  1401.     DCR    B        ;MORE?
  1402.     JNZ    MOVE        ;YES, LOOP
  1403.     RET            ;NO, RETURN
  1404. ;.....
  1405. ;
  1406. ; TEST FILE EXTENT FOR LBR
  1407. ;
  1408. CKLBR:    PUSH    H
  1409.     PUSH    D
  1410.     PUSH    B
  1411.     XCHG
  1412.     LXI    H,LBRTYP
  1413.     MVI    C,3
  1414. ;
  1415. CKLBL:    LDAX    D
  1416.     ANI    7FH
  1417.     CMP    M
  1418.     JNZ    CKLBX
  1419.     INX    H
  1420.     INX    D
  1421.     DCR    C
  1422.     JNZ    CKLBL
  1423. CKLBX:    POP    B
  1424.     POP    D
  1425.     POP    H
  1426.     RET
  1427. ;.....
  1428. ;
  1429. LBRTYP:    DB    'LBR'
  1430. ;
  1431. ;
  1432. ;-----------------------------------------------------------------------
  1433. ;
  1434. ;            END OF PROGRAM CODE
  1435. ;
  1436. ;-----------------------------------------------------------------------
  1437. ;
  1438. ; INITIALIZED DATA AREA
  1439. ;
  1440. VERBAD:    DB    '+++ Needs CP/M 2.0 or Newer to RU','N'+80H
  1441. DREMSG: DB    '+++ Driv','e' OR 80H
  1442. ERRMS1: DB    ' '
  1443. ERRMS2: DB    'Erro','r' OR 80H
  1444. USRMSG: DB    'User ','#' OR 80H
  1445. NOFMS1:    DB    '+++ NO FILE ON '
  1446. NOFMS2: DB    ' ',':' OR 80H
  1447. ;
  1448. VECTBL: DW    DSKERR        ;BDOS SECTOR ERROR INTERCEPT VECTOR
  1449.     DW    DSKERR        ;BDOS SELECT ERROR INTERCEPT VECTOR
  1450. DOPFLG    DB    0
  1451. ;
  1452. ;=======================================================================
  1453. ;
  1454. ;        UNINITIALIZED DATA AREA
  1455. ;
  1456. ;=======================================================================
  1457. ;
  1458. BASUSR:    DB    0        ;DUPE OF ORIGINAL DIR. USER # TO SEARCH
  1459. BLKMAX:    DW    0        ;HIGHEST BLOCK # ON DRIVE
  1460. BLKMSK:    DB    0        ;SEC/BLK - 1
  1461. BLKSHF:    DB    0        ;# SHIFTS TO MULT BY SEC/BLK
  1462. COUNT:    DW    0        ;ENTRY COUNT
  1463. DIRMAX:    DW    0        ;HIGHEST FILE # IN DIRECTORY
  1464. GAP:    DW    0        ;SORT ROUTINE STORAGE
  1465. HITRAP:    DB    0        ;HIGHLIT TRAP (PREVIOUSLY TYPED CHAR)
  1466. I:    DW    0        ;SORT ROUTINE STORAGE
  1467. J:    DW    0        ;SORT ROUTINE STORAGE
  1468. JG:    DW    0        ;SORT ROUTINE STORAGE
  1469. LZFLG:    DB    0        ;0 WHEN PRINTING LEADING ZEROS
  1470. MAXUSR:    DB    0        ;MAX USER # FOR DRIVE FROM LOOKUP TABLE
  1471. NEWUSR:    DB    0        ;CONTAINS USER # SELECTED BY "$U" OPTION
  1472. NEXTT:    DW    0        ;NEXT TABLE ENTRY
  1473. OLDDSK:    DB    0        ;HOLDER FOR CURRENTLY LOGGED-IN DRIVE
  1474. OLDUSR:    DB    0        ;CONTAINS USER NUMBER UPON INVOCATION
  1475. SCOUNT:    DW    0        ;# TO SORT
  1476. SUPSPC:    DB    0        ;LEADING SPACE FLAG FOR DECIMAL ROUTINE
  1477. TBLOC:    DW    0        ;POINTER TO START OF NAME TABLE
  1478. TEMP:    DW    0        ;SAVE DIR ENTRY
  1479. VERFLG:    DB    0        ;CX/M VERSION NUMBER (0=PRE-CP/M 2)
  1480. FNDFLG    DB    0        ;File found flag
  1481. LLENLOC:DW    0        ;RUNNING TOTAL OF .LBR LENGTH
  1482. LCOUNT:    DW    0
  1483. NEXTL:    DW    0
  1484. SLFILE:    DW    0
  1485. SEARN    DS    11        ;HOLDING AREA FOR SEARCH NAME
  1486. LBRFCB: DS    36
  1487. LBBUF:    DS    80H
  1488. ;
  1489.     DS    80H        ;STACK AREA
  1490. STACK:    DS    2        ;SAVE OLD STACK POINTER HERE
  1491. ;
  1492. ORDER:    EQU    $        ;ORDER TABLE STARTS HERE
  1493. ;
  1494. ;
  1495.     END
  1496.