]> cloudbase.mooo.com Git - kermit-80.git/blame - cpstt.asm
Bugfix in outmdm (output buffer flush)
[kermit-80.git] / cpstt.asm
CommitLineData
e58a7a25
L
1; CPSTT.ASM\r
2; KERMIT - (Celtic for "FREE")\r
3;\r
4; This is the CP/M-80 implementation of the Columbia University\r
5; KERMIT file transfer protocol.\r
6;\r
7; Version 4.0\r
8;\r
9; Copyright June 1981,1982,1983,1984,1985\r
10; Columbia University\r
11;\r
12; Originally written by Bill Catchings of the Columbia University Center for\r
13; Computing Activities, 612 W. 115th St., New York, NY 10025.\r
14;\r
15; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,\r
16; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many\r
17; others. \r
18;\r
19; This file contains the code for the TRANSMIT and CONNECT commands,\r
20; which communicate with a host which is not running KERMIT.\r
21;\r
22; revision history:\r
23;\r
24;edit 12, 31-Jan-1991 by MF. Delete call to "inbuf" after "xmit1" in\r
25; the TRANSMIT command. "getfil" initializes various counters so that\r
26; when "in1chr" is first called, "inbuf" will be called immediately\r
27; and will read sectors of the file to be transmitted from disk.\r
28; This, along with a fix to "in1chr" in CPSUTL.ASM, fixes a bug\r
29; discovered by Lance Tagliapietra of the University of Wisconsin at\r
30; Platteville wherein the TRANSMIT command was failing to transmit some\r
31; characters in files over one sector in length. See CPSUTL.ASM,\r
32; edit 29.\r
33; edit 11, 10 September, a987, by OBSchou. Modified TRANSMIT command\r
34; to TRANSMIT <file> <string>\r
35;\r
36; edit 10, 27 August, 1987 by OBSchou. Fixed bugs in Transmit, but I may\r
37; be introducing problems for IBM/CMS or half duplex systems. What\r
38; does this combination do??\r
39;\r
40; edit 9 30 March, 1987 by OBSchou to replace the TRANSMIT routine.\r
41; Syntax is now TRANSMIT file after a previous \r
42; INPUT <wait time> <string to wait for>\r
43;\r
44; edit 8 19 June, 1986 by OBSchou. Modified the interupt testing routine\r
45; to see if the command was a 'D' (Drop the line), in which case also\r
46; do a 'C', ie disconnect. This is really a little too much of a\r
47; system dependent thing.\r
48; For now, Ill leave it here, and possibly move it later.\r
49;\r
50; edit 7 30 May 1986 OBSchou. Moved xon/xoff control (ie XON/OFF sent to host)\r
51; out to CPSUTL so that ther printer routine can use it too.\r
52;\r
53; edit 6 30 April, 1986 by OBSchou.\r
54; Fixed transmit bug, so as soon as the protocol character is \r
55; received from the host is received then another line is sent.\r
56; added in a comchr (ds 1) to save the character read from the comm \r
57; line in prtchr, and is restored in a on return.\r
58;\r
59; edit 5 7 March, 1986 by OBSchou Loughborough University. \r
60; Need to save the E register before calling outmdm (in CPSSYS.ASM)\r
61; if doing Half duplex. Push/pop DE should sort this problem\r
62;\r
63; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809\r
64;\r
65;pcc002 28-Dec-84 modules:cp4tt,cp4utl\r
66; Add connect mode <esc>P command to toggle printer on\r
67; and off. Conflicts with "official" recommended commands\r
68; in protocol manual, but I don't think CP/M will ever get\r
69; a PUSH command.\r
70;\r
71;pcc003-pcc005 2-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl\r
72; These edits must all be installed together and change the way\r
73; logging is handled. The log file spec is moved to a separate\r
74; fcb, and not opened until an actual CONNECT command is given.\r
75; This takes care of a NASTY bug that if you used any other file\r
76; command between the LOG and CONNECT, the log file would get\r
77; written over the last file used. This also allows logging to\r
78; be "permanently" enabled until an CLOSE (new command) for all\r
79; CONNECT sessions, like most other kermits do. If a log file\r
80; already exists, it will be appended to. Also add two new\r
81; CONNECT mode commands <esc>Q to suspend logging and <esc>R to\r
82; resume. <esc>R means something else during TRANSMIT, but\r
83; logging is never on then, so there shouldn't be any conflict.\r
84; I also changed the write code, so that it can handle one more\r
85; character after the XOFF is send to stop the host. This allows\r
86; a little "slop" for systems that don't stop immediately (such\r
87; as TOPS10), but it didn't help much.\r
88;\r
89;pcc008 2-Jan-85 vjc modules:cp4def,cp4tt,cp4utl\r
90; Keyboard input during CONNECT mode can get locked out if\r
91; there is enough input from the modem port to keep prtchr\r
92; busy. This can happen for example, if the printer is running\r
93; at the same speed as the modem line, leaving you helpless to\r
94; turn it off or abort the host. Add a fairness count, so that\r
95; at least every prfair characters we look at console input.\r
96;\r
97;pcc012 4-Jan-85 vjc modules:cp4mit,cp4tt,cp4utl\r
98; Use the big buffer for the log file. Move the log file back\r
99; into the common fcb and only save the drive, name, and\r
100; extension between connects. Add new routines to cp4utl to\r
101; create or append to an existing file, and to conditionally\r
102; advance buffers only if in memory. Remove edit pcc003 that\r
103; allows one more character after the xoff, since it didn't\r
104; really work very well and does not fit in well with the way\r
105; the buffer advancing routines are set up. If someone still\r
106; thinks this would be useful, it could be put back in with a\r
107; little more work.\r
108; \r
109; While testing this edit, I also noticed another bug that\r
110; the command parsing routines do not limit or check the\r
111; length of command lines or file specs, trashing what ever\r
112; comes after them. Currently because of where the fcb and\r
113; command buffer are located, this does not usually cause a\r
114; problem, but could if an extremely long line was typed in,\r
115; or in the future multiple fcbs defined elsewhere in memory\r
116; were used. Maybe this should be put on the bug list\r
117; somewhere.\r
118;\r
119; edit 3: July 27, 1984\r
120; Allow assembly with LASM: to CP4TT is linked by CP4PKT, and links\r
121; to CP4CPM; remove exclamation points so as not to confuse LASM.\r
122; Add Toad Hall TACtrap to TRANSMIT command (TAC intercept character\r
123; is only doubled if it's data; when typed by the user, they're not\r
124; automatically doubled)\r
125;\r
126; edit 2: June 7, 1984\r
127; formatting and documentation; add module version number; make sure\r
128; console is selected when leaving intchr.\r
129;\r
130; edit 1: May, 1984\r
131; extracted from CPMBASE.M80 version 3.9; modifications are described\r
132; in the accompanying .UPD file.\r
133\r
134ttver: db 'CPSTT.ASM (12) 31-Jan-1991$'\r
135\r
136; This is the TRANSMIT command. It attempts to send a file, even\r
137; though there is no KERMIT on the other side.\r
138; here from: kermit\r
139;\r
140; [OBS] I have replaced the routine, so that TRANSMIT <filename> <wait string>\r
141; will send a line at a time to the host in a manner similar to MSKERMIT\r
142;\r
143;\r
144xmit: mvi a,cmofi ;Parse an input file spec (non-wild).\r
145 lxi d,fcb ;Give the address for the FCB.\r
146 call comnd\r
147 jmp kermit ;Give up on bad parse.\r
148;\r
149 lxi d,stbuff ; where to put the string\r
150 mvi a,cmtxt ; get text\r
151 call comnd\r
152 jmp kermit ; not quite correct...\r
153 sta strcnt ; string count returned in a\r
154 ana a ; if its zero, make it 1 character (CR)\r
155 jnz xmit0\r
156 mvi a,1\r
157 sta strcnt\r
158 mvi a,cr\r
159 sta stbuff\r
160;\r
161xmit0: call cfmcmd\r
162 call getfil ;Open file.\r
163 cpi 0FFH ;Succeed?\r
164 jnz xmit1\r
165 lxi d,erms15\r
166 call prtstr ;Display error msg.\r
167 jmp kermit\r
168\r
169;\r
170; New TRANSMIT routine - transmit a file, line by line, to a remote host\r
171; waiting each time for one or more characters to be returned\r
172; as a remote host prompt. It could be as simple as a CR or LF\r
173; character. Repeat until the complete file has been sent, then\r
174; close the transmitted file, and drop into the connect state so the\r
175; user can tidy up at the host end.\r
176;get the file to send, open it up, and read first sector from disk\r
177\r
178xmit1: lxi d,inms19 ; say we are send a file to the host\r
179 call prtstr\r
180\r
181 xra a\r
182 sta repcnt ; clear the host prompt chars. counter \r
183 sta starc ; clear star count\r
184;[MF][12]Delete the following call to "inbuf" as the call to "getfil"\r
185;[MF][12]above will have initialized counters and flags so that when\r
186;[MF][12]"in1chr" is called, "inbuf" will be called immediately and will\r
187;[MF][12]immediately read from disk. Counters and flags will then be\r
188;[MF][12]properly set up to read all characters of the file to be\r
189;[MF][12]transmitted.\r
190; call inbuf ; read one sector from disk\r
191; jmp xmtex ; exit if error\r
192\r
193\r
194xmt10: xra a ; clear retransmit flag and count etc\r
195 sta rexbfl ; retransmit flag (1=> retransmit)\r
196 sta rexcnt ; character counter\r
197\r
198xmt1: call xmt1ch ; send a character\r
199 ani 7fh ; strip any parity\r
200 cpi cr ; have we reached the end of the line\r
201 jnz xmt1 ; nope, loop around again\r
202\r
203; Now wait for a string back from the host. Compare with STRING buffer\r
204;\r
205 xra a ; clear the character count\r
206 sta rexcnt\r
207;\r
208 call selcon ; sent a line, send a star to console\r
209 mvi e,'*'\r
210 call outcon\r
211 lda starc ; update star count\r
212 inr a\r
213 sta starc\r
214 cpi 60 ; sent 60 stars?\r
215 jnz xmt1a ; nope...\r
216 xra a\r
217 sta starc\r
218 call prcrlf\r
219xmt1a:\r
220\r
221xmt3: lda eoflag ; have we hit end of file?\r
222 ana a\r
223 jnz xmtex ; yup, so quit.\r
224 xra a\r
225 sta repcnt ; clear the host prompt chars.counter\r
226xmt2: call rd1chl ; read a character from the line\r
227 ani 7fh ; set flags\r
228 jnz xmt4 ; Not zero => we have a character from host\r
229 call ckchr ; see if *WE* have a character from console\r
230 push psw ; restore to modem\r
231 call selmdm\r
232 pop psw\r
233 ani 7fh ; stip parity (should not be there)\r
234 jnz xmt2a ; if a null, try again\r
235 lda strcnt ; if the string length is zero, dont wait.\r
236 ana a\r
237 jz xmt1 ; so loop back again\r
238 jmp xmt4 ; else test for xon/off and incomming string\r
239\r
240xmt2a: cpi cntlc ; do we want to abort?\r
241 jz xmtex ; in which case drop through to connect mode\r
242 cpi cntlz ; if control z exit back to command loop\r
243 jnz xmt2b ; else try for other characters\r
244 lxi d,fcb ; close file before exiting to command loop\r
245 mvi c,closf\r
246 call bdos\r
247 jmp kermit\r
248\r
249xmt2b: cpi cr ; a cr => resend last line\r
250 jnz xmt2 ; nope, then ignore it\r
251 mvi a,1\r
252 sta rexbfl ; else we want to resend the line.\r
253 jmp xmt1\r
254\r
255xmt4: jmp xmt6 ; skit xoff test for now...*****************\r
256\r
257 cpi xoff ; xoff from host?\r
258 jnz xmt6\r
259xmt5: call rd1chl ; else see if XOFF comming\r
260 ani 7fh\r
261 jnz xmt6 ; assume an xoff\r
262 call ckchr ; anything at console?\r
263 push psw\r
264 call selmdm\r
265 pop psw\r
266 ani 7fh\r
267 cpi cntlc ; control-c == abort & play terminal\r
268 jz xmtex\r
269 ana a ; anything else?\r
270 jz xmt5 ;loop again\r
271\r
272xmt6: mov e,a ; save it for a while\r
273 lda repcnt ; see if this character matches with one in buffer\r
274 lxi h,stbuff ; point to string buffer\r
275 add l ; make hl = hl + a\r
276 mov l,a\r
277 mvi a,0\r
278 adc h\r
279 mov h,a ; not using xra, as that clears the Carry flag\r
280 mov a,e ; get the character back again\r
281 cmp m ; is it = to what we expect?\r
282 jnz xmt3 ; no, clear counter and try again\r
283 lda repcnt ; yes, then update the pointer, and ...\r
284 inr a ; ... see if we have received all ...\r
285 sta repcnt ; ... we should have received\r
286 mov e,a ; save length into E again\r
287 lda strcnt ; get the length to compare\r
288 sub e ; if (e) > string length, we have it\r
289 jz xmt10 ; so send next line (clear counters etc)\r
290 jmp xmt2 ; else wait for a little longer\r
291\r
292\r
293;\r
294; Routine below sends a character to the line. It sends up to a CR, and then\r
295; it waits for a reply. This routine is called from xmt1, so if at \r
296; end of file, return. Then XMT1 will drop through\r
297; to connect.\r
298xmt1ch: ; send a character from the xmtbuf to the line\r
299 call selmdm ; just in case it uses it\r
300 lda eoflag ; have we hit end of file\r
301 ana a ; set flags\r
302 jnz xmt1c1 ; no, so dont...\r
303 mvi a,cr ; load up a carriage return\r
304xmt1c1: call get1xc ; get the character to send\r
305 cpi lf ; dont send line feeds\r
306; jz xmt1c1\r
307 cpi cntlz ; if control z, then we are at end of the file\r
308 jz xmtex ; so close the file and drop into telcon\r
309 cpi 20h ; control character?\r
310 jp xmt11 ; no, so ok\r
311 cpi cr ; cr, and tabs ok to send\r
312 jz xmt11\r
313 cpi tab\r
314 jz xmt11\r
315 jmp xmt1c1 ; else try for another character\r
316\r
317xmt11: call setpar ; else set parity etc\r
318 push psw ; we want to keep this for a while\r
319 mov e,a ; we need character in e\r
320 call outmdm\r
321 pop psw ; restore the character we sent\r
322 mov e,a ; now, if a TAC is set on..\r
323 lda tacflg\r
324 ana a \r
325 mov a,e ; (return must have sent character in a)\r
326 jz xmt1c2 ; test for xon/off\r
327 lda tacchr ;... get the tac character\r
328 cmp e ; do we send it again?\r
329 jnz xmt1c2 ; test for xon/off\r
330 push psw ; save character for return. Already set E...\r
331 call outmdm\r
332 pop psw\r
333\r
334xmt1c2: ret\r
335\r
336get1xc: ; get a character from the sector or re-transmit buffer read \r
337; into a. Read a new sector if we run out.\r
338;\r
339; First, see if we do a retransmit\r
340 lda rexbfl\r
341 ana a ; if zero, a genuine line\r
342 jz get1x1\r
343; have to retransmit a line\r
344 lxi h,rexbuf\r
345 lda rexcnt ; add counter to buffer base\r
346 mvi d,0\r
347 mov e,a\r
348 dad d\r
349 inr a ; update pointer\r
350 sta rexcnt\r
351 mov a,m ; get next character to send\r
352 ret ; and exit\r
353\r
354get1x1: call in1chr ; get a character from the file. \r
355 mov c,a ; save it to the retransmit buffer\r
356 lda rexcnt\r
357 mov e,a\r
358 mvi d,0\r
359 lxi h,rexbuf\r
360 dad d ; point to next position\r
361 inr a\r
362 sta rexcnt ; update the character pointer\r
363 mov a,c ; restore character to a\r
364 mov m,c ; get character to c\r
365 ret\r
366\r
367\r
368\r
369; read a character from the line.\r
370rd1chl: \r
371 call selmdm ; select the modem\r
372 call inpmdm ; get input from the modem\r
373 ani 7fh ; strip parity\r
374 ; may UPPERCASE-ify if case sensitivity off\r
375 ret ; return to caller\r
376\r
377; End of transmit routine. Close input file name, and say we are dropping\r
378; throught to telnet. Note that if eof not found, it is assumed that\r
379; this is the ABORT exit.\r
380\r
381xmtex:\r
382 lxi d,fcb ; close the transmitted file\r
383 mvi c,closf\r
384 call bdos\r
385 call selcon ; make sure we are talking to the console\r
386\r
387 lda eoflag ; end of file or abort exit?\r
388 lxi d,inms22 ; assume eof...\r
389 ana a\r
390 jz xmtex1\r
391 lxi d,inms29 ; we were wrong, its an abort.\r
392xmtex1: jmp telnt1 ; and drop through to connect mode\r
393 ; telnet does the printing\r
394\r
395\r
396\r
397;\f\r
398; telnet - the CONNECT command.\r
399; here from: kermit\r
400; telnt1 - entry to connect mode from TRANSMIT command\r
401; here from: xend\r
402\r
403telnet: call cfmcmd\r
404 lxi d,infms7 ;Output start of message\r
405; enter here from TRANSMIT command.\r
406telnt1: call prtstr\r
407 call escpr ;Print the escape char.\r
408 lxi d,infms8 ;Output some more of the message\r
409 call prtstr\r
410 call escpr ;Print the escape char again.\r
411 lxi d,inms8a ;Print the remainder of the message\r
412 call prtstr\r
413 call syscon ;do system-dependent stuff\r
414 lda logflg ;[pcc005] Want a log?\r
415 ora a ;[pcc005]\r
416 cnz logopn ;[pcc005] Open if so\r
417\r
418chrlup: call prtchr ;See if char at port (send to console).\r
419 call conchr ;See if char at console (send to port).\r
420 jmp kermit ;requested to end session - go to command loop.\r
421 jmp chrlup ;Go do it again.\r
422;\f\r
423;\r
424; prtchr - copy characters from comm line to console\r
425; returns: nonskip, console selected.\r
426; called by: xnext, rexmit, telnet\r
427;\r
428\r
429prtchr: call selmdm ; select modem port\r
430 call inpmdm ; try to get a character from it\r
431 push psw ; restore to console\r
432 call selcon ; select console\r
433 pop psw ; restore the (possible character) read\r
434 ora a ; test character\r
435 jnz prtch0 ; if non-zero, process it.\r
436 sta prtcnt ;[pcc008] zero out prt fairness count\r
437 ret ; return.\r
438\r
439prtch0: ani 7FH ; drop parity bit.\r
440 sta comchr ;[6] save it in case we need it again\r
441 lda vtflg ;[9] get the vt52 emulation flag\r
442 cpi vtdefe ;[9] are we doing external emulation?\r
443 lda comchr ;[9] collect character again\r
444 jz extern ;[9] jup, go do it.\r
445\r
446 ana a ; set flags. it may be a null\r
447 jz prtchr ; ignore null (filler)\r
448 cpi del ; ignore delete, too\r
449 jz prtchr\r
450 cpi xon ;Is it an XON?\r
451 jz prtxon ;yes\r
452 cpi xoff ;Is it an XOFF?\r
453 jz prtxof ;yes\r
454 mov e,a ;Set the char aside.\r
455 lda vtflg ;Get the VT52 emulation flag.\r
456 cpi vtdefv ;Is the flag set for VT52 (ie 1)\r
457 ;0 = none\r
458 ;1 = VT52\r
459 ;2 = external\r
460 ;3 = dumb (traps non printing chars)\r
461 ;0ffh not possible by local code (Will change)\r
462 jnz prtch1 ;If not, don't do this stuff.\r
463 lda escflg ;Get the escape flag.\r
464 ora a ;Are we working on an escape sequence?\r
465 jz prtch2 ;If not, continue.\r
466 call vt52 ;If so, work on it some more\r
467 jmp prtchr ;try for more characters.\r
468\r
469prtch2: mov a,e ;normal text.\r
470 cpi esc ;Is the char an escape?\r
471 jnz prtch1 ;If not skip on.\r
472 mvi a,1\r
473 sta escflg ;Set the escape flag: escape seen.\r
474 jmp prtchr ;Get another char...\r
475\r
476prtch1: cpi vtdefe ; are we doing external emulation?\r
477 jnz prtch3 ; assume we continue on\r
478 lxi h,extern+1 ; get address of external emulator\r
479 mov a,h ; se if address = 0 (not implemented)\r
480 ora l\r
481 jz prtch3 ; not external, assume we just carry on\r
482 pchl ; go do external emulation. RET back to caller\r
483\r
484prtch3: cpi vtdefd ; are we trapping all non printing characters?\r
485 jnz prtch4 ; nope, something else\r
486 lda comchr ; Dumb terminal. Lets test the character\r
487 cpi cr ; cr then ok\r
488 jz prtch4 ; its ok\r
489 cpi lf ; lf then ok\r
490 jz prtch4\r
491 cpi tab\r
492 jz prtch4 ; assume tabs are expanded\r
493 cpi space ; if less than 20H ignore it\r
494 rm ; return if a control character\r
495\r
496prtch4: call sysflt ; ok to print this character (in E)?\r
497 ora a\r
498 jz prtchr ; no, skip it.\r
499 lda logflg ;Get the log flag.\r
500 cpi 81H ;[pcc003] Are we logging\r
501 cz logit ;[pcc003] Do so if needed\r
502 call selcon ; select console\r
503 lda prnflg ;Get Print parallel flag\r
504 ora a\r
505 cnz outlpt ; output to printer if flag set\r
506 call outcon ; output to console.\r
507 lxi h,prtcnt ;[pcc008] point to prt fairness count\r
508 inr m ;[pcc008] bump\r
509 mov a,m ;[pcc008] get it in a\r
510 cpi prfair+1 ;[pcc008] time to be fair?\r
511 jm prtchr ;[pcc008] no, go around again.\r
512 mvi m,0 ;[pcc008] reset count\r
513 lda comchr ;[6] restore that character read from comm line\r
514 ret ;[pcc008] and return\r
515\r
516; I don't think we want to print xon/xoff - this should be\r
517; flow control only across the link between us and the host.\r
518; (besides, IBM host xon's don't make sense to most micros)\r
519; remember xon/xoff state in xofflg (zero = xon, non-zero = xoff)\r
520prtxon: xra a ;Yes, reset XOFF flag\r
521prtxof: sta xofflg\r
522 jmp prtchr ; look for another character\r
523;\f;[pcc005] Log file routines\r
524\r
525;[pcc005]\r
526; logopn - open the log file\r
527; Open the log file and append to it if it already exists\r
528; or create one if not.\r
529\r
530logopn: \r
531 mvi a,ctrlz ;[9] ignore control-z in log files\r
532 cmp e ;[9] well, was it?\r
533 rz ;[9] yes, to ignore it.\r
534 lxi h,lognam ;[pcc012] copy name\r
535 lxi d,fcb ;[pcc012] to fcb\r
536 lxi b,12 ;[pcc012] 12 bytes\r
537 call mover ;[pcc012] copy it\r
538 call appfil ;[pcc012] open file for appending\r
539 jmp logerr ;[pcc012] error\r
540 lxi h,logflg ;[pcc005] point to log flag\r
541 mvi a,80H ;[pcc005] file open flag\r
542 ora m ;[pcc005] or in contents of logflg\r
543 mov m,a ;[pcc005] and store back\r
544 lxi d,inms28 ;[pcc005] assume logging is on\r
545 cpi 81H ;[pcc005] check\r
546 jz prtstr ;[pcc005] print msg if true\r
547 lxi d,inms27 ;[pcc005] no, must be suspended\r
548 jmp prtstr ;[pcc005] print and return\r
549\r
550;\r
551; logit - output character in E to log file.\r
552; we assume the host recognizes xon/xoff. (we probably shouldn't)\r
553; modem port is selected.\r
554; preserves de\r
555; called by: prtchr\r
556\r
557logit: lxi h,chrcnt ;[pcc012] point to buffer count\r
558 dcr m ;[pcc012] and decrement\r
559 jp logit1 ;[pcc012] continue if ok\r
560 push d ;[pcc012] save de\r
561 call outadv ;[pcc012] advance buffer if in memory\r
562 call logwrt ;[pcc012] sigh, time to write to disk\r
563 pop d ;[pcc012] restore de\r
564 lda logflg ;[pcc012] get logging flag\r
565 ora a ;[pcc012] Did we quit because of an error\r
566 rz ;[pcc012] return now if so\r
567logit1: lhld bufpnt ;[pcc012] get buffer pointer\r
568 mov m,e ;Store the char.\r
569 inx h\r
570 shld bufpnt\r
571 ret ;[pcc012] and return\r
572\r
573;[pcc012]\r
574; logwrt - write to log file with XON/XOFF since it may take a while.\r
575\r
576logwrt: call sndxoff ;[7] send and xoff to host\r
577 call outbuf ;[pcc012] output the buffer and advance\r
578 call logerr ;[pcc005] quit if error\r
579 call sndxon ;[send an xon to host\r
580 ret ;[pcc012]\r
581\r
582;[pcc005]\r
583; logcls - Close the log file and reset the flag\r
584\r
585logcls: lxi d,infms6 ;[pcc005] Tell user we are closing file.\r
586 call prtstr ;[pcc005]\r
587 call clofil ;[pcc012] and do it\r
588 jmp logerr ;[pcc005] jump if error\r
589 lxi h,logflg ;[pcc005] point to flag\r
590 mov a,m ;[pcc005] get it\r
591 ani 7FH ;[pcc005] clear the open bit\r
592 mov m,a ;[pcc005] and store back\r
593 ret ;[pcc005]\r
594\r
595;[pcc005]\r
596; logerr - here on a variety of logging errors\r
597; just close the file and disable logging\r
598; called from logopn,logptr,logcls\r
599\r
600logerr: lxi d,erms22 ;[pcc005] Error message\r
601 call prtstr ;[pcc005] print it\r
602 mvi c,closf ;[pcc005] Close the file.\r
603 lxi d,fcb ;[pcc012]\r
604 call bdos ;[pcc005] \r
605 xra a ;[pcc005] clear logflg\r
606 sta logflg ;[pcc005] so don't try again\r
607 ret ;[pcc005]\r
608;\f\r
609;\r
610; VT52 emulation.\r
611; called by: prtchr\r
612; A/ contents of escflg (guaranteed non-zero)\r
613; E/ current character\r
614; modem is selected.\r
615;\r
616vt52: cpi 1 ; first character after escape?\r
617 jnz vt52y ; no, must be doing cursor positioning.\r
618;\r
619; E contains the character that followed the escape.\r
620; valid characters are:\r
621; A - cursor up\r
622; B - cursor down\r
623; C - cursor right\r
624; D - cursor left\r
625; F - enter graphics mode (hard to do on a non-vt52)\r
626; G - exit graphics mode\r
627; H - home\r
628; I - reverse linefeed\r
629; J - erase to end of screen\r
630; K - erase to end of line\r
631; Y - cursor positioning leadin\r
632; Z - identify terminal as VT52\r
633; [ - enter hold-screen mode (not supported)\r
634; \ - exit hold-screen mode (not supported)\r
635; > - enter alternate-keypad mode? (not supported)\r
636; = - exit alternate-keypad mode? (not supported)\r
637;\r
638; Invalid sequences are handled as the VT52 does - the escape and\r
639; the following character are swallowed, never to be seen again.\r
640; For <esc>E, the translation table may contain just '$' (no action),\r
641; or may be used as clear-and-home, as in the Heath/Zenith H19.\r
642;\r
643 mov a,e ; get the second character of the sequence.\r
644 cpi 'Y' ; if cursor lead-in handle it.\r
645 jnz vt52a ; if not, go on.\r
646 mvi a,2 ; state = 2: row follows.\r
647 sta escflg ; update the flag.\r
648 ret ; back for another character\r
649\r
650vt52a: cpi 'Z' ; VT52 ID query?\r
651 jz vt52id ; yes. claim to be one.\r
652 cpi 'A' ;Less than an 'A'?\r
653 jm vtig ;Yes - ignore.\r
654 cpi 'K'+1 ;Greater than 'K'?\r
655 jp vtig ;Yes - ignore.\r
656 sui 'A' ;Else make into index.\r
657 rlc ;Multiply by four.\r
658 rlc ;(Shift left twice.)\r
659 lhld pttab ;Load base addr of table.\r
660 mov e,a ;Move a into de pair.\r
661 mvi d,00H ;Zero out high byte.\r
662 dad d ;Double add index+offset.\r
663 xchg ;Exchange de with hl.\r
664 call selcon ; select console\r
665 call prtstr ;and syscall.\r
666vtig: ;Ignore escape sequence.\r
667 xra a ;Reset the ol' escape flag.\r
668 sta escflg\r
669 ret ;Return home.\r
670\r
671; here for <esc>Z. Tell the host we're a VT52. (Sure we are...)\r
672vt52id: mvi a,esc ; response is escape...\r
673 call setpar ; (need correct parity)\r
674 mov e,a\r
675 call outmdm ; (console already selected)\r
676 mvi a,'/' ; ... slash ...\r
677 call setpar ; (with parity)\r
678 mov e,a\r
679 call outmdm\r
680 mvi a,'K' ; ... K.\r
681 call setpar\r
682 mov e,a\r
683 call outmdm\r
684 jmp vtig ; clear escape-sequence flag and return.\r
685\r
686; here when escflg isn't 0 or 1 - processing cursor positioning sequence.\r
687vt52y: cpi 2 ; looking for row? (y-coordinate)\r
688 jnz vt52x ; no, must be column.\r
689 mov a,e ; yes. get coordinate\r
690 sui (' '-1) ; convert from ascii (1 = top line)\r
691 sta vtyval ; store for later\r
692 mvi a,3 ; advance to next state (x coord)\r
693 sta escflg ; store it\r
694 ret ; try for another character\r
695\r
696; here when escflag isn't 0, 1, or 2 - it must be 3. (right?)\r
697; E holds the last character of the cursor positioning sequence.\r
698vt52x: xra a ; end of escape sequence, reset state.\r
699 sta escflg\r
700 mov a,e ; get column (' ' is left margin)\r
701 sui (' '-1) ; make left margin be one\r
702 mov c,a ; stash column in c\r
703 lda vtyval ; get row number\r
704 mov b,a ; in b\r
705 call selcon ; select console\r
706 call csrpos ; call system-dependent cursor positioner\r
707 ret ; all through.\r
708;\f\r
709;\r
710; conchr - copy character from console to comm line, processing\r
711; (kermit's) escape sequences.\r
712; Enter and exit with console selected.\r
713; nonskip return: transparent mode terminated.\r
714; skip return: still in transparent mode.\r
715; called by: rexmit, telnet\r
716\r
717conchr: call inpcon ;Try to get a character from the console\r
718 ani 07FH ;Keep only 7 bits\r
719 jz rskp ;Null means nothing there.\r
720 mov e,a ;Move the char for comparison.\r
721 sta lstchr ;Save it\r
722 lda escchr ;Get the escape char.\r
723 cmp e ;Is it an escape char?\r
724 jz intchr ;If so go process it.\r
725 call selmdm ; select the modem\r
726 mov a,e ;Get the char.\r
727 call setpar ;Set parity (if any).\r
728 mov e,a ;Restore it.\r
729 push d ; need to save e in case we are half dplx [5]\r
730 call outmdm ;Output the char to the port.\r
731 pop d ; Just in case we are half dplx [5]\r
732 call selcon ; reselect console\r
733 lda ecoflg ;Get the echo flag.\r
734 ora a ;Is it turned on?\r
735 jz rskp ;If not we're done here.\r
736 mov a,e ;Get the char.\r
737 ani 7FH ;Turn off the parity bit.\r
738 mov e,a\r
739 call outcon ; echo the character.\r
740 jmp rskp ; use skip return\r
741;\f\r
742; transparent escape character has been typed. dispatch on second\r
743; character. (console is still selected)\r
744; here from: conchr\r
745\r
746intchr: call inpcon ; get another character from the console\r
747 ora a ; zero means no character available yet.\r
748 jz intchr ; If so, loop until we get a char.\r
749 mov b,a ;Save the actual char.\r
750 cpi ctrlc ;is it Control-C?\r
751 jz contc ;yes\r
752 ani 137O ;Convert to upper case.\r
753 cpi 'C' ;Is it close?\r
754 jnz intch0 ;If not proceed.\r
755contc: lxi d,infms9 ;Say we are back.\r
756 call prtstr\r
757 call syscls ; call system-dependent close routine\r
758 lda logflg ;Get the log flag.\r
759 ora a ;[pcc005] Check if open\r
760 cm logcls ;[pcc005] Close if needed\r
761 ret\r
762\r
763;Here if not a 'C' or '^C'\r
764\r
765intch0: cpi 'S' ;Is it status?\r
766 jnz inch01 ;If not, proceed.\r
767 call stat01 ;Print out the status stuff.\r
768 call prcrlf ;[pcc011] add a crlf\r
769 jmp rskp ;return from conchr\r
770\r
771inch01:\r
772inch03: mov a,b ;Get the char.\r
773 cpi '?' ;Is it a help request?\r
774 jnz intch1 ;If not, go to the next check.\r
775inch3a: lda logflg ;[pcc003] Logging flag\r
776 ora a ;[pcc003] see if active\r
777 jp inch04 ;[pcc005] jump if no file open\r
778 lxi d,loghlp ;[pcc003] yes, tell about R AND Q\r
779 call prtstr ;[pcc003]\r
780inch04: lxi d,inthlp ;If so, get the address of the help message.\r
781 call prtstr\r
782 call sysinh ; print system-dependent help message\r
783 lxi d,inhlp1 ; Tell about doubling the escape character\r
784 call prtstr\r
785 call escpr ;Print escape character\r
786 lxi d,inhlp2 ;Print the rest\r
787 call prtstr\r
788 jmp intchr ;Get another char.\r
789\r
790intch1: mov a,b ;Get the character.\r
791 cpi '0' ;Is it '0', to send a null?\r
792 jnz intch3 ;No.\r
793 xra a ;Yes, send an ASCII zero.\r
794 call setpar ; with the correct parity\r
795 mov e,a\r
796 call selmdm ; (to the modem...)\r
797 call outmdm\r
798 call selcon ; return with console selected\r
799 jmp rskp\r
800\r
801intch3: lda escchr ;Get the escape char.\r
802 cmp b ;Is it the escape char?\r
803 jnz intch4 ;[pcc002] jump if not\r
804 mov a,b ;Get the char.\r
805 call setpar\r
806 mov e,a ;Restore it.\r
807 call selmdm\r
808 call outmdm ;Output it.\r
809 call selcon ;We promised console would be selected...\r
810 jmp rskp ;Return, we are done here.\r
811intch4: mov a,b ;[pcc002] get it again\r
812 ani 137o ;[pcc002] in upper case\r
813 cpi 'P' ;[pcc002] toggle printer?\r
814 jnz intch5 ;[pcc003] nope\r
815 lda prnflg ;[pcc002] get printer flag\r
816 xri 01h ;[pcc002] complement it\r
817 sta prnflg ;[pcc002] and put back\r
818 jmp rskp ;[pcc002]\r
819intch5: lda logflg ;[pcc003] get log flag\r
820 ora a ;[pcc003] See if open\r
821 jp intch7 ;[pcc003] no, skip R and Q\r
822 mov a,b ;[pcc003] get back chr\r
823 ani 137o ;[pcc003] make upper case\r
824 cpi 'R' ;[pcc003] Is it R\r
825 jnz intch6 ;[pcc003] Jump if not\r
826 mvi a,81H ;[pcc003] set flag for logging\r
827 sta logflg ;[pcc003] put it back\r
828 lxi d,inms28 ;[pcc003] message\r
829 call prtstr ;[pcc003]\r
830 jmp rskp ;[pcc003] done\r
831intch6: cpi 'Q' ;[pcc003] Quit logging?\r
832 jnz intch7 ;[pcc003] no\r
833 mvi a,82H ;[pcc003] flag for open, but suspended\r
834 sta logflg ;[pcc003] store away\r
835 lxi d,inms27 ;[pcc003] keep them informed\r
836 call prtstr ;[pcc003]\r
837 jmp rskp ;[pcc003]\r
838intch7: ;[pcc003]\r
839\r
840intchz: mov a,b ; not recognized. get saved copy back.\r
841 push psw ;[8] save as we will want to test for 'D'\r
842 call sysint ; interpret system-dependent sequences\r
843 jmp intchy ; done. [10] Now see if D. If so, do a C.\r
844 pop psw ;[10] tidy stack\r
845 mvi e,'G'-100O ;Otherwise send a beep.\r
846 call outcon ; to the console.\r
847 jmp rskp\r
848\r
849intchy: pop psw ;[10] adjust stack\r
850 ani 5fh ;[10] strip parity, make it upper case\r
851 cpi 'D' ;[10] was it a D?\r
852 jz contc ;[10] yup, so to the equivalent of an escape-C\r
853 jmp rskp\r
854;\f\r
855; Little code to allow some expansion of code without changing\r
856; every futher address, only up to the end of this file.\r
857; TO BE REMOVED FOR RELEASE!\r
858\r
859; org ($+100h) AND 0FF00H\r
860IF lasm\r
861 LINK CPSCPM\r
862ENDIF;lasm\r