NEW
  AUTO 3,1
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF bin/gopher
*--------------------------------------
* mirrors.apple2.org.za
* gopherpedia.com
*--------------------------------------
				.INB inc/macros.i
				.INB inc/a2osx.i
				.INB inc/eth.i
				.INB inc/net.tcpip.i
				.INB inc/libtcpip.i
				.INB inc/libtui.i
*--------------------------------------
TIMEOUT.MAX		.EQ 250					25 sec.
BUFSIZE			.EQ 4096
*--------------------------------------
				.DUMMY
				.OR ZPBIN
ZS.START
ZPIPCfgPtr		.BS 2
ZPBufPtr		.BS 2
ZPLinePtr		.BS 2
ZPFramePtr		.BS 2

ZPnFrameLen		.BS 2

hBuf			.BS 1
hLine			.BS 1
hSocket			.BS 1
hFrame			.BS 1

TimeOut			.BS 1

hCTX			.BS 1
hSCR			.BS 1
hTBOX			.BS 1

TargetHost		.BS 2
TargetPort		.BS 2
TargetSelector	.BS 2
ZPPtr1			.BS 2
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.LIBTUI		.DA LIBTUI

L.MSG.ScrTitle0	.DA MSG.ScrTitle0
L.MSG.ScrTitle	.DA MSG.ScrTitle

L.MSG.IPKO		.DA MSG.IPKO
L.MSG.USAGE		.DA MSG.USAGE
L.MSG.CRLF		.DA MSG.CRLF
L.MSG.NULL		.DA MSG.NULL

L.MSG.CONNECT	.DA MSG.CONNECT
L.MSG.GETTING	.DA MSG.GETTING
L.MSG.OK		.DA MSG.OK
L.MSG.ERROR		.DA MSG.ERROR
L.MSG.GOTO		.DA MSG.GOTO

J.items2Buf		.DA CS.Net.File2Buf
				.DA CS.Net.Dir2Buf
				.DA CS.Net.Search2Buf
				.DA CS.Net.Info2Buf
				
J.items2HL		.DA CS.Net.File2HL
				.DA CS.Net.Dir2HL
				.DA CS.Net.Search2HL
				.DA CS.Net.Info2HL				
				.DA 0
*--------------------------------------
CS.INIT			>LDYA L.LIBTCPIP
				>SYSCALL LoadLib
				bcs .9

				sta hLIBTCPIP

				>LDYA L.LIBTUI
                >SYSCALL LoadLib
                bcs .9

                sta hLIBTUI

.9
CS.INIT.RTS		rts
*--------------------------------------
CS.RUN.USAGE	>LDYA L.MSG.USAGE
				>SYSCALL PutS
				lda #E.SYN
				sec
				rts
*--------------------------------------
CS.RUN			jsr CS.Net.Init
				bcs CS.INIT.RTS

				lda #1
				>SYSCALL ArgV
				bcs CS.RUN.USAGE

				phy
				pha

				>PUSHEA.G NET.HyperLink+1

				pla
				>PUSHA
				pla
				>PUSHA
				>SYSCALL strcpy

				>LDYAI BUFSIZE
				>SYSCALL GetMem
				bcs CS.INIT.RTS

				stx hBuf

				>LDYAI 256
				>SYSCALL GetMem
				bcs CS.INIT.RTS

				>STYA ZPLinePtr
				stx hLine

				jsr CS.Scr.Init
				bcs CS.INIT.RTS
*--------------------------------------
CS.RUN.LOOP0	jsr CS.Scr.SetStatusConn
				bcs CS.RUN.LOOP.9

				jsr CS.Net.ParseHL
				jsr CS.Scr.SetStatusOkErr
				bcs CS.RUN.LOOP

				jsr CS.Net.Connect
				jsr CS.Scr.SetStatusOkErr
				bcs CS.RUN.LOOP

				jsr CS.Net.Get
				jsr CS.Scr.SetStatusOkErr
				bcs CS.RUN.LOOP

				jsr CS.Scr.SetTitle
				jsr CS.Scr.SetBuf
				jsr CS.Scr.SetStatusOkErr
*--------------------------------------
CS.RUN.LOOP		>SLEEP 

				lda hSCR
                >LIBCALL hLIBTUI,LIBTUI.Exec
                bcs CS.RUN.LOOP.9

				tay
				beq CS.RUN.LOOP			No Event

				cmp #3
				beq CS.RUN.LOOP.9

				cmp #EV.HL.SELECTED
				bne .1

				jsr CS.Scr.SetStatusGoto
				bcc CS.RUN.LOOP

				rts

.1				cmp #EV.HL.PRESSED
				bne CS.RUN.LOOP
				
				jsr CS.Net.GetHL
				bcc CS.RUN.LOOP0

				tay
				beq CS.RUN.LOOP

CS.RUN.LOOP.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			lda hCTX
				beq .10

				>LIBCALL hLIBTUI,LIBTUI.Close

.10				lda hLIBTUI
                beq .1

                >SYSCALL UnloadLib

.1				lda hSocket
				beq .2

				>LIBCALL hLIBTCPIP,LIBTCPIP.Shutdown

.2				lda hBuf
				beq .3

				>SYSCALL FreeMem

.3				lda hLine
				beq .4

				>SYSCALL FreeMem

.4				lda hLIBTCPIP
				beq .8

				>SYSCALL UnloadLib

.8				clc
				rts
*--------------------------------------
CS.Net.Init		>LIBCALL hLIBTCPIP,LIBTCPIP.GETCFG	is TCPIP loaded ?
				>STYA ZPIPCfgPtr
				lda (ZPIPCfgPtr)		Configured ?
				bpl .97

				ldy #S.IPCFG.IP+3
				ldx #4

.1				lda (ZPIPCfgPtr),y
				pha
				dey
				dex
				bne .1

				ldy #SA.LOCAL+S.SOCKADDR.ADDR
				ldx #4

.2				pla
				sta (pData),y
				iny
				dex
				bne .2

				lda #AF.INET
				>STA.G SA.LOCAL+S.SOCKADDR.AF
				>STA.G SA.REMOTE+S.SOCKADDR.AF

				clc
				rts

.97				>LDYA L.MSG.IPKO
				>SYSCALL PutS
				lda #E.SYN
				sec
.99				rts
*--------------------------------------
CS.Net.ParseHL	>LEA.G NET.HyperLink+1
				>STYA ZPPtr1
				>STYA TargetHost

				lda (ZPPtr1)
				beq .9

				cmp #'/'
				beq .50

				ldy #$ff

.1				iny
				lda (ZPPtr1),y
				bne .2

				jsr CS.Net.Resolve		host\0
				bcs .99

				>LDYAI 70
				>STYA TargetPort
				bra .7

.9				lda #E.SYN
				sec
.99				rts

.2				eor #':'
				beq .3

				eor #'/'
				bne .1

				lda #70
				sta TargetPort			Default PORT
				lda /70
				sta TargetPort+1
				bra .5

.3				lda #0					host:Port, stop HOST here
				sta (ZPPtr1),y

				jsr CS.Net.AddYp1Ptr1

				jsr CS.Net.Resolve
				bcs .99

				>LDYA ZPPtr1
				>SYSCALL AToI
				>STYA TargetPort

				ldy #$ff

.4				iny
				lda (ZPPtr1),y
				beq .7

				eor #'/'
				bne .4

.5				jsr CS.Net.AddYp1Ptr1
				bra .6

.50				>LDYA L.MSG.NULL
				>STYA TargetHost

.6				>LDYA ZPPtr1
				>STYA TargetSelector

				clc
				rts

.7				>LDYA L.MSG.NULL
				>STYA TargetSelector

.8				clc
				rts
*--------------------------------------
CS.Net.AddYp1Ptr1
				tya
				sec						skip :
				adc ZPPtr1
				sta ZPPtr1
				tay
				lda ZPPtr1+1
				clc
				adc #0
				sta ZPPtr1+1
				rts
*--------------------------------------
CS.Net.Resolve	lda #TIMEOUT.MAX
				sta TimeOut

.1				>SLEEP

				>PUSHEA.G SA.REMOTE+S.SOCKADDR.ADDR
				>PUSHEA.G NET.HyperLink+1
				>LIBCALL hLIBTCPIP,LIBTCPIP.HST.GetByName
				bcc .9

				ldx TimeOut
				bne .1

.9				rts
*--------------------------------------
CS.Net.Connect	>PUSHBI S.SOCKET.T.SEQPKT
				>PUSHBI 0
				>LIBCALL hLIBTCPIP,LIBTCPIP.Socket
				bcs .9

				sta hSocket

				>PUSHA
				>PUSHEA.G SA.LOCAL
				>LIBCALL hLIBTCPIP,LIBTCPIP.Bind
				bcs .9

				>LDYA TargetPort
				>STYA.G SA.REMOTE+S.SOCKADDR.PORT

				lda #TIMEOUT.MAX
				sta TimeOut

.1				>SLEEP

				>PUSHB hSocket
				>PUSHEA.G SA.REMOTE
				>LIBCALL hLIBTCPIP,LIBTCPIP.Connect
				bcc .9

				ldx TimeOut
				bne .1

.9				rts
*--------------------------------------
CS.Net.Get		>PUSHEA.G SCR.StatusBuf
				>PUSHW L.MSG.GETTING
				>PUSHW TargetSelector
				>PUSHBI 2
				>SYSCALL SPrintF
				jsr CS.Scr.SetStatus

				lda hBuf
				>SYSCALL GetMemPtr
				>STYA ZPBufPtr

				lda #0					Reset Buffer
				sta (ZPBufPtr)

				>PUSHB hSocket
				>PUSHW ZPLinePtr

				ldy #$ff

.1				iny
				lda (TargetSelector),y
				sta (ZPLinePtr),y
				bne .1

				lda #C.CR
				sta (ZPLinePtr),y
				iny

				lda #C.LF
				sta (ZPLinePtr),y
				iny

				lda #0
				sta (ZPLinePtr),y
				iny

				>PUSHYA

				>LIBCALL hLIBTCPIP,LIBTCPIP.Send
				bcs .9

				lda #0
				sta (ZPLinePtr)

.2				>SLEEP

				lda hSocket
				>LIBCALL hLIBTCPIP,LIBTCPIP.Recv
				bcc .3

				cmp #E.NODATA
				beq .2

				lda hSocket
				>LIBCALL hLIBTCPIP,LIBTCPIP.Shutdown

				stz hSocket
				
				clc
				rts

.3				jsr CS.Net.GetFrame

				jsr CS.Net.GetLines


				lda hFrame
				>SYSCALL FreeMem

				bra .2

.9				rts
*--------------------------------------
CS.Net.GetFrame	sta hFrame
				>SYSCALL GetMemPtr
				>STYA ZPFramePtr

				ldy #S.IP.TOTAL.LENGTH+1
				lda (ZPFramePtr),y
				sec
				sbc #S.TCP-S.ETH.EII
				eor #$ff
				sta ZPnFrameLen

				dey

				lda (ZPFramePtr),y
				sbc /S.TCP-S.ETH.EII
				eor #$ff
				sta ZPnFrameLen+1

				lda ZPFramePtr
				clc
				adc #S.TCP
				sta ZPFramePtr
				bcc .8

				inc ZPFramePtr+1

.8				rts
*--------------------------------------
CS.Net.GetLines	ldy #$ff

.1				iny
				lda (ZPLinePtr),y
				bne .1

.2				jsr CS.Net.GetChar
				bcs .8

				cmp #C.LF
				beq .3

				sta (ZPLinePtr),y
				iny
				bra .2

.3				lda #0
				sta (ZPLinePtr),y

				jsr CS.Net.Line2Buf

				lda #0
				sta (ZPLinePtr)
				tay
				bra .2

.8				lda #0
				sta (ZPLinePtr),y
				clc
				rts
*--------------------------------------
CS.Net.Line2Buf	lda (ZPLinePtr)

				ldx #ITEMTYPES.L

.1				cmp ITEMTYPES-1,x
				beq .2

				dex
				bne .1

				bra .6

.2				txa
				asl
				tax
				jmp (J.items2Buf-2,x)

.6				ldy #$ff

.7				iny
				lda (ZPLinePtr),y
				sta (ZPBufPtr),y
				bne .7

				tya
				clc
				adc ZPBufPtr
				sta ZPBufPtr
				bcc .8

				inc ZPBufPtr+1

.8				rts
*--------------------------------------
* hyperlinks: [[text to show]targetUrl]
*--------------------------------------
CS.Net.File2Buf
CS.Net.Dir2Buf
CS.Net.Search2Buf
				lda #'['
				jsr CS.Net.Char2Buf
				jsr CS.Net.Char2Buf

				ldy #0

				jsr CS.Net.Token2Buf

				lda #']'
				jsr CS.Net.Char2Buf

				phy						save Selector pos

				txa
				jsr CS.Net.Char2Buf		Type

				jsr CS.Net.SkipToken

				jsr CS.Net.Token2Buf	address

				lda #':'
				jsr CS.Net.Char2Buf

				jsr CS.Net.Token2Buf	port

				ply

				jsr CS.Net.Token2Buf	selector

				lda #']'
				jsr CS.Net.Char2Buf

				lda #C.CR
				jsr CS.Net.Char2Buf

				lda #0
				sta (ZPBufPtr)

				rts
*--------------------------------------
CS.Net.Info2Buf	ldy #0

				jsr CS.Net.Token2Buf

				lda #C.CR
				jsr CS.Net.Char2Buf

				lda #0
				sta (ZPBufPtr)

				rts
*--------------------------------------
CS.Net.Token2Buf
				iny
				lda (ZPLinePtr),y
				cmp #C.TAB
				beq .8

				cmp #C.CR
				beq .8

				jsr CS.Net.Char2Buf
				bra CS.Net.Token2Buf

.8				rts
*--------------------------------------
CS.Net.SkipToken
				iny
				lda (ZPLinePtr),y
				cmp #C.TAB
				beq .8

				cmp #C.CR
				beq .8

				bra CS.Net.SkipToken

.8				rts
*--------------------------------------
CS.Net.Char2Buf	sta (ZPBufPtr)

				inc ZPBufPtr
				bne .8

				inc ZPBufPtr+1

.8				rts
*--------------------------------------
CS.Net.GetChar	inc ZPnFrameLen
				bne .1

				inc ZPnFrameLen+1
				beq .9

.1				lda (ZPFramePtr)
				inc ZPFramePtr
				bne .8

				inc ZPFramePtr+1

.8				clc
				rts

.9				sec
				rts
*--------------------------------------
CS.Net.GetHL	>LDA.G NET.HyperLink
				tax
				jmp (J.items2HL-2,x)
*--------------------------------------

CS.Net.Search2HL

*--------------------------------------
CS.Net.File2HL
CS.Net.Dir2HL
CS.Net.Info2HL	clc
				rts
*--------------------------------------
CS.Scr.Init		>LIBCALL hLIBTUI,LIBTUI.Init
                bcs .99

                sta hCTX

				>PUSHA					hCTX
                >PUSHBI S.OBJ.F.bTitle+S.OBJ.F.bStatus
                >LIBCALL hLIBTUI,LIBTUI.NewScrn
                bcs .99

                sta hSCR

				jsr CS.Scr.SetTitle0
                jsr CS.Scr.SetStatus

				>PUSHB hSCR
                >PUSHBI 0    			X1
                >PUSHBI 0    			Y1
                >PUSHBI 80    			W
                >PUSHBI 22    			H
                >PUSHBI 0				F
                lda hBuf
                >SYSCALL GetMemPtr
                >PUSHYA
                >PUSHWI BUFSIZE
                >LIBCALL hLIBTUI,LIBTUI.NewTBox
.99             bcs .9

				sta hTBOX

                >LIBCALL hLIBTUI,LIBTUI.Activate
				bcs .9

				>PUSHB hTBOX
                >PUSHBI S.OBJ.pVar
                >PUSHEA.G NET.HyperLink
                >LIBCALL hLIBTUI,LIBTUI.SetProp

.9              rts
*--------------------------------------
CS.Scr.SetTitle0
				>PUSHB hSCR
                >PUSHBI S.OBJ.pTITLE
                >PUSHW L.MSG.ScrTitle0
                >LIBCALL hLIBTUI,LIBTUI.SetProp
				rts
*--------------------------------------
CS.Scr.SetTitle	>PUSHEA.G SCR.TitleBuf
				>PUSHW L.MSG.ScrTitle
				>PUSHW TargetHost
				>PUSHW TargetPort
				>PUSHW TargetSelector
				>PUSHBI 6
				>SYSCALL SPrintF

				>PUSHB hSCR
                >PUSHBI S.OBJ.pTITLE
                >PUSHEA.G SCR.TitleBuf
                >LIBCALL hLIBTUI,LIBTUI.SetProp
				rts
*--------------------------------------
CS.Scr.SetBuf	>PUSHB hTBOX
				>PUSHBI S.OBJ.pBuf
                lda hBuf
				>SYSCALL GetMemPtr
				>PUSHYA
                >LIBCALL hLIBTUI,LIBTUI.SetProp
				rts
*--------------------------------------
CS.Scr.SetStatusConn
				>PUSHEA.G SCR.StatusBuf
				>PUSHW L.MSG.CONNECT
				>PUSHEA.G NET.HyperLink+1
				>PUSHBI 2
				>SYSCALL SPrintF
				jmp CS.Scr.SetStatus
*--------------------------------------
CS.Scr.SetStatusGoto
				>PUSHEA.G SCR.StatusBuf	skip type
				>PUSHW L.MSG.GOTO
				>PUSHEA.G NET.HyperLink+1
				>PUSHBI 2
				>SYSCALL SPrintF
				bra CS.Scr.SetStatus
*--------------------------------------
CS.Scr.SetStatusOkErr
				bcc .1

				pha
				>PUSHEA.G SCR.StatusBuf
				>PUSHW L.MSG.ERROR
				pla
				pha
				>PUSHA
				>PUSHBI 1
				>SYSCALL SPrintF
				jsr CS.Scr.SetStatus
				pla
				sec
				rts

.1				>PUSHEA.G SCR.StatusBuf
				>PUSHW L.MSG.OK
				>PUSHBI 0
				>SYSCALL SPrintF
*--------------------------------------
CS.Scr.SetStatus
				>PUSHB hSCR
                >PUSHBI S.OBJ.pSTATUS
                >PUSHEA.G SCR.StatusBuf
                >LIBCALL hLIBTUI,LIBTUI.SetProp
				rts
*--------------------------------------
CS.END
LIBTCPIP		.AZ "libtcpip"
hLIBTCPIP		.BS 1
LIBTUI          .AZ "libtui"
hLIBTUI         .BS 1
*--------------------------------------
MSG.ScrTitle0	.CZ "A2osX-GOPHER - <Ctrl-Q>uit"
MSG.ScrTitle	.CZ "A2osX-GOPHER %s:%D/%s - <Ctrl-Q>uit"
*--------------------------------------
MSG.IPKO		.CZ "TCP/IP Not Loaded/Configured.\r\n"
MSG.USAGE		.CS "Usage : GOPHER <ip|host[:port][/selector]"
MSG.CRLF		.CS "\r\n"
MSG.NULL		.HS 00
MSG.CONNECT		.CZ "Connect: %s..."
MSG.GETTING		.CZ "Getting: /%s..."
MSG.OK			.CZ "Ok"
MSG.ERROR		.CZ "Error: $%h"
MSG.GOTO		.CZ "Goto: %s"
*--------------------------------------
ITEMTYPES		.AS "017i"
ITEMTYPES.L		.EQ *-ITEMTYPES
*--------------------------------------
				.DUMMY
				.OR 0
DS.START
SA.LOCAL		.BS S.SOCKADDR
SA.REMOTE		.BS S.SOCKADDR

SCR.TitleBuf	.BS 80
SCR.StatusBuf	.BS 80

NET.HyperLink	.BS 80
DS.END			.ED
*--------------------------------------
MAN
SAVE usr/src/bin/gopher.s
ASM
