STTL Packet routines - SPAK - send packet * * This routine forms and a sends out a complete packet in the * following format * * * * Input kerbf1- Pointer to packet buffer * pdlen- Length of data * pnum- Packet number * ptype- Packet type * * Output A- True or False return code * spak equ * lda #'s jsr couts tell console we are sending packet jsr qures flush que * PRINT PACKET NUMBER TO CONSOLE spaknd lda spadch * Get the padding character ldb #$00 * Init counter spakpd cmpb spad * Are we done padding? beq spakst * Yes, start sending packet inc b * No, up the index and a count by one jsr telppc * Output a padding character jmp spakpd * Go around again spakst lda #soh * Get the start-of-header char into AC jsr telppc * Send it lda pdlen * Get the data length add a #$03 * Adjust it pshs a * Save this to be added into stot add a #sp * Make the thing a character sta chksum * First item, start off chksum with it jsr telppc * Send the character puls a * Fetch the pdlen and a add it into the add a stot * ... sta stot * ... lda stot+1 * ... add a #$00 * ... sta stot+1 * ... lda pnum * Get the packet number clc * ... add a #sp * Char it pshs a * Save it in this condition add a chksum * Add this to the checksum sta chksum * ... puls a * Restore character jsr telppc * Send it lda ptype * Fetch the packet type and a #$7f * Make sure H.O. bit is off for chksum pshs a * Save it on stack add a chksum * ... sta chksum * ... puls a * Get the original character off stack jsr telppc * Send packet type ldb #$00 * Initialize data count stb datind * Hold it here spaklp ldb datind * Get the current index into the data cmpb pdlen * Check against packet data length, done? blo spakdc * Not yet, process another character jmp spakch * Go do chksum calculations spakdc ldy kerbf1 lda b,y add a chksum * ... sta chksum * ... lda b,y * Refetch data from packet buffer jsr telppc * Send it inc datind * Up the counter and a index jmp spaklp * Loop to do next character spakch lda chksum * Now, adjust the chksum to fit in 6 bits and a #$c0 * First, take bits 6 and 7 lsr a * and a shift them to the extreme right lsr a * side of the AC lsr a * ... lsr a * ... lsr a * ... lsr a * ... add a chksum * ... and a #$3f * All this should be mod decimal 64 add a #sp * Put it in printable range jsr telppc * and a send it lda seol * Fetch the eol character jsr telppc * Send that as the last byte of the packet spakcr rts * and a return STTL Packet routines - RPAK - receive a packet * * This routine receives a standard Kermit packet and a then breaks * it apart returning the individuals components in their respective * memory locations. * * Input * * Output kerbf1- Pointer to data from packet * pdlen- Length of data * pnum- Packet number * ptype- Packet type * rpak equ * * update user console with packet number lda #'r jsr couts tell console we are receiving packet rpaknd lda #$00 * Clear the sta chksum * chksum sta datind * index into packet buffer sta kerchr * and the current character input rpakfs jsr getplc * Get a char, find SOH sta kerchr * Save it cmp a #soh * Is it an SOH character? bne rpakfs * Nope, try again lda #$01 * Set up the switch for receive packet sta fld * ... rpklp1 lda fld * Get switch cmp a #$06 * Compare for <= 5 blo rpklp2 * If it still is, continue jmp rpkchk * Otherwise, do the chksum calcs rpklp2 cmp a #$05 * Check fld bne rpkif1 * If it is not 5, go check for SOH lda datind * Fetch the data index cmp a #$00 * If the data index is not null bne rpkif1 * do the same thing jmp rpkif2 * Go process the character rpkif1 jsr getplc * Get a char, find SOH sta kerchr * Save that here cmp a #soh * Was it another SOH? bne rpkif2 * If not, we don't have to resynch lda #$00 * Yes, resynch sta fld * Reset the switch rpkif2 lda fld * Get the field switch cmp a #$04 * Is it <= 3? bhs rpkswt * No, go check the different cases now lda kerchr * Yes, it was, get the character add a chksum * ... sta chksum * ... rpkswt lda fld * Now check the different cases of fld cmp a #$00 * Case 0? bne rpkc1 * Nope, try next one lda #$00 * Yes, zero the chksum sta chksum * ... jmp rpkef * and restart the loop rpkc1 cmp a #$01 * Is it case 1? bne rpkc2 * No, continue checking lda kerchr * Yes, get the length of packet sec * ... sub a #sp * Unchar it sec * ... sub a #$03 * Adjust it down to data length sta pdlen * That is the packet data length, put it there jmp rpkef * Continue on to next item rpkc2 cmp a #$02 * Case 2 (packet number)? bne rpkc3 * If not, try case 3 lda kerchr * Fetch the character sec * ... sub a #sp * Take it down to what it really is sta pnum * That is the packet number, save it jmp rpkef * On to the next packet item rpkc3 cmp a #$03 * Is it case 3 (packet type)? bne rpkc4 * If not, try next one lda kerchr * Get the character and sta ptype * stuff it as is into the packet type jmp rpkef * Go on to next item rpkc4 cmp a #$04 * Is it case 4??? bne rpkc5 * No, try last case ldb #$00 * Set up the data index stb datind * ... rpkchl ldb datind * Make sure datind is in Y cmpb pdlen * Compare to the packet data length, done? blo rpkif3 * Not yet, process the character as data jmp rpkef * Yes, go on to last field (chksum) rpkif3 cmpb #$00 * Is this the first time through the data loop? beq rpkacc * If so, SOH has been checked, skip it jsr getplc * Get a char, find SOH sta kerchr * Store it here cmp a #soh * Is it an SOH again? bne rpkacc * No, go accumulate chksum lda #$ff * Yup, SOH, go resynch packet input once again sta fld * ... jmp rpkef * ... rpkacc lda kerchr * Get the character clc * ... add a chksum * Add it to the chksum sta chksum * and save new chksum lda kerchr * Get the character again ldy kerbf1 ldb datind * Get our current data index sta b,y * Stuff the current character into the buffer inc datind * Up the index once jmp rpkchl * Go back and check if we have to do this again rpkc5 cmp a #$05 * Last chance, is it case 5? beq rpkc51 * Ok, continue jmp rpkpe * Warn user about program error rpkc51 lda chksum * Do chksum calculations and a #$c0 * Grab bits 6 and 7 lsr a * Shift them to the right (6 times) lsr a * ... lsr a * ... lsr a * ... lsr a * ... lsr a * ... clc * Clear carry for addition add a chksum * Add this into original chksum and a #$3f * Make all of this mod decimal 64 sta chksum * and resave it rpkef inc fld * Now increment the field switch jmp rpklp1 * And go check the next item rpkchk lda kerchr * Get chksum from packet sub a #sp * Unchar it cmp a chksum * Compare it to the one this Kermit generated beq rpkret * We were successful, tell the caller that lda #$06 * Store the error code sta errcod * ... *print to console the * error message,packet checksum,expected checksum,crlf ldx #err6 jsr pstr rpkfls equ * sta rtot * ... lda rtot+1 * ... add a #$00 * ... sta rtot+1 * ... lda #'T sta ptype error packet type lda #false * Set up failure return rts * and go back rpkret equ * rpkrnd lda pdlen * Get the packet data length add a rtot * 'total characters received' counter sta rtot * ... lda rtot+1 * ... add a #$00 * ... sta rtot+1 * ... lda #true * Show a successful return rts * and return rpkpe equ * * send error message to console lda #$07 * Load error code and store in errcod sta errcod * ... jmp rpkfls * Go give a false return * * Bufill - takes characters from the file, does any neccesary quoting, * and then puts them in the packet data buffer. It returns the size * of the data in the AC. If the size is zero and it hit end-of-file, * it turns on eofinp. * bufill lda #$00 * Zero sta datind * the buffer index tst filend bne bendit bufil1 tst lfnext bne flfs ldx #fcb jsr fms read char from file bne frder fcrchk cmpa #cr cr from file ? bne nchck clr linlen sta lfnext nchck bra notend bendit jmp bffchk eof detect crsubs lda #cr bra fcrchk flfs clr lfnext lda #lf bra notend and send it frder lda 1,x get error state cmpa #8 bne frder1 error bra bffchk eof frder1 jsr rpterr jsr fmscls jmp main notend tst monito beq notenm jsr couts data to console notenm sta kerchr * Got a character, save it bffqc0 cmp a #sp * Is the character less than a space? bhs bffqc1 * If not, try next possibility jmp bffctl * This has to be controlified bffqc1 cmp a #del * Is the character a del? bne bffqc2 * If not, try something else jmp bffctl * Controlify it bffqc2 cmp a squote * Is it the quote character? bne bffqc3 * If not, continue trying jmp bffstq * It was, go stuff a quote in buffer bffqc3 bra bffstf * Nope, just stuff the character itself bffctl lda kerchr *[2] Get original character back eor a #$40 * Ctl(AC) sta kerchr * Save the character again bffstq lda squote * Get the quote character ldy kerbf1 ldb datind * and the index into the buffer sta b,y * Store it in the next location inc b * Up the data index once stb datind * Save the index again bffstf inc schr * Increment the data character count bne bffsdc * ... inc schr+1 * ... bffsdc ldy kerbf1 * Get the saved character lda kerchr ldb datind * and the data index sta b,y * This is the actual char we must store incb * Increment the index stb datind * And resave it pshs b * Take this index, put it in AC puls a add a #$06 * Adjust it so we can see if it cmp a spsiz * is >= spsiz-6 bhs bffret * If it is, go return jmp bufil1 * Otherwise, go get more characters bffret lda datind * Get the index, that will be the size rts * Return with the buffer size in AC bffchk lda datind * Get the data index cmp a #$00 * Is it zero? bne bffnes * Nope, just return pshs a * Yes, this means the entire file has lda #true * been transmitted so turn on sta eofinp * the eofinp flag puls a bffnes sta filend bffne rts * Return * * Bufemp - takes a full data buffer, handles all quoting transforms * and writes the reconstructed data out to the file using calls to * FPUTC. * bufemp lda #$00 * Zero sta datind * the data index bfetol lda datind * Get the data index cmp a pdlen * Is it >= the packet data length? blo bfemor * No, there is more to come rts * Yes, we emptied the buffer, return bfemor ldy kerbf1 ldb datind * Get the current buffer index lda b,y * Fetch the character in that position sta kerchr * Save it for the moment bfeqc cmp a rquote * Is it the normal quote character bne bfeout * No, pass this stuff up inc datind * Increment the data index ldb datind * and fetch it in the Y-reg lda b,y * Get the next character from buffer sta kerchr * Save it cmp a rquote * Were we quoting a quote? beq bfeout * Yes, nothing has to be done lda kerchr *[2] Fetch back the original character eor a #$40 * No, so controlify this again sta kerchr * Resave it bfeout lda kerchr * Get the character tst monito beq bfeoum jsr couts in monitor send to screen bfeoum ldx #fcb jsr fms write char bne wder1 inc rchr * Increment the 'data characters receive' count bne bfeou1 * ... inc rchr+1 * ... bfeou1 inc datind * Up the buffer index once jmp bfetol * Return to the top of the loop wder1 jsr rpterr jsr fmscls jmp main pemsg equ * write packet contents to screen ldx kerbf1 lda #eom ldb pdlen sta b,x set eof jsr pstr string to console rts * Incn - increment the packet sequence number expected by this * Kermit. Then take that number Mod $3f. * incn psh a * Save AC lda n * Get the packet number add a #$01 * Up the number by one and a #$3f * Do this Mod $3f! sta n * Stuff the number where it belongs puls a * Restore the AC rts * and return * * Spar - This routine loads the data buffer with the init parameters * requested for this Kermit. * * Input NONE * * Output @Kerbf1 - Operational parameters * * Registers destroyed A,Y * spar clr b * Clear B ldy kerbf1 stb datind *clear datind lda rpsiz * Fetch receive packet size add a #$20 * Characterize it sta b,y * Stuff it in the packet buffer inc b * Increment the buffer index lda rtime * get the timeout interval add a #$20 * Make that a printable character sta b,y * and stuff it in the buffer inc b * Advance the index lda rpad * Get the amount of padding required add a #$20 * Make that printable sta b,y * Put it in the buffer inc b * Advance index lda rpadch * Get the padding character expected eor a #$40 * Controlify it sta b,y * And stuff it inc b * Up the packet buffer index lda reol * Get the end-of-line expected add a #$20 * Characterize it sta b,y * Place that next in the buffer inc b * Advance the index lda rquote * Get the quote character expected sta b,y * Store it as-is last in the buffer inc b * Advance index lda rebq * Get eight-bit-quote character sta b,y * Stuff it into the data area rts * * Rpar - This routine sets operational parameters for the other kermit * from the init packet data buffer. * * Input @Kerbf1 - Operational parameters * * Output Operational parameters set * * Registers destroyed A,Y * rpar ldy kerbf1 * Start the data index at 0! clr b lda b,y * Start grabbing data from packet buffer sub a #$20 * ... sta spsiz * That must be the packet size of other Kermit inc b * Increment the buffer index lda b,y * Get the next item sub a #$20 * Uncharacterize that sta stime * Other Kermit's timeout interval inc b * Up the index once again lda b,y * Get next char sub a #$20 * Restore to original value sta spad * This is the amount of padding he wants inc b * Advnace index lda b,y * Next item eor a #$40 * Uncontrolify this one sta spadch * That is padding character for other Kermit inc b * Advance index lda b,y * Get next item of data cmp a #$00 * If it is equal to zero beq rpar2 * Use as a default jmp rpar3 * ... rpar2 lda #cr * Get value of sta seol * That will be the eol character jmp rpar4 * Continue rpar3 sec * ... sub a #$20 * unchar the character sta seol * That is the eol character other Kermit wants rpar4 inc b * Advance the buffer index lda b,y * Get quoting character cmp a #$00 * If that is zero beq rpar5 * Use # sign as the qoute character jmp rpar6 * Otherwise, give him what he wants rpar5 lda #'# * Load # sign rpar6 sta squote * Make that the other Kermit's quote character inc b * Advance the index lda b,y * Get 8-bit-quoting character sta sebq * Store it - a higher level routine will work * out how to use it rts * Return * * Nakit - sends a standard NAK packet out to the other Kermit. * * Input NONE * * Output NONE * nakit lda #$00 * Zero the packet data length sta pdlen * ... lda #'N * Set up a nak packet type sta ptype * ... jsr spak * Now, send it rts * Return STTL End of Kermit-65 Source end start