/** * Copyright (c) 2017 rxi * * This library is free software; you can redistribute it and/or modify it * under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include "luaobj.h" #include "keyboard.h" #include "event.h" #define KEY_MAX 128 #define BUFFER_SIZE 32 #define BUFFER_MASK (BUFFER_SIZE - 1) static const char *scancodeMap[] = { [0] = "?", [1] = "escape", [2] = "1", [3] = "2", [4] = "3", [5] = "4", [6] = "5", [7] = "6", [8] = "7", [9] = "8", [10] = "9", [11] = "0", [12] = "-", [13] = "=", [14] = "backspace", [15] = "tab", [16] = "q", [17] = "w", [18] = "e", [19] = "r", [20] = "t", [21] = "y", [22] = "u", [23] = "i", [24] = "o", [25] = "p", [26] = "[", [27] = "]", [28] = "return", [29] = "lctrl", [30] = "a", [31] = "s", [32] = "d", [33] = "f", [34] = "g", [35] = "h", [36] = "j", [37] = "k", [38] = "l", [39] = ";", [40] = "\"", [41] = "`", [42] = "lshift", [43] = "\\", [44] = "z", [45] = "x", [46] = "c", [47] = "v", [48] = "b", [49] = "n", [50] = "m", [51] = ",", [52] = ".", [53] = "/", [54] = "rshift", [55] = "*", [56] = "lalt", [57] = "space", [58] = "capslock", [59] = "f1", [60] = "f2", [61] = "f3", [62] = "f4", [63] = "f5", [64] = "f6", [65] = "f7", [66] = "f8", [67] = "f9", [68] = "f10", [69] = "numlock", [70] = "scrolllock", [71] = "home", [72] = "up", [73] = "pageup", [74] = "-", [75] = "left", [76] = "5", [77] = "right", [78] = "+", [79] = "end", [80] = "down", [81] = "pagedown", [82] = "insert", [83] = "delete", [84] = "?", [85] = "?", [86] = "?", [87] = "?", [88] = "f12", [89] = "?", [90] = "?", [91] = "?", [92] = "?", [93] = "?", [94] = "?", [95] = "?", [96] = "enter", [97] = "lctrl", [98] = "/", [99] = "f12", [100] = "rctrl", [101] = "pause", [102] = "home", [103] = "up", [104] = "pageup", [105] = "left", [106] = "right", [107] = "end", [108] = "down", [109] = "pagedown", [110] = "insert", [111] = "?", [112] = "?", [113] = "?", [114] = "?", [115] = "?", [116] = "?", [117] = "?", [118] = "?", [119] = "pause", [120] = "?", [121] = "?", [122] = "?", [123] = "?", [124] = "?", [125] = "?", [126] = "?", [127] = "?", [128] = NULL, }; volatile int keyboard_allowKeyRepeat = 0; volatile char keyboard_keyStates[KEY_MAX]; enum { KEYPRESSED, KEYRELEASED }; typedef struct { unsigned char type, code, isrepeat; } key_event_t; volatile struct { key_event_t data[32]; unsigned readi, writei; } keyboard_events; _go32_dpmi_seginfo old_keyb_handler_seginfo, new_keyb_handler_seginfo; void keyboard_handler() { static unsigned char code; code = inportb(0x60); if (code != 224) { volatile key_event_t *e; /* Handle key up / down */ if (code & (1 << 7)) { /* Key up */ code &= ~(1 << 7); keyboard_keyStates[code] = 0; e = &keyboard_events.data[keyboard_events.writei & BUFFER_MASK]; e->type = KEYRELEASED; e->code = code; e->isrepeat = 0; keyboard_events.writei++; } else { /* Key down */ int isrepeat = keyboard_keyStates[code]; if (!isrepeat || keyboard_allowKeyRepeat) { keyboard_keyStates[code] = 1; e = &keyboard_events.data[keyboard_events.writei & BUFFER_MASK]; e->type = KEYPRESSED; e->code = code; e->isrepeat = isrepeat; keyboard_events.writei++; } } } outportb(0x20, 0x20); } void keyboard_handler_end() {} int keyboard_init(void) { _go32_dpmi_lock_data((char *)&keyboard_keyStates, KEY_MAX); _go32_dpmi_lock_data((char *)&keyboard_events, sizeof(keyboard_events)); _go32_dpmi_lock_code(keyboard_handler, (unsigned long)keyboard_handler_end - (unsigned long)keyboard_handler); _go32_dpmi_get_protected_mode_interrupt_vector(9, &old_keyb_handler_seginfo); new_keyb_handler_seginfo.pm_offset = (int)keyboard_handler; _go32_dpmi_chain_protected_mode_interrupt_vector(9, &new_keyb_handler_seginfo); return 0; } void keyboard_deinit(void) { _go32_dpmi_set_protected_mode_interrupt_vector(9, &old_keyb_handler_seginfo); } void keyboard_setKeyRepeat(int allow) { keyboard_allowKeyRepeat = allow; } int keyboard_isDown(const char *key) { int i; for (i = 0; scancodeMap[i]; i++) { if (!strcmp(scancodeMap[i], key)) { return keyboard_keyStates[i]; } } return 0; } void keyboard_update(void) { /* Handle key press / release */ while (keyboard_events.readi != keyboard_events.writei) { key_event_t ke = keyboard_events.data[keyboard_events.readi++ & BUFFER_MASK]; event_t e; if (ke.type == KEYPRESSED) { e.type = EVENT_KEYBOARD_PRESSED; } else { e.type = EVENT_KEYBOARD_RELEASED; } e.keyboard.key = scancodeMap[ke.code]; e.keyboard.isrepeat = ke.isrepeat; event_push(&e); } /* Handle text input */ char buf[64]; int i = 0; while (kbhit()) { int chr = getch(); if (chr == 0) { /* Discard "special" keys */ getch(); } else if (chr >= 32) { buf[i++] = chr; } } if (i > 0) { event_t e; e.type = EVENT_KEYBOARD_TEXTINPUT; memcpy(e.keyboard.text, buf, i); e.keyboard.text[i] = '\0'; event_push(&e); } }