Code Snippets
Code Samples

The Blog
Our Projects

::Add RageStorm to Favorites!::

The Blog | Our Projects | Guest Book | About | Contact

Tutorial - Keyboard
Uploaded at:29-May-03

Using the regular keyboard input, like getch() in C or readkey in Pascal notifies us when a key was hit, but it doesn't let us know that it was released. Therefore, we cannot tell which keys are being held at a specific moment, which is, as you sure have noticed, a very important thing to know, especially in action games (moving and shooting simultaneously).

So, we have to take care of the keyboard input by ourselves:
What we'll do is install an interrupt that will get messages from the Keyboard IO and will update a buffer (array) of keys that tells 'key is currently DOWN' or 'key is currently UP' for each of the keys.

The interrupt (0x9) is generated by the system every time a key is pressed or released.
The value retrieved by port 0x60 tells us what had happened (which key and [Pressed/Released]).
When a key is pressed a "make" code is sent, when a key is released a "break" code is sent. The value range of the make code is 0-127, the value of the corresponding break code is 128 + the make code (or in other words - MSB on). For example: When a key ESC is pressed the code is 1, when it is released the code is 129(=1+128).

Ok, so we have an array of 128 booleans (true = key down), the interrupt updates it and in the game loop we check if our keys are pressed in this array.

Now, to the code:

void interrupt key_interrupt(...)
 unsigned char ch, dummy;
 asm cli //Disable interrupts
 ch = inp(0x60); //Read the value from the KB IO
 dummy = inp(0x61); //Read the value from the KB Status Controller
 dummy |= 0x80; //Clear Keyboard, by setting 8th bit, and leave the other untouched
 dummy = outp(0x61, dummy);
 dummy &= 0x7f; //Enable Keyboard, by clearing the 8th bit, and leave the other untouched
 outp(0x61, dummy);
 // We disable and then reenable immediately the interrupt to acknowledge the KB controller of the scan code receival.
 if (ch < 128) keypress[ch] = 1; //Is it up?
 else keypress[ch - 128] = 0; //Is it down?
 outportb(0x20, 0x20); //Let the PIC know we are finished
 asm sti //Enable interrupts

looks confusing huh? don't worry, it'll be clearer.

Now instead of doing the 'if else' statement we can use just one line:
keypress[(ch & 127)] = (ch >> 7);
(ch >> 7) ---> returns 0 if ch < 128, returns 1 otherwise.
It's like what we said ...remember? up to 128 is down(true) and more than 128 is up(false)..
Now you wonder what (ch & 127) does?
Well if you don't have a clue about bits read this first!
According to what we said..we get 128 plus the "make" code, it means we want just the first 7 bits of the value and 2^7=128 which is the maximum of the array. So any number AND (logic) 01111111B will make it at least 127 OK think we get the number 64 from the KB IO so 64 & 127 is 64(again you must know BITWISE AND!)
But when you do 255 & 127 you'll get 127...
ahhhhh I hope you still get what I try to explain it's pretty easy
So we get the same result from the if else statement and the AND logic trick...

That's it for now I hope you got it all......
Take a look at the source to see how to install the interrupt
and how to use it correctly.

Source Code:
Turbo C - skeys.cpp

Comments that will hurt anyone in any way will be deleted.
Don't ask for features, advertise or curse.
If you want to leave a message to the author use the contacts,
if you have any question in relation to your comments please use the forum.
Comments which violate any of these requests will be deleted without further
notice. Use the comment system decently.

Post your comment:
::Top 5 Tutorials::
Embedded Python[116941]
2D Rotated Rectangles Collision Detection[88963]
Keyboard Hook[77269]
HTTP Proxy[41198]

::Top 5 Samples::
2D ColDet Rotated Rectangles[11560]
PS2 Mouse Driver[6956]
Wave Format Player[5791]
Reading FAT12[5619]

All rights reserved to RageStorm © 2009