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-MH04.Z80 < prev    next >
Text File  |  1991-02-02  |  17KB  |  871 lines

  1. ;-----------------------------------------------------------------------------
  2. ;
  3. ;    Overlay for ZMP (Z-Modem Program)
  4. ;
  5. ;    Name    ZMO-MH04.Z80
  6. ;
  7. ;    Dated   19 Sep 1988
  8. ;
  9. ;    Written by -
  10. ;      Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia.
  11. ;      Modified for the MD11 by Lindsay Allen, sysop, Z-Node 62.
  12. ;
  13. ;    Modified to ZMP v1.2 standard rjm 15/9/88
  14. ;    Modified to v1.3 standard rjm 12/10/88
  15. ;    Modified to v1.4 standard and added 1200/75 rjm 23/11/88
  16. ;
  17. ;
  18. ;    Rename subsequent versions as ZMO-MHxx.Z80 etc
  19. ;
  20. ;
  21. ;    This overlay is set up for a Morrow MD11 using the SIO.
  22. ;     Uses a Z80SIO and an 8253 CTC
  23. ;
  24. ;
  25. ;-----------------------------------------------------------------------------
  26. ;
  27. ;
  28. ;    System-dependent code overlay for ZMODEM
  29. ;
  30. ;
  31. ;
  32. ;    Insert your own code as necessary in this file. Code contained herein
  33. ; has been written in Z80 code for use with M80 or SLR. Assemble as follows:
  34. ;
  35. ;    SLR ZMO-MHxx/h
  36. ;    MLOAD ZMP.COM=ZMPX.COM,ZMO-MHxx.HEX
  37. ; or
  38. ;    M80 =ZMO-MHxx.Z80
  39. ;    RELHEX ZMO-MHxx
  40. ;    MLOAD ZMP.COM=ZMPX.COM,ZMO-MHxx.HEX
  41. ;
  42. ;
  43. ;       (Don't use L80 without changing the source for assembly as a
  44. ;         cseg file.)
  45. ;
  46. ;-----------------------------------------------------------------------------
  47. ;
  48. ;
  49. ; Notes on modifying this file:
  50. ;
  51. ;    C requires that functions do not change either index register
  52. ; (IX or IY), nor the BC register pair. If your overlay requires any of
  53. ; these to be changed, ensure they are restored to the original values
  54. ; on return.
  55. ;    Since collecting parameters from C functions can be tricky, only change
  56. ; the parts marked 'Insert your own code here'. Do NOT modify the jump
  57. ; table at the start. Do NOT modify the entry/exit sections of each
  58. ; function. Do NOT pass 'GO'. Do NOT collect $200.
  59. ;    Apart from defining modem functions, this file also defines terminal
  60. ; characteristics. Most have been set up for ADM-3A (with a few of my own
  61. ; additions). Modify to suit your own terminal. An inline print routine
  62. ; is provided for printing strings in the usual way: usage is
  63. ;
  64. ;    call    print
  65. ;    db    'required string',0
  66. ;
  67. ;-----------------------------------------------------------------------------
  68. ;
  69. ;
  70. ;    Don't forget to set your clock speed at the clkspd variable.
  71. ;
  72. ;
  73. ;    If you find your overlay exceeds the maximum size (currently 0400h),
  74. ; you will have to contact me for another version. If too many people need 
  75. ; to do it, we haven't allowed enough room.
  76. ;
  77. ; Ron Murray 15/8/88
  78. ;
  79. ;
  80. ;
  81. ;
  82. ;
  83. ;
  84. ;
  85. ;
  86. ;
  87. ;
  88. ;---------------------------------------------------------------------------
  89. ;
  90. ;                                       |
  91. ;    Ports:                                   |
  92. ;        Console data    60    |                   |
  93. ;            stat    61    |                   |
  94. ;        Modem   data    62    |    Rx bit 2           |
  95. ;            stat    63    |    Tx     0           |
  96. ;        SIO    data    70    |                   |
  97. ;            stat    71    |                   |
  98. ;                                       |
  99. ;                                       |
  100. ;                          mode 3        bnkbios3   |
  101. ;        CTC    SIO    50    ch 0    3E    port 3    (baud2)    |
  102. ;            modem    51    ch 1    7E    port 2    (baud1)    |
  103. ;            con    52    ch 2    BE    port 1    (baud0)    |
  104. ;            select    53                       |
  105. ;                                       |
  106. ;                                        |
  107. ;
  108. ;
  109. ;---------------------------------------------------------------------------
  110.  
  111. false    equ    0
  112. true    equ    not false
  113.  
  114.  
  115. ; User-set variables: ***********
  116.  
  117. clkspd    equ    4        ; Processor clock speed in MHz
  118.  
  119. debug    equ    false
  120.  
  121. userdef    equ    00145h        ; origin of this overlay
  122.                 ; This address should remain constant
  123.                 ; with subsequent revisions.
  124.  
  125. sio    equ    true        ; true to use the SIO, false to use the DART
  126.  
  127. s1275    equ    true        ; true to use 1200/75, with the DART sending
  128.                 ; at 75 and the SIO receiving at 1200. Ensure
  129.                 ; the sio equate is set TRUE.
  130.  
  131. ;Set the following two equates to the drive and user area which will contain
  132. ;   ZMP's .OVR files, .CFG file, .FON file and .HLP file. Set both to zero
  133. ;   (null) to locate them on the drive from which ZMP was invoked.
  134.  
  135. overdrive    equ    'A'    ; Drive to find overlay files on ('A'-'P')
  136. overuser    equ    3    ; User area to find files
  137.  
  138.  
  139.  
  140. ; NOT user-set variables
  141. mspeed    equ    003ch        ; baud rate id
  142. ovsize    equ    0400h        ; max size of this overlay
  143.  
  144.     .z80            ; use z80 code
  145.     aseg            ; absolute
  146.  
  147.      if    debug
  148.     org    100h        ; so you can debug it with cebug, zsid, etc
  149.      else
  150.     org    userdef
  151.      endif
  152.  
  153.  
  154. esc    equ    1bh
  155. ctrlq    equ    11h
  156. cr    equ    0dh
  157. lf    equ    0ah
  158. bdos    equ    5
  159.  
  160.  
  161. ; MDII specific equates  ***************************************************
  162.  
  163.      if SIO
  164. mdata    equ    070h        ; use RS232 socket at other end from Terminal
  165. mstat    equ    mdata+1
  166. ctc    equ    50h
  167. mode    equ    3Eh
  168.      else
  169. mdata    equ    62h        ; use RSs232 socket adjacent to Terminal
  170. mstat    equ    mdata+1
  171. ctc    equ    51h
  172. mode    equ    7Eh
  173.      endif
  174.  
  175.      if s1275 and sio    ; must have sio set for 1200/75
  176. bmdata    equ    62h
  177. bmstat    equ    bmdata+1
  178. bctc    equ    51h
  179. bmode    equ    7Eh
  180.      endif
  181.  
  182. rda    equ    0
  183. tbe    equ    2
  184. ctcsel    equ    53h
  185. onhook    equ    7Fh
  186. online    equ    80h
  187. error    equ    70h
  188. break    equ    0F8h
  189. reset    equ    30h
  190. ;            ******************************************
  191.  
  192.  
  193. ;-------------------------------------------------------------------------
  194. ; Main code starts here
  195.  
  196. codebgn    equ    $
  197.  
  198. ;Jump table for the overlay: do NOT change this
  199. jump_tab:
  200.     jp    scrnpr        ; screen print
  201.     jp    mrd        ; modem read with timeout
  202.     jp    mchin        ; get a character from modem
  203.     jp    mchout        ; send a character to the modem
  204.     jp    mordy        ; test for tx buffer empty
  205.     jp    mirdy        ; test for character received
  206.     jp    sndbrk        ; send break
  207.     jp    cursadd        ; cursor addressing
  208.     jp    cls        ; clear screen
  209.     jp    invon        ; inverse video on
  210.     jp    invoff        ; inverse video off
  211.     jp    hide        ; hide cursor
  212.     jp    show        ; show cursor
  213.     jp    savecu        ; save cursor position
  214.     jp    rescu        ; restore cursor position
  215.     jp    mint        ; service modem interrupt
  216.     jp    invec        ; initialise interrupt vectors
  217.     jp    dinvec        ; de-initialise interrupt vectors
  218.     jp    mdmerr        ; test uart flags for error
  219.     jp    dtron        ; turn DTR on
  220.     jp    dtroff        ; turn DTR OFF
  221.     jp    init        ; initialise uart
  222.     jp    wait        ; wait seconds
  223.     jp    mswait        ; wait milliseconds
  224.     jp    userin        ; user-defined entry routine
  225.     jp    userout        ; user-defined exit routine
  226.     jp    getvars        ; get system variables
  227.  
  228. ;Spare jumps for compatibility with future versions
  229.     jp    spare        ; spares for later use
  230.     jp    spare        ; spares for later use
  231.     jp    spare        ; spares for later use
  232.     jp    spare        ; spares for later use
  233.     jp    spare        ; spares for later use
  234.  
  235. spare:    ret
  236.  
  237. ;-------------------------------------------------------------------------
  238.  
  239. ;
  240. ;Screen print function
  241. scrnpr:
  242.                 ; <== Insert your own code here
  243.     call    print
  244.     db    'This function not supported.',cr,lf,0
  245.                 ; <== End of your own code
  246.     ret
  247.  
  248.  
  249. ;Get a character from the modem: return in HL
  250. mchin:
  251.     push    bc
  252.                 ; <== Insert your own code here
  253.  
  254. mchin2:
  255.     in    a,(mstat)    ; check for char waiting
  256.     bit    rda,a
  257.     jr    z,mchin2
  258.  
  259.     in    a,(mdata)    ; read the char
  260.  
  261.  
  262.                 ; <== End of your own code
  263.  
  264.  
  265.     ld    l,a        ; put in HL
  266.     ld    h,0
  267.     or    a        ; set/clear Z
  268.     pop    bc
  269.     ret
  270.  
  271. ;Send a character to the modem
  272. mchout:
  273.     ld    hl,2        ; get the character
  274.     add    hl,sp
  275.     ld    a,(hl)
  276.                 ; <== Insert your own code here
  277.  
  278.     push    bc
  279.     ld    b,a        ; save the char
  280.  
  281.      if    s1275
  282.     ld    a,(mspeed)    ; are we using 110 baud?
  283.     or    a
  284.     jr    nz,mchout2    ; no, act normally..
  285.  
  286. mchout1:
  287.     in    a,(bmstat)
  288.     bit    tbe,a
  289.     jr    z,mchout1
  290.     ld    a,b
  291.     out    (bmdata),a
  292.     jr    mchout3
  293.      endif        ; s1275
  294.  
  295. mchout2:
  296.     in    a,(mstat)    ; check for uart ready
  297.     bit    tbe,a
  298.     jr    z,mchout2
  299.  
  300.     ld    a,b        ; char in a
  301.     out    (mdata),a    ; send it
  302.  
  303. mchout3:
  304.     pop    bc
  305.  
  306.                 ; <== End of your own code
  307.     ret            ; done
  308.  
  309. ;Test for output ready: return TRUE (1) in HL if ok
  310. mordy:
  311.                 ; <== Insert your own code here
  312.  
  313.     ld    hl,0        ; assume not ready
  314.  
  315.      if    s1275
  316.     ld    a,(mspeed)    ; are we running 12/75?
  317.     or    a
  318.     jr    nz,mordy1
  319.  
  320.     in    a,(bmstat)
  321.     bit    tbe,a
  322.     jr    z,mordy2
  323.     inc    hl
  324.     jr    mordy2
  325.      endif        ; s1275
  326.  
  327. mordy1:
  328.     in    a,(mstat)
  329.     bit    tbe,a        ; transmit buffer empty
  330.     jr    z,mordy2
  331.     inc    hl
  332.  
  333. mordy2:
  334.  
  335.                 ; <== End of your own code
  336.  
  337.     ld    a,l        ; set/clear Z
  338.     or    a
  339.     ret
  340.  
  341. ;Test for character at modem: return TRUE (1) in HL if so
  342. mirdy:
  343.                 ; <== Insert your own code here
  344.  
  345.     ld    hl,0
  346.     in    a,(mstat)
  347.     bit    rda,a        ; received data available
  348.     jr    z,mirdy1
  349.     inc    hl
  350. mirdy1:
  351.  
  352.                 ; <== End of your own code
  353.     ld    a,l        ; set/clear Z
  354.     or    a
  355.     ret
  356.  
  357. ;Send a break to the modem: leave empty if your system can't do it
  358. sndbrk:
  359.                 ; <== Insert your own code here
  360.     ld    a,5
  361.     out    (mstat),a
  362.     ld    a,break        ; F8
  363.     out    (mstat),a
  364.  
  365.     ld    hl,300        ; a 300 mS break
  366.     call    waithlms
  367.  
  368.     ld    a,5
  369.     out    (mstat),a
  370.     ld    a,online    ; 68
  371.     out    (mstat),a
  372.  
  373.     ld    a,3
  374.     out    (mstat),a
  375.     ld    a,0E1h
  376.     out    (mstat),a    ; E1
  377.  
  378.                 ; <== End of your own code
  379.     ret
  380. ;
  381. ;Test UART flags for error: return TRUE (1) in HL if error.
  382. mdmerr:
  383.                 ; <== Insert your own code here
  384.     ld    hl,0
  385.     in    a,(mstat)
  386.     and    error
  387.     jr    z,mdmer2
  388.     inc    hl
  389. mdmer2:
  390.                 ; <== End of your own code
  391.     ld    a,l        ; set/clear Z
  392.     or    a
  393.     ret
  394.  
  395.  
  396.  
  397. ;Turn DTR ON
  398. dtron:
  399.                 ; <== Insert your own code here
  400.     ld    a,5
  401.     out    (mstat),a
  402.  
  403.      if    s1275
  404.     out    (bmstat),a
  405.      endif
  406.  
  407.     ld    a,(combyt)    ; get the one we used last time
  408.     or    online        ; 80h - set bit 7 high
  409.     ld    (combyt),a    ; save it for next time
  410.     out    (mstat),a    ; go
  411.  
  412.      if    s1275
  413.     out    (bmstat),a
  414.      endif
  415.                 ; <== End of your own code
  416.     ret
  417.  
  418.  
  419.  
  420. ;Turn DTR OFF
  421. dtroff:
  422.                 ; <== Insert your own code here
  423.  
  424.     ld    a,5
  425.     out    (mstat),a
  426.  
  427.      if    s1275
  428.     out    (bmstat),a
  429.      endif
  430.  
  431.     ld    a,(combyt)    ; get the one we used last time
  432.     and    onhook        ; 7Fh - clear bit 7
  433.     ld    (combyt),a    ; save it for next time
  434.     out    (mstat),a    ; go
  435.  
  436.      if    s1275
  437.     out    (bmstat),a
  438.      endif
  439.  
  440.                 ; <== End of your own code
  441.     ret
  442.  
  443.  
  444.  
  445. ;Initialise the SIO +++
  446. ; The SIO is set up in four steps:
  447. ;     1)  Reset
  448. ;       2)  Reg 4 - clock, stop bits, parity
  449. ;    3)  Reg 5 - dtr, Tx bits, Brk, TxEn, rts
  450. ;    4)  Reg 3 - Rx bits, RxEn
  451.  
  452. init:
  453.  
  454.     ld    hl,2        ; get parameters
  455.     add    hl,sp
  456.     ex    de,hl
  457.     call    getparm        ; in HL
  458.     ld    (brate),hl    ; baud rate
  459.     ld    a,l
  460.     ld    (003Ch),a    ; save the baud rate in 3C for later as per IMP
  461.     call    getparm
  462.     ld    (parity),hl    ; parity
  463.     call    getparm
  464.     ld    (data),hl    ; data bits
  465.     call    getparm
  466.     ld    (stop),hl    ; stop bits
  467.  
  468.  
  469.                 ; <== Insert your own code here
  470.                 ; using values below
  471.  
  472.     push    bc
  473.  
  474.     ld    a,0
  475.     out    (mstat),a    ; point to reg 0
  476.     ld    a,18h        ; reset
  477.     out    (mstat),a    ;                *** step 1
  478.  
  479.      if    s1275
  480.     ld    a,0
  481.     out    (bmstat),a    ; back channel too
  482.     ld    a,18h
  483.     out    (bmstat),a
  484.      endif
  485.  
  486.     ld    a,4        ; point to wrt reg 4
  487.     out    (mstat),a
  488.  
  489.      if    s1275
  490.     out    (bmstat),a    ; back channel too
  491.      endif
  492.  
  493.     ld    e,44h        ; assume  x16, 1 stop, No parity
  494.     ld    a,(stop)    ; set stop bits
  495.     cp    2        ; set 2 if required
  496.     jr    nz,setpar
  497.     set    3,e
  498.  
  499. setpar:
  500.     ld    a,(parity)    ; set parity bits
  501.     cp    'O'
  502.     jr    nz,setpa2
  503.     set    0,e        ; ODD
  504.     jr    setpa3
  505.  
  506. setpa2:    cp    'E'
  507.     jr    nz,setpa3
  508.     set    0,e
  509.     set    1,e        ; EVEN
  510.  
  511. setpa3:    ld    a,e
  512.     out    (mstat),a    ;                *** step 2
  513.  
  514.      if    s1275
  515.     out    (bmstat),a    ; back channel too
  516.      endif
  517.  
  518.  
  519.     ld    a,5        ; point to wrt reg 5 - dtr, Tx bits, etc
  520.     out    (mstat),a
  521.  
  522.      if    s1275
  523.     out    (bmstat),a    ; back channel too
  524.      endif
  525.  
  526.     ld    e,0EAh        ; assume dtr, TX 8 bits, TxEn, rts
  527.     ld    a,(data)
  528.     cp    7
  529.     jr    nz,setbi2
  530.     res    6,e        ; 7 bits
  531.  
  532. setbi2:    ld    a,e
  533.     out    (mstat),a    ;                *** step 3
  534.  
  535.      if    s1275
  536.     out    (bmstat),a    ; back channel too
  537.      endif
  538.  
  539.     ld    a,3        ; point to wrt reg 3
  540.     out    (mstat),a
  541.  
  542.      if    s1275
  543.     out    (bmstat),a    ; back channel too
  544.      endif
  545.  
  546.     ld    e,0C1h        ; assume 8 bits
  547.     ld    a,(data)
  548.     cp    7
  549.     jr    nz,setbi3
  550.     res    7,e        ; 7 bits
  551.  
  552. setbi3:    ld    a,e
  553.     out    (mstat),a    ;                *** step 4
  554.  
  555.      if    s1275
  556.     out    (bmstat),a    ; back channel too
  557.      endif
  558.  
  559. setbrate:
  560.     push    ix
  561.     ld    de,(brate)    ; get baud rate value (0-10)
  562.  
  563.      if    s1275
  564.     ld    a,e        ; see if 12/75
  565.     or    a
  566.     jr    nz,setbr1    ; no
  567.     ld    de,5        ; yes, set main channel to 1200
  568.      endif
  569.  
  570. setbr1:
  571.     ld    hl,brval
  572.     add    hl,de
  573.     add    hl,de        ; hl now points to the divisor dw
  574.     push    hl        ; look at it
  575.     pop    ix
  576.     ld    a,(ix)
  577.     or    (ix+1)
  578.     jr    z,setbrx    ; zero = invalid
  579.     ld    c,ctcsel    ; 053h
  580.     ld    a,mode        ; 03Eh or 7Eh
  581.     out    (c),a        ; select the correct timer and mode of the 8253
  582.     ld    c,ctc        ; 050h or 51h
  583.     outi            ; lo byte
  584.     outi            ; hi byte
  585.  
  586.      if    s1275
  587.     ld    hl,brv75    ; set back chnl to 75 baud
  588.     ld    c,ctcsel    ; 053h
  589.     ld    a,bmode        ; 03Eh or 7Eh
  590.     out    (c),a        ; select the correct timer and mode of the 8253
  591.     ld    c,bctc        ; 050h or 51h
  592.     outi            ; lo byte
  593.     outi            ; hi byte
  594.      endif        ; s1275
  595.  
  596.     ld    a,(brate)    ; tell zmp it's ok
  597.     ld    (mspeed),a
  598. setbrx:
  599.     pop    ix
  600.     pop    bc
  601.                 ; <== End of your own code
  602.     ret
  603. ;--------------------------------------------------------------------------
  604.  
  605. stop:    dw    1        ; stop bits
  606. parity:    dw    'N'        ; parity
  607. data:    dw    8        ; data bits
  608. brate:    dw    7        ; baud rate:
  609. combyt:    db    0EAh        ; for now
  610.  
  611. ;--------------------------------------------------------------------------
  612. ;Values for 8253 control reg for each baud rate
  613.  
  614. brv75:
  615.     dw    3332    ; 75 baud for 1200/75
  616.  
  617. brval:
  618.     dw    2273    ;   110        0
  619.     dw     833    ;   300        1
  620.     dw     555    ;   450        2
  621.     dw     417    ;   600        3
  622.     dw     352    ;   710        4
  623.     dw     208    ;  1200        5
  624.     dw     104    ;  2400        6
  625.     dw      52    ;  4800        7
  626.     dw      26    ;  9600        8
  627.     dw      13    ; 19200        9
  628.     dw       0    ; 38400        10
  629.     dw       0    ; 57600        11
  630.     dw       0    ; 76800        12    
  631.  
  632. ;****************************************************************************
  633. ;Video terminal sequences: these are for ADM-3A: Modify as you wish
  634. ;Cursor addressing: 
  635. cursadd:
  636.     ld    hl,2        ; get parameters
  637.     add    hl,sp
  638.     ex    de,hl
  639.     call    getparm        ; in HL
  640.     ld    (row),hl    ; row
  641.     call    getparm
  642.     ld    (col),hl    ; column
  643.                 ; <== Insert your own code here
  644.                 ; using values in row and col
  645.     call    print
  646.     db    esc,'=',0    ; ADM-3A leadin
  647.     ld    a,(row)        ; row first
  648.     add    a,' '        ; add offset
  649.     call    cout
  650.     ld    a,(col)        ; sane for column
  651.     add    a,' '
  652.     call    cout
  653.                 ; <== end of your own code
  654.     ret
  655.  
  656. row:    ds    2        ; row
  657. col:    ds    2        ; column
  658.  
  659.  
  660. ;Clear screen:
  661. cls:
  662.     call    print
  663.     db    esc,'*',0
  664.     ret
  665.  
  666. ;Inverse video on:
  667. invon:
  668.     call    print
  669.     db    esc,'G4',0
  670.     ret
  671.  
  672. ;Inverse video off:
  673. invoff:
  674.     call    print
  675.     db    esc,'G0',0
  676.     ret
  677.  
  678. ;Turn off cursor:
  679. hide:
  680.     call    print
  681.     db    esc,'.1',0
  682.     ret
  683.  
  684. ;Turn on cursor:
  685. show:
  686.     call    print
  687.     db    esc,'.3',0
  688.     ret
  689.  
  690. ;Save cursor position:
  691. savecu:
  692.     ret
  693.  
  694. ;Restore cursor position:
  695. rescu:
  696.     ret
  697.  
  698. ;****************************************************************************
  699.  
  700. ;Service modem interrupt:
  701. mint:
  702.     ret            ; my system doesn't need this
  703.  
  704. ;Initialise interrupt vectors:
  705. invec:
  706.     ret            ; ditto
  707.  
  708. ;De-initialise interrupt vectors:
  709. dinvec:
  710.     ret            ; ditto
  711.  
  712. ;User-defined entry routine: leave empty if not used
  713. userin:
  714.     ret
  715.  
  716. ;User-defined exit routine: leave empty if not used
  717. userout:
  718.     ret
  719.  
  720.  
  721. ;****************** End of user-defined code ********************************
  722. ;        Do not change anything below here.
  723.  
  724. ;Modem character test for 100 ms
  725. mrd:
  726.     push    bc        ; save bc
  727.     ld    bc,100        ; set limit
  728. mrd1:
  729.     call    mirdy        ; char at modem?
  730.     jr    nz,mrd2        ; yes, exit
  731.     ld    hl,1        ; else wait 1ms
  732.     call    waithlms
  733.     dec    bc        ; loop till done
  734.     ld    a,b
  735.     or    c
  736.     jr    nz,mrd1
  737.     ld    hl,0        ; none there, result=0
  738.     xor    a
  739. mrd2:
  740.     pop    bc
  741.     ret
  742.  
  743. ; Inline print routine: destroys A and HL
  744.  
  745. print:
  746.     ex    (sp),hl        ; get address of string
  747. ploop:
  748.     ld    a,(hl)        ; get next
  749.     inc    hl        ; bump pointer
  750.     or    a        ; done if zero
  751.     jr    z,pdone
  752.     call    cout        ; else print
  753.     jr    ploop        ; and loop
  754. pdone:
  755.     ex    (sp),hl        ; restore return address
  756.     ret            ; and quit
  757.  
  758. ;
  759. ;Output a character in A to the console
  760. ;
  761. cout:
  762.     push    bc        ; save regs
  763.     push    de
  764.     push    hl
  765.     ld    e,a        ; character to E
  766.     ld    c,2
  767.     call    bdos        ; print it
  768.     pop    hl
  769.     pop    de
  770.     pop    bc
  771.     ret
  772.  
  773. ;Wait(seconds)
  774. wait:
  775.     ld    hl,2
  776.     add    hl,sp
  777.     ex    de,hl        ; get delay size
  778.     call    getparm
  779.                 ; fall thru to..
  780. ;Wait seconds in HL
  781. waithls:
  782.     push    bc        ; save bc
  783.     push    de        ; de
  784.     push    ix        ; and ix
  785.     ld    ix,0        ; then point ix to 0
  786.                 ; so we don't upset memory-mapped i/o
  787.  
  788. ;Calculate values for loop constants. Need to have two loops to avoid
  789. ;   16-bit overflow with clock speeds above 9 MHz.
  790.  
  791. outerval    equ    (clkspd / 10) + 1
  792. innerval    equ    (6667 / outerval) * clkspd
  793.  
  794. wait10:
  795.     ld    b,outerval
  796.  
  797. wait11:
  798.     ld    de,innerval
  799.  
  800. wait12:
  801.     bit    0,(ix)        ; time-wasters
  802.     bit    0,(ix)
  803.     bit    0,(ix)        ; 20 T-states each
  804.     bit    0,(ix)
  805.     bit    0,(ix)
  806.     bit    0,(ix)
  807.     dec    de
  808.     ld    a,e
  809.     ld    a,d
  810.     or    e
  811.     jr    nz,wait12    ; 150 T-states per inner loop
  812.     djnz    wait11        ; decrement outer loop
  813.     dec    hl        ; ok, decrement count in hl
  814.     ld    a,h
  815.     or    l
  816.     jr    nz,wait10
  817.     pop    ix        ; done -- restore ix
  818.     pop    de        ; de
  819.     pop    bc        ; and bc
  820.     ret
  821.  
  822. ;Wait milliseconds
  823. mswait:
  824.     ld    hl,2
  825.     add    hl,sp
  826.     ex    de,hl        ; get delay size
  827.     call    getparm
  828.                 ; fall thru to..
  829. ;Wait milliseconds in HL
  830. waithlms:
  831.     push    de
  832. w1ms0:
  833.     ld    de,39 * clkspd
  834. w1ms1:
  835.     dec    de
  836.     ld    a,d
  837.     or    e
  838.     jr    nz,w1ms1
  839.     dec    hl
  840.     ld    a,h
  841.     or    l
  842.     jr    nz,w1ms0
  843.     pop    de
  844.     ret
  845.  
  846. ;Get next parameter from (de) into hl
  847. getparm:
  848.     ex    de,hl        ; get address into hl
  849.     ld    e,(hl)        ; get lo
  850.     inc    hl
  851.     ld    d,(hl)        ; then hi
  852.     inc    hl        ; bump for next
  853.     ex    de,hl        ; result in hl, address still in de
  854.     ret
  855.  
  856. ;Get address of user-defined variables
  857.  
  858. getvars:
  859.     ld    hl,uservars
  860.     ret
  861.  
  862. uservars:
  863.     dw    overdrive    ; .OVR etc. drive/user
  864.     dw    overuser
  865.  
  866.      if    ($ - codebgn) gt ovsize
  867. toobig:    jp    errval        ; Overlay too large!
  868.      endif
  869.  
  870.     end
  871.