X-Git-Url: http://cloudbase.mooo.com/gitweb/kermit-80.git/blobdiff_plain/c25f6a44a6e2266617af2f326fa5dc0c4864035f..e58a7a2546e59e692ea958cbdcdbb184654383be:/cpstt.asm diff --git a/cpstt.asm b/cpstt.asm index 41a30af..1e96171 100644 --- a/cpstt.asm +++ b/cpstt.asm @@ -1,862 +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 -; -; 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 -; -; 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 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 Q to suspend logging and R to -; resume. 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 -; 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 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 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 +; 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 +; +; 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 +; +; 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 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 Q to suspend logging and R to +; resume. 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 +; 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 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 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