dosgame1/system/dos/Keyboard.cpp

430 lines
9.8 KiB
C++

#include "../Keyboard.h"
#include <go32.h>
#include "../Pic.h"
#define PIC
#define KEYB_DATA 0x60
Keyboard keyboard;
static const char *keyNames[] = {
"<unknown:00>",
"KeyEscape", // = 0x01,
"Key1", // = 0x02,
"Key2", // = 0x03,
"Key3", // = 0x04,
"Key4", // = 0x05,
"Key5", // = 0x06,
"Key6", // = 0x07,
"Key7", // = 0x08,
"Key8", // = 0x09,
"Key9", // = 0x0a,
"Key0", // = 0x0b,
"KeyMinus", // = 0x0c,
"KeyEqual", // = 0x0d,
"KeyBackspace", // = 0x0e,
"KeyTab", // = 0x0f,
"KeyQ", // = 0x10,
"KeyW", // = 0x11,
"KeyE", // = 0x12,
"KeyR", // = 0x13,
"KeyT", // = 0x14,
"KeyY", // = 0x15,
"KeyU", // = 0x16,
"KeyI", // = 0x17,
"KeyO", // = 0x18,
"KeyP", // = 0x19,
"KeyBracketLeft", // = 0x1a,
"KeyBracketRight", // = 0x1b,
"KeyEnter", // = 0x1c,
"KeyLeftCtrl", // = 0x1d,
"KeyA", // = 0x1e,
"KeyS", // = 0x1f,
"KeyD", // = 0x20,
"KeyF", // = 0x21,
"KeyG", // = 0x22,
"KeyH", // = 0x23,
"KeyJ", // = 0x24,
"KeyK", // = 0x25,
"KeyL", // = 0x26,
"KeySemicolon", // = 0x27,
"KeyApostrophe", // = 0x28,
"KeyBacktick", // = 0x29,
"KeyLeftShift", // = 0x2a,
"KeyBackslash", // = 0x2b,
"KeyZ", // = 0x2c,
"KeyX", // = 0x2d,
"KeyC", // = 0x2e,
"KeyV", // = 0x2f,
"KeyB", // = 0x30,
"KeyN", // = 0x31,
"KeyM", // = 0x32,
"KeyComma", // = 0x33,
"KeyPeriod", // = 0x34,
"KeySlash", // = 0x35,
"KeyRightShift", // = 0x36,
"KeyKeypadMultiply", // = 0x37,
"KeyLeftAlt", // = 0x38,
"KeySpace", // = 0x39,
"KeyCapsLock", // = 0x3a,
"KeyF1", // = 0x3b,
"KeyF2", // = 0x3c,
"KeyF3", // = 0x3d,
"KeyF4", // = 0x3e,
"KeyF5", // = 0x3f,
"KeyF6", // = 0x40,
"KeyF7", // = 0x41,
"KeyF8", // = 0x42,
"KeyF9", // = 0x43,
"KeyF10", // = 0x44,
"KeyNumLock", // = 0x45,
"KeyScrollLock", // = 0x46,
"KeyKeypad7", // = 0x47,
"KeyKeypad8", // = 0x48,
"KeyKeypad9", // = 0x49,
"KeyKeypadMinus", // = 0x4a,
"KeyKeypad4", // = 0x4b,
"KeyKeypad5", // = 0x4c,
"KeyKeypad6", // = 0x4d,
"KeyKeypadPlus", // = 0x4e,
"KeyKeypad1", // = 0x4f,
"KeyKeypad2", // = 0x50,
"KeyKeypad3", // = 0x51,
"KeyKeypad0", // = 0x52,
"KeyKeypadPeriod", // = 0x53,
"<unknown:54>",
"<unknown:55>",
"<unknown:56>",
"KeyF11", // = 0x57,
"KeyF12", // = 0x58,
"<unknown:59>",
"<unknown:5a>",
"<unknown:5b>",
"<unknown:5c>",
"<unknown:5d>",
"<unknown:5e>",
"<unknown:5f>",
"<unknown:60>",
"<unknown:61>",
"<unknown:62>",
"<unknown:63>",
"<unknown:64>",
"<unknown:65>",
"<unknown:66>",
"<unknown:67>",
"<unknown:68>",
"<unknown:69>",
"<unknown:6a>",
"<unknown:6b>",
"<unknown:6c>",
"<unknown:6d>",
"<unknown:6e>",
"<unknown:6f>",
"<unknown:70>",
"<unknown:71>",
"<unknown:72>",
"<unknown:73>",
"<unknown:74>",
"<unknown:75>",
"<unknown:76>",
"<unknown:77>",
"<unknown:78>",
"<unknown:79>",
"<unknown:7a>",
"<unknown:7b>",
"<unknown:7c>",
"<unknown:7d>",
"<unknown:7e>",
"<unknown:7f>",
"<unknown:80>",
"<unknown:81>",
"<unknown:82>",
"<unknown:83>",
"<unknown:84>",
"<unknown:85>",
"<unknown:86>",
"<unknown:87>",
"<unknown:88>",
"<unknown:89>",
"<unknown:8a>",
"<unknown:8b>",
"<unknown:8c>",
"<unknown:8d>",
"<unknown:8e>",
"<unknown:8f>",
"KeyMediaPrev", // = 0x90,
"<unknown:91>",
"<unknown:92>",
"<unknown:93>",
"<unknown:94>",
"<unknown:95>",
"<unknown:96>",
"<unknown:97>",
"<unknown:98>",
"KeyMediaNext", // = 0x99,
"<unknown:9a>",
"<unknown:9b>",
"KeyKeypadEnter", // = 0x9c,
"KeyRightControl", // = 0x9d,
"<unknown:9e>",
"<unknown:9f>",
"KeyMediaMute", // = 0xa0,
"KeyMediaCalculator", // = 0xa1,
"KeyMediaPlay", // = 0xa2,
"<unknown:a3>",
"KeyMediaStop", // = 0xa4,
"<unknown:a5>",
"<unknown:a6>",
"<unknown:a7>",
"<unknown:a8>",
"<unknown:a9>",
"<unknown:aa>",
"<unknown:ab>",
"<unknown:ac>",
"<unknown:ad>",
"KeyMediaVolumeDown", // = 0xae,
"<unknown:af>",
"KeyMediaVolumeUp", // = 0xb0,
"<unknown:b1>",
"KeyMediaWww", // = 0xb2,
"<unknown:b3>",
"<unknown:b4>",
"KeyKeypadDivide", // = 0xb5,
"<unknown:b6>",
"<unknown:b7>",
"KeyRightAlt", // = 0xb8,
"<unknown:b9>",
"<unknown:ba>",
"<unknown:bb>",
"<unknown:bc>",
"<unknown:bd>",
"<unknown:be>",
"<unknown:bf>",
"<unknown:c0>",
"<unknown:c1>",
"<unknown:c2>",
"<unknown:c3>",
"<unknown:c4>",
"<unknown:c5>",
"<unknown:c6>",
"KeyHome", // = 0xc7,
"KeyUp", // = 0xc8,
"KeyPageUp", // = 0xc9,
"<unknown:ca>",
"KeyLeft", // = 0xcb,
"<unknown:cc>",
"KeyRight", // = 0xcd,
"<unknown:ce>",
"KeyEnd", // = 0xcf,
"KeyDown", // = 0xd0,
"KeyPageDown", // = 0xd1,
"KeyInsert", // = 0xd2,
"KeyDelete", // = 0xd3,
"<unknown:d4>",
"<unknown:d5>",
"<unknown:d6>",
"<unknown:d7>",
"<unknown:d8>",
"<unknown:d9>",
"<unknown:da>",
"KeyLeftGui", // = 0xdb,
"KeyRightGui", // = 0xdc,
"KeyApps", // = 0xdd,
"KeyAcpiPower", // = 0xde,
"KeyAcpiSleep", // = 0xdf,
"<unknown:e0>",
"<unknown:e1>",
"<unknown:e2>",
"KeyAcpiWake", // = 0xe3,
"<unknown:e4>",
"KeyMediaWwwSearch", // = 0xe5,
"KeyMediaWwwFavorites", // = 0xe6,
"KeyMediaWwwRefresh", // = 0xe7,
"KeyMediaWwwStop", // = 0xe8,
"KeyMediaWwwForward", // = 0xe9,
"KeyMediaWwwBack", // = 0xea,
"KeyMediaMyComputer", // = 0xeb,
"KeyMediaEmail", // = 0xec,
"KeyMediaSelect", // = 0xed,
"<unknown:ee>",
"<unknown:ef>",
"<unknown:f0>",
"<unknown:f1>",
"<unknown:f2>",
"<unknown:f3>",
"<unknown:f4>",
"<unknown:f5>",
"<unknown:f6>",
"<unknown:f7>",
"<unknown:f8>",
"<unknown:f9>",
"<unknown:fa>",
"<unknown:fb>",
"<unknown:fc>",
"<unknown:fd>",
"KeyPrint", // = 0xfe,
"KeyPause", // = 0xff,
};
void keyboardIsr() {
keyboard.Isr();
}
Keyboard::Keyboard() {
_go32_dpmi_get_protected_mode_interrupt_vector(9, &_oldIsr);
_newIsr.pm_offset = (int)keyboardIsr;
_newIsr.pm_selector = _go32_my_cs();
_go32_dpmi_allocate_iret_wrapper(&_newIsr);
_go32_dpmi_set_protected_mode_interrupt_vector(9, &_newIsr);
}
Keyboard::~Keyboard() {
_go32_dpmi_set_protected_mode_interrupt_vector(9, &_oldIsr);
_go32_dpmi_free_iret_wrapper(&_newIsr);
}
Keyboard::KeyHandleFunction Keyboard::setKeyUpHandler(KeyHandleFunction handler) {
auto oldHandler = _keyUpHandler;
_keyUpHandler = handler;
return oldHandler;
}
Keyboard::KeyHandleFunction Keyboard::setKeyDownHandler(KeyHandleFunction handler) {
auto oldHandler = _keyDownHandler;
_keyDownHandler = handler;
return oldHandler;
}
Keyboard::KeyHandleFunction Keyboard::setKeyRepeatHandler(KeyHandleFunction handler) {
auto oldHandler = _keyRepeatHandler;
_keyRepeatHandler = handler;
return oldHandler;
}
const char *Keyboard::getKeyName(unsigned char keyCode) {
return keyNames[keyCode];
}
void Keyboard::Isr() {
auto code = inb(KEYB_DATA);
switch (_state) {
case Start:
if (code == 0xe0) {
_state = Extended;
break;
}
if (code == 0xe1) {
_state = PauseBegin;
break;
}
if (code & 0x80) {
_state = Start;
keyUp(code & 0x7f);
} else {
_state = Start;
keyDown(code & 0x7f);
}
break;
case Extended:
if (code == 0x2a) {
_state = PrintPressed1;
break;
}
if (code == 0xb7) {
_state = PrintReleased1;
break;
}
if (code & 0x80) {
_state = Start;
keyUp(0x80 + (code & 0x7f));
} else {
_state = Start;
keyDown(0x80 + code);
}
break;
case PauseBegin:
if (code == 0x1d) {
_state = PausePressed1;
break;
}
if (code == 0x9d) {
_state = PauseReleased1;
break;
}
_state = Start;
break;
case PausePressed1:
if (code == 45) {
keyDown(KeyPause);
}
_state = Start;
break;
case PauseReleased1:
if (code == 0xc5) {
keyUp(KeyPause);
}
_state = Start;
break;
case PrintPressed1:
if (code == 0xe0) {
_state = PrintPressed2;
break;
}
_state = Start;
break;
case PrintPressed2:
if (code == 0x37) {
keyDown(KeyPrint);
}
_state = Start;
break;
case PrintReleased1:
if (code == 0xe0) {
_state = PrintReleased2;
break;
}
_state = Start;
break;
case PrintReleased2:
if (code == 0xaa) {
keyUp(KeyPrint);
}
_state = Start;
break;
}
Pic::clearInterrupt();
}
void Keyboard::keyDown(unsigned char c) {
if (keyState[c]) {
if (_keyRepeatHandler) _keyRepeatHandler(c);
} else {
keyState[c] = true;
if (_keyDownHandler) _keyDownHandler(c);
}
}
void Keyboard::keyUp(unsigned char c) {
keyState[c] = false;
if (_keyUpHandler) _keyUpHandler(c);
}