home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / cpm3 / zfile3p.lbr / ZFILE3.AZM / ZFILE3.ASM
Assembly Source File  |  1987-07-25  |  35KB  |  1,543 lines

  1.  
  2. ; ZFILE.ASM - Searches for file names (rename to FILE.ASM) - 07/17/87
  3. ;
  4. VERS    EQU    3        ; Version number
  5. ;
  6.     ASEG            ; Needed for M80, disregard otherwise
  7.     ORG    0100H
  8. ;
  9. ;
  10.     JMP    START
  11. ;
  12. ;
  13. ; ZFILE looks  on all permitted  drives and user areas    for one or more
  14. ; requested files.  Wild cards may  be used.  It usually  works best to
  15. ; use just 1-2-3 characters and complete  the file name with wildcards.
  16. ; The file you    are looking for may be spelled a little  differently or
  17. ; it may have been updated or there might be several  versions on line.
  18. ; To use:
  19. ;           A>FILE *.DOC,FI1*.*,FI*.COM,FILE3.TXT(,etc.)
  20. ;
  21. ; Max drive and max user that will be searched are automatically set if
  22. ; using a WHEEL byte with USEZCPR set YES, and the associated addresses
  23. ; below are remotely supplied by the BBS or RCPM system.  If USEZCPR is
  24. ; set NO, you can still use a wheel byte to limit the user to the areas
  25. ; set manually at MAXDRV and MAXUSR.  For private systems with no WHEEL
  26. ; byte set  SYSFILE to YES  if you wish to include systems files, these
  27. ; are automatically included when the WHEEL byte is set for remote use.
  28. ;
  29. ; The file may be aborted with 'c C ^C', 'x X ^X or 'k K ^K'.  's S ^S'
  30. ; to pause, and non-abort key to resume.
  31. ;
  32. ; The program automatically commences at A0: regardless of the drive or
  33. ; user area from which it is requested.  Suggest you rename the program
  34. ; FILE.COM when placing on your system.  (It is called ZFILE here since
  35. ; there are numerous other similar programs available most of which are
  36. ; considerably slower in operation.) Try this one, you will be very im-
  37. ; pressed with its speed.  ZFILE.COM is 16 records, 2k in length.
  38. ;
  39. ; (If using ZCPR3, there are two lines commencing with ;; and ending in
  40. ; '*** ZCPR3 ?' that you can easily find  that may need to be activated
  41. ; for your particular  system.    Just remove the two ;; and reassemble.)
  42. ;
  43. ;                    - notes by Irv Hoff W6FFC
  44. ;
  45. ;-----------------------------------------------------------------------
  46. ;
  47. ; 07/17/87  Rewrote the abort and pause routines.  Previously needed two
  48. ;    v3     consecutive CTL-C to abort or two CTL-S to pause.  Now works
  49. ;        properly.  Pauses with 's S ^S', aborts with a message with:
  50. ;        'c C ^C', 'k K ^K' or 'x X ^X', in keeping    with other pgms.
  51. ;        (A pause or abort also only stops at the end of the  current
  52. ;        line, not in  the middle  of a word, or just anywhere on the
  53. ;        line, etc.)  Also returns directly to CCP when finished now,
  54. ;        instead of requiring a warm reboot which was  unecessary and
  55. ;        wasted time on an otherwise super-fast program.  As no writ-
  56. ;        is done to the disk this is acceptable.  Per a suggestion by
  57. ;        Paul Foote, added a 3rd "skip drive" equate, which is needed
  58. ;        by some computers such as his Xerox. Fixed an obscure bug in
  59. ;        the CONTIN area reported by Bill Duerr.  He was also helpful
  60. ;        in testing this version and pointing out some typos.  It now
  61. ;        can properly handle files up to 8 Mb.   ZFILE2 was duplicat-
  62. ;        ing files names if over 512k long.    Thanks to Joe Wright for
  63. ;        this fix as well as extensive disucssions on how the program
  64. ;        should work.  17 records object code when assembled.  Built-
  65. ;        in help guide.        - Irv Hoff
  66. ;                      PRACSA RCPM
  67. ;
  68. ; 12/22/85  Removed the external macros, eliminated the need for special
  69. ;    v2     macro assemblers  with linking loaders.  Systems files auto-
  70. ;        matically included with  WHEEL  byte set, or for private use
  71. ;        if not using ZCPR, if SYSFILE has been set YES.  (This still
  72. ;        permits RCPM use without ZCPR/ZCMD.)  Several subtle changes
  73. ;        in the display  to better  isolate and clarify the    results.
  74. ;        Program completely reorganized with all subroutines and data
  75. ;        areas alphabetized for easy location.  Help guide rewritten.
  76. ;                    - Irv Hoff
  77. ;
  78. ; 12/14/85  First issue of ZFILE, based  upon the ZCPR3 utility FINDF by
  79. ;    v1     Richard Conn.  This variation  was created for  RAS/RCPM use
  80. ;        by standard  CP/M computers  (non-ZCPR3).  Uses std. BYE/KMD
  81. ;        dynamic max. drive/max. user/wheel locations  in low memory.
  82. ;        Added ^X abort, ^S to stop    scroll, wheel check  to allow or
  83. ;        disallow systems files, SKIP1 and SKIP2 equ's to allow skip-
  84. ;        ping drives if  needed.  Minor format  changes  to eliminate
  85. ;        unecessary scrolling if no files  found.  Assemble using M80
  86. ;        with .LIB files included.    - Norman Beeler
  87. ;                      ZeeMachine RAS
  88. ;                      408-245-1420
  89. ;
  90. ;-----------------------------------------------------------------------
  91. ;
  92. ; System equates:
  93. ;
  94. NO    EQU    0
  95. YES    EQU    NOT NO
  96.  
  97.  
  98. USEZCPR    EQU    YES        ;*Yes, if using ZCPR for MAXUSR, MAXDRV
  99. SYSFILE    EQU    NO        ;*To include systems files with no WHEEL
  100.                 ; (May be YES or NO if USEZCPR is YES)
  101. ;
  102. ; The following two should be selected for your system if USEZCPR is NO
  103. ;
  104. MAXDRV    EQU    'B'-40H        ; Highest drive used if not USEZCPR
  105. MAXUSR    EQU    15        ; Highest user area used if not USEZCPR
  106. ;
  107. MAXDRIV    EQU    3DH        ; ZCPR location of MAXDRIV byte
  108. WHEEL    EQU    3EH        ; Location of ZCPR's wheel flag
  109. MAXUSER    EQU    3FH        ; ZCPR location of MAXUSR byte
  110. ;
  111. ; General equates
  112. ;
  113. BOOT    EQU    0000H        ; CP/M warm boot jump vector
  114. BDOS    EQU    0005H        ; CP/M BDOS call jump vector
  115. TBUFF    EQU    0080H        ; Disk I/O buffer
  116. FCB    EQU    005CH        ; Default file control block
  117.  
  118. BELL    EQU    07H        ; Bell
  119. BS    EQU    08H        ; Backspace
  120. CR    EQU    0DH        ; CTL-M for carriage return
  121. CTLC    EQU    03H        ; Abort
  122. CTLS    EQU    13H        ; Pause
  123. CTLX    EQU    18H        ; Abort
  124. LF    EQU    0AH        ; CTL-J for line feed
  125. NULL    EQU    00H        ; Null character
  126. TAB    EQU    09H        ; Tab
  127. ;
  128. ; The following equ's allow skipping up to three drives, enter 0FFH for
  129. ; no skipping.
  130. ;
  131. SKIP1    EQU    0FFH        ; A=0,B=1,E=4,etc
  132. SKIP2    EQU    0FFH        ; F=5
  133. SKIP3    EQU    0FFH        ; G=6
  134. ;
  135. ; The following two bytes are at addresses 0103H and 0104H and may be
  136. ; set by DDT without needing to edit, assemble and reload.  (Save 8
  137. ; pages for 2k.)
  138. ;
  139. MXUSR:    DB    MAXUSR        ; Runtime maximum user area available
  140. MXDRV:    DB    MAXDRV        ; Runtime maximum drive available;
  141. ;
  142. ;-----------------------------------------------------------------------
  143. ;
  144. ;            Start of program
  145. ;
  146. ;-----------------------------------------------------------------------
  147. ;
  148. START:    LXI    H,0        ; Save stack pointer
  149.     DAD    SP
  150.     SHLD    STACK
  151.     LXI    SP,STACK
  152.  
  153.     LXI    H,BUFTBL
  154.     SHLD    FNTAB        ; File name table
  155.     LXI    D,1024        ; 1k space
  156.     DAD    D
  157.     SHLD    SCRATCH        ; Beginning of scratch area
  158.  
  159.      IF    USEZCPR
  160.     LDA    MAXDRIV        ; Get from ZCPR/ZCMD
  161.     INR    A        ; Make things come out right
  162.     STA    MXDRV
  163.     LDA    MAXUSER        ; Get from ZCPR/ZCMD
  164.     DCR    A        ; Make things come out right
  165.     STA    MXUSR        ; Save it
  166.      ENDIF            ; USEZCPR
  167.  
  168.     CALL    GTBIOS        ; Get BIOS jump table
  169.     CALL    HELLO        ; Sign on message
  170.     CALL    HELPCHK        ; Check for and print help message
  171.     CALL    OPTCHK        ; Process options, build file name table
  172.     CALL    CRLF        ; New line
  173.     CALL    FIND        ; Do the searches
  174.     CALL    BYE        ; Sign off message
  175.  
  176. EXIT:    LDA    NEWCR
  177.     ORA    A
  178.     CNZ    CRLF
  179.     LHLD    STACK        ; Get CCP return address
  180.     SPHL
  181.     RET
  182. ;
  183. ;-----------------------------------------------------------------------
  184. ;
  185. ;          S  U    B  R  O  U  T  I  N  E    S
  186. ;
  187. ;-----------------------------------------------------------------------
  188. ;
  189. ; Output character in A via BDOS call
  190. ;
  191. BOUT:    PUSH    H        ; Save registers
  192.     PUSH    D
  193.     PUSH    B
  194.     PUSH    PSW
  195.     MVI    C,2
  196.     MOV    E,A        ; Put the character into the 'E" reg.
  197.     CALL    BDOS
  198.     POP    PSW        ; Restore the character
  199.     POP    B
  200.     POP    D
  201.     POP    H
  202.     RET
  203. ;.....
  204. ;
  205. ; Sign off
  206. ;
  207. BYE:    LDA    FFLAG        ; Get 'file found' flag
  208.     ORA    A        ; No files found?
  209.     JNZ    EXIT
  210.     CALL    PRINT
  211.     DB    BS,BS,BS,' [no files found]',0
  212.     JMP    EXIT
  213. ;.....
  214. ;
  215. ; Check for a CTL-C or CTL-S entered from the keyboard.  Jump to EXIT if
  216. ; CTL-C, pause on CTL-S.
  217. ;
  218. CKABRT:    PUSH    H
  219.     PUSH    D
  220.     PUSH    B
  221.     MVI    C,11
  222.     CALL    BDOS
  223.     ORA    A
  224.     JZ    CKAB3        ; No character, exit
  225.  
  226.     MVI    C,1
  227.     CALL    BDOS
  228.     ANI    5FH
  229.     CPI    'S'-40H
  230.     JZ    CKAB0
  231.     CPI    'S'
  232.     JNZ    CKAB1
  233.     CALL    CKAB4
  234.  
  235. CKAB0:    MVI    C,1
  236.     CALL    BDOS
  237.     ANI    5FH
  238.  
  239. CKAB1:    CPI    'C'-40H        ; CTL-C?
  240.     JZ    CKAB2        ; Yes, quit
  241.     CPI    'K'-40H
  242.     JZ    CKAB2
  243.     CPI    'X'-40H
  244.     JZ    CKAB2
  245.     CPI    ' '        ; Any other CTL-character, abort
  246.     JC    CKAB3
  247.     CALL    CKAB4        ; Clear the character from screen
  248.     CPI    'C'
  249.     JZ    CKAB2
  250.     CPI    'K'
  251.     JZ    CKAB2
  252.     CPI    'X'
  253.     JNZ    CKAB3
  254.  
  255. CKAB2:    MVI    C,9
  256.     LXI    D,CKMS1
  257.     CALL    BDOS
  258.     POP    B
  259.     POP    D
  260.     POP    H
  261.     LHLD    STACK
  262.     SPHL
  263.     RET
  264.  
  265. CKAB3:    POP    B
  266.     POP    D
  267.     POP    H
  268.     RET
  269.  
  270. CKAB4:    PUSH    PSW
  271.     MVI    C,9
  272.     LXI    D,CKMS2
  273.     CALL    BDOS
  274.     POP    PSW
  275.     RET
  276. ;.....
  277. ;
  278. ; Console input routine.
  279. ;
  280. CIN:    PUSH    B        ; Save the registers
  281.     PUSH    D
  282.     PUSH    H
  283.     LHLD    BOOT+1        ; Jump table address
  284.     MVI    L,9        ; Console input address
  285.     LXI    D,CIN1        ; Set up return address on stack
  286.     PUSH    D
  287.     PCHL
  288.  
  289. CIN1:    POP    H        ; Restore the registers
  290.     POP    D
  291.     POP    B
  292.     RET
  293. ;.....
  294. ;
  295. ; Console output routine with control character processing.  Output the
  296. ; character in 'A' to the console, affects no registers or flags.
  297. ;
  298. CCOUT:    CPI    ' '        ; See if a printing character
  299.     JNC    COUT        ; If yes, handle normally
  300. ;
  301. ; Trap out <NULL>, <BEL>, <BS>, <LF>, <CR>
  302. ;
  303.     CPI    NULL        ; <NULL>
  304.     JZ    COUT
  305.     CPI    BELL        ; <BEL>
  306.     JZ    COUT
  307.     CPI    BS        ; <BS>
  308.     JZ    COUT
  309.     CPI    LF        ; <LF>
  310.     JZ    COUT
  311.     CPI    CR        ; <CR>
  312.     JZ    COUT
  313. ;
  314. ; Print as CTL-character
  315. ;
  316.     PUSH    PSW        ; Save the character
  317.     MVI    A,'^'        ; Print and 'up arrow' character'
  318.     CALL    COUT
  319.     POP    PSW        ; Get the character
  320.     PUSH    PSW        ; Save it again, now that we have it
  321.     ADI    40H        ; Convert from binary to ASCII
  322.     CALL    COUT        ; Display the character
  323.     POP    PSW        ; Restore the original character
  324.     RET
  325. ;.....
  326. ;
  327. ; Checks the current 4 directory entries against argument.  If match,
  328. ; rewrites record with reactivated 1st bytes.
  329. ;
  330. CHKENT:    MVI    B,4        ; Number of entries per record
  331.     LXI    H,TBUFF        ; Beginning of buffer
  332.  
  333. CKLUP:    PUSH    B
  334.     MOV    A,M
  335.     CPI    0E5H        ; Check for unused
  336.     JZ    CKINC
  337.     XRA    A        ; A=0
  338.     STA    CLPFLG        ; Set flag for no entries found
  339.     LDA    FNCOUNT        ; Get number of file names to check
  340.     MOV    B,A        ; In B
  341.     PUSH    H
  342.     LHLD    FNTAB        ; Point to table
  343.     XCHG            ; In DE
  344.     POP    H
  345.  
  346. CKLUP1:    PUSH    B        ; Save count
  347.     PUSH    H        ; Save beginning address
  348.     PUSH    D
  349.     CALL    COMPAR        ; Compare with argument and save if match
  350.     POP    D
  351.     LXI    H,11        ; Point to next entry
  352.     DAD    D
  353.     XCHG
  354.     POP    H
  355.     POP    B
  356.     DCR    B        ; Count down
  357.     JNZ    CKLUP1
  358.  
  359. CKINC:    POP    B
  360.     LXI    D,32        ; Length of entry
  361.     DAD    D
  362.     DCR    B
  363.     JNZ    CKLUP
  364.     LHLD    DIRMAX
  365.     DCX    H        ; Reduce records left
  366.     SHLD    DIRMAX
  367.     LHLD    RECORD        ; Point to next record
  368.     INX    H
  369.     SHLD    RECORD
  370.     XCHG
  371.     LHLD    MAXREC        ; Reached limit?
  372. ;;;    inx    h        ; One more            **** ZCPR3
  373.     MOV    A,H        ; Check high
  374.     CMP    D
  375.     RNZ
  376.     MOV    A,L        ; Check low
  377.     CMP    E
  378.     RNZ
  379.     LHLD    TRACK        ; Next track
  380.     INX    H
  381.     SHLD    TRACK
  382. ;;;    lxi    h,1        ; First record of next track *** ZCPR3
  383.     LXI    H,0
  384.     SHLD    RECORD
  385.     RET
  386. ;.....
  387. ;
  388. ; Compare directory entry pointed to by HL with that pointed to by DE.
  389. ; No net effect on HL or DE.  Return with carry set means DE<HL.  Return
  390. ; with zero set means DE=HL.  Compare by file name, file type, extension
  391. ; and user number (in that order).
  392. ;
  393. CMP$ENTRY:
  394.     PUSH    H
  395.     PUSH    D
  396.     INX    H        ; Point to filename
  397.     INX    D
  398.     MVI    B,11        ; Compare filename and filetype
  399.     CALL    COMP
  400.     POP    D
  401.     POP    H
  402.     RNZ
  403.     LDAX    D        ; Compare user number
  404.     CMP    M
  405.     RET
  406. ;.....
  407. ;
  408. ; Compare 11 bytes of directory entry against argument; RNZ if not
  409. ; matched.  DE points to table entry to compare to.
  410. ;
  411. COMPAR:    LDA    CLPFLG        ; Get found flag
  412.     ORA    A        ; 0=no
  413.     RNZ
  414.     SHLD    TEMP        ; Hold pointer in case of match
  415.     INX    H
  416.     XCHG
  417.     MVI    B,11
  418.  
  419. CMPR1:    LDAX    D        ; Get directory entry character
  420.     ANI    7FH        ; Strip any flags
  421.     CMP    M
  422.     JZ    CMPR2
  423.     MOV    A,M
  424.     CPI    '?'
  425.     RNZ
  426.  
  427. CMPR2:    INX    D
  428.     INX    H        ; Bump to next character
  429.     DCR    B
  430.     JNZ    CMPR1        ; Loop for 11 characters
  431.     PUSH    D        ; Save entry pointer
  432.     LDAX    D        ; Get extent in B
  433.     MOV    B,A
  434.     LDA    EXTENT        ; Get extent mask
  435.     CMP    B
  436.     POP    D        ; Get entry pointer
  437.     JC    CMPR6        ; No match
  438. ;
  439. ; Check to insure REEL number is zero
  440. ;
  441.     PUSH    D        ; Save DE
  442.     INX    D        ; S1
  443.     INX    D        ; S2
  444.     LDAX    D        ; Get it
  445.     POP    D        ; Restore DE
  446.     ORA    A        ; S2 must be zero
  447.     JNZ    CMPR6        ; No match
  448.  
  449.     LDA    SYSTEM        ; Include system files?
  450.     ORA    A        ; 0=no
  451.     JNZ    CMPR3
  452.     DCX    D        ; Back up 2 bytes
  453.     DCX    D
  454.     LDAX    D        ; Get T2
  455.     ANI    80H        ; Check high bit set for system file
  456.     RNZ
  457.  
  458. CMPR3:    LHLD    TEMP        ; Check for user limit
  459.     LDA    WHEEL        ; Get wheel byte
  460.     CPI    0        ; Check if set
  461.     JNZ    CMPR4        ; Don't limit if wheel
  462.     LDA    MXUSR        ; Maximum user
  463.     JMP    CMPR5
  464.  
  465. CMPR4:    MVI    A,15        ; Don't limit wheels
  466.  
  467. CMPR5:    CMP    M        ; Beyond maximum?
  468.     JC    CMPR6
  469.     LHLD    FCOUNT        ; Increment count
  470.     INX    H
  471.     SHLD    FCOUNT
  472.     LHLD    DSTART        ; Get ptr to next entry
  473.     XCHG
  474.     LHLD    TEMP
  475.     MVI    B,12        ; Copy entry
  476.     CALL    MOVE
  477.     XCHG
  478.     SHLD    DSTART        ; Ptr to next entry
  479.     XCHG
  480.     LHLD    BDOS+1        ; Check for memory overflow
  481.     MOV    A,H
  482.     SUI    10        ; Below CCP
  483.     CMP    D        ; Point beyond limit?
  484.     JC    MOVFL
  485.     MVI    A,0FFH        ; Set found flag
  486.     STA    FFLAG
  487.     XRA    A
  488.     RET            ; Returns 'zero' flag set for match
  489.  
  490. CMPR6:    MVI    A,0FFH        ; No match
  491.     ORA    A
  492.     RET
  493. ;.....
  494. ;
  495. ; Compares DE with HL for B bytes; returns with carry set if DE<HL.
  496. ; MSB is disregarded.
  497. ;
  498. COMP:    MOV    A,M        ; Get (HL)
  499.     ANI    7FH        ; Mask MSB, put into 'C' reg
  500.     MOV    C,A
  501.     LDAX    D        ; Compare
  502.     ANI    7FH        ; Mask MSB
  503.     CMP    C
  504.     RNZ
  505.     INX    H        ; Point to next
  506.     INX    D
  507.     DCR    B        ; Count down
  508.     JNZ    COMP
  509.     RET
  510. ;....
  511. ;
  512. ; As COMP, but match on '?' pointed to by HL
  513. ;
  514. COMP2:    MOV    A,M        ; Get (HL)
  515.     ANI    7FH        ; Mask MSB
  516.     CPI    '?'        ; Match '?'
  517.     JZ    COMP3
  518.     MOV    C,A        ; In 'C'
  519.     LDAX    D        ; Compare
  520.     ANI    7FH        ; Mask MSB
  521.     CMP    C
  522.     RNZ
  523.  
  524. COMP3:    INX    H        ; Point to next
  525.     INX    D
  526.     DCR    B        ; Count down
  527.     JNZ    COMP2
  528.     RET
  529. ;.....
  530. ;
  531. CONTIN:
  532.     MOV    C,A
  533.     MVI    E,0
  534.     CALL    SELDSK        ; Make sure drive is selected
  535.     MOV    A,H
  536.     ORA    L
  537.     RZ            ; Error return
  538.  
  539.     SHLD    DPH        ; Save the address
  540.     LXI    D,10        ; Point to DPB
  541.     DAD    D
  542.     MOV    E,M        ; Get DPB address in HL
  543.     INX    H
  544.     MOV    D,M
  545.     XCHG
  546.     MOV    E,M        ; Number of records/track
  547.     INX    H        ; As 2-byte quantity in DE
  548.     MOV    D,M
  549.     INX    H
  550.     XCHG
  551.     SHLD    MAXREC        ; Set maximum records/track
  552.     XCHG
  553.     INX    H
  554.     INX    H
  555.     MOV    A,M        ; Get EXM
  556.     STA    EXTENT
  557.     INX    H        ; Point to DRM
  558.     INX    H
  559.     INX    H
  560.     MOV    E,M        ; Get number of
  561.     INX    H        ; Directory entries
  562.     MOV    D,M
  563.     XCHG
  564.     INX    H        ; Account for - 1
  565.     SHLD    DSTART        ; Save number of directory entries
  566.     CALL    SHFHL2        ; Shift 'HL' right 2
  567.     SHLD    DIRMAX        ; Save number directory records
  568.     LXI    H,5        ; Now point to system
  569.     DAD    D        ; Track offset
  570.     MOV    A,M        ; Pick up number
  571.     INX    H
  572.     MOV    H,M
  573.     MOV    L,A
  574.     SHLD    TRACK
  575.     LXI    H,0
  576.     SHLD    RECORD
  577.     LDA    ECOUNT        ; Last new line?
  578.     ANI    3
  579.     CNZ    CRLF
  580.     LDA    ECOUNT
  581.     ORA    A
  582.     CNZ    CRLF
  583.     CALL    PRINT
  584.     DB    CR,'Disk ',0
  585.     LDA    FCB
  586.     ADI    'A'
  587.     STA    NEWCR
  588.     CALL    BOUT
  589.     CALL    PRINT
  590.     DB    ' -- ',0    ; ** CR,LF,0
  591.     LHLD    SCRATCH        ; Point to scratch area
  592.     SHLD    ORDER        ; Address of order table
  593.     XCHG
  594.     LHLD    DSTART        ; Get number of directory entries
  595.     DAD    H        ; Double for # of bytes in order table
  596.     DAD    D        ; Point to first byte of DIRBUF
  597.     SHLD    DIRBUF        ; Set pointer
  598.     SHLD    DSTART        ; Set loop pointer
  599.     LXI    H,0        ; Set file count
  600.     SHLD    FCOUNT
  601.     XRA    A        ; Set count
  602.     STA    ECOUNT
  603.     CMA            ; Flip
  604.     ORA    A        ; Ok to continue
  605.     RET
  606. ;.....
  607. ;
  608. ; Console output routine, sends character in 'A' register to console.
  609. ;
  610. COUT:    PUSH    PSW
  611.     PUSH    B        ; Save registers
  612.     PUSH    D
  613.     PUSH    H
  614.     MOV    C,A
  615.     LHLD    BOOT+1        ; Jump table address
  616.     MVI    L,12        ; Console output address
  617.     LXI    D,COUT1        ; Set up return address on stack
  618.     PUSH    D
  619.     PCHL
  620.  
  621. COUT1:    POP    H        ; Restore registers
  622.     POP    D
  623.     POP    B
  624.     POP    PSW        ; Restore the character
  625.     RET
  626. ;.....
  627. ;
  628. ; Print CR and LF on the console, affects no registers
  629. ;
  630. CRLF:    PUSH    PSW        ; Save the character
  631.     MVI    A,CR
  632.     CALL    COUT
  633.     MVI    A,LF
  634.     CALL    COUT
  635.     POP    PSW        ; Restore the original character
  636.     RET
  637. ;.....
  638. ;
  639. ; Console status routine
  640. ;
  641. CST:    PUSH    B        ; Save the registers
  642.     PUSH    D
  643.     PUSH    H
  644.     LHLD    BOOT+1        ; Jump table address
  645.     MVI    L,6        ; Console status address
  646.     LXI    D,CST1        ; Set up return address on stack
  647.     PUSH    D
  648.     PCHL
  649.  
  650. CST1:    CMA            ; Invert the flags
  651.     ANI    1        ; Set flags, 0 = RDA
  652.     POP    H        ; Restore the registers
  653.     POP    D
  654.     POP    B
  655.     RET
  656. ;.....
  657. ;
  658. DELCHK:    ORA    A        ; End of line?
  659.     RZ
  660.     CPI    '.'        ; End of field?
  661.     RZ
  662.     CPI    ','        ; End of entry?
  663.     RZ
  664.     CPI    ' '
  665.     RET
  666. ;.....
  667. ;
  668. ; Alphabetize directory pointed to by HL; BC contains the number of
  669. ; files in the directory
  670. ;
  671. DIRALPHA:
  672.     LHLD    FCOUNT        ; Get file count
  673.     MOV    A,H        ; Any files?
  674.     ORA    L
  675.     RZ
  676.  
  677.     SHLD    NUMBR        ; Set "N"
  678.     MOV    B,H        ; BC=count
  679.     MOV    C,L
  680.     LHLD    DIRBUF        ; Point to directory
  681.     JMP    SORT
  682. ;.....
  683. ;
  684. ; Fatal error, internal error, pointer table not consistent.
  685. ;
  686. FERR$PTR:
  687.     CALL    PRINT
  688.     DB    CR,LF,'DIRALPHA -- pointer error',0
  689.     JMP    EXIT
  690. ;.....
  691. ;
  692. ; Look through the directory
  693. ;
  694. FIND:    XRA    A        ; Select first disk
  695.     STA    FCB
  696.  
  697. FIND1:    CALL    NXTDISK        ; Get info the first time
  698.     RZ            ; Abort if error
  699.     CALL    CKABRT        ; Want to abort now?
  700.  
  701. FIND2:    CALL    NXTREC        ; Get a directory record
  702.     JZ    FIND3        ; Returns zero flag if no more
  703.     CALL    CHKENT        ; Check it out
  704.     JMP    FIND2        ; Keep it up till done
  705.  
  706. FIND3:    CALL    CKABRT        ; Want to abort now?
  707.     CALL    DIRALPHA    ; Sort entries
  708.     CALL    CKABRT        ; Want to abort now?
  709.     CALL    PRFILES        ; Print sorted entries
  710.     LDA    FCB        ; Next disk
  711.     INR    A
  712.     STA    FCB
  713.     CALL    NXTDISK        ; Select next disk
  714.     JMP    FIND1
  715. ;.....
  716. ;
  717. ; Get BIOS jump vectors for easy reference
  718. ;
  719. GTBIOS:    LHLD    BOOT+1        ; Points to BIOS jump TABLE+3
  720.     LXI    D,WBOOT        ; Where we will keep a copy
  721.     MVI    B,16*3        ; Move 48 bytes and fall thru to move
  722.     JMP    MOVE
  723. ;.....
  724. ;
  725. GETFN:    PUSH    D        ; Fill target FCB
  726.     MVI    B,11        ; 11 bytes
  727.     MVI    A,' '        ; Space fill
  728.  
  729. GETFN0:    STAX    D        ; Put space
  730.     INX    D
  731.     DCR    B
  732.     JNZ    GETFN0
  733.     POP    D        ; Point to entry again
  734.     CALL    SCANCOL        ; Scan for colon
  735.     MVI    B,8        ; 8 characters maximum for filename
  736.     CALL    GETFN1        ; Get and fill entry
  737.     MOV    A,M        ; Get character
  738.     CPI    '.'        ; Delimimter between name and extent?
  739.     RNZ            ; Done
  740.     INX    H        ; Point to after period
  741.     MVI    B,3        ; 3 characters maximum and do it again
  742.  
  743. GETFN1:    MOV    A,M        ; Get character
  744.     CPI    '.'        ; End of field?
  745.     JZ    GETFN3
  746.     CALL    DELCHK        ; Check delimiter
  747.     RZ
  748.     CPI    '*'        ; Wild?
  749.     JZ    GETFN4
  750.     STAX    D        ; Store character
  751.     INX    H        ; Point to next
  752.     INX    D
  753.     DCR    B        ; Count down
  754.     JNZ    GETFN1
  755. ;
  756. GETFN2:    MOV    A,M        ; Flush characters to the delimiter
  757.     CALL    DELCHK        ; Check for delimiter
  758.     RZ
  759.     INX    H        ; Point to next
  760.     JMP    GETFN2
  761.  
  762. GETFN3:    INX    D        ; Point to 'after' field
  763.     DCR    B        ; Count down
  764.     JNZ    GETFN3
  765.     RET
  766.  
  767. GETFN4:    MVI    A,'?'        ; Fill with question marks
  768.     STAX    D
  769.     INX    D
  770.     DCR    B
  771.     JNZ    GETFN4
  772.     JMP    GETFN2        ; Skip to the delimiter
  773. ;.....
  774. ;
  775. ; Check for help request
  776. ;
  777. HELPCHK:LDA    FCB+1        ; Get 1st byte of filename
  778.     CPI    ' '        ; Make sure it is non-blank
  779.     JZ    HELP
  780.     CPI    '?'
  781.     RNZ
  782.     LDA    FCB+2
  783.     CPI    ' '
  784.     RNZ
  785. ;.....
  786. ;
  787. ; Compares the entry pointed to by the pointer pointed to by HL with
  788. ; that pointed to by DE (1st level indirect addressing).  On entry, HL
  789. ; and DE contain the numbers of the elements to compare (1, 2, ...).  On
  790. ; exit, carry set means ((DE)) < ((HL)), zero set means ((HL)) = ((DE)),
  791. ; and non-zero and no-carry means ((DE)) > ((HL))
  792. ;
  793. ICOMPARE:
  794.     PUSH    H        ; Save HL
  795.     LHLD    ORDER        ; Address of order - 2
  796.     MOV    B,H        ; In BC
  797.     MOV    C,L
  798.     POP    H
  799.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  800.     DAD    H        ; Double the element number
  801.     DAD    B        ; Add to this the base address
  802.     XCHG            ; Result in DE
  803.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  804.     DAD    H        ; Do the same with the original DE
  805.     DAD    B
  806.     XCHG
  807. ;
  808. ; HL now points to the pointer whose index was in HL to begin with.  DE
  809. ; now points to the pointer whose index was in DE to begin with.  For
  810. ; example, if DE=5 and HL=4, DE now points to the 5th pointer and HL to
  811. ; the 4th pointer.
  812. ;
  813.     MOV    C,M        ; BC is points to the object indexed to
  814.     INX    H        ; By the original HL
  815.     MOV    B,M
  816.     XCHG
  817.     MOV    E,M        ; DE is points to the object indexed to
  818.     INX    H        ; By the original DE
  819.     MOV    D,M
  820.     MOV    H,B        ; HL=object pointed to indirectly by BC
  821.     MOV    L,C
  822.     JMP    CMP$ENTRY
  823. ;.....
  824. ;
  825. ; Swap (exchange) the pointers in the order table whose indexes are in
  826. ; HL and DE.
  827. ;
  828. ISWAP:    PUSH    H        ; Save HL
  829.     LHLD    ORDER        ; Address of order table - 2
  830.     MOV    B,H        ; In BC
  831.     MOV    C,L
  832.     POP    H
  833.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  834.     DAD    H        ; HL points to offset address
  835.     DAD    B        ; HL now points to pointer involved
  836.     XCHG            ; De now points to pointer indexed by HL
  837.     DCX    H        ; Adjust index to 0...n-1 from 1...n
  838.     DAD    H        ; HL points to offset address
  839.     DAD    B        ; HL now points to pointer involved
  840.     MOV    C,M        ; Exchange pointers -- get old (DE)
  841.     LDAX    D        ; -- get old (HL)
  842.     XCHG            ; Switch
  843.     MOV    M,C        ; Put new (HL)
  844.     STAX    D        ; Put new (DE)
  845.     INX    H        ; Point to next byte of pointer
  846.     INX    D
  847.     MOV    C,M        ; Get old (HL)
  848.     LDAX    D        ; Get old (de)
  849.     XCHG            ; Switch
  850.     MOV    M,C        ; Put new (de)
  851.     STAX    D        ; Put new (hl)
  852.     RET
  853. ;.....
  854. ;
  855. ; General purpose move routine from HL to DE for count of 8
  856. ;
  857. MOVE:    MOV    A,M        ; Get a byte
  858.     STAX    D        ; Put a byte
  859.     INX    D        ; Increment to next
  860.     INX    H
  861.     DCR    B        ; Count down
  862.     JNZ    MOVE
  863.     RET
  864. ;.....
  865. ;
  866. MOVFL:    CALL    PRINT
  867.     DB    CR,LF,'Aborting, not enough memory for buffers',0
  868.     JMP    EXIT
  869. ;.....
  870. ;
  871. ; Advance to next disk
  872. ;
  873. NXTDISK:LXI    B,TBUFF        ; Set DMA address
  874.     CALL    SETDMA
  875.     LDA    FCB
  876.     LXI    H,MXDRV        ; Maximum disk
  877.     CMP    M        ; Compare
  878.     LXI    H,0
  879.     RNC
  880.  
  881.     CPI    SKIP1        ; Skip a drive?
  882.     JZ    RETST        ; Yes,if zero  -- reset counters
  883.     CPI    SKIP2        ; Skip a second drive?
  884.     JZ    RETST        ; Yes, reset counters
  885.     CPI    SKIP3        ; Skip a third drive?
  886.     JZ    RETST        ; Yes, reset counters
  887.     JMP    CONTIN        ; No, continue
  888. ;...
  889. ;
  890. ; Reads next record (group of four directory entries).    Returns with
  891. ; zero flag set if no more.
  892. ;
  893. NXTREC:    LHLD    DIRMAX        ; See if more records
  894.     MOV    A,H
  895.     ORA    L
  896.     RZ            ; Returns zero flag if no more
  897.     LHLD    TRACK        ; Set track
  898.     MOV    B,H
  899.     MOV    C,L
  900.     CALL    SETTRK
  901.     LHLD    RECORD        ; Set record
  902.     MOV    B,H
  903.     MOV    C,L
  904.     CALL    TRNSLT
  905.     CALL    SETREC
  906.     CALL    READ        ; Read a record
  907.     ANI    1        ; Reverse sense of error flag
  908.     XRI    1        ; Returns with zero flag set
  909.     RET            ; If bad read
  910. ;.....
  911. ;
  912. ; Checks for S-option in command line and extracts file names into table
  913. ;
  914. OPTCHK:    XRA    A        ; Turn off flags
  915.     STA    SYSTEM        ; No system files
  916.     STA    FFLAG        ; No files found
  917.     STA    ECOUNT        ; No entries
  918.     STA    FNCOUNT        ; No file names
  919.     LHLD    FNTAB        ; Point to table
  920.     XCHG            ; In DE
  921.     LXI    H,TBUFF+1    ; Scan thru TBUFF, building a FN table
  922.     CALL    SBLANK        ; Skip blanks
  923.  
  924. OPTCK1:    PUSH    D        ; Save table pointer
  925.     CALL    GETFN        ; Extract file name
  926.     POP    D
  927.     PUSH    H
  928.     LXI    H,11        ; Point to next table entry
  929.     DAD    D
  930.     XCHG
  931.     POP    H
  932.     LDA    FNCOUNT        ; Increment count
  933.     INR    A
  934.     STA    FNCOUNT
  935.     MOV    A,M        ; Get terminating character
  936.     INX    H        ; Point to next
  937.     CPI    ','        ; Another follows?
  938.     JZ    OPTCK1
  939.     DCX    H        ; Point back to delimiter
  940.     CALL    SBLANK        ; Skip to non-blank
  941.  
  942. OPTCK2:     IF    USEZCPR
  943.     LDA    WHEEL        ; Load WHEEL byte
  944.     ORA    A        ; Check if set
  945.     JZ    OPTCK3        ; Don't set flag if not wheel
  946.      ENDIF            ; USEZCPR
  947.  
  948.      IF    NOT SYSFILE    ; If SYSFILE is YES, show systems files
  949.     LDA    WHEEL        ; Load WHEEL byte
  950.     ORA    A        ; Check if set
  951.     JZ    OPTCK3        ; Don't set flag if not wheel
  952.      ENDIF            ; NOT SYSFILE
  953.  
  954.     MVI    A,0FFH        ; Set flag
  955.     STA    SYSTEM
  956. ;
  957. OPTCK3:    MOV    A,M        ; Get option
  958.     CALL    DELCHK        ; Done if delimiter
  959.     RZ
  960.     CALL    PRINT
  961.     DB    CR,LF,'Invalid option -- ',0
  962.     MOV    A,M
  963.     CALL    BOUT
  964.     JMP    HELP
  965. ;.....
  966. ;
  967. ; Print register A value as 3 decimal characters
  968. ;
  969. PA3DC:    PUSH    B        ; Save registers
  970.     PUSH    D
  971.     PUSH    PSW        ; Save the character
  972.     MVI    D,0        ; Turn off the leading space flag
  973.     JMP    PADC1
  974. ;.....
  975. ;
  976. ; Print register A value as decimal character with a leading space in a
  977. ; three-character field.
  978. ;
  979. PADC:    PUSH    B        ; Save registers
  980.     PUSH    D
  981.     PUSH    PSW
  982.     MVI    D,1        ; Turn on leading space flag
  983. ;
  984. ; Print routine
  985. ;
  986. PADC1:    MVI    B,100        ; Print hundreds
  987.     CALL    PAC        ; Print a character
  988.     MVI    B,10        ; Print tens
  989.     CALL    PAC
  990.     ADI    '0'        ; Convert to ASCII
  991.     CALL    COUT        ; Print
  992.     POP    PSW        ; Restore registers
  993.     POP    D
  994.     POP    B
  995.     RET
  996. ;.....
  997. ;
  998. ; Print result of division of A by B with leading space
  999. ;
  1000. PAC:    MVI    C,0        ; Set count
  1001.  
  1002. PAC1:    SUB    B        ; Compute count
  1003.     JC    PAC2
  1004.     INR    C        ; Increment count
  1005.     JMP    PAC1
  1006.  
  1007. PAC2:    ADD    B        ; Add 'B' back in
  1008.     MOV    E,A        ; Save 'A'
  1009.     MOV    A,C        ; Get count
  1010.     ORA    A        ; Zero?
  1011.     JNZ    PAC3
  1012.     ORA    D        ; 0 means no leading space
  1013.     JZ    PAC3
  1014.     MVI    A,' '        ; Print a space
  1015.     CALL    COUT
  1016.     MOV    A,E        ; Restore A
  1017.     RET
  1018.  
  1019. PAC3:    MVI    D,0        ; D=0 For no leading space
  1020.     MOV    A,C        ; Get count
  1021.     ADI    '0'        ; Convert to decimal
  1022.     CALL    COUT        ; Print it
  1023.     MOV    A,E        ; Restore A
  1024.     RET
  1025. ;.....
  1026. ;
  1027. ; Print the string pointed to by the return address, terminated by a 0
  1028. ;
  1029. PRINT:    XTHL            ; HL=address, old HL on stack
  1030.     CALL    PSTR        ; Print string pointed to by HL
  1031.     XTHL            ; Restore HL and new return address
  1032.     RET
  1033. ;.....
  1034. ;
  1035. ; Print string pointed to by HL, affects only HL.  When done, HL points
  1036. ; to the byte after the string.
  1037. ;
  1038. PSTR:    PUSH    D        ; Save registers
  1039.     PUSH    B
  1040.     PUSH    PSW
  1041.     MVI    C,0        ; Set position count
  1042.  
  1043. PSTR1:    MOV    A,M        ; Get byte
  1044.     INX    H        ; Point to next
  1045.     ORA    A        ; 0=done
  1046.     JZ    PSTR7
  1047.     CPI    TAB        ; Expand tab
  1048.     JZ    PSTR5
  1049. ;
  1050. ; Print the character
  1051. ;
  1052.     INR    C        ; Increment position
  1053.     CALL    CCOUT        ; Print it on the console
  1054.     CPI    CR
  1055.     JZ    PSTR2
  1056.     CPI    LF
  1057.     JZ    PSTR3
  1058.     CPI    BELL
  1059.     JZ    PSTR3
  1060.     CPI    BS
  1061.     JZ    PSTR4
  1062.     JMP    PSTR1
  1063. ;...
  1064. ;
  1065. ; Reset position count
  1066. ;
  1067. PSTR2:    MVI    C,0        ; Reset
  1068.     JMP    PSTR1
  1069. ;
  1070. ; LF, BELL, NULL, cursor did not advance
  1071. ;
  1072. PSTR3:    DCR    C        ; Back up count by 1
  1073.     JMP    PSTR1
  1074. ;
  1075. ; Backspace, cursor went backward, perhaps
  1076. ;
  1077. PSTR4:    MOV    A,C        ; Check for zero
  1078.     ORA    A
  1079.     JZ    PSTR1
  1080.     DCR    C        ; Back up count by 2
  1081.     DCR    C
  1082.     JMP    PSTR1
  1083. ;
  1084. ; Expand tab
  1085. ;
  1086. PSTR5:    MOV    A,C        ; Get count
  1087.     ANI    7        ; Mask for subtract from 8
  1088.     MOV    B,A        ; Store temporarily
  1089.     MVI    A,8        ; Subtract from 8 for spaces count
  1090.     SUB    B
  1091.     MOV    B,A        ; Count in B
  1092.     ADD    C        ; Add to position count
  1093.     MOV    C,A
  1094.     MVI    A,' '        ; Print a space character
  1095.  
  1096. PSTR6:    CALL    COUT
  1097.     DCR    B        ; Decrement the count
  1098.     JNZ    PSTR6
  1099.     JMP    PSTR1
  1100. ;
  1101. ; PSTR done
  1102. ;
  1103. PSTR7:    POP    PSW        ; Restore registers
  1104.     POP    B
  1105.     POP    D
  1106.     RET
  1107. ;.....
  1108. ;
  1109. ; Print files in DIRBUF
  1110. ;
  1111. PRFILES:LHLD    FCOUNT        ; Get count
  1112.     MOV    A,H        ; Any?
  1113.     ORA    L
  1114.     RZ
  1115.  
  1116.     CALL    CKABRT        ; Want to abort now?
  1117.     CALL    CRLF
  1118.     MOV    B,H        ; Count in BC
  1119.     MOV    C,L
  1120.     LHLD    DIRBUF        ; Point to first one
  1121.  
  1122. PRFLOOP:
  1123.     PUSH    B        ; Save count
  1124.     PUSH    H        ; Save pointer
  1125.     CALL    PRINTFCB    ; Print FCB
  1126.     POP    H        ; Get registers back
  1127.     POP    B
  1128.     LXI    D,12        ; Point to next
  1129.     DAD    D
  1130.     DCX    B        ; Count down
  1131.     MOV    A,B
  1132.     ORA    C
  1133.     JNZ    PRFLOOP
  1134.  
  1135.     MVI    A,0FFH        ; Set ok
  1136.     ORA    A        ; Clear the flag
  1137.     RET
  1138. ;.....
  1139. ;
  1140. ; FCB printing routine
  1141. ;
  1142. PRINTFCB:
  1143.     CALL    PRINT        ; 2 spaces
  1144.     DB    ' ',0
  1145.     MOV    A,M        ; Get user number
  1146.     CALL    PADC        ; Print it
  1147.     MVI    A,':'
  1148.     CALL    BOUT
  1149.     INX    H
  1150.  
  1151. PR0:    MVI    B,8
  1152.     CALL    PR1
  1153.     MVI    A,'.'
  1154.     CALL    BOUT
  1155.     MVI    B,3
  1156.     CALL    PR1
  1157.     LDA    ECOUNT        ; Increment count
  1158.     INR    A
  1159.     STA    ECOUNT
  1160.     STA    NEWCR
  1161.     ANI    3        ; Every 4 filenames start a new line
  1162.     RNZ
  1163.  
  1164.     CALL    CKABRT        ; Want to abort or pause now?
  1165.     CALL    CRLF        ; New line
  1166.     XRA    A
  1167.     STA    NEWCR
  1168.     RET
  1169. ;.....
  1170. ;
  1171. PR1:    MOV    A,M
  1172.     ANI    7FH
  1173.     CALL    BOUT
  1174.     INX    H
  1175.     DCR    B
  1176.     JNZ    PR1
  1177.     RET
  1178. ;.....
  1179. ;
  1180. RETST:    LDA    ECOUNT        ; Last new line?
  1181.     ANI    3
  1182.     CNZ    CRLF
  1183.     LXI    H,0        ; Set file count
  1184.     SHLD    FCOUNT
  1185.     XRA    A        ; Set count
  1186.     STA    ECOUNT
  1187.     CMA            ; Flip
  1188.     ORA    A        ; Ok to continue
  1189.     RET
  1190. ;.....
  1191. ;
  1192. SBLANK:    MOV    A,M        ; Skip to non-blank
  1193.     CPI    ' '
  1194.     RNZ
  1195.     INX    H
  1196.     JMP    SBLANK
  1197. ;.....
  1198. ;
  1199. SCANCOL:PUSH    D        ; Save table pointer
  1200.     PUSH    H        ; Save pointer
  1201.  
  1202. SCOL1:    MOV    A,M        ; Get character
  1203.     INX    H        ; Point to next
  1204.     CPI    ':'        ; Colon?
  1205.     JZ    SCOLX
  1206.     CALL    DELCHK        ; Check for delimiter
  1207.     JNZ    SCOL1
  1208.  
  1209. SCOL2:    POP    H        ; Restore
  1210.     POP    D
  1211.     RET
  1212. ;...
  1213. ;
  1214. SCOLX:    XCHG            ; DE points after colon
  1215.     POP    H        ; Get old pointer
  1216.     XCHG            ; Replace it
  1217.     POP    D        ; Get table pointer
  1218.     RET
  1219. ;.....
  1220. ;
  1221. ; Shift regs HL right 2 bits logical.
  1222. ;
  1223. SHFHL2:    CALL    SHFHL        ; Rotate right 1 bit and fall thru
  1224. ;
  1225. SHFHL:    XRA    A        ; Clear carry
  1226.     MOV    A,H
  1227.     RAR            ; Shifted bit in carry
  1228.     MOV    H,A
  1229.     MOV    A,L
  1230.     RAR
  1231.     MOV    L,A
  1232.     RET
  1233. ;.....
  1234. ;
  1235. ; SHELL SORT - This sort routine is adapted from "SOFTWARE TOOLS" by
  1236. ; Kernigan and Plaugher, page 106.  Copyright, 1976, Addison-Wesley.
  1237. ; On entry, BC=number of entries and HL=address of first entry.
  1238. ;
  1239. SORT:    XCHG            ; Pointer to directory in de
  1240.     LHLD    ORDER        ; Pt to order table
  1241. ;
  1242. ; Set up order table; HL points to next entry in order table, DE points
  1243. ; to next entry in directory, BC = number of elements remaining
  1244. ;
  1245. SORT1:    MOV    M,E        ; Store low-order address
  1246.     INX    H        ; Point to next order byte
  1247.     MOV    M,D        ; Store high-order address
  1248.     INX    H        ; Point to next order entry
  1249.     PUSH    H        ; Save pointer
  1250.     LXI    H,12        ; HL=number of bytes/entry
  1251.     DAD    D        ; Point to next DIR1 entry
  1252.     XCHG            ; DE points to next entry
  1253.     POP    H        ; Get pointer to order table
  1254.     DCX    B        ; Count down
  1255.     MOV    A,B        ; Done?
  1256.     ORA    C
  1257.     JNZ    SORT1
  1258. ;
  1259. ; This is the main sort loop for the shell sort in "SOFTWARE TOOLS" by
  1260. ; Kernigan and Plaugher.
  1261. ;
  1262.     LHLD    NUMBR        ; Number of items to sort
  1263.     SHLD    GAP        ; Initial GAP to N for 1st divide by 2
  1264. ;
  1265. ; For (GAP = NUMBR/2; GAP > 0; GAP = GAP/2)
  1266. ;
  1267. SRTL0:    ORA    A        ; Clear carry
  1268.     LHLD    GAP        ; Get previous GAP
  1269.     MOV    A,H        ; Rotate right to divide by 2
  1270.     RAR
  1271.     MOV    H,A
  1272.     MOV    A,L
  1273.     RAR
  1274.     MOV    L,A
  1275. ;
  1276. ; Test for zero
  1277. ;
  1278.     ORA    H
  1279.     JZ    SDONE        ; Done with sort if GAP = 0
  1280.     SHLD    GAP        ; Set value of GAP
  1281.     SHLD    I        ; Set I=GAP for following loop
  1282. ;
  1283. ; For (i = gap + 1; i <= n; i = i + 1)
  1284. ;
  1285. SRTL1:    LHLD    I        ; Add 1 to I
  1286.     INX    H
  1287.     SHLD    I
  1288. ;
  1289. ; Test for I <= NUMBR
  1290. ;
  1291.     XCHG            ; I is in DE
  1292.     LHLD    NUMBR        ; Get the number
  1293.     MOV    A,L        ; Compare by subtraction
  1294.     SUB    E
  1295.     MOV    A,H
  1296.     SBB    D        ; Carry set means I > NUMBR
  1297.     JC    SRTL0        ; Don't do for loop if I > NUMBR
  1298.  
  1299.     LHLD    I        ; J = I initially for 1st subtr. of GAP
  1300.     SHLD    J
  1301. ;
  1302. ; For (J = I - GAP; J > 0; J = J - GAP)
  1303. ;
  1304. SRTL2:    LHLD    GAP        ; Get GAP
  1305.     XCHG            ; In DE
  1306.     LHLD    J        ; Get J
  1307.     MOV    A,L        ; Compute J - GAP
  1308.     SUB    E
  1309.     MOV    L,A
  1310.     MOV    A,H
  1311.     SBB    D
  1312.     MOV    H,A
  1313.     SHLD    J        ; J = J - GAP
  1314.     JC    SRTL1        ; If carry from subtr. J < 0 and abort
  1315.     MOV    A,H        ; J=0?
  1316.     ORA    L
  1317.     JZ    SRTL1        ; If zero, j=0 and abort
  1318. ;
  1319. ; Set JG = J + GAP
  1320. ;
  1321.     XCHG            ; J in DE
  1322.     LHLD    GAP        ; Get GAP
  1323.     DAD    D        ; J + GAP
  1324.     SHLD    JG        ; JG = J + GAP
  1325. ;
  1326. ; If (V(J) <= V(JG))
  1327. ;
  1328.     CALL    ICOMPARE    ; J in DE, JG in HL
  1329.     JC    SRTL1        ; Then break
  1330.     LHLD    J        ; Else exchange
  1331.     XCHG
  1332.     LHLD    JG
  1333.     CALL    ISWAP        ; J in DE, JG in HL
  1334. ;
  1335. ; End of innermost for loop
  1336. ;
  1337.     JMP    SRTL2
  1338. ;.....
  1339. ;
  1340. ; Sort is done, restructure DIR1 in sorted order in place.
  1341. ;
  1342. SDONE:    LHLD    NUMBR        ; Number of entries
  1343.     MOV    B,H        ; In BC
  1344.     MOV    C,L
  1345.     LHLD    ORDER        ; Pointer to ordered pointer table
  1346.     SHLD    PTPTR        ; Set pointer pointer
  1347.     LHLD    DIRBUF        ; Pointer to unordered directory
  1348.     SHLD    PTDIR        ; Set ppinter directory buffer
  1349. ;
  1350. ; Find pointer to next DIR1 entry
  1351. ;
  1352. SRTDN:    LHLD    PTPTR        ; Point to remaining pointers
  1353.     XCHG            ; In DE
  1354.     LHLD    PTDIR        ; HL points to next directory entry
  1355.     PUSH    B        ; Save count of remaining entries
  1356. ;
  1357. ; Find pointer table entry
  1358. ;
  1359. SRTDN1:    LDAX    D        ; Get current pointer table entry value
  1360.     INX    D        ; Point to high-order pointer byte
  1361.     CMP    L        ; Compare against DIR1 address, low
  1362.     JNZ    SRTDN2        ; Not found yet
  1363.     LDAX    D        ; Low-order bytes match, get high-order
  1364.     CMP    H        ; Compare against DIR1 address, high
  1365.     JZ    SRTDN3        ; Match found
  1366. ;
  1367. SRTDN2:    INX    D        ; Point to next pointer table entry
  1368.     DCX    B        ; Count down
  1369.     MOV    A,C        ; End of table?
  1370.     ORA    B
  1371.     JNZ    SRTDN1        ; Continue if not
  1372.     JMP    FERR$PTR
  1373. ;.....
  1374. ;
  1375. ; Found the pointer table entry which points to the next unordered DIR1
  1376. ; entry make both pointers (pointer to next, pointer to current unorder-
  1377. ; ed DIR1 entry).  Point to same location (pointer to next DIR1 entry to
  1378. ; be ordered)
  1379. ;
  1380. SRTDN3:    LHLD    PTPTR        ; Get pointer to next ordered entry
  1381.     DCX    D        ; DE points to low-order pointer address
  1382.     MOV    A,M        ; Make pointer to next unordered DIR1
  1383.     STAX    D        ; DIR1 entry to be moved to next DIR1
  1384.     INX    H        ; Point to next pointer address
  1385.     INX    D
  1386.     MOV    A,M        ; Make high point similarly
  1387.     STAX    D
  1388. ;
  1389. ; Copy next unordered dir1 entry to hold buffer
  1390. ;
  1391.     MVI    B,12        ; B=number of bytes/entry
  1392.     LHLD    PTDIR        ; Point to entry
  1393.     LXI    D,HOLD        ; Point to hold buffer
  1394.     PUSH    B        ; Save B=number of bytes/entry
  1395.     CALL    MOVE
  1396.     POP    B
  1397. ;
  1398. ; Copy to-be-ordered DIR1 entry to next ordered DIR1 position
  1399. ;
  1400.     LHLD    PTPTR        ; Point to its pointer
  1401.     MOV    E,M        ; Get low-address pointer
  1402.     INX    H
  1403.     MOV    D,M        ; Get high-address pointer
  1404.     LHLD    PTDIR        ; Destination address for next DIR1
  1405.     XCHG            ; Hl points to entry to be moved
  1406.     PUSH    B        ; Save B=number of bytes/entry
  1407.     CALL    MOVE
  1408.     POP    B
  1409.     XCHG            ; HL pts to next unordered DIR1 entry
  1410.     SHLD    PTDIR        ; Set pointer for next loop
  1411. ;
  1412. ; Copy entry in hold buffer to location previously held by latest order-
  1413. ; ed entry.
  1414. ;
  1415.     LHLD    PTPTR        ; Get 'pntr to ptr' to the destination
  1416.     MOV    E,M        ; Get low-address pointer
  1417.     INX    H
  1418.     MOV    D,M        ; High-address pointer
  1419.     LXI    H,HOLD        ; HL points to hold buffer
  1420.     CALL    MOVE        ; B=number of bytes/entry
  1421. ;
  1422. ; Point to next entry in pointer table.
  1423. ;
  1424.     LHLD    PTPTR        ; Pointer to current entry
  1425.     INX    H        ; Skip over it
  1426.     INX    H
  1427.     SHLD    PTPTR
  1428. ;
  1429. ; Count down
  1430. ;
  1431.     POP    B        ; Get counter
  1432.     DCX    B        ; Count down
  1433.     MOV    A,C        ; Done?
  1434.     ORA    B
  1435.     JNZ    SRTDN
  1436.     RET            ; Done
  1437. ;.....
  1438. ;
  1439. ; Translate regs BC from logical to physical record number
  1440. ;
  1441. TRNSLT:    LHLD    DPH        ; Get pointer to DPH
  1442.     MOV    E,M        ; Get address of XLT
  1443.     INX    H
  1444.     MOV    D,M
  1445.     CALL    RECTRAN        ; Use BIOS routine
  1446.     MOV    C,L        ; Return value in BC
  1447.     MOV    B,H
  1448.     RET
  1449. ;.....
  1450. ;              end of subroutines
  1451. ;-----------------------------------------------------------------------
  1452. ;
  1453. ; Messages
  1454. ;
  1455. CKMS1:    DB    13,10,13,10,'++ ABORTED ++',13,10,'$'
  1456. CKMS2:    DB    8,' ',8,'$'
  1457. ;
  1458. ; Say who we are
  1459. ;
  1460. HELLO:    CALL    PRINT
  1461.     DB    CR,LF,'ZFILE v',(VERS MOD 10)+'0','  '
  1462.     DB    'S to pause - C, K or X to abort',CR,LF,0
  1463.     RET
  1464. ;.....
  1465. ;
  1466. ; If no file name is specified, send following help guide
  1467. ;
  1468. HELP:    CALL    PRINT
  1469.     DB    CR,LF,'Searches all allowed drives and user '
  1470.     DB    'areas',CR,LF,'for requested files.  Systems files '
  1471.     DB    'included',CR,LF,'if using a WHEEL byte and it is '
  1472.     DB    'set.  Several',CR,LF,'files can be requested at '
  1473.     DB    'the same time:',CR,LF,CR,LF
  1474.     DB    'A>FILE FILE1*.*,FILE2*.*,FILE3*.*(,etc.)'
  1475.     DB    CR,LF,CR,LF,CR,LF,0
  1476.     JMP    EXIT
  1477. ;.....
  1478. ;
  1479. ; Sort buffers
  1480. ;
  1481. DIRBUF:    DS    2        ; Pointer to directory
  1482. DSTART:    DS    2        ; Pointer to first directory entry
  1483. FCOUNT:    DS    2        ; Total # of files/# of selected files
  1484. GAP:    DS    2        ; Binary GAP size
  1485. HOLD:    DS    12        ; Exchange hold buffer for FCB's
  1486. I:    DS    2        ; Indexes for sort
  1487. J:    DS    2
  1488. JG:    DS    2
  1489. NUMBR:    DS    2        ; Number of elements to sort
  1490. ORDER:    DS    2        ; Pointer to order table
  1491. PTPTR:    DS    2        ; Pointer pointer
  1492. PTDIR:    DS    2        ; Directory pointer
  1493. ;.....
  1494. ;
  1495. ; This is the working copy of the BIOS jump table
  1496. ;
  1497. WBOOT:    DS    3
  1498. CONST:    DS    3
  1499. CONIN:    DS    3
  1500. CONOUT:    DS    3
  1501. LIST:    DS    3
  1502. PUNCH:    DS    3
  1503. READER:    DS    3
  1504. HOME:    DS    3
  1505. SELDSK:    DS    3
  1506. SETTRK:    DS    3
  1507. SETREC:    DS    3
  1508. SETDMA:    DS    3
  1509. READ:    DS    3
  1510. WRITE:    DS    3
  1511. LISTST:    DS    3
  1512. RECTRAN:DS    3
  1513. ;.....
  1514. ;
  1515. ; Data areas
  1516. ;
  1517. CLPFLG:    DS    1        ; 0 for no match locally
  1518. DIRMAX:    DS    2        ; Number of records in directory
  1519. DPH:    DS    2        ; Address of DPH
  1520. ECOUNT:    DS    1        ; Count of entries printed - 1
  1521. EXTENT:    DS    1        ; Extent mask
  1522. FFLAG:    DS    1        ; File found flag (0=no)
  1523. FNCOUNT:DS    1        ; Number of file names found
  1524. FNTAB:    DS    2        ; File name table
  1525. MAXREC:    DS    2        ; Maximum number of records/track
  1526. NEWCR:    DS    1        ; To finish with a new line
  1527. RECORD:    DS    2        ; Current sector number
  1528. SCRATCH:DS    2        ; Scratch area
  1529. SYSTEM:    DS    1        ; 0 if no system files
  1530. TEMP:    DS    2        ; Temporary storage for FCB print
  1531. TRACK:    DS    2        ; Track number of directory
  1532. ;.....
  1533. ;
  1534.     DS    64        ; Minimum stack depth
  1535.  
  1536.     ORG    ($+127)/128*128
  1537.  
  1538. BUFTBL    EQU    $
  1539. STACK    EQU    BUFTBL-2
  1540. ;.....
  1541. ;
  1542.     END
  1543.