home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / p / z33rcp02.lbr / RCPSUBS.LZB / RCPSUBS.LIB
Encoding:
Text File  |  1993-10-25  |  18.6 KB  |  858 lines

  1.     page
  2.  
  3. ; RCPSUBS.Z80    Subroutines for Z33RCP.Z80
  4.  
  5.  
  6. ;-----------------------------------------------------------------------------
  7.  
  8. ; Display decimal digit routines
  9.  
  10. ;--------------------
  11.  
  12. ; Display hundreds, tens, and units digits (assumes flag in B has been set)
  13.  
  14.      if    regon or spaceon
  15.  
  16. decdsp3:
  17.     ld    de,100        ; Display hundreds
  18.     call    decdsp
  19.     ld    e,10        ; Display tens
  20.     call    decdsp
  21.     ld    a,l        ; Get remaining units value
  22.     add    '0'        ; Convert to character
  23.     jr    conout        ; Print it and return
  24.  
  25. ;--------------------
  26.  
  27. ; Routine to print any single digit
  28.  
  29. ; Actually, this routine displays the value of HL divided by DE and leaves the
  30. ; remainder in HL.  In computing the character to display, it assumes that the
  31. ; result of the division will be a decimal digit.  If the result is zero, the
  32. ; value in the B register, which is the number of digits already printed, is
  33. ; checked.  If it is zero, a space is printed instead of a leading '0'.  If it
  34. ; is not zero, the '0' is printed.  Whenever any digit (not a space) is
  35. ; printed, the value in B is incremented.
  36.  
  37. decdsp:
  38.     ld    c,'0'-1        ; Initialize digit count
  39.     xor    a        ; Clear carry flag
  40.  
  41. decdsp1:
  42.     inc    c        ; Pre-increment the digit
  43.     sbc    hl,de        ; Subtract DE from HL
  44.     jr    nc,decdsp1
  45.  
  46.     add    hl,de        ; Add back in to produce remainder
  47.     ld    a,c        ; Get decimal digit
  48.     cp    '0'        ; Check for leading 0
  49.     jr    nz,decdsp2    ; If not 0, proceed to display it
  50.     ld    a,b        ; Digit printed already?
  51.     or    a
  52.     ld    a,' '        ; Possible space for calling routine to print
  53.     ret    z        ; If no digit printed, return zero flag set
  54. decdsp2:
  55.     inc    b        ; Indicate digit printed
  56.     ld    a,c        ; Else print real digit
  57.                 ; Fall through to CONOUT
  58.  
  59.      endif    ;regon or spaceon
  60.  
  61. ;-----------------------------------------------------------------------------
  62.  
  63. ;  Console Output Routine
  64.  
  65. conout:
  66.     putreg            ; Save all register except AF
  67.     push    af        ; Save AF, too
  68.     and    7fh        ; Mask out MSB
  69.     ld    e,a        ; Transfer character to E
  70.     ld    c,2        ; BDOS conout function number
  71.     call    bdos
  72.     pop    af
  73.     getreg            ; Restore registers
  74. note:                ; Use this RET for NOTE command
  75.     ret
  76.  
  77. ;-----------------------------------------------------------------------------
  78.  
  79. ; String printing routines
  80.  
  81. ;--------------------
  82.  
  83. ; Print string following call (terminated with null or character with the
  84. ; high bit set)
  85.  
  86. print:
  87.     ex    (sp),hl        ; Get address
  88.     call    printhl
  89.     ex    (sp),hl        ; Put address
  90.     ret
  91.  
  92. ;--------------------
  93.  
  94. ; Print string pointed to by HL (terminated with null or character with the
  95. ; high bit set)
  96.  
  97. printhl:
  98.     ld    a,(hl)        ; Get next character
  99.     inc    hl        ; Point to following one
  100.     or    a        ; See if null terminator
  101.     ret    z        ; If so, we are done
  102.     call    conout        ; Display the character
  103.     ret    m        ; We are done if MSB is set (negative number)
  104.     jr    printhl        ; Back for more
  105.  
  106. ;-----------------------------------------------------------------------------
  107.  
  108. ;  OUTPUT NEW LINE TO CON:
  109.  
  110. crlf:
  111.     call    print
  112.     db    cr,lf+80h
  113.     ret
  114.  
  115. ; CONSOLE INPUT
  116.  
  117.      if    eraon or lton or proton    or renon or cpon
  118.  
  119. conin:
  120.     push    hl        ; Save regs
  121.     push    de
  122.     push    bc
  123.     ld    c,1        ; Input
  124.     call    bdos
  125.     pop    bc        ; Get regs
  126.     pop    de
  127.     pop    hl
  128.     and    7fh        ; Mask msb
  129.     cp    61h
  130.     ret    c
  131.     and    5fh        ; To upper case
  132.     ret
  133.  
  134.      endif            ; Eraon or lton or proton or renon or cpon
  135.  
  136. ; SAVE RETURN ADDRESS
  137.  
  138. retsave:
  139.     pop    de        ; Get return address
  140.     pop    hl        ; Get return address to zcpr3
  141.     ld    (z3ret),hl    ; Save it
  142.     push    hl        ; Put return address to zcpr3 back
  143.     push    de        ; Put return address back
  144.     ret
  145.  
  146.      if    spaceon    and [dirsp or cpsp or erasp]
  147. spaexit:
  148.     call    crspace        ; Show space remaining
  149.      endif            ; Spaceon and [dirsp or cpsp or erasp]
  150.  
  151. ; EXIT TO ZCPR3
  152.  
  153. exit:
  154. z3ret    equ    $+1        ; Pointer to in-the-code modification
  155.     ld    hl,0        ; Return address
  156.     jp    (hl)        ; Goto zcpr3
  157.  
  158.  
  159. ; PRINT A DASH
  160.  
  161.      if    lton or    peekon
  162. dash:
  163.     call    print
  164.     db    ' -',' '+80h
  165.     ret
  166.  
  167.      endif            ; Lton or peekon
  168.  
  169. ; PRINT ADDRESS MESSAGE
  170. ;   PRINT ADDRESS IN DE
  171.  
  172.      if    peekon or pokeon
  173.      if    not pokeq
  174. adrat:
  175.     call    print
  176.     db    ' at',' '+80h
  177.     ld    a,d        ; Print high
  178.     call    pahc
  179.     ld    a,e        ; Print low
  180.     jp    pahc
  181.  
  182.      endif            ; Not pokeq
  183.      endif            ; Peekon or pokeon
  184.  
  185. ; EXTRACT HEXADECIMAL NUMBER FROM LINE PTED TO BY HL
  186. ;   RETURN WITH VALUE IN DE AND HL PTING TO OFFENDING CHAR
  187.  
  188.      if    peekon or pokeon or porton
  189.  
  190. hexnum:
  191.     ld    de,0        ; De=accumulated value
  192.     ld    b,5        ; B=char count
  193. hnum1:
  194.     ld    a,(hl)        ; Get char
  195.     cp    ' '+1        ; Done?
  196.     ret    c        ; Return if space or less
  197.     inc    hl        ; Pt to next
  198.     sub    '0'        ; Convert to binary
  199.     jr    c,numerr    ; Return and done if error
  200.     cp    10        ; 0-9?
  201.     jr    c,hnum2
  202.     sub    7        ; A-f?
  203.     cp    10h        ; Error?
  204.     jr    nc,numerr
  205. hnum2:
  206.     ld    c,a        ; Digit in c
  207.     ld    a,d        ; Get accumulated value
  208.     rlca            ; Exchange nybbles
  209.     rlca
  210.     rlca
  211.     rlca
  212.     and    0f0h        ; Mask out low nybble
  213.     ld    d,a
  214.     ld    a,e        ; Switch low-order nybbles
  215.     rlca
  216.     rlca
  217.     rlca
  218.     rlca
  219.     ld    e,a        ; High nybble of e=new high of e,
  220.                 ; Low nybble of e=new low of d
  221.     and    0fh        ; Get new low of d
  222.     or    d        ; Mask in high of d
  223.     ld    d,a        ; New high byte in d
  224.     ld    a,e
  225.     and    0f0h        ; Mask out low of e
  226.     or    c        ; Mask in new low
  227.     ld    e,a        ; New low byte in e
  228.     djnz    hnum1        ; Count down
  229.     ret
  230.  
  231. ; NUMBER ERROR
  232.  
  233. numerr:
  234.     call    print
  235.     db    ' Num','?'+80h
  236.     jp    exit
  237.  
  238. ; SKIP TO NEXT NON-BLANK
  239.  
  240. sksp:
  241.     ld    a,(hl)        ; Get char
  242.     inc    hl        ; Pt to next
  243.     cp    ' '        ; Skip spaces
  244.     jr    z,sksp
  245.     dec    hl        ; Pt to good char
  246.     or    a        ; Set eol flag
  247.     ret
  248.  
  249.      endif            ; Peekon or pokeon or porton
  250.  
  251. ;-----------------------------------------------------------------------------
  252.  
  253. ; Test File in FCB for unambiguity and existence, ask user to delete if so
  254. ;   Return with Z flag set if R/O or no permission to delete
  255.  
  256.      if    renon or cpon
  257. extest:
  258.     call    ambchk        ; Ambiguous file names not allowed
  259.     call    searf        ; Look for specified file
  260.     jr    z,exok        ; Ok if not found
  261.     call    getsbit        ; Position into dir
  262.     inc    de        ; Pt to file name
  263.     ex    de,hl        ; Hl pts to file name
  264.     push    hl        ; Save ptr to file name
  265.     call    prfn        ; Print file name
  266.     pop    hl
  267.     call    rotest        ; Check for r/o
  268.     jr    nz,exer
  269.     call    eraq        ; Erase?
  270.     jr    nz,exer        ; Restart as error if no
  271.     ld    de,fcb1        ; Pt to fcb1
  272.     ld    c,19        ; Delete file
  273.     call    bdos
  274. exok:
  275.     xor    a
  276.     dec    a        ; Nz = ok
  277.     ret
  278. exer:
  279.     xor    a        ; Error flag - file is r/o or no permission
  280.     ret
  281.  
  282.  
  283. ; CHECK FOR AMBIGUOUS FILE NAME IN FCB1
  284. ;   RETURN Z IF SO
  285.  
  286. ambchk:
  287.     ld    hl,fcb1+1    ; Pt to fcb
  288.  
  289. ; CHECK FOR AMBIGUOUS FILE NAME PTED TO BY HL
  290.  
  291. ambchk1:
  292.     push    hl
  293.     ld    b,11        ; 11 bytes
  294. amb1:
  295.     ld    a,(hl)        ; Get char
  296.     and    7fh        ; Mask
  297.     cp    '?'
  298.     jr    z,amb2
  299.     inc    hl        ; Pt to next
  300.     djnz    amb1
  301.     dec    b        ; Set nz flag
  302.     pop    de
  303.     ret
  304. amb2:
  305.     pop    hl        ; Pt to file name
  306.     call    prfn
  307.     call    print
  308.     db    ' is AF','N'+80h
  309.     jp    exit
  310.  
  311.      endif            ; Renon or cpon
  312.  
  313. ; TEST FILE PTED TO BY HL FOR R/O
  314. ;    NZ IF R/O
  315.  
  316.      if    renon or cpon or eraon
  317.  
  318. rotest:
  319.     push    hl        ; Advance to r/o byte
  320.     ld    bc,8        ; Pt to 9th byte
  321.     add    hl,bc
  322.     ld    a,(hl)        ; Get it
  323.     and    80h        ; Mask bit
  324.     push    af
  325.     ld    hl,romsg
  326.     call    nz,printhl    ; Print if nz
  327.     pop    af        ; Get flag
  328.     pop    hl        ; Get ptr
  329.     ret
  330. romsg:
  331.     db    ' is R/','O'+80h
  332.  
  333. ;  CHECK USER TO SEE IF HE APPROVES ERASE OF FILE
  334. ;    RETURN WITH Z IF YES
  335.  
  336. eraq:
  337.     call    print
  338.     db    ' - Eras','e'+80h
  339.      endif            ; Renon or cpon or eraon
  340.  
  341.      if    renon or cpon or eraon or proton
  342. eraq1:
  343.     call    print
  344.     db    ' (Y/N/Q)?',' '+80h
  345.     call    conin        ; Get response
  346.     cp    'Q'        ; Quit command?
  347.     jp    z,exit
  348.     cp    'Y'        ; Key on yes
  349.     ret
  350.  
  351.      endif            ; Renon or cpon or eraon or proton
  352.  
  353. ; INIT FCB1, RETURN WITH DE PTING TO FCB1
  354.  
  355.      if    eraon or lton or cpon
  356. initfcb1:
  357.     ld    hl,fcb1        ; Pt to fcb
  358. initfcb2:
  359.     push    hl        ; Save ptr
  360.     ld    bc,12        ; Pt to first byte
  361.     add    hl,bc
  362.     ld    b,24        ; Zero 24 bytes
  363.     xor    a        ; Zero fill
  364.     call    fillp        ; Fill memory
  365.     pop    de        ; Pt to fcb
  366.     ret
  367.  
  368.      endif            ; Eraon or lton or cpon
  369.  
  370.      if    eraon or lton or cpon or diron
  371.  
  372. fillp:
  373.     ld    (hl),a        ; Store byte
  374.     inc    hl        ; Pt to next
  375.     djnz    fillp        ; Count down
  376.     ret
  377.  
  378.      endif            ; Eraon or lton or cpon or diron
  379.  
  380.  
  381. ;  CHECK FOR USER INPUT; IF ^C, RETURN WITH Z
  382.  
  383.      if    diron or lton or eraon or proton or peekon
  384.  
  385. break:
  386.     push    hl        ; Save regs
  387.     push    de
  388.     push    bc
  389.     ld    c,11        ; Console status check
  390.     call    bdos
  391.     or    a
  392.     ld    c,1        ; Get char if any
  393.     call    nz,bdos
  394.     pop    bc        ; Restore regs
  395.     pop    de
  396.     pop    hl
  397. break1:    cp    ctrlc        ; Check for abort
  398.     jp    z,exit        ; Exit
  399.     cp    ctrlx        ; Skip?
  400.     ret
  401.      endif            ; Diron or lton or eraon or proton or peekon
  402.  
  403. ; AFTER A SEARCH, RETURN NZ SET IF DESIRED TYPE OF FILE FOUND, Z IF NOT
  404. ;   THIS ALGORITHM LOOKS AT THE SYSTEM BIT OF THE LOCATED FILE; THIS
  405. ;   BIT IS SET TO 1 IF THE FILE IS A SYSTEM FILE AND 0 IF NOT A SYSTEM
  406. ;   FILE.  THE FOLLOWING EXCLUSIVE OR MASKS ARE APPLIED TO RETURN Z OR NZ
  407. ;   AS REQUIRED BY THE CALLING PROGRAM:
  408. ;
  409. ;    SYSTEM BYTE: X 0 0 0  0 0 0 0    (AFTER 80H MASK, X=1 IF SYS, 0 IF DIR)
  410. ;
  411. ;    SYS-ONLY   : 0 0 0 0  0 0 0 0    (XOR 0 = 0 if X=0, = 80H if X=1)
  412. ;    DIR-ONLY   : 1 0 0 0  0 0 0 0    (XOR 80H = 80h if X=0, = 0 if X=1)
  413. ;    BOTH       : 0 0 0 0  0 0 0 1    (XOR 1 = 81H or 1H, NZ in both cases)
  414.  
  415.      if    diron or eraon or lton or proton or cpon or renon
  416.  
  417. getsbit:
  418.     dec    a        ; Adjust to returned value
  419.     rrca            ; Convert number to offset into tbuff
  420.     rrca
  421.     rrca
  422.     and    60h
  423.     ld    de,tbuff    ; Pt to buffer
  424.     add    a,e        ; Add entry offset to base addr
  425.     ld    e,a        ; Result in e
  426.     push    de        ; Save ptr in de
  427.     add    10        ; Add offset of 10 to pt to system byte
  428.     ld    e,a        ; Set address
  429.     ld    a,(de)        ; Get byte
  430.     pop    de        ; Get ptr in de
  431.     and    80h        ; Look at only system bit
  432. systst    equ    $+1        ; In-the-code variable
  433.     xor    0        ; If systst=0, sys only; if systst=80h, dir
  434.                 ; Only; if systst=1, both sys and dir
  435.     ret            ; Nz if ok, z if not ok
  436.  
  437.  
  438. ; COPY HL TO DE FOR B BYTES
  439.  
  440. blkmov:
  441.     ld    a,(hl)        ; Get
  442.     ld    (de),a        ; Put
  443.     inc    hl        ; Pt to next
  444.     inc    de
  445.     djnz    blkmov        ; Loop
  446.     ret
  447.  
  448.  
  449. ;  PRINT FILE NOT FOUND MESSAGE
  450.  
  451. prfnf:
  452.     call    print
  453.     db    ' No File','s'+80h
  454.     jp    exit
  455.  
  456. ; LOG INTO USER AREA CONTAINED IN FCB1
  457.  
  458. logusr:
  459.     ld    a,(fcb1+13)    ; Get user number
  460. setusr:
  461.     ld    e,a
  462.     ld    c,32        ; Use bdos fct
  463.     jp    bdos
  464.  
  465.  
  466. ;  PRINT FILE NAME PTED TO BY HL
  467.  
  468. prfn:
  469.     call    print        ; Leading space
  470.     db    ' '+80h
  471.     ld    b,8        ; 8 chars
  472.     call    prfn1
  473.     call    print
  474.     db    '.'+80h        ; Dot
  475.     ld    b,3        ; 3 chars
  476. prfn1:
  477.     ld    a,(hl)        ; Get char
  478.     inc    hl        ; Pt to next
  479.     call    conout        ; Print char
  480.     djnz    prfn1        ; Count down
  481.     ret
  482.  
  483.  
  484. ; SEARCH FOR FIRST
  485.  
  486. searf:
  487.     push    bc        ; Save counter
  488.     push    hl        ; Save hl
  489.     ld    c,17        ; Search for first function
  490. searf1:
  491.     ld    de,fcb1        ; Pt to fcb
  492.     call    bdos
  493.     inc    a        ; Set zero flag for error return
  494.     pop    hl        ; Get hl
  495.     pop    bc        ; Get counter
  496.     ret
  497.  
  498.      endif            ; Diron or eraon or lton or proton or cpon or renon
  499.  
  500. ;-----------------------------------------------------------------------------
  501.  
  502. ; Define buffers as high as possible in TPA for the following groups
  503. ; of commands:
  504. ;    COPY                needs SRCFCB and CBUFF
  505. ;    LIST/TYPE            needs PAGCNT and DIRBUF
  506. ;    ERA, PROT, and DIR commands.    needs DIRBUF
  507. ; If DIRBUF is defined, its value is in HL on return from this code.  The DE
  508. ; register pair is not changed by the code, but the BC pair is affected.
  509.  
  510. dirbufon equ    lton or    diron or eraon or proton
  511.  
  512.      if    dirbufon
  513. dirbuf:    ds    2        ; Address for directory buffer
  514.      endif    ;dirbufon
  515.  
  516.      if    cpon
  517. srcfcb:    ds    2        ; Address of source file FCB (CBUFF address
  518.                 ; ..is in the code)
  519.      endif    ;cpon
  520.  
  521.      if    lton
  522. pagcnt:    ds    2        ; Address for page counter
  523.      endif    ;lton
  524.  
  525.  
  526.      if    cpon or    lton or    eraon or proton    or diron
  527.  
  528. define:
  529.     push    de
  530.     ld    hl,(bdos+1)    ; Get bottom of BDOS
  531.     ex    de,hl        ; ..into DE
  532.     ld    hl,(1)        ; Get BIOS warmboot address into HL
  533.     ld    bc,-[0e00h+800h+3] ; Offset to command processor address
  534.     add    hl,bc
  535.  
  536. ; Now we have to compare and pick the lower address as the top of TPA
  537.  
  538.     push    hl        ; Save CPR address while comparing
  539.     xor    a        ; Clear the carry flag
  540.     sbc    hl,de        ; Compute (CPR-BDOS)
  541.     pop    hl        ; Restore CPR address
  542.     jr    c,define1    ; Branch if BDOS address is higher (use CPR)
  543.     ex    de,hl        ; Otherwise use BDOS address
  544. define1:
  545.  
  546.      if    lton
  547.     dec    hl        ; Put PAGCNT in first free byte at top of TPA
  548.     ld    (pagcnt),hl
  549.      endif    ;lton
  550.  
  551.      if    cpon
  552.     ld    de,-36        ; Calculate place for SRCFCB for copy command
  553.     add    hl,de
  554.     ld    (srcfcb),hl
  555.       if    dirbufon
  556.     push    hl        ; Save if needed below
  557.       endif    ;dirbufon
  558.     ld    de,-[cpblocks*128] ; CBUFF can use same space as DIRBUF
  559.     add    hl,de
  560.     ld    (cbuff),hl
  561.       if    dirbufon
  562.     pop    hl
  563.       endif    ;dirbufon
  564.      endif    ;cpon
  565.  
  566.      if    dirbufon
  567.     ld    de,-[maxdirs*11] ; Space for directory buffer
  568.     add    hl,de
  569.     ld    (dirbuf),hl
  570.      endif
  571.  
  572.     pop    de
  573.     ret
  574.  
  575.      endif    ;cpon or dirbufon
  576.  
  577. ;-----------------------------------------------------------------------------
  578.  
  579. ; SEARCH FOR NEXT
  580.  
  581.      if    diron or eraon or lton or proton
  582.  
  583. searn:
  584.     push    bc        ; Save counter
  585.     push    hl        ; Save hl
  586.     ld    c,18        ; Search for next function
  587.     jr    searf1
  588.  
  589. ; LOAD DIRECTORY AND SORT IT
  590. ;   ON INPUT, A=SYSTST FLAG (0=SYS, 1=DIR, 80H=BOTH)
  591. ;   DIRECTORY IS LOADED INTO BUFFER AT TOP OF TPA
  592. ;   RETURN WITH ZERO SET IF NO MATCH AND HL PTS TO 1ST ENTRY IF MATCH
  593.  
  594. direrr:
  595.     call    print
  596.     db    'DIR Ovf','l'+80h
  597.     jp    exit
  598.  
  599. getdir:
  600.     ld    (systst),a    ; Set system test flag
  601.     call    logusr        ; Log into user area of fcb1
  602.  
  603.     call    define        ; Define buffer addresses
  604.     ld    (hl),0        ; Set empty
  605.     ld    bc,0        ; Set counter
  606.     call    searf        ; Look for match
  607.     ret    z        ; Return if not found
  608.  
  609. ;  STEP 1:  LOAD DIRECTORY
  610.  
  611. gd1:
  612.     push    bc        ; Save counter
  613.     call    getsbit        ; Check for system ok
  614.     pop    bc
  615.     jr    z,gd2        ; Not ok, so skip
  616.     push    bc        ; Save counter
  617.     inc    de        ; Pt to file name
  618.     ex    de,hl        ; Hl pts to file name, de pts to buffer
  619.     ld    b,11        ; Copy 11 bytes
  620.     call    blkmov        ; Do copy
  621.     pop    bc        ; Get counter
  622.     inc    bc        ; Increment counter
  623.     ld    hl,maxdirs-1    ; See if count equals or exceeds MAXDIRS
  624.     ld    a,b        ; Check high bytes
  625.     sub    a,h
  626.     jr    c,gd1a        ; If carry set, we are OK
  627.     ld    a,c        ; Check low bytes
  628.     sub    a,l
  629.     jr    nc,direrr    ; If no carry, jump to error message
  630. gd1a:
  631.     ex    de,hl        ; Hl pts to next buffer location
  632. gd2:
  633.     call    searn        ; Look for next
  634.     jr    nz,gd1
  635.     ld    (hl),0        ; Store ending 0
  636.     ld    hl,(dirbuf)    ; Pt to dir buffer
  637.     ld    a,(hl)        ; Check for empty
  638.     or    a
  639.     ret    z
  640.  
  641. ;  STEP 2:  SORT DIRECTORY
  642.  
  643.     push    hl        ; Save ptr to dirbuf for return
  644.     call    diralpha    ; Sort
  645.     pop    hl
  646.     xor    a        ; Set nz flag for ok
  647.     dec    a
  648.     ret
  649.  
  650.  
  651. ;  DIRALPHA -- ALPHABETIZES DIRECTORY IN DIRBUF; BC CONTAINS
  652. ;    THE NUMBER OF FILES IN THE DIRECTORY
  653.  
  654. diralpha:
  655.  
  656. ;  SHELL SORT --
  657. ;    THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS"
  658. ;    BY KERNIGAN AND PLAUGHER, PAGE 106.  COPYRIGHT, 1976, ADDISON-WESLEY.
  659.  
  660.     ld    h,b        ; Hl=bc=file count
  661.     ld    l,c
  662.     ld    (n),hl        ; Set "N"
  663.     ld    (gap),hl    ; Set initial gap to n for first division by 2
  664.  
  665. ;  FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
  666. srtl0:
  667.     or    a        ; Clear carry
  668. gap    equ    $+1        ; Pointer for in-the-code modification
  669.     ld    hl,0        ; Get previous gap
  670.     ld    a,h        ; Rotate right to divide by 2
  671.     rra
  672.     ld    h,a
  673.     ld    a,l
  674.     rra
  675.     ld    l,a
  676.  
  677. ;  TEST FOR ZERO
  678.     or    h
  679.     ret    z        ; Done with sort if gap = 0
  680.  
  681.     ld    (gap),hl    ; Set value of gap
  682.     ld    (ii),hl        ; Set ii=gap for following loop
  683.  
  684. ;  FOR (II = GAP + 1; II <= N; II = II + 1)
  685. srtl1:
  686. ii    equ    $+1        ; Pointer for in-the-code modification
  687.     ld    hl,0        ; Add 1 to ii
  688.     inc    hl
  689.     ld    (ii),hl
  690.  
  691. ;  TEST FOR II <= N
  692.     ex    de,hl        ; Ii is in de
  693. n    equ    $+1        ; Pointer for in-the-code modification
  694.     ld    hl,0        ; Number of items to sort
  695.     ld    a,l        ; Compare by subtraction
  696.     sub    a,e
  697.     ld    a,h
  698.     sbc    a,d        ; Carry set means ii > n
  699.     jr    c,srtl0        ; Don't do for loop if ii > n
  700.  
  701.     ex    de,hl        ; Set jj = ii initially for first subtraction of gap
  702.     ld    (jj),hl
  703.  
  704. ;  FOR (JJ = II - GAP; JJ > 0; JJ = JJ - GAP)
  705. srtl2:
  706.     ld    hl,(gap)    ; Get gap
  707.     ex    de,hl        ; In de
  708. jj    equ    $+1        ; Pointer for in-the-code modification
  709.     ld    hl,0        ; Get jj
  710.     ld    a,l        ; Compute jj - gap
  711.     sub    a,e
  712.     ld    l,a
  713.     ld    a,h
  714.     sbc    a,d
  715.     ld    h,a
  716.     ld    (jj),hl        ; Jj = jj - gap
  717.     jr    c,srtl1        ; If carry from subtractions, jj < 0 and abort
  718.     or    l        ; Jj=0?
  719.  
  720.     jr    z,srtl1        ; If zero, jj=0 and abort
  721.  
  722. ;  SET JG = JJ + GAP
  723.     ex    de,hl        ; Jj in de
  724.     ld    hl,(gap)    ; Get gap
  725.     add    hl,de        ; Jj + gap
  726.     ld    (jg),hl        ; Jg = jj + gap
  727.  
  728. ;  IF (V(JJ) <= V(JG))
  729.     call    icompare    ; J in de, jg in hl
  730.  
  731. ;  ... THEN BREAK
  732.     jr    c,srtl1
  733.  
  734. ;  ... ELSE EXCHANGE
  735.     ld    hl,(jj)        ; Swap jj, jg
  736.     ex    de,hl
  737. jg    equ    $+1        ; Pointer for in-the-code modification
  738.     ld    hl,0
  739.     call    iswap        ; Jj in de, jg in hl
  740.  
  741. ;  END OF INNER-MOST FOR LOOP
  742.     jr    srtl2
  743.  
  744.  
  745. ;  SWAP (Exchange) the elements whose indexes are in HL and DE
  746.  
  747. iswap:
  748.     call    ipos        ; Compute position from index
  749.     ex    de,hl
  750.     call    ipos        ; Compute 2nd element position from index
  751.     ld    b,11        ; 11 bytes to flip
  752.      endif            ; Diron or eraon or lton or proton
  753.  
  754.      if    diron or eraon or lton or proton or renon
  755. iswap1:
  756.     ld    a,(de)        ; Get bytes
  757.     ld    c,(hl)
  758.     ld    (hl),a        ; Put bytes
  759.     ld    a,c
  760.     ld    (de),a
  761.     inc    hl        ; Pt to next
  762.     inc    de
  763.     djnz    iswap1
  764.     ret
  765.      endif            ; Diron or eraon or lton or proton or renon
  766.  
  767.      if    diron or eraon or lton or proton
  768.  
  769. ;  ICOMPARE compares the entry pointed to by the pointer pointed to by HL
  770. ;    with that pointed to by DE (1st level indirect addressing); on entry,
  771. ;    HL and DE contain the numbers of the elements to compare (1, 2, ...);
  772. ;    on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)),
  773. ;    and Non-Zero and No-Carry means ((DE)) > ((HL))
  774.  
  775. icompare:
  776.     call    ipos        ; Get position of first element
  777.     ex    de,hl
  778.     call    ipos        ; Get position of 2nd element
  779.     ex    de,hl
  780.  
  781. ;  COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE;
  782. ;    NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE<HL
  783. ;    RET W/ZERO SET MEANS DE=HL
  784.  
  785.      if    not sortnt    ; Type and name?
  786.  
  787. ;  COMPARE BY FILE TYPE AND FILE NAME
  788.  
  789.     push    hl
  790.     push    de
  791.     ld    bc,8        ; Pt to ft (8 bytes)
  792.     add    hl,bc
  793.     ex    de,hl
  794.     add    hl,bc
  795.     ex    de,hl        ; De, hl now pt to their ft's
  796.     ld    b,3        ; 3 bytes
  797.     call    comp        ; Compare ft's
  798.     pop    de
  799.     pop    hl
  800.     ret    nz        ; Continue if complete match
  801.     ld    b,8        ; 8 bytes
  802. ; FALL THROUGH TO COMP
  803.  
  804.      else            ; Name and type
  805.  
  806. ;  COMPARE BY FILE NAME AND FILE TYPE
  807.  
  808.     ld    b,11        ; Compare fn, ft and fall thru to comp
  809.  
  810.      endif            ; Not sortnt
  811.      endif            ; Diron or eraon or lton or proton
  812.  
  813.      if    diron or eraon or lton or proton or cpon or whlon
  814.  
  815. ;  COMP COMPARES DE W/HL FOR B BYTES; RET W/CARRY IF DE<HL
  816. ;    MSB IS DISREGARDED
  817.  
  818. comp:
  819.     ld    a,(hl)        ; Get (hl)
  820.     and    7fh        ; Mask msb
  821.     ld    c,a        ; In c
  822.     ld    a,(de)        ; Compare
  823.     and    7fh        ; Mask msb
  824.     cp    c
  825.     ret    nz
  826.     inc    hl        ; Pt to next
  827.     inc    de
  828.     djnz    comp        ; Count down
  829.     ret
  830.  
  831.      endif            ; Diron or eraon or lton or proton or cpon or
  832.                 ; whlon
  833.  
  834.      if    diron or eraon or lton or proton
  835.  
  836. ;  Compute physical position of element whose index is in HL; on exit, HL
  837. ; is the physical address of this element; Indexes are 1..N
  838.  
  839. ipos:
  840.     dec    hl        ; We want HL=(HL-1)*11+(DIRBUF)
  841.     ld    b,h        ; Bc=hl
  842.     ld    c,l
  843.     add    hl,hl        ; Hl=hl*2
  844.     add    hl,hl        ; Hl=hl*4
  845.     add    hl,bc        ; Hl=hl*5
  846.     add    hl,hl        ; Hl=hl*10
  847.     add    hl,bc        ; Hl=hl*11
  848.     ld    b,h        ; Move offset into BC
  849.     ld    c,l
  850.     ld    hl,(dirbuf)
  851.     add    hl,bc
  852.     ret
  853.  
  854.      endif            ; Diron or eraon or lton or proton
  855.  
  856. ; End RCPSUBS.Z80
  857.  
  858.