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