aboutsummaryrefslogtreecommitdiff
path: root/src/cpstt.asm
blob: 41a30af18fa4b45692f0adc0657db00dee4d907a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
; CPSTT.ASM
;       KERMIT - (Celtic for "FREE")
;
;       This is the CP/M-80 implementation of the Columbia University
;       KERMIT file transfer protocol.
;
;       Version 4.0
;
;       Copyright June 1981,1982,1983,1984,1985
;       Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others. 
;
;       This file contains the code for the TRANSMIT and CONNECT commands,
;       which communicate with a host which is not running KERMIT.
;
; revision history:
;
;edit 12, 31-Jan-1991 by MF. Delete call to "inbuf" after "xmit1" in
;	the TRANSMIT command. "getfil" initializes various counters so that
;	when "in1chr" is first called, "inbuf" will be called immediately
;	and will read sectors of the file to be transmitted from disk.
;	This, along with a fix to "in1chr" in CPSUTL.ASM, fixes a bug
;	discovered by Lance Tagliapietra of the University of Wisconsin at
;	Platteville wherein the TRANSMIT command was failing to transmit some
;	characters in files over one sector in length. See CPSUTL.ASM,
;	edit 29.
; edit 11, 10 September, a987, by OBSchou.  Modified TRANSMIT command
;	to TRANSMIT <file> <string>
;
; edit 10, 27 August, 1987 by OBSchou.  Fixed bugs in Transmit, but I may
;	be introducing problems for IBM/CMS or half duplex systems.  What
;	does this combination do??
;
; edit 9 30 March, 1987 by OBSchou to replace the TRANSMIT routine.
;	Syntax is now TRANSMIT file after a previous 
;	INPUT <wait time> <string to wait for>
;
; edit 8 19 June, 1986 by OBSchou.  Modified the interupt testing routine
;       to see if the command was a 'D' (Drop the line), in which case also
;       do a 'C', ie disconnect.  This is really a little too much of a
;       system dependent thing.
;       For now, Ill leave it here, and possibly move it later.
;
; edit 7 30 May 1986 OBSchou.  Moved xon/xoff control (ie XON/OFF sent to host)
;       out to CPSUTL so that ther printer routine can use it too.
;
; edit 6 30 April, 1986 by OBSchou.
;       Fixed transmit bug, so as soon as the protocol character is 
;       received from the host is received then another line is sent.
;       added in a comchr (ds 1) to save the character read from the comm 
;       line in prtchr, and is restored in a on return.
;
; edit 5 7 March, 1986 by OBSchou Loughborough University.  
;       Need to save the E register before calling outmdm (in CPSSYS.ASM)
;       if doing Half duplex.  Push/pop DE should sort this problem
;
; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
;
;pcc002 28-Dec-84       modules:cp4tt,cp4utl
;       Add connect mode <esc>P command to toggle printer on
;       and off.  Conflicts with "official" recommended commands
;       in protocol manual, but I don't think CP/M will ever get
;       a PUSH command.
;
;pcc003-pcc005  2-Jan-85        vjc     modules:cp4mit,cp4tt,cp4utl
;       These edits must all be installed together and change the way
;       logging is handled.  The log file spec is moved to a separate
;       fcb, and not opened until an actual CONNECT command is given.
;       This takes care of a NASTY bug that if you used any other file
;       command between the LOG and CONNECT, the log file would get
;       written over the last file used.  This also allows logging to
;       be "permanently" enabled until an CLOSE (new command) for all
;       CONNECT sessions, like most other kermits do.  If a log file
;       already exists, it will be appended to.  Also add two new
;       CONNECT mode commands <esc>Q to suspend logging and <esc>R to
;       resume.  <esc>R means something else during TRANSMIT, but
;       logging is never on then, so there shouldn't be any conflict.
;       I also changed the write code, so that it can handle one more
;       character after the XOFF is send to stop the host.  This allows
;       a little "slop" for systems that don't stop immediately (such
;       as TOPS10), but it didn't help much.
;
;pcc008 2-Jan-85        vjc     modules:cp4def,cp4tt,cp4utl
;       Keyboard input during CONNECT mode can get locked out if
;       there is enough input from the modem port to keep prtchr
;       busy.  This can happen for example, if the printer is running
;       at the same speed as the modem line, leaving you helpless to
;       turn it off or abort the host.  Add a fairness count, so that
;       at least every prfair characters we look at console input.
;
;pcc012 4-Jan-85        vjc     modules:cp4mit,cp4tt,cp4utl
;       Use the big buffer for the log file.  Move the log file back
;       into the common fcb and only save the drive, name, and
;       extension between connects.  Add new routines to cp4utl to
;       create or append to an existing file, and to conditionally
;       advance buffers only if in memory.  Remove edit pcc003 that
;       allows one more character after the xoff, since it didn't
;       really work very well and does not fit in well with the way
;       the buffer advancing routines are set up.  If someone still
;       thinks this would be useful, it could be put back in with a
;       little more work.
;       
;       While testing this edit, I also noticed another bug that
;       the command parsing routines do not limit or check the
;       length of command lines or file specs, trashing what ever
;       comes after them.  Currently because of where the fcb and
;       command buffer are located, this does not usually cause a
;       problem, but could if an extremely long line was typed in,
;       or in the future multiple fcbs defined elsewhere in memory
;       were used.  Maybe this should be put on the bug list
;       somewhere.
;
; edit 3: July 27, 1984
;       Allow assembly with LASM: to CP4TT is linked by CP4PKT, and links
;       to CP4CPM; remove exclamation points so as not to confuse LASM.
;       Add Toad Hall TACtrap to TRANSMIT command (TAC intercept character
;       is only doubled if it's data; when typed by the user, they're not
;       automatically doubled)
;
; edit 2: June 7, 1984
;       formatting and documentation; add module version number; make sure
;       console is selected when leaving intchr.
;
; edit 1: May, 1984
;       extracted from CPMBASE.M80 version 3.9; modifications are described
;       in the accompanying .UPD file.

ttver:	db	'CPSTT.ASM  (12) 31-Jan-1991$'

;       This is the TRANSMIT command.  It attempts to send a file, even
;       though there is no KERMIT on the other side.
;       here from: kermit
;
; [OBS] I have replaced the routine, so that TRANSMIT <filename> <wait string>
; will send a line at a time to the host in a manner similar to MSKERMIT
;
;
xmit:	mvi	a,cmofi		;Parse an input file spec (non-wild).
	lxi	d,fcb		;Give the address for the FCB.
	call	comnd
	jmp	kermit		;Give up on bad parse.
;
	lxi	d,stbuff	; where to put the string
	mvi	a,cmtxt		; get text
	call	comnd
	jmp	kermit		; not quite correct...
	sta	strcnt		; string count returned in a
	ana	a		; if its zero, make it 1 character (CR)
	jnz	xmit0
	mvi	a,1
	sta	strcnt
	mvi	a,cr
	sta	stbuff
;
xmit0:	call	cfmcmd
	call	getfil		;Open file.
	cpi	0FFH		;Succeed?
	jnz	xmit1
	lxi	d,erms15
	call	prtstr		;Display error msg.
	jmp	kermit

;
; New TRANSMIT routine - transmit a file, line by line, to a remote host
;	waiting each time for one or more characters to be returned
;	as a remote host prompt.  It could be as simple as a CR or LF
;	character.  Repeat until the complete file has been sent, then
;	close the transmitted file, and drop into the connect state so the
;	user can tidy up at the host end.
;get the file to send, open it up, and read first sector from disk

xmit1:	lxi	d,inms19	; say we are send a file to the host
	call	prtstr

	xra	a
	sta	repcnt		; clear the host prompt chars. counter 
	sta	starc		; clear star count
;[MF][12]Delete the following call to "inbuf" as the call to "getfil"
;[MF][12]above will have initialized counters and flags so that when
;[MF][12]"in1chr" is called, "inbuf" will be called immediately and will
;[MF][12]immediately read from disk. Counters and flags will then be
;[MF][12]properly set up to read all characters of the file to be
;[MF][12]transmitted.
;	call	inbuf		; read one sector from disk
;	jmp	xmtex		; exit if error


xmt10:	xra	a		; clear retransmit flag and count etc
	sta	rexbfl		; retransmit flag (1=> retransmit)
	sta	rexcnt		; character counter

xmt1:	call	xmt1ch		; send a character
	ani	7fh		; strip any parity
	cpi	cr		; have we reached the end of the line
	jnz	xmt1		; nope, loop around again

; Now wait for a string back from the host.  Compare with STRING buffer
;
	xra	a		; clear the character count
	sta	rexcnt
;
	call	selcon		; sent a line, send a star to console
	mvi	e,'*'
	call	outcon
	lda	starc		; update star count
	inr	a
	sta	starc
	cpi	60		; sent 60 stars?
	jnz	xmt1a		; nope...
	xra	a
	sta	starc
	call	prcrlf
xmt1a:

xmt3:	lda	eoflag		; have we hit end of file?
	ana	a
	jnz	xmtex		; yup, so quit.
	xra	a
	sta	repcnt		; clear the host prompt chars.counter
xmt2:	call	rd1chl		; read a character from the line
	ani	7fh		; set flags
	jnz	xmt4		; Not zero => we have a character from host
	call	ckchr		; see if *WE* have a character from console
	push	psw		; restore to modem
	call	selmdm
	pop	psw
	ani	7fh		; stip parity (should not be there)
	jnz	xmt2a		; if a null, try again
	lda	strcnt		; if the string length is zero, dont wait.
	ana	a
	jz	xmt1		; so loop back again
	jmp	xmt4		; else test for xon/off and incomming string

xmt2a:	cpi	cntlc		; do we want to abort?
	jz	xmtex		; in which case drop through to connect mode
	cpi	cntlz		; if control z exit back to command loop
	jnz	xmt2b		; else try for other characters
	lxi	d,fcb		; close file before exiting to command loop
	mvi	c,closf
	call	bdos
	jmp	kermit

xmt2b:	cpi	cr		; a cr => resend last line
	jnz	xmt2		; nope, then ignore it
	mvi	a,1
	sta	rexbfl		; else we want to resend the line.
	jmp	xmt1

xmt4:	jmp	xmt6		; skit xoff test for now...*****************

	cpi	xoff		; xoff from host?
	jnz	xmt6
xmt5:	call	rd1chl		; else see if XOFF comming
	ani	7fh
	jnz	xmt6		; assume an xoff
	call	ckchr		; anything at console?
	push	psw
	call	selmdm
	pop	psw
	ani	7fh
	cpi	cntlc		; control-c == abort & play terminal
	jz	xmtex
	ana	a		; anything else?
	jz	xmt5		;loop again

xmt6:	mov	e,a		; save it for a while
	lda	repcnt		; see if this character matches with one in buffer
	lxi	h,stbuff	; point to string buffer
	add	l		; make hl = hl + a
	mov	l,a
	mvi	a,0
	adc	h
	mov	h,a		; not using xra, as that clears the Carry flag
	mov	a,e		; get the character back again
	cmp	m		; is it = to what we expect?
	jnz	xmt3		; no, clear counter and try again
	lda	repcnt		; yes, then update the pointer, and ...
	inr	a		; ... see if we have received all ...
	sta	repcnt		; ... we should have received
	mov	e,a		; save length into E again
	lda	strcnt		; get the length to compare
	sub	e		; if (e) > string length, we have it
	jz	xmt10		; so send next line (clear counters etc)
	jmp	xmt2		; else wait for a little longer


;
; Routine below sends a character to the line.  It sends up to a CR, and then
;	it waits for a reply.  This routine is called from xmt1, so if at 
;	end of file, return.  Then XMT1 will drop through
;	to connect.
xmt1ch:	; send a character from the xmtbuf to the line
	call	selmdm		; just in case it uses it
	lda	eoflag		; have we hit end of file
	ana	a		; set flags
	jnz	xmt1c1		; no, so dont...
	mvi	a,cr		; load up a carriage return
xmt1c1:	call	get1xc		; get the character to send
	cpi	lf		; dont send line feeds
;	jz	xmt1c1
	cpi	cntlz		; if control z, then we are at end of the file
	jz	xmtex		; so close the file and drop into telcon
	cpi	20h		; control character?
	jp	xmt11		; no, so ok
	cpi	cr		; cr, and tabs ok to send
	jz	xmt11
	cpi	tab
	jz	xmt11
	jmp	xmt1c1		; else try for another character

xmt11:	call	setpar		; else set parity etc
	push	psw		; we want to keep this for a while
	mov	e,a		; we need character in e
	call	outmdm
	pop	psw		; restore the character we sent
	mov	e,a		; now, if a TAC is set on..
	lda	tacflg
	ana	a		
	mov	a,e		; (return must have sent character in a)
	jz	xmt1c2		; test for xon/off
	lda	tacchr		;... get the tac character
	cmp	e		; do we send it again?
	jnz	xmt1c2		; test for xon/off
	push	psw		; save character for return. Already set E...
	call	outmdm
	pop	psw

xmt1c2:	ret

get1xc:	; get a character from the sector or re-transmit buffer read 
;	into a.  Read a new sector if we run out.
;
; First, see if we do a retransmit
	lda	rexbfl
	ana	a		; if zero, a genuine line
	jz	get1x1
; have to retransmit a line
	lxi	h,rexbuf
	lda	rexcnt		; add counter to buffer base
	mvi	d,0
	mov	e,a
	dad	d
	inr	a		; update pointer
	sta	rexcnt
	mov	a,m		; get next character to send
	ret			; and exit

get1x1:	call	in1chr		; get a character from the file. 
	mov	c,a		; save it to the retransmit buffer
	lda	rexcnt
	mov	e,a
	mvi	d,0
	lxi	h,rexbuf
	dad	d		; point to next position
	inr	a
	sta	rexcnt		; update the character pointer
	mov	a,c		; restore character to a
	mov	m,c		; get character to c
	ret



; read a character from the line.
rd1chl:	
	call	selmdm		; select the modem
	call	inpmdm		; get input from the modem
	ani	7fh		; strip parity
				; may UPPERCASE-ify if case sensitivity off
	ret			; return to caller

;  End of transmit routine.  Close input file name, and say we are dropping
;  throught to telnet.  Note that if eof not found, it is assumed that
;  this is the ABORT exit.

xmtex:
	lxi	d,fcb		; close the transmitted file
	mvi	c,closf
	call	bdos
	call	selcon		; make sure we are talking to the console

	lda	eoflag		; end of file or abort exit?
	lxi	d,inms22	; assume eof...
	ana	a
	jz	xmtex1
	lxi	d,inms29	; we were wrong, its an abort.
xmtex1:	jmp	telnt1		; and drop through to connect mode
				; telnet does the printing



;
;   telnet - the CONNECT command.
;       here from: kermit
;   telnt1 - entry to connect mode from TRANSMIT command
;       here from: xend

telnet:	call	cfmcmd
	lxi	d,infms7	;Output start of message
; enter here from TRANSMIT command.
telnt1:	call	prtstr
	call	escpr		;Print the escape char.
	lxi	d,infms8	;Output some more of the message
	call	prtstr
	call	escpr		;Print the escape char again.
	lxi	d,inms8a	;Print the remainder of the message
	call	prtstr
	call	syscon		;do system-dependent stuff
	lda	logflg		;[pcc005] Want a log?
	ora	a		;[pcc005]
	cnz	logopn		;[pcc005] Open if so

chrlup:	call	prtchr		;See if char at port (send to console).
	call	conchr		;See if char at console (send to port).
	jmp	kermit		;requested to end session - go to command loop.
	jmp	chrlup		;Go do it again.
;
;
;       prtchr - copy characters from comm line to console
;       returns: nonskip, console selected.
;       called by: xnext, rexmit, telnet
;

prtchr:	call	selmdm		; select modem port
	call	inpmdm		; try to get a character from it
	push	psw		; restore to console
	call	selcon		; select console
	pop	psw		; restore the (possible character) read
	ora	a		; test character
	jnz	prtch0		; if non-zero, process it.
	sta	prtcnt		;[pcc008] zero out prt fairness count
	ret			; return.

prtch0:	ani	7FH		; drop parity bit.
	sta	comchr		;[6] save it in case we need it again
	lda	vtflg		;[9] get the vt52 emulation flag
	cpi	vtdefe		;[9] are we doing external emulation?
	lda	comchr		;[9] collect character again
	jz	extern		;[9] jup, go do it.

	ana	a		; set flags.  it may be a null
	jz	prtchr		; ignore null (filler)
	cpi	del		; ignore delete, too
	jz	prtchr
	cpi	xon		;Is it an XON?
	jz	prtxon		;yes
	cpi	xoff		;Is it an XOFF?
	jz	prtxof		;yes
	mov	e,a		;Set the char aside.
	lda	vtflg		;Get the VT52 emulation flag.
	cpi	vtdefv		;Is the flag set for VT52 (ie 1)
				;0 = none
				;1 = VT52
				;2 = external
				;3 = dumb (traps non printing chars)
				;0ffh not possible by local code (Will change)
	jnz	prtch1		;If not, don't do this stuff.
	lda	escflg		;Get the escape flag.
	ora	a		;Are we working on an escape sequence?
	jz	prtch2		;If not, continue.
	call	vt52		;If so, work on it some more
	jmp	prtchr		;try for more characters.

prtch2:	mov	a,e		;normal text.
	cpi	esc		;Is the char an escape?
	jnz	prtch1		;If not skip on.
	mvi	a,1
	sta	escflg		;Set the escape flag: escape seen.
	jmp	prtchr		;Get another char...

prtch1:	cpi	vtdefe		; are we doing external emulation?
	jnz	prtch3		; assume we continue on
	lxi	h,extern+1	; get address of external emulator
	mov	a,h		; se if address = 0 (not implemented)
	ora	l
	jz	prtch3		; not external, assume we just carry on
	pchl			; go do external emulation.  RET back to caller

prtch3:	cpi	vtdefd		; are we trapping all non printing characters?
	jnz	prtch4		; nope, something else
	lda	comchr		; Dumb terminal.  Lets test the character
	cpi	cr		; cr then ok
	jz 	prtch4		; its ok
	cpi	lf		; lf then ok
	jz	prtch4
	cpi	tab
	jz	prtch4		; assume tabs are expanded
	cpi	space		; if less than 20H ignore it
	rm			; return if a control character

prtch4:	call	sysflt		; ok to print this character (in E)?
	ora	a
	jz	prtchr		; no, skip it.
	lda	logflg		;Get the log flag.
	cpi	81H		;[pcc003] Are we logging
	cz	logit		;[pcc003] Do so if needed
	call	selcon		; select console
	lda	prnflg		;Get Print parallel flag
	ora	a
	cnz	outlpt		; output to printer if flag set
	call	outcon		; output to console.
	lxi	h,prtcnt	;[pcc008] point to prt fairness count
	inr	m		;[pcc008] bump
	mov	a,m		;[pcc008] get it in a
	cpi	prfair+1	;[pcc008] time to be fair?
	jm	prtchr		;[pcc008] no, go around again.
	mvi	m,0		;[pcc008] reset count
	lda	comchr		;[6] restore that character read from comm line
	ret			;[pcc008] and return

; I don't think we want to print xon/xoff - this should be
; flow control only across the link between us and the host.
; (besides, IBM host xon's don't make sense to most micros)
; remember xon/xoff state in xofflg (zero = xon, non-zero = xoff)
prtxon:	xra	a		;Yes, reset XOFF flag
prtxof:	sta	xofflg
	jmp	prtchr		; look for another character
;;[pcc005] Log file routines

;[pcc005]
;    logopn - open the log file
;       Open the log file and append to it if it already exists
;       or create one if not.

logopn:	
	mvi	a,ctrlz		;[9] ignore control-z in log files
	cmp	e		;[9] well, was it?
	rz			;[9] yes, to ignore it.
	lxi	h,lognam	;[pcc012] copy name
	lxi	d,fcb		;[pcc012] to fcb
	lxi	b,12		;[pcc012] 12 bytes
	call	mover		;[pcc012] copy it
	call	appfil		;[pcc012] open file for appending
	jmp	logerr		;[pcc012] error
	lxi	h,logflg	;[pcc005] point to log flag
	mvi	a,80H		;[pcc005] file open flag
	ora	m		;[pcc005] or in contents of logflg
	mov	m,a		;[pcc005] and store back
	lxi	d,inms28	;[pcc005] assume logging is on
	cpi	81H		;[pcc005] check
	jz	prtstr		;[pcc005] print msg if true
	lxi	d,inms27	;[pcc005] no, must be suspended
	jmp	prtstr		;[pcc005] print and return

;
;       logit - output character in E to log file.
;       we assume the host recognizes xon/xoff. (we probably shouldn't)
;       modem port is selected.
;       preserves de
;       called by: prtchr

logit:	lxi	h,chrcnt	;[pcc012] point to buffer count
	dcr	m		;[pcc012] and decrement
	jp	logit1		;[pcc012] continue if ok
	push	d		;[pcc012] save de
	call	outadv		;[pcc012] advance buffer if in memory
	call	logwrt		;[pcc012] sigh, time to write to disk
	pop	d		;[pcc012] restore de
	lda	logflg		;[pcc012] get logging flag
	ora	a		;[pcc012] Did we quit because of an error
	rz			;[pcc012] return now if so
logit1:	lhld	bufpnt		;[pcc012] get buffer pointer
	mov	m,e		;Store the char.
	inx	h
	shld	bufpnt
	ret			;[pcc012] and return

;[pcc012]
;  logwrt - write to log file with XON/XOFF since it may take a while.

logwrt:	call	sndxoff		;[7] send and xoff to host
	call	outbuf		;[pcc012] output the buffer and advance
	call	logerr		;[pcc005] quit if error
	call	sndxon		;[send an xon to host
	ret			;[pcc012]

;[pcc005]
;       logcls - Close the log file and reset the flag

logcls:	lxi	d,infms6	;[pcc005] Tell user we are closing file.
	call	prtstr		;[pcc005]
	call	clofil		;[pcc012] and do it
	jmp	logerr		;[pcc005] jump if error
	lxi	h,logflg	;[pcc005] point to flag
	mov	a,m		;[pcc005] get it
	ani	7FH		;[pcc005] clear the open bit
	mov	m,a		;[pcc005] and store back
	ret			;[pcc005]

;[pcc005]
;    logerr - here on a variety of logging errors
;       just close the file and disable logging
;       called from logopn,logptr,logcls

logerr:	lxi	d,erms22	;[pcc005] Error message
	call	prtstr		;[pcc005] print it
	mvi	c,closf		;[pcc005] Close the file.
	lxi	d,fcb		;[pcc012]
	call	bdos		;[pcc005] 
	xra	a		;[pcc005] clear logflg
	sta	logflg		;[pcc005] so don't try again
	ret			;[pcc005]
;
;
;       VT52 emulation.
;       called by: prtchr
;       A/ contents of escflg (guaranteed non-zero)
;       E/ current character
;       modem is selected.
;
vt52:	cpi	1		; first character after escape?
	jnz	vt52y		; no, must be doing cursor positioning.
;
;       E contains the character that followed the escape.
;       valid characters are:
;       A - cursor up
;       B - cursor down
;       C - cursor right
;       D - cursor left
;       F - enter graphics mode (hard to do on a non-vt52)
;       G - exit graphics mode
;       H - home
;       I - reverse linefeed
;       J - erase to end of screen
;       K - erase to end of line
;       Y - cursor positioning leadin
;       Z - identify terminal as VT52
;       [ - enter hold-screen mode (not supported)
;       \ - exit hold-screen mode (not supported)
;       > - enter alternate-keypad mode? (not supported)
;       = - exit alternate-keypad mode? (not supported)
;
;       Invalid sequences are handled as the VT52 does - the escape and
;       the following character are swallowed, never to be seen again.
;       For <esc>E, the translation table may contain just '$' (no action),
;       or may be used as clear-and-home, as in the Heath/Zenith H19.
;
	mov	a,e		; get the second character of the sequence.
	cpi	'Y'             ; if cursor lead-in handle it.
	jnz	vt52a		; if not, go on.
	mvi	a,2		; state = 2: row follows.
	sta	escflg		; update the flag.
	ret			; back for another character

vt52a:	cpi	'Z'             ; VT52 ID query?
	jz	vt52id		; yes. claim to be one.
	cpi	'A'             ;Less than an 'A'?
	jm	vtig		;Yes - ignore.
	cpi	'K'+1           ;Greater than 'K'?
	jp	vtig		;Yes - ignore.
	sui	'A'             ;Else make into index.
	rlc			;Multiply by four.
	rlc			;(Shift left twice.)
	lhld	pttab		;Load base addr of table.
	mov	e,a		;Move a into de pair.
	mvi	d,00H		;Zero out high byte.
	dad	d		;Double add index+offset.
	xchg			;Exchange de with hl.
	call	selcon		; select console
	call	prtstr		;and syscall.
vtig:				;Ignore escape sequence.
	xra	a		;Reset the ol' escape flag.
	sta	escflg
	ret			;Return home.

; here for <esc>Z.  Tell the host we're a VT52. (Sure we are...)
vt52id:	mvi	a,esc		; response is escape...
	call	setpar		; (need correct parity)
	mov	e,a
	call	outmdm		; (console already selected)
	mvi	a,'/'           ; ... slash ...
	call	setpar		; (with parity)
	mov	e,a
	call	outmdm
	mvi	a,'K'           ; ... K.
	call	setpar
	mov	e,a
	call	outmdm
	jmp	vtig		; clear escape-sequence flag and return.

; here when escflg isn't 0 or 1 - processing cursor positioning sequence.
vt52y:	cpi	2		; looking for row? (y-coordinate)
	jnz	vt52x		; no, must be column.
	mov	a,e		; yes. get coordinate
	sui	(' '-1)         ; convert from ascii (1 = top line)
	sta	vtyval		; store for later
	mvi	a,3		; advance to next state (x coord)
	sta	escflg		; store it
	ret			; try for another character

; here when escflag isn't 0, 1, or 2 - it must be 3. (right?)
; E holds the last character of the cursor positioning sequence.
vt52x:	xra	a		; end of escape sequence, reset state.
	sta	escflg
	mov	a,e		; get column (' ' is left margin)
	sui	(' '-1)         ; make left margin be one
	mov	c,a		; stash column in c
	lda	vtyval		; get row number
	mov	b,a		;  in b
	call	selcon		; select console
	call	csrpos		; call system-dependent cursor positioner
	ret			; all through.
;
;
;       conchr - copy character from console to comm line, processing
;       (kermit's) escape sequences.
;       Enter and exit with console selected.
;       nonskip return: transparent mode terminated.
;       skip return:    still in transparent mode.
;       called by: rexmit, telnet

conchr:	call	inpcon		;Try to get a character from the console
	ani	07FH		;Keep only 7 bits
	jz	rskp		;Null means nothing there.
	mov	e,a		;Move the char for comparison.
	sta	lstchr		;Save it
	lda	escchr		;Get the escape char.
	cmp	e		;Is it an escape char?
	jz	intchr		;If so go process it.
	call	selmdm		; select the modem
	mov	a,e		;Get the char.
	call	setpar		;Set parity (if any).
	mov	e,a		;Restore it.
	push	d		; need to save e in case we are half dplx [5]
	call	outmdm		;Output the char to the port.
	pop	d		; Just in case we are half dplx [5]
	call	selcon		; reselect console
	lda	ecoflg		;Get the echo flag.
	ora	a		;Is it turned on?
	jz	rskp		;If not we're done here.
	mov	a,e		;Get the char.
	ani	7FH		;Turn off the parity bit.
	mov	e,a
	call	outcon		; echo the character.
	jmp	rskp		; use skip return
;
;       transparent escape character has been typed. dispatch on second
;       character. (console is still selected)
;       here from: conchr

intchr:	call	inpcon		; get another character from the console
	ora	a		; zero means no character available yet.
	jz	intchr		; If so, loop until we get a char.
	mov	b,a		;Save the actual char.
	cpi	ctrlc		;is it Control-C?
	jz	contc		;yes
	ani	137O		;Convert to upper case.
	cpi	'C'             ;Is it close?
	jnz	intch0		;If not proceed.
contc:	lxi	d,infms9	;Say we are back.
	call	prtstr
	call	syscls		; call system-dependent close routine
	lda	logflg		;Get the log flag.
	ora	a		;[pcc005] Check if open
	cm	logcls		;[pcc005] Close if needed
	ret

;Here if not a 'C' or '^C'

intch0:	cpi	'S'             ;Is it status?
	jnz	inch01		;If not, proceed.
	call	stat01		;Print out the status stuff.
	call	prcrlf		;[pcc011] add a crlf
	jmp	rskp		;return from conchr

inch01:
inch03:	mov	a,b		;Get the char.
	cpi	'?'             ;Is it a help request?
	jnz	intch1		;If not, go to the next check.
inch3a:	lda	logflg		;[pcc003] Logging flag
	ora	a		;[pcc003] see if active
	jp	inch04		;[pcc005] jump if no file open
	lxi	d,loghlp	;[pcc003] yes, tell about R AND Q
	call	prtstr		;[pcc003]
inch04:	lxi	d,inthlp	;If so, get the address of the help message.
	call	prtstr
	call	sysinh		; print system-dependent help message
	lxi	d,inhlp1	; Tell about doubling the escape character
	call	prtstr
	call	escpr		;Print escape character
	lxi	d,inhlp2	;Print the rest
	call	prtstr
	jmp	intchr		;Get another char.

intch1:	mov	a,b		;Get the character.
	cpi	'0'             ;Is it '0', to send a null?
	jnz	intch3		;No.
	xra	a		;Yes, send an ASCII zero.
	call	setpar		; with the correct parity
	mov	e,a
	call	selmdm		; (to the modem...)
	call	outmdm
	call	selcon		; return with console selected
	jmp	rskp

intch3:	lda	escchr		;Get the escape char.
	cmp	b		;Is it the escape char?
	jnz	intch4		;[pcc002] jump if not
	mov	a,b		;Get the char.
	call	setpar
	mov	e,a		;Restore it.
	call	selmdm
	call	outmdm		;Output it.
	call	selcon		;We promised console would be selected...
	jmp	rskp		;Return, we are done here.
intch4:	mov	a,b		;[pcc002] get it again
	ani	137o		;[pcc002] in upper case
	cpi	'P'             ;[pcc002] toggle printer?
	jnz	intch5		;[pcc003] nope
	lda	prnflg		;[pcc002] get printer flag
	xri	01h		;[pcc002] complement it
	sta	prnflg		;[pcc002] and put back
	jmp	rskp		;[pcc002]
intch5:	lda	logflg		;[pcc003] get log flag
	ora	a		;[pcc003] See if open
	jp	intch7		;[pcc003] no, skip R and Q
	mov	a,b		;[pcc003] get back chr
	ani	137o		;[pcc003] make upper case
	cpi	'R'             ;[pcc003] Is it R
	jnz	intch6		;[pcc003] Jump if not
	mvi	a,81H		;[pcc003] set flag for logging
	sta	logflg		;[pcc003] put it back
	lxi	d,inms28	;[pcc003] message
	call	prtstr		;[pcc003]
	jmp	rskp		;[pcc003] done
intch6:	cpi	'Q'             ;[pcc003] Quit logging?
	jnz	intch7		;[pcc003] no
	mvi	a,82H		;[pcc003] flag for open, but suspended
	sta	logflg		;[pcc003] store away
	lxi	d,inms27	;[pcc003] keep them informed
	call	prtstr		;[pcc003]
	jmp	rskp		;[pcc003]
intch7:				;[pcc003]

intchz:	mov	a,b		; not recognized. get saved copy back.
	push	psw		;[8] save as we will want to test for 'D'
	call	sysint		; interpret system-dependent sequences
	jmp	intchy		;  done. [10] Now see if D.  If so, do a C.
	pop	psw		;[10] tidy stack
	mvi	e,'G'-100O      ;Otherwise send a beep.
	call	outcon		; to the console.
	jmp	rskp

intchy:	pop	psw		;[10] adjust stack
	ani	5fh		;[10] strip parity, make it upper case
	cpi	'D'             ;[10] was it a D?
	jz	contc		;[10] yup, so to the equivalent of an escape-C
	jmp	rskp
;
; Little code to allow some expansion of code without changing
;  every futher address, only up to the end of this file.
;   TO BE REMOVED FOR RELEASE!

;	org ($+100h) AND 0FF00H
IF lasm
	LINK	CPSCPM
ENDIF;lasm