Boriel Basic Forum
Looking for an Inkey$ routine. - Printable Version

+- Boriel Basic Forum (https://forum.boriel.com)
+-- Forum: Compilers and Computer Languages (https://forum.boriel.com/forumdisplay.php?fid=12)
+--- Forum: ZX Basic Compiler (https://forum.boriel.com/forumdisplay.php?fid=11)
+---- Forum: Help & Support (https://forum.boriel.com/forumdisplay.php?fid=16)
+---- Thread: Looking for an Inkey$ routine. (/showthread.php?tid=851)



Looking for an Inkey$ routine. - ardentcrest - 2018-09-16

I'm thinking of re-doing my spectranet client but I need a good inkey$ input routine. the one I have ether misses keys presses or does multi letters.

I am using

#include <input.bas>
#include <keys.bas>

Code:
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


any hekp


Re: Looking for an Inkey$ routine. - boriel - 2018-09-17

I don't understand. Does the one bundled with ZX Basic does not work? You can also use GetKey().
Anyway, there's a simple inkeys routine here:
http://www.breakintoprogram.co.uk/computers/zx-spectrum/keyboard
Ah, check you have the latest version (1.8.5 at this moment). The compiler has changed a lot last year and more is expected to come these next months! 8)
Nice to see you, BTW!


Re: Looking for an Inkey$ routine. - ardentcrest - 2018-09-17

nice to be back Smile

the routine I'm looking for is to use inkey to input a line of text like in an adventure game which will, when no key is pressed, will look to see if a sever has sent a message to print.


Re: Looking for an Inkey$ routine. - boriel - 2018-09-17

ardentcrest Wrote:nice to be back Smile

the routine I'm looking for is to use inkey to input a line of text like in an adventure game which will, when no key is pressed, will look to see if a sever has sent a message to print.
And is the bundled input.bas library not suitable for you?


Re: Looking for an Inkey$ routine. - ardentcrest - 2018-09-17

will check later. a 42input with a 64print might work.

It's the missing keys presses or does multi letters when listening to the server that gets to me.


Re: Looking for an Inkey$ routine. - ardentcrest - 2018-09-17

new help.
My code used to work with an old compiler but I'm getting
Quote:Undefined label

I do have the labels

Code:
INK 7 : PAPER 0 : BORDER 0 : CLs #include <times2.bas> #include <print42.bas> #include <print64.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 the online MUD.") printat64(8,25) print64("The 8 Bit Mud.") printat64(9,3) print64("With the 8 Bit Mud, we will be adding text adventure games") printat64(10,23) print64("from the spectrum.") PRINT AT 17,1;"PRESS 1 to Play or Q to Quit "; MENUINPUT: let a$=" The Spectrum Client V 1.3 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 Rubbish 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$="q" or i$="Q" then stop : end if NEXT n goto MENUINPUT THEBITMUD: INK 7 : PAPER 0 : BORDER 0 : CLS 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 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

I cant see what I'm doing wrong


Re: Looking for an Inkey$ routine. - boriel - 2018-09-17

Can you post the file times2.bas? I think it's not included with ZX Basic :roll:


Re: Looking for an Inkey$ routine. - ardentcrest - 2018-09-17

this is the doubleSizePrintChar I just changed the name to make it shorter
Code:
SUB doubleSizePrintChar(y AS UBYTE, x AS UBYTE, thingToPrint AS UBYTE) ' Prints a single character double sized. ' Takes X and Y values as character positions, like print. ' takes an ascii code value for a character. ' By Britlion, 2012. ASM LD A,(IX+5) ;' Y value CP 22 JP NC, doubleSizePrintCharEnd ;' A=y value LD E,A AND 24 ; calculate OR 64 ; screen LD H,A ; address LD A,E ; FOR AND 7 ; row OR a ; Y RRA RRA RRA RRA LD E,A LD A,(IX+7) ;' X Value CP 30 JP NC, doubleSizePrintCharEnd ADD A,E ;' correct address for column value. (add it in) LD L,A EX DE,HL ;' Save it in DE LD A,(IX+9) ;'Character CP 164 ;' > UDG "U" ? JP NC, doubleSizePrintCharEnd CP 32 ;' < space+1? JP C, doubleSizePrintCharEnd CP 144 ;' >144? JP NC, doubleSizePrintCharUDGAddress LD L,A LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL ;' multiply by 8. LD BC,(23606) ;' Chars ADD HL,BC ;' Hl -> Character data. EX DE,HL ;' DE -> character data, HL-> screen address. JP doubleSizePrintCharRotateLoopCharStart doubleSizePrintCharUDGAddress: LD HL,(23675) ;'UDG address SUB 144 ADD A,A ;multiply by 8. ADD A,A ADD A,A ADD A,L LD L,A JR NC, doubleSizePrintCharUDGAddressNoCarry INC H doubleSizePrintCharUDGAddressNoCarry: ;' At this point HL -> Character data in UDG block. EX DE,HL ;' DE -> character data, HL-> screen address. doubleSizePrintCharRotateLoopCharStart: LD C,2 ;' 2 character rows. doubleSizePrintCharRotateLoopCharRowLoopOuter: LD b,4 ;' 4 source bytes to count through per character row. doubleSizePrintCharRotateLoopCharRowLoopInner: PUSH BC LD A,(DE) ;' Grab a bitmap. PUSH DE LD B,4 LD C,A ; Copy BYTE so we can put two into the big version. doubleSizePrintCharRotateLoop1: RRA ; one bit into carry RR E ; one bit into result RR C ; same bit into carry again RR E ; duplicated bit into result DJNZ doubleSizePrintCharRotateLoop1 LD B,4 doubleSizePrintCharRotateLoop2: RRA RR D ; Other register FOR other half of big 16 bit line. RR C RR D DJNZ doubleSizePrintCharRotateLoop2 LD (HL),D ;' Output first byte INC HL ;' Move right LD (HL),E ;' Second half. DEC HL ;' Move left INC H ;' Move down LD (HL),D ;' Output second row (copy of first), first byte. INC HL ;' Move right LD (HL),E ; Output second row, second BYTE DEC HL ; Move left INC H ; Move down. POP DE INC DE POP BC DJNZ doubleSizePrintCharRotateLoopCharRowLoopInner ; CALL __DECY+2 ;'Jump into the DRAW next_line_down routine, at a convenient point (accounting for the INC H above) ; Can't seem to call to this at the moment! Here in longhand form: ld a, h AND 7 jr nz, doubleSizePrintCharRotateNextCharRow ld a, l add a, 32 ld l, a jr c, doubleSizePrintCharRotateNextCharRow ld a, h SUB 8 ld h, a doubleSizePrintCharRotateNextCharRow: DEC C JR NZ, doubleSizePrintCharRotateLoopCharRowLoopOuter doubleSizePrintCharEnd: END ASM END SUB SUB doubleSizePrint(y AS UBYTE, x AS UBYTE, thingToPrint$ AS STRING) 'Uses doubleSizePrintChar subroutine to print a string. 'By Britlion, 2012 DIM n AS UBYTE FOR n=0 TO LEN thingToPrint - 1 doubleSizePrintChar(y,x,CODE thingToPrint$(n) ) x=x+2 NEXT n END SUB

the undefined label starts with

Code:
SUB fastcall NETline() ASM newline: ld hl, lineMSG <----- this label ld bc, end1-lineMSG call myPrint42 END ASM END SUB

but it is near the bottom of code
Code:
lineMSG: defm " " defm 10,13



Re: Looking for an Inkey$ routine. - britlion - 2018-09-18

You have no idea how much it gives me the warm fuzzies when someone adopts a bit of my code from the library, by the way Big Grin


Re: Looking for an Inkey$ routine. - britlion - 2018-09-18

ardentcrest Wrote:[code]
ASM
newline:
ld hl, lineMSG <----- this label
ld bc, end1-lineMSG
call myPrint42
[code]

Is your other label reference inside an asm context as well?

Edit: Derp me. You posted it. Without checking it (no time) - have you tried putting the label on a line by itself?


Re: Looking for an Inkey$ routine. - boriel - 2018-09-19

Ardencrest, I will contact you privately so you can pass me the source code for me to debug it.
This seems to be a bug in the scope resolving level.


Re: Looking for an Inkey$ routine. - ardentcrest - 2018-09-23

any luck???


Re: Looking for an Inkey$ routine. - boriel - 2018-09-23

Yes:!: I think I've fixed.
Please download version 1.8.7.
Please, try it and tell me. :roll:

Also, I think it's better this bug report to be in a separated topic in the "Bug reports" section, so other users are aware of it.
I'm also checking the github issues section: https://github.com/boriel/zxbasic/issues since it's more dynamic and the forum needs to be updated.