PR#3 PREFIX /A2OSX.SRC LOMEM $900 INC 1 AUTO 6 .LIST OFF */-------------------------------------- * #SKT.New * Create a new socket * ##In : * PUSHW = PTR to S.SOCKET template * ##Out : * YA = PTR to new S.SOCKET * X = hSocket *\-------------------------------------- SKT.New >PULLW ZPTmpPtr1 ldy #S.SOCKET.SRC.PORT+1 lda (ZPTmpPtr1),y dey ora (ZPTmpPtr1),y bne .1 jsr GetDynPort sta (ZPTmpPtr1),y txa iny sta (ZPTmpPtr1),y .1 lda hSocketTable >SYSCALL GetMemPtrA >STYA ZPTmpPtr2 lda #$ff sta TmpOffset to keep track of any free slot ldx #0 .2 lda (ZPTmpPtr2) beq .4 empty!!! cmp (ZPTmpPtr1) bne .5 not same SKT type...try next ldy #S.SOCKET.SRC.ADDR .3 lda (ZPTmpPtr1),y cmp (ZPTmpPtr2),y bne .5 iny cpy #S.SOCKET.DST.PORT+2 bne .3 lda #ERR.SKT.BUSY same one!!!!! busy... sec rts .4 lda TmpOffset bpl .5 already found an empty slot.... >LDYA ZPTmpPtr2 found one... >STYA ZPTmpPtr3 save it! stx TmpOffset .5 lda ZPTmpPtr2 clc adc #S.SOCKET sta ZPTmpPtr2 bcc .6 inc ZPTmpPtr2+1 .6 inx cpx #K.SKTTABLE.SIZE bne .2 lda TmpOffset Did we found an empty slot ? bmi .9 ldy #S.SOCKET.TEMPLATE-1 .7 lda (ZPTmpPtr1),y sta (ZPTmpPtr3),y dey bpl .7 lda (ZPTmpPtr1) cmp #S.SOCKET.SOCK.STREAM bne .8 ldy #S.SOCKET.SO lda (ZPTmpPtr1),y and #S.SOCKET.SO.ACCEPTCONN bne .8 jsr SKT.New.TCP bcs .99 .8 ldx TmpOffset >LDYA ZPTmpPtr3 clc rts .9 lda #ERR.SKT.OOS sec .99 rts *-------------------------------------- SKT.New.TCP ldy #S.SOCKET.SQ.INFREE lda #K.TCP.WSIZE sta (ZPTmpPtr3),y iny lda /K.TCP.WSIZE sta (ZPTmpPtr3),y ldy #S.SOCKET.SQ.OUTFREE lda #K.TCP.WSIZE sta (ZPTmpPtr3),y iny lda /K.TCP.WSIZE sta (ZPTmpPtr3),y lda #0 ldy #S.SOCKET.SQ.INUSED sta (ZPTmpPtr3),y iny sta (ZPTmpPtr3),y ldy #S.SOCKET.SQ.OUTUSED sta (ZPTmpPtr3),y iny sta (ZPTmpPtr3),y ldx #3 ldy #S.SOCKET.SQ.SEQNUM+3 .2 lda A2osX.TIMER16,x sta (ZPTmpPtr3),y dey dex bpl .2 >PUSHW K.TCP.WSIZE >PUSHBI 0 >SYSCALL GetMem bcs .9 txa ldy #S.SOCKET.STREAM.hInMem sta (ZPTmpPtr3),y >PUSHW K.TCP.WSIZE >PUSHBI 0 >SYSCALL GetMem bcs .9 txa ldy #S.SOCKET.STREAM.hOutMem sta (ZPTmpPtr3),y clc .9 rts */-------------------------------------- * #SKT.CloseA * Close socket * ##In : * A = hSocket * ##Out : *\-------------------------------------- SKT.CloseA cmp #K.SKTTABLE.SIZE bcs SKT.GetA.9 jsr SKT.GetA.I bcs .9 cmp #S.SOCKET.SOCK.DGRAM beq .8 cmp #S.SOCKET.SOCK.RAW beq .8 ldy #S.SOCKET.SO lda (ZPPtrSKT),y bit #S.SOCKET.SO.ACCEPTCONN beq * .8 lda #0 sta (ZPPtrSKT) clc .9 rts */-------------------------------------- * #SKT.GetA * Get Ptr to socket * ##In : * A = hSocket * ##Out : * Y,A = pS.SOCKET *\-------------------------------------- SKT.GetA cmp #K.SKTTABLE.SIZE bcs SKT.GetA.9 jsr SKT.GetA.I bcs SKT.GetA.9 >LDYA ZPPtrSKT rts SKT.GetA.I pha lda hSocketTable >SYSCALL GetMemPtrA >STYA ZPPtrSKT plx beq .8 .1 lda ZPPtrSKT clc adc #S.SOCKET sta ZPPtrSKT bcc .2 inc ZPPtrSKT+1 .2 dex bne .1 .8 lda (ZPPtrSKT) beq SKT.GetA.9 clc rts SKT.GetA.9 lda #ERR.SKT.BAD sec rts */-------------------------------------- * #SKT.GetTable * Get socket table * ##In : * ##Out : * Y,A = pS.SOCKET *\-------------------------------------- SKT.GetTable lda hSocketTable >SYSCALL GetMemPtrA clc rts */-------------------------------------- * #SKT.AcceptA * Check for an incoming connection * ##In : * A = hListeningSocket * ##Out : * A = hSocket *\-------------------------------------- SKT.AcceptA jsr SKT.GetA.I bcs .9 ldy #S.SOCKET.SO lda (ZPPtrSKT),y and #S.SOCKET.SO.ACCEPTCONN beq .99 ldy #S.SOCKET.HQ.TAIL lda (ZPPtrSKT),y ldy #S.SOCKET.HQ.HEAD cmp (ZPPtrSKT),y Queue Empty beq .9 CS pha save tail... inc cmp #S.SOCKET.HQ.MAX bne .1 lda #0 .1 ldy #S.SOCKET.HQ.TAIL sta (ZPPtrSKT),y pla clc adc #S.SOCKET.HQ tay lda (ZPPtrSKT),y clc rts .99 lda #ERR.SKT.BAD sec .9 rts */-------------------------------------- * #SKT.Write (DGRAM,STREAM,RAW) * Send block of data * ##In : * PUSHB = hSocket * PUSHW = pBuf * PUSHW = len * ##Out : * A = hFrame *\-------------------------------------- SKT.Write >PULLW ZPDataInLen >PULLW ZPDataInPtr >PULLB hSocket jsr SKT.GetA.I bcs .9 cmp #S.SOCKET.SOCK.DGRAM beq SKT.Write.UDP cmp #S.SOCKET.SOCK.STREAM bne .1 ldy #S.SOCKET.SO lda (ZPPtrSKT),y and #S.SOCKET.SO.ACCEPTCONN bne .99 jmp SKT.Write.TCP .1 cmp #S.SOCKET.SOCK.RAW bne .99 jmp SKT.Write.RAW .99 lda #ERR.SKT.BAD sec .9 rts *-------------------------------------- SKT.Write.UDP ldx #S.IP.PROTOCOL.UDP >LDYA ZPDataInLen jsr FRM.NewIP bcs .9 jsr SKT.SetFrameOutDstIP ldy #S.SOCKET.SRC.PORT lda (ZPPtrSKT),y tax iny lda (ZPPtrSKT),y ldy #S.UDP.SRCPORT sta (ZPFrameOutPtr),y iny txa sta (ZPFrameOutPtr),y ldy #S.SOCKET.DST.PORT lda (ZPPtrSKT),y tax iny lda (ZPPtrSKT),y ldy #S.UDP.DSTPORT sta (ZPFrameOutPtr),y iny txa sta (ZPFrameOutPtr),y jsr SKT.CopyDataInToOut jmp FRM.SendIP .9 rts *-------------------------------------- SKT.Write.RAW ldy #S.SOCKET.RAW.PROTO lda (ZPPtrSKT),y tax >LDYA ZPDataInLen jsr FRM.NewIP bcs .9 jsr SKT.SetFrameOutDstIP jsr SKT.CopyDataInToOut jmp FRM.SendIP .9 sec rts *-------------------------------------- SKT.Write.TCP ldy #S.SOCKET.TCP.STATUS lda (ZPPtrSKT),y cmp #S.SOCKET.TCP.STATUS.ESTBLSH bne .91 jsr SKT.AddDataToSktOut bcs .90 jsr TCP.OUT try to push, ignore error.... clc rts .90 lda #0 no data transfered sec rts .91 lda #MLI.ERR.IO sec .99 rts */-------------------------------------- * #SKT.ReadA (DGRAM,RAW) * ##In : * A = hSocket * ##Out : * A = hFrame *\-------------------------------------- SKT.ReadA jsr SKT.GetA.I bcs .9 ldy #S.SOCKET.HQ.TAIL lda (ZPPtrSKT),y tax ldy #S.SOCKET.HQ.HEAD cmp (ZPPtrSKT),y beq .99 inc cmp #S.SOCKET.HQ.MAX bne .1 lda #0 .1 ldy #S.SOCKET.HQ.TAIL sta (ZPPtrSKT),y txa clc adc #S.SOCKET.HQ tay lda (ZPPtrSKT),y clc rts .99 sec .9 rts */-------------------------------------- * #SKT.PutC (STREAM) * Write a Char To Stream * ##In : * PUSHB = hSocket * PUSHB = Char * ##Out : * A = char *\-------------------------------------- SKT.PutC sec rts */-------------------------------------- * #SKT.PutS (STREAM) * Write Line in pBuf * ##In : * PUSHB = hSocket * PUSHW = PSTR * ##Out : *\-------------------------------------- SKT.PutS sec rts */-------------------------------------- * #SKT.GetCA (STREAM) * Read a Char From Stream in A * ##In : * A = hSocket * ##Out : * A = char *\-------------------------------------- SKT.GetCA sec rts */-------------------------------------- * #SKT.GetS (STREAM) * Read a CR terminated Line in pBuf * ##In : * PUSHB = hSocket * PUSHW = pBuf * PUSHW = len * ##Out : * Y,A = bytes read *\-------------------------------------- SKT.GetS sec .HS 90 bcc */-------------------------------------- * #SKT.Read (STREAM) * Read data in pBuf * ##In : * PUSHB = hSocket * PUSHW = pBuf * PUSHW = len * ##Out : * Y,A = bytes transfered *\-------------------------------------- SKT.Read clc ror bTextMode >PULLW ZPDataOutLen >PULLW ZPDataOutPtr >PULLB hSocket jsr SKT.GetA.I bcs .99 cmp #S.SOCKET.SOCK.STREAM bne .90 bad skt ldy #S.SOCKET.SO lda (ZPPtrSKT),y and #S.SOCKET.SO.ACCEPTCONN bne .90 Bad Skt ldy #S.SOCKET.TCP.STATUS lda (ZPPtrSKT),y cmp #S.SOCKET.TCP.STATUS.ESTBLSH bne .91 IO err jsr SKT.GetDataFromSktIn bcs .99 No data... >STYA TmpOffset ldy #S.SOCKET.SQ.ACKNUM lda (ZPPtrSKT),y clc adc TmpOffset sta (ZPPtrSKT),y iny lda (ZPPtrSKT),y adc TmpOffset+1 sta (ZPPtrSKT),y iny lda (ZPPtrSKT),y adc #0 sta (ZPPtrSKT),y iny lda (ZPPtrSKT),y adc #0 sta (ZPPtrSKT),y ldy #S.SOCKET.TCP.OPTIONS lda (ZPPtrSKT),y ora #S.TCP.OPTIONS.ACK sta (ZPPtrSKT),y >LDYA TmpOffset clc rts .90 lda #ERR.SKT.BAD sec rts .91 lda #MLI.ERR.IO sec .99 rts *-------------------------------------- * PRIVATE *-------------------------------------- * ZPPtrSKT -> actual socket * A = hSocket or hFrame *-------------------------------------- SKT.AddToQueueA sta .2+1 ldy #S.SOCKET.HQ.HEAD lda (ZPPtrSKT),y tax inc cmp #S.SOCKET.HQ.MAX bne .1 lda #0 .1 ldy #S.SOCKET.HQ.TAIL cmp (ZPPtrSKT),y beq .9 Queue full!! ldy #S.SOCKET.HQ.HEAD sta (ZPPtrSKT),y txa clc adc #S.SOCKET.HQ tay .2 lda #$ff sta (ZPPtrSKT),y clc rts .9 sec rts *-------------------------------------- * From TCP.IN * Src : A,X * Dst : hOutMem/OUTTAIL *-------------------------------------- SKT.FreeDataFromSktOutAX pha ldy #S.SOCKET.SQ.OUTTAIL clc adc (ZPPtrSKT),y sta (ZPPtrSKT),y iny txa adc (ZPPtrSKT),y and /K.TCP.WSIZE-1 sta (ZPPtrSKT),y pla sta .1+1 stx .2+1 ldy #S.SOCKET.SQ.OUTFREE clc adc (ZPPtrSKT),y sta (ZPPtrSKT),y iny txa adc (ZPPtrSKT),y sta (ZPPtrSKT),y ldy #S.SOCKET.SQ.OUTUSED sec lda (ZPPtrSKT),y .1 sbc #$ff sta (ZPPtrSKT),y iny adc (ZPPtrSKT),y .2 sbc #$ff sta (ZPPtrSKT),y rts *-------------------------------------- * From TCP.IN * Src : ZPDataInPtr/ZPDataInLen * Dst : hInMem/INHEAD *-------------------------------------- SKT.AddDataToSktIn jsr SKT.GetTCB ldx ZPDataInLen cpx SKT.TCBCache+S.SOCKET.SQ.INFREE lda ZPDataInLen+1 sbc SKT.TCBCache+S.SOCKET.SQ.INFREE+1 bcc .9 Not enough room in Q lda SKT.TCBCache+S.SOCKET.STREAM.hInMem >SYSCALL GetMemPtrA >STYA ZPTmpPtr1 Make ZPTmpPtr1=buffer base lda ZPTmpPtr1 clc adc SKT.TCBCache+S.SOCKET.SQ.INHEAD sta ZPTmpPtr2 lda ZPTmpPtr1+1 adc SKT.TCBCache+S.SOCKET.SQ.INHEAD+1 sta ZPTmpPtr2+1 Make ZPTmpPtr2=base+Tail lda ZPDataInLen eor #$FF tax lda ZPDataInLen+1 eor #$FF pha ldy #0 .1 inx bne .2 pla inc beq .8 .2 lda (ZPDataInPtr),y sta (ZPTmpPtr2) iny bne .3 inc ZPDataInPtr+1 .3 inc ZPTmpPtr2 bne .4 inc ZPTmpPtr2+1 .4 inc SKT.TCBCache+S.SOCKET.SQ.INHEAD bne .1 inc SKT.TCBCache+S.SOCKET.SQ.INHEAD+1 lda SKT.TCBCache+S.SOCKET.SQ.INHEAD+1 cmp /K.TCP.WSIZE bne .1 stz SKT.TCBCache+S.SOCKET.SQ.INHEAD+1 lda ZPTmpPtr1 Dst Ptr=Buffer Base sta ZPTmpPtr2 lda ZPTmpPtr1+1 sta ZPTmpPtr2+1 bra .1 .9 sec rts .8 lda SKT.TCBCache+S.SOCKET.SQ.INFREE sec sbc ZPDataInLen sta SKT.TCBCache+S.SOCKET.SQ.INFREE lda SKT.TCBCache+S.SOCKET.SQ.INFREE+1 sbc ZPDataInLen+1 sta SKT.TCBCache+S.SOCKET.SQ.INFREE+1 lda SKT.TCBCache+S.SOCKET.SQ.INUSED clc adc ZPDataInLen sta SKT.TCBCache+S.SOCKET.SQ.INUSED lda SKT.TCBCache+S.SOCKET.SQ.INUSED+1 adc ZPDataInLen+1 sta SKT.TCBCache+S.SOCKET.SQ.INUSED+1 jsr SKT.StoreTCB clc rts *-------------------------------------- * From SKT.SEND.TCP * Src : ZPDataInPtr/ZPDataInLen * Dst : hOutMem/OUTHEAD *-------------------------------------- SKT.AddDataToSktOut jsr SKT.GetTCB ldx ZPDataInLen cpx SKT.TCBCache+S.SOCKET.SQ.OUTFREE lda ZPDataInLen+1 sbc SKT.TCBCache+S.SOCKET.SQ.OUTFREE+1 bcc .9 Not enough room in Q lda SKT.TCBCache+S.SOCKET.STREAM.hOutMem >SYSCALL GetMemPtrA >STYA ZPTmpPtr1 Make ZPTmpPtr1=buffer base lda ZPTmpPtr1 clc adc SKT.TCBCache+S.SOCKET.SQ.OUTHEAD sta ZPTmpPtr2 lda ZPTmpPtr1+1 adc SKT.TCBCache+S.SOCKET.SQ.OUTHEAD+1 sta ZPTmpPtr2+1 Make ZPTmpPtr2=base+Tail lda ZPDataInLen eor #$FF tax lda ZPDataInLen+1 eor #$FF pha ldy #0 .1 inx bne .2 pla inc beq .8 .2 lda (ZPDataInPtr),y sta (ZPTmpPtr2) iny bne .3 inc ZPDataInPtr+1 .3 inc ZPTmpPtr2 bne .4 inc ZPTmpPtr2+1 .4 inc SKT.TCBCache+S.SOCKET.SQ.OUTHEAD bne .1 inc SKT.TCBCache+S.SOCKET.SQ.OUTHEAD+1 lda SKT.TCBCache+S.SOCKET.SQ.OUTHEAD+1 cmp /K.TCP.WSIZE bne .1 stz SKT.TCBCache+S.SOCKET.SQ.OUTHEAD+1 lda ZPTmpPtr1 Dst Ptr=Buffer Base sta ZPTmpPtr2 lda ZPTmpPtr1+1 sta ZPTmpPtr2+1 bra .1 .9 sec rts .8 lda SKT.TCBCache+S.SOCKET.SQ.OUTFREE sec sbc ZPDataInLen sta SKT.TCBCache+S.SOCKET.SQ.OUTFREE lda SKT.TCBCache+S.SOCKET.SQ.OUTFREE+1 sbc ZPDataInLen+1 sta SKT.TCBCache+S.SOCKET.SQ.OUTFREE+1 lda SKT.TCBCache+S.SOCKET.SQ.OUTUSED clc adc ZPDataInLen sta SKT.TCBCache+S.SOCKET.SQ.OUTUSED lda SKT.TCBCache+S.SOCKET.SQ.OUTUSED+1 adc ZPDataInLen+1 sta SKT.TCBCache+S.SOCKET.SQ.OUTUSED+1 jsr SKT.StoreTCB clc rts *-------------------------------------- * From TCP.OUT * Src : hOutMem/OUTTAIL * Dst : ZPDataOutPtr/ZPDataOutLen *-------------------------------------- SKT.GetDataFromSktOut jsr SKT.GetTCB lda SKT.TCBCache+S.SOCKET.STREAM.hOutMem >SYSCALL GetMemPtrA >STYA ZPTmpPtr1 Make ZPTmpPtr1=buffer base lda ZPTmpPtr1 clc adc SKT.TCBCache+S.SOCKET.SQ.OUTTAIL sta ZPTmpPtr2 lda ZPTmpPtr1+1 adc SKT.TCBCache+S.SOCKET.SQ.OUTTAIL+1 sta ZPTmpPtr2+1 lda ZPDataOutLen eor #$FF tax lda ZPDataOutLen+1 eor #$FF pha ldy #0 .1 inx bne .2 pla inc beq .8 .2 lda (ZPTmpPtr2) sta (ZPDataOutPtr),y iny bne .3 inc ZPDataOutPtr+1 .3 inc ZPTmpPtr2 bne .4 inc ZPTmpPtr2+1 .4 inc SKT.TCBCache+S.SOCKET.SQ.OUTTAIL bne .1 inc SKT.TCBCache+S.SOCKET.SQ.OUTTAIL+1 lda SKT.TCBCache+S.SOCKET.SQ.OUTTAIL+1 cmp /K.TCP.WSIZE bne .1 stz SKT.TCBCache+S.SOCKET.SQ.OUTTAIL+1 lda ZPTmpPtr1 Dst Ptr=Buffer Base sta ZPTmpPtr2 lda ZPTmpPtr1+1 sta ZPTmpPtr2+1 bra .1 .8 clc rts *-------------------------------------- * From SKT.Read * In: * Src : hInMem/INTAIL * Dst : ZPDataOutPtr/ZPDataOutLen * CS : Text Mode * CC : Binary Mode * Out: * Y,A = bytes read *-------------------------------------- SKT.GetDataFromSktIn ldy #S.SOCKET.STREAM.hInMem lda (ZPPtrSKT),y >SYSCALL GetMemPtrA >STYA ZPTmpPtr1 Make ZPTmpPtr1=buffer base jsr SKT.GetTCB lda ZPTmpPtr1 clc adc SKT.TCBCache+S.SOCKET.SQ.INTAIL sta ZPTmpPtr2 lda ZPTmpPtr1+1 adc SKT.TCBCache+S.SOCKET.SQ.INTAIL+1 sta ZPTmpPtr2+1 lda ZPDataOutLen eor #$FF tax lda ZPDataOutLen+1 eor #$FF pha stz ZPTmpPtr3 Reset byte counter stz ZPTmpPtr3+1 ldy #0 .1 inx Check if room left in dest buffer bne .2 pla inc beq .7 pha .2 lda SKT.TCBCache+S.SOCKET.SQ.INTAIL eor SKT.TCBCache+S.SOCKET.SQ.INHEAD bne .3 lda SKT.TCBCache+S.SOCKET.SQ.INTAIL+1 eor SKT.TCBCache+S.SOCKET.SQ.INHEAD+1 beq .8 no more data.... .3 lda (ZPTmpPtr2) pha inc SKT.TCBCache+S.SOCKET.SQ.INTAIL bne .5 inc SKT.TCBCache+S.SOCKET.SQ.INTAIL+1 lda SKT.TCBCache+S.SOCKET.SQ.INTAIL+1 cmp /K.TCP.WSIZE bne .4 stz SKT.TCBCache+S.SOCKET.SQ.INTAIL+1 lda ZPTmpPtr1 sta ZPTmpPtr2 lda ZPTmpPtr1+1 sta ZPTmpPtr2+1 bra .5 .4 inc ZPTmpPtr2 bne .4 inc ZPTmpPtr2+1 .5 pla get back data.... bit bTextMode do we need to check CR ? bpl .6 cmp #13 beq .8 .6 sta (ZPDataOutPtr),y iny bne .61 inc ZPDataOutPtr+1 .61 inc ZPTmpPtr3 bne .1 inc ZPTmpPtr3+1 bra .1 .7 bit bTextMode here, bacause dst buf full.... bmi .9 ....and TextMode selected, NO ending CR found .8 pla discard byte counter HI lda ZPTmpPtr3 Do we have transfered something? eor ZPTmpPtr3+1 beq .9 lda SKT.TCBCache+S.SOCKET.SQ.INFREE clc adc ZPTmpPtr3 sta SKT.TCBCache+S.SOCKET.SQ.INFREE lda SKT.TCBCache+S.SOCKET.SQ.INFREE+1 adc ZPTmpPtr3+1 sta SKT.TCBCache+S.SOCKET.SQ.INFREE+1 lda SKT.TCBCache+S.SOCKET.SQ.INUSED sec sbc ZPTmpPtr3 sta SKT.TCBCache+S.SOCKET.SQ.INUSED lda SKT.TCBCache+S.SOCKET.SQ.INUSED+1 sbc ZPTmpPtr3+1 sta SKT.TCBCache+S.SOCKET.SQ.INUSED+1 jsr SKT.StoreTCB >LDYA ZPTmpPtr3 clc rts .9 lda #0 NO DATA sec rts *-------------------------------------- SKT.GetTCB ldy #S.SOCKET-1 .1 lda (ZPPtrSKT),y sta SKT.TCBCache,y dey bpl .1 rts *-------------------------------------- SKT.StoreTCB ldy #S.SOCKET-1 .1 lda SKT.TCBCache,y sta (ZPPtrSKT),y dey bpl .1 rts *-------------------------------------- SKT.SetFrameOutDstIP ldy #S.SOCKET.DST.ADDR ldx #4 .1 lda (ZPPtrSKT),y pha iny dex bne .1 ldy #S.IP.DST+3 ldx #4 .2 pla sta (ZPFrameOutPtr),y dey dex bne .2 rts *-------------------------------------- SKT.CopyDataInToOut lda ZPDataInPtr+1 pha lda ZPDataOutPtr+1 pha lda ZPDataInLen eor #$ff tax lda ZPDataInLen+1 eor #$ff pha ldy #0 .1 inx bne .2 pla inc beq .9 pha .2 lda (ZPDataInPtr),y sta (ZPDataOutPtr),y iny bne .1 inc ZPDataInPtr+1 inc ZPDataOutPtr+1 bne .1 .9 pla sta ZPDataOutPtr+1 pla sta ZPDataInPtr+1 rts *-------------------------------------- MAN SAVE LIB/LIBTCPIP.S.SKT LOAD LIB/LIBTCPIP.S ASM