home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / cpm80 / cpxpcw.asm < prev    next >
Assembly Source File  |  2020-01-01  |  23KB  |  913 lines

  1. IF NOT lasm
  2. .printx * CPXPCW.ASM *
  3. ENDIF    ;NOT lasm
  4. ;
  5. ; KERMIT - (Celtic for "FREE")
  6. ;
  7. ; This is the CP/M-80 implementation of the Columbia University
  8. ; KERMIT file transfer protocol.
  9. ;
  10. ; Version 4.08
  11. ;
  12. ; Copyright June 1981,1982,1983,1984,1985
  13. ; Columbia University
  14. ;
  15. ; Originally written by Bill Catchings of the Columbia University Center for
  16. ; Computing Activities, 612 W. 115th St., New York, NY 10025.
  17. ;
  18. ; This file contains the system-dependent code and data for KERMIT
  19. ; on the Amstrad range of personal computers.
  20. ;
  21. ;
  22. ; Revision history:
  23. ;
  24. ;edit 9, 22-Jan-1991 by MF. Added "sysinit" code at "init04" from Kermit
  25. ;    version 4.08 which had been left out of version 4.09 to reserve
  26. ;    space for the Amstrad's I/O buffers. Amstrad Kermit now stores
  27. ;    files correctly (version 4.09 had garbled files). Again,
  28. ;    this fix comes from Mr. D. P. Arnot of the Scottish Agricultural
  29. ;    College in the UK.
  30. ;edit 8, 16-Jan-1991 by MF. Added a "bs" left out of "delstr" per
  31. ;    instruction from David P. Arnot of Scottish Agricultural
  32. ;    College, Auchincruive, Ayr, UK.
  33. ;    E-mail:  <D.P.Arnot@edinburgh.ac.uk>
  34. ; edit 7, 22 July 1987 by OBSchou to massage code to fit with CPXCOM.ASM
  35. ;    Had to rename bcnout to bcnot as the former label clashed with
  36. ;    one of the same name in CPXCOM.ASM.  Sorry, folks.
  37. ;
  38. ; edit 6, 14th July, 1987 by OBSchou for Phillip Wade, Hull University
  39. ;    Computer Centre.  Change to delchr routine for PCW machines, 
  40. ;    as character 127 decimal is a printing character on 
  41. ;    the Amstrad PCW.  The routine has been replaced 
  42. ;    by a bs,space,bs,bs string. (OBS Comment - why a total of THREE bs?)
  43. ;
  44. ; edit 5 9 May 1987 by C.J.MILES@UK.AC.UMRCC
  45. ;    Hangup phone and clear screen options added to
  46. ;    terminal mode.
  47. ;
  48. ; edit 4 23 March 1987 by C.J.MILES@UK.AC.UMRCC
  49. ;    Use direct input drom SIO for CPC machines instead
  50. ;    of using BDOS. Improvement reduces time for file
  51. ;    transfer to 65% of time used by BDOS method.
  52. ;    Add reverse Prestel baud rate.
  53. ;
  54. ; edit 3 20 March 1987 by Chris Miles (C.J.MILES@UK.AC.UMRCC)
  55. ;    (Greater Manchester Archaeological Unit, Manchester Univ.).
  56. ;    Added support for Amstrad CPC CP/M Plus machines,
  57. ;    Added 31250 baud rate option,
  58. ;    Bug fixed in sending BREAK,
  59. ;    Bug fixed in 1200/75 baud setup
  60. ;    Machine and CP/M version checks added.
  61. ;
  62. ; edit 2 11 Febuary, 1987 by OBSchou for Ian Young.
  63. ;    Changes to the send break routine to change two lines of code from
  64. ;        ori    018h        ; send break, Tx enable
  65. ;    and    ori    0008h        ; Tx enable 
  66. ;
  67. ;    to    ori    01ah        ; send break, Tx enable, RTS
  68. ;    and    ori    00ah        ; Tx enable, RTS
  69. ;
  70. ;    This is a bug fix to hopefully keep RTS actve during breaks.
  71. ;
  72. ; [Ed. (OBSchou) 21/1/87.
  73. ; This file linked FROM cpxsys.asm, so do NOT rename this
  74. ; file.  The diffculty of needing a HUGE CPXSYS.ASM file on your floppy
  75. ; only to act as a switcher remains, but hopefully will be better in 
  76. ; the future.  If you ARE stuck, then rename this CPXSYS.ASM but add the
  77. ; label SYSEDT: to the FAMILY label.  A bit messy.]
  78. ;
  79. ;
  80. ; The "author" of this system-dependent file is:
  81. ;
  82. ;  Ian A. Young
  83. ;  Lattice Logic Ltd
  84. ;  9 Wemyss Place
  85. ;  Edinburgh
  86. ;
  87. ; Some other addresses:
  88. ;
  89. ;  ian@latlog.uucp
  90. ;  ...seismo!mcvax!ukc!latlog!ian
  91. ; or c/o OBSchou@uk.ac.lut.multics
  92. ;
  93. ; ... although much of the code concerned was written by others.
  94. ;
  95.  
  96.  
  97. ; Keep module name, edit number, and last revision date in memory.
  98.  
  99. ;sysedt:    db    'CPXSYS.ASM (36) 20-Mar-87$'
  100. family:    db    'CPXPCW.ASM (9)  22-Jan-1991$'
  101.  
  102.  
  103. ;
  104. ; Assembly-time message announcing which version we are building
  105. ;
  106.  
  107. IF pcw
  108. .printx    * Assembling Amstrad PCW Kermit-80 *
  109. ENDIF
  110.  
  111. IF cpc
  112. .printx    * Assembling Amstrad CPC Kermit-80 *
  113. ENDIF
  114.  
  115. ;
  116. ; Miscellany of parameter settings
  117. ;
  118. z80    EQU    TRUE         ; all Amstrads have a Z80.
  119. defesc    EQU    '\'-100O    ; The default escape character.
  120. vtval    EQU    0         ; we don't need VT52 emulation
  121.  
  122. ;
  123. ; Amstrad CPC machines use 16 bit I/O address decoding and therefore
  124. ; the Z80 instructions OUT (C),A and IN A,(C) must be defined.
  125. ;
  126. outc    EQU    79edh        ; IN    A,(C)
  127. inpc    EQU    78edh        ; OUT    (C),A
  128.  
  129. ;
  130. ; hardware information
  131. ;
  132. ; There is a Z80-DART (Mostek/SGS 8470) at I/O addresses E0..E3 (PCW)
  133. ; and FADC..FADD (CPC), and a 8253 programmable divider running it at
  134. ; E4..E7 (PCW) and FBDC..FBDF (CPC)
  135. ;
  136.  
  137. input    EQU    01h        ; input data available
  138. output    EQU    04h        ; output buffer ready
  139.  
  140. IF pcw
  141. mnport    EQU    0E0h        ; data register for SIO
  142. mnprts    EQU    0E1h        ; control register for SIO
  143. ctc0    EQU    0E4h        ; 8253 load counter 0
  144. ctc1    EQU    0E5h        ; 8253 load counter 1
  145. ctcmod    EQU    0E7h        ; 8253 write mode word
  146. ENDIF
  147.  
  148. IF cpc
  149. mnport    EQU    0FADCh        ; data register for SIO
  150. mnprts    EQU    0FADDh        ; control register for SIO
  151. ctc0    EQU    0FBDCh        ; 8253 load counter 0
  152. ctc1    EQU    0FBDDh        ; 8253 load counter 1
  153. ctcmod    EQU    0FBDFh        ; 8253 write mode word
  154. ENDIF
  155.  
  156. ;
  157. ; SIO input buffering
  158. ;
  159. siosz    EQU    4096        ; size of SIO input buffer
  160. siomsk    EQU    4095        ; mask for wrapping buffer round
  161.  
  162. ;
  163. ; Extended BIOS jump-block addresses; reached through USERF
  164. ;
  165. sainit    EQU    00B6h        ; initialise SIO
  166. sabaud    EQU    00B9h        ; set baud rate
  167. saparm    EQU    00BCh        ; fetch SIO parameters
  168. teask    EQU    00BFh        ; find out cursor position
  169. cdvers    EQU    00E3h        ; get version numbers
  170. cdinfo    EQU    00E6h        ; get BIOS system information
  171.  
  172. ;
  173. ; System-dependent initialization
  174. ; Called once at program start.
  175. sysxin:        ; continuation of system initialzation 
  176. ;
  177. ; check for correct CP/M version
  178. ;
  179.     mvi    c,12        ; get CP/M version BDOS call
  180.     call    bdos
  181.     mov    a,l        ; check if CP/M Plus
  182.     cpi    31h
  183.     jz    init08
  184.     lxi    d,wrong2    ; point to error message
  185.     call    prtstr
  186.     mvi    c,0        ; warm boot
  187.     call    bdos
  188. ;
  189. init08:        ;[OBS] Moved the Cinfigured for message out as
  190.         ;[OBS]   it is in CPXCOM.ASM
  191. ;
  192. ; get addresses of BIOS routines
  193. ;
  194. ; BIOS USERF is used to get to extended BIOS routines
  195. ;
  196.     lhld    1        ; warm boot vector
  197.     lxi    d,87        ; offset to USERF vector
  198.     dad    d        ; DE now has USERF vector address
  199.     shld    userf+1        ; ready for jumping to...
  200. ;
  201. ; BIOS routines for fast character I/O
  202. ;
  203.     lhld    1        ; warm boot vector (#1)
  204.     lxi    d,3
  205.     dad    d        ; next is #2, CONST
  206.     shld    bcnst+1
  207.     dad    d        ; next is #3, CONIN
  208.     shld    bcnin+1
  209.     dad    d        ; next is #4, CONOUT
  210.     shld    bcnot+1        ;[obs] Was bcnout, but this conflicts
  211.                 ;[obs] with a label in CPXCOM.ASM
  212.     dad    d        ; next is #5, LIST
  213.     shld    blist+1
  214.     dad    d        ; next is #6, AUXOUT
  215.     dad    d        ; next is #7, AUXIN
  216.     shld    baxin+1
  217.     lhld    1        ; warm boot vector again
  218.     lxi    d,002Ah        ; offset to LISTST (#15)
  219.     dad    d
  220.     shld    lptstat+1
  221.     lhld    1        ; warm boot vector again
  222.     lxi    d,0033h        ; offset to AUXIST (#18)
  223.     dad    d
  224.     shld    baxist+1
  225. ;
  226. ; check if running on correct Amstrad
  227. ;
  228.     call    userf
  229.     dw    cdvers
  230. IF pcw
  231.     cpi    0
  232. ENDIF
  233. IF cpc
  234.     cpi    1
  235. ENDIF
  236.     jnz    init06
  237.     lxi    d,wrong1    ; point to error message
  238.     call    prtstr
  239.     mvi    c,0
  240.     call    bdos
  241. ;
  242. ; verify presence of SIO board by asking the BIOS.
  243. ;
  244. init06:    call    userf        ; C gets 00 if not fitted
  245.     dw    cdinfo
  246.     xra    a        ; a <- 0
  247.     ora    c        ; zero => no serial port
  248.     jnz    init03        ; non-zero => OK
  249.     lxi    d,nosio        ; snooty message...
  250.     call    prtstr
  251.     mvi    c,0        ; warm boot out of here
  252.     call    bdos
  253. init03:
  254. ;
  255. ; find initial baud rate and other information
  256. ;
  257.     call    userf        ; gives B=rx baud, C=tx baud, D=stop bits,
  258.                 ; E=parity, H=rx bits, L=tx bits.
  259.     dw    saparm        ; get SIO parameters
  260.     push    h        ; save bit settings
  261.     mov    a,b        ; if TX and RX speeds same, they are OK
  262.     cmp    c
  263.     jz    init01
  264.     cpi    8        ; rx=1200?
  265.     jnz    init02        ; no, can't be Prestel
  266.     mov    a,c
  267.     cpi    2        ; tx=75?
  268.     jnz    init02        ; no, can't be Prestel
  269.     lxi    b,0        ; otherwise 1200/75 comes out as 0s.
  270. init01:    push    b        ; assign value to SPEED
  271.     pop    h
  272.     shld    speed
  273. init02:                ; here if we leave it as is
  274.     pop    h        ; get bit settings
  275.     mov    a,l        ; no of TX data bits set
  276.     sui    5        ; make into 00, 01, 10, 11.
  277.     rrc
  278.     rrc
  279.     rrc
  280.     sta    txbits        ; we may need it later
  281. ;
  282. ; set handshake mode: there are two parts to this, interrupts and
  283. ; hardware handshake. The MODE byte used by the firmware expresses
  284. ; this combination as -(int*2 + hand*1).  Thus, both options on would
  285. ; be (-3) or 0FDh.
  286. ;
  287. ; Here, we set the interrupt part of the mode on; it helps the BIOS cope.
  288. ; Unfortunately, >sigh<, according to Soft971, this will only work
  289. ; if you have BIOS V1.4 or higher.  I have no idea what would happen
  290. ; if we tried random hanshake mode flags with lower versions, so we
  291. ; just skip over if it would be dangerous...
  292. ;
  293.     call    userf        ; fetch all parameters
  294.     dw    saparm
  295.     sta    orgmode        ; remember original mode for later
  296.  
  297.     call    userf        ; get BIOS version to B,C
  298.     dw    cdvers
  299.     mov    a,b        ; BIOS major version number (eg 1)
  300.     ora    a        ; if zero, too low...
  301.     jz    init04
  302.     cpi    1        ; if not 1, definitely OK
  303.     jnz    init05
  304.     mov    a,c        ; otherwise, its 1.X; want >= 4
  305.     cpi    4
  306.     jm    init04        ; <4 => too low
  307.  
  308. init05:    call    userf        ; get the original flags back
  309.     dw    saparm
  310.     xri    0FFh        ; make mode into bit mask
  311.     inr    a
  312.     ori    2        ; set interrupt mode
  313.     xri    0FFh        ; turn back into mode value
  314.     inr    a
  315.     call    userf        ; feed change back to BIOS
  316.     dw    sainit
  317. init04:                ; come here if not setting mode
  318.  
  319. ; Locate large buffers for multi-sector I/O and SIO input buffering.
  320. ; Space above ovlend is available for buffers; we have pretty well the machine
  321. ; to ourselves in an Amstrad PCW because they all gave 61K TPAs. We don't even
  322. ; bother to perform any checking.
  323. ; We don't want to use more than maxsec for disk buffers because
  324. ; if we use too many, the remote end could time out while we're
  325. ; writing to disk.  maxsec is system-dependent, but for now we'll just
  326. ; use 8Kbytes.  If you get retransmissions and other protocol errors after
  327. ; transferring the first maxsec sectors, lower maxsec.
  328. ;
  329. maxsec  EQU     (8*1024)/bufsiz ; 8K / number of bytes per sector
  330.  
  331.         lxi     h,ovlend+siosz  ; get start of buffer
  332.         shld    bufadr          ; store in linkage section
  333.         mvi     a,maxsec        ; get size of buffer, in sectors
  334.         sta     bufsec          ; store that, too.
  335.  
  336.  
  337.         ret                     ; return from system-dependent routine
  338.  
  339. ;
  340. ; message complaining about wrong Amstrad machine
  341. ;
  342. wrong1:    db    'Error -   This Kermit will only run on the Amstrad '
  343. IF pcw
  344.     db    'PCW 8256/8512'
  345. ENDIF
  346. IF cpc
  347.     db    'CPC 464/664/6128'
  348. ENDIF
  349.     db    cr,lf,'$'
  350. ;
  351. ; message complaining about version of CP/M being used
  352. ;
  353. wrong2:    db    'Error - Incorrect CP/M version, needs CP/M 3.x'
  354.     db    cr,lf,'$' 
  355. ;
  356. ; message complaining of no SIO board
  357. ;
  358. nosio:    db    'Error -   No SIO option fitted to this machine'
  359.     db    cr,    lf, '$'
  360.  
  361. ;
  362. ; jumps to BIOS character I/O routines.
  363. ; Addresses filled in by initialisation code above.
  364. ;
  365. bcnst:    jmp    $-$        ; console status
  366. bcnin:    jmp    $-$        ; console input
  367. bcnot:    jmp    $-$        ; console output [obs - was bcnout]
  368. blist:    jmp    $-$        ; printer output
  369. baxin:    jmp    $-$        ; aux port input
  370. baxist:    jmp    $-$        ; aux port status
  371. lptstat:jmp    $-$        ; printer status
  372.  
  373. ;
  374. ; Other BIOS routines
  375. ;
  376. userf:    jmp    $-$        ; call extended BIOS function
  377.  
  378. ;
  379. ; saved value of some original parameters
  380. ;
  381. orgmode:ds    1
  382. txbits:    ds    1
  383.  
  384. ;
  385. ; system-dependent termination processing
  386. ; If we've changed anything, this is our last chance to put it back.
  387. sysexit:
  388.     call    userf        ; fetch firmware parameters
  389.     dw    saparm
  390.     lda    orgmode        ; replace with original mode
  391.     call    userf        ; inform BIOS
  392.     dw    sainit
  393.     ret
  394.  
  395. ;
  396. ; system-dependent processing for start of CONNECT command
  397. ;
  398. syscon:
  399.     lxi    d,conmsg    ; how to get escape char message
  400.     call    prtstr
  401.     ret
  402.  
  403. conmsg:        ; Messages printed when entering transparent (CONNECT) mode:
  404. IF pcw
  405.     db    '(Use boxed minus key next to space bar to generate a Control-\)'
  406. ENDIF
  407.     db    cr,lf,'$'
  408.  
  409. ;
  410. ; syscls - system-dependent close routine
  411. ; called when exiting transparent session.
  412. ;
  413. syscls:
  414.     ret
  415.  
  416. ;
  417. ; sysinh - help for system-dependent special functions.
  418. ; called in response to <escape>?, after listing all the
  419. ; system-independent escape sequences.
  420. ;
  421. sysinh:
  422.     lxi    d,inhlps    ; we got options...
  423.     call    prtstr        ; print them.
  424.     ret
  425.  
  426. ;
  427. ; additional, system-dependent help for transparent mode
  428. ; (two-character escape sequences)
  429. ;
  430. inhlps:
  431.     db    cr,lf,'B  Transmit a BREAK'
  432.     db    cr,lf,'H  Hangup using DTR'
  433.     db    cr,lf,'W  Wipe screen clear'
  434.     db    '$'            ;[hh] table terminator
  435.  
  436. ;
  437. ; sysint - system dependent special functions
  438. ; called when transparent escape character has been typed;
  439. ; the second character of the sequence is in A (and in B).
  440. ; returns:
  441. ;         non-skip: sequence has been processed
  442. ;         skip    : sequence was not recognized
  443. ;
  444. sysint:    ani    137O        ; convert lower case to upper, for testing...
  445.     cpi    'B'        ; send break ?
  446.     jz    sendbr        ; yes, go do it.  return nonskip when through.
  447.     cpi    'H'        ; hang up ?
  448.     jz    hangup
  449.     cpi    'W'        ; clear screen ?
  450.     jz    clrtop
  451.     jmp    rskp        ; take skip return - command not recognized.
  452.  
  453. ;
  454. ; Hangup (drop DTR) and Break send routine
  455. ;
  456.  
  457. hangup:
  458.     mvi    d,0ah        ; set up hangup bit mask
  459.     mvi    e,255        ; time for hangup is 2 1/2 secs
  460.     jmp    setbit        ; skip Tx empty test
  461.  
  462. sendbr:
  463.     mvi    d,9ah        ; set up break bit mask
  464.     mvi    e,30        ; time for break is 300 ms
  465.  
  466. sndbr1:    mvi    a,1        ; select Read Register 1
  467.  
  468. IF pcw    ; allow 8 bit I/O instructions
  469.     out    mnprts
  470.     in    mnprts        ; read the contents
  471. ENDIF
  472.  
  473. IF cpc    ; use 16 bit I/O instructions
  474.     lxi    b,mnprts
  475.     dw    outc        ; OUT    (C),A
  476.     dw    inpc        ; IN    A,(C)
  477. ENDIF
  478.  
  479.     ani    1        ; test "all done" flag
  480.     jz    sndbr1        ; loop until it's nonzero.
  481. ;
  482. ; Next, set the break or hangup bit on the SIO.
  483. ;
  484. setbit:
  485.     mvi    a,5        ; select Write Register 5
  486. IF pcw
  487.     out    mnprts
  488. ENDIF
  489. IF cpc
  490.     dw    outc        ; OUT    (C),A
  491. ENDIF
  492.     lda    txbits        ; get txbits (already in correct bit positions)
  493.     ora    d        ; send break, Tx Enable, RTS
  494. IF pcw
  495.     out    mnprts
  496. ENDIF
  497. IF cpc
  498.     dw    outc        ; OUT    (C),A
  499. ENDIF
  500.  
  501. ;
  502. ; Now, delay for duration of hangup or break
  503. ;
  504.     mov    a,e        ; delay count
  505.     call    delay
  506. ;
  507. ; Time's up. Put transmitter back in normal state and return.
  508. ;
  509.     mvi    a,5        ; select Write Register 5
  510. IF pcw
  511.     out    mnprts
  512. ENDIF
  513. IF cpc
  514.     lxi    b,mnprts
  515.     dw    outc        ; OUT    (C),A
  516. ENDIF
  517.     lda    txbits        ; get txbits again
  518.     ori    8ah        ; Reset break, Tx Enable, RTS
  519. IF pcw
  520.     out    mnprts
  521. ENDIF
  522. IF cpc    
  523.     dw    outc        ; OUT    (C),A
  524. ENDIF
  525.     ret            ; done.
  526.  
  527. ;
  528. ; sysflt - system-dependent filter
  529. ; called with character in E.
  530. ; if this character should not be printed, return with A = zero.
  531. ; preserves bc, de, hl.
  532. ; note: <xon>,<xoff>,<del>, and <nul> are always discarded.
  533. ;
  534. sysflt:
  535.     mov    a,e        ; get character for testing
  536.     ret
  537. ;
  538. ; system-dependent processing for BYE command.
  539. ;
  540. sysbye:
  541.     ret
  542.  
  543. ;
  544. ; This is the system-dependent command to change the baud rate.
  545. ; DE contains the two-byte value from the baud rate table; this
  546. ; value is also stored in 'speed'.
  547. ;
  548. sysspd:
  549.     push    d        ; move to HL for firmware
  550.     pop    h
  551.     mov    a,h        ; if h=0 then Prestel rates
  552.     ora    a
  553.     jnz    spd01        ; if not 1200/75 then skip
  554.     lxi    h,0802H        ; else set 1200/75 into HL
  555.     jmp    spd03        ; jump to normal setup
  556.  
  557. spd01:    cpi    11h        ; if h=11h then reverse Prestel
  558.     jnz    spd02        ; if not 75/1200 then skip
  559.     lxi    h,0208h        ; else set 75/1200 into HL
  560.     jmp    spd03        ; jump to normal setup
  561.  
  562. spd02:    cpi    10h        ; if h=10h then 31250 baud
  563.     jnz    spd03        ; if not 31250 then skip to normal setup
  564.     mvi    a,36h        ; set 8253 for mode 2 binary count
  565.     lxi    b,ctcmod    ; output to CTC mode register
  566.     dw    outc
  567.     lxi    b,ctc0        ; select transmit clock
  568.     mov    a,4        ; timer value for 31250 (04h)
  569.     dw    outc
  570.     mov    a,0        ; timer value for 31250 (04h)
  571.     dw    outc
  572.     lxi    b,ctc0        ; select receive clock
  573.     mov    a,4        ; timer value for 31250 (04h)
  574.     dw    outc
  575.     mov    a,0        ; timer value for 31250 (04h)
  576.     dw    outc
  577.     ret
  578.  
  579. spd03:    call    userf        ; set whatever we have now...
  580.     dw    sabaud        ; using BIOS routine
  581.     ret
  582.  
  583. ;
  584. ; Speed tables
  585. ; (Note that speed tables MUST be in alphabetical order for later
  586. ; lookup procedures, and must begin with a value showing the total
  587. ; number of entries.  The speed help tables are just for us poor
  588. ; humans.
  589. ;
  590. ; db string length,string,divisor (2 identical bytes or 1 word)
  591. ;
  592. spdtbl:    db    12h            ;18 entries
  593.     db    03h,'110$', 03h,03h
  594.     db    04h,'1200$', 08h,08h
  595.     db    07h,'1200/75$', 00h,00h    ; real values faked up when required
  596.     db    05h,'134.5$', 04h,04h
  597.     db    03h,'150$', 05h,05h
  598.     db    04h,'1800$', 09h,09h
  599.     db    05h,'19200$', 0fh,0fh
  600.     db    04h,'2400$', 0ah,0ah
  601.     db    03h,'300$', 06h,06h
  602.     db    05h,'31250$',10h,10h    ; flag to direct setup routine
  603.     db    04h,'3600$', 0bh,0bh
  604.     db    04h,'4800$', 0ch,0ch
  605.     db    02h,'50$', 01h,01h
  606.     db    03h,'600$', 07h,07h
  607.     db    04h,'7200$', 0dh,0dh
  608.     db    02h,'75$', 02h,02h
  609.     db    07h,'75/1200$',11h,11h    ; real values faked up when required
  610.     db    04h,'9600$', 0eh,0eh
  611.  
  612. sphtbl:    db    cr,lf,lf
  613.     db    'Normal rates: 50    75    110   134.5 150   300   600'
  614.     db    cr,lf
  615.     db    '              1200  1800  2400  3600  4800  7200  9600  19200'
  616.     db    cr,lf,lf
  617.     db    'High speed  : 31250 (only between Amstrads)'
  618.     db    cr,lf,lf
  619.     db    'Split rates : 1200/75 (Rx=1200, Tx=  75)'
  620.     db    cr,lf
  621.     db    '              75/1200 (Rx=  75, Tx=1200)'
  622.     db    cr,lf,'$'
  623.  
  624. ;
  625. ; This is the system-dependent SET PORT command.
  626. ; HL contains the argument from the command table.
  627. ;
  628. sysprt:
  629.     ret
  630.  
  631. prttbl    equ    0        ; SET PORT is not supported
  632. prhtbl    equ    0
  633.  
  634. ;
  635. ; selmdm - select modem port
  636. ; selcon - select console port
  637. ; selmdm is called before using inpmdm or outmdm;
  638. ; selcon is called before using inpcon or outcon.
  639. ; preserves bc, de, hl.
  640. ;
  641. selmdm:
  642. selcon:
  643.     ret
  644.  
  645. ;
  646. ; Get character from console, or return zero.
  647. ; result is returned in A.  destroys bc, de, hl.
  648. ;
  649. inpcon:
  650.     call    bcnst        ; get console status
  651.     ora    a        ; anything there?
  652.     rz            ; no, forget it
  653.     jmp    bcnin        ; yes, get the character
  654.  
  655. ;
  656. ; Output character in E to the console.
  657. ; destroys bc, de, hl
  658. ;
  659. outcon:
  660.     mov    a,e        ; TAB?
  661.     cpi    tab
  662.     jz    out001
  663.     mov    c,e        ; set correct arg register
  664.     jmp    bcnot        ; output to console via BIOS [obs was bcnout]
  665.  
  666. ;
  667. ; perform tab expansion ourselves
  668. ;
  669. out001:    call    userf        ; get column in L
  670.     dw    teask
  671.     mov    a,l        ; a <- column 0..n
  672.     ani    7        ; column 0..7
  673.     xri    0FFh        ; not(col 0..7)
  674.     adi    9        ; a is 8-(colf7)
  675. out002:    ora    a        ; any left?
  676.     rz            ; return if not
  677.     dcr    a        ; one less now, anyhow
  678.     push    psw        ; save over BIOS call (just in case)
  679.     mvi    c,' '        ; print one space
  680.     call    bcnot        ;[obs was bcnout]
  681.     call    suck        ; in case any stuff coming in
  682.     pop    psw        ; fetch count back
  683.     jmp    out002        ; and go round again
  684.  
  685. ;
  686. ; outmdm - output a char from E to the modem.
  687. ;  the parity bit has been set as necessary.
  688. ; returns nonskip; bc, de, hl preserved.
  689. outmdm:
  690. IF cpc
  691.     push    b        ; save BC for CPC 16 bit I/O
  692. ENDIF
  693. outmd1:
  694.     call    xsuck        ; keep checking for incoming characters
  695. IF pcw
  696.     in    mnprts        ; get the output done flag.
  697. ENDIF
  698. IF cpc
  699.     lxi    b,mnprts
  700.     dw    inpc        ; IN    A,(C)
  701. ENDIF
  702.     ani    output        ; is it set?
  703.     jz    outmd1        ; if not, loop until it is.
  704.     mov    a,e
  705. IF pcw
  706.     out    mnport        ; output it.
  707. ENDIF
  708. IF cpc
  709.     lxi    b,mnport
  710.     dw    outc        ; OUT    (C),A
  711.     pop    b        ; restore BC
  712. ENDIF
  713.     ret
  714.  
  715. ;
  716. ; get character from modem; return zero if none available.
  717. ; destroys bc, de, hl.
  718. ;
  719. inpmdm:
  720.     call    suck        ; get any characters pending
  721.     lhld    sioct        ; count of chars in buffer
  722.     mov    a,h        ; or together to get result
  723.     ora    l
  724.     rz            ; not got any, return now
  725.  
  726.     dcx    h        ; down count
  727.     shld    sioct
  728.  
  729.     lhld    siord        ; read pointer
  730.     mov    c,m        ; fetch character ** NB TO C FOR NOW **
  731.  
  732.     lxi    d,1-ovlend    ; bump pointer, subtract base
  733.     dad    d
  734.     mov    a,h        ; mask high byte of offset
  735.     ani    siomsk/256
  736.     mov    h,a
  737.     lxi    d,ovlend    ; add in base again
  738.     dad    d
  739.     shld    siord
  740.  
  741.     mov    a,c        ; get to proper register
  742.     ret
  743.  
  744. ;
  745. ; flsmdm - flush comm line.
  746. ; Modem is selected.
  747. ; Currently, just gets characters until none are available.
  748.  
  749. flsmdm:    call    inpmdm        ; Try to get a character
  750.     ora    a        ; Got one?
  751.     jnz    flsmdm        ; If so, try for another
  752.     ret            ; Receiver is drained.  Return.
  753.  
  754. ;
  755. ; SIO input buffer handling.  The buffer pointers are held as pointers into
  756. ; the buffer. The read pointer
  757. ; is to the next unused character, the write pointer to the next unused space.
  758. ;
  759. siord:    dw    ovlend        ; next char to read
  760. siowr:    dw    ovlend        ; next char to write
  761. sioct:    dw    0        ; number in buffer
  762.  
  763. xsuck:    push    d        ; save regs version of suck
  764.     push    b
  765.     push    h
  766.     call    suck
  767.     pop    h
  768.     pop    b
  769.     pop    d
  770.     ret
  771.  
  772. ;
  773. ; suck
  774. ;
  775. ; this routine is called whenever it would be possible that some
  776. ; characters might be available in the SIO device; they are all
  777. ; transferred (there may be up to 4 pending) to the buffer.
  778. ;
  779. ; all registers are destroyed
  780. ;
  781. suck:
  782. IF pcw
  783.     call    baxist        ; check input status via BDOS
  784.     ora    a        ; check if zero
  785. ENDIF
  786. IF cpc
  787.     lxi    b,mnprts    ; get input status directly
  788.     dw    inpc        ; IN A,(C)
  789.     ani    input        ; mask for Rx ready
  790. ENDIF
  791.     rz            ; return if no
  792.  
  793. IF pcw
  794.     call    baxin        ; fetch character via BDOS
  795. ENDIF
  796. IF cpc
  797.     lxi    b,mnport    ; fetch character directly from SIO
  798.     dw    inpc        ; IN A,(C)
  799. ENDIF
  800.  
  801.     lhld    siowr        ; write pointer
  802.     mov    m,a        ; put character
  803.  
  804.     lxi    d,1-ovlend    ; take off base, bump pointer
  805.     dad    d
  806.     mov    a,h        ; top byte of offset
  807.     ani    siomsk/256    ; masked off
  808.     mov    h,a
  809.     lxi    d,ovlend    ; add on base again
  810.     dad    d
  811.     shld    siowr        ; replace pointer
  812.  
  813.     lhld    sioct        ; bump count in buffer
  814.     inx    h
  815.     shld    sioct
  816.  
  817.     jmp    suck        ; go round in case any more
  818.  
  819. ;
  820. ; outlpt - output character in E to printer
  821. ; console is selected.
  822. ; preserves de.
  823. outlpt:
  824.     push    d        ; save DE in either case
  825.     mov    c,e        ; correct arg register
  826.     call    blist
  827.     pop    d        ; restore saved register pair
  828.     ret
  829.  
  830. ;
  831. ; Screen manipulation routines
  832. ; csrpos - move to row B, column C
  833. ;
  834. ; csrpos for terminals that use a leadin sequence followed
  835. ;  by (row + 31.) and (column + 31.)
  836. ;  or (row) and (column)
  837. ;
  838. csrpos:    push    b        ; save coordinates
  839.     lxi    d,curldn    ; get cursor leadin sequence
  840.     call    prtstr        ; print it
  841.     pop    h        ; restore coordinates
  842.     mov    a,h        ; get row
  843.     adi    (' '-1)        ; space is row one
  844.     mov    e,a
  845.     push    h
  846.     call    outcon        ; output row
  847.     pop    h
  848.     mov    a,l        ; get column
  849.     adi    (' '-1)        ; space is column one
  850.     mov    e,a
  851.     jmp    outcon        ; output it and return
  852.  
  853. ;
  854. ; delchr - make delete look like a backspace.  Unless delete is a printing
  855. ; character, we just need to print a backspace. (we'll output clrspc
  856. ; afterwards)
  857. ; For Kaypro and Vector General, delete puts a blotch on the screen.
  858. ; For Apple and Osborne 1, delete moves but doesn't print.
  859. delchr:
  860. IF pcw    ;[6] OBS for Phillip Wade
  861.     lxi    d,delstr    ;[5] send a string rather than a single character
  862.     call    prtstr
  863.  
  864. delstr:    db    bs,' ',bs,'$'    ;[OBS] Was bs,space,bs,bs
  865. ENDIF    ;pcw
  866.  
  867.     mvi    e,bs        ;get a backspace
  868.     jmp    outcon
  869.  
  870. ; erase the character at the current cursor position
  871. clrspc:    mvi    e,' '
  872.     call    outcon
  873.     mvi    e,bs        ;get a backspace
  874.     jmp    outcon
  875.  
  876. ; erase the current line
  877. clrlin:    lxi    d,eralin
  878.     jmp    prtstr
  879.  
  880. ; erase the whole screen, and go home. preserves b (but not c)
  881. clrtop:    lxi    d,erascr
  882.     jmp    prtstr
  883.  
  884.  
  885. IF pcw
  886. sysver:    db    'Amstrad PCW with SIO option$'
  887. ENDIF
  888. IF cpc
  889. sysver:    db    'Amstrad CPC with CP/M Plus$'
  890. ENDIF
  891.  
  892. outlin:    db    esc,'H',esc,'J',cr,lf,'                $'
  893.  
  894. erascr:    db    esc,'H',esc,'J$'    ;Clear screen and go home.
  895. eralin:    db    cr,esc,'K$'        ;Clear line.
  896. curldn:    db    esc,'Y$'        ;cursor leadin
  897. ttab:                    ;Table start location.
  898. ta:    db    esc,'A$',0        ;Cursor up.
  899. tb:    db    esc,'B$',0        ;Cursor down.
  900. tc:    db    esc,'C$',0        ;Cursor right.
  901. td:    db    esc,'D$',0        ;Cursor left
  902. te:    db    esc,'E$',0        ;Clear display
  903. tf:    db    '$',0,0,0        ;Enter Graphics Mode
  904. tg:    db    '$',0,0,0        ;Exit Graphics mode
  905. th:    db    esc,'H$',0        ;Cursor home.
  906. ti:    db    esc,'I$',0        ;Reverse linefeed.
  907. tj:    db    esc,'J$',0        ;Clear to end of screen.
  908. tk:    db    esc,'K$',0        ;Clear to end of line.
  909.  
  910. ovlend    equ    $    ; End of overlay
  911.  
  912.     END
  913.