NEW AUTO 3,1 .LIST OFF .OP 65C02 .OR $2000 .TF bin/irc *-------------------------------------- .INB inc/macros.i .INB inc/a2osx.i .INB inc/mli.i .INB inc/eth.i .INB inc/libtcpip.i *-------------------------------------- TIMEOUT.MAX .EQ 250 25 sec. MSGSIZE .EQ 4096 TEXTMAX .EQ 240 *-------------------------------------- * https://tools.ietf.org/html/rfc2812#section-3.3 *-------------------------------------- .DUMMY .OR ZPBIN ZS.START ZPPtr1 .BS 2 bEscMode .BS 1 bJoin .BS 1 TimeOut .BS 1 hSocket .BS 1 TextPtr .BS 1 TextLen .BS 1 ZPRespPtr .BS 2 ZPMsg .BS 2 ZPMsgPtr .BS 2 ZPOutputBufPtr .BS 2 ZPMsgPfxPtr .BS 2 ZPMsgCmdPtr .BS 2 ZPMsgArgPtr .BS 2 ZPMsgExtPtr .BS 2 BufPtr .BS 1 BufLen .BS 1 ZPBufPtr .BS 2 bPendingMsg .BS 1 ZS.END .ED *-------------------------------------- * File Header (16 Bytes) *-------------------------------------- CS.START cld jmp (.1,x) .DA #$61 6502,Level 1 (65c02) .DA #1 BIN Layout Version 1 .DA #S.PS.F.EVENT S.PS.F .DA #0 .DA CS.END-CS.START Code Size (without Constants) .DA DS.END-DS.START Data Segment Size .DA #64 Stack Size .DA #ZS.END-ZS.START Zero Page Size .DA 0 *-------------------------------------- .1 .DA CS.INIT .DA CS.RUN .DA CS.DOEVENT .DA CS.QUIT L.LIBTCPIP .DA LIBTCPIP L.SA.LOCAL .DA SA.LOCAL L.SA.REMOTE .DA SA.REMOTE L.SA.REMOTE.AD .DA SA.REMOTE+S.SOCKADDR.ADDR L.MSG.IPKO .DA MSG.IPKO L.MSG.USAGE .DA MSG.USAGE L.MSG.UNKNOWN .DA MSG.UNKNOWN L.MSG.HOSTOK .DA MSG.HOSTOK L.MSG.SKTKO .DA MSG.SKTKO L.MSG.SKTOK .DA MSG.SKTOK L.MSG.SKTERR .DA MSG.SKTERR L.MSG.REGISTER .DA MSG.REGISTER L.MSG.JOIN .DA MSG.JOIN L.MSG.TOPBAR .DA MSG.TOPBAR L.MSG.STATUSBAR .DA MSG.STATUSBAR L.MSG.STATUSBARMSG .DA MSG.STATUSBARMSG L.MSG.NULL .DA MSG.NULL L.IRC.REGISTER .DA IRC.REGISTER L.IRC.JOIN .DA IRC.JOIN L.IRC.JOINKEY .DA IRC.JOINKEY L.IRC.PONG .DA IRC.PONG L.IRC.PART .DA IRC.PART L.IRC.NAMES .DA IRC.NAMES L.IRC.PRIVMSG .DA IRC.PRIVMSG L.SEQ.INIT .DA SEQ.INIT L.SEQ.BAR .DA SEQ.BAR L.SEQ.TXTCLR .DA SEQ.TXTCLR L.SEQ.PRIVMSG .DA SEQ.PRIVMSG L.SEQ.INFOMSG .DA SEQ.INFOMSG L.SEQ.DUMPMSG .DA SEQ.DUMPMSG L.SEQ.RESET .DA SEQ.RESET L.IRC.CMDS .DA IRC.CMDS J.IRC.CMDS .DA CS.RUN.CMD.PING .DA CS.RUN.CMD.JOIN .DA CS.RUN.CMD.PART .DA CS.RUN.CMD.QUIT .DA CS.RUN.CMD.PRIVMSG .DA CS.RUN.CMD.MODE .DA CS.RUN.CMD.001 .DA CS.RUN.CMD.353 .DA CS.RUN.CMD.375 .DA CS.RUN.CMD.372 .DA CS.RUN.CMD.376 J.ESC .DA CS.RUN.CHARIN.LEFT .DA CS.RUN.CHARIN.DOWN .DA CS.RUN.CHARIN.UP .DA CS.RUN.CHARIN.RIGHT .DA 0 *-------------------------------------- CS.INIT >LDYA L.LIBTCPIP >SYSCALL LoadLib bcs .9 sta hLIBTCPIP .9 CS.INIT.RTS rts *-------------------------------------- CS.RUN jsr CS.RUN.CheckTCPIP bcs CS.INIT.RTS jsr CS.RUN.CheckArgs bcs CS.INIT.RTS jsr CS.RUN.Connect bcs CS.INIT.RTS jsr CS.RUN.GetBuffers bcs CS.INIT.RTS jsr CS.RUN.SCRSETUP bcs CS.INIT.RTS jsr CS.RUN.Register bcs CS.INIT.RTS CS.RUN.LOOP >SLEEP jsr CS.RUN.GetMsg bcs .9 bne .2 jsr CS.RUN.SplitMsg bcs .2 jsr CS.RUN.ProcessMsg bcs .9 >SLEEP .2 ldy #S.PS.hStdIn lda (pPS),y >SYSCALL FEOF bcs .9 tay bne CS.RUN.LOOP EOF = true, no char from STDIN >SYSCALL GetChar bcs .9 jsr CS.RUN.CHARIN bcc CS.RUN.LOOP .9 php pha >PUSHW L.SEQ.RESET >PUSHBI 0 >SYSCALL PrintF pla plp rts *-------------------------------------- CS.RUN.CheckTCPIP >LIBCALL hLIBTCPIP,LIBTCPIP.GETCFG is TCPIP loaded ? bcs .9 >STYA ZPPtr1 lda (ZPPtr1) Configured ? bpl .99 ldy #S.IPCFG.IP+3 ldx #3 .1 lda (ZPPtr1),y sta SA.LOCAL+S.SOCKADDR.ADDR,x dey dex bpl .1 rts .99 >LDYA L.MSG.IPKO >SYSCALL PutS lda #E.SYN sec .9 rts *-------------------------------------- CS.RUN.CheckArgs ldy #S.PS.ARGC lda (pPS),y cmp #3 bcs .1 >LDYA L.MSG.USAGE >SYSCALL PutS lda #E.SYN sec rts .1 lda #TIMEOUT.MAX sta TimeOut .2 >PUSHW L.SA.REMOTE.AD lda #1 >SYSCALL ArgV >PUSHYA >LIBCALL hLIBTCPIP,LIBTCPIP.HST.GetByName bcc .3 >SLEEP lda TimeOut bne .2 >PUSHW L.MSG.UNKNOWN lda #1 >SYSCALL ArgV >PUSHYA >PUSHBI 2 >SYSCALL PrintF lda #ERR.SKT.NOCONN sec rts .3 lda #2 >SYSCALL ArgV >SYSCALL AToI >STYA SA.REMOTE+S.SOCKADDR.PORT >PUSHW L.MSG.HOSTOK ldx #0 .4 >PUSHB SA.REMOTE+S.SOCKADDR.ADDR,x inx cpx #4 bne .4 >PUSHW SA.REMOTE+S.SOCKADDR.PORT lda #1 >SYSCALL ArgV >PUSHYA >PUSHBI 8 >SYSCALL PrintF rts *-------------------------------------- CS.RUN.Connect >PUSHBI S.SOCKET.T.STREAM >PUSHBI 0 no protocol >LIBCALL hLIBTCPIP,LIBTCPIP.Socket bcs .9 sta hSocket >PUSHA >PUSHW L.SA.LOCAL >LIBCALL hLIBTCPIP,LIBTCPIP.Bind bcs .9 lda #TIMEOUT.MAX sta TimeOut .1 >SLEEP >PUSHB hSocket >PUSHW L.SA.REMOTE >LIBCALL hLIBTCPIP,LIBTCPIP.Connect bcc .8 ldx TimeOut bne .1 .9 pha >LDYA L.MSG.SKTKO >SYSCALL PutS pla sec rts .8 >PUSHW L.MSG.SKTOK >PUSHBI 0 >SYSCALL PrintF rts *-------------------------------------- CS.RUN.GetBuffers >LDYAI 256 >SYSCALL GetMem bcs .9 >STYA ZPBufPtr txa >STA.G hBufBuf >LDYAI MSGSIZE >SYSCALL GetMem bcs .9 >STYA ZPMsg txa >STA.G hMsgBuf >LDYAI 384 >SYSCALL GetMem bcs .9 >STYA ZPRespPtr txa >STA.G hRespBuf >LDYAI 256 >SYSCALL GetMem bcs .9 >STYA ZPOutputBufPtr txa >STA.G hOutputBuf .9 rts *-------------------------------------- CS.RUN.Register >LDYA L.MSG.REGISTER jsr CS.RUN.STATUSMSG >PUSHW ZPRespPtr >PUSHW L.IRC.REGISTER lda #3 nickname >SYSCALL ArgV >PUSHYA lda #3 nickname >SYSCALL ArgV >PUSHYA lda #3 nickname >SYSCALL ArgV >PUSHYA lda #3 nickname >SYSCALL ArgV >PUSHYA >PUSHBI 8 >SYSCALL SPrintF bcs .9 jsr CS.RUN.SendMsg .9 rts *-------------------------------------- CS.RUN.GetMsg bit bPendingMsg bmi .10 >LDYA ZPMsg >STYA ZPMsgPtr .10 ldy BufLen bne .2 .1 >PUSHB hSocket >PUSHW ZPBufPtr >PUSHWI 255 >LIBCALL hLIBTCPIP,LIBTCPIP.Read bcs .7 sty BufLen stz BufPtr .2 ldy BufPtr lda (ZPBufPtr),y cmp #C.CR beq .3 cmp #C.LF beq .6 sta (ZPMsgPtr) inc ZPMsgPtr bne .3 inc ZPMsgPtr+1 .3 inc BufPtr dec BufLen bne .2 bra .1 .6 inc BufPtr Skip LF dec BufLen stz bPendingMsg lda #0 sta (ZPMsgPtr) will exit with Z clc rts .7 cmp #E.NODATA bne .9 .8 lda #$80 will exit with NZ sta bPendingMsg clc .9 rts *-------------------------------------- CS.RUN.SplitMsg >LDYA L.MSG.NULL >STYA ZPMsgPfxPtr >STYA ZPMsgCmdPtr >STYA ZPMsgArgPtr >STYA ZPMsgExtPtr ldy #0 ldx #0 lda (ZPMsg) cmp #':' do we have a prefix ? bne .2 lda ZPMsg clc adc #1 sta ZPMsgPfxPtr lda ZPMsg+1 adc #0 sta ZPMsgPfxPtr+1 .1 iny lda (ZPMsg),y beq .9 cmp #C.SPACE bne .1 lda #0 sta (ZPMsg),y End Of prefix iny Skip blank tya tax Save CMD start pos .2 iny lda (ZPMsg),y beq .4 .3 cmp #C.SPACE scan until end of CMD bne .2 lda #0 sta (ZPMsg),y End of CMD iny Skip blank .4 php txa clc adc ZPMsg sta ZPMsgCmdPtr lda #0 adc ZPMsg+1 sta ZPMsgCmdPtr+1 plp beq .80 tya tax Save Arg start pos lda (ZPMsg),y cmp #':' beq .71 no arg....ext .6 iny lda (ZPMsg),y beq .7 cmp #':' ARGS could be "ARG1 ARG2 ARG3" bne .6 lda #0 sta (ZPMsg),y iny Skip : .7 php txa clc adc ZPMsg sta ZPMsgArgPtr lda #0 adc ZPMsg+1 sta ZPMsgArgPtr+1 plp beq .80 lda (ZPMsg),y cmp #':' bne .8 .71 iny Skip blank .8 tya clc adc ZPMsg sta ZPMsgExtPtr lda #0 adc ZPMsg+1 sta ZPMsgExtPtr+1 .80 clc rts .9 sec rts **-------------------------------------- CS.RUN.ProcessMsg >LDYA L.IRC.CMDS >STYA ZPPtr1 ldx #0 .1 lda (ZPPtr1) beq .8 ldy #$ff .2 iny lda (ZPPtr1),y cmp (ZPMsgCmdPtr),y bne .3 ora #0 bne .2 jmp (J.IRC.CMDS,x) .3 ora #0 beq .5 .4 iny lda (ZPPtr1),y bne .4 .5 inx inx tya sec adc ZPPtr1 sta ZPPtr1 bcc .1 inc ZPPtr1+1 bra .1 .8 clc .9 rts *-------------------------------------- CS.RUN.CMD.PING >PUSHW ZPRespPtr >PUSHW L.IRC.PONG >PUSHW ZPMsgExtPtr >PUSHBI 2 >SYSCALL SPrintF bcs .9 jsr CS.RUN.SendMsg .9 rts *-------------------------------------- CS.RUN.CMD.JOIN sec ror bJoin >LDYA L.MSG.NULL jsr CS.RUN.STATUSPDATE *-------------------------------------- CS.RUN.CMD.PART CS.RUN.CMD.QUIT >PUSHW ZPRespPtr >PUSHW L.IRC.NAMES lda #4 channel >SYSCALL ArgV >PUSHYA >PUSHBI 2 >SYSCALL SPrintF bcs .9 jsr CS.RUN.SendMsg .9 rts *-------------------------------------- CS.RUN.CMD.PRIVMSG ldy #0 .1 iny lda (ZPMsgPfxPtr),y beq .2 eor #'!' bne .1 sta (ZPMsgPfxPtr),y .2 >PUSHW L.SEQ.PRIVMSG >PUSHW ZPMsgPfxPtr >PUSHW ZPMsgExtPtr >PUSHBI 4 >SYSCALL PrintF rts *-------------------------------------- CS.RUN.CMD.MODE clc rts *-------------------------------------- CS.RUN.CMD.001 jsr CS.RUN.CMD.INFO >LDYA L.MSG.JOIN jsr CS.RUN.STATUSMSG >PUSHW ZPRespPtr lda #5 key >SYSCALL ArgV bcs .1 >PUSHW L.IRC.JOINKEY lda #4 channel >SYSCALL ArgV >PUSHYA lda #5 key >SYSCALL ArgV >PUSHYA >PUSHBI 4 bra .2 .1 >PUSHW L.IRC.JOIN lda #4 channel >SYSCALL ArgV >PUSHYA >PUSHBI 2 .2 >SYSCALL SPrintF bcs .9 jsr CS.RUN.SendMsg .9 rts *-------------------------------------- CS.RUN.CMD.353 ldy #80 lda #0 sta (ZPMsgExtPtr),y >LDYA ZPMsgExtPtr RPL_NAMREPLY jmp CS.RUN.STATUSPDATE *-------------------------------------- CS.RUN.CMD.372 CS.RUN.CMD.375 CS.RUN.CMD.376 CS.RUN.CMD.INFO >PUSHW L.SEQ.INFOMSG >PUSHW ZPMsgExtPtr >PUSHBI 2 >SYSCALL PrintF rts *-------------------------------------- CS.RUN.DUMPMSG >PUSHW L.SEQ.DUMPMSG >PUSHW ZPMsgPfxPtr >PUSHW ZPMsgCmdPtr >PUSHW ZPMsgArgPtr >PUSHW ZPMsgExtPtr >PUSHBI 8 >SYSCALL PrintF rts *-------------------------------------- CS.RUN.SendMsg pha >PUSHB hSocket >PUSHW ZPRespPtr pla >PUSHYA >LIBCALL hLIBTCPIP,LIBTCPIP.Write rts *-------------------------------------- CS.RUN.SCRSETUP >PUSHW L.SEQ.INIT >PUSHBI 0 >SYSCALL PrintF bcs CS.RUN.TXTCLR.RTS jsr CS.RUN.TOPUPDATE bcs CS.RUN.TXTCLR.RTS *-------------------------------------- CS.RUN.TXTCLR lda #0 sta (pData) stz TextPtr stz TextLen stz bEscMode >PUSHW L.SEQ.TXTCLR >PUSHBI 0 >SYSCALL PrintF CS.RUN.TXTCLR.RTS rts *-------------------------------------- CS.RUN.TOPUPDATE >PUSHW ZPOutputBufPtr >PUSHW L.MSG.TOPBAR >PUSHB #K.VER >PUSHB /K.VER lda #1 >SYSCALL ArgV >PUSHYA lda #2 >SYSCALL ArgV >PUSHYA lda #3 >SYSCALL ArgV >PUSHYA >PUSHBI 8 >SYSCALL SPrintF >PUSHW L.SEQ.BAR >PUSHBI 1 >PUSHW ZPOutputBufPtr >PUSHBI 3 >SYSCALL PrintF rts *-------------------------------------- CS.RUN.STATUSPDATE pha phy >PUSHW ZPOutputBufPtr >PUSHW L.MSG.STATUSBAR lda #4 >SYSCALL ArgV >PUSHYA ply pla >PUSHYA >PUSHBI 4 bra CS.RUN.STATUS *-------------------------------------- CS.RUN.STATUSMSG pha >PUSHW ZPOutputBufPtr >PUSHW L.MSG.STATUSBARMSG pla >PUSHYA >PUSHBI 2 CS.RUN.STATUS >SYSCALL SPrintF >PUSHW L.SEQ.BAR >PUSHBI 21 >PUSHW ZPOutputBufPtr >PUSHBI 3 >SYSCALL PrintF rts *-------------------------------------- CS.RUN.CHARIN bit bEscMode bpl .4 cmp #'[' beq .8 stz bEscMode ldx #EscChars.Cnt-1 .1 cmp EscChars,x beq .2 dex bpl .1 clc rts .2 txa asl tax jmp (J.ESC,x) .4 cmp #C.ESC bne .5 sec ror bEscMode .8 clc rts .5 cmp #C.SPACE bcc CS.RUN.CHARIN.CTRL cmp #C.DEL bne CS.RUN.CHARIN.INS jmp CS.RUN.CHARIN.DEL *-------------------------------------- CS.RUN.CHARIN.INS ldy TextLen cpy #TEXTMAX beq .8 inc TextLen ldy TextPtr sta (pData),y iny sty TextPtr pha lda #0 sta (pData),y pla >SYSCALL PutChar rts .8 CS.RUN.CHARIN.INS.8 clc rts *-------------------------------------- CS.RUN.CHARIN.CTRL cmp #C.CR beq CS.RUN.CHARIN.CR cmp #$14 Ctrl-T bne .8 >PUSHW ZPRespPtr >PUSHW L.IRC.PART lda #4 channel >SYSCALL ArgV >PUSHYA >PUSHBI 2 >SYSCALL SPrintF bcs .9 jsr CS.RUN.SendMsg bcs .9 lda #3 sec .9 rts .8 clc rts *-------------------------------------- CS.RUN.CHARIN.CR bit bJoin bpl CS.RUN.CHARIN.INS.8 lda TextLen beq CS.RUN.CHARIN.INS.8 >PUSHW ZPRespPtr >PUSHW L.IRC.PRIVMSG lda #4 channel >SYSCALL ArgV >PUSHYA >PUSHW pData >PUSHBI 4 >SYSCALL SPrintF bcs .9 jsr CS.RUN.SendMsg bcs .9 >PUSHW L.SEQ.PRIVMSG lda #3 nickname >SYSCALL ArgV >PUSHYA >PUSHW pData >PUSHBI 4 >SYSCALL PrintF bcs .9 jmp CS.RUN.TXTCLR .9 rts *-------------------------------------- CS.RUN.CHARIN.DEL *-------------------------------------- CS.RUN.CHARIN.LEFT clc ldy TextPtr beq .9 dey sty TextPtr lda #0 sta (pData),y lda #C.BS >SYSCALL PutChar lda #C.SPACE >SYSCALL PutChar lda #C.BS >SYSCALL PutChar .9 rts *-------------------------------------- CS.RUN.CHARIN.DOWN CS.RUN.CHARIN.UP clc rts *-------------------------------------- CS.RUN.CHARIN.RIGHT clc rts lda TextPtr cmp TextLen clc beq .9 inc sta TextPtr lda #C.FS >SYSCALL PutChar .9 rts *-------------------------------------- CS.DOEVENT lda (pEvent) bpl .9 is it a TIMER event? lda TimeOut beq .9 dec TimeOut .9 sec do not discard TIMER event rts *-------------------------------------- CS.QUIT ldy #hOutputBuf jsr .7 ldy #hRespBuf jsr .7 ldy #hMsgBuf jsr .7 ldy #hBufBuf jsr .7 lda hSocket beq .1 >LIBCALL hLIBTCPIP,LIBTCPIP.Shutdown .1 lda hLIBTCPIP beq .2 >SYSCALL UnloadLib .2 clc rts .7 lda (pData),y beq .8 >SYSCALL FreeMem .8 rts *-------------------------------------- CS.END LIBTCPIP .AZ "libtcpip" hLIBTCPIP .BS 1 MSG.IPKO .AZ "TCP/IP Not Loaded/Configured." MSG.USAGE .AZ "Usage : IRC <#channel> [key]" MSG.UNKNOWN .AZ "%s: Unknown host\r\n" MSG.HOSTOK .AZ "Connecting to %d.%d.%d.%d:%D (%s)..." MSG.SKTKO .AZ "Failed to Open Socket." MSG.SKTOK .AZ "Connected\r\n(Exit key is Ctrl-T)\r\n" MSG.SKTERR .AZ "Socket Error : $%h\r\n" MSG.REGISTER .AZ "Registering User..." MSG.JOIN .AZ "Joining Channel..." MSG.TOPBAR .AZ "A2osX IRC %d.%d Server:%s:%s Nick:%s" MSG.STATUSBAR .AZ "%s:%s" MSG.STATUSBARMSG .AS "STATUS:%s" MSG.NULL .HS 00 *-------------------------------------- EscChars .AS 'DBAC' EscChars.Cnt .EQ *-EscChars EscChars.Remap .DA #C.BS,#C.VT,#C.LF,#C.FS *-------------------------------------- IRC.REP.NOIDENT .AZ "*** No Ident response" IRC.REP.JOIN .AZ "JOIN" *-------------------------------------- IRC.CMDS .AZ "PING" .AZ "JOIN" .AZ "PART" .AZ "QUIT" .AZ "PRIVMSG" .AZ "MODE" .AZ "001" .AZ "353" .AZ "372" .AZ "375" .AZ "376" .DA #0 *-------------------------------------- IRC.REGISTER .AS "NICK %s\r\n" .AZ "USER %s %s %s :A2osX IRC\r\n" IRC.JOIN .AZ "JOIN %s\r\n" IRC.JOINKEY .AZ "JOIN %s %s\r\n" IRC.PONG .AZ "PONG :%s\r\n" IRC.PART .AS "PART %s\r\n" .AZ "QUIT :Pfff\r\n" IRC.NAMES .AZ "NAMES %s\r\n" IRC.PRIVMSG .AZ "PRIVMSG %s :%s\r\n" *-------------------------------------- SEQ.INIT .AZ "\ec\e(B\e)0\e[?7l\e[2;20r\e[22;1H\e[?7h" SEQ.BAR .AZ "\e[?7l\e7\e[%d;1H\e[7m\e[37;40m%80s\e[0m\e8\e[?7h" SEQ.TXTCLR .AZ "\e[22;1H\e[97;41m\e[K\r\n\e[K\r\n\e[K\e[22;1H" SEQ.PRIVMSG .AZ "\e7\e[20;1H\r\n\e[93;44m\e[7m%s:\e[0m\e[93;44m%s\e[K\e8" SEQ.DUMPMSG .AZ "\e7\e[20;1H\r\n\e[7m%s \e[0m%s %s %s\e8" SEQ.INFOMSG .AZ "\e7\e[20;1H\e[92;44m%s\r\n\e8" SEQ.RESET .AZ "\ec" *-------------------------------------- SA.LOCAL .DA #AF.INET S.SOCKADDR.AF .BS 1 .BS 4 S.SOCKADDR.ADDR .BS 2 S.SOCKADDR.PORT *-------------------------------------- SA.REMOTE .DA #AF.INET S.SOCKADDR.AF .BS 1 .BS 4 S.SOCKADDR.ADDR .DA 6667 *-------------------------------------- .DUMMY .OR 0 DS.START .BS TEXTMAX+1 hBufBuf .BS 1 hMsgBuf .BS 1 hRespBuf .BS 1 hOutputBuf .BS 1 DS.END .ED *-------------------------------------- MAN SAVE usr/src/bin/irc.s ASM