03-12-2015, 11:23 AM
The Client code
the myprint64.bas
Code:
INK 7 : PAPER 0 : BORDER 0 : CLS
#include <times2.bas>
#include <print42.bas>
#include <print64.bas>
#include <input.bas>
#include <keys.bas>
#include <myprint64.bas>
let length=60 : let rowx=0 : let xx$="<"
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 17,1;"PRESS (1/2/3/Q) ";
MENUINPUT:
let a$=" The Spectrum Client V 1.2 Thanks to Polomint for his incomplete code. Thanks to John Metcalf for his help in the 64 column scroll code. Thanks to Boriel for his ZX Compiler. And THANKS to ME for this SHIT code. "
FOR n=1 TO LEN a$
LET a$=a$(2 TO )+a$(1)
doubleSizePrint(20,1,a$(1 TO 31))
PAUSE 20
i$=inkey$
if i$="1" then goto THEBITMUD : end if
if i$="2" then goto STARWARS : end if
if i$="3" then goto BBS : end if
if i$="q" or i$="Q" then stop : end if
NEXT n
goto MENUINPUT
THEBITMUD:
INK 7 : PAPER 0 : BORDER 0 : CLS
doubleSizePrint(0,4,"Ardentcrests")
doubleSizePrint(2,5,"Spectranet")
doubleSizePrint(4,12,"TCP")
doubleSizePrint(6,4,"Client Test")
doubleSizePrint(10,5,"Looking up")
doubleSizePrint(12,2,"The 8 Bit Mud")
print at 18,0;
poke (@MyLabel3),0
poke (@MyLabel3+1),64
goto THESTART
STARWARS:
INK 7 : PAPER 0 : BORDER 0 : CLS
doubleSizePrint(0,4,"Ardentcrests")
doubleSizePrint(2,5,"Spectranet")
doubleSizePrint(4,12,"TCP")
doubleSizePrint(6,4,"Client Test")
doubleSizePrint(10,5,"Looking up")
doubleSizePrint(12,5,"Star Wars:")
doubleSizePrint(14,4,"Fall of the")
doubleSizePrint(16,8,"Empire")
print at 18,0;
poke (@MyLabel3),0
poke (@MyLabel3+1),128
goto THESTART
BBS:
INK 7 : PAPER 0 : BORDER 0 : CLS
doubleSizePrint(0,4,"Ardentcrests")
doubleSizePrint(2,5,"Spectranet")
doubleSizePrint(4,12,"TCP")
doubleSizePrint(6,4,"Client Test")
doubleSizePrint(10,5,"Looking up")
doubleSizePrint(12,2,"The 8 Bit BBS")
print at 14,0;
poke (@MyLabel3),0
poke (@MyLabel3+1),24
goto THESTART
THESTART:
pause 50
pause 50
opensocket()
hostip()
connect()
sendfirst()
INK 7 : PAPER 0 : BORDER 0 : CLS
NETline()
MAIN:
NETmainloop()
gosub NETinputloop
NETmainloop()
goto MAIN
NETinputloop:
for timeout=0 to 1500 : next timeout
if rowx=0 then printat64(22,0):print64(xx$+" "):goto NetJump1 : end if
FOR ii = 0 TO rowx : printat64(22,ii):print64(chr$(peek (@MyLabel + ii))) : NEXT ii : print64(xx$+" ")
NetJump1:
let k=code inkey$ : for timeout=0 to 1500 : next timeout
if k>31 and k<128 then goto NetKeyPress : end if
if k=13 then goto senddata : end if
if k=12 then goto NetDeleteKey : end if
return
NetDeleteKey:
if rowx=0 then goto NETinputloop : end if
POKE (@MyLabel + (rowx-1)), 0
let rowx = rowx - 1
return
NetKeyPress:
if rowx=length then goto NETinputloop : end if
POKE (@MyLabel + rowx), k
let rowx = rowx + 1
return
senddata:
printat64(22,0):print64(" ")
POKE (@MyLabel + rowx), 13
POKE (@MyLabel + rowx+1), 10
poke (@MyLabel2),(rowx+2)
poke (@MyLabel2+1),0
send2()
NETline()
for ii=0 to rowx+1 : POKE (@MyLabel + ii), 0 : next ii
let rowx=0
return
END
SUB fastcall NETline()
ASM
newline:
ld hl, lineMSG
ld bc, end1-lineMSG
call myPrint42
END ASM
END SUB
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, text1
ld bc, (length1)
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 myPrint64
call newline
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
lineMSG: defm " "
defm 10,13
end1: defm 0
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
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
responseBuffer: ds 1024
responseBufferEnd: defm 0
garbage2: defm "daddydaylight"
serverhost: defb "the8bitmud.zapto.org"
END ASM
MyLabel3:
ASM
serverport: ds 2
END ASM
MyLabel:
ASM
text1: ds 60
END ASM
MyLabel2:
ASM
length1: ds 2
END ASM
the myprint64.bas
Code:
' vim:ts=4:et:
' ---------------------------------------------------------
' 64 Characters wide PRINT Routine for ZX BASIC
' Contributed by Britlion
' ---------------------------------------------------------
#ifndef __MYPRINT64__
#define __MYPRINT64__
#pragma push(case_insensitive)
#pragma case_insensitive = TRUE
' Print given string at current position
SUB fastcall myPrint64 ()
asm
PROC ; Declares begin of procedure
; so we can now use LOCAL labels
myPrint64:
; Test string length. If Zero, exit.
ld a, c
or b
jp z, myp64_END
LOCAL examineChar
examineChar:
ld a, (hl) ; Grab the character
cp 128 ; too high to print?
jr nc, nextChar ; then we go to next.
cp 22 ; Is this an AT?
jr nz, newLine ; If not, hop to newLine routine.
ex de, hl ; Swap DE and HL
and a ; Clear Carry
ld hl, 2 ;
sbc hl, bc ; Can we Shorten our string length by 2? If not then at (y,x) doesn't make sense.
ex de, hl ; Swap DE and HL back
jp nc, myp64_END ; If we went negative, there wasn't anything to AT to, so we return.
inc hl ; Onto our Y co-ordinate
ld d, (hl) ; And load it into D
dec bc ; Shorten our remaining string counter.
inc hl ; Onto the X Co-ordinate
ld e, (hl) ; Load it into E
dec bc ; Shorten our remaining string counter
call myp64_test_X ; Make xy legal 60051 205 53 235
jr myp64_eaa3 ; Go to save coords 60054 24 11
LOCAL newLine
newLine:
cp 13 ; Is this a newline character? 60056 254 13
jr nz, myp64_isPrintable ; If not, hop to testing to see if we can print this 60058 32 13
ld de, (myp64_coords) ; Get coords 60060 237 91 68 235
call myp64_nxtLine ; Go to next line.
LOCAL myp64_eaa3
myp64_eaa3:
ld (myp64_coords), de
jr nextChar
LOCAL myp64_isPrintable
myp64_isPrintable:
cp 31 ; Bigger than 31? 60073 254 31
jr c, nextChar ; If not, get the next one. 60075 56 7
push hl ; Save position 60077 229
push bc ; Save Count 60078 197
call myp64_PrintChar ; Call Print SubRoutine 60079 205 189 234
pop bc ; Recover length count 60082 193
pop hl ; Recover Position 60083 225
LOCAL nextChar
nextChar:
inc hl ; Point to next character 60084 35
dec bc ; Count off this character 60085 11
ld a, b ; Did we run out? 60086 120
or c
jr nz, examineChar ; If not, examine the next one 60088 32 193
jp myp64_END ; Otherwise hop to END. 60090 201
LOCAL myp64_PrintChar
myp64_PrintChar:
exx
push hl ; Save HL' 60094 229
exx
sub 32 ; Take out 32 to convert ascii to position in charset 60096 214 32
ld h, 0
rra ; Divide by 2 60100 31
ld l, a ; Put our halved value into HL 60101 111
ld a, 240 ; Set our mask to LEFT side 60102 62 240
jr nc, myp64_eacc ; If we didn't have a carry (even #), hop forward. 60104 48 2
ld a, 15 ; If we were ab idd #, set our mask to RIGHT side instead 60106 62 15
LOCAL myp64_eacc
myp64_eacc:
add hl, hl
add hl, hl
add hl, hl ; Multiply our char number by 8 60110 41
ld de, myp64_charset ; Get our Charset position 60111 17 70 235
add hl, de ; And add our character count, so we're now pointed at the first
; byte of the right character. 60114 25
exx
ld de, (myp64_coords)
ex af, af'
call myp64_loadAndTest
ex af, af'
inc e
ld (myp64_coords), de ; Put position+1 into coords 60126 237 83 68 235
dec e
ld b, a
rr e ; Divide X position by 2 60132 203 27
ld c, 0
rl c ; Bring carry flag into C (result of odd/even position) 60136 203 17
and 1 ; Mask out lowest bit in A 60138 230 1
xor c ; XOR with C (Matches position RightLeft with Char RightLeft) 60140 169
ld c, a
jr z, myp64_eaf6 ; If they are both the same, skip rotation. 60142 40 6
ld a, b
rrca
rrca
rrca
rrca
ld b, a
LOCAL myp64_eaf6
myp64_eaf6:
ld a, d ; Get Y coord 60150 122
sra a
sra a
sra a ; Multiply by 8 60155 203 47
add a, 88
ld h, a ; Put high byte value for attribute into H. 60159 103
ld a, d
and 7
rrca
rrca
rrca
add a, e
ld l, a ; Put low byte for attribute into l 60167 111
ld a, (23693) ; Get permanent Colours from System Variable 60168 58 141 92
ld (hl), a ; Write new attribute 60171 119
ld a, d
and 248
add a, 64
ld h, a
ld a, b
cpl
ld e, a
exx
ld b, 8
LOCAL myp64_eb18
myp64_eb18:
ld a, (hl)
exx
bit 0, c
jr z, myp64_eb22
rrca
rrca
rrca
rrca
LOCAL myp64_eb22
myp64_eb22:
and b
ld d, a
ld a, (hl)
and e
or d
ld (hl), a
inc h
exx
inc hl
djnz myp64_eb18
exx
pop hl
exx
ret
LOCAL myp64_loadAndTest
myp64_loadAndTest:
ld de, (myp64_coords)
; SubRoutine to go to legal character position. (60213)
LOCAL myp64_test_X
myp64_test_X:
ld a, e ; Get column from e
cp 64 ; more than 64 ?
jr c, myp64_test_Y ; If not, then jump over nextline
LOCAL myp64_nxtLine
myp64_nxtLine:
inc d ; Move down 1
ld e, 0 ; reset x co-ord to zero
LOCAL myp64_test_Y
myp64_test_Y:
ld a, d ; get Y co-ord
cp 22 ; Past 22?
ret c ; Return if not.
dec d
call myp64_scroll
ret ; Return.
LOCAL myp64_scroll
myp64_scroll:
push af
push bc
push de
push hl
ld de,16384
ld hl,16384+32
LOCAL scrltop
scrltop:
ld bc,7*32
ldir
ld b,7
add hl,bc
ld bc,32
ldir
ld b,-7
add hl,bc
bit 4,h
jr z,scrltop
ld a,8
LOCAL scrlbot
scrlbot:
ld d,h
ld e,0
push hl
ld bc,5*32
ldir
ld b,32
ex de,hl
LOCAL scrlblnk
scrlblnk:
ld (hl),c
inc hl
djnz scrlblnk
pop hl
inc h
dec a
jr nz,scrlbot
pop hl
pop de
pop bc
pop af
ret
end asm
myp64coords:
asm
LOCAL myp64_coords;
myp64_coords:
defb 64; X Coordinate store 60228 64
defb 23; Y Coordinate Store 60229 23
LOCAL myp64_charset
myp64_charset:
DEFB 0,2,2,2,2,0,2,0 ; Space !
DEFB 0,80,82,7,2,7,2,0 ; "" #
DEFB 0,37,113,66,114,20,117,32 ; $ %
DEFB 0,34,84,32,96,80,96,0 ; & '
DEFB 0,36,66,66,66,66,36,0 ; ( )
DEFB 0,0,82,34,119,34,82,0 ; * +
DEFB 0,0,0,0,7,32,32,64 ; , -
DEFB 0,1,1,2,2,100,100,0 ; . /
DEFB 0,34,86,82,82,82,39,0 ; 0 1
DEFB 0,34,85,18,33,69,114,0 ; 2 3
DEFB 0,87,84,118,17,21,18,0 ; 4 5
DEFB 0,55,65,97,82,84,36,0 ; 6 7
DEFB 0,34,85,37,83,85,34,0 ; 8 9
DEFB 0,0,2,32,0,34,2,4 ; : ;
DEFB 0,0,16,39,64,39,16,0 ; < =
DEFB 0,2,69,33,18,32,66,0 ; > ?
DEFB 0,98,149,183,181,133,101,0 ; @ A Changed from ;0,2,37,87,117,85,53,0
DEFB 0,98,85,100,84,85,98,0 ; B C
DEFB 0,103,84,86,84,84,103,0 ; D E
DEFB 0,114,69,116,71,69,66,0 ; F G
DEFB 0,87,82,114,82,82,87,0 ; H I
DEFB 0,53,21,22,21,85,37,0 ; J K
DEFB 0,69,71,71,69,69,117,0 ; L M
DEFB 0,82,85,117,117,85,82,0 ; N O
DEFB 0,98,85,85,103,71,67,0 ; P Q
DEFB 0,98,85,82,97,85,82,0 ; R S
DEFB 0,117,37,37,37,37,34,0 ; T U
DEFB 0,85,85,85,87,39,37,0 ; V W
DEFB 0,85,85,37,82,82,82,0 ; X Y
DEFB 0,119,20,36,36,68,119,0 ; Z [
DEFB 0,71,65,33,33,17,23,0 ; \ ]
DEFB 0,32,112,32,32,32,47,0 ; ^ _
DEFB 0,32,86,65,99,69,115,0 ; £ a
DEFB 0,64,66,101,84,85,98,0 ; b c
DEFB 0,16,18,53,86,84,35,0 ; d e
DEFB 0,32,82,69,101,67,69,2 ; f g
DEFB 0,66,64,102,82,82,87,0 ; h i
DEFB 0,20,4,53,22,21,85,32 ; j k
DEFB 0,64,69,71,71,85,37,0 ; l m
DEFB 0,0,98,85,85,85,82,0 ; n o
DEFB 0,0,99,85,85,99,65,65 ; p q
DEFB 0,0,99,84,66,65,70,0 ; r s
DEFB 0,64,117,69,69,85,34,0 ; t u
DEFB 0,0,85,85,87,39,37,0 ; v w
DEFB 0,0,85,85,35,81,85,2 ; x y
DEFB 0,0,113,18,38,66,113,0 ; z {
DEFB 0,32,36,34,35,34,36,0 ; | {
DEFB 0,6,169,86,12,6,9,6 ; ~ (c)
LOCAL myp64_END
myp64_END:
ENDP
end asm
end sub
#pragma pop(case_insensitive)
#endif
I'm always on the chat or facebook.