]> cloudbase.mooo.com Git - kermit-80.git/blob - cpxpcw.asm
Bugfix in outmdm (output buffer flush)
[kermit-80.git] / cpxpcw.asm
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