Forum archive
Key detection under dos
- i was wondering what the best way to detect keys is. im currently using getxkey (like getch but returns extended codes all at once) combined with kbhit to see if there is keypress occuring. the problem with this is that if your doing a lot of graphics work its very easy for the buffer to fill up quickly and you get the anoying beep especially if you need to hold the same key down for a while. plus if you want to push up AND left at the same time you can't do this. so what method should i use?
Re: Key detection under dos
I remind this little thingy:
BYTE ascii;
BYTE scancode;
asm
{
MOV AH,1
INT 16h
JZ leer:
MOV AH,0
INT 16h
MOV [ascii],AL
MOV [scancode],AH
JMP sense
leer:
MOV [ascii],0
MOV [scancode],0
sense:
};Key detection under dos
well i tried this and it seems to be an improvement over getxkey/getch however, this only allows 1 key press at a time. I think what im looking for is called keyboard polling (not sure) but it can detect multiple key presses simultaniously.
basically im asking what method does duke3d(or doom) use for keyboard input?- The idea is to set up your own interrupt service routine that replaces the usual DOS one, and process the raw keyboard data that gets generated on each key press or release in whatever way you desire. The keyboard interrupt is number 9 and the scan codes bytes read from port 0x60. Keyboards generate 7-bit scancodes with the 8th bit signifying whether the key was pressed (bit 8 clear) or released (bit 8 set). That's very nice and simple, but as is always the way with a lot of things, there are exceptions and complications. Certain keys generate two or three bytes for each press or release and those keys require a bit of special handling.
Duke, Shadow Warrior, and Blood use Mark Dochtermann's 'MACT' library for input device handling, and it takes care of processing the keyboard data giving raw key states, ASCII input, and game 'button' actions (eg. walk, jump, use inventory, etc). Ken's keyboard facilities give just key states and ASCII input. Both do the job of reading the keyboard data stream much the same way though.
Jonathon - I haven't written DOS code for a long time now, but I think this should work fine. I used to use Turbo C++ 3.1 back then, so this is hacked from some stuff I wrote back then, so stuff like 'volatile' and 'interrupt' might need modification depending on your compiler.
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
// holds the address of DOS's keyboard handler
void interrupt (*OldKbdVector)(...);
// holds the state of each key
char volatile keystatus[256];
// our replacement handler
void interrupt KeyboardISR(...)
{
unsigned char k, temp;
k = inp(0x60); // get the scancode
// acknowledge the key
outp(0x61, (temp=inp(0x61)) | 0x80);
outp(0x61, temp);
// save its state. In the real world you'd be looking here for an 0xE0 byte
// which indicates a special key. Special keys have another byte to follow
// that comes in a seperate interrupt, so you would set a flag to indicate
// the next interrupt is special. Keys which do this are most of the
// extended keys on a keyboard like the insert/delete/printscreen/home
// keypad keys. The second special case is when an 0xE1 byte is seen.
// Two more bytes in two seperate interrupts will follow it. This happens
// when the pause/break key is pressed.
keystatus[k & 0x7f] = ((k & 0x80) == 0);
outp(0x20, 0x20); // signal end of interrupt processing
}
int main(int argc, char **argv)
{
memset(keystatus,0,sizeof(keystatus));
OldKbdVector = getvect(9); // install our handler
setvect(9, KeyboardISR);
while (!keystatus[1]) { } // waste time until Escape (scancode 1) is pressed
setvect(9, OldKbdVector); // restore DOS's handler
return 0;
} - thanks i did some searching and found some stuff on my own but its not nearly as simple as this is.