home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ZSYS / SIMTEL20 / SYSLIB / SLIB1.LBR / SDIRQS.Z80 < prev   
Text File  |  2000-06-30  |  20KB  |  784 lines

  1. ;
  2. ; SYSLIB Module Name:  SDIRQS
  3. ; Author:  Richard Conn
  4. ; Part of SYSLIB3 SDIR Series
  5. ; SYSLIB Version Number:  3.6
  6. ; Module Version Number:  1.5
  7.  
  8.     public    dirqs
  9.  
  10. ;
  11. ; EQUATES
  12. ;
  13. CPM    EQU    0
  14. BDOS    EQU    5
  15. BUFF    EQU    80H    ; DMA BUFFER
  16. ESIZE    EQU    16    ; 16 BYTES/ENTRY
  17.  
  18. ;
  19. ;  GENERAL-PURPOSE DIRECTORY SELECT ROUTINE WITHOUT SIZING INFORMATION
  20. ;    THIS ROUTINE SCANS FOR THE FCB PTED TO BY DE AND LOADS ALL ENTRIES
  21. ; WHICH MATCH IT INTO THE MEMORY BUFFER PTED TO BY HL.  ON EXIT, 
  22. ; BC=NUMBER OF FILES IN BUFFER, AND HL PTS TO FIRST FILE IN BUFFER.
  23. ;    THE DIRECTORY BUFFER GENERATED BY DIRQ CONTAINS ENTRIES WHICH MAY NOT
  24. ; BE USED TO COMPUTE THE SIZE OF THE FILES USING THE FSIZE ROUTINE.  THE
  25. ; DIRQS ROUTINE IS DESIGNED FOR THIS PURPOSE.  THE BASIC TRADEOFF BETWEEN
  26. ; THE TWO ROUTINES IS THE DIRQ RUNS FASTER THAN DIRQS, AND THIS IS NOTICABLE
  27. ; IF THERE IS A SIGNIFICANT NUMBER OF FILES TO BE PROCESSED.
  28. ;
  29. ;    THE DIRQ/DIRQS ROUTINES ARE INTENDED TO BE USED IN APPLICATIONS WHERE
  30. ; THE ONLY THING DESIRED IS A DIRECTORY LOAD OF THE CURRENT DIRECTORY
  31. ; (DISK AND USER).  DIRF/DIRFS PROVIDE MORE FLEXIBILITY AT A GREATER COST
  32. ; IN TERMS OF SIZE.
  33. ;
  34. ;    INPUT PARAMETERS:
  35. ;    HL PTS TO BUFFER, DE PTS TO FCB, A IS SELECT FLAG:
  36. ;            Bit 7 - Select Non-Sys, Bit 6 - Select Sys
  37. ;            Bit 5 - Sort by File Name and Type (0) or other (1)
  38. ;            Bits 4-0 - Unused
  39. ;    OUTPUT PARAMETERS:
  40. ;    HL PTS TO FIRST FILE IN BUFFER
  41. ;    BC = NUMBER OF FILES
  42. ;    A=0 and Z Flag Set if TPA Overflow
  43. ;    DE UNCHANGED
  44. ;
  45. DIRQS:
  46.     PUSH    DE    ; SAVE PTR TO FCB
  47.  
  48.     LD    (SELFLG),A    ; SAVE SELECT FLAG FOR SELECTION AND ALPHA
  49.     LD    (HOLD),HL    ; SET PTR TO HOLD BUFFER
  50.     LD    BC,36    ; ALLOW 36 BYTES
  51.     ADD    HL,BC    ; HL NOW POINTS TO TEMP FCB
  52.     LD    (TFCB),HL    ; SET PTR TO TEMP FCB
  53.     ADD    HL,DE    ; HL NOW PTS TO SCRATCH AREA
  54.  
  55.     PUSH    DE    ; SAVE PTR TO FCB
  56.     CALL    DBUFFER    ; GET PTRS
  57.     POP    DE    ; GET PTR TO FCB
  58.     PUSH    HL    ; SAVE PTR TO BUFFER
  59.     CALL    DIRLOAD    ; LOAD DIRECTORY WITHOUT SIZING INFORMATION (FAST LOAD)
  60.     POP    HL    ; GET PTR TO BUFFER
  61.  
  62.     POP    DE    ; GET PTR TO FCB
  63.  
  64.     RET    Z        ; ABORT IF TPA OVERFLOW
  65.  
  66.     PUSH    AF    ; SAVE FLAG TO INDICATE NO TPA OVERFLOW
  67.     CALL    DIRALPHA    ; ALPHABETIZE
  68.     POP    AF    ; GET PSW (TPA OVERFLOW FLAG)
  69.     RET
  70.  
  71. ;
  72. ;  THIS ROUTINE ACCEPTS A BASE ADDRESS FOR THE DYNAMIC BUFFERS
  73. ;    REQUIRED, DETERMINES HOW MUCH SPACE IS REQUIRED FOR THE BUFFERS,
  74. ;    AND SETS THE ORDER PTR TO PT TO THE FIRST AND DIRBUF TO PT TO
  75. ;    THE SECOND (ORDER SPACE = DIRMAX*2 AND DIRBUF = DIRMAX * ESIZE)
  76. ;  ON INPUT, HL PTS TO AVAILABLE BASE
  77. ;  ON OUTPUT, HL PTS TO DIRBUF
  78. ;    A=0 AND ZERO FLAG SET IF CCP OVERRUN
  79. ;
  80. DBUFFER:
  81.     LD    (ORDER),HL    ; PT TO ORDER TABLE
  82.     CALL    DPARAMS    ; GET PARAMETERS
  83.     LD    HL,(DIRMAX)    ; NUMBER OF ENTRIES IN DIR
  84.     EX    DE,HL        ; ... IN DE
  85.     LD    HL,(ORDER)    ; ADD TO ORDER BASE
  86.     ADD    HL,DE    ; *1
  87.     CALL    MEMCHK    ; CHECK FOR WITHIN RANGE
  88.     ADD    HL,DE    ; HL PTS TO DIRBUF
  89.     CALL    MEMCHK    ; CHECK FOR WITHIN RANGE
  90.     LD    (DIRBUF),HL    ; SET PTR AND HL PTS TO DIRECTORY BUFFER
  91.     XOR    A    ; OK
  92.     DEC    A    ; SET FLAGS (NZ)
  93.     RET
  94.  
  95. MEMCHK:
  96.     PUSH    HL    ; SAVE REGS
  97.     PUSH    DE
  98.     EX    DE,HL        ; NEXT ADDRESS IN DE
  99.     LD    HL,(BDOS+1)    ; GET ADDRESS OF BDOS
  100.     LD    A,D    ; CHECK FOR PAGE OVERRUN
  101.     CP    H
  102.     JP    NC,MEMORUN    ; OVERRUN IF D>=H
  103.     POP    DE
  104.     POP    HL
  105.     RET
  106. MEMORUN:
  107.     POP    DE    ; RESTORE
  108.     POP    HL
  109.     POP    AF    ; CLEAR STACK
  110.     XOR    A    ; RETURN 0
  111.     RET
  112.  
  113. ;
  114. ;  THIS ROUTINE EXTRACTS DISK PARAMETER INFORMATON FROM THE DPB AND
  115. ;    STORES THIS INFORMATION IN:
  116. ;    BLKSHF    <-- BLOCK SHIFT FACTOR (1 BYTE)
  117. ;    BLKMSK    <-- BLOCK MASK (1 BYTE)
  118. ;    EXTENT  <-- EXTENT MASK (1 BYTE) [NOT ANY MORE]
  119. ;    BLKMAX    <-- MAX NUMBER OF BLOCKS ON DISK (2 BYTES)
  120. ;    DIRMAX    <-- MAX NUMBER OF DIRECTORY ENTRIES (2 BYTES)
  121. ;
  122. DPARAMS:
  123. ;
  124. ;  VERSION 2.x OR MP/M
  125. ;
  126.     LD    C,31    ; 2.x OR MP/M...REQUEST DPB
  127.     CALL    BDOS
  128.     INC    HL
  129.     INC    HL
  130.     LD    A,(HL)    ; GET BLOCK SHIFT
  131.     LD    (BLKSHF),A    ; BLOCK SHIFT FACTOR
  132.     INC    HL    ; GET BLOCK MASK
  133.     LD    A,(HL)
  134.     LD    (BLKMSK),A    ; BLOCK MASK
  135.     INC    HL
  136.     INC    HL
  137.     LD    E,(HL)    ; GET MAX BLOCK NUMBER
  138.     INC    HL
  139.     LD    D,(HL)
  140.     EX    DE,HL
  141.     INC    HL    ; ADD 1 FOR MAX NUMBER OF BLOCKS
  142.     LD    (BLKMAX),HL    ; MAXIMUM NUMBER OF BLOCKS
  143.     EX    DE,HL
  144.     INC    HL
  145.     LD    E,(HL)    ; GET DIRECTORY SIZE
  146.     INC    HL
  147.     LD    D,(HL)
  148.     EX    DE,HL
  149.     INC    HL    ; ADD 1 FOR NUMBER OF ENTRIES
  150.     LD    (DIRMAX),HL    ; MAXIMUM NUMBER OF DIRECTORY ENTRIES
  151.     RET
  152.  
  153. ;
  154. ;  BUILD DIRECTORY TABLE AT DIRBUF
  155. ;    THIS IS THE OPTIMAL DIRECTORY LOAD ROUTINE; IT ONLY LOADS UNIQUE
  156. ;        FILE NAMES FROM DISK, BUT THE INFORMATION IS NOT SUFFICIENT
  157. ;        TO COMPUTE THE FILE SIZES
  158. ;    ON INPUT, HL PTS TO DIRECTORY BUFFER (16 x N MAX)
  159. ;        DE PTS TO FCB (ONLY 12 BYTES NEEDED)
  160. ;    ON OUTPUT, BC IS NUM OF FILES
  161. ;        A=0 AND ZERO FLAG SET IF TPA OVERFLOW
  162. ;
  163. DIRLOAD:
  164.     LD    (DSTART),HL    ; SET START OF BUFFER AREA
  165.     INC    DE    ; PT TO FILE NAME
  166.     LD    HL,(TFCB)    ; PT TO TFCB
  167.     LD    (HL),0    ; SELECT CURRENT DISK
  168.     INC    HL    ; PT TO FILE NAME IN TFCB
  169.     LD    B,11    ; 11 CHARS
  170. DLLOOP:
  171.     LD    A,(DE)    ; COPY
  172.     LD    (HL),A
  173.     INC    HL    ; PT TO NEXT
  174.     INC    DE
  175.     DEC    B    ; COUNT DOWN
  176.     JP    NZ,DLLOOP
  177.     LD    (HL),'?'    ; SELECT ALL EXTENTS
  178.     INC    HL    ; PT TO NEXT CHAR
  179.     LD    B,23    ; 23 CHARS
  180.     XOR    A    ; ZERO REST OF TFCB
  181. DLLOOP1:
  182.     LD    (HL),A    ; STORE ZERO
  183.     INC    HL    ; PT TO NEXT
  184.     DEC    B    ; COUNT DOWN
  185.     JP    NZ,DLLOOP1
  186.  
  187. ;
  188. ;  THIS SECTION OF CODE INITIALIZES THE COUNTERS USED
  189. ;
  190.     LD    HL,0    ; HL=0
  191.     LD    (FCOUNT),HL    ; TOTAL FILES ON DISK = 0
  192. ;
  193. ;  NOW WE BEGIN SCANNING FOR FILES TO PLACE INTO THE MEMORY BUFFER
  194. ;
  195.     LD    C,17    ; SEARCH FOR FILE
  196.     JP    DIRLP1
  197. DIRLP:
  198.     CALL    PENTRY    ; PLACE ENTRY IN DIR
  199.     JP    Z,DIROVFL    ; MEMORY OVERFLOW ERROR
  200.     LD    C,18    ; SEARCH FOR NEXT MATCH
  201. DIRLP1:
  202.     LD    HL,(TFCB)    ; PT TO FCB
  203.     EX    DE,HL
  204.     CALL    BDOS
  205.     CP    255    ; DONE?
  206.     JP    NZ,DIRLP
  207. ;
  208. ;  NOW WE ARE DONE WITH THE LOAD -- SET UP RETURN VALUES
  209. ;
  210. DIRDN:
  211.     XOR    A    ; LOAD OK
  212.     DEC    A    ; SET FLAGS (NZ)
  213. DIRDNX:
  214.     LD    HL,(FCOUNT)    ; GET TOTAL NUMBER OF FILES
  215.     LD    B,H    ; ... IN BC
  216.     LD    C,L
  217.     RET
  218. ;
  219. ;  MEMORY OVERFLOW ERROR
  220. ;
  221. DIROVFL:
  222.     XOR    A    ; LOAD ERROR
  223.     JP    DIRDNX
  224.  
  225. ;
  226. ;  PENTRY --
  227. ;  PLACE ENTRY IN DIRECTORY BUFFER IF NOT AN ERASED ENTRY
  228. ;
  229. ;  ON INPUT,  A=0-3 FOR ADR INDEX IN BUFF OF ENTRY FCB
  230. ;          FCOUNT=NUMBER OF FILES IN DIR SO FAR
  231. ;  ON OUTPUT, FCOUNT=NUMBER OF FILES IN DIR SO FAR
  232. ;          A=0 AND ZERO FLAG SET IF MEMORY OVERFLOW ERROR
  233. ;
  234. PENTRY:
  235.     RRCA        ; MULTIPLY BY 32 FOR OFFSET COMPUTATION
  236.     RRCA
  237.     RRCA
  238.     AND    60H    ; A=BYTE OFFSET
  239.     LD    DE,BUFF    ; PT TO BUFFER ENTRY
  240.     LD    L,A    ; LET HL=OFFSET
  241.     LD    H,0
  242.     ADD    HL,DE    ; HL=PTR TO FCB
  243. ;
  244. ;  HL=ADR OF FCB IN BUFF
  245. ;
  246.     CALL    ATTEST    ; TEST ATTRIBUTES
  247.     JP    Z,PEDONE    ; SKIP IF ATTRIBUTE NOT DESIRED
  248.  
  249. ;
  250. ;  SCAN DIRECTORY ENTRIES AS LOADED SO FAR FOR ANOTHER ENTRY BY THE SAME
  251. ;    NAME; IF FOUND, SET THAT ENTRY TO BE THE ENTRY WITH THE LARGER EX
  252. ;    AND RETURN WITH THE ZERO FLAG SET, INDICATING NO NEW FILE; IF NOT
  253. ;    FOUND, RETURN WITH ZERO FLAG RESET (NZ)
  254. ;
  255.     CALL    DUPENTRY    ; CHECK FOR DUPLICATE AND SELECT EX
  256.     JP    Z,PEDONE    ; SKIP IF DUPLICATE
  257.  
  258. ;
  259. ;  COPY FCB PTED TO BY HL INTO DIRECTORY BUFFER
  260. ;
  261.     EX    DE,HL        ; SAVE PTR IN DE
  262.     LD    HL,(DIRBUF)    ; PT TO NEXT ENTRY LOCATION
  263.     EX    DE,HL        ; HL PTS TO FCB, DE PTS TO NEXT ENTRY LOCATION
  264.     LD    B,ESIZE    ; NUMBER OF BYTES/ENTRY
  265.     CALL    SDMOVE    ; COPY FCB INTO MEMORY BUFFER
  266.     EX    DE,HL        ; HL PTS TO NEXT ENTRY
  267.     LD    (DIRBUF),HL    ; SET PTR
  268.     EX    DE,HL        ; PTR TO NEXT ENTRY IN DE
  269.     LD    HL,(BDOS+1)    ; BASE ADDRESS OF BDOS IN HL
  270.     LD    A,H    ; GET BASE PAGE OF BDOS
  271.     SUB    9    ; COMPUTE 1 PAGE IN FRONT OF BASE PAGE OF CCP
  272.     CP    D    ; IS PTR TO NEXT ENTRY BEYOND THIS?
  273.     RET    Z
  274.  
  275. ;  INCREMENT TOTAL NUMBER OF FILES
  276.     LD    HL,(FCOUNT)    ; TOTAL FILES = TOTAL FILES + 1
  277.     INC    HL
  278.     LD    (FCOUNT),HL
  279.  
  280. ;  DONE WITH PENTRY AND NO ERROR
  281. PEDONE:
  282.     XOR    A    ; NO ERROR
  283.     DEC    A    ; SET FLAGS (NZ)
  284.     RET
  285.  
  286. ;
  287. ;  CHECK ATTRIBUTES OF FILE ENTRY PTED TO BY HL AGAINST SELFLG
  288. ;    IF SYSTEM FILE AND SYSTEM ATTRIBUTE SET, RETURN NZ
  289. ;    IF NORMAL FILE AND NORMAL ATTRIBUTE SET, RETURN NZ
  290. ;
  291. ATTEST:
  292.     PUSH    HL    ; SAVE PTR
  293.     LD    BC,10    ; PT TO SYSTEM ATTRIBUTE
  294.     ADD    HL,BC
  295.     LD    A,(HL)    ; GET SYSTEM ATTRIBUTE
  296.     POP    HL    ; RESTORE PTR
  297.     AND    80H    ; CHECK FOR SYS
  298.     LD    A,(SELFLG)    ; GET SELECTION FLAG
  299.     JP    Z,ATDIR
  300.     AND    01000000B    ; CHECK SYSTEM ATTRIBUTE
  301.     RET
  302. ATDIR:
  303.     AND    10000000B    ; CHECK NORMAL ATTRIBUTE
  304.     RET
  305.  
  306. ;
  307. ;  SCAN DIRECTORY ENTRIES AS LOADED SO FAR FOR ANOTHER ENTRY BY THE SAME
  308. ;    NAME; IF FOUND, SET THAT ENTRY TO BE THE ENTRY WITH THE LARGER EX
  309. ;    AND RETURN WITH THE ZERO FLAG SET, INDICATING NO NEW FILE; IF NOT
  310. ;    FOUND, RETURN WITH ZERO FLAG RESET (NZ)
  311. ;  ON INPUT, HL PTS TO ENTRY TO SCAN FOR, FCOUNT = NUMBER OF ENTRIES SO FAR,
  312. ;        AND (DSTART) = STARTING ADDRESS OF DIRECTORY LOADED
  313. ;  ON OUTPUT, A=0 AND ZERO FLAG SET IF DUPLICATE ENTRY FOUND; A=0FFH AND NZ
  314. ;        IF NO DUP ENTRY FOUND
  315. ;        ONLY HL NOT AFFECTED
  316. ;
  317. DUPENTRY:
  318.     PUSH    HL    ; SAVE PTR TO ENTRY TO SCAN FOR
  319.     EX    DE,HL        ; PTR IN DE
  320.     LD    HL,(FCOUNT)    ; CHECK COUNT
  321.     LD    A,H    ; NO ENTRIES?
  322.     OR    L
  323.     JP    Z,NODUP    ; NO DUPLICATE ENTRY RETURN
  324.     LD    B,H    ; BC=NUMBER OF ENTRIES
  325.     LD    C,L
  326.     LD    HL,(DSTART)    ; HL PTS TO FIRST ENTRY
  327. DUPELOOP:
  328.     PUSH    BC    ; SAVE COUNT
  329.     PUSH    HL    ; SAVE PTRS
  330.     PUSH    DE
  331.     INC    HL    ; PT TO FN
  332.     INC    DE
  333.     LD    B,11    ; COMPARE FN AND FT
  334.     CALL    COMP
  335.     JP    NZ,NODUPL    ; CONTINUE LOOKING FOR ANOTHER ENTRY
  336. ;  DUPLICATE ENTRIES HAVE BEEN IDENTIFIED AT THIS POINT
  337.     LD    A,(DE)    ; GET EXTENT FIELD FROM TARGET
  338.     CP    (HL)    ; COMPARE WITH THAT IN DIRECTORY ENTRY
  339.     POP    DE    ; GET PTRS
  340.     POP    HL
  341.     JP    C,DUPSMALL
  342. ;  NEW TARGET IS LARGER THAN STORED ENTRY
  343.     EX    DE,HL        ; HL PTS TO TARGET, DE PTS TO DIR ENTRY
  344.     LD    B,ESIZE    ; NUMBER OF BYTES TO MOVE
  345.     CALL    SDMOVE    ; MOVE IT
  346. ;  NEW TARGET IS SMALLER THAN STORED ENTRY
  347. DUPSMALL:
  348.     POP    BC    ; CLEAR COUNT FROM STACK
  349.     XOR    A    ; INDICATE DUP FOUND
  350.     POP    HL    ; RESTORE PTR TO ENTRY TO SCAN FOR
  351.     RET
  352. ;  NO DUPLICATE FOUND; ADVANCE TO NEXT ENTRY
  353. NODUPL:
  354.     POP    DE    ; RESTORE PTRS
  355.     POP    HL
  356.     LD    BC,ESIZE    ; HL PTS TO CURRENT ENTRY IN BUFFER,
  357.     ADD    HL,BC    ; ... SO ADD ESIZE TO IT
  358.     POP    BC    ; GET COUNT
  359.     DEC    BC    ; COUNT DOWN
  360.     LD    A,B    ; CHECK FOR DONE
  361.     OR    C
  362.     JP    NZ,DUPELOOP
  363. ;  NO DUPLICATE FOUND
  364. NODUP:
  365.     XOR    A    ; INDICATE DUP NOT FOUND
  366.     DEC    A    ; SET FLAGS (NZ)
  367.     POP    HL    ; RESTORE PTR TO ENTRY TO SCAN FOR
  368.     RET
  369.  
  370. ;
  371. ;  DIRALPHA -- ALPHABETIZES DIRECTORY PTED TO BY HL; BC CONTAINS
  372. ;    THE NUMBER OF FILES IN THE DIRECTORY AND A = SORT FLAG
  373. ;    (0=SORT BY FILE NAME/TYPE, <>0 = SORT BY FILE TYPE/NAME)
  374. ;
  375. DIRALPHA:
  376.     LD    A,B    ; ANY FILES?
  377.     OR    C
  378.     RET    Z
  379.     PUSH    HL    ; SAVE REGS
  380.     PUSH    DE
  381.     PUSH    BC
  382.     LD    (DIRBUF),HL    ; SAVE PTR TO DIRECTORY
  383.     PUSH    HL    ; SAVE HL
  384.     LD    H,B    ; HL=BC=FILE COUNT
  385.     LD    L,C
  386.     LD    (N),HL    ; SET "N"
  387.     POP    HL
  388. ;
  389. ;  SHELL SORT --
  390. ;    THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS"
  391. ;    BY KERNIGAN AND PLAUGHER, PAGE 106.  COPYRIGHT, 1976, ADDISON-WESLEY.
  392. ;  ON ENTRY, BC=NUMBER OF ENTRIES
  393. ;
  394. SORT:
  395.     EX    DE,HL        ; POINTER TO DIRECTORY IN DE
  396.     LD    HL,(ORDER)    ; PT TO ORDER TABLE
  397. ;
  398. ;  SET UP ORDER TABLE; HL PTS TO NEXT ENTRY IN ORDER TABLE, DE PTS TO NEXT
  399. ;    ENTRY IN DIRECTORY, BC = NUMBER OF ELEMENTS REMAINING
  400. ;
  401. SORT1:
  402.     LD    (HL),E    ; STORE LOW-ORDER ADDRESS
  403.     INC    HL    ; PT TO NEXT ORDER BYTE
  404.     LD    (HL),D    ; STORE HIGH-ORDER ADDRESS
  405.     INC    HL    ; PT TO NEXT ORDER ENTRY
  406.     PUSH    HL    ; SAVE PTR
  407.     LD    HL,ESIZE    ; HL=NUMBER OF BYTES/ENTRY
  408.     ADD    HL,DE    ; PT TO NEXT DIR1 ENTRY
  409.     EX    DE,HL        ; DE PTS TO NEXT ENTRY
  410.     POP    HL    ; GET PTR TO ORDER TABLE
  411.     DEC    BC    ; COUNT DOWN
  412.     LD    A,B    ; DONE?
  413.     OR    C
  414.     JP    NZ,SORT1
  415. ;
  416. ;  THIS IS THE MAIN SORT LOOP FOR THE SHELL SORT IN "SOFTWARE TOOLS" BY K&P
  417. ;
  418.  
  419. ;
  420. ;  SHELL SORT FROM "SOFTWARE TOOLS" BY KERNINGHAN AND PLAUGER
  421. ;
  422.     LD    HL,(N)    ; NUMBER OF ITEMS TO SORT
  423.     LD    (GAP),HL    ; SET INITIAL GAP TO N FOR FIRST DIVISION BY 2
  424.  
  425. ;  FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
  426. SRTL0:
  427.     OR    A    ; CLEAR CARRY
  428.     LD    HL,(GAP)    ; GET PREVIOUS GAP
  429.     LD    A,H    ; ROTATE RIGHT TO DIVIDE BY 2
  430.     RRA
  431.     LD    H,A
  432.     LD    A,L
  433.     RRA
  434.     LD    L,A
  435.  
  436. ;  TEST FOR ZERO
  437.     OR    H
  438.     JP    Z,SDONE    ; DONE WITH SORT IF GAP = 0
  439.  
  440.     LD    (GAP),HL    ; SET VALUE OF GAP
  441.     LD    (IVAL),HL    ; SET I=GAP FOR FOLLOWING LOOP
  442.  
  443. ;  FOR (I = GAP + 1; I <= N; I = I + 1)
  444. SRTL1:
  445.     LD    HL,(IVAL)    ; ADD 1 TO I
  446.     INC    HL
  447.     LD    (IVAL),HL
  448.  
  449. ;  TEST FOR I <= N
  450.     EX    DE,HL        ; I IS IN DE
  451.     LD    HL,(N)    ; GET N
  452.     LD    A,L    ; COMPARE BY SUBTRACTION
  453.     SUB    E
  454.     LD    A,H
  455.     SBC    A,D    ; CARRY SET MEANS I > N
  456.     JP    C,SRTL0    ; DON'T DO FOR LOOP IF I > N
  457.  
  458.     LD    HL,(IVAL)    ; SET J = I FOR FIRST SUBTRACTION OF GAP
  459.     LD    (J),HL
  460.  
  461. ;  FOR (J = I - GAP; J > 0; J = J - GAP)
  462. SRTL2:
  463.     LD    HL,(GAP)    ; GET GAP
  464.     EX    DE,HL        ; ... IN DE
  465.     LD    HL,(J)    ; GET J
  466.     LD    A,L    ; COMPUTE J - GAP
  467.     SUB    E
  468.     LD    L,A
  469.     LD    A,H
  470.     SBC    A,D
  471.     LD    H,A
  472.     LD    (J),HL    ; J = J - GAP
  473.     JP    C,SRTL1    ; IF CARRY FROM SUBTRACTIONS, J < 0 AND ABORT
  474.     LD    A,H    ; J=0?
  475.     OR    L
  476.     JP    Z,SRTL1    ; IF ZERO, J=0 AND ABORT
  477.  
  478. ;  SET JG = J + GAP
  479.     EX    DE,HL        ; J IN DE
  480.     LD    HL,(GAP)    ; GET GAP
  481.     ADD    HL,DE    ; J + GAP
  482.     LD    (JG),HL    ; JG = J + GAP
  483.  
  484. ;  IF (V(J) <= V(JG))
  485.     CALL    ICOMPARE    ; J IN DE, JG IN HL
  486.  
  487. ;  ... THEN BREAK
  488.     JP    C,SRTL1
  489.  
  490. ;  ... ELSE EXCHANGE
  491.     LD    HL,(J)    ; SWAP J, JG
  492.     EX    DE,HL
  493.     LD    HL,(JG)
  494.     CALL    ISWAP    ; J IN DE, JG IN HL
  495.  
  496. ;  END OF INNER-MOST FOR LOOP
  497.     JP    SRTL2
  498.  
  499. ;
  500. ;  SORT IS DONE -- RESTRUCTURE DIR1 IN SORTED ORDER IN PLACE
  501. ;
  502. SDONE:
  503.     LD    HL,(N)    ; NUMBER OF ENTRIES
  504.     LD    B,H    ; ... IN BC
  505.     LD    C,L
  506.     LD    HL,(ORDER)    ; PTR TO ORDERED POINTER TABLE
  507.     LD    (PTPTR),HL    ; SET PTR PTR
  508.     LD    HL,(DIRBUF)    ; PTR TO UNORDERED DIRECTORY
  509.     LD    (PTDIR),HL    ; SET PTR DIR BUFFER
  510.  
  511. ;  FIND PTR TO NEXT DIR1 ENTRY
  512. SRTDN:
  513.     LD    HL,(PTPTR)    ; PT TO REMAINING POINTERS
  514.     EX    DE,HL        ; ... IN DE
  515.     LD    HL,(PTDIR)    ; HL PTS TO NEXT DIR ENTRY
  516.     PUSH    BC    ; SAVE COUNT OF REMAINING ENTRIES
  517.  
  518. ;  FIND PTR TABLE ENTRY
  519. SRTDN1:
  520.     LD    A,(DE)    ; GET CURRENT POINTER TABLE ENTRY VALUE
  521.     INC    DE    ; PT TO HIGH-ORDER POINTER BYTE
  522.     CP    L    ; COMPARE AGAINST DIR1 ADDRESS LOW
  523.     JP    NZ,SRTDN2    ; NOT FOUND YET
  524.     LD    A,(DE)    ; LOW-ORDER BYTES MATCH -- GET HIGH-ORDER POINTER BYTE
  525.     CP    H    ; COMPARE AGAINST DIR1 ADDRESS HIGH
  526.     JP    Z,SRTDN3    ; MATCH FOUND
  527. SRTDN2:
  528.     INC    DE    ; PT TO NEXT PTR TABLE ENTRY
  529.     DEC    BC    ; COUNT DOWN
  530.     LD    A,C    ; END OF TABLE?
  531.     OR    B
  532.     JP    NZ,SRTDN1    ; CONTINUE IF NOT
  533.  
  534. ;  FATAL ERROR -- INTERNAL ERROR; POINTER TABLE NOT CONSISTENT
  535. FERR$PTR:
  536.     LD    E,7    ; RING BELL
  537.     LD    C,2    ; OUTPUT
  538.     CALL    BDOS
  539.     JP    CPM
  540.  
  541. ;  FOUND THE POINTER TABLE ENTRY WHICH POINTS TO THE NEXT UNORDERED DIR1 ENTRY
  542. ;    MAKE BOTH POINTERS (PTR TO NEXT, PTR TO CURRENT UNORDERED DIR1 ENTRY)
  543. ;    POINT TO SAME LOCATION (PTR TO NEXT DIR1 ENTRY TO BE ORDERED)
  544. SRTDN3:
  545.     LD    HL,(PTPTR)    ; GET PTR TO NEXT ORDERED ENTRY
  546.     DEC    DE    ; DE PTS TO LOW-ORDER POINTER ADDRESS
  547.     LD    A,(HL)    ; MAKE PTR TO NEXT UNORDERED DIR1 PT TO BUFFER FOR
  548.     LD    (DE),A    ;   DIR1 ENTRY TO BE MOVED TO NEXT UNORDERED DIR1 POS
  549.     INC    HL    ; PT TO NEXT PTR ADDRESS
  550.     INC    DE
  551.     LD    A,(HL)    ; MAKE HIGH POINT SIMILARLY
  552.     LD    (DE),A
  553.  
  554. ;  COPY NEXT UNORDERED DIR1 ENTRY TO HOLD BUFFER
  555.     LD    B,ESIZE    ; B=NUMBER OF BYTES/ENTRY
  556.     LD    HL,(HOLD)    ; PT TO HOLD BUFFER
  557.     EX    DE,HL
  558.     LD    HL,(PTDIR)    ; PT TO ENTRY
  559.     PUSH    BC    ; SAVE B=NUMBER OF BYTES/ENTRY
  560.     CALL    SDMOVE
  561.     POP    BC
  562.  
  563. ;  COPY TO-BE-ORDERED DIR1 ENTRY TO NEXT ORDERED DIR1 POSITION
  564.     LD    HL,(PTPTR)    ; POINT TO ITS POINTER
  565.     LD    E,(HL)    ; GET LOW-ADDRESS POINTER
  566.     INC    HL
  567.     LD    D,(HL)    ; GET HIGH-ADDRESS POINTER
  568.     LD    HL,(PTDIR)    ; DESTINATION ADDRESS FOR NEXT ORDERED ENTRY
  569.     EX    DE,HL        ; HL PTS TO ENTRY TO BE MOVED, DE PTS TO DEST
  570.     PUSH    BC    ; SAVE B=NUMBER OF BYTES/ENTRY
  571.     CALL    SDMOVE
  572.     POP    BC
  573.     EX    DE,HL        ; HL PTS TO NEXT UNORDERED DIR1 ENTRY
  574.     LD    (PTDIR),HL    ; SET POINTER FOR NEXT LOOP
  575.  
  576. ;  COPY ENTRY IN HOLD BUFFER TO LOC PREVIOUSLY HELD BY LATEST ORDERED ENTRY
  577.     LD    HL,(PTPTR)    ; GET PTR TO PTR TO THE DESTINATION
  578.     LD    E,(HL)    ; GET LOW-ADDRESS POINTER
  579.     INC    HL
  580.     LD    D,(HL)    ; HIGH-ADDRESS POINTER
  581.     LD    HL,(HOLD)    ; HL PTS TO HOLD BUFFER, DE PTS TO ENTRY DEST
  582.     CALL    SDMOVE    ; B=NUMBER OF BYTES/ENTRY
  583.  
  584. ;  POINT TO NEXT ENTRY IN POINTER TABLE
  585.     LD    HL,(PTPTR)    ; POINTER TO CURRENT ENTRY
  586.     INC    HL    ; SKIP OVER IT
  587.     INC    HL
  588.     LD    (PTPTR),HL
  589.  
  590. ;  COUNT DOWN
  591.     POP    BC    ; GET COUNTER
  592.     DEC    BC    ; COUNT DOWN
  593.     LD    A,C    ; DONE?
  594.     OR    B
  595.     JP    NZ,SRTDN
  596.     POP    BC    ; RESTORE REGS
  597.     POP    DE
  598.     POP    HL
  599.     RET        ; DONE
  600.  
  601. ;
  602. ;  SWAP (Exchange) the pointers in the ORDER table whose indexes are in
  603. ;    HL and DE
  604. ;
  605. ISWAP:
  606.     PUSH    HL        ; SAVE HL
  607.     LD    HL,(ORDER)        ; ADDRESS OF ORDER TABLE - 2
  608.     LD    B,H        ; ... IN BC
  609.     LD    C,L
  610.     POP    HL
  611.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  612.     ADD    HL,HL        ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
  613.                 ;   OF ORIGINAL HL (1, 2, ...)
  614.     ADD    HL,BC        ; HL NOW PTS TO POINTER INVOLVED
  615.     EX    DE,HL            ; DE NOW PTS TO POINTER INDEXED BY HL
  616.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  617.     ADD    HL,HL        ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
  618.                 ;   OF ORIGINAL DE (1, 2, ...)
  619.     ADD    HL,BC        ; HL NOW PTS TO POINTER INVOLVED
  620.     LD    C,(HL)        ; EXCHANGE POINTERS -- GET OLD (DE)
  621.     LD    A,(DE)        ; -- GET OLD (HL)
  622.     EX    DE,HL            ; SWITCH
  623.     LD    (HL),C        ; PUT NEW (HL)
  624.     LD    (DE),A        ; PUT NEW (DE)
  625.     INC    HL        ; PT TO NEXT BYTE OF POINTER
  626.     INC    DE
  627.     LD    C,(HL)        ; GET OLD (HL)
  628.     LD    A,(DE)        ; GET OLD (DE)
  629.     EX    DE,HL            ; SWITCH
  630.     LD    (HL),C        ; PUT NEW (DE)
  631.     LD    (DE),A        ; PUT NEW (HL)
  632.     RET
  633. ;
  634. ;  ICOMPARE compares the entry pointed to by the pointer pointed to by HL
  635. ;    with that pointed to by DE (1st level indirect addressing); on entry,
  636. ;    HL and DE contain the numbers of the elements to compare (1, 2, ...);
  637. ;    on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)),
  638. ;    and Non-Zero and No-Carry means ((DE)) > ((HL))
  639. ;
  640. ICOMPARE:
  641.     PUSH    HL        ; SAVE HL
  642.     LD    HL,(ORDER)        ; ADDRESS OF ORDER - 2
  643.     LD    B,H        ; ... IN BC
  644.     LD    C,L
  645.     POP    HL
  646.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  647.     ADD    HL,HL        ; DOUBLE THE ELEMENT NUMBER TO POINT TO THE PTR
  648.     ADD    HL,BC        ; ADD TO THIS THE BASE ADDRESS OF THE PTR TABLE
  649.     EX    DE,HL            ; RESULT IN DE
  650.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  651.     ADD    HL,HL        ; DO THE SAME WITH THE ORIGINAL DE
  652.     ADD    HL,BC
  653.     EX    DE,HL
  654.  
  655. ;
  656. ;  HL NOW POINTS TO THE POINTER WHOSE INDEX WAS IN HL TO BEGIN WITH
  657. ;  DE NOW POINTS TO THE POINTER WHOSE INDEX WAS IN DE TO BEGIN WITH
  658. ;    FOR EXAMPLE, IF DE=5 AND HL=4, DE NOW POINTS TO THE 5TH PTR AND HL
  659. ; TO THE 4TH POINTER
  660. ;
  661.     LD    C,(HL)        ; BC IS MADE TO POINT TO THE OBJECT INDEXED TO
  662.     INC    HL        ; ... BY THE ORIGINAL HL
  663.     LD    B,(HL)
  664.     EX    DE,HL
  665.     LD    E,(HL)        ; DE IS MADE TO POINT TO THE OBJECT INDEXED TO
  666.     INC    HL        ; ... BY THE ORIGINAL DE
  667.     LD    D,(HL)
  668.     LD    H,B        ; SET HL = OBJECT PTED TO INDIRECTLY BY BC
  669.     LD    L,C
  670.  
  671. ;
  672. ;  COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE;
  673. ;    NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE<HL
  674. ;    RET W/ZERO SET MEANS DE=HL
  675. ;
  676. CMP$ENTRY:
  677.     LD    A,(SELFLG)    ; GROUP BY FILE TYPE?
  678.     AND    00100000B
  679.     JP    Z,CMP$FN$FT
  680. ;
  681. ;  COMPARE BY FILE TYPE AND FILE NAME (IN THAT ORDER)
  682. ;
  683.     PUSH    HL
  684.     PUSH    DE
  685.     LD    BC,9    ; PT TO FT (8 BYTES + 1 BYTE FOR USER NUMBER)
  686.     ADD    HL,BC
  687.     EX    DE,HL
  688.     ADD    HL,BC
  689.     EX    DE,HL        ; DE, HL NOW PT TO THEIR FT'S
  690.     LD    B,3    ; 3 BYTES
  691.     CALL    COMP    ; COMPARE FT'S
  692.     POP    DE
  693.     POP    HL
  694.     RET    NZ        ; CONTINUE IF COMPLETE MATCH
  695.     LD    B,8    ; 8 BYTES
  696.     JP    CMP$FT1
  697. ;
  698. ;  COMPARE BY FILE NAME AND FILE TYPE (IN THAT ORDER)
  699. ;
  700. CMP$FN$FT:
  701.     LD    B,11    ; 11 BYTES FOR FN AND FT
  702. CMP$FT1:
  703.     PUSH    HL
  704.     PUSH    DE
  705.     INC    HL    ; PT TO FN
  706.     INC    DE
  707.     CALL    COMP    ; DO COMPARISON
  708.     POP    DE
  709.     POP    HL
  710.     RET
  711. ;
  712. ;  COMP COMPARES DE W/HL FOR B BYTES; RET W/CARRY IF DE<HL
  713. ;    MSB IS DISREGARDED
  714. ;
  715. COMP:
  716.     LD    A,(HL)    ; GET (HL)
  717.     AND    7FH    ; MASK MSB
  718.     LD    C,A    ; ... IN C
  719.     LD    A,(DE)    ; COMPARE
  720.     AND    7FH    ; MASK MSB
  721.     CP    C
  722.     RET    NZ
  723.     INC    HL    ; PT TO NEXT
  724.     INC    DE
  725.     DEC    B    ; COUNT DOWN
  726.     JP    NZ,COMP
  727.     RET
  728.  
  729. ;
  730. ; COPY FROM HL TO DE FOR B BYTES
  731. ;
  732. SDMOVE:
  733.     LD    A,(HL)    ; COPY
  734.     LD    (DE),A
  735.     INC    HL    ; PT TO NEXT
  736.     INC    DE
  737.     DEC    B    ; COUNT DOWN
  738.     JP    NZ,SDMOVE
  739.     RET
  740.  
  741. ;
  742. ;  BUFFERS
  743. ;
  744. HOLD:
  745.     DS    2    ; EXCHANGE HOLD BUFFER FOR FCB'S
  746. PTPTR:
  747.     DS    2    ; POINTER POINTER
  748. PTDIR:
  749.     DS    2    ; DIRECTORY POINTER
  750. IVAL:
  751.     DS    2    ; INDEXES FOR SORT
  752. J:
  753.     DS    2
  754. JG:
  755.     DS    2
  756. N:
  757.     DS    2    ; NUMBER OF ELEMENTS TO SORT
  758. GAP:
  759.     DS    2    ; BINARY GAP SIZE
  760.  
  761. TFCB:
  762.     DS    2    ; ADDRESS OF TEMPORARY FCB
  763. DSTART:
  764.     DS    2    ; POINTER TO FIRST DIRECTORY ENTRY
  765. FCOUNT:
  766.     DS    2    ; TOTAL NUMBER OF FILES/NUMBER OF SELECTED FILES
  767.  
  768. BLKSHF:
  769.     DB    0    ; BLOCK SHIFT FACTOR
  770. BLKMSK:
  771.     DB    0    ; BLOCK MASK
  772. BLKMAX:
  773.     DW    0    ; MAX NUMBER OF BLOCKS
  774. DIRMAX:
  775.     DW    0    ; MAX NUMBER OF DIRECTORY ENTRIES
  776. SELFLG:
  777.     DB    0    ; FILE ATTRIBUTE FLAG
  778. ORDER:
  779.     DW    0    ; POINTER TO ORDER TABLE
  780. DIRBUF:
  781.     DW    0    ; POINTER TO DIRECTORY
  782.  
  783.     END
  784.