diff options
Diffstat (limited to 'src/glut/dos/PC_HW/pc_keyb.c')
-rw-r--r-- | src/glut/dos/PC_HW/pc_keyb.c | 1084 |
1 files changed, 542 insertions, 542 deletions
diff --git a/src/glut/dos/PC_HW/pc_keyb.c b/src/glut/dos/PC_HW/pc_keyb.c index ec509c2..d3c87bc 100644 --- a/src/glut/dos/PC_HW/pc_keyb.c +++ b/src/glut/dos/PC_HW/pc_keyb.c @@ -1,542 +1,542 @@ -/*
- * PC/HW routine collection v1.3 for DOS/DJGPP
- *
- * Copyright (C) 2002 - Borca Daniel
- * Email : dborca@yahoo.com
- * Web : http://www.geocities.com/dborca
- */
-
-
-#include <pc.h>
-#include <sys/exceptn.h>
-#include <sys/farptr.h>
-
-#include "pc_hw.h"
-
-
-
-#define KEYB_IRQ 1
-
-#define KEY_BUFFER_SIZE 64
-
-#define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG)
-#define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG)
-
-static int keyboard_installed;
-
-static volatile struct {
- volatile int start, end;
- volatile int key[KEY_BUFFER_SIZE];
-} key_buffer;
-
-static volatile int key_enhanced, key_pause_loop, key_shifts;
-static int leds_ok = TRUE;
-static int in_a_terrupt = FALSE;
-static volatile char pc_key[KEY_MAX];
-
-
-
-/* convert Allegro format scancodes into key_shifts flag bits */
-static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] =
-{
- KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG,
- KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG,
- KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG,
- KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG
-};
-
-
-
-/* lookup table for converting hardware scancodes into Allegro format */
-static unsigned char hw_to_mycode[128] =
-{
- /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
- /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
- /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
- /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
- /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R,
- /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I,
- /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
- /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S,
- /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
- /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
- /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH,
- /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
- /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
- /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK,
- /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
- /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
- /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
- /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD,
- /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD,
- /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD,
- /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD,
- /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
- /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
- /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
- /* 0x60 */ 0, 0, 0, 0,
- /* 0x64 */ 0, 0, 0, 0,
- /* 0x68 */ 0, 0, 0, 0,
- /* 0x6C */ 0, 0, 0, 0,
- /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1,
- /* 0x74 */ 0, 0, 0, 0,
- /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT,
- /* 0x7C */ 0, KEY_YEN, 0, 0
-};
-
-
-
-/* lookup table for converting extended hardware codes into Allegro format */
-static unsigned char hw_to_mycode_ex[128] =
-{
- /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
- /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
- /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
- /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
- /* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R,
- /* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I,
- /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
- /* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S,
- /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
- /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
- /* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH,
- /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
- /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
- /* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR,
- /* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
- /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
- /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
- /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME,
- /* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT,
- /* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END,
- /* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL,
- /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
- /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
- /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
- /* 0x60 */ 0, 0, 0, 0,
- /* 0x64 */ 0, 0, 0, 0,
- /* 0x68 */ 0, 0, 0, 0,
- /* 0x6C */ 0, 0, 0, 0,
- /* 0x70 */ 0, 0, 0, 0,
- /* 0x74 */ 0, 0, 0, 0,
- /* 0x78 */ 0, 0, 0, 0,
- /* 0x7C */ 0, 0, 0, 0
-};
-
-
-
-/* default mapping table for the US keyboard layout */
-static unsigned short standard_key_ascii_table[KEY_MAX] =
-{
- /* start */ 0,
- /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
- /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* numpad */ '/', '*', '-', '+', '.', 13,
- /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-
-/* capslock mapping table for the US keyboard layout */
-static unsigned short standard_key_capslock_table[KEY_MAX] =
-{
- /* start */ 0,
- /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
- /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* numpad */ '/', '*', '-', '+', '.', 13,
- /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-
-/* shifted mapping table for the US keyboard layout */
-static unsigned short standard_key_shift_table[KEY_MAX] =
-{
- /* start */ 0,
- /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
- /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ',
- /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* numpad */ '/', '*', '-', '+', '.', 13,
- /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-
-/* ctrl+key mapping table for the US keyboard layout */
-static unsigned short standard_key_control_table[KEY_MAX] =
-{
- /* start */ 0,
- /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
- /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
- /* numpad */ 2, 2, 2, 2, 2, 10,
- /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-
-/* convert numeric pad scancodes into arrow codes */
-static unsigned char numlock_table[10] =
-{
- KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT,
- KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP
-};
-
-
-
-/* kb_wait_for_write_ready:
- * Wait for the keyboard controller to set the ready-for-write bit.
- */
-static __inline int kb_wait_for_write_ready (void)
-{
- int timeout = 4096;
-
- while ((timeout>0) && (inportb(0x64)&2)) timeout--;
-
- return (timeout>0);
-}
-
-
-
-/* kb_wait_for_read_ready:
- * Wait for the keyboard controller to set the ready-for-read bit.
- */
-static __inline int kb_wait_for_read_ready (void)
-{
- int timeout = 16384;
-
- while ((timeout>0) && (!(inportb(0x64)&1))) timeout--;
-
- return (timeout>0);
-}
-
-
-
-/* kb_send_data:
- * Sends a byte to the keyboard controller. Returns 1 if all OK.
- */
-static __inline int kb_send_data (unsigned char data)
-{
- int resends = 4;
- int timeout, temp;
-
- do {
- if (!kb_wait_for_write_ready())
- return 0;
-
- outportb(0x60, data);
- timeout = 4096;
-
- while (--timeout>0) {
- if (!kb_wait_for_read_ready())
- return 0;
-
- temp = inportb(0x60);
-
- if (temp == 0xFA)
- return 1;
-
- if (temp == 0xFE)
- break;
- }
- } while ((resends-- > 0) && (timeout > 0));
-
- return 0;
-}
-
-
-
-static void update_leds (int leds)
-{
- if (leds_ok) {
- if (!in_a_terrupt)
- DISABLE();
-
- if (!kb_send_data(0xED)) {
- kb_send_data(0xF4);
- leds_ok = FALSE;
- } else if (!kb_send_data((leds>>8)&7)) {
- kb_send_data(0xF4);
- leds_ok = FALSE;
- }
-
- if (!in_a_terrupt)
- ENABLE();
- }
-} ENDOFUNC(update_leds)
-
-
-
-static void inject_key (int scancode)
-{
- unsigned short *table;
-
- if ((scancode >= KEY_0_PAD) && (scancode <= KEY_9_PAD)) {
- if (((key_shifts & KB_NUMLOCK_FLAG) != 0) == ((key_shifts & KB_SHIFT_FLAG) != 0)) {
- scancode = numlock_table[scancode - KEY_0_PAD];
- }
- table = standard_key_ascii_table;
- } else if (key_shifts & KB_CTRL_FLAG) {
- table = standard_key_control_table;
- } else if (key_shifts & KB_SHIFT_FLAG) {
- if (key_shifts & KB_CAPSLOCK_FLAG) {
- if (standard_key_ascii_table[scancode]==standard_key_capslock_table[scancode]) {
- table = standard_key_shift_table;
- } else {
- table = standard_key_ascii_table;
- }
- } else {
- table = standard_key_shift_table;
- }
- } else if (key_shifts & KB_CAPSLOCK_FLAG) {
- table = standard_key_capslock_table;
- } else {
- table = standard_key_ascii_table;
- }
-
- key_buffer.key[key_buffer.end++] = (scancode<<16)|table[scancode];
-
- if (key_buffer.end>=KEY_BUFFER_SIZE)
- key_buffer.end = 0;
- if (key_buffer.end==key_buffer.start) {
- key_buffer.start++;
- if (key_buffer.start>=KEY_BUFFER_SIZE)
- key_buffer.start = 0;
- }
-} ENDOFUNC(inject_key)
-
-static void handle_code (int scancode, int keycode)
-{
- in_a_terrupt++;
-
- if (keycode==0) { /* pause */
- inject_key(scancode);
- pc_key[KEY_PAUSE] ^= TRUE;
- } else if (scancode) {
- int flag;
-
- if (scancode>=KEY_MODIFIERS) {
- flag = modifier_table[scancode - KEY_MODIFIERS];
- } else {
- flag = 0;
- }
- if ((char)keycode<0) { /* release */
- pc_key[scancode] = FALSE;
- if (flag&KB_MODIFIERS) {
- key_shifts &= ~flag;
- }
- } else { /* keypress */
- pc_key[scancode] = TRUE;
- if (flag&KB_MODIFIERS) {
- key_shifts |= flag;
- }
- if (flag&KB_LED_FLAGS) {
- key_shifts ^= flag;
- update_leds(key_shifts);
- }
- if (scancode<KEY_MODIFIERS) {
- inject_key(scancode);
- }
- }
- }
-
- in_a_terrupt--;
-} ENDOFUNC(handle_code)
-
-static int keyboard ()
-{
- unsigned char temp, scancode;
-
- temp = inportb(0x60);
-
- if (temp<=0xe1) {
- if (key_pause_loop) {
- if (!--key_pause_loop) handle_code(KEY_PAUSE, 0);
- } else
- switch (temp) {
- case 0xe0:
- key_enhanced = TRUE;
- break;
- case 0xe1:
- key_pause_loop = 5;
- break;
- default:
- if (key_enhanced) {
- key_enhanced = FALSE;
- scancode = hw_to_mycode_ex[temp&0x7f];
- } else {
- scancode = hw_to_mycode[temp&0x7f];
- }
- handle_code(scancode, temp);
- }
- }
-
- if (((temp==0x4F)||(temp==0x53))&&(key_shifts&KB_CTRL_FLAG)&&(key_shifts&KB_ALT_FLAG)) {
- /* Hack alert:
- only SIGINT (but not Ctrl-Break)
- calls the destructors and will safely clean up
- */
- __asm("\n\
- movb $0x79, %%al \n\
- call ___djgpp_hw_exception \n\
- ":::"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
- }
-
- __asm("\n\
- inb $0x61, %%al \n\
- movb %%al, %%ah \n\
- orb $0x80, %%al \n\
- outb %%al, $0x61 \n\
- xchgb %%al, %%ah \n\
- outb %%al, $0x61 \n\
- movb $0x20, %%al \n\
- outb %%al, $0x20 \n\
- ":::"%eax");
- return 0;
-} ENDOFUNC(keyboard)
-
-
-int pc_keypressed (void)
-{
- return (key_buffer.start!=key_buffer.end);
-}
-
-int pc_readkey (void)
-{
- if (keyboard_installed) {
- int key;
-
- while (key_buffer.start==key_buffer.end) {
- __dpmi_yield();
- }
-
- DISABLE();
- key = key_buffer.key[key_buffer.start++];
- if (key_buffer.start>=KEY_BUFFER_SIZE)
- key_buffer.start = 0;
- ENABLE();
-
- return key;
- } else {
- return 0;
- }
-}
-
-int pc_keydown (int code)
-{
- return pc_key[code];
-}
-
-int pc_keyshifts (void)
-{
- return key_shifts;
-}
-
-void pc_remove_keyb (void)
-{
- if (keyboard_installed) {
- int s1, s2, s3;
-
- keyboard_installed = FALSE;
- pc_clexit(pc_remove_keyb);
-
- DISABLE();
- _farsetsel(__djgpp_dos_sel);
- _farnspokew(0x41c, _farnspeekw(0x41a));
-
- s1 = _farnspeekb(0x417) & 0x80;
- s2 = _farnspeekb(0x418) & 0xFC;
- s3 = _farnspeekb(0x496) & 0xF3;
-
- if (pc_key[KEY_RSHIFT]) { s1 |= 1; }
- if (pc_key[KEY_LSHIFT]) { s1 |= 2; }
- if (pc_key[KEY_LCONTROL]) { s2 |= 1; s1 |= 4; }
- if (pc_key[KEY_ALT]) { s1 |= 8; s2 |= 2; }
- if (pc_key[KEY_RCONTROL]) { s1 |= 4; s3 |= 4; }
- if (pc_key[KEY_ALTGR]) { s1 |= 8; s3 |= 8; }
-
- if (key_shifts&KB_SCROLOCK_FLAG) s1 |= 16;
- if (key_shifts&KB_NUMLOCK_FLAG) s1 |= 32;
- if (key_shifts&KB_CAPSLOCK_FLAG) s1 |= 64;
-
- _farnspokeb(0x417, s1);
- _farnspokeb(0x418, s2);
- _farnspokeb(0x496, s3);
- update_leds(key_shifts);
-
- ENABLE();
- pc_remove_irq(KEYB_IRQ);
- }
-}
-
-int pc_install_keyb (void)
-{
- if (keyboard_installed||pc_install_irq(KEYB_IRQ, keyboard)) {
- return -1;
- } else {
- int s1, s2, s3;
-
- LOCKDATA(key_buffer);
- LOCKDATA(key_enhanced);
- LOCKDATA(key_pause_loop);
- LOCKDATA(key_shifts);
- LOCKDATA(leds_ok);
- LOCKDATA(in_a_terrupt);
- LOCKDATA(pc_key);
- LOCKDATA(modifier_table);
- LOCKDATA(hw_to_mycode);
- LOCKDATA(hw_to_mycode_ex);
- LOCKDATA(standard_key_ascii_table);
- LOCKDATA(standard_key_capslock_table);
- LOCKDATA(standard_key_shift_table);
- LOCKDATA(standard_key_control_table);
- LOCKDATA(numlock_table);
- LOCKFUNC(update_leds);
- LOCKFUNC(inject_key);
- LOCKFUNC(handle_code);
- LOCKFUNC(keyboard);
-
- DISABLE();
- _farsetsel(__djgpp_dos_sel);
- _farnspokew(0x41c, _farnspeekw(0x41a));
-
- key_shifts = 0;
- s1 = _farnspeekb(0x417);
- s2 = _farnspeekb(0x418);
- s3 = _farnspeekb(0x496);
-
- if (s1&1) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_RSHIFT] = TRUE; }
- if (s1&2) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_LSHIFT] = TRUE; }
- if (s2&1) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_LCONTROL] = TRUE; }
- if (s2&2) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALT] = TRUE; }
- if (s3&4) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_RCONTROL] = TRUE; }
- if (s3&8) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALTGR] = TRUE; }
-
- if (s1&16) key_shifts |= KB_SCROLOCK_FLAG;
- if (s1&32) key_shifts |= KB_NUMLOCK_FLAG;
- if (s1&64) key_shifts |= KB_CAPSLOCK_FLAG;
- update_leds(key_shifts);
-
- key_enhanced = key_pause_loop = 0;
- key_buffer.start = key_buffer.end = 0;
- ENABLE();
-
- pc_atexit(pc_remove_keyb);
- keyboard_installed = TRUE;
- return 0;
- }
-}
+/* + * PC/HW routine collection v1.3 for DOS/DJGPP + * + * Copyright (C) 2002 - Borca Daniel + * Email : dborca@yahoo.com + * Web : http://www.geocities.com/dborca + */ + + +#include <pc.h> +#include <sys/exceptn.h> +#include <sys/farptr.h> + +#include "pc_hw.h" + + + +#define KEYB_IRQ 1 + +#define KEY_BUFFER_SIZE 64 + +#define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG) +#define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG) + +static int keyboard_installed; + +static volatile struct { + volatile int start, end; + volatile int key[KEY_BUFFER_SIZE]; +} key_buffer; + +static volatile int key_enhanced, key_pause_loop, key_shifts; +static int leds_ok = TRUE; +static int in_a_terrupt = FALSE; +static volatile char pc_key[KEY_MAX]; + + + +/* convert Allegro format scancodes into key_shifts flag bits */ +static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] = +{ + KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG, + KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG, + KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG, + KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG +}; + + + +/* lookup table for converting hardware scancodes into Allegro format */ +static unsigned char hw_to_mycode[128] = +{ + /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2, + /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6, + /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0, + /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, + /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R, + /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I, + /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE, + /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S, + /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H, + /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON, + /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH, + /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V, + /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA, + /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK, + /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, + /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5, + /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, + /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD, + /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD, + /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD, + /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD, + /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11, + /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN, + /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0, + /* 0x60 */ 0, 0, 0, 0, + /* 0x64 */ 0, 0, 0, 0, + /* 0x68 */ 0, 0, 0, 0, + /* 0x6C */ 0, 0, 0, 0, + /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1, + /* 0x74 */ 0, 0, 0, 0, + /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT, + /* 0x7C */ 0, KEY_YEN, 0, 0 +}; + + + +/* lookup table for converting extended hardware codes into Allegro format */ +static unsigned char hw_to_mycode_ex[128] = +{ + /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2, + /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6, + /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0, + /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, + /* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R, + /* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I, + /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE, + /* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S, + /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H, + /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON, + /* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH, + /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V, + /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA, + /* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR, + /* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, + /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5, + /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, + /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME, + /* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT, + /* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END, + /* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL, + /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11, + /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN, + /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0, + /* 0x60 */ 0, 0, 0, 0, + /* 0x64 */ 0, 0, 0, 0, + /* 0x68 */ 0, 0, 0, 0, + /* 0x6C */ 0, 0, 0, 0, + /* 0x70 */ 0, 0, 0, 0, + /* 0x74 */ 0, 0, 0, 0, + /* 0x78 */ 0, 0, 0, 0, + /* 0x7C */ 0, 0, 0, 0 +}; + + + +/* default mapping table for the US keyboard layout */ +static unsigned short standard_key_ascii_table[KEY_MAX] = +{ + /* start */ 0, + /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', + /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* numpad */ '/', '*', '-', '+', '.', 13, + /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* capslock mapping table for the US keyboard layout */ +static unsigned short standard_key_capslock_table[KEY_MAX] = +{ + /* start */ 0, + /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', + /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* numpad */ '/', '*', '-', '+', '.', 13, + /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* shifted mapping table for the US keyboard layout */ +static unsigned short standard_key_shift_table[KEY_MAX] = +{ + /* start */ 0, + /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', + /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ', + /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* numpad */ '/', '*', '-', '+', '.', 13, + /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* ctrl+key mapping table for the US keyboard layout */ +static unsigned short standard_key_control_table[KEY_MAX] = +{ + /* start */ 0, + /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, + /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + /* numpad */ 2, 2, 2, 2, 2, 10, + /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* convert numeric pad scancodes into arrow codes */ +static unsigned char numlock_table[10] = +{ + KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT, + KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP +}; + + + +/* kb_wait_for_write_ready: + * Wait for the keyboard controller to set the ready-for-write bit. + */ +static __inline int kb_wait_for_write_ready (void) +{ + int timeout = 4096; + + while ((timeout>0) && (inportb(0x64)&2)) timeout--; + + return (timeout>0); +} + + + +/* kb_wait_for_read_ready: + * Wait for the keyboard controller to set the ready-for-read bit. + */ +static __inline int kb_wait_for_read_ready (void) +{ + int timeout = 16384; + + while ((timeout>0) && (!(inportb(0x64)&1))) timeout--; + + return (timeout>0); +} + + + +/* kb_send_data: + * Sends a byte to the keyboard controller. Returns 1 if all OK. + */ +static __inline int kb_send_data (unsigned char data) +{ + int resends = 4; + int timeout, temp; + + do { + if (!kb_wait_for_write_ready()) + return 0; + + outportb(0x60, data); + timeout = 4096; + + while (--timeout>0) { + if (!kb_wait_for_read_ready()) + return 0; + + temp = inportb(0x60); + + if (temp == 0xFA) + return 1; + + if (temp == 0xFE) + break; + } + } while ((resends-- > 0) && (timeout > 0)); + + return 0; +} + + + +static void update_leds (int leds) +{ + if (leds_ok) { + if (!in_a_terrupt) + DISABLE(); + + if (!kb_send_data(0xED)) { + kb_send_data(0xF4); + leds_ok = FALSE; + } else if (!kb_send_data((leds>>8)&7)) { + kb_send_data(0xF4); + leds_ok = FALSE; + } + + if (!in_a_terrupt) + ENABLE(); + } +} ENDOFUNC(update_leds) + + + +static void inject_key (int scancode) +{ + unsigned short *table; + + if ((scancode >= KEY_0_PAD) && (scancode <= KEY_9_PAD)) { + if (((key_shifts & KB_NUMLOCK_FLAG) != 0) == ((key_shifts & KB_SHIFT_FLAG) != 0)) { + scancode = numlock_table[scancode - KEY_0_PAD]; + } + table = standard_key_ascii_table; + } else if (key_shifts & KB_CTRL_FLAG) { + table = standard_key_control_table; + } else if (key_shifts & KB_SHIFT_FLAG) { + if (key_shifts & KB_CAPSLOCK_FLAG) { + if (standard_key_ascii_table[scancode]==standard_key_capslock_table[scancode]) { + table = standard_key_shift_table; + } else { + table = standard_key_ascii_table; + } + } else { + table = standard_key_shift_table; + } + } else if (key_shifts & KB_CAPSLOCK_FLAG) { + table = standard_key_capslock_table; + } else { + table = standard_key_ascii_table; + } + + key_buffer.key[key_buffer.end++] = (scancode<<16)|table[scancode]; + + if (key_buffer.end>=KEY_BUFFER_SIZE) + key_buffer.end = 0; + if (key_buffer.end==key_buffer.start) { + key_buffer.start++; + if (key_buffer.start>=KEY_BUFFER_SIZE) + key_buffer.start = 0; + } +} ENDOFUNC(inject_key) + +static void handle_code (int scancode, int keycode) +{ + in_a_terrupt++; + + if (keycode==0) { /* pause */ + inject_key(scancode); + pc_key[KEY_PAUSE] ^= TRUE; + } else if (scancode) { + int flag; + + if (scancode>=KEY_MODIFIERS) { + flag = modifier_table[scancode - KEY_MODIFIERS]; + } else { + flag = 0; + } + if ((char)keycode<0) { /* release */ + pc_key[scancode] = FALSE; + if (flag&KB_MODIFIERS) { + key_shifts &= ~flag; + } + } else { /* keypress */ + pc_key[scancode] = TRUE; + if (flag&KB_MODIFIERS) { + key_shifts |= flag; + } + if (flag&KB_LED_FLAGS) { + key_shifts ^= flag; + update_leds(key_shifts); + } + if (scancode<KEY_MODIFIERS) { + inject_key(scancode); + } + } + } + + in_a_terrupt--; +} ENDOFUNC(handle_code) + +static int keyboard () +{ + unsigned char temp, scancode; + + temp = inportb(0x60); + + if (temp<=0xe1) { + if (key_pause_loop) { + if (!--key_pause_loop) handle_code(KEY_PAUSE, 0); + } else + switch (temp) { + case 0xe0: + key_enhanced = TRUE; + break; + case 0xe1: + key_pause_loop = 5; + break; + default: + if (key_enhanced) { + key_enhanced = FALSE; + scancode = hw_to_mycode_ex[temp&0x7f]; + } else { + scancode = hw_to_mycode[temp&0x7f]; + } + handle_code(scancode, temp); + } + } + + if (((temp==0x4F)||(temp==0x53))&&(key_shifts&KB_CTRL_FLAG)&&(key_shifts&KB_ALT_FLAG)) { + /* Hack alert: + only SIGINT (but not Ctrl-Break) + calls the destructors and will safely clean up + */ + __asm("\n\ + movb $0x79, %%al \n\ + call ___djgpp_hw_exception \n\ + ":::"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); + } + + __asm("\n\ + inb $0x61, %%al \n\ + movb %%al, %%ah \n\ + orb $0x80, %%al \n\ + outb %%al, $0x61 \n\ + xchgb %%al, %%ah \n\ + outb %%al, $0x61 \n\ + movb $0x20, %%al \n\ + outb %%al, $0x20 \n\ + ":::"%eax"); + return 0; +} ENDOFUNC(keyboard) + + +int pc_keypressed (void) +{ + return (key_buffer.start!=key_buffer.end); +} + +int pc_readkey (void) +{ + if (keyboard_installed) { + int key; + + while (key_buffer.start==key_buffer.end) { + __dpmi_yield(); + } + + DISABLE(); + key = key_buffer.key[key_buffer.start++]; + if (key_buffer.start>=KEY_BUFFER_SIZE) + key_buffer.start = 0; + ENABLE(); + + return key; + } else { + return 0; + } +} + +int pc_keydown (int code) +{ + return pc_key[code]; +} + +int pc_keyshifts (void) +{ + return key_shifts; +} + +void pc_remove_keyb (void) +{ + if (keyboard_installed) { + int s1, s2, s3; + + keyboard_installed = FALSE; + pc_clexit(pc_remove_keyb); + + DISABLE(); + _farsetsel(__djgpp_dos_sel); + _farnspokew(0x41c, _farnspeekw(0x41a)); + + s1 = _farnspeekb(0x417) & 0x80; + s2 = _farnspeekb(0x418) & 0xFC; + s3 = _farnspeekb(0x496) & 0xF3; + + if (pc_key[KEY_RSHIFT]) { s1 |= 1; } + if (pc_key[KEY_LSHIFT]) { s1 |= 2; } + if (pc_key[KEY_LCONTROL]) { s2 |= 1; s1 |= 4; } + if (pc_key[KEY_ALT]) { s1 |= 8; s2 |= 2; } + if (pc_key[KEY_RCONTROL]) { s1 |= 4; s3 |= 4; } + if (pc_key[KEY_ALTGR]) { s1 |= 8; s3 |= 8; } + + if (key_shifts&KB_SCROLOCK_FLAG) s1 |= 16; + if (key_shifts&KB_NUMLOCK_FLAG) s1 |= 32; + if (key_shifts&KB_CAPSLOCK_FLAG) s1 |= 64; + + _farnspokeb(0x417, s1); + _farnspokeb(0x418, s2); + _farnspokeb(0x496, s3); + update_leds(key_shifts); + + ENABLE(); + pc_remove_irq(KEYB_IRQ); + } +} + +int pc_install_keyb (void) +{ + if (keyboard_installed||pc_install_irq(KEYB_IRQ, keyboard)) { + return -1; + } else { + int s1, s2, s3; + + LOCKDATA(key_buffer); + LOCKDATA(key_enhanced); + LOCKDATA(key_pause_loop); + LOCKDATA(key_shifts); + LOCKDATA(leds_ok); + LOCKDATA(in_a_terrupt); + LOCKDATA(pc_key); + LOCKDATA(modifier_table); + LOCKDATA(hw_to_mycode); + LOCKDATA(hw_to_mycode_ex); + LOCKDATA(standard_key_ascii_table); + LOCKDATA(standard_key_capslock_table); + LOCKDATA(standard_key_shift_table); + LOCKDATA(standard_key_control_table); + LOCKDATA(numlock_table); + LOCKFUNC(update_leds); + LOCKFUNC(inject_key); + LOCKFUNC(handle_code); + LOCKFUNC(keyboard); + + DISABLE(); + _farsetsel(__djgpp_dos_sel); + _farnspokew(0x41c, _farnspeekw(0x41a)); + + key_shifts = 0; + s1 = _farnspeekb(0x417); + s2 = _farnspeekb(0x418); + s3 = _farnspeekb(0x496); + + if (s1&1) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_RSHIFT] = TRUE; } + if (s1&2) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_LSHIFT] = TRUE; } + if (s2&1) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_LCONTROL] = TRUE; } + if (s2&2) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALT] = TRUE; } + if (s3&4) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_RCONTROL] = TRUE; } + if (s3&8) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALTGR] = TRUE; } + + if (s1&16) key_shifts |= KB_SCROLOCK_FLAG; + if (s1&32) key_shifts |= KB_NUMLOCK_FLAG; + if (s1&64) key_shifts |= KB_CAPSLOCK_FLAG; + update_leds(key_shifts); + + key_enhanced = key_pause_loop = 0; + key_buffer.start = key_buffer.end = 0; + ENABLE(); + + pc_atexit(pc_remove_keyb); + keyboard_installed = TRUE; + return 0; + } +} |