; 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