home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / ftp.demon.co.uk-pub-cpm / amstrad / zmp15pcw.com / ZMP15PCW.MAC < prev    next >
Text File  |  1979-11-30  |  17KB  |  768 lines

  1. ;-----------------------------------------------------------------------
  2. ;
  3. ;    Amstrad PCW8000 Overlay for ZMP (Z-Modem Program)  Jul 6, 89
  4. ;
  5. ;    Name    ZMP15PCW.MAC
  6. ;
  7. ;    Dated Jul 6, 1989
  8. ;
  9. ;    Modified from ZMP-BLNK.Z80 by Nigel Dallard
  10. ;
  11. ;    NOTE:    As supplied in the ZMP15.LBR library, ZMP-BLNK.Z80
  12. ;    would not assemble with M80. M80 objected to the hyphen in the
  13. ;    filename, and to the labels WAITHLS and WAITHLMS which it
  14. ;    thought were the same label. To enable M80 to assemble the file
  15. ;    the name was changed to the current one, and the offending
  16. ;    labels changed to WAITSHL and WAITMSHL.
  17. ;    The conditional assembly portion at the end of the file was also
  18. ;    removed since it included a call to a non-existant label. This
  19. ;    does not affect the program assuming the code is within the
  20. ;    specified size limitation.
  21. ;    The code as supplied did not initialise the serial port on entry.
  22. ;    The routine USERIN is used to call the INIT routine part way
  23. ;    through to cure this.
  24. ;
  25. ;    Modified from Nigel Dallard's code by Ian Macdonald
  26. ;                          (ianmacd@xs4all.nl) 16/6/95
  27. ;
  28. ;    This slightly modified version produced 28/6/95 for use with EMU,
  29. ;    the VT100 emulator. When run with EMU in the background, the
  30. ;    16/6/95 version causes a crash because both programs make use of
  31. ;    the Z80 alternate register set for screen display.
  32. ;    If you wish to use EMU, set the EMU equate to YES prior to
  33. ;    assembly.
  34. ;
  35. ;------------------------------------------------------------------------
  36. ;
  37. ;    System-dependent code overlay for ZMODEM
  38. ;
  39. ; Assemble as follows:
  40. ;
  41. ;    First edit this file and change the FAXLINK and SPRINTER equates
  42. ;    to reflect your hardware (YES or NO). Save the file and then
  43. ;    execute the following sequence of commands:
  44. ;
  45. ;    M80    =ZMP15PCW
  46. ;    RELHEX    ZMP15PCW
  47. ;    MLOAD    ZMP.COM=ZMPX.COM,ZMP15PCW.HEX
  48. ;
  49. ; (Don't use L80 without changing the source  for  assembly  as  a  CSEG
  50. ; file.)
  51. ;
  52. ; Then add Stephen Younger's interrupt driven RSX as follows:
  53. ;
  54. ;    First edit QTERMRSX.ASM to change the ZMP equate to YES and, if
  55. ;    necessary, alter the FAXLINK equate to YES. Then execute the
  56. ;    following sequence of commands:
  57. ;
  58. ;    RMAC    QTERMRSX $$PZ
  59. ;    LINK    QTERMRSX[OP NR]
  60. ;    ERA    ZMPRSX.RSX
  61. ;    REN    ZMPRSX.RSX=QTERMRSX.PRL
  62. ;    GENCOM    ZMP ZMPRSX
  63. ;
  64. ;
  65. ;
  66. ;-----------------------------------------------------------------------
  67. ;
  68. ; Notes on modifying this file:
  69. ;
  70. ;    C    requires  that functions do not change either index register (IX
  71. ; or IY). If your overlay requires either of these to be changed, ensure
  72. ; they are restored to the original values on return.
  73. ;
  74. ; An  inline print routine is provided for printing strings in the usual
  75. ; way, usage is:
  76. ;
  77. ;              CALL    PRINT
  78. ;              DB    'required string',0
  79. ;
  80. ;-----------------------------------------------------------------------
  81. ;
  82. ;    Don't forget to set your clock speed at the clkspd variable.
  83. ;
  84. ;-----------------------------------------------------------------------
  85. ;
  86. NO    EQU    0
  87. YES    EQU    NOT NO
  88. ;
  89. ;
  90. ; User-set variables:
  91. ;
  92. FAXLINK    equ    NO        ; set YES for Fax Link, NO for CPS8256
  93. SPRINTER equ    NO        ; set YES for Cirtech Sprinter
  94. EMU    equ    YES        ; set YES if the EMU VT100 emulator will be used
  95. rsxbas    equ    0006h        ; to base offsets for SI calls
  96. rsxini  equ    001bh        ;  offset for initializing RSX
  97. rsxxit    equ    001eh        ;  offset to quit from RSX
  98. txrdy    equ    4        ; transmit buffer clear mask
  99. conout    equ    0fc0ch        ; BIOS CONOUT function
  100. userf    equ    0fc5ah        ; BIOS USERF function
  101.  
  102. IF FAXLINK
  103. datap    equ    0c8h        ; Values with Fax link fitted
  104. statp    equ    0c9h        ;          ~~~~~~~~~~~~~~~
  105.  
  106. ELSE
  107. datap    equ    0e0h        ; Values with CPS8256 fitted
  108. statp    equ    0e1h        ;          ~~~~~~~~~~~~~~
  109.  
  110. ENDIF
  111.  
  112. IF SPRINTER
  113. clkspd    equ    6        ; value with Sprinter 6 - otherwise 3
  114.                 ; (PCW closer to 3 Mhz than 4)
  115. ELSE
  116. clkspd    equ    3        ; Processor clock speed in MHz
  117. ENDIF
  118.  
  119. DEBUG    EQU    NO        ; To allow debugging of overlay with
  120.                 ; Z8E etc.
  121. ;
  122. ;
  123. ; Set the following two equates to the drive and user area which will
  124. ; contain ZMP's .OVR files, .CFG file, .FON file and .HLP file.  Set
  125. ; both to zero (null) to locate them on the drive from which ZMP was
  126. ; invoked.
  127. ;
  128. OVERDRIVE EQU    0        ; Drive to find overlay files on ('A'-'P')
  129. OVERUSER EQU    0        ; User area to find files
  130. ;
  131. ;-----------------------------------------------------------------------
  132. ;
  133. ; NOT user-set variables
  134. ;
  135. USERDEF    EQU    0145H        ; Origin of this overlay.  This address
  136. ;                ;   should not change with subsequent
  137. ;                ;   revisions.
  138. MSPEED    EQU    03CH        ; Location of current baud rate
  139. OVSIZE    EQU    0400H        ; Maximum size of this overlay
  140. ;
  141.     .Z80            ; Use Z80 code
  142. ;
  143.     ASEG            ; Absolute
  144. ;
  145. ;
  146.      IF    DEBUG
  147.     ORG    100H        ; So you can debug it with CEBUG, ZSID, etc.
  148.      ELSE
  149.     ORG    USERDEF
  150.      ENDIF
  151. ;
  152. ;
  153. ESC    EQU    1BH
  154. CTRLQ    EQU    11H
  155. CR    EQU    0DH
  156. LF    EQU    0AH
  157. BDOS    EQU    5
  158. ;
  159. ;-----------------------------------------------------------------------
  160. ;
  161. ;Jump table for the overlay: do NOT change this
  162. ;
  163. JUMPTAB:JP    SCRNPR        ; Screen print
  164.     JP    MRD        ; Modem read with timeout
  165.     JP    MCHIN        ; Get a character from modem
  166.     JP    MCHOUT        ; Send a character to the modem
  167.     JP    MORDY        ; Test for tx buffer empty
  168.     JP    MIRDY        ; Test for character received
  169.     JP    SNDBRK        ; Send break
  170.     JP    CURSADD        ; Cursor addressing
  171.     JP    CLS        ; Clear screen
  172.     JP    INVON        ; Inverse video on
  173.     JP    INVOFF        ; Inverse video off
  174.     JP    HIDE        ; Hide cursor
  175.     JP    SHOW        ; Show cursor
  176.     JP    SAVECU        ; Save cursor position
  177.     JP    RESCU        ; Restore cursor position
  178.     JP    MINT        ; Service modem interrupt
  179.     JP    INVEC        ; Initialise interrupt vectors
  180.     JP    DINVEC        ; De-initialise interrupt vectors
  181.     JP    MDMERR        ; Test uart flags for error
  182.     JP    DTRON        ; Turn DTR on
  183.     JP    DTROFF        ; Turn DTR OFF
  184.     JP    INIT        ; Initialise uart
  185.     JP    WAIT        ; Wait seconds
  186.     JP    MSWAIT        ; Wait milliseconds
  187.     JP    USERIN        ; User-defined entry routine
  188.     JP    USEROUT        ; User-defined exit routine
  189.     JP    GETVARS        ; Get system variables
  190.     JP    SETPORT        ; Set the modem port being used
  191. ;
  192. ; Spare jumps for compatibility with future versions
  193. ;
  194.     JP    SPARE        ; Spare for later use
  195.     JP    SPARE        ; Spare for later use
  196.     JP    SPARE        ; Spare for later use
  197.     JP    SPARE        ; Spare for later use
  198.     JP    SPARE        ; Spare for later use
  199.     JP    SPARE        ; Spare for later use
  200. ;
  201. ;-----------------------------------------------------------------------
  202. ;
  203. ; Main code starts here
  204. ;
  205. ; Screen print function
  206. ;
  207. SCRNPR: CALL    PRINT            ; print message
  208.     DB    CR,LF,'Press [EXTRA] + [PTR] for a screen dump.',CR,LF,0
  209. ;
  210. SPARE:    RET
  211. ;
  212. ; User-defined entry routine: used by ND to initialise UART on entry
  213. ; Code to initialise RSX added by IM
  214. ;
  215. USERIN:    CALL    INIT2
  216. rsxin:    ld    de,rsxini    ; offset for RSXinit
  217. grsxbs:    ld    hl,(rsxbas)    ; get RSX base address
  218.         ld    l,0           
  219.         add    hl,de         
  220.         jp    (hl)              ; execute
  221. ;
  222. ; User-defined exit routine: leave empty if not needed
  223. ;
  224. USEROUT:
  225. rsxout: ld    de,rsxxit    ; offset for quit routine - A MUST
  226.     jr    grsxbs        ; get RSX base address and execute
  227. ;
  228. ; Get a character from the modem: return in HL
  229. ;
  230. MCHIN:    ;PUSH    BC
  231. ;
  232. ; <== Start of user-defined code
  233. ;
  234.     exx            ; save BC
  235.     call    0000        ; RSX will fill in the correct address
  236.     exx            ; restore BC
  237. ;
  238. ; <== End of user-defined code
  239. ;
  240.     LD    L,A        ; Put in HL
  241.     LD    H,0
  242.     OR    A        ; Set/clear Z
  243.     ;POP    BC
  244.     RET
  245. ;
  246. ; Send a character to the modem
  247. ;
  248. MCHOUT:    LD    HL,2        ; Get the character
  249.     ADD    HL,SP
  250.     LD    A,(HL)
  251. ;
  252. ; <== Start of user-defined code
  253. ;
  254.     out    (datap),a
  255. ;
  256. ; <== End of user-defined code
  257. ;
  258.     RET            ; Done
  259. ;
  260. ;
  261. ;Test for output ready: return TRUE (1) in HL if ok
  262. ;
  263. MORDY:
  264. ;
  265. ; <== Start of user-defined code
  266. ;
  267.     in    a,(statp)
  268.     and    txrdy
  269.     ld    hl,0
  270.     ret    z        ; not ready
  271.     inc    l
  272.  
  273. ; <== End of user-defined code
  274.  
  275.     RET
  276. ;
  277. ;
  278. MIRDY:
  279. ;
  280. ; <== Start of user-defined code
  281. ;
  282.     jp    0000        ; RSX will fill in the correct address
  283. ;
  284. ; <== End of user-defined code
  285.  
  286.     ;RET
  287. ;
  288. ; Send a break to the modem: leave empty if your system can't do it
  289. ;
  290. SNDBRK:
  291. ;
  292. ; <== Start of user-defined code
  293. ;
  294. ;    The PCW BDOS/BIOS doesn't allow you to send a BREAK (ND)
  295. ;    True, but we can make our own (IM)
  296.  
  297.     call    getr5        ; get DART wreg5 bit pattern in b
  298.     set    4,b        ; set break
  299.     ld    a,5
  300.     out    (statp),a    ; send to wreg5
  301.     ld    a,b
  302.     out    (statp),a
  303.  
  304.     ld    hl,300
  305.     call    waitmshl    ; make the break last 300 msecs.
  306.  
  307. ebreak:    call    getr5
  308.     ld    a,5
  309.     out    (statp),a
  310.     ld    a,b
  311.     out    (statp),a
  312. ;
  313. ; <== End of user-defined code
  314. ;
  315.     RET
  316.  
  317. getr5:    call    getpara        ; ext BIOS call
  318.     ld    a,l        ; put Tx Data bit size into a
  319.     and    3        ; 0=8b,1=5b,2=6b,3=7b
  320.     ld    c,a
  321.     ld    b,0
  322.     ld    hl,wreg5
  323.     add    hl,bc
  324.     ld    b,(hl)        ; get bit pattern from lookup table
  325.     ret
  326.  
  327. wreg5:    db 11101010b        ; 8 Data bits Tx DTR ON
  328.     db 10001010b        ; 5 Data bits Tx
  329.     db 11001010b        ; 6 Data bits Tx
  330.     db 10101010b        ; 7 Data bits Tx
  331. ;
  332. ; Test UART flags for error: return TRUE (1) in HL if error.
  333. ;
  334. MDMERR:
  335. ;
  336. ; <== Start of user-defined code
  337. ;
  338.     ;LD    HL,0        ; Serial errors are dealt with by BDOS
  339.     xor    a
  340. ;
  341. ; <== End of user-defined code
  342. ;
  343.     ;LD    A,L        ; Set/clear Z
  344.     ;OR    A
  345.     RET
  346. ;
  347. ;
  348. ; Turn DTR ON
  349. ;
  350. DTRON:
  351. ;
  352. ; <== Start of user-defined code
  353. ;
  354.     LD    A,80H        ; ask the BIOS to drop DTR
  355.     jp    sioset
  356.  
  357. ; <== End of user-defined code
  358. ;
  359.     ;RET
  360. ;
  361. ;
  362. ; Turn DTR OFF
  363. ;
  364. DTROFF:
  365. ;
  366. ; <== Start of user-defined code
  367. ;
  368.     LD    A,7FH        ; ask BIOS to raise DTR
  369.     jp    sioset
  370. ;
  371. ; <== End of user-defined code
  372. ;
  373.     ;RET
  374. ;
  375. ; Initialise the uart
  376. ;
  377. INIT:    LD    HL,2        ; Get parameters
  378.     ADD    HL,SP
  379.     EX    DE,HL
  380.     CALL    GETPARM        ; In HL
  381.     LD    (BRATE),HL    ; Baud rate
  382.     CALL    GETPARM
  383.     LD    (PARITY),HL    ; Parity
  384.     CALL    GETPARM
  385.     LD    (DATA),HL    ; Data bits (BINARY 7 or 8)
  386.     CALL    GETPARM
  387.     LD    (STOP),HL    ; Stop bits (BINARY 1 or 2)
  388. ;
  389. ; <== Start of user-defined code
  390. ;
  391. ;    LD    (MSPEED),A    ; Don't forget to load mspeed with the
  392. ;                ;   Current BRATE value if the new rate
  393. ;                ;   is valid.  See table of values below.
  394. ;
  395. INIT2:    ld    hl,(conout+1)    ; get BIOS CONOUT jump
  396.     ld    (outadd+1),hl    ; store it in print routine
  397.     LD    HL,(BRATE)    ; HL = baud-rate code
  398.     ADD    HL,HL        ; double it
  399.     LD    BC,BRTBL    ; BC = base of baud-rate look-up table
  400.     ADD    HL,BC        ; HL points to entry in look-up table
  401.     LD    E,(HL)        ; E = encoded tx baud rate
  402.     INC    HL
  403.     LD    D,(HL)        ; D = encoded rx baud rate
  404.     LD    A,E        ; encoded tx baud rate of 0 => not supported
  405.     OR    A
  406.     JR    NZ,SETBD    ; if not supported, print message & leave
  407.     CALL    PRINT        ;   baud rate set as present.
  408.     DB    'Baud Rate not supported.',CR,LF,0
  409.     JR    CHKPAR
  410. SETBD:    EX    DE,HL        ; HL = encoded baud-rates
  411.     CALL    BAUD        ; let BIOS set the baud-rate
  412.     LD    A,(BRATE)    ; adjust the ZMP modem speed variable
  413.     LD    (MSPEED),A
  414.     JR    CHKPAR        ; go on to set the rest of the uart parameters
  415.  
  416. BRTBL:    DB    03H,03H        ; 110 baud
  417.     DB    06H,06H        ; 300 baud
  418.     DB    08H,02H        ; 450 baud [ actually used for 7512 ]
  419.     DB    07H,07H        ; 600 baud
  420.     DB    02H,08H        ; 710 baud [ actually used for 1275 ]
  421.     DB    08H,08H        ; 1200 baud
  422.     DB    0AH,0AH        ; 2400 baud
  423.     DB    0CH,0CH        ; 4800 baud
  424.     DB    0EH,0EH        ; 9600 baud
  425. IF NOT FAXLINK
  426.     DB    0FH,0FH        ; 19200 baud
  427.     DB    00H,00H        ; 38400 baud
  428. ELSE
  429.     DB    00H,00H        ; 19200 baud
  430.     DB    0FH,0FH        ; 38400 baud
  431. ENDIF
  432.     DB    00H,00H        ; 57600 baud
  433.     DB    00H,00H        ; 76800 baud
  434.  
  435. CHKPAR:    LD    E,0        ; no parity => E = 0
  436.     LD    A,(PARITY)    ; A = parity value
  437.     CP    'N'
  438.     JR    z,chkdata
  439. NOTNONE:inc    e        ; odd parity => E = 1
  440.     CP    'O'
  441.     JR    z,chkdata
  442. NOTODD:    inc    e        ; even parity => E = 2
  443.  
  444. CHKDATA:LD    A,(DATA)    ; A = number of data bits
  445.     LD    H,A        ; H = rx data bits
  446.     LD    L,A        ; L = tx data bits
  447.  
  448.     LD    A,(STOP)    ; A = number of stop bits
  449.     dec    a
  450.     JR    NZ,STOP2
  451.     ld    d,a        ; 1 stop bit => D = 0
  452.     JR    SETSIO
  453. STOP2:    LD    D,2        ; 2 stop bits => D = 2
  454.  
  455. SETSIO:    LD    A,0FEH        ; sio mode = interrupt, no handshake
  456.     jr    sioset        ; let BIOS set up the sio port
  457.     ;RET
  458.  
  459.  
  460. BAUD:    CALL    PARMS        ; set the baud rate
  461.     DW    00B9H        ;   via extended BIOS function B9h
  462.     RET
  463.  
  464. SIOSET:    CALL    PARMS        ; set the sio parameters
  465.     DW    00B6H        ;   via extended BIOS function B6h
  466.     RET
  467.  
  468. getpara: call    parms        ; get the current settings
  469.     dw    0bch        ;   via extended BIOS function B9h
  470.     ret
  471.  
  472. PARMS:    JP    userf        ; BIOS entry point to set sio parameters
  473.                 ;  and baud rate. The code self-modifies
  474.                 ;  itself to provide the correct address.
  475. ;
  476. ; <== End of user-defined code
  477.  
  478.     ;RET
  479. ;
  480. ;-----------------------------------------------------------------------
  481. ;
  482. STOP:    DW    1        ; Stop bits
  483. PARITY:    DW    'N'        ; Parity
  484. DATA:    DW    8        ; Data bits
  485. BRATE:    DW    6        ; Baud rate:
  486. ;
  487. ;-----------------------------------------------------------------------
  488. ;
  489. ; Values of BRATE for each baud rate
  490. ;
  491. ; baud rate    BRATE
  492. ;
  493. ;   110      0
  494. ;   300      1
  495. ;   450      2
  496. ;   600      3
  497. ;   710      4
  498. ;  1200      5
  499. ;  2400      6
  500. ;  4800      7
  501. ;  9600      8
  502. ; 19200      9
  503. ; 38400     10
  504. ; 57600     11
  505. ; 76800     12
  506. ;
  507. ;-----------------------------------------------------------------------
  508. ;
  509. ; Set the port. ZMP supplies either 0 or 1 as a parameter. If you only
  510. ; have one UART port, or if you don't want to go through all the hassles
  511. ; just have this routine returning with no changes made. Note that ZMP
  512. ; calls this routine twice -- once for each port value -- on
  513. ; initialisation.
  514. ;
  515. SETPORT:LD    HL,2        ; Get port number
  516.     ADD    HL,SP
  517.     EX    DE,HL
  518.     CALL    GETPARM        ; In HL (values are 0 and 1)
  519. ;
  520. ;  <== Start of user defined code
  521. ;
  522. ;    Only one serial port on the PCW.
  523. ;
  524. ;  <== End of user defined code
  525. ;
  526.     RET
  527. ;
  528. PORT:    DS    1
  529. ;-----------------------------------------------------------------------
  530. ;
  531. ; Video terminal sequences: these are for Amstrad PCW8000 series
  532. ;
  533. ; Cursor addressing:
  534. ;
  535. CURSADD:LD    HL,2        ; Get parameters
  536.     ADD    HL,SP
  537.     EX    DE,HL
  538.     CALL    GETPARM        ; In HL
  539.     LD    (ROW),HL    ; Row
  540.     CALL    GETPARM
  541.     LD    (COL),HL    ; Column
  542. ;
  543. ; <== Start of user-defined code
  544. ;
  545.     CALL    PRINT
  546.     DB    ESC,'Y',0    ; leadin
  547.     LD    A,(ROW)        ; Row first
  548.     ADD    A,32        ; Add offset
  549.     CALL    COUT
  550.     LD    A,(COL)        ; Same for column
  551.     ADD    A,32
  552.     jr    COUT
  553. ;
  554. ; <== End of user-defined code
  555. ;
  556.     ;RET
  557. ;
  558. ROW:    DS    2        ; Row
  559. COL:    DS    2        ; Column
  560. ;
  561. ; Clear screen
  562. ;
  563. CLS:    CALL    PRINT
  564.     DB    ESC,'E',ESC,'H',0
  565.     RET
  566. ;
  567. ; Inverse video on
  568. ;
  569. INVON:    CALL    PRINT
  570.     DB    ESC,'p',0
  571.     RET
  572. ;
  573. ; Inverse video off
  574. ;
  575. INVOFF:    CALL    PRINT
  576.     DB    ESC,'q',0
  577.     RET
  578. ;
  579. ;Turn off cursor
  580. ;
  581. HIDE:    CALL    PRINT
  582.     DB    ESC,'f',0
  583.     RET
  584. ;
  585. ; Turn on cursor
  586. ;
  587. SHOW:    CALL    PRINT
  588.     DB    ESC,'e',0
  589.     RET
  590. ;
  591. ; Save cursor position
  592. ;
  593. SAVECU:    CALL    PRINT
  594.     DB    ESC,'j',0
  595.     RET
  596. ;
  597. ; Restore cursor position
  598. ;
  599. RESCU:    CALL    PRINT
  600.     DB    ESC,'k',0
  601.     ;RET
  602. ;
  603. ;-----------------------------------------------------------------------
  604. ;
  605. ; Service modem interrupt
  606. ;
  607. MINT:    ;RET            ; My system doesn't need this
  608. ;
  609. ; Initialise interrupt vectors
  610. ;
  611. INVEC:    ;RET            ; Ditto
  612. ;
  613. ; De-initialise interrupt vectors
  614. ;
  615. DINVEC:    RET            ; Ditto
  616. ;
  617. ;------------------ end of user-defined code ---------------------------
  618. ;        do not change anything below here
  619. ;
  620. ; Modem character test for 100 ms
  621. ;
  622. MRD:    PUSH    BC        ; Save BC
  623.     LD    BC,100        ; Set limit
  624. ;
  625. MRD1:    CALL    MIRDY        ; Char at modem?
  626.     JR    NZ,MRD2        ; Yes, exit
  627.     LD    HL,1        ; Else wait 1ms
  628.     CALL    WAITMSHL
  629.     DEC    BC        ; Loop till done
  630.     LD    A,B
  631.     OR    C
  632.     JR    NZ,MRD1
  633.     XOR    A
  634.     ld    h,a
  635.     ld    l,a        ; None there, result=0
  636. ;
  637. MRD2:    POP    BC
  638.     RET
  639. ;
  640. ; Inline print routine: destroys A and HL
  641. ;
  642. PRINT:    EX    (SP),HL        ; Get address of string
  643. ;
  644. PLOOP:    LD    A,(HL)        ; Get next
  645.     INC    HL        ; Bump pointer
  646.     OR    A        ; Done if zero
  647.     JR    Z,PDONE
  648.     CALL    COUT        ; Else print
  649.     JR    PLOOP        ; And loop
  650. ;
  651. PDONE:    EX    (SP),HL        ; Restore return address
  652.     RET            ; And quit
  653. ;
  654. ; Output a character in A to the console
  655. ;
  656. COUT:
  657. IF EMU
  658.     PUSH    BC        ; Save registers
  659.     PUSH    DE
  660.     PUSH    HL
  661. ELSE
  662.     exx            ; register switch is much faster than all those
  663.                 ; speed killing stack operations (but fatal with EMU!)
  664. ENDIF
  665.     ld    c,a        ; Character to E
  666. outadd:    call    0000        ; Print it (via the BIOS - BDOS was too slow)
  667. IF EMU
  668.     POP    HL
  669.     POP    DE
  670.     POP    BC
  671. ELSE
  672.     exx
  673. ENDIF
  674.     RET
  675. ;
  676. ; Wait(seconds)
  677. ;
  678. WAIT:    LD    HL,2
  679.     ADD    HL,SP
  680.     EX    DE,HL        ; Get delay size
  681.     CALL    GETPARM
  682. ;                ; Fall thru to..
  683. ;Wait seconds in HL
  684. ;
  685. WAITSHL:PUSH    BC        ; Save BC
  686.     PUSH    DE        ; DE
  687.     PUSH    IX        ; And IX
  688.     LD    IX,0        ; Then point IX to 0
  689.                 ; So we don't upset memory-mapped I/O
  690. ;
  691. ; Calculate values for loop constants. Need to have two loops to avoid
  692. ; 16-bit overflow with clock speeds above 9 MHz.
  693. ;
  694. OUTERVAL EQU    (CLKSPD/10)+1
  695. INNERVAL EQU    (6667/OUTERVAL)*CLKSPD
  696. ;
  697. WAIT10:    LD    B,OUTERVAL
  698. ;
  699. WAIT11:    LD    DE,INNERVAL
  700. ;
  701. WAIT12:    BIT    0,(IX)        ; Time-wasters
  702.     BIT    0,(IX)
  703.     BIT    0,(IX)        ; 20 T-states each
  704.     BIT    0,(IX)
  705.     BIT    0,(IX)
  706.     BIT    0,(IX)
  707.     DEC    DE
  708.     LD    A,E
  709.     LD    A,D
  710.     OR    E
  711.     JR    NZ,WAIT12    ; 150 T-states per inner loop
  712.     DJNZ    WAIT11        ; Decrement outer loop
  713.     DEC    HL        ; Ok, decrement count in hl
  714.     LD    A,H
  715.     OR    L
  716.     JR    NZ,WAIT10
  717.     POP    IX        ; Done -- restore ix
  718.     POP    DE        ; De
  719.     POP    BC        ; And bc
  720.     RET
  721. ;
  722. ; Wait milliseconds
  723. ;
  724. MSWAIT:    LD    HL,2
  725.     ADD    HL,SP
  726.     EX    DE,HL        ; Get delay size
  727.     CALL    GETPARM
  728. ;                ; Fall thru to..
  729. ; Wait milliseconds in HL
  730. ;
  731. WAITMSHL:PUSH    DE
  732. ;
  733. W1MS0:    LD    DE,39*CLKSPD
  734. ;
  735. W1MS1:    DEC    DE
  736.     LD    A,D
  737.     OR    E
  738.     JR    NZ,W1MS1
  739.     DEC    HL
  740.     LD    A,H
  741.     OR    L
  742.     JR    NZ,W1MS0
  743.     POP    DE
  744.     RET
  745. ;
  746. ; Get next parameter from (DE) into HL
  747. ;
  748. GETPARM:EX    DE,HL        ; Get address into HL
  749.     LD    E,(HL)        ; Get LOW
  750.     INC    HL
  751.     LD    D,(HL)        ; Then HIGH
  752.     INC    HL        ; Bump for next
  753.     EX    DE,HL        ; Result in hl, address still in de
  754.     RET
  755. ;
  756. ; Get address of user-defined variables
  757. ;
  758. GETVARS:LD    HL,USERVARS
  759.     RET
  760. ;
  761. USERVARS:
  762.     DW    OVERDRIVE    ; OVR etc. drive/user
  763.     DW    OVERUSER
  764.  
  765.     END
  766. ----------------------------------------------------
  767. ;
  768. ;    Amstrad PCW8000 Overlay for ZMP (Z-Modem Program)