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 / SLIB3.LBR / SSORT.Z80 < prev    next >
Text File  |  2000-06-30  |  14KB  |  563 lines

  1. ;
  2. ; SYSLIB Module Name:  SSORT
  3. ; Author:  Richard Conn
  4. ; SYSLIB Version Number:  3.6
  5. ; Module Version Number:  1.2
  6.  
  7.     public    ssbinit,sort
  8.  
  9. ;
  10. ;  EXTERNALS
  11. ;
  12.     EXT    MOVEB
  13.     EXT    PRINT
  14.  
  15. ;
  16. ;  BASIC EQUATES
  17. ;
  18. CPM    EQU    0    ; CP/M WARM BOOT
  19. BIOS    EQU    CPM+1    ; BIOS BASE ADDRESS
  20. BDOS    EQU    CPM+5    ; BDOS ENTRY POINT
  21. ESIZE    EQU    16    ; NUMBER OF BYTES/ENTRY IN MEMORY BUFFER
  22. BUFF    EQU    CPM+80H    ; DEFAULT DMA BUFFER
  23.  
  24. ;
  25. ;  SSBINI -- Initialize SSB
  26. ;    This routine sets the value of FIRSTP and ORDER for the SORT
  27. ; routine.  On Entry, HL pts to first available byte after user's
  28. ; program (beginning of buffer area) and DE pts to an SSB.  On exit,
  29. ; HL pts to first available byte for the user's in-memory data file
  30. ; (same address as FIRSTP).  If the TPA is overflowed by the ORDER
  31. ; table that would be generated by SORT, then the Z flag is returned set
  32. ; (Z); if no error, NZ is returned.
  33. ;    If the user has already loaded his data and just wants to
  34. ; allocate an ORDER table, then he should have HL before calling SSBINI,
  35. ; restore HL upon return from SSBINI, and then store HL into his FIRSTP
  36. ; entry before calling SORT.
  37. ;
  38. SSBINIT:
  39.     PUSH    DE    ; SAVE REGS
  40.     PUSH    BC
  41.     PUSH    HL    ; SAVE NEXT AVAILABLE BYTE ADDRESS
  42.     EX    DE,HL    ; MAKE HL PT TO USER'S SSB
  43.     LD    (USRSSB),HL    ; SAVE PTR TO USER'S SSB
  44.     LD    DE,SSB    ; COPY INTO MY SSB
  45.     LD    B,12    ; 12 BYTES
  46.     CALL    MOVEB
  47.     POP    HL    ; GET NEXT AVAILABLE BYTE ADDRESS
  48.     LD    (ORDER),HL    ; SET PTR TO IT
  49.     LD    HL,(RECNT)    ; GET NUMBER OF RECORDS
  50.     LD    A,L    ; DOUBLE IT WITH ERROR CHECKING
  51.     ADD    A,L
  52.     LD    L,A
  53.     LD    A,H
  54.     ADC    A,H
  55.     LD    H,A
  56.     JP    C,SSBOVFL    ; OVERFLOW IF CARRY
  57.     EX    DE,HL    ; SIZE OF ORDER TABLE IN DE
  58.     LD    HL,(ORDER)    ; BASE ADDRESS OF ORDER TABLE IN HL
  59.     LD    A,L    ; ADD HL TO DE WITH ERROR CHECKING
  60.     ADD    A,E
  61.     LD    L,A
  62.     LD    A,H
  63.     ADC    A,D
  64.     LD    H,A    ; HL IS NOW ADDRESS OF BYTE AFTER ORDER TABLE
  65.     JP    C,SSBOVFL    ; OVERFLOW IF CARRY
  66.     LD    (FIRSTP),HL    ; SET PTR TO NEXT AVAILABLE BYTE
  67.     LD    HL,(USRSSB)    ; PT TO USER'S SSB
  68.     EX    DE,HL    ; ... IN DE
  69.     LD    HL,SSB    ; PT TO USER'S NEW SSB
  70.     LD    B,12    ; COPY IT BACK
  71.     CALL    MOVEB
  72.     POP    BC    ; RESTORE REGS
  73.     POP    DE
  74.     LD    HL,(FIRSTP)    ; PT TO NEXT AVAILABLE MEMORY ADDRESS
  75.     LD    A,0FFH    ; SET NO ERROR CODE
  76.     OR    A
  77.     RET
  78. SSBOVFL:
  79.     POP    BC    ; RESTORE REGS
  80.     POP    DE
  81.     LD    HL,(ORDER)    ; RESTORE PTR TO USER'S BUFFER
  82.     XOR    A    ; ERROR CODE
  83.     RET
  84. USRSSB:
  85.     DS    2    ; BUFFER FOR ADDRESS OF USER'S SSB
  86.  
  87. ;
  88. ;  SORT -- Sort memory-resident file of fixed-length records in an order
  89. ;    specified by the user;  On entry, DE pts to a SORT Specification
  90. ;    Block (SSB) which contains the following information:
  91. ;
  92. ;        Bytes 0&1:  Starting Address of File (1st byte of 1st record)
  93. ;        Bytes 2&3:  Number of Records in the File
  94. ;        Bytes 4&5:  Size of Each Record (in Bytes)
  95. ;        Bytes 6&7:  Address of a Compare Routine Provided by the User
  96. ;                This routine compares two records, one pted
  97. ;                to by HL and the other pted to by DE; if the
  98. ;                record pted to by DE is less in sorting order
  99. ;                than that pted to by HL, this routine returns
  100. ;                with Carry Set (C); if the records are equal
  101. ;                in sorting order, this routine returns with
  102. ;                Zero Set (Z); no registers asside from the PSW
  103. ;                are to be affected by this routine
  104. ;        Bytes 8&9:  Address of ORDER Buffer (RECNT*2 in size)
  105. ;        Byte 10:  Flag; 0 means to use pointers, 0FFH means to not
  106. ;                use pointers
  107. ;        Byte 11:  Unused
  108. ;
  109. ;    SORT does not have any net affect on any registers
  110. ;
  111.  
  112. ;
  113. ;  SORT SPECIFICATION BLOCK (SSB) FOR USE BY SORT ROUTINE
  114. ;
  115. SSB:
  116. FIRSTP:
  117.     DS    2    ; POINTER TO FIRST RECORD IN FILE
  118. RECNT:
  119.     DS    2    ; NUMBER OF RECORDS IN FILE
  120. RECSIZ:
  121.     DS    2    ; SIZE OF EACH RECORD
  122. CMPADR:
  123.     DS    2    ; ADDRESS OF COMPARE ROUTINE
  124. ORDER:
  125.     DS    2    ; ADDRESS OF ORDER TABLE
  126. SFLAG:
  127.     DS    1    ; USE POINTERS? 0=NO
  128.     DS    1    ; UNUSED, BUT RESERVED, AT THIS TIME
  129.  
  130. ;
  131. ;  SORT AND POINTER BUFFERS
  132. ;
  133. N:
  134.     DS    2    ; NUMBER OF RECS
  135. GAP:
  136.     DS    2    ; VARIABLE GAP
  137. J:
  138.     DS    2    ; REC PTR 1
  139. JG:
  140.     DS    2    ; REC PTR 2
  141. IDX:
  142.     DS    2    ; INDEX PTR
  143. PTPTR:
  144.     DS    2    ; 2-LEVEL INDIRECT PTR
  145. PTFIL:
  146.     DS    2    ; REC PTR
  147.  
  148. ;
  149. ;  START OF SORT ROUTINE
  150. ;
  151. SORT:
  152.     PUSH    HL    ; SAVE REGS
  153.     PUSH    DE
  154.     PUSH    BC
  155.     PUSH    AF
  156.     EX    DE,HL    ; PTR IN HL
  157.     LD    DE,SSB    ; COPY HIS SORT BLOCK INTO MINE FOR EASIER ACCESS
  158.     LD    B,12    ; 12 BYTES LONG
  159.     CALL    MOVEB
  160.     LD    HL,(RECNT)    ; GET RECORD COUNT
  161.     LD    (N),HL    ; SET "N"
  162.     LD    B,H    ; ... IN BC
  163.     LD    C,L
  164.  
  165. ;
  166. ;  CHECK FOR TRIVIAL CASE - 0 OR 1; DON'T DO IT IF SO
  167. ;
  168.     LD    A,B    ; SEE IF BC=1
  169.     OR    A    ; B=0?
  170.     JP    NZ,SHELL    ; DO SORT IF B<>0
  171.     LD    A,C    ; C=0 OR 1?
  172.     CP    2
  173.     JP    C,SEXIT
  174.  
  175. ;
  176. ;  SHELL SORT --
  177. ;    THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS"
  178. ;    BY KERNIGAN AND PLAUGHER, PAGE 106.  COPYRIGHT, 1976, ADDISON-WESLEY.
  179. ;  ON ENTRY, BC=NUMBER OF ENTRIES
  180. ;
  181. SHELL:
  182.     LD    A,(SFLAG)    ; USE POINTERS?
  183.     OR    A        ; 0=NO
  184.     JP    Z,SORT2
  185.     LD    HL,(FIRSTP)    ; PT TO FIRST RECORD
  186.     EX    DE,HL        ; POINTER TO 1ST RECORD IN DE
  187.     LD    HL,(ORDER)    ; PT TO ORDER TABLE
  188. ;
  189. ;  SET UP ORDER TABLE; HL PTS TO NEXT ENTRY IN ORDER TABLE, DE PTS TO NEXT
  190. ;    REC IN FILE, BC = NUMBER OF RECS REMAINING
  191. ;
  192. SORT1:
  193.     LD    A,B    ; DONE?
  194.     OR    C    ; 0 IF SO
  195.     JP    Z,SORT2
  196.     DEC    BC    ; COUNT DOWN
  197.     LD    (HL),E    ; STORE LOW-ORDER ADDRESS
  198.     INC    HL    ; PT TO NEXT ORDER BYTE
  199.     LD    (HL),D    ; STORE HIGH-ORDER ADDRESS
  200.     INC    HL    ; PT TO NEXT ORDER ENTRY
  201.     PUSH    HL    ; SAVE PTR
  202.     LD    HL,(RECSIZ)    ; HL=NUMBER OF BYTES/ENTRY
  203.     ADD    HL,DE    ; PT TO NEXT DIR1 ENTRY
  204.     EX    DE,HL        ; DE PTS TO NEXT ENTRY
  205.     POP    HL    ; GET PTR TO ORDER TABLE
  206.     JP    SORT1
  207. ;
  208. ;  THIS IS THE MAIN SORT LOOP FOR THE SHELL SORT IN "SOFTWARE TOOLS" BY K&P
  209. ;
  210. SORT2:
  211.     LD    HL,(N)    ; NUMBER OF ITEMS TO SORT
  212.     LD    (GAP),HL    ; SET INITIAL GAP TO N FOR FIRST DIVISION BY 2
  213.  
  214. ;  FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
  215. SRTL0:
  216.     OR    A    ; CLEAR CARRY
  217.     LD    HL,(GAP)    ; GET PREVIOUS GAP
  218.     LD    A,H    ; ROTATE RIGHT TO DIVIDE BY 2
  219.     RRA
  220.     LD    H,A
  221.     LD    A,L
  222.     RRA
  223.     LD    L,A
  224.  
  225. ;  TEST FOR ZERO
  226.     OR    H
  227.     JP    Z,SDONE    ; DONE WITH SORT IF GAP = 0
  228.  
  229.     LD    (GAP),HL    ; SET VALUE OF GAP
  230.     LD    (IDX),HL    ; SET I=GAP FOR FOLLOWING LOOP
  231.  
  232. ;  FOR (I = GAP + 1; I <= N; I = I + 1)
  233. SRTL1:
  234.     LD    HL,(IDX)    ; ADD 1 TO I
  235.     INC    HL
  236.     LD    (IDX),HL
  237.  
  238. ;  TEST FOR I <= N
  239.     EX    DE,HL    ; I IS IN DE
  240.     LD    HL,(N)    ; GET N
  241.     LD    A,L    ; COMPARE BY SUBTRACTION
  242.     SUB    E
  243.     LD    A,H
  244.     SBC    A,D    ; CARRY SET MEANS I > N
  245.     JP    C,SRTL0    ; DON'T DO FOR LOOP IF I > N
  246.  
  247.     LD    HL,(IDX)    ; SET J = I INITIALLY FOR FIRST SUBTRACTION OF GAP
  248.     LD    (J),HL
  249.  
  250. ;  FOR (J = I - GAP; J > 0; J = J - GAP)
  251. SRTL2:
  252.     LD    HL,(GAP)    ; GET GAP
  253.     EX    DE,HL    ; ... IN DE
  254.     LD    HL,(J)    ; GET J
  255.     LD    A,L    ; COMPUTE J - GAP
  256.     SUB    E
  257.     LD    L,A
  258.     LD    A,H
  259.     SBC    A,D
  260.     LD    H,A
  261.     LD    (J),HL    ; J = J - GAP
  262.     JP    C,SRTL1    ; IF CARRY FROM SUBTRACTIONS, J < 0 AND ABORT
  263.     LD    A,H    ; J=0?
  264.     OR    L
  265.     JP    Z,SRTL1    ; IF ZERO, J=0 AND ABORT
  266.  
  267. ;  SET JG = J + GAP
  268.     EX    DE,HL        ; J IN DE
  269.     LD    HL,(GAP)    ; GET GAP
  270.     ADD    HL,DE    ; J + GAP
  271.     LD    (JG),HL    ; JG = J + GAP
  272.  
  273. ;  IF (V(J) <= V(JG))
  274.     CALL    ICOMPARE    ; J IN DE, JG IN HL
  275.  
  276. ;  ... THEN BREAK
  277.     JP    C,SRTL1
  278.  
  279. ;  ... ELSE EXCHANGE
  280.     LD    HL,(J)    ; SWAP J, JG
  281.     EX    DE,HL
  282.     LD    HL,(JG)
  283.     CALL    ISWAP    ; J IN DE, JG IN HL
  284.  
  285. ;  END OF INNER-MOST FOR LOOP
  286.     JP    SRTL2
  287.  
  288. ;
  289. ;  SORT IS DONE -- RESTRUCTURE FILE IN SORTED ORDER IN PLACE
  290. ;
  291. SDONE:
  292.     LD    A,(SFLAG)    ; USE POINTERS?
  293.     OR    A    ; 0=NO
  294.     JP    Z,SEXIT    ; DONE IF NO POINTERS
  295.     LD    HL,(RECNT)    ; NUMBER OF RECORDS
  296.     LD    (J),HL    ; SAVE COUNT IN J
  297.     LD    HL,(ORDER)    ; PTR TO ORDERED POINTER TABLE
  298.     LD    (PTPTR),HL    ; SET PTR PTR
  299.     LD    HL,(FIRSTP)    ; PTR TO UNORDERED FILE
  300.     LD    (PTFIL),HL    ; SET PTR TO FILE BUFFER
  301.  
  302. ;  FIND PTR TO NEXT FILE ENTRY
  303. SRTDN:
  304.     LD    HL,(J)    ; GET ENTRY COUNT
  305.     LD    B,H    ; ... IN BC
  306.     LD    C,L
  307.     LD    HL,(PTPTR)    ; PT TO REMAINING POINTERS
  308.     EX    DE,HL        ; ... IN DE
  309.     LD    HL,(PTFIL)    ; HL PTS TO NEXT FILE ENTRY
  310.  
  311. ;  FIND PTR TABLE ENTRY
  312. SRTDN1:
  313.     LD    A,(DE)    ; GET CURRENT POINTER TABLE ENTRY VALUE
  314.     INC    DE    ; PT TO HIGH-ORDER POINTER BYTE
  315.     CP    L    ; COMPARE AGAINST FILE ADDRESS LOW
  316.     JP    NZ,SRTDN2    ; NOT FOUND YET
  317.     LD    A,(DE)    ; LOW-ORDER BYTES MATCH -- GET HIGH-ORDER POINTER BYTE
  318.     CP    H    ; COMPARE AGAINST FILE ADDRESS HIGH
  319.     JP    Z,SRTDN3    ; MATCH FOUND
  320. SRTDN2:
  321.     INC    DE    ; PT TO NEXT PTR TABLE ENTRY
  322.     DEC    BC    ; COUNT DOWN
  323.     LD    A,C    ; END OF TABLE?
  324.     OR    B
  325.     JP    NZ,SRTDN1    ; CONTINUE IF NOT
  326.  
  327. ;  FATAL ERROR -- INTERNAL ERROR; POINTER TABLE NOT CONSISTENT
  328. FERR$PTR:
  329.     CALL    PRINT
  330.     DB    0DH,0AH,'SORT Pointer Error',0
  331.     JP    CPM
  332.  
  333. ;  FOUND THE POINTER TABLE ENTRY WHICH POINTS TO THE NEXT UNORDERED FILE ENTRY
  334. ;    MAKE BOTH POINTERS (PTR TO NEXT, PTR TO CURRENT UNORDERED FILE ENTRY)
  335. ;    POINT TO SAME LOCATION (PTR TO NEXT FILE ENTRY TO BE ORDERED)
  336. SRTDN3:
  337.     LD    HL,(PTPTR)    ; GET PTR TO NEXT ORDERED ENTRY
  338.     DEC    DE    ; DE PTS TO LOW-ORDER POINTER ADDRESS
  339.     LD    A,(HL)    ; MAKE PTR TO NEXT UNORDERED REC PT TO BUFFER FOR
  340.     LD    (DE),A    ;   FILE REC TO BE MOVED TO NEXT UNORDERED FILE POS
  341.     INC    HL    ; PT TO NEXT PTR ADDRESS
  342.     INC    DE
  343.     LD    A,(HL)    ; MAKE HIGH POINT SIMILARLY
  344.     LD    (DE),A
  345.  
  346. ;  INTERCHANGE NEXT ENTRY IN LINE WITH THE ENTRY CURRENTLY IN ITS POSITION
  347.     LD    HL,(RECSIZ)    ; HL=NUMBER OF BYTES/ENTRY
  348.     LD    B,H    ; BC=NUMBER OF BYTES/ENTRY
  349.     LD    C,L
  350.     LD    HL,(PTFIL)    ; PT TO ENTRY
  351.     EX    DE,HL
  352.  
  353. ;  COPY TO-BE-ORDERED FILE ENTRY TO NEXT ORDERED FILE POSITION
  354.     LD    HL,(PTPTR)    ; POINT TO ITS POINTER
  355.     LD    A,(HL)    ; GET LOW-ADDRESS POINTER
  356.     INC    HL
  357.     LD    H,(HL)    ; GET HIGH-ADDRESS POINTER
  358.     LD    L,A    ; HL IS ADDRESS OF UNORDERED ENTRY
  359.     EX    DE,HL    ; HL PTS TO ORDERED ENTRY TO BE MOVED, DE PTS TO REPL
  360. SRTDN4:
  361.     PUSH    BC    ; SAVE COUNT
  362.     LD    A,(DE)    ; GET BYTES
  363.     LD    C,(HL)
  364.     EX    DE,HL    ; EXCHANGE PTRS
  365.     LD    (DE),A    ; PUT BYTE
  366.     LD    (HL),C
  367.     EX    DE,HL    ; RESTORE PTRS TO ORIGINAL
  368.     POP    BC    ; GET COUNT
  369.     INC    HL    ; PT TO NEXT
  370.     INC    DE
  371.     DEC    BC    ; COUNT DOWN
  372.     LD    A,B    ; DONE?
  373.     OR    C
  374.     JP    NZ,SRTDN4
  375.  
  376. ;  POINT TO NEXT TARGET RECORD POSITION
  377.     LD    HL,(RECSIZ)    ; GET SIZE OF RECORD
  378.     EX    DE,HL        ; ... IN DE
  379.     LD    HL,(PTFIL)    ; PT TO ENTRY JUST PLACED
  380.     ADD    HL,DE    ; PT TO NEXT ENTRY
  381.     LD    (PTFIL),HL    ; SET POINTER FOR NEXT LOOP
  382.  
  383. ;  POINT TO NEXT ENTRY IN POINTER TABLE
  384.     LD    HL,(PTPTR)    ; POINTER TO CURRENT REC
  385.     INC    HL    ; PT TO NEXT REC
  386.     INC    HL
  387.     LD    (PTPTR),HL
  388.  
  389. ;  COUNT DOWN
  390.     LD    HL,(J)    ; GET COUNT
  391.     DEC    HL    ; COUNT DOWN
  392.     LD    (J),HL    ; PUT COUNT
  393.     LD    A,H    ; DONE?
  394.     OR    L
  395.     JP    NZ,SRTDN
  396.  
  397. ;  EXIT
  398. SEXIT:
  399.     POP    AF    ; RESTORE REGS
  400.     POP    BC
  401.     POP    DE
  402.     POP    HL
  403.     RET        ; DONE
  404.  
  405. ;
  406. ;  ISWAP -- Perform exchange of elements whose indices are in HL and DE
  407. ;
  408. ISWAP:
  409.     LD    A,(SFLAG)    ; USE POINTERS?
  410.     OR    A    ; 0=NO
  411.     JP    NZ,SWAP    ; DO POINTER SWAP
  412.     CALL    ADRCOMP    ; COMPUTE ADDRESS OF RECORDS FROM THEIR INDICES
  413.     PUSH    HL    ; SAVE HL PTR
  414.     LD    HL,(RECSIZ)    ; SIZE OF RECORD
  415.     LD    B,H    ; ... IN BC
  416.     LD    C,L
  417.     POP    HL    ; GET HL PTR
  418. SWAPC:
  419.     PUSH    BC    ; SAVE COUNT
  420.     LD    A,(DE)    ; GET BYTES
  421.     LD    C,(HL)
  422.     LD    (HL),A    ; PUT BYTES
  423.     LD    A,C
  424.     LD    (DE),A    ; PUT BYTES
  425.     INC    HL    ; PT TO NEXT
  426.     INC    DE
  427.     POP    BC    ; GET COUNT
  428.     DEC    BC    ; COUNT DOWN
  429.     LD    A,B    ; DONE?
  430.     OR    C
  431.     JP    NZ,SWAPC
  432.     RET
  433.  
  434. ;
  435. ;  GIVEN INDICES IN HL AND DE, RETURN ADDRESSES OF RECORDS PTED TO BY
  436. ;    THESE INDICES IN HL AND DE, RESP
  437. ;
  438. ADRCOMP:
  439.     PUSH    HL    ; SAVE HL RECORD
  440.     CALL    ADROFF    ; COMPUTE OFFSET TO RECORD PTED TO BY DE
  441.     LD    (REC1),HL    ; SAVE ADDRESS OF RECORD
  442.     POP    DE    ; GET OLD HL INDEX
  443.     CALL    ADROFF    ; COMPUTE OFFSET TO THE DESIRED RECORD
  444.     EX    DE,HL        ; ADDRESS IN DE
  445.     LD    HL,(REC1)    ; GET ADDRESS
  446.     EX    DE,HL        ; ORIGINAL ORDER
  447.     RET
  448. REC1:
  449.     DS    2    ; TEMP STORAGE FOR SWAPC
  450.  
  451. ADROFF:
  452.     LD    HL,(RECSIZ)    ; SIZE OF RECORD
  453.     LD    B,H    ; ... IN BC
  454.     LD    C,L
  455.     LD    HL,0    ; OFFSET IN HL
  456. ADRO1:
  457.     DEC    DE    ; DECREMENT BY 1 SO BASE-RELATIVE
  458.     LD    A,D    ; DONE WITH LOOP?
  459.     OR    E
  460.     JP    Z,ADRO2
  461.     ADD    HL,BC    ; ADD IN RECORD SIZE
  462.     JP    ADRO1
  463. ADRO2:
  464.     EX    DE,HL    ; OFFSET IN DE
  465.     LD    HL,(FIRSTP)    ; PT TO FIRST ENTRY
  466.     ADD    HL,DE    ; ADD IN OFFSET
  467.     RET
  468.  
  469. ;
  470. ;  SWAP (Exchange) the pointers in the ORDER table whose indexes are in
  471. ;    HL and DE
  472. ;
  473. SWAP:
  474.     PUSH    HL        ; SAVE HL
  475.     LD    HL,(ORDER)        ; ADDRESS OF ORDER TABLE
  476.     LD    B,H        ; ... IN BC
  477.     LD    C,L
  478.     POP    HL
  479.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  480.     ADD    HL,HL        ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
  481.                 ;   OF ORIGINAL HL (0, 2, 4, ...)
  482.     ADD    HL,BC        ; HL NOW PTS TO POINTER INVOLVED
  483.     EX    DE,HL            ; DE NOW PTS TO POINTER INDEXED BY HL
  484.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  485.     ADD    HL,HL        ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
  486.                 ;   OF ORIGINAL DE (0, 2, 4, ...)
  487.     ADD    HL,BC        ; HL NOW PTS TO POINTER INVOLVED
  488.     LD    C,(HL)        ; EXCHANGE POINTERS -- GET OLD (DE)
  489.     LD    A,(DE)        ; -- GET OLD (HL)
  490.     EX    DE,HL            ; SWITCH
  491.     LD    (HL),C        ; PUT NEW (HL)
  492.     LD    (DE),A        ; PUT NEW (DE)
  493.     INC    HL        ; PT TO NEXT BYTE OF POINTER
  494.     INC    DE
  495.     LD    C,(HL)        ; GET OLD (HL)
  496.     LD    A,(DE)        ; GET OLD (DE)
  497.     EX    DE,HL            ; SWITCH
  498.     LD    (HL),C        ; PUT NEW (DE)
  499.     LD    (DE),A        ; PUT NEW (HL)
  500.     RET
  501.  
  502. ;
  503. ;  ICOMPARE - Compares entries whose indices are in HL and DE; on exit,
  504. ;    Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE))
  505. ;
  506. ICOMPARE:
  507.     LD    A,(SFLAG)    ; USE POINTERS?
  508.     OR    A    ; 0=NO
  509.     JP    NZ,COMPARE
  510.     CALL    ADRCOMP    ; COMPUTE ADDRESSES
  511.     JP    CALLCMP    ; CALL COMPARE ROUTINE OF USER
  512.  
  513. ;
  514. ;  COMPARE compares the entry pointed to by the pointer pointed to by HL
  515. ;    with that pointed to by DE (1st level indirect addressing); on entry,
  516. ;    HL and DE contain the numbers of the elements to compare (1, 2, ...);
  517. ;    on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)),
  518. ;    and Non-Zero and No-Carry means ((DE)) > ((HL))
  519. ;
  520. COMPARE:
  521.     PUSH    HL        ; SAVE HL
  522.     LD    HL,(ORDER)    ; ADDRESS OF ORDER
  523.     LD    B,H        ; ... IN BC
  524.     LD    C,L
  525.     POP    HL
  526.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  527.     ADD    HL,HL        ; DOUBLE THE ELEMENT NUMBER TO POINT TO THE PTR
  528.     ADD    HL,BC        ; ADD TO THIS THE BASE ADDRESS OF THE PTR TABLE
  529.     EX    DE,HL        ; RESULT IN DE
  530.     DEC    HL        ; ADJUST INDEX TO 0...N-1 FROM 1...N
  531.     ADD    HL,HL        ; DO THE SAME WITH THE ORIGINAL DE
  532.     ADD    HL,BC
  533.     EX    DE,HL
  534.  
  535. ;
  536. ;  HL NOW POINTS TO THE POINTER WHOSE INDEX WAS IN HL TO BEGIN WITH
  537. ;  DE NOW POINTS TO THE POINTER WHOSE INDEX WAS IN DE TO BEGIN WITH
  538. ;    FOR EXAMPLE, IF DE=5 AND HL=4, DE NOW POINTS TO THE 5TH PTR AND HL
  539. ; TO THE 4TH POINTER
  540. ;
  541.     LD    C,(HL)        ; BC IS MADE TO POINT TO THE OBJECT INDEXED TO
  542.     INC    HL        ; ... BY THE ORIGINAL HL
  543.     LD    B,(HL)
  544.     EX    DE,HL
  545.     LD    E,(HL)        ; DE IS MADE TO POINT TO THE OBJECT INDEXED TO
  546.     INC    HL        ; ... BY THE ORIGINAL DE
  547.     LD    D,(HL)
  548.     LD    H,B        ; SET HL = OBJECT PTED TO INDIRECTLY BY BC
  549.     LD    L,C
  550.  
  551. ;
  552. ;  COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE;
  553. ;    NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE<HL
  554. ;    RET W/ZERO SET MEANS DE=HL
  555. ;
  556. CALLCMP:
  557.     PUSH    HL    ; SAVE HL ON STACK
  558.     LD    HL,(CMPADR)    ; GET ADDRESS OF COMPARE ROUTINE IN HL
  559.     EX    (SP),HL    ; ADDRESS OF COMPARE ROUTINE ON STACK AND RESTORE HL
  560.     RET        ; "CALL" ROUTINE AND RETURN TO SORT CORRECTLY
  561.  
  562.     END
  563.