aboutsummaryrefslogtreecommitdiff
path: root/src/cpstt.asm
diff options
context:
space:
mode:
authorJeff Armstrong <jeff@approximatrix.com>2026-10-25 17:42:06 -0400
committerJeff Armstrong <jeff@approximatrix.com>2026-10-25 17:42:06 -0400
commitebb2ff2af569d5822b70ee555a32d27cf7494816 (patch)
tree7ac5e7b3fa73f7a8d996129086932ecce66374ad /src/cpstt.asm
downloadkermit-80-main.tar.gz
kermit-80-main.zip
Initial import of 4.11HEADmain
Diffstat (limited to 'src/cpstt.asm')
-rw-r--r--src/cpstt.asm862
1 files changed, 862 insertions, 0 deletions
diff --git a/src/cpstt.asm b/src/cpstt.asm
new file mode 100644
index 0000000..41a30af
--- /dev/null
+++ b/src/cpstt.asm
@@ -0,0 +1,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