page 64 title 'Simple terminal emulator - KERMIT part 2' maclib term ; -->> File : KERSUB.ASM ; ========== ; (Adapted from the Version 3.9A, (c) Columbia University) ; Copyright (c) Werner Cirsovius ; Hohe Weide 44 ; D-2000 Hamburg 20 ; Federal Republic of Germany ; Tel.: 040/4223247 ; Version 1.10, February 1988 ; ===== Externals ===== ; From LIB BASELIB extrn strbi0,break,conind,open,dskwrt,dskred,crlf ; From main module TERMINAL extrn xmitch,inrdy,rcvchr,errdo,errstk ; From module KERMIT extrn @abort,nak0,updrtr ; To module KERMIT public argblk,numtry,czseen,data,oldtry,bufpnt,chrcnt public state,temp4,spad,spadch,seol,squote,quot8 public qbchr,chktyp,inichk,pktnum,spsiz,rquote public reol,rpadch,rpad,rtime,rpsiz,numrtr,curchk public numpkt,size,datptr,cbfptr,filbuf,filflg public eoflag,fcbptr,modflg public ermes4,ermes5,ermes6,erms10,infms3 public infms4,inms13,inms22,inms23,inms24 public scrnrt,scrnp,outln2 public ptchr,spack,error3,tryagn,errchk,compp,countp public outbuf,ackp,rpack,error,finmes,errmsg public Zstate,gtchr,r,finish ; ***** PART 3 : the SUBROUTINES ***** compp: ;This routine used to compare packet-Nr ; lda pktnum ;Get the packet Nr. mov b,a lda argblk cmp b ret ; countp: ;This routine up's the packet Nr. modulo 64 ; inr a ;Increment packet Nr. ani 3fh ;Turn off the two high order bits sta pktnum ;Save modulo 64 of number lhld numpkt inx h ;Increment Nr. of packets shld numpkt ret ; ackp: ;This routine sends an ACK-packet ; xra a sta numtry ;Reset number of retries sta argblk+1;No data. ;(The packet number is in argblk) mvi a,'Y' ;Acknowledge packet call spack ;Send packet jmp @abort ret ; tryagn: ; Set up retry ; inr a ;Increment it. sta oldtry ;Save the updated number of tries. lda pktnum ;Get the present packet number. dcr a ;Decrement. mov b,a lda argblk ;Get the packet's number cmp b ;Is the packet's number ;one less than now? jnz nak0 ;No, NAK it and try again. call updrtr ;Update the number of retries. call ackp ret ; spack: ; Send_Packet ; This routine assembles a packet from the arguments ; given and sends it to the host. ; ;Expects the following: ; A - Type of packet (D,Y,N,S,R,E,F,Z,T) ; ARGBLK - Packet sequence number ; ARGBLK+1 - Number of data characters ;Returns: +1 on failure ; +2 on success ; sta argblk+2 lxi h,packet;Get address of the send packet. mvi m,soh ;Get the start of header char. ;Put in the packet. inx h ;Point to next char. lda curchk ;Get current checksum type sui '1' ;Determine extra length of checksum mov b,a ;Copy length lda argblk+1;Get the number of data chars. adi ' '+3 ;Real packet character count made ;printable. add b ;Determine overall length mov m,a ;Put in the packet. inx h ;Point to next char. lxi b,0 ;Zero the checksum AC. mov c,a ;Start the checksum. lda argblk ;Get the packet number. adi ' ' ;Add a space so the number is printable mov m,a ;Put in the packet. inx h ;Point to next char. add c mov c,a ;Add the packet number to the checksum. mvi a,0 ;Clear A (Cannot be XRA A, since we ;can't touch carry flag) adc b ;Get high order portion of checksum mov b,a ;Copy back to B lda argblk+2;Get the packet type. mov m,a ;Put in the packet. inx h ;Point to next char. add c mov c,a ;Add the packet number to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B spack2: lda argblk+1;Get the packet size. ora a ;Are there any chars of data? jz spack3 ; No, finish up. dcr a ;Decrement the char count. sta argblk+1;Put it back. mov a,m ;Get the next char. inx h ;Point to next char. add c mov c,a ;Add the packet number to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B jmp spack2 ;Go try again. spack3: lda curchk ;Get the current checksum type cpi '2' ;Two character? jz spack4 ;Yes, go handle it jnc spack5 ;No, go handle CRC if '3' mov a,c ;Get the character total. ani 0c0h ;Turn off all but the two ;high order bits. ;Shift them into the low order position rlc ;Two left rotates same as 6 rights rlc add c ;Add it to the old bits. ani 3fh ;Turn off the two high order bits. ;(MOD 64) adi ' ' ;Add a space so the number is printable mov m,a ;Put in the packet. inx h ;Point to next char. jmp spack7 ;Go store eol character ; spack5: ;Here for 3 character CRC-CCITT ; mvi m,0 ;Store a null for current end push h ;Save H lxi h,packet+1;Point to first checksumed character call crcclc ;Calculate the CRC pop h ;Restore the pointer mov c,e ;Get low order half for later mov b,d ;Copy the high order mov a,d ;Get the high order portion rlc ;Shift off low 4 bits rlc rlc rlc ani 0fh ;Keep only low 4 bits adi ' ' ;Put into printing range mov m,a ;Store the character inx h ;Point to next position ; spack4: ;Here for two character checksum ; mov a,b ;Get high order portion ani 0fh ;Only keep last four bits rlc ;Shift up two bits rlc mov b,a ;Copy back into safe place mov a,c ;Get low order half rlc ;Shift high two bits rlc ;to low two bits ani 03h ;Keep only two low bits ora b ;Get high order portion in adi ' ' ;Convert to printing character range mov m,a ;Store the character inx h ;Point to next character mov a,c ;get low order portion ani 3fh ;Keep only six bits adi ' ' ;Convert to printing range mov m,a ;Store it inx h ;Bump the pointer spack7: lda seol ;Get the EOL the other host wants. mov m,a ;Put in the packet. inx h ;Point to next char. mvi m,0 ;Put null in the packet. call outpkt ;Call the system dependent routine. jmp r jmp rskp ; outpkt: ; Write out a packet. ; lda spad ;Get the number of padding chars. sta temp1 outpk2: lda temp1 ;Get the count. dcr a ora a jm outpk6 ;If none left proceed. sta temp1 lda spadch ;Get the padding char. call xmitch ;Output it. jmp outpk2 outpk6: lxi h,packet;Point to the packet. outlup: mov a,m ;Get the next character. ora a ;Is it a null? jz rskp ;If so return success. call xmitch ;Output the character. inx h ;Increment the char pointer. jmp outlup ; rpack: ; Receive_Packet ; This routine waits for a packet to arrive from the ; host. It reads characters until it finds a SOH. It ; then reads the packet into packet. ; ;Returns: +1 failure (if the checksum is wrong or the ; packet trashed) ; +2 success with A - message type ; ARGBLK - message number ; ARGBLK+1 - length of data ; call inpkt ;Read up to a carriage return. jmp r ; Return bad. rpack0: call getchr ;Get a character. jmp rpack ; Hit a CR;null line;just start over. cpi soh ;Is the char the start of header char? jnz rpack0 ; No, go until it is. rpack1: call getchr ;Get a character. jmp r ; Hit the carriage return, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sta packet+1;Store in packet also mov c,a ;Start the checksum. lda curchk ;Get block check type sui '1' ;Determine extra length of block check mov b,a ;Get a copy mov a,c ;Get back length character sui ' '+3 ;Get the real data count. sub b ;Get total length sta argblk+1 mvi b,0 ;Clear high order half of checksum call getchr ;Get a character. jmp r ; Hit the carriage return, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sta argblk sta packet+2;Save also in packet add c mov c,a ;Add the character to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B lda argblk sui ' ' ;Get the real packet number. sta argblk call getchr ;Get a character. jmp r ; Hit the carriage return, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sta temp1 ;Save the message type. sta packet+3;Save in packet add c mov c,a ;Add the character to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B lda argblk+1;Get the number of data characters. sta temp2 lxi h,data ;Point to the data buffer. shld datptr rpack2: lda temp2 sui 1 ;Any data characters? jm rpack3 ; If not go get the checksum. sta temp2 call getchr ;Get a character. jmp r ; Hit the carriage return, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. lhld datptr mov m,a ;Put the char into the packet. inx h ;Point to the next character. shld datptr add c mov c,a ;Add the character to the checksum. mvi a,0 ;Clear A adc b ;Get high order portion of checksum mov b,a ;Copy back to B jmp rpack2 ;Go get another. rpack3: call getchr ;Get a character. jmp r ; Hit the carriage return, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sui ' ' ;Turn the char back into a number. sta temp3 ; ;Determine type of checksum ; lda curchk ;Get the current checksum type cpi '2' ;1, 2 or 3 character? jz rpack4 ;If zero, 2 character jnc rpack5 ;Go handle 3 character mov a,c ;Get the character total. ani 0c0h ;Turn off all but the two ;high order bits. ;Shift them into the low order position rlc ;Two left rotates same as six rights rlc add c ;Add it to the old bits. ani 3fh ;Turn off the two high order bits. ;(MOD 64) mov b,a lda temp3 ;Get the real received checksum. cmp b ;Are they equal? jz rpack7 ;If so, proceed. rpack9: call updrtr ;If not, update the number of retries. ret ;Return error. ; rpack5: ;Here for three character CRC-CCITT ; lhld datptr ;Get the address of the data mvi m,0 ;Store a zero in the buffer to ;terminate packet lxi h,packet+1;Point at start of checksummed region call crcclc ;Calculate the CRC mov c,e ;Save low order half for later mov b,d ;Also copy high order mov a,d ;Get high byte rlc ;Want high four bits rlc rlc ;And shift two more rlc ani 0fh ;Keep only 4 bits mov d,a ;Back into D lda temp3 ;Get first value back cmp d ;Correct? jnz rpack9 ;No, punt call getchr ;Get a character. jmp r ; Hit the carriage return, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sui ' ' ;Remove space offset sta temp3 ;Store for later check ; rpack4: ;Here for a two character checksum and ;last two characters of CRC ; mov a,b ;Get high order portion ani 0fh ;Only four bits rlc ;Shift up two bits rlc mov b,a ;Save back in B mov a,c ;Get low order rlc ;move two high bits to low bits rlc ani 03h ;Save only low two bits ora b ;Get other 4 bits mov b,a ;Save back in B lda temp3 ;Get this portion of checksum cmp b ;Check first half jnz rpack9 ;If bad, go give up call getchr ;Get a character. jmp r ; Hit the carriage return, return bad. cpi soh ;Is the char the start of header char? jz rpack1 ; Yes, then go start over. sui ' ' ;Remove space offset mov b,a ;Save in safe place mov a,c ;Get low 8 bits of checksum ani 3fh ;Keep only 6 bits cmp b ;Correct value jnz rpack9 ;Bad, give up rpack7: lhld datptr mvi m,0 ;Put a null at the end of the data. lda temp1 ;Get the type. jmp rskp ; getchr: ; Get a character from packet ; lhld pktptr ;Get the packet pointer. mov a,m ;Get the char. inx h shld pktptr cpi cr ;Is it the carriage return? jnz rskp ;If not return retskp. ret ;If so return failure. ; error: ;This is where we go if we get an error during ;a protocol communication. ; Call error prints the error packet. ; Call error3 positions cursor and prints error message ; specified in DE. ; call error9 ;Position the cursor. mvi a,'A' ;Set the state to abort. sta state lda argblk+1;Get the length of the data. mov c,a mvi b,0 ;Put it into BC lxi h,data ;Get the address of the data. dad b ;Get to the end of the string. mvi m,0 ;Put a zero at the end. lxi d,data ;Print error message call strbi0 ret error3: push d ;Save the pointer to the message. call error9 ;Position the cursor. pop d err31: push d lxi d,clrlin;Clear the line call strbi0 pop d ;Get the pointer back. call strbi0 ;Print error message ret error9: lxi d,screrr;Position cursor call strbi0 ret ; finmes: ; Process finish ; push d ;Save message. lxi d,scrst ;Position the cursor call strbi0 pop d call err31 ;Print the terminating mesage ret ; inpkt: ; Input a package ; lxi h,recpkt;Point to the beginning of the packet. shld pktptr inpkt1: call inchr ;Get first character jmp r ;Return failure cpi soh ;is it the beginning of a packet? jnz inpkt1 ;if not, ignore leading junk jmp inpkt3 ;else go put it in packet inpkt2: call inchr ;Get a character. jmp r ; Return failure. cpi soh ;is it a new beginning of packet? jnz inpkt3 ;if not continue lxi h,recpkt;else throw away what we've got so far shld pktptr inpkt3: lhld pktptr mov m,a ;Put the char in the packet. inx h shld pktptr mov b,a lxi d,recpkx;Start over if packet buffer overflow dad d jc inpkt lda reol ;Get the EOL char. cmp b jnz inpkt2 ;If not loop for another. lhld pktptr ;Reload packet pointer mvi m,cr ;Set a carriage-return to stop rpack: lxi h,recpkt shld pktptr ;Save the packet pointer. jmp rskp ;If so we are done. ; crcclc: ; CRCCLC - Routine to calculate ; a CRC-CCITT for a string. ; ;This routine will calculate a CRC using the CCITT ;polynomial for a string. ; ;Usage: ; HL/ Address of string ; A/ Length of string ; CALL CRCCLC ; ;16-bit CRC value is returned in DE. ; ;Registers BC and HL are preserved. ; push h ;Save HL push b ;And BC lxi d,0 ;Initial CRC value is 0 crccl0: mov a,m ;Get a character ora a ;Check if zero jz crccl1 ;If so, all done push h ;Save the pointer xra e ;Add in with previous value mov e,a ;Get a copy ani 0fh ;Get last 4 bits of combined value mov c,a ;Get into C mvi b,0 ;And make high order zero lxi h,crctb2;Point at low order table dad b ;Point to correct entry dad b push h ;Save the address mov a,e ;Get combined value back again rrc ;Shift over to make index rrc rrc ani 1eh ;Keep only 4 bits mov c,a ;Set up to offset table lxi h,crctab;Point at high order table dad b ;Correct entry mov a,m ;Get low order portion of entry xra d ;XOR with previous high order half inx h ;Point to high order byte mov d,m ;Get into D pop h ;Get back pointer to other table entry xra m ;Include with new high order half mov e,a ;Copy new low order portion inx h ;Point to other portion mov a,m ;Get the other portion of ;the table entry xra d ;Include with other high order portion mov d,a ;Move back into D pop h ;And H inx h ;Point to next character jmp crccl0 ;Go get next character crccl1: pop b ;Restore B pop h ;And HL ret ;And return, DE=CRC-CCITT ; inchr: ; Input character from remote line or keyboard ; push h push b inchr2: call inrdy ;Get port status jc inchr3 ;we have one call break ;see if char from keyboard jnc inchr2 ;nothing, check remote lne call conind ;get Keyboard-Input cpi cr ;Carriage return? jz inchr4 ;take only Carriage returns ; ;Here if not a cr, check other possibilities ; cpi eof ;Control-Z? jz inchr5 ;Yes, go flag it cpi abort ;Control-C? jz usrbrk ;re-enter, he wants to get out jmp inchr2 ;No, try for another character inchr5: adi '@' ;Convert to printing range sta czseen ;Flag we saw a control-Z inchr4: pop b ;Restore B pop h ;And H ret ;And return inchr3: call rcvchr ;we got a char at COMM-Port pop b pop h ; rskp: ;Jumping to this location is like retskp. It assumes ;the instruction after the call is a jmp addr. ; pop h ;Get the return address. inx h ;Increment by three. inx h inx h pchl ; r: ;Jumping here is the same as a ret. ; ret ; errchk: ; Check error packet ; cpi 'E' ;Is it an error packet. cz error jmp @abort ; Zstate: ; Check error, set Z state if not ; cpi true ;Is it EOF? jnz @abort ;If not give up. mvi a,'Z' ;Set the state to EOF. sta state ret ; errmsg: ; Tell error, cannot get ACK ; lxi d,erms14 call error3 ;Display ermsg jmp @abort ;Change the state to abort. ; ptchr: ;Output the chars in a packet. ; sta temp1 ;Save the size. lxi h,data ;Beginning of received packet data. shld outpnt ;Remember where we are. lda rquote mov b,a ;Keep the quote char in b. mvi c,0 ;Assume no 8-bit quote char lda quot8 ;Doing 8-bit quoting? ora a jz ptchr1 ;No, keep going lda qbchr ;Else get 8-bit quote char mov c,a ;Keep this in c ptchr1: lxi h,temp1 dcr m ;Decrement # of chars in packet. jm rskp ;Return successfully if done. lxi h,chrcnt;Number of chars remaining in dma. dcr m ;Decrement. jp ptchr2 ;Continue if space left. call outbuf ;Output it if full. jmp r ; Error return if disk is full. ptchr2: lhld outpnt ;Get position in output buffer. mov a,m ;Grab a char. inx h shld outpnt ;and bump pointer. mvi e,0 ;Assume nothing to OR in. cmp c ;Is it the binary quote char? jnz ptch2a ;No, keep going mvi e,80h ;Include parity bit lda temp1 dcr a sta temp1 ;Decrement character count mov a,m ;Get next character inx h shld outpnt ptch2a: cmp b ;Is it the quote char? jnz ptchr3 ;Changed to ptchr3 ;so includes parity mov a,m ;Get the quoted character inx h shld outpnt ;and bump pointer. lxi h,temp1 dcr m ;Decrement # of chars in packet. mov d,a ;Save the char. ani 80h ;Turn off all but the parity bit. ora e ;Let parity come from either (???) mov e,a ;Save the parity bit. mov a,d ;Get the char. ani 7fh ;Turn off the parity bit. cmp b ;Is it the quote char? jz ptchr3 ;If so just go write it out. cmp c ;Maybe it's the 8-bit ;prefix character? jz ptchr3 ;Then don't controllify. mov a,d ;Get the char. adi '@' ;Make the character a control ;char again. ani 7fh ;Modulo 128. ptchr3: ora e ;Or in the parity bit. ptchr4: lhld bufpnt ;Destination buffer. mov m,a ;Store it. inx h shld bufpnt ;Update the pointer jmp ptchr1 ;and loop to next char. ; outbuf: ;output the buffer, reset bufpnt and chrcnt ; lxi d,fcb call dskwrt ;Write the record. jnc outbf1 ;Successfull. lxi d,erms11 call error3 ret outbf1: lxi h,dma ;Addr for beginning. shld bufpnt ;Store addr for beginning. mvi a,reclng-1;Buffer size. sta chrcnt ;Number of chars left. jmp rskp ; gtchr: ;Get the chars from the file. ; lda squote ;Get the quote char. mov c,a ;Keep quote char in c. lda filflg ;Get the file flag. ora a ;Is there anything in the DMA? jz gtchr0 ;Yup, proceed. mvi b,0 ;No chars yet. call inbuf jmp gtceof ;No more chars, go return EOF. gtchr0: lda curchk ;Get current block check type sui '1' ;Get the extra overhead mov b,a ;Get a copy lda spsiz ;Get the maximum packet size. sui 5 ;Subtract the overhead. sub b ;Determine max packet length sta temp1 ;This is the number of chars ;we are to get. lxi h,filbuf;Where to put the data. shld cbfptr ;Remember where we are. mvi b,0 ;No chars. gtchr1: lda temp1 dcr a ;Decrement the number of chars left. jp gtchr2 ;Go on if there is more than one left. mov a,b ;Return the count in A. jmp rskp gtchr2: sta temp1 lda chrcnt ;Space left in the DMA. dcr a jm gtchr3 sta chrcnt jmp gtchr4 gtchr3: call inbuf ;Get another buffer full. jmp gtch30 ; If no more return what we got. jmp gtchr4 ;If we got some, proceed. gtch30: mov a,b ;Return the count in A. ora a ;Get any chars? jnz rskp ;If so return them. jmp gtceof ;If not, say we found ;the end of the file. gtchr4: lhld bufpnt ;Position in DMA. mov a,m ;Get a char from the file. inx h shld bufpnt mov d,a ;Save the char. ani 80h ;Turn off all but parity. mov e,a ;Save the parity bit. jz gtch4a ;No parity, skip this check... lda quot8 ;Doing eighth-bit quoting? ora a jz gtch4a ;No, just proceed normally lda temp1 ;Get space remaining cpi 2 ;3 chrs left (one cnted already)? jm gtchr9 ;No, skip this dcr a ;Decrement space remaining sta temp1 ;Put back. lhld cbfptr ;Position in character buffer. lda qbchr ;Get quote character mov m,a ;Put the quote char in the buffer inx h ;Increment destination ;buffer pointer shld cbfptr ;Store the pointer back inr b ;Increment the char count. mvi e,0 ;No parity bit to OR in. gtch4a: mov a,d ;Restore the char. ani 7fh ;Turn off the parity. mov d,a ;Save here for later... cpi ' ' ;Compare to a space. jm gtchr5 ;If less then its a control char, ;handle it. cpi dell ;Is the char a delete? jz gtchr5 ;Go quote it. lda quot8 ; Are we doing 8th-bit quoting? ora a jz gtch4c ; if not, skip this test and restore ; character. lda qbchr ; get 8th-bit quote character cmp d ; same as current character? jz gtch4b ; yes, have to quote it... gtch4c: mov a,d ; no. get character back again. cmp c ;Is it the quote char? jnz gtchr8 ;If not proceed. gtch4b: lxi h,temp1 ;Point to char count dcr m ;Decrement ;(know room for at least one) lhld cbfptr ;Position in character buffer. mov m,c ;Put the (quote) char in the buffer. inx h shld cbfptr inr b ;Increment the char count. mov a,d ;Restore character again jmp gtchr8 gtchr5: ora e ;Turn on the parity bit. cpi eof ;Is it a ^Z? jnz gtchr7 ;If not just proceed. lda modflg ;Was the file created by CPM? cpi 1 ;in ASCII-mode ? jz gtch52 ;First Control-Z stops text lda eoflag ;EOF flag set? ora a jz gtchr6 ;If not just go on. lda modflg ;Was the file created by CPM? cpi 2 ;in BINARY (same as default) jz gtchr6 ;Yes ;(this code currently does the same) lhld bufpnt ;since CHRCNT is ZERO at EOF-time lda chrcnt ;(set by INBUF5 B.G.E) mov d,a ;Get the number of chars left ;in the DMA. gtch51: dcr d mov a,d jp gtch53 ;Any chars left? gtch52: xra a ;If not, get a zero. sta chrcnt ;Say no more chars in buffer. mov a,b ;Return the count in A. jmp rskp gtch53: mov a,m ;Get the next char. inx h ;Move the pointer. cpi eof ;Is it a ^Z? jz gtch51 ;If so see if they rest are. gtchr6: mvi a,eof ;Restore the ^Z. gtchr7: sta temp2 ;Save the char. lxi h,temp1 ;Point to the char total remaining. dcr m ;Decrement it. lhld cbfptr ;Position in character buffer. mov m,c ;Put the quote in the buffer. inx h shld cbfptr inr b ;Increment the char count. lda temp2 ;Get the control char back. adi '@' ;Make the non-control. ani 7fh ;Modulo 128 gtchr8: lhld cbfptr ;Position in character buffer. ora e ;Or in the parity bit. mov m,a ;Put the char in the buffer. inx h shld cbfptr inr b ;Increment the char count. jmp gtchr1 ;Go around again. ; gtchr9: ; Not enough room left in buffer... ; lhld bufpnt dcx h shld bufpnt ;Back up over last character lxi h,chrcnt;Point to character count inr m ;Increment it mov a,b ;Count of chars transferred jmp rskp ;Return it gtceof: mvi a,true ;Get a minus one. ret ; inbuf: ; Fill buffer ; lda eoflag ;Have we reached the end? ora a jz inbufa ;no mvi b,0 ret ;Return if set. inbufa: push b push d push h lxi h,chrcnt;Reset character count. lda filflg ;Get the file flag. ora a ;Has there ever been anything ;in the DMA? jz inbuf1 ;If so just set it. mvi m,reclng;If not set it the buffer size. xra a ;Zero the flag. sta filflg jmp inbuf2 inbuf1: mvi m,reclng-1;ELse set it to one less than ;the buffer size. inbuf2: lxi h,dma ;Set the buffer pointer. shld bufpnt lxi d,fcb call dskred ;Read a record jnc inbuf5 ;No Carry => read O.K. ;we either hit EOF or an ERROR ;more data, restore and rskp mvi a,0 sta chrcnt ;say no more chars in buffer mvi a,true sta eoflag ;Set the EOF flag. inbuf5: pop h pop d pop b jnc rskp ret ;Either EOF or ERROR => finish ;with NON-skip return ; usrbrk: ; We got a Ctrl-C while sending, so exit ; pop b pop h lxi d,inms12 finish: push psw push d lxi d,scrend call strbi0 ; Set cursor pop d pop psw lhld errstk ; Get callers stack sphl lhld errdo ; And PC pchl ; Exit ; ***** PART 4 : the DATA FIELD ***** dseg crctab: dw 00000h,01081h,02102h,03183h,04204h,05285h dw 06306h,07387h,08408h,09489h,0a50ah,0b58bh dw 0c60ch,0d68dh,0e70eh,0f78fh crctb2: dw 00000h,01189h,02312h,0329bh,04624h,057adh dw 06536h,074bfh,08c48h,09dc1h,0af5ah,0bed3h dw 0ca6ch,0dbe5h,0e97eh,0f8f7h if german inms12: db 'KERMIT Transfer abgebrochen',cr,lf,0 inms13: db 'Unterbrechung',cr,lf,0 inms22: db 'Warten auf Leitung...',0 inms23: db 'Sendung...',0 inms24: db 'Empfang...',0 infms3: db 'Komplett',cr,lf,0 infms4: db cr,lf,'Fehler',0 ermes4: db '?Initialisierung kann nicht empfangen werden' db cr,lf,0 ermes5: db '?Dateiname kann nicht empfangen werden' db cr,lf,0 ermes6: db '?End Of File kann nicht empfangen werden' db cr,lf,0 erms10: db '?Daten k|nnen nicht empfangen werden',cr,lf,0 erms11: db '?Diskette voll',cr,lf,0 erms14: db '?ACK kann nicht epfangen werden vom Host' db cr,lf,0 screrr: poscur 5,10 db 'Fehler :' poscur 5,24 db 0 outln2: poscur 2,0 db 'Anzahl Pakete :',cr,lf db 'Anzahl Versuche :',cr,lf db 'Aktueller Status :',cr,0 else inms12: db 'KERMIT transfer cancelled',cr,lf,0 inms13: db 'Interrupted',cr,lf,0 inms22: db 'Waiting for remote line...',0 inms23: db 'Sending...',0 inms24: db 'Receiving...',0 infms3: db 'Completed',cr,lf,0 infms4: db 'Failed',cr,lf,0 ermes4: db '?Unable to receive initiate',cr,lf,0 ermes5: db '?Unable to receive file name',cr,lf,0 ermes6: db '?Unable to receive end of file',cr,lf,0 erms10: db '?Unable to receive data',cr,lf,0 erms11: db '?Disk full',cr,lf,0 erms14: db '?Unable to receive an acknowledgement from ' db 'the host',cr,lf,0 screrr: poscur 5,10 db 'Error :' poscur 5,24 db 0 outln2: poscur 2,0 db 'Number of packets:',cr,lf db 'Number of retries:',cr,lf db 'Current state :',cr,0 endif;german scrnp: poscur 2,24 ;Place for number of packets. db 0 scrnrt: poscur 3,24 ;Place for number of retries. db 0 scrst: poscur 4,24 ;Place for status. db 0 scrend: poscur 7,1 ;End of KERMIT db 0 clrlin: if not debug db esc,'K' ;Clear line. endif;NOT debug db 0 packet: ds 4 ;Packet (data is part of it). data: ds 90 ;Data and checksum field of packet. argblk: ds 32 ;Used for subroutine arguments curchk: db dschkt ;Current 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. chrcnt: ds 1 ;Number of chars in the file buffer. bufpnt: ds 2 ;Position in file buffer. inichk: db dschkt ;Agreed upon checksum type rpsiz: db drpsiz ;Receive packet size. rtime: db drtime ;Receive time out. rpad: db drpad ;Receive padding. rpadch: db drpadc ;Receive padding char. reol: db dreol ;Receive EOL char. rquote: db drquot ;Receive quote char. qbchr: db '&' ;Binary quote character. recpkt: ds 101 ;Receive packet storage ;(use the following). recpkx: db cr,0 ;= = = buffer limit temp1: ds 1 ;Temporary storage temp2: ds 1 temp3: ds 1 temp4: ds 1 spad: db dspad ;Send padding. spadch: db dspadc ;Send padding char. seol: db dseol ;Send EOL char. squote: db dsquot ;Send quote char. spsiz: db dspsiz ;Send packet size. chktyp: db dschkt ;Checksum type desired modflg: db 1 ;File was created by CPM. quot8: db 0 ;Non-zero if doing 8-bit quoting fcbptr: ds 2 ;Position in FCB. datptr: ds 2 ;Position in packet data buffer. eoflag: ds 1 ;EOF flag;non-zero on EOF. filflg: ds 1 ;Non-zero when nothing in DMA buffer. filbuf: ds 101 ;Character buffer. cbfptr: ds 2 ;Position in character buffer. size: ds 1 ;Size of data from gtchr. pktptr: ds 2 ;Position in receive packet. outpnt: ds 2 ;Position in packet. ; +++++ END OF KERMIT SUB PACKAGE +++++ end tptr: ds 2 ;Position in receive packet. outpnt: ds 2 ;Position in packet. ; +++++ END OF KERM