; SHELL-METZNER SORT
; Call with the following information:
;
; BC  =  Number of records to be sorted
; DE  =  Record length
; HL  =  Buffer address
;
; Comment out the following line if subroutine is
; to be yanked into a file instead of using RMAC/LINK
;
       PUBLIC  SORT
;
TRUE    EQU     255
FALSE   EQU     0
;
ASCEND  EQU     TRUE            ;set FALSE for descending sort
STRIPHI EQU     FALSE           ;true, if high bits not significant
;
SORT:   SHLD    SSTADR
       PUSH    H
       XCHG
       SHLD    SRECLEN
       PUSH    H
       MOV     H,B
       MOV     L,C
       SHLD    SNUMRT
       SHLD    SNUMRW
;
; NOW DIVIDE # OF FIELDS BY 2
;
DIVIDE: LHLD    SNUMRW  ;GET VALUE
       ORA     A               ;CLEAR CARRY
       MOV     A,H
       RAR
       MOV     H,A
       MOV     A,L
       RAR
       MOV     L,A
       SHLD    SNUMRW  ;SAVE RESULT
       MOV     A,L             ;IF SNUMRW<>0
       ORA     H               ;  THEN
       JNZ     NOTDONE         ;    NOT DONE
;
; ALL FIELDS SORTED
;
       POP     B               ;CLEAN UP STACK
       POP     D
       RET
;
NOTDONE:XCHG
       LHLD    SNUMRT
       MOV     A,L
       SUB     E
       MOV     L,A
       MOV     A,H
       SBB     D
       MOV     H,A
       SHLD    SRECLEN
       LXI     H,1
       SHLD    SORTV1
       SHLD    SSTADR
       DCR     L
       POP     B
       PUSH    B
NDONE1: DAD     D
       DCX     B
       MOV     A,B
       ORA     C
       JNZ     NDONE1
       SHLD    SORTV2
       XCHG
       POP     B
       POP     H
       PUSH    H
       PUSH    B
NDONE2: SHLD    SORTV4
       SHLD    SORTV3
       XCHG
       DAD     D
       XCHG
COMPRE: POP     B
       PUSH    B
COMPR1: LDAX    D
       IF      STRIPHI
       ANI     7FH
       PUSH    B
       PUSH    PSW
       MOV     A,M
       ANI     7FH
       MOV     B,A
       POP     PSW
       SUB     B
       POP     B
       ELSE
       SUB     M
       ENDIF
       JNZ     NOTEQU
       INX     H
       INX     D
       DCX     B
       MOV     A,B
       ORA     C
       JNZ     COMPR1
       JMP     NOSWITCH
;
NOTEQU:
       IF      ASCEND
       JNC     NOSWITCH
       ELSE
       JC      NOSWITCH
       ENDIF
SWITCH: PUSH    B
       MOV     B,M
       LDAX    D
       MOV     M,A
       MOV     A,B
       STAX    D
       INX     H
       INX     D
       POP     B
       DCX     B
       MOV     A,B
       ORA     C
       JNZ     SWITCH
       LHLD    SNUMRW
       MOV     A,H
       CMA
       MOV     D,A
       MOV     A,L
       CMA
       MOV     E,A
       LHLD    SORTV1
       DAD     D
       JNC     NOSWITCH
       INX     H
       SHLD    SORTV1
       LHLD    SORTV3
       XCHG
       LHLD    SORTV2
       MOV     A,E
       SUB     L
       MOV     L,A
       MOV     A,D
       SBB     H
       MOV     H,A
       SHLD    SORTV3
       JMP     COMPRE
;
NOSWITCH:
       LHLD    SSTADR
       INX     H
       SHLD    SSTADR
       SHLD    SORTV1
       XCHG
       LHLD    SRECLEN
       MOV     A,L
       SUB     E
       MOV     A,H
       SBB     D
       JC      DIVIDE
       LHLD    SORTV4
       POP     D
       PUSH    D
       DAD     D
       XCHG
       LHLD    SORTV2
       XCHG
       JMP     NDONE2
;.....
;
;
; UTILITY SUBTRACTION SUBROUTINE...
; HL=HL-DE
;
SUBDE:  MOV     A,L
       SUB     E
       MOV     L,A
       MOV     A,H
       SBB     D
       MOV     H,A
       RET
;
SRECLEN:DW      0
SSTADR: DW      0
SORTV1:DW       0
SORTV2:DW       0
SORTV3:DW       0
SORTV4:DW       0
SNUMRT:DW       0
SNUMRW:DW       0