; CP4UTL.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. ; ; Utility routines, pure and impure data. ; ; revision history: ; edit 6: February 6, 1985 ; Added a storage location for the port value (PORT, just below ; SPEED) which is used by the port status routine, and moved the ; printer copy flag (PRNFLG:) into the communications area so ; that the machine dependant overlay can toggle it. [Hal Hostetler] ; Added ffussy flag for filename checking. Generate the version ; string from 'verno', which is set in CP4KER, because CP4KER has the ; list of modules and their edit numbers. [Charles Carvalho] ; ; edit 5: 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. ; ;pcc006 2-jan-85 VJC modules:cp4cmd,cp4utl ; Problems with "?" in filespecs. On reparse, may cause action ; flag to be reset at wrong point, requiring multiple 's ; to terminate the line or other weird stuff. Also need to ; check flag and complain if wild-cards illegal. ; ;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. ; ;pcc013 8-Jan-85 vjc modules:cp4mit,cp4utl,cp4typ ; Replace CLOSE command to cancel session logging to SET ; LOGGING ON/OFF. This seems to fit in with the command ; structure better. Default the log file to KERMIT.LOG ; incase no previous LOG command. Logging is also enabled ; by LOG command, as before. ; ; edit 4: September 9, 1984 ; Move command tables and associated help text to CP4MIT. Add ; makfil/clofil routines and modify outbuf to write files in big ; chunks. Update Kermit's version to 4.03. ; ; edit 3: August 21, 1984 ; Make inbuf read files in big chunks to minimize disk start/stop ; delays. Buffer size and address is specified by system-dependent ; overlay. ; ; edit 2: August 3, 1984 ; move "mover" to CP4SYS to allow use of Z80 block move instruction. ; ; edit 1: July 27, 1984 ; extracted from CP4MIT.M80 edit 2, as part of LASM support. This is ; the last file linked for the system-independent code. ; utlver: db 'CP4UTL.ASM (5) 13-Jan-85$' ; Set the parity for a character in A. ; called by: spack, rexmit, logit, vt52, conchr, intchr setpar: push h ;Save HL. push b lxi h,parity mov c,m ;Get the parity routine. mvi b,0 lxi h,parjmp ;Get the first address. dad b pchl parjmp: jmp even jmp mark jmp none jmp odd jmp space none: jmp parret ;Don't touch the parity bit. even: ani 7FH ;Strip parity. jpe parret ;Already even, leave it. ori 80H ;Make it even parity. jmp parret mark: ori 80H ;Turn on the parity bit. jmp parret odd: ani 7FH ;Strip parity. jpo parret ;Already odd, leave it. ori 80H ;Make it odd parity. jmp parret space: ani 7FH ;Turn off the parity bit. jmp parret parret: pop b pop h ;Restore HL. ret ; ; Print the escape char. ; called by: stat01, xmit, telnet, intchr escpr: lda escchr ;Get the escape char. cpi ' ' ;Is it a control char? jp escpr2 lxi d,inms10 ;Output "Control-". call prtstr lda escchr ori 100O ;De-controlify. escpr2: mvi c,conout ;Output the char mov e,a call bdos ret ; fetch keyword; if unsuccessful, return to command level. ; called by: kermit, setcom keycmd: mvi a,cmkey call comnd jmp keycm2 ;no match ret keycm2: lxi d,ermes1 ;"Unrecognized Command" call prtstr jmp kermit ;Do it again. ; request confirmation; if unsuccessful, return to command level ; called by: bye, exit, help, log, setcom, show, status, send, ; finish, logout, xmit, telnet cfmcmd: mvi a,cmcfm call comnd jmp kermt3 ;"Not confirmed" ret ; ; This routine prints the number in HL on the screen in decimal. ; Uses all ACs. ; called by: cp4sys, read, send, updrtr, dir nout: lxi b,-10 ;Get some useful constants. nout1: lxi d,-1 nout2: dad b ;Subtract as many 10s as possible. inx d ;Count them. jc nout2 ;If some left keep going. push h ;save remainder - 10 xchg ;Swap the remainder and the quotient. mov a,h ;Get the number of 10s found. ora l ;check for quotient non zero cnz nout1 ;If non zero, recurse. pop h ;Get the remainder - 10 mov a,l ;in a adi '0'+10 ;Make the number printable and add the 10 back mov e,a ;Output the digit. mvi c,conout jmp bdos ; prcrlf - print a CR/LF. (Saves no registers.) [Toad Hall] ; prtstr - print string pointed to by DE ; called by: lots of places. prcrlf: lxi d,crlf ;Point to the CR/LF prtstr: mvi c,prstr ; output string jmp bdos ;a CALL followed by a RET becomes a JMP ; Jumping to this location is like retskp. It assumes the instruction ; after the call is a jmp addr. ; here from: many places. rskp: pop h ;Get the return address. inx h ;Increment by three. inx h inx h pchl ; Jumping here is the same as a ret. 'jmp r' is used after routines ; that have skip returns, where the non-skip instruction must be 3 bytes. ; here from: many places. r: ret ; ; Open a file for reading (with inbuf). The filename is already ; in fcb; upon return, the end of file flag is cleared and chrcnt ; is set to zero, so inbuf will be called to get a buffer when we ; next attempt to get a character. ; called by: sinit, seof, xmit getfil: xra a sta chrcnt ;Buffer is empty. sta seccnt ;No sectors buffered. sta eoflag ;Not the end of file. sta endsts ;No EOF/error pending. sta fcb+0CH ;Zero the extent. sta fcb+0EH ;Must be zero for MAKEF or OPENF. sta fcb+20H ;Zero the current record. mvi c,openf ;Open the file. lxi d,fcb call bdos ret ; Get next sector. If necessary, read some more from disk. ; preserves bc, de, hl ; returns nonskip if EOF or error; ; returns skip with chrcnt and bufpnt updated if success. ; called by: gtchr, xnext inbuf: lda eoflag ;Have we reached the end? ora a rnz ;Return if so. push b push d push h inbuf1: lda seccnt ; Do we have any sectors left? ora a jz inbuf3 ; If not, go get some more. inbuf2: lhld nxtbuf ; Yes. Get address of next sector shld bufpnt ; Update current buffer pointer lxi b,bufsiz ; Get number of bytes in sector dad b ; Update HL to point to next sector shld nxtbuf ; Save for next time dcr a ; Decrement count of buffered sectors sta seccnt ; Put it back mvi a,bufsiz-1 ; Number of bytes in buffer (pre-decremented) sta chrcnt ; Store for our caller pop h pop d pop b jmp rskp ; Return success ; We don't have any sectors buffered. If we've already hit an error or ; EOF, return that status to the user. inbuf3: lda endsts ; Check status from previous read ora a jz inbuf4 ; It was OK. Get some more sectors. sta eoflag ; End of file or error. Set the flag. xra a sta chrcnt ; Say no characters in buffer. pop h pop d pop b ret ; Return failure ; Read sectors until we fill the buffer or get an error or EOF, then return ; the first buffer to the user. (seccnt is zero) inbuf4: lhld bufadr ; Get address of big buffer shld nxtbuf ; Store as next buffer address to give user inbuf5: shld bufpnt ; Store as next buffer address to read into xchg ; Move buffer address to DE mvi c,setdma ; Tell CP/M where to put the data call bdos ; ... mvi c,readf ; Read a record. lxi d,fcb call bdos sta endsts ; Save ending status ora a ; 00H => read O.K jnz inbuf6 ; EOF/error: stop reading. lxi h,seccnt ; Success. Get addr of sector count inr m ; Bump sector count by one lda bufsec ; Get max number of sectors in buffer cmp m ; Are we there yet? jz inbuf7 ; Yes, can't read any more. lhld bufpnt ; No, try for another. Get buffer address, lxi d,bufsiz ; and size of sector, dad d ; giving next buffer address in HL jmp inbuf5 ; Go read another sector. ; We hit EOF or got an error. Put the DMA address back where it belongs, ; then go see if we have any sectors (before the one that got the error) ; to return to the caller. Nxtbuf points to the first good sector, if ; any; seccnt contains the count of good sectors. inbuf6: call rstdma jmp inbuf1 ; Go see if we have some data to return ; We've filled the big buffer. Reset the DMA address, then go return a ; sector to the caller. nxtbuf points to the beginning of the buffer; ; seccnt contains the number of sectors successfully read (except that ; if we've read 256 sectors, seccnt contains zero, so we can't just go ; to inbuf1). inbuf7: call rstdma ;[pcc012] lda seccnt ; Get sector count again. jmp inbuf2 ; Return a sector. ; ;[pcc012] ; appfil - Create or append to an existing file. File name is in FCB. ; Non-skip return if could not be done. Skip return with file ; open and bufpnt pointing to end of file. ; called by logopn appfil: xra a ;[pcc012] zero out stuff for open sta fcb+0CH ;[pcc012] extent sta fcb+0EH ;[pcc012] Must be zero for MAKEF or OPENF. sta fcb+20H ;[pcc012] Zero the current record. mvi c,openf ;[pcc012] Try to open the file lxi d,fcb ;[pcc012] call bdos ;[pcc012] cpi 0FFH ;[pcc012] Did we find it? jz makfi1 ;[pcc012] If not, go create it mvi c,cflsz ;[pcc012] Compute the file size lxi d,fcb ;[pcc012] call bdos ;[pcc012] lhld fcb+21H ;[pcc012] random record pointer mov a,h ;[pcc012] See if zero length file ora l ;[pcc012] jz makfi2 ;[pcc012] set up pointers if null file dcx h ;[pcc012] backup to last record written shld fcb+21H ;[pcc012] store rec ptr back lhld bufadr ;[pcc012] get buffer address xchg ;[pcc012] to DE mvi c,setdma ;[pcc012] set dma address call bdos ;[pcc012] for read mvi c,rrand ;[pcc012] read the last block lxi d,fcb ;[pcc012] call bdos ;[pcc012] ora a ;[pcc012] check results jnz rstdma ;[pcc012] reset dma and return if error lhld bufadr ;[pcc012] get address again lxi d,bufsiz ;[pcc012] and and size mvi a,'Z'-40H ;[pcc012] control-Z for comparison appcz: cmp m ;[pcc012] Is this the EOF? jz appxit ;[pcc012] Jump if yes inx h ;[pcc012] no, bump dcr e ;[pcc012] and grind jnz appcz ;[pcc012] until find or buffer empty appxit: shld bufpnt ;[pcc012] store buffer pointer dad d ;[pcc012] compute next buffer adr shld nxtbuf ;[pcc012] and store mov a,e ;[pcc012] updated chr count sta chrcnt ;[pcc012] xra a ;[pcc012] reset sector count sta seccnt ;[pcc012] call rstdma ;[pcc012] reset normal dma jmp rskp ;[pcc012] and give good return ; Create a file, deleting any previous version. The filename is in ; fcb. ; Returns nonskip if file could not be created. ; If successful, takes skip return with bufpnt and chrcnt initialized ; for output; buffers should be output via outbuf. ; called by: gofil makfil: mvi c,delf ; delete the file if it exists. lxi d,fcb call bdos xra a sta fcb+0CH ; zero the extent. sta fcb+0EH ; must be zero for MAKEF or OPENF. sta fcb+20H ; zero the current record. ;[pcc012] here from appfil above if file does not exist makfi1: mvi c,makef ;[pcc012] now create it. lxi d,fcb call bdos cpi 0FFH ; is the disk full? rz ; take error return if so. ; success. set up pointers and counters for multisector buffering. ;[pcc012] also here from appfil if found zero length file makfi2: lhld bufadr ;[pcc012] find beginning of buffer space. shld bufpnt ; make it current buffer. lxi d,bufsiz ; get sector size. dad d ; find beginning of next buffer. shld nxtbuf ; store for later. mov a,e ; store buffer size sta chrcnt ; for caller. xra a sta seccnt ; no sectors stored yet. jmp rskp ; take success return. ;[pcc012] ; outadv - conditionally advance output buffer if disk write not needed. ; preserves BC ; skip return with with next output buffer set up ; non-skip return if memory buffer full and must write to disk. ; called by:logit outadv: push b ;[pcc012] save BC as advertised lxi h,seccnt ;[pcc012] point to sectors buffered inr m ;[pcc012] count this one lda bufsec ;[pcc012] how many we can hold cmp m ;[pcc012] check if full jnz outbf2 ;[pcc012] continue if not dcr m ;[pcc012] full, un-advance sector count pop b ;[pcc012] restore bc ret ;[pcc012] and give non-skip return ; get a fresh output buffer, flushing big buffer if necessary. ; returns nonskip if disk full. ; if successful, returns skip with bufpnt and chrcnt updated. Note ; that chrcnt holds one less than the buffer size. ; preserves BC. ; called by: ptchr,logwrt outbuf: push b lxi h,seccnt ; count another buffered sector inr m ; ... lda bufsec ; get number of sectors we can hold cmp m ; full? jnz outbf2 ; if not, set up pointers and return call outmbf ; flush the big buffer jmp outbf9 ; disk error. ;[pcc012] also here from outadv to advance buffer outbf2: lhld nxtbuf ; get pointer to fresh buffer shld bufpnt ; store for caller lxi d,bufsiz ; advance our pointer to next buffer dad d shld nxtbuf mvi a,bufsiz-1 ; get buffer size (pre-decremented) sta chrcnt ; store for caller pop b jmp rskp ; return success. outbf9: pop b ; clean up stack ret ; and take error return. ; flush incore output buffers. ; returns nonskip if disk full. ; if successful, returns skip with nxtbuf reset to start of buffer and ; seccnt zero. ; destroys all ac's. ; called by: outbuf, clofil. outmbf: lhld bufadr ; get start of buffer shld nxtbuf ; store for next fill cycle shld bufpnt ; store for empty loop outmb2: lhld bufpnt ; get address of current sector xchg ; into DE lxi h,bufsiz ; advance HL to next sector dad d ; ... shld bufpnt ; and store for later mvi c,setdma call bdos ; point CP/M at current sector lxi d,fcb mvi c,writef call bdos ; output the sector ora a ; test for error (A non-zero) jnz rstdma ;[pcc012] reset dma and take nonskip return if so lxi h,seccnt dcr m ; count down buffered sectors jnz outmb2 ; loop if more saved call rstdma ;[pcc012] restore normal dma jmp rskp ; return success. ; output current buffer, flush incore buffers, and close output file. ; returns nonskip if disk full; skip if successful. ; called by: rdata clofil: lda chrcnt ; get the number of chars left in the buffer. cpi bufsiz ; Virgin buffer? jz clofl3 ; yes, don't output it. lhld bufpnt ; get the buffer pointer. clofl1: dcr a ; lower the count. jm clofl2 ; if full then stop. mvi m,'Z'-100O ; put in a ^Z for EOF. inx h ; point to the next space. jmp clofl1 clofl2: call outbuf ; output the last buffer. jmp r ; give up if the disk is full. clofl3: lda seccnt ; any sectors buffered in memory? ora a jz clofl4 ; if not, don't try to flush. call outmbf ; flush buffers jmp r ; disk full. clofl4: mvi c,closf ; close up the file. lxi d,fcb call bdos jmp rskp ; return success. ; Reset DMA address to the default buffer ; called from inbuf,appfil,outmbf rstdma: lxi d,buff ;[pcc012] mvi c,setdma ;[pcc012] jmp bdos ;[pcc012] ; version:db 'Kermit-80 v4.' db (verno/10) + '0' ; tenth's digit of version number db (verno MOD 10) + '0' ; hundredth's digit db ' $' kerm: db 'Kermit-80 ' kerm1: db 'x:>$' ;'x' filled in at startup with DRIVE name crlf: db cr,lf,'$' ermes1: db cr,lf,'?Unrecognized command$' ermes3: db cr,lf,'?Not confirmed$' ermes4: db '?Unable to receive initiate',cr,lf,'$' ermes5: db '?Unable to receive file name',cr,lf,'$' ermes6: db '?Unable to receive end of file',cr,lf,'$' erms10: db '?Unable to receive data',cr,lf,'$' erms11: db '?Disk full',cr,lf,'$' erms14: db '?Unable to receive an acknowledgement from the host',cr,lf,'$' erms15: db cr,lf,'?Unable to find file',cr,lf,'$' erms16: db '?Unable to rename file$' erms17: db cr,lf,'?Disk full$' erms18: db cr,lf,'?Unable to tell host that the session is finished$' erms19: db cr,lf,'?Unable to tell host to logout$' erms20: db cr,lf,'?Kermit has not been configured for a target system$' erms21: db cr,lf,'?Consistency check on configuration failed$' erms22: db cr,lf,'?Error writing to log file',cr,lf,'$' ;[pcc005] infms3: db bell,'Completed$' infms4: db bell,'Failed$' infms5: db '%Renaming file to $' infms6: db cr,lf,'[Closing the log file]$' infms7: db cr,lf,'[Connected to remote host. Type $' infms8: db 'C to return;',cr,lf,' type $' inms8a: db '? for command list]',cr,lf,'$' infms9: db cr,lf,'[Connection closed, back at micro]$' inms10: db 'Control-$' inms12: db ' (Not implemented)',cr,lf,'$' inms13: db bell,'Interrupted$' inms14: db TAB,TAB,' Directory for drive ' dnam14: db 'x:',cr,lf,'$' ;filled in by dir routine. inms15: DB CR,LF,TAB,TAB,'Drive $' inms16: DB ' has $';filled in by summary code with drive letter inms17: DB 'K bytes free',CR,LF,'$' inms18: DB CR,LF,'File(s) erased$',CR,LF inms19: db cr,lf,'[Transmitting file to host:' db cr,lf,' 1. Type any character to send a line.' db cr,lf,' 2. Type RETURN to terminate the line ' db 'and to get the next line (go back to 1.)' db cr,lf,' (You may send other characters ' db 'before RETURN.),' db cr,lf,' or type $' inms20: db 'R to send the same line again,' db cr,lf,' or type $' inms21: db 'C to abort transmission.]',cr,lf,'$' inms22: db cr,lf,'[Transmission done. Connected normally ' db 'to remote host,' db cr,lf,' type $' inms23: db 'Sending...$' inms24: db 'Receiving...$' inms25: db bell,'Warning: eighth bit cannot be sent$' inms26: db cr,lf,'For help, type ? at any point in a command$' inms27: db cr,lf,'[Logging suspended]',cr,lf,'$' ;[pcc003] inms28: db cr,lf,'[Logging resumed]',cr,lf,'$' ;[pcc003] escmes: db cr,lf,'Type the new escape character: $' tacmes: db cr,lf,'Type the new TAC intercept character: $' xmthlp: db cr,lf,'R Send the same line again$' loghlp: db cr,lf,'Q Suspend logging' ;[pcc003] db cr,lf,'R Resume logging$' ;[pcc003] inthlp: db cr,lf,'? This message' db cr,lf,'C Close the connection' db cr,lf,'0 (zero) Transmit a NULL' db cr,lf,'P Toggle printer on/off' ;[pcc002] db cr,lf,'S Status of the connection$' inhlp1: db cr,lf,'Typing another $' inhlp2: db ' will send it to the host' db cr,lf,cr,lf,'Command>$' xmtst: db cr,lf,'Transmitting a file$' locst: db cr,lf,'Local echo$' onstr: db ' on$' offstr: db ' off$' vtemst: db cr,lf,'VT52 emulation$' cpmst: db cr,lf,'File Mode$' defstr: db ' default$' ascstr: db ' ASCII$' binstr: db ' binary$' ibmst: db cr,lf,'IBM flag$' filst: db cr,lf,'File warning$' prst: db cr,lf,'Printer copy$' logst: db cr,lf,'Logging is$' ;[pcc003] susstr: db ' suspended$' ;[pcc003] escst: db cr,lf,'Escape char: $' bckst: db cr,lf,'Block check type: $' bckst1: db '-character$' parst: db cr,lf,'Parity: $' pnonst: db 'none$' pmrkst: db 'mark$' pspcst: db 'space$' poddst: db 'odd$' pevnst: db 'even$' porst: db cr,lf,'Port in use is: $' spdst: db cr,lf,'Current baud rate is: $' spdust: db 'indeterminate (not SET)$' timmsg: db 'Timer$' tacst: db cr,lf,'Current TACTrap Status/Intercept Character: $' cmer00: db cr,lf,'?Program error: Invalid COMND call$' cmer01: db cr,lf,'?Ambiguous$' cmer02: db cr,lf,'?Illegal CP/M file specification$' cmer03: db cr,lf,'?Wild-cards not allowed in file specification$' ;[pcc006] cmin00: db ' Confirm with carriage return$' ; ;Impure data ;COMND storage cmstat: ds 1 ;What is presently being parsed. cmaflg: ds 1 ;Non-zero when an action char has been found. cmccnt: ds 1 ;Non-zero if a significant char is found. cmsflg: ds 1 ;Non-zero when the last char was a space. cmostp: ds 2 ;Old stack pointer for reparse. cmrprs: ds 2 ;Address to go to on reparse. cmprmp: ds 2 ;Address of prompt. cmptab: ds 2 ;Address of present keyword table. cmhlp: ds 2 ;Address of present help. cmdbuf: ds 80H ;Buffer for command parsing. cmfcb: ds 2 ;Pointer to FCB. cmfcb2: ds 2 ;Pointer to position in FCB. cmfwld: ds 1 ;Wildcard flag cmcptr: ds 2 ;Pointer for next char input. cmdptr: ds 2 ;Pointer into the command buffer. cmkptr: ds 2 ;Pointer to keyword. cmsptr: ds 2 ;Place to save a pointer. ; oldsp: ds 2 ;Room for old system stack. ds 40H ;Room for 32 levels of calls. stack: ds 2 eoflag: ds 1 ;EOF flag;non-zero on EOF. curdsk: db 0 ;holds "logged" disk prtcnt: db 0 ;[pcc008] prtchr fairness count timflg: db 0 ;[jd] timer flag: 0 -> no timer timval: dw 0 ;[jd] timer value wrn8: db 0 ;[jd] non-zero if 8-bit-lost warning sent qbchr: db '&' ;[jd] binary quote character. quot8: db 0 ;[jd] non-zero if doing 8-bit quoting logflg: db 0 ;Flag for a log file. ;[pcc005] 0 = no log ;[pcc005] x1 = logging on ;[pcc005] x2 = suspended ;[pcc005] 8xH (bit 7) = file open lognam: db 0 ;[pcc013] File to use for session logging db 'KERMIT ' ;[pcc013] db 'LOG' ;[pcc013] escflg: db 0 ;Escape flag (start off). fileio: db 0 ;Line-by-line from file (default off). xofflg: db 0 ;X-OFF (=^S) received from COMM-line ; ;X-ON (=^Q) received resets this vtyval: ds 1 ; holds row number for VT52 cursor positioning chrcnt: ds 1 ;Number of chars in the file buffer. filcnt: ds 1 ;Number of chars left to fill. outpnt: ds 2 ;Position in packet. bufpnt: ds 2 ;Position in file buffer. fcbptr: ds 2 ;Position in FCB. datptr: ds 2 ;Position in packet data buffer. cbfptr: ds 2 ;Position in character buffer. pktptr: ds 2 ;Position in receive packet. size: ds 1 ;Size of data from gtchr. curchk: ds 1 ;Current checksum type inichk: ds 1 ;Agreed upon checksum type czseen: ds 1 ;Flag that control-Z was typed pktnum: ds 1 ;Packet number. numpkt: ds 2 ;Total number of packets sent. numrtr: ds 2 ;Total number of retries. numtry: ds 1 ;Number of tries on this packet. oldtry: ds 1 ;Number of tries on previous packet. state: ds 1 ;Present state of the automaton. packet: ds 4 ;Packet (data is part of it). data: ds 5AH ;Data and checksum field of packet. recpkt: ds 65H ;Receive packet storage (use the following). recpkx: db cr,'$' ;= = = buffer limit filbuf: ds 65H ;Character buffer. fnbuf: ds 20h ;[jd] file name buffer ;** Temp 1 & 2 must be in order temp1: ds 1 ;Temporary storage. lstchr EQU temp1 ;Last console input character. temp2: ds 1 temp3: ds 1 temp4: ds 1 argblk: ds 20H ;Used for subroutine arguments maxfil EQU 2 ; currently, only two names used. fcbblk: ds maxfil*10H ;Used for a list of FCB's ; Bookkeeping storage for multiple-sector buffering. The actual buffer ; is somewhere in the system-dependent overlay. (at the end, I hope). nxtbuf: ds 2 ; Pointer to next sector seccnt: ds 1 ; Number of sectors buffered endsts: ds 1 ; Status for last read into buffer patch: ds 100 ; Guarantee some patch space ORG ($ + 0ffH) AND 0ff00H ; move to start of next page ; ; hooks for system-dependent routines: ; This area is overwritten by the system-dependent overlay. ; lnkflg: dw 0 ; linkage information for consistency check. lnkent: dw 0 ; more of the same. ovlver: dw 0 ; pointer to overlay's version string ; ; Input/output routines. Note that outmdm and outcon may actually be the ; same routine if selmdm and selcon do anything. (the same is true ; of inpmdm and inpcon). ; selmdm: jmp $-$ ; select modem for I/O outmdm: jmp $-$ ; output character in E to modem inpmdm: jmp $-$ ; read character from modem. return character or 0 in A. flsmdm: jmp $-$ ; flush pending input from modem selcon: jmp $-$ ; select console for I/O outcon: jmp $-$ ; output character in E to console inpcon: jmp $-$ ; read char from console. return character or 0 in A outlpt: jmp $-$ ; output character in E to printer ; ; screen formatting routines clrlin: jmp $-$ ; erase current line clrspc: jmp $-$ ; erase current position (after backspace) delchr: jmp $-$ ; make delete look like backspace clrtop: jmp $-$ ; erase screen and go home ; ; these routines are called to display a field on the screen. scrend: jmp $-$ ; move to prompt field screrr: jmp $-$ ; move to error message field scrfln: jmp $-$ ; move to filename field scrnp: jmp $-$ ; move to packet count field scrnrt: jmp $-$ ; move to retry count field scrst: jmp $-$ ; move to status field rppos: jmp $-$ ; move to receive packet field (debug) sppos: jmp $-$ ; move to send packet field (debug) ; sysinit: jmp $-$ ; program initialization sysexit: jmp $-$ ; program termination syscon: jmp $-$ ; remote session initialization syscls: jmp $-$ ; return to local command level sysinh: jmp $-$ ; help text for interrupt (escape) extensions sysint: jmp $-$ ; interrupt (escape) extensions, including break sysflt: jmp $-$ ; filter for incoming characters. ; called with character in E. sysbye: jmp $-$ ; terminate remote session sysspd: jmp $-$ ; baud rate change routine. ; called with value from table in DE sysprt: jmp $-$ ; port change routine. ; called with value from table in DE sysscr: jmp $-$ ; screen setup for file transfer ; called with Kermit's version string in DE csrpos: jmp $-$ ; move cursor to row B, column C sysspc: jmp $-$ ; calculate free space for current disk mover: jmp $-$ ; block move ; ; Data initialized by system-dependent overlay: ; pttab: ds 2 ; points to local equivalents to VT52 escape sequences spdtab: ds 2 ; address of baud rate command table, or zero spdhlp: ds 2 ; address of baud rate help table, or zero prttab: ds 2 ; address of port command table, or zero prthlp: ds 2 ; address of port help table, or zero timout: ds 2 ; Initial value for fuzzy timeout vtflg: ds 1 ; VT52 emulation flag escchr: ds 1 ; Storage for the escape character. speed: ds 2 ; storage for the baud rate port: ds 2 ; storage for port value prnflg: ds 1 ;[hh] printer copy flag (overlay may need it) dbgflg: ds 1 ; debugging flag ecoflg: ds 1 ; Local echo flag (default off). flwflg: ds 1 ; File warning flag (default on). ibmflg: ds 1 ; IBM flag (default off). cpmflg: ds 1 ; File mode flag (ascii/binary/default) parity: ds 1 ; Current parity. spsiz: ds 1 ; Send packet size. rpsiz: ds 1 ; Receive packet size. stime: ds 1 ; Send time out. rtime: ds 1 ; Receive time out. spad: ds 1 ; Send padding. rpad: ds 1 ; Receive padding. spadch: ds 1 ; Send padding char. rpadch: ds 1 ; Receive padding char. seol: ds 1 ; Send EOL char. reol: ds 1 ; Receive EOL char. squote: ds 1 ; Send quote char. rquote: ds 1 ; Receive quote char. chktyp: ds 1 ; Checksum type desired tacflg: ds 1 ; TACTrap flag (zero=off, nonzero=on; when non-zero, ; contains current TAC intercept character) tacchr: ds 1 ; TAC intercept character bufadr: ds 2 ; Pointer to big buffer for multiple-sector I/O bufsec: ds 1 ; Number of sectors big buffer can hold (0 means 256) ffussy: ds 1 ; if nonzero, don't permit <>.,;?*[] in CP/M filespec. ; space used by directory command; here because space calculation is ; (operating) system-dependent bmax: ds 2 ; highest block number on drive bmask: ds 1 ; (records/block)-1 bshiftf: ds 1 ; number of shifts to multiply by rec/block nnams: ds 1 ; counter for filenames per line lnksiz equ $-lnkflg ; length of linkage section, for consistency check. END START