Keyboard buffer problem

If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!

Moderators: Pete, Mods

Post Reply
User avatar
ThirtyNitesOfMX
Coder
Posts: 18
Joined: Sun Nov 28, 2010 6:58 pm
Location: seattle, wa

Keyboard buffer problem

Post by ThirtyNitesOfMX »

for my main walking engine, im using INP(96) which seems to work fine other than the anomaly with releasing 2 buttons at once and the CPU missing one of the keyUP inputs.

however, ill call a subroutine where i prefer using key$ = inkey$, it makes more sense for battle menus, item menus, etc.

the problem is, when the subroutine is finished and it goes back to the main walking engine, all the keystrokes have been saved in the buffer and the character walks around in all the directions i moved the cursor in the menu sub, until the buffer is clear.

i have heard of one way to wipe the keyboard buffer to eliminate this problem, using this code

DEF SEG = &H40
POKE &H1A, PEEK(&H1A + 2)

i have it right before

k = inp(96)

it is obviously not doing what it is supposed to. in fact, im not sure its doing anything.

my first instinct was to write a subroutine which is called at the end of every sub which uses key$ for the keyboard input and just lets the keyboard buffer blow its load there, but obviously its not going to clear out until i go back to my main engine and it unloads in the walking sequence.

any thoughts? anybody ever successfully tackled this problem?

maybe im just not putting the:

DEF SEG = &H40
POKE &H1A, PEEK(&H1A + 2)

..in the right place?
thanks.
User avatar
ThirtyNitesOfMX
Coder
Posts: 18
Joined: Sun Nov 28, 2010 6:58 pm
Location: seattle, wa

Post by ThirtyNitesOfMX »

i was just looking at the source code for qb64

shouldnt &h40 be &H60? since 60 = 96 in hex...
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

THAT is for using PEEK to read the Function keys like Caps Lock, Scroll Lock, Number Lock, etc.

You can't POKE newer PC keyboards! Not even XP...

Try this Multikey Function I made:

Code: Select all

  
DECLARE FUNCTION ScanKey%(code%)                   'NOT required in QB64
         
CLS
LOCATE 8, 14: PRINT "W A S D": LOCATE 8, 52: PRINT "ARROW PAD"
DO: _LIMIT 1000   ' program or game loop
  IF ScanKey%(17) THEN LOCATE 2, 15: PRINT " UP " ELSE LOCATE 2, 15: PRINT "----"   'W key
  IF ScanKey%(31) THEN LOCATE 6, 15: PRINT "DOWN" ELSE LOCATE 6, 15: PRINT "----"   'S key
  IF ScanKey%(30) THEN LOCATE 4, 12: PRINT "LEFT" ELSE LOCATE 4, 12: PRINT "----"   'A key
  IF ScanKey%(32) THEN LOCATE 4, 18: PRINT "RIGHT" ELSE LOCATE 4, 18: PRINT "---- " 'D key
  IF ScanKey%(72) THEN LOCATE 2, 55: PRINT " UP " ELSE LOCATE 2, 55: PRINT "----"   'arrow
  IF ScanKey%(80) THEN LOCATE 6, 55: PRINT "DOWN" ELSE LOCATE 6, 55: PRINT "----"   'arrow
  IF ScanKey%(75) THEN LOCATE 4, 52: PRINT "LEFT" ELSE LOCATE 4, 52: PRINT "----"   'arrow
  IF ScanKey%(77) THEN LOCATE 4, 58: PRINT "RIGHT" ELSE LOCATE 4, 58: PRINT "---- " 'arrow
LOOP UNTIL ScanKey%(1)
zerocodes% = ScanKey%(0)     'reset all array values to zero for next part of program
END

FUNCTION ScanKey% (scancode%)
STATIC Ready%, keyflags%()
IF NOT Ready% THEN REDIM keyflags%(0 TO 127): Ready% = -1 
i% = INP(&H60)  'read keyboard states
IF (i% AND 128) THEN keyflags%(i% XOR 128) = 0
IF (i% AND 128) = 0 THEN keyflags%(i%) = -1
K$ = INKEY$
ScanKey% = keyflags%(scancode%)
IF scancode% = 0 THEN Ready% = 0  'allows program to reset all values to 0 with a REDIM
END FUNCTION  
Use scancode% = 0 to reset the Array on the next use.

erasearray% = ScanKey%(0) 'resets Ready% in function

Ted
Last edited by burger2227 on Tue Nov 30, 2010 11:25 pm, edited 1 time in total.
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

You can use INKEY$ to clear the keyboard buffer before or after an INP(&H60) read.

This will clear the keyboard in QB64:

Code: Select all

DEF SEG = 0
DO 'program loop
  i = INP(&H60)              'update keydown states
  DO                         'key read loop
    IF (i AND 128) THEN KeyPress(i XOR 128) = 0
    IF (i AND 128) = 0 THEN KeyPress(i) = -1
    i2 = i
    i = INP(&H60)
    POKE 1050, PEEK(1052)     'clear keyboard buffer
  LOOP UNTIL i = i2
'key read code
LOOP
DEF SEG
BTW, can you share your RPG code so that Galleon can test it?

You never answered...

Ted
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
User avatar
ThirtyNitesOfMX
Coder
Posts: 18
Joined: Sun Nov 28, 2010 6:58 pm
Location: seattle, wa

Post by ThirtyNitesOfMX »

i was still trying to understand how the first one works.

it didnt seem to help.

i implemented the function, used the if scankey%(x) then, else

used zerocodes% = ScanKey%(0) at the end of each sub before returning to the main loop

did not work. i will try the second thing you posted.
User avatar
ThirtyNitesOfMX
Coder
Posts: 18
Joined: Sun Nov 28, 2010 6:58 pm
Location: seattle, wa

Post by ThirtyNitesOfMX »

i did reply in the last thread, i said if you shoot me an email adress ill send the code. i will also have to send all the files its loading for him to run the program though
User avatar
ThirtyNitesOfMX
Coder
Posts: 18
Joined: Sun Nov 28, 2010 6:58 pm
Location: seattle, wa

Post by ThirtyNitesOfMX »

thanks.. i figured it out. im a little confused though, why did you say you cant poke and peek with newer pc keyboards and then suggest that i poke and peek?

anyways, im assuming the keyboard buffer array is < 300 entries? i think i heard somewhere it was 255 or 155

i just let the first 300 times through the main loop and the first 300 times through every time i return back to it have no control over the keyup and keydown variables, and also set them all to up.. seems to work fine without any lag when returning to the main loop. thanks for your help.. i couldnt figure your code out but it helped me realize all i needed to do was clear the buffer manually.. its weird though that qbasic never has had a clear keyboard buffer command. or allow you to take temporary control over the keyboards repeat rate. anyways..

can qb64 read usb info? ive figured out a way to use a usb gamepad, but its probably not the best way, and if theres another way, im guessing you know it.
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Post by burger2227 »

There are 255 ASCII characters, but the keyboard only has about 101 keys. You can't POKE &H60 or use OUT &H60.

Since QB64 emulates POKEs Galleon allowed that to work. Many others do not work in QB64 yet.

I don't understand why you can't clear the keyboard buffer. An INKEY$ loop will clear it:

DO: K$ = INKEY$: LOOP UNTIL K$ = ""

The function can only clear the array that holds multiple press or release codes. Not the buffer. INKEY$ is used in the function to help clear the buffer so that it does not BEEP when it gets full.

No USB stuff yet either except for LPRINT with a USB printer.

Anyhow, my Email address is the same place yours is. Just click it or right click it to copy it!

Ted
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
Post Reply