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 / BEEHIVE / COMMS / ZMP-OV16.ARC / ZMO-KP05.Z80 < prev    next >
Text File  |  1991-02-02  |  17KB  |  679 lines

  1. ;
  2. ;    Overlay to ZMP (Z-Modem Program), for the Kaypro CP/M computers.
  3. ;        (Z80 SIO and 8116 baudrate generator.)
  4. ;
  5. ;    Name:  ZMO-KP05.MAC
  6. ;
  7. ;    Dated: November 25, 1988
  8. ;
  9. ;    Written by -
  10. ;      Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia.
  11. ;
  12. ;    KP05 - Nov. 24, 88. Updated for ZMP version 1.4 (overlay drive/user
  13. ;            equates).  Added conditional to check RTS/CTS signals.
  14. ;            Bill Duerr, GEnie ID: B.DUERR
  15. ;                    DKUG RBBS [313] 772-0522
  16. ;
  17. ;    KP04 - Oct. 22, 88. Updated to allow program to be reentered properly,
  18. ;            for 8-N-1 only -- still problems with even/odd parity.
  19. ;            Bill Duerr, GEnie ID: B.DUERR
  20. ;                    DKUG RBBS [313] 772-0522
  21. ;
  22. ;    KP03 - Oct. 12, 88 Modified to ZMP v1.3 standard rjm
  23. ;
  24. ;
  25. ;    Insert your own code as necessary in this file. Code contained herein
  26. ; has been written in Z80 code for use with M80. Once assembled,
  27. ; convert to hex with RELHEX and use MLOAD to overlay it over the main
  28. ; ZMPX.COM file to produce your very own ZMP.COM.
  29. ;
  30. ; Notes on modifying this file:
  31. ;    Hi-Tech C requires that functions do not change either index register
  32. ; (IX or IY). If your overlay requires either of these to be changed, ensure
  33. ; they are restored to their original values on return.
  34. ;    Since collecting parameters from C functions can be tricky, only change
  35. ; the parts marked 'Insert your own code here'. Do NOT modify the jump
  36. ; table at the start. Do NOT modify the entry/exit sections of each
  37. ; function. Do NOT pass 'GO'. Do NOT collect $200.
  38. ;    Apart from defining modem functions, this file also defines terminal
  39. ; characteristics. Most have been set up for ADM-3A (with a few of my own
  40. ; additions). Modify to suit your own terminal. An inline print routine
  41. ; is provided for printing strings in the usual way: usage is
  42. ;
  43. ;    call    print
  44. ;    db    'required string',0
  45. ;
  46. ;    Don't forget to set your clock speed at the clkspd variable.
  47. ;
  48. ;    If you find your overlay exceeds the maximum size (currently 0400h),
  49. ; you will have to re-compile the whole thing. Good luck. You might try
  50. ; informing us if you need to do this: if too many people need to do it, we
  51. ; haven't allowed enough room.
  52. ;
  53. ; Ron Murray 15/8/88
  54. ;
  55. ;
  56. false    equ    0
  57. true    equ    not false
  58. ;
  59. ; If the following equate is set to true, code will be added to set
  60. ; the RTS modem signal, telling the modem not to send any characters
  61. ; till RTS is reset, and also to check CTS if characters may be sent.
  62. ; This allows the Kaypro screen to keep up with the characters sent
  63. ; over the modem lines at higher speeds.  (The modem must be able to
  64. ; recognize RTS and set CTS for this to work.)
  65. ;
  66. rtscts    equ    false
  67. ;
  68. ;Set the following two equates to the drive and user area which will contain
  69. ;   ZMP's .OVR files, .CFG file, .FON file and .HLP file.  Set both to zero
  70. ;   (null) to locate them on the drive from which ZMP was invoked.
  71.  
  72. overdrive    equ    'A'    ; Drive to find overlay files on ('A'-'P')
  73. overuser    equ    0    ; User area to find files
  74.  
  75. ;------------------------------------------------------------------------------
  76.  
  77. ;User-set variables:
  78. clkspd    equ    4        ; Processor clock speed in MHz
  79. mspeed    equ    003ch        ; Current baud rate: as used by BYE etc
  80.                 ; This MUST be the same as Mspeed in
  81.                 ; ZMP.H
  82.  
  83.  
  84. dport    equ    04h        ; Kaypro SIO data port
  85. sport    equ    dport+2        ; Modem control port
  86. mdrcv    equ    01h        ; Modem receive ready
  87. mdsnd    equ    04h        ; Modem send ready bit
  88. mdtxe    equ    01h        ; Modem send buffer empty, holding buffer empty
  89. rsterr    equ    30h        ; Reset parity and overrun flags - register 0
  90. reg1ins    equ    0        ; No interrupts - register 1
  91. reg3ins    equ    0c1h        ; 8 Rx bits, Rx enable
  92. reg4ins    equ    44h        ; 16X baud rate, 1 stop bit, no parity
  93. reg5ins    equ    0eah        ; 8 Tx bits, Tx enable, RTS, DTR
  94.  
  95. bauda    equ    00h        ; 8116 port for baudrate
  96. rstsio    equ    18h        ; Reset the SIO
  97. dcd    equ    08h        ; Data Carrier Detect
  98. dtr    equ    80h        ; Data Terminal Ready
  99. rts    equ    02h        ; Request to send
  100. cts    equ    20h        ; Clear to send
  101. brk    equ    10h        ; SIO Break
  102. sioerr    equ    70h        ; SIO error
  103.  
  104. userdef    equ    00145h        ; origin of this overlay: get this value
  105.                 ; from the .SYM file produced when ZMP.COM
  106.                 ; is linked
  107. ovsize    equ    0400h        ; max size of this overlay
  108.  
  109.     .z80            ; use z80 code
  110.     aseg            ; absolute
  111.  
  112.     org    userdef
  113.  
  114. esc    equ    1bh
  115. ctrlq    equ    11h
  116. cr    equ    0dh
  117. lf    equ    0ah
  118. bdos    equ    5
  119.  
  120. ;Jump table for the overlay: do NOT change this
  121.  
  122. jump_tab:
  123.     jp    scrnpr        ; screen print
  124.     jp    mrd        ; modem read with timeout
  125.     jp    mchin        ; get a character from modem
  126.     jp    mchout        ; send a character to the modem
  127.     jp    mordy        ; test for tx buffer empty
  128.     jp    mirdy        ; test for character received
  129.     jp    sndbrk        ; send break
  130.     jp    cursadd        ; cursor addressing
  131.     jp    cls        ; clear screen
  132.     jp    invon        ; inverse video on
  133.     jp    invoff        ; inverse video off
  134.     jp    hide        ; hide cursor
  135.     jp    show        ; show cursor
  136.     jp    savecu        ; save cursor position
  137.     jp    rescu        ; restore cursor position
  138.     jp    mint        ; service modem interrupt
  139.     jp    invec        ; initialise interrupt vectors
  140.     jp    dinvec        ; de-initialise interrupt vectors
  141.     jp    mdmerr        ; test uart flags for error
  142.     jp    dtron        ; turn DTR on
  143.     jp    dtroff        ; turn DTR OFF
  144.     jp    init        ; initialise uart
  145.     jp    wait        ; wait seconds
  146.     jp    mswait        ; wait milliseconds
  147.     jp    userin        ; user-defined entry routine
  148.     jp    userout        ; user-defined exit routine
  149.     jp    getvars        ; get system variables
  150.  
  151. ; Spare jumps for compatibility with future versions
  152.     jp    spare        ; spare for later use
  153.     jp    spare        ; spare for later use
  154.     jp    spare        ; spare for later use
  155.     jp    spare        ; spare for later use
  156.     jp    spare        ; spare for later use
  157.     jp    spare        ; spare for later use
  158.  
  159. ;
  160. ; Main code starts here
  161. ;
  162. codebgn    equ    $
  163. ;
  164. ;Screen print function
  165. scrnpr:
  166.                 ; <== Insert your own code here
  167.     call    print
  168.     db    'This function not supported.',cr,lf,0
  169.                 ; <== End of your own code
  170. spare:
  171.     ret
  172.  
  173. ; User-defined entry routine
  174. userin:
  175.     ret
  176. ; User-defined exit routine
  177. userout:            ; Leave RTS off
  178.     if    rtscts
  179.     ld    a,05h        ; Select register 5
  180.     out    (sport),a    ; Send to the status port
  181.     ld    a,(reg5)    ; Get register 5 settings
  182.     and    255-rts        ; Turn off RTS
  183.     out    (sport),a    ; Send to the status port
  184.     endif            ; rtscts
  185.     ret
  186.  
  187. ;Get a character from the modem: return in HL
  188. ; It is not necessary to test for status
  189. mchin:
  190. ;-- Code added specific to Kaypro
  191.     in    a,(dport)    ; get the character in A
  192. ;
  193. ; This routine checks parity, and if parity is not "none", strips high bit.
  194. ; This is needed, even if the filter is turned on, because CONNECT message
  195. ; is not filtered.
  196. ;
  197.     ld    l,a        ; Save in L
  198.     ld    a,(parity)    ; Check parity
  199.     cp    'N'        ; No parity?
  200.     ld    a,l        ; Get the character back
  201.     jr    z,mchin1    ; Bypass following kludge
  202.     and    7fh
  203.     ld    l,a        ; put in HL
  204. mchin1:
  205.     if    rtscts
  206.     ld    a,05h        ; Select register 5
  207.     out    (sport),a    ; Send to the status port
  208.     ld    a,(reg5)    ; Get register 5 settings
  209.     and    255-rts        ; Turn off RTS
  210.     out    (sport),a    ; Send to the status port
  211.     endif            ; rtscts
  212. ;-- End of this block of machine specific code
  213.     ld    a,l        ; get character from HL
  214.     ld    h,0
  215.     or    a        ; set/clear Z
  216.     ret
  217.  
  218. ;Send a character to the modem
  219. mchout:
  220.     ld    hl,2        ; Get the character
  221.     add    hl,sp
  222.     ld    a,(hl)        ; in A
  223. ;-- Code added specific to Kaypro
  224.     out    (dport),a    ; Put the character to the serial port
  225. ;-- End of this block of machine specific code
  226.     ret            ; done
  227.  
  228. ;Test for output ready: return TRUE (1) in HL if ok
  229. mordy:
  230. ;-- Code added specific to Kaypro
  231.     ld    hl,0        ; Assume not ready
  232. ;
  233.     if    rtscts
  234.     ld    a,10h        ; Reset register 0
  235.     out    (sport),a    ; Send to the status port
  236.     in    a,(sport)    ; read status port
  237.     and    cts        ; Is clear to send up
  238.     jr    z,mordy1    ; Branch if not clear to send
  239.     endif            ; rtscts
  240. ;
  241.     ld    a,10h        ; Reset register 0
  242.     out    (sport),a    ; Send to the status port
  243.     in    a,(sport)    ; Read status port
  244.     and    mdsnd        ; Isolate transmit empty bit
  245.     jr    z,mordy1    ; Branch if not ready
  246.     inc    hl        ; otherwise set HL to indicate ready
  247. mordy1:
  248. ;-- End of this block of machine specific code
  249.     ld    a,l
  250.     or    a        ; set/clear Z
  251.     ret
  252.  
  253. ;Test for character at modem: return TRUE (1) in HL if so
  254. mirdy:
  255. ;-- Code added specific to Kaypro
  256.     ld    a,05h        ; Select register 5
  257.     out    (sport),a    ; Send to the status port
  258.     ld    a,(reg5)    ; Get register 5 settings
  259.     or    rts        ; Turn on RTS
  260.     out    (sport),a    ; Send to the status port
  261.     ld    hl,0        ; Assume not ready
  262.     ld    a,10h        ; Reset register 0
  263.     out    (sport),a    ; Send to the status port
  264.     in    a,(sport)    ; Get the status
  265.     and    mdrcv        ; Isolate receive ready bit
  266.     jr    z,mirdy1    ; Branch if not ready
  267.     inc    hl        ; otherwise set HL to indicate ready
  268. mirdy1:
  269. ;-- End of this block of machine specific code
  270.     ld    a,l
  271.     or    a        ; set/clear Z
  272.     ret
  273.  
  274. ;Send a break to the modem: leave empty if your system can't do it
  275. sndbrk:
  276. ;-- Code added specific to Kaypro
  277.     ld    a,5        ; Select register 5
  278.     out    (sport),a    ; Send to the status port
  279.     ld    a,(reg5)    ; Get parameters for register 5
  280.     or    brk        ; Set the break tone
  281.     out    (sport),a    ; Send to the status port
  282. ;-- End of this block of machine specific code
  283.     ld    hl,300
  284.     call    waitms        ; wait 300 mS
  285. ;-- Code added specific to Kaypro
  286.     ld    a,5        ; Select register 5
  287.     out    (sport),a    ; Send to the status port
  288.     ld    a,(reg5)    ; Restore register 5 settings
  289.     out    (sport),a    ; Send to the status port
  290. ;-- End of this block of machine specific code
  291.     ret
  292.  
  293. ;Test UART flags for error: return TRUE (1) in HL if error
  294. mdmerr:
  295. ;-- Code added specific to Kaypro
  296.     ld    hl,0        ; Assume no error
  297.     ld    a,011h        ; Select read register 1
  298.     out    (sport),a    ; Send to the status port
  299.     in    a,(sport)    ; Get error status
  300.     and    sioerr        ; Mask all but error bits
  301.     ret    z        ; Return zeor in HL if no error
  302.     inc    hl        ; Otherwise set HL to indicate error
  303.     ret            ; Return
  304.  
  305.  
  306. ;Turn DTR (and optionally RTS) ON.
  307. dtron:
  308. ;-- Code added specific to Kaypro
  309.     ld    a,05h        ; Select register 5
  310.     out    (sport),a    ; Send to the status port
  311.     ld    a,(reg5)    ; Get register 5 settings
  312.     out    (sport),a    ; Send to the status port
  313. ;-- End of this block of machine specific code
  314.     ret
  315.  
  316. ;Turn DTR ( and RTS?) OFF
  317. dtroff:
  318. ;-- Code added specific to Kaypro
  319.     ld    a,05h        ; Select register 5
  320.     out    (sport),a    ; Send to the status port
  321.     ld    a,(reg5)    ; Get register 5 settings
  322.     and    255-dtr        ; Turn off DTR
  323.     out    (sport),a    ; Send to the status port
  324. ;-- End of this block of machine specific code
  325.     ret
  326.  
  327. ;Initialise the UART
  328. init:
  329.     ld    hl,2        ; get parameters
  330.     add    hl,sp
  331.     ld    a,(hl)        ; get lo
  332.     ld    (mspeed),a    ; save in baud rate low memory
  333.     inc    hl
  334.     inc    hl        ; bump for next
  335.     ld    a,(hl)        ; get lo
  336.     and    5Fh        ; Convert to upper case
  337.     ld    (parity),a    ; parity
  338.     inc    hl
  339.     inc    hl        ; bump for next
  340.     ld    a,(hl)        ; get lo
  341.     and    0fh        ; Make sure binary
  342.     ld    (data),a    ; Save data bits
  343.     cp    7        ; but 7 if required
  344.     ld    a,reg5ins    ; 8 Tx bits, Tx enable, RTS, DTR
  345.     jr    nz,setbs
  346.     ld    a,reg5ins-040h    ; Turn bit off
  347. setbs:
  348.     ld    (reg5),a
  349.     inc    hl
  350.     inc    hl        ; bump for next
  351.     ld    a,(hl)        ; get lo
  352.     and    0fh        ; Make sure binary
  353.     ld    (stop),a    ; stop bits
  354.                 ; <== Insert your own code here
  355. ;-- Code added specific to Kaypro
  356.     ld    a,10h        ; Reset register 0
  357.     out    (sport),a    ; Send to the status port
  358.     in    a,(sport)    ; read status port
  359.     and    DCD        ; Is carrier up
  360.     jr    nz,initr    ; Branch if carrier already there
  361.     ld    A,0        ; Select register 0
  362.     out    (sport),a    ; Send to status port
  363.     ld    a,rstsio    ; Reset SIO - 18h
  364.     out    (sport),a    ; Send to status port
  365. ;
  366.     ld    A,4        ; Select register 4
  367.     out    (sport),a    ; Send to status port
  368.     ld    a,(parity)    ; do parity
  369.     ld    e,003h        ; assume even parity
  370.     cp    'E'        ; even?
  371.     jr    z,setstop    ; yes
  372.     ld    e,001h        ; try odd
  373.     cp    'O'
  374.     jr    z,setstop
  375.     ld    e,0        ; Indicate no parity
  376. setstop:
  377.     ld    a,(stop)    ; set stop bits
  378.     cp    2
  379.     ld    a,reg4ins    ; 16X baud rate, 1 stop bit, no parity
  380.     jr    nz,onestop
  381.     or    00ch        ; set bits 2 and 3
  382. onestop:
  383.     or    e        ; put parity bits in the register
  384. ;
  385.     out    (sport),a    ; Send to status port
  386. ;
  387.     ld    a,3        ; Select register 3
  388.     out    (sport),a    ; Send to status port
  389. ;
  390.     ld    a,(data)    ; get data bits parameter field
  391.     cp    7        ; is 7 required
  392.     ld    a,reg3ins    ; 8 Rx bits, Rx enable
  393.     jr    nz,setbr
  394.     and    07fh
  395. setbr:
  396.     out    (sport),a    ; Set Rx bits
  397.     ld    a,5        ; Select register 5
  398.     out    (sport),a    ; Send to status port
  399.     ld    a,(reg5)    ; Get register 5 settings
  400.     out    (sport),a    ; Set tx bits
  401. ;
  402.     ld    a,1        ; Select register 1
  403.     out    (sport),a
  404.     ld    a,reg1ins    ; No interrupts
  405.     out    (sport),a    ; Send to status port
  406. ;
  407.     ld    a,(mspeed)    ; set baud rate: get index
  408.     ld    hl,brval
  409.     ld    e,a        ; rate to DE
  410.     ld    d,0
  411.     add    hl,de
  412.     ld    a,(hl)        ; get baud rate value
  413.     out    (bauda),a
  414.                 ; <== End of your own code
  415. initr:    ret
  416.  
  417. ;
  418. ; Baud rate factors, output to bauda to select baud rate
  419. ;
  420. bd10    equ    02h        ; 110 baud rate     0
  421. bd30    equ    05h        ; 300 baud rate     1
  422. bd12    equ    07h        ; 1200 baud rate    5
  423. bd24    equ    0ah        ; 2400 baud rate    6
  424. bd48    equ    0ch        ; 4800 baud rate    7
  425. bd96    equ    0eh        ; 9600 baud rate    8
  426. bd19k    equ    0fh        ; 19.2k baud rate    9
  427.  
  428.  
  429. ;Values for control reg for each baud rate: 0 if invalid
  430. brval:
  431. ;         0, 1, 2, 3, 4, 5, 6, 7, 8, 9
  432.     db    00,01,00,00,00,07,10,12,14,15
  433.  
  434.                 ; <== End of your own code
  435.     ret
  436.  
  437. brate:    db    6,0        ; baud rate:
  438.                 ; 0 = 110 baud    1 = 300 baud    2 = 450 baud
  439.                 ; 3 = 600 baud    4 = 710 baud    5 = 1200 baud
  440.                 ; 6 = 2400 baud 7 = 4800 baud    8 = 9600 baud
  441.                 ; 9 = 19200 baud
  442. parity:    db    'N',0        ; parity (will be 'N', 'E' or 'O')
  443. data:    db    8,0        ; data bits (will be 7 or 8)
  444. stop:    db    1,0        ; stop bits (will be 1 or 2)
  445. reg5:    db    reg5ins
  446.  
  447. ;****************************************************************************
  448. ;Video terminal sequences: these are for ADM-3A: Modify as you wish
  449. ;Cursor addressing:
  450. cursadd:
  451.     ld    hl,2        ; get parameters
  452.     add    hl,sp
  453.     ex    de,hl
  454.     call    getparm        ; in HL
  455.     ld    (row),hl    ; row
  456.     call    getparm
  457.     ld    (col),hl    ; column
  458.                 ; <== Insert your own code here
  459.                 ; using values in row and col
  460.     call    print
  461.     db    esc,'=',0    ; ADM-3A leadin
  462.     ld    a,(row)        ; row first
  463.     add    a,' '        ; add offset
  464.     call    cout
  465.     ld    a,(col)        ; sane for column
  466.     add    a,' '
  467.     call    cout
  468.                 ; <== end of your own code
  469.     ret
  470.  
  471. row:    ds    2        ; row
  472. col:    ds    2        ; column
  473.  
  474.  
  475. ;Clear screen:
  476. cls:
  477.     call    print
  478.     db    01ah,0
  479.     ret
  480.  
  481. ;Inverse video on:
  482. invon:
  483.     call    print
  484.     db    esc,')',0
  485.     ret
  486.  
  487. ;Inverse video off:
  488. invoff:
  489.     call    print
  490.     db    esc,'(',0
  491.     ret
  492.  
  493. ;Turn off cursor:
  494. hide:
  495.     call    print
  496.     db    esc,'z',0
  497.     ret
  498.  
  499. ;Turn on cursor:
  500. show:
  501.     call    print
  502.     db    esc,'v',0
  503.     ret
  504.  
  505. ;Save cursor position:
  506. savecu:
  507.     ret
  508.  
  509. ;Restore cursor position:
  510. rescu:
  511.     ret
  512.  
  513. ;****************************************************************************
  514.  
  515. ;Service modem interrupt:
  516. mint:
  517.     ret            ; my system doesn't need this
  518.  
  519. ;Initialise interrupt vectors:
  520. invec:
  521.     ret            ; ditto
  522.  
  523. ;De-initialise interrupt vectors:
  524. dinvec:
  525.     ret            ; ditto
  526.  
  527. ;****************** End of user-defined code ********************************
  528. ; Don't change anything below this point. We needed some assembly language
  529. ; stuff for speed, and this seemed like a good place to put it.
  530.  
  531. ;Modem character test for 100 ms
  532. mrd:
  533.     push    bc        ; save bc
  534.     ld    bc,100        ; set limit
  535. mrd1:
  536.     call    mirdy        ; character at modem?
  537.     jr    nz,mrd2        ; yes, exit
  538.     ld    hl,1        ; else wait 1ms
  539.     call    waitms
  540.     dec    bc        ; loop till done
  541.     ld    a,b
  542.     or    c
  543.     jr    nz,mrd1
  544.     ld    hl,0        ; none there, result=0
  545.     xor    a
  546. mrd2:
  547.     pop    bc
  548.     ret
  549.  
  550. ; Inline print routine: destroys A and HL
  551.  
  552. print:
  553.     ex    (sp),hl        ; get address of string
  554. ploop:
  555.     ld    a,(hl)        ; get next
  556.     inc    hl        ; bump pointer
  557.     or    a        ; done if zero
  558.     jr    z,pdone
  559.     call    cout        ; else print
  560.     jr    ploop        ; and loop
  561. pdone:
  562.     ex    (sp),hl        ; restore return address
  563.     ret            ; and quit
  564.  
  565. ;
  566. ;Output a character in A to the console
  567. ;
  568. cout:
  569.     push    bc        ; save regs
  570.     push    de
  571.     push    hl
  572.     ld    e,a        ; Save the character to E for BDOS routine
  573.     ld    c,2        ; BDOS conout routine
  574.     call    bdos        ; print it
  575.     pop    hl
  576.     pop    de
  577.     pop    bc
  578.     ret
  579.  
  580. ;Wait(seconds)
  581. wait:
  582.     ld    hl,2
  583.     add    hl,sp
  584.     ex    de,hl        ; get delay size
  585.     call    getparm
  586.                 ; fall thru to..
  587. ;Wait seconds in HL
  588. waits:
  589.     push    bc        ; save bc
  590.     push    de        ; de
  591.     push    ix        ; and ix
  592.     ld    ix,0        ; then point ix to 0
  593.                 ; so we don't upset memory-mapped i/o
  594.  
  595. ;Calculate values for loop constants. Need to have two loops to avoid
  596. ;   16-bit overflow with clock speeds above 9 MHz.
  597.  
  598. outerval    equ    (clkspd    / 10) +    1
  599. innerval    equ    (6667 /    outerval) * clkspd
  600.  
  601. wait10:
  602.     ld    b,outerval
  603.  
  604. wait11:
  605.     ld    de,innerval
  606.  
  607. wait12:
  608.     bit    0,(ix)        ; time-wasters
  609.     bit    0,(ix)
  610.     bit    0,(ix)        ; 20 T-states each
  611.     bit    0,(ix)
  612.     bit    0,(ix)
  613.     bit    0,(ix)
  614.     dec    de
  615.     ld    a,e
  616.     ld    a,d
  617.     or    e
  618.     jr    nz,wait12    ; 150 T-states per inner loop
  619.     djnz    wait11        ; decrement outer loop
  620.     dec    hl        ; ok, decrement count in hl
  621.     ld    a,h
  622.     or    l
  623.     jr    nz,wait10
  624.     pop    ix        ; done -- restore ix
  625.     pop    de        ; de
  626.     pop    bc        ; and bc
  627.     ret
  628.  
  629. ;Wait milliseconds
  630. mswait:
  631.     ld    hl,2
  632.     add    hl,sp
  633.     ex    de,hl        ; get delay size
  634.     call    getparm
  635.                 ; fall thru to..
  636. ;Wait milliseconds in HL
  637. waitms:
  638.     push    de
  639. w1ms0:
  640.     ld    de,39 *    clkspd
  641. w1ms1:
  642.     dec    de
  643.     ld    a,d
  644.     or    e
  645.     jr    nz,w1ms1
  646.     dec    hl
  647.     ld    a,h
  648.     or    l
  649.     jr    nz,w1ms0
  650.     pop    de
  651.     ret
  652.  
  653. ;Get next parameter from (de) into hl
  654. getparm:
  655.     ex    de,hl        ; get address into hl
  656.     ld    e,(hl)        ; get lo
  657.     inc    hl
  658.     ld    d,(hl)        ; then hi
  659.     inc    hl        ; bump for next
  660.     ex    de,hl        ; result in hl, address still in de
  661.     ret
  662.  
  663. ;Get address of user-defined variables
  664.  
  665. getvars:
  666.     ld    hl,uservars
  667.     ret
  668.  
  669. uservars:
  670.     dw    overdrive    ; .OVR etc. drive/user
  671.     dw    overuser
  672.  
  673.  
  674.      if    ($ - codebgn) gt ovsize
  675. toobig:    jp    errval        ; Overlay too large!
  676.      endif
  677.  
  678.     end
  679.