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
|