Code:
INK 7 : PAPER 0 : BORDER 0 : CLS
#include <times2.bas>
#include <print42.bas>
#include <print64.bas>
#include <input.bas>
#include <keys.bas>
dim thekeys$: let thekeys$=" "
let length=60 : let rowx=0 : let xx$="<"
pause 10
plot 0,0 : draw 255,0 : draw 0,175 : draw -255,0 : draw 0,-175
doubleSizePrint(0,4,"The Spectrum")
doubleSizePrint(2,10,"Client")
printat42(5,4)
Print42("Welcome to the The Spectrum Client.")
printat64(7,8)
print64("With this client YOU can access 2 online MUDS.")
printat64(8,12)
print64("The 8 Bit Mud, and the Star Wars Mud.")
printat64(9,3)
print64("With the 8 Bit Mud, we will be adding text adventure games")
printat64(10,23)
print64("from the spectrum.")
printat64(12,7)
print64("You can also access a BBS Bulletin Board System")
printat64(14,2)
print64("1 : The 8 Bit Mud. 2 : The Star Wars Mud. 3 : The 8 Bit BBS")
PRINT AT 20,1;"(1/2/3/Q) ";
MENUINPUT:
i$=INPUT(1)
if i$="1" then goto THEBITMUD : end if
if i$="q" or i$="Q" then stop : end if
goto MENUINPUT
THEBITMUD:
INK 7 : PAPER 0 : BORDER 0 : CLS
print at 0,0;"Ardent's Spectranet TCP Client Test"
print at 2,0;"Looking up Host The8bitmud.zapto.org"
goto THESTART
end
THESTART:
pause 50
opensocket()
pause 50
hostip()
pause 50
connect()
pause 50
sendfirst()
pause 100
INK 7 : PAPER 0 : BORDER 0 : CLS : CLS
print at 0,0;
MAIN:
NETmainloop()
gosub NETinputloop
goto MAIN
NETinputloop:
2008 print at 22,0;thekeys$( to rowx )+xx$+thekeys$( rowx+1 to )
2010 let k=code inkey$ : if k then beep .2,0 : end if
2011 if k>31 and k<128 then goto 2264 : end if
2012 if k=13 then goto 2036 :end if
2013 if k=8 then goto 2026 :end if
2014 if k=9 then goto 2028 :end if
2015 if k=10 then goto 2030 :end if
2016 if k=11 then goto 2032 :end if
2017 if k=12 then goto 2034 :end if
2019 return
2026 if rowx=0 then goto 2010 : end if
2027 let rowx=rowx-1 : goto NETinputloop
2028 if rowx=length then goto 2010 :end if
2029 let rowx=rowx+1 : goto NETinputloop
2030 if rowx+32>length then goto 2010 :end if
2031 let rowx=rowx+32 : goto NETinputloop
2032 if rowx<32 then goto 2010 : end if
2033 let rowx=rowx-32 : goto NETinputloop
2034 if not rowx then goto 2010 : end if
2035 let rowx=rowx-1 : goto 2041
2036 gosub senddata : gosub NETrestart : return
2038 goto 2010
2040 if rowx=length then goto 2010 : end if
2041 let thekeys$( rowx+1 to )=thekeys$( rowx+2 to ) : let thekeys$(length)="" : goto 2008
2264 if rowx=length then goto 2010 : end if
let thekeys$(rowx)=chr$(k)
2265 let rowx=rowx+1 : if rowx<length then let thekeys$( rowx+1 to )=thekeys$( rowx to ) : end if
goto 2008
2499 goto 2010
NETrestart:
let rowx=0: let thekeys$=" "
return
senddata:
let p=len(z$) - 1
ttt:
if thekeys$(p)=" " then let p=p-1 : goto ttt :end if
FOR ii = 0 TO p:
POKE @MyLabel + ii, CODE thekeys(ii)
NEXT ii
poke @MyLabel2,p
return
SUB fastcall opensocket()
ASM
ld c, 1
ld hl, SOCKET
call HLCALL
ld (v_sockfd), a
ret
END ASM
END SUB
SUB fastcall hostip()
ASM
ld hl, serverhost
ld de, ip_buffer
ld ix, GETHOSTBYNAME
call IXCALL
ret
END ASM
END SUB
SUB fastcall connect()
ASM
ld hl, connectingMSG
ld bc, end3-connectingMSG
call myPrint42
; now actually connect...
ld a, (v_sockfd) ; get back the socket file descriptor
ld de, ip_buffer ; point to the dotted ip notation we got previously
ld bc, serverport ; the port I want to use to connect on... (22528 as is heh)
ld hl, CONNECT
call HLCALL ; call the Spectranet CONNECT ROM routine, :D
;jp c, commerror ; carry is set if there is an error (fingers crossed k)
; CONNECTED !!!
xor a
inc a
ld (connected), a
ld hl, connectedMSG
ld bc, end5-connectedMSG
call myPrint42
END ASM
END SUB
SUB fastcall sendfirst()
ASM
ld a, (v_sockfd)
ld de, garbage
ld bc, garbageend-garbage
ld hl, SEND
call HLCALL
END ASM
END SUB
SUB fastcall send2()
ASM
ld a, (v_sockfd)
ld de, garbage2
ld bc, garbageend2-garbage2
ld hl, SEND
call HLCALL
END ASM
END SUB
SUB fastcall NETmainloop()
ASM
; main receive loop, :/
.tightloop:
; poll the socket to see if data is waiting
call pollSocket
jr c, .no_data1
; there is data to be collected
.gData2:
call clearBuffer
ld a, (v_sockfd)
ld de, responseBuffer
ld bc, responseBufferEnd-responseBuffer
ld hl, RECV
call HLCALL
jp c, commerror
ld hl, responseBuffer ; get the address of the buffer
add hl, bc ; add on the number of received bytes
inc hl
ld (hl), msgEND ; mark that point as the end of the text
call displayData ; and just display that, :D
jr .tightloop
.no_data1:
scf
; xor a
; .checkkeys:
; jr nc, .tightloop
; now close the socket, dunno why cos I ain't never ever gonna give you up, err, I mean drop to BASIC
; green indicates complete run through worked ok...
ret
;========================================================================
pollSocket:
; returns carry clear if data to be fetched
; or set carry to indicate no data...
ld a, (v_sockfd)
ld hl, POLLFD
CALL HLCALL
jr z, .nodata
scf
ccf
ret
.nodata:
scf
ret
displayData:
;ld a, 3
;out ($fe), a
ld hl, responseBuffer
call myPrint42
ret
END ASM
END SUB
SUB fastcall clearBuffer()
ASM
clearBuffer:
ld hl, responseBuffer
ld de, responseBuffer+1
ld bc, responseBufferEnd-responseBuffer-1
ld (hl), 32
ldir
ret
END ASM
END SUB
SUB fastcall commerror()
ASM
commerror:
ld a, 2
out ($fe), a ; turn border red to indicate error... :/
ld hl, errorMSG
call myPrint42 ; print the error msg
ld a, (v_sockfd)
and a ; do we have a socket?
ret z ; nope, so return ;NOTE: This may cause a ret to BASIC, grr, will sort it later, :p
ld hl, CLOSE ; we have a socket, so clean it up
call HLCALL
;call end_interrupts ; reset interrupts back to im 1..
ret
END ASM
END SUB
SUB fastcall myPrint42()
ASM
myPrint42:
push af
push ix
push hl
ld ix, PRINT42
CALL IXCALL
pop hl
pop ix
pop af
ret
END ASM
END SUB
ASM
msgEND EQU 0
msgCR EQU 10
RET_OK EQU 0
RET_SOCKERR EQU 1
RET_PORTERR EQU 2
RET_RECEIVEERR EQU 4
RET_UNKNOWN EQU 128
SOCK_STREAM EQU 1
SOCK_DGRAM EQU 2
SOCK_RAW EQU 3
CALLBAS EQU 0x10
STACK_BC EQU $2D2B
PRINT_FP EQU $2DE3
MODULECALL equ $3FF8
MODULECALL_NOPAGE equ $28
PAGEIN equ $3FF9
PAGEOUT equ $007C
HLCALL equ $3FFA
IXCALL equ $3FFD
; Port defines
CTRLREG equ $033B
CPLDINFO equ $023B
; Jump table entry points
SOCKET equ $3E00 ; Allocate a socket
CLOSE equ $3E03 ; Close a socket
LISTEN equ $3E06 ; Listen for incoming connections
ACCEPT equ $3E09 ; Accept an incoming connection
BIND equ $3E0C ; Bind a local address to a socket
CONNECT equ $3E0F ; Connect to a remote host
SEND equ $3E12 ; Send data
RECV equ $3E15 ; Receive data
SENDTO equ $3E18 ; Send data to an address
RECVFROM equ $3E1B ; Receive data from an address
POLL equ $3E1E ; Poll a list of sockets
POLLALL equ $3E21 ; Poll all open sockets
POLLFD equ $3E24 ; Poll a single socket
GETHOSTBYNAME equ $3E27 ; Look up a hostname
PUTCHAR42 equ $3E2A ; 42 column print write a character
PRINT42 equ $3E2D ; 42 column print a null terminated string
CLEAR42 equ $3E30 ; Clear the screen and reset 42-col print
SETPAGEA equ $3E33 ; Sets page area A
SETPAGEB equ $3E36 ; Sets page area B
LONG2IPSTRING equ $3E39 ; Convert a 4 byte big endian long to an IP
IPSTRING2LONG equ $3E3C ; Convert an IP to a 4 byte big endian long
ITOA8 equ $3E3F ; Convert a byte to ascii
RAND16 equ $3E42 ; 16 bit PRNG
REMOTEADDRESS equ $3E45 ; Fill struct sockaddr_in
IFCONFIG_INET equ $3E48 ; Set IPv4 address
IFCONFIG_NETMASK equ $3E4B ; Set netmask
IFCONFIG_GW equ $3E4E ; Set gateway
INITHW equ $3E51 ; Set the MAC address and initial hw registers
GETHWADDR equ $3E54 ; Read the MAC address
DECONFIG equ $3E57 ; Deconfigure inet, netmask and gateway
MAC2STRING equ $3E5A ; Convert 6 byte MAC address to a string
STRING2MAC equ $3E5D ; Convert a hex string to a 6 byte MAC address
ITOH8 equ $3E60 ; Convert accumulator to hex string
HTOI8 equ $3E63 ; Convert hex string to byte in A
GETKEY equ $3E66 ; Get a key from the keyboard, and put it in A
KEYUP equ $3E69 ; Wait for key release
INPUTSTRING equ $3E6C ; Read a string into buffer at DE
GET_IFCONFIG_INET equ $3E6F ; Gets the current IPv4 address
GET_IFCONFIG_NETMASK equ $3E72 ; Gets the current netmask
GET_IFCONFIG_GW equ $3E75 ; Gets the current gateway address
SETTRAP equ $3E78 ; Sets the programmable trap
DISABLETRAP equ $3E7B ; Disables the programmable trap
ENABLETRAP equ $3E7E ; Enables the programmable trap
PUSHPAGEA equ $3E81 ; Pages a page into area A, pushing the old one
POPPAGEA equ $3E84 ; Restores the previous page in area A
PUSHPAGEB equ $3E87 ; Pages into area B pushing the old one
POPPAGEB equ $3E8A ; Restores the previous page in area B
PAGETRAPRETURN equ $3E8D ; Returns from a trap to page area B
TRAPRETURN equ $3E90 ; Returns from a trap that didn't page area B
ADDBASICEXT equ $3E93 ; Adds a BASIC command
STATEMENT_END equ $3E96 ; Check for statement end, exit at syntax time
EXIT_SUCCESS equ $3E99 ; Use this to exit successfully after cmd
PARSE_ERROR equ $3E9C ; Use this to exit to BASIC with a parse error
RESERVEPAGE equ $3E9F ; Reserve a page of static RAM
FREEPAGE equ $3EA2 ; Free a page of static RAM
REPORTERR equ $3EA5 ; report an error via BASIC
connectingMSG: defm "Connecting..."
defm 13
end3: defm 0
allocatingMSG: defm "Allocating resources..."
defm 13
end4: defm 0
connectedMSG: defm "Connected. "
defm 13
end5: defm 0
receivngMSG: defm "Receiving data."
defm 13
end6: defm 0
errorMSG: defm "Failed."
defm 13
end7: defm 0
doneMSG: defm "Done"
defm 13
end8: defm 0
waitingMSG: defm "I iz waitingz k :p"
defm 13
end9: defm 0
crMSG: defm 13
end10: defm 0
v_sockfd: defb 0 ; storage for socket file descriptor
serverport equ 16384
serverhost: defb "the8bitmud.zapto.org"
more: ds 60
connected: defb 0 ; 0 means not connected, 1 means connected
ip_buffer: defb 0, 0, 0, 0 ; leave 4 bytes free for an IP address
garbage: defm ""
defm 10
garbageend: defb 0
defm 10
garbageend2: defb 0
responseBuffer: ds 1024
responseBufferEnd: defm 0
garbage2: defm "ardentcrest"
END ASM
MyLabel:
ASM
text1:
ds 1024 ; 1024 bytes of space MAX!!
END ASM
MyLabel2:
ASM
lenth1:
ds 1 ; 1024 bytes of space MAX!!
END ASM