12-27-2002, 03:58 AM
The pureQB trick uses a 127 indexes array to store keyboard info. For example, key Enter has scancode # &H1D, so keys%(&H1D) will be -1 (TRUE) if Enter is pressed, otherwise 0 (FALSE).
To do the trick, the array is written inside a loop, for example the vertical retrace loop or your timing loop. Port &H60 is read, and the value returned is set in the array, then the buffer is cleared. In the next loop, a new key will be read from the buffer if you are pressing several.
At the end of the loop, all your multiple keypresses have been read and you just have to check the correct indexes in the array keys%(), for example, keys%(72) to read the "UP" key.
When you've checked all the keypresses, you just put all key%() array indexes to 0, to clear your virtual keyboard handler.
Check this snipped by Eric Carr to understand how it works
This code snipped uses timer. Windoze doesn't like that, so maybe you'll like to code a VGA retrace wait loop:
Hope this works
To do the trick, the array is written inside a loop, for example the vertical retrace loop or your timing loop. Port &H60 is read, and the value returned is set in the array, then the buffer is cleared. In the next loop, a new key will be read from the buffer if you are pressing several.
At the end of the loop, all your multiple keypresses have been read and you just have to check the correct indexes in the array keys%(), for example, keys%(72) to read the "UP" key.
When you've checked all the keypresses, you just put all key%() array indexes to 0, to clear your virtual keyboard handler.
Check this snipped by Eric Carr to understand how it works
Code:
'===========================================================================
' Subject: SIMULTANEOUS KEY DEMO Date: 03-18-96 (13:12)
' Author: Eric Carr Code: QB, QBasic, PDS
' Origin: FidoNet QUIK_BAS Echo Packet: KEYBOARD.ABC
'===========================================================================
'Ok..Here is the sample keyboard routine I promised..I haven't tested it on any
'other computer excpet mine, but it should work for anyone.. This program lets
'you move a box around by pressing the arrow keys..The acual routine in only 4
'lines as i have marked..This program requires a minimum of a 486sx 25mhz if
'not compiled to run fast enough for all the keys to be updated..I also
'reprogrammed the internal timer from 18.2 to 30, so I could time it to 30 fps.
'To see if a key is being currently pressed, the variable KS is used (IF
'KS(75)=1 THEN button is pressed). Instead of ASCII, this uses scan codes,
'which you can look at in the QB help..Hope you can understand it! :)
DEFINT A-Z: DIM B(300): CLS
N& = 39772 'Reprogram the timer to 30hz
LB& = N& AND &HFF 'instead of 18.2 (for 30 frames
HB& = (N& / 256) AND &HFF 'per second.)
OUT &H43, &H3C: OUT &H40, LB&: OUT &H40, HB&
DIM KS(255), SC(255), DU(255)
FOR E = 0 TO 127 ' Setup key data table KSC()
SC(E) = E: DU(E) = 1
NEXT
FOR E = 128 TO 255
SC(E) = E - 128: DU(E) = 0
NEXT
SCREEN 13: COLOR 4
LOCATE 10, 3: PRINT "Keyboard input routine by Eric Carr"
COLOR 7: PRINT : COLOR 2
PRINT " Use the arrow keys to move the box."
PRINT "Note that you can press two or more keys"
PRINT " at once for diagnal movement!"
PRINT : COLOR 8: PRINT " Press [Esc] to quit"
X = 150: Y = 100: BX = X: BY = Y
DEF SEG = 0
POKE (1132), 0
GET (X, Y)-(X + 15, Y + 15), B
DO 'main loop
' __ By NATHAN __ : This is the loop where KS array is
' filled with values depending on the keypresses:
T:
I$ = INKEY$ ' So the keyb buffer don't get full \routine/
I = INP(&H60) ' Get keyboard scan code from port 60h \lines/
OUT &H61, INP(&H61) OR &H82: OUT &H20, &H20 ' \!!!/
KS(SC(I)) = DU(I) ' This says what keys are pressed \!/
IF PEEK(1132) < 1 THEN GOTO T 'If not enough time was passed goto T
POKE (1132), 0 'reset timer again
BX = X: BY = Y
' __ By NATHAN __ See how we check inside the array for
' keypresses:
IF KS(75) = 1 THEN XC = XC - 2: IF XC < -15 THEN XC = -15
IF KS(77) = 1 THEN XC = XC + 2: IF XC > 15 THEN XC = 15
IF KS(72) = 1 THEN YC = YC - 2: IF YC < -15 THEN YC = -15
IF KS(80) = 1 THEN YC = YC + 2: IF YC > 15 THEN YC = 15
IF XC > 0 THEN XC = XC - 1 ELSE IF XC < 0 THEN XC = XC + 1
IF YC > 0 THEN YC = YC - 1 ELSE IF YC < 0 THEN YC = YC + 1
Y = Y + YC: X = X + XC
IF X > 300 THEN X = 300 ELSE IF X < 0 THEN X = 0
IF Y > 180 THEN Y = 180 ELSE IF Y < 0 THEN Y = 0
IF X <> BX OR Y <> BY THEN
WAIT 936, 8: PUT (BX, BY), B, PSET
GET (X, Y)-(X + 15, Y + 15), B: LINE (X, Y)-(X + 15, Y + 15), 9, BF
END IF
LOOP UNTIL KS(1) = 1 'loop until [Esc] (scan code 1) is pressed
N& = 65535 'Program the timer back to
LB& = N& AND &HFF '18.2hz before exiting!
HB& = (N& / 256) AND &HFF
OUT &H43, &H3C: OUT &H40, LB&: OUT &H40, HB&
OUT &H61, INP(&H61) OR &H82: OUT &H20, &H20
CLEAR 'need to have this if reprograming the timer
END 'I think this ends the program. I'm not quite sure.. :)
This code snipped uses timer. Windoze doesn't like that, so maybe you'll like to code a VGA retrace wait loop:
Code:
' Missing initialization code, just line in Carr's routine
' This is the same as WAIT &H3DA,8: WAIT &H3DA,8,8
' Nathan's code, untested but likely to work
' while bit 3 of port 3DAh is 0 do keyboard stuff;
WHILE (INP(&H3DA) AND 8 ) = 0
' Put here the ks stuff and so:
I$ = INKEY$ ' So the keyb buffer don't get full \routine/
I = INP(&H60) ' Get keyboard scan code from port 60h \lines/
OUT &H61, INP(&H61) OR &H82: OUT &H20, &H20 ' \!!!/
KS(SC(I)) = DU(I) ' This says what keys are pressed \!/
WEND
' while bit 3 of port 3DAh is 1 no opperation;
WHILE (INP(&H3DA) AND 8 ) = 8
WEND
Hope this works