|
|
1.1 root 1: /*
1.1.1.6 root 2: Hatari - keymap.c
1.1.1.5 root 3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
1.1 root 6:
1.1.1.3 root 7: Here we process a key press and the remapping of the scancodes.
1.1 root 8: */
1.1.1.10! root 9: const char Keymap_rcsid[] = "Hatari $Id: keymap.c,v 1.32 2008/01/12 02:04:59 thothy Exp $";
1.1 root 10:
11: #include "main.h"
12: #include "keymap.h"
13: #include "misc.h"
1.1.1.5 root 14: #include "configuration.h"
1.1.1.10! root 15: #include "file.h"
1.1.1.3 root 16: #include "ikbd.h"
17: #include "joy.h"
18: #include "shortcut.h"
19: #include "screen.h"
1.1.1.4 root 20: #include "debugui.h"
1.1.1.9 root 21: #include "log.h"
1.1 root 22:
1.1.1.2 root 23:
24: /*-----------------------------------------------------------------------*/
1.1 root 25: /*
1.1.1.5 root 26: Remap table of PC keys to ST scan codes, -ve is invalid key (ie doesn't occur on ST)
1.1 root 27:
28: PC Keyboard:-
29:
30: Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Print Scroll Pause
31:
32: 1 59 60 61 62 63 64 65 66 67 68 87 88 70 69
33:
34:
1.1.1.10! root 35: ! " $ % ^ & * ( ) _ + Page
1.1 root 36: ` 1 2 3 4 5 6 7 8 9 0 - = <- Ins Home Up
37:
38: 41 2 3 4 5 6 7 8 9 10 11 12 13 14 82 71 73
39: -- -- --
40: |
41: { } | Page
42: Tab Q W E R T Y U I O P [ ] <---- Del End Down
1.1.1.5 root 43:
1.1 root 44: 15 16 17 18 19 20 21 22 23 24 25 26 27 28 83 79 81
45: -- -- --
46:
47: : @ ~ ^
48: Caps A S D F G H J K L ; ' # |
49:
50: 58 30 31 32 33 34 35 36 37 38 39 40 43 72
51: --
1.1.1.5 root 52:
1.1 root 53: ^ | < > ? ^
54: | \ Z X C V B N M , . / | <- | ->
55:
56: 42 86 44 45 46 47 48 49 50 51 52 53 54 75 80 77
57: -- -- --
58:
59: Ctrl Alt SPACE Alt Gr Ctrl
60:
61: 29 56 57 56 29
62: --
63:
64: And:-
65:
66: Num
67: Lock / * -
68:
69: 69 53 55 74
70: -- --
71:
72: 7 8 9 +
73: Home ^ Pg Up
74:
75: 71 72 73 78
76:
77:
78: 4 5 6
79: <- ->
80:
81: 75 76 77
82:
83:
84: 1 2 3
85: End | Pg Dn Enter
86:
87: 79 70 81 28
88: --
89:
90: 0 .
91: Ins Del
92:
93: 82 83
94:
95:
96: */
97:
98:
1.1.1.5 root 99: /* SDL symbolic key to ST scan code mapping table */
100: static const char SymbolicKeyToSTScanCode[SDLK_LAST] =
101: {
1.1.1.10! root 102: /* ST, PC Code */
! 103: -1, /* 0 */
! 104: -1, /* 1 */
! 105: -1, /* 2 */
! 106: -1, /* 3 */
! 107: -1, /* 4 */
! 108: -1, /* 5 */
! 109: -1, /* 6 */
! 110: -1, /* 7 */
! 111: 0x0E, /* SDLK_BACKSPACE=8 */
! 112: 0x0F, /* SDLK_TAB=9 */
! 113: -1, /* 10 */
! 114: -1, /* 11 */
! 115: 0x47, /* SDLK_CLEAR = 12 */
! 116: 0x1C, /* SDLK_RETURN = 13 */
! 117: -1, /* 14 */
! 118: -1, /* 15 */
! 119: -1, /* 16 */
! 120: -1, /* 17 */
! 121: -1, /* 18 */
! 122: -1, /* SDLK_PAUSE = 19 */
! 123: -1, /* 20 */
! 124: -1, /* 21 */
! 125: -1, /* 22 */
! 126: -1, /* 23 */
! 127: -1, /* 24 */
! 128: -1, /* 25 */
! 129: -1, /* 26 */
! 130: 0x01, /* SDLK_ESCAPE = 27 */
! 131: -1, /* 28 */
! 132: -1, /* 29 */
! 133: -1, /* 30 */
! 134: -1, /* 31 */
! 135: 0x39, /* SDLK_SPACE = 32 */
! 136: -1, /* SDLK_EXCLAIM = 33 */
! 137: -1, /* SDLK_QUOTEDBL = 34 */
! 138: 0x29, /* SDLK_HASH = 35 */
! 139: -1, /* SDLK_DOLLAR = 36 */
! 140: -1, /* 37 */
! 141: -1, /* SDLK_AMPERSAND = 38 */
! 142: 0x28, /* SDLK_QUOTE = 39 */
! 143: 0x63, /* SDLK_LEFTPAREN = 40 */
! 144: 0x64, /* SDLK_RIGHTPAREN = 41 */
! 145: -1, /* SDLK_ASTERISK = 42 */
! 146: 0x1B, /* SDLK_PLUS = 43 */
! 147: 0x33, /* SDLK_COMMA = 44 */
! 148: 0x35, /* SDLK_MINUS = 45 */
! 149: 0x34, /* SDLK_PERIOD = 46 */
! 150: 0x35, /* SDLK_SLASH = 47 */
! 151: 0x0B, /* SDLK_0 = 48 */
! 152: 0x02, /* SDLK_1 = 49 */
! 153: 0x03, /* SDLK_2 = 50 */
! 154: 0x04, /* SDLK_3 = 51 */
! 155: 0x05, /* SDLK_4 = 52 */
! 156: 0x06, /* SDLK_5 = 53 */
! 157: 0x07, /* SDLK_6 = 54 */
! 158: 0x08, /* SDLK_7 = 55 */
! 159: 0x09, /* SDLK_8 = 56 */
! 160: 0x0A, /* SDLK_9 = 57 */
! 161: -1, /* SDLK_COLON = 58 */
! 162: 0x27, /* SDLK_SEMICOLON = 59 */
! 163: 0x60, /* SDLK_LESS = 60 */
! 164: 0x0D, /* SDLK_EQUALS = 61 */
! 165: -1, /* SDLK_GREATER = 62 */
! 166: -1, /* SDLK_QUESTION = 63 */
! 167: -1, /* SDLK_AT = 64 */
! 168: -1, /* 65 */ /* Skip uppercase letters */
! 169: -1, /* 66 */
! 170: -1, /* 67 */
! 171: -1, /* 68 */
! 172: -1, /* 69 */
! 173: -1, /* 70 */
! 174: -1, /* 71 */
! 175: -1, /* 72 */
! 176: -1, /* 73 */
! 177: -1, /* 74 */
! 178: -1, /* 75 */
! 179: -1, /* 76 */
! 180: -1, /* 77 */
! 181: -1, /* 78 */
! 182: -1, /* 79 */
! 183: -1, /* 80 */
! 184: -1, /* 81 */
! 185: -1, /* 82 */
! 186: -1, /* 83 */
! 187: -1, /* 84 */
! 188: -1, /* 85 */
! 189: -1, /* 86 */
! 190: -1, /* 87 */
! 191: -1, /* 88 */
! 192: -1, /* 89 */
! 193: -1, /* 90 */
! 194: 0x63, /* SDLK_LEFTBRACKET = 91 */
! 195: 0x2B, /* SDLK_BACKSLASH = 92 */ /* Might be 0x60 for UK keyboards */
! 196: 0x64, /* SDLK_RIGHTBRACKET = 93 */
! 197: 0x2B, /* SDLK_CARET = 94 */
! 198: -1, /* SDLK_UNDERSCORE = 95 */
! 199: 0x52, /* SDLK_BACKQUOTE = 96 */
! 200: 0x1E, /* SDLK_a = 97 */
! 201: 0x30, /* SDLK_b = 98 */
! 202: 0x2E, /* SDLK_c = 99 */
! 203: 0x20, /* SDLK_d = 100 */
! 204: 0x12, /* SDLK_e = 101 */
! 205: 0x21, /* SDLK_f = 102 */
! 206: 0x22, /* SDLK_g = 103 */
! 207: 0x23, /* SDLK_h = 104 */
! 208: 0x17, /* SDLK_i = 105 */
! 209: 0x24, /* SDLK_j = 106 */
! 210: 0x25, /* SDLK_k = 107 */
! 211: 0x26, /* SDLK_l = 108 */
! 212: 0x32, /* SDLK_m = 109 */
! 213: 0x31, /* SDLK_n = 110 */
! 214: 0x18, /* SDLK_o = 111 */
! 215: 0x19, /* SDLK_p = 112 */
! 216: 0x10, /* SDLK_q = 113 */
! 217: 0x13, /* SDLK_r = 114 */
! 218: 0x1F, /* SDLK_s = 115 */
! 219: 0x14, /* SDLK_t = 116 */
! 220: 0x16, /* SDLK_u = 117 */
! 221: 0x2F, /* SDLK_v = 118 */
! 222: 0x11, /* SDLK_w = 119 */
! 223: 0x2D, /* SDLK_x = 120 */
! 224: 0x15, /* SDLK_y = 121 */
! 225: 0x2C, /* SDLK_z = 122 */
! 226: -1, /* 123 */
! 227: -1, /* 124 */
! 228: -1, /* 125 */
! 229: -1, /* 126 */
! 230: 0x53, /* SDLK_DELETE = 127 */
! 231: /* End of ASCII mapped keysyms */
! 232: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 128-143*/
! 233: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144-159*/
! 234: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160-175*/
! 235: -1, -1, -1, -1, 0x0D, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176-191*/
! 236: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192-207*/
! 237: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x0C, /* 208-223*/
! 238: -1, -1, -1, -1, 0x28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224-239*/
! 239: -1, -1, -1, -1, -1, -1, 0x27, -1, -1, -1, -1, -1, 0x1A, -1, -1, -1, /* 240-255*/
! 240: /* Numeric keypad: */
! 241: 0x70, /* SDLK_KP0 = 256 */
! 242: 0x6D, /* SDLK_KP1 = 257 */
! 243: 0x6E, /* SDLK_KP2 = 258 */
! 244: 0x6F, /* SDLK_KP3 = 259 */
! 245: 0x6A, /* SDLK_KP4 = 260 */
! 246: 0x6B, /* SDLK_KP5 = 261 */
! 247: 0x6C, /* SDLK_KP6 = 262 */
! 248: 0x67, /* SDLK_KP7 = 263 */
! 249: 0x68, /* SDLK_KP8 = 264 */
! 250: 0x69, /* SDLK_KP9 = 265 */
! 251: 0x71, /* SDLK_KP_PERIOD = 266 */
! 252: 0x65, /* SDLK_KP_DIVIDE = 267 */
! 253: 0x66, /* SDLK_KP_MULTIPLY = 268 */
! 254: 0x4A, /* SDLK_KP_MINUS = 269 */
! 255: 0x4E, /* SDLK_KP_PLUS = 270 */
! 256: 0x72, /* SDLK_KP_ENTER = 271 */
! 257: -1, /* SDLK_KP_EQUALS = 272 */
! 258: /* Arrows + Home/End pad */
! 259: 0x48, /* SDLK_UP = 273 */
! 260: 0x50, /* SDLK_DOWN = 274 */
! 261: 0x4D, /* SDLK_RIGHT = 275 */
! 262: 0x4B, /* SDLK_LEFT = 276 */
! 263: 0x52, /* SDLK_INSERT = 277 */
! 264: 0x47, /* SDLK_HOME = 278 */
! 265: 0x61, /* SDLK_END = 279 */
! 266: 0x63, /* SDLK_PAGEUP = 280 */
! 267: 0x64, /* SDLK_PAGEDOWN = 281 */
! 268: /* Function keys */
! 269: 0x3B, /* SDLK_F1 = 282 */
! 270: 0x3C, /* SDLK_F2 = 283 */
! 271: 0x3D, /* SDLK_F3 = 284 */
! 272: 0x3E, /* SDLK_F4 = 285 */
! 273: 0x3F, /* SDLK_F5 = 286 */
! 274: 0x40, /* SDLK_F6 = 287 */
! 275: 0x41, /* SDLK_F7 = 288 */
! 276: 0x42, /* SDLK_F8 = 289 */
! 277: 0x43, /* SDLK_F9 = 290 */
! 278: 0x44, /* SDLK_F10 = 291 */
! 279: -1, /* SDLK_F11 = 292 */
! 280: -1, /* SDLK_F12 = 293 */
! 281: -1, /* SDLK_F13 = 294 */
! 282: -1, /* SDLK_F14 = 295 */
! 283: -1, /* SDLK_F15 = 296 */
! 284: -1, /* 297 */
! 285: -1, /* 298 */
! 286: -1, /* 299 */
! 287: /* Key state modifier keys */
! 288: -1, /* SDLK_NUMLOCK = 300 */
! 289: 0x3A, /* SDLK_CAPSLOCK = 301 */
! 290: 0x61, /* SDLK_SCROLLOCK = 302 */
! 291: 0x36, /* SDLK_RSHIFT = 303 */
! 292: 0x2A, /* SDLK_LSHIFT = 304 */
! 293: 0x1D, /* SDLK_RCTRL = 305 */
! 294: 0x1D, /* SDLK_LCTRL = 306 */
! 295: 0x38, /* SDLK_RALT = 307 */
! 296: 0x38, /* SDLK_LALT = 308 */
! 297: -1, /* SDLK_RMETA = 309 */
! 298: -1, /* SDLK_LMETA = 310 */
! 299: -1, /* SDLK_LSUPER = 311 */
! 300: -1, /* SDLK_RSUPER = 312 */
! 301: -1, /* SDLK_MODE = 313 */ /* "Alt Gr" key */
! 302: -1, /* SDLK_COMPOSE = 314 */
! 303: /* Miscellaneous function keys */
! 304: 0x62, /* SDLK_HELP = 315 */
! 305: 0x62, /* SDLK_PRINT = 316 */
! 306: -1, /* SDLK_SYSREQ = 317 */
! 307: -1, /* SDLK_BREAK = 318 */
! 308: -1, /* SDLK_MENU = 319 */
! 309: -1, /* SDLK_POWER = 320 */
! 310: -1, /* SDLK_EURO = 321 */
! 311: 0x61 /* SDLK_UNDO = 322 */
1.1 root 312: };
313:
1.1.1.5 root 314: /* Table for loaded keys: */
315: static char LoadedKeyToSTScanCode[SDLK_LAST];
316:
317: /* This table is used to translate a symbolic keycode to the (SDL) scancode */
318: static Uint8 SdlSymToSdlScan[SDLK_LAST];
319:
1.1 root 320:
1.1.1.3 root 321: /* List of ST scan codes to NOT de-bounce when running in maximum speed */
1.1.1.9 root 322: static const char DebounceExtendedKeys[] =
1.1.1.5 root 323: {
1.1.1.10! root 324: 0x1d, /* CTRL */
! 325: 0x2a, /* Left SHIFT */
! 326: 0x01, /* ESC */
! 327: 0x38, /* ALT */
! 328: 0x36, /* Right SHIFT */
! 329: 0 /* term */
1.1.1.3 root 330: };
331:
332:
1.1.1.5 root 333:
334: /*-----------------------------------------------------------------------*/
1.1.1.10! root 335: /**
! 336: * Initialization.
! 337: */
1.1.1.5 root 338: void Keymap_Init(void)
339: {
1.1.1.10! root 340: memset(SdlSymToSdlScan, 0, sizeof(SdlSymToSdlScan)); /* Clear array */
! 341: Keymap_LoadRemapFile(ConfigureParams.Keyboard.szMappingFileName);
1.1.1.5 root 342: }
343:
344:
345: /*-----------------------------------------------------------------------*/
1.1.1.10! root 346: /**
! 347: * Heuristic analysis to find out the obscure scancode offset.
! 348: * Some keys like 'z' can't be used for detection since they are on different
! 349: * locations on "qwertz" and "azerty" keyboards.
! 350: * This clever code has originally been taken from the emulator Aranym. (cheers!)
! 351: */
1.1.1.5 root 352: static int Keymap_FindScanCodeOffset(SDL_keysym* keysym)
353: {
1.1.1.10! root 354: int offset = -1; /* uninitialized scancode offset */
! 355: int scanPC = keysym->scancode;
1.1.1.5 root 356:
1.1.1.10! root 357: if (scanPC == 0) return -1; /* Ignore illegal scancode */
1.1.1.5 root 358:
1.1.1.10! root 359: switch (keysym->sym)
! 360: {
! 361: case SDLK_ESCAPE: offset = scanPC - 0x01; break;
! 362: case SDLK_1: offset = scanPC - 0x02; break;
! 363: case SDLK_2: offset = scanPC - 0x03; break;
! 364: case SDLK_3: offset = scanPC - 0x04; break;
! 365: case SDLK_4: offset = scanPC - 0x05; break;
! 366: case SDLK_5: offset = scanPC - 0x06; break;
! 367: case SDLK_6: offset = scanPC - 0x07; break;
! 368: case SDLK_7: offset = scanPC - 0x08; break;
! 369: case SDLK_8: offset = scanPC - 0x09; break;
! 370: case SDLK_9: offset = scanPC - 0x0a; break;
! 371: case SDLK_0: offset = scanPC - 0x0b; break;
! 372: case SDLK_BACKSPACE: offset = scanPC - 0x0e; break;
! 373: case SDLK_TAB: offset = scanPC - 0x0f; break;
! 374: case SDLK_RETURN: offset = scanPC - 0x1c; break;
! 375: case SDLK_SPACE: offset = scanPC - 0x39; break;
! 376: /*case SDLK_q: offset = scanPC - 0x10; break;*/ /* different on azerty */
! 377: /*case SDLK_w: offset = scanPC - 0x11; break;*/ /* different on azerty */
! 378: case SDLK_e: offset = scanPC - 0x12; break;
! 379: case SDLK_r: offset = scanPC - 0x13; break;
! 380: case SDLK_t: offset = scanPC - 0x14; break;
! 381: /*case SDLK_y: offset = scanPC - 0x15; break;*/ /* different on qwertz */
! 382: case SDLK_u: offset = scanPC - 0x16; break;
! 383: case SDLK_i: offset = scanPC - 0x17; break;
! 384: case SDLK_o: offset = scanPC - 0x18; break;
! 385: case SDLK_p: offset = scanPC - 0x19; break;
! 386: /*case SDLK_a: offset = scanPC - 0x1e; break;*/ /* different on azerty */
! 387: case SDLK_s: offset = scanPC - 0x1f; break;
! 388: case SDLK_d: offset = scanPC - 0x20; break;
! 389: case SDLK_f: offset = scanPC - 0x21; break;
! 390: case SDLK_g: offset = scanPC - 0x22; break;
! 391: case SDLK_h: offset = scanPC - 0x23; break;
! 392: case SDLK_j: offset = scanPC - 0x24; break;
! 393: case SDLK_k: offset = scanPC - 0x25; break;
! 394: case SDLK_l: offset = scanPC - 0x26; break;
! 395: /*case SDLK_z: offset = scanPC - 0x2c; break;*/ /* different on qwertz and azerty */
! 396: case SDLK_x: offset = scanPC - 0x2d; break;
! 397: case SDLK_c: offset = scanPC - 0x2e; break;
! 398: case SDLK_v: offset = scanPC - 0x2f; break;
! 399: case SDLK_b: offset = scanPC - 0x30; break;
! 400: case SDLK_n: offset = scanPC - 0x31; break;
! 401: /*case SDLK_m: offset = scanPC - 0x32; break;*/ /* different on azerty */
! 402: case SDLK_CAPSLOCK: offset = scanPC - 0x3a; break;
! 403: case SDLK_LSHIFT: offset = scanPC - 0x2a; break;
! 404: case SDLK_LCTRL: offset = scanPC - 0x1d; break;
! 405: case SDLK_LALT: offset = scanPC - 0x38; break;
! 406: case SDLK_F1: offset = scanPC - 0x3b; break;
! 407: case SDLK_F2: offset = scanPC - 0x3c; break;
! 408: case SDLK_F3: offset = scanPC - 0x3d; break;
! 409: case SDLK_F4: offset = scanPC - 0x3e; break;
! 410: case SDLK_F5: offset = scanPC - 0x3f; break;
! 411: case SDLK_F6: offset = scanPC - 0x40; break;
! 412: case SDLK_F7: offset = scanPC - 0x41; break;
! 413: case SDLK_F8: offset = scanPC - 0x42; break;
! 414: case SDLK_F9: offset = scanPC - 0x43; break;
! 415: case SDLK_F10: offset = scanPC - 0x44; break;
! 416: default: break;
! 417: }
! 418:
! 419: if (offset != -1)
! 420: {
! 421: fprintf(stderr, "Detected scancode offset = %d (key: '%s' with scancode $%02x)\n",
! 422: offset, SDL_GetKeyName(keysym->sym), scanPC);
! 423: }
1.1.1.5 root 424:
1.1.1.10! root 425: return offset;
1.1.1.5 root 426: }
427:
428:
429: /*-----------------------------------------------------------------------*/
1.1.1.10! root 430: /**
! 431: * Map PC scancode to ST scancode.
! 432: * This code was heavily inspired by the emulator Aranym. (cheers!)
! 433: */
1.1.1.5 root 434: static char Keymap_PcToStScanCode(SDL_keysym* keysym)
435: {
1.1.1.10! root 436: static int offset = -1; /* uninitialized scancode offset */
1.1.1.5 root 437:
1.1.1.10! root 438: switch (keysym->sym)
! 439: {
! 440: /* Numeric Pad */
! 441: /* note that the numbers are handled in Keymap_GetKeyPadScanCode()! */
! 442: case SDLK_KP_DIVIDE: return 0x65; /* Numpad / */
! 443: case SDLK_KP_MULTIPLY: return 0x66; /* NumPad * */
! 444: case SDLK_KP_MINUS: return 0x4a; /* NumPad - */
! 445: case SDLK_KP_PLUS: return 0x4e; /* NumPad + */
! 446: case SDLK_KP_PERIOD: return 0x71; /* NumPad . */
! 447: case SDLK_KP_ENTER: return 0x72; /* NumPad Enter */
! 448:
! 449: /* Special Keys */
! 450: case SDLK_PAGEUP: return 0x62; /* F11 => Help */
! 451: case SDLK_PAGEDOWN: return 0x61; /* F12 => Undo */
! 452: case SDLK_HOME: return 0x47; /* Home */
! 453: case SDLK_END: return 0x60; /* End => "<>" on German Atari kbd */
! 454: case SDLK_UP: return 0x48; /* Arrow Up */
! 455: case SDLK_LEFT: return 0x4b; /* Arrow Left */
! 456: case SDLK_RIGHT: return 0x4d; /* Arrow Right */
! 457: case SDLK_DOWN: return 0x50; /* Arrow Down */
! 458: case SDLK_INSERT: return 0x52; /* Insert */
! 459: case SDLK_DELETE: return 0x53; /* Delete */
! 460: case SDLK_LESS: return 0x60; /* "<" */
! 461:
! 462: /* Map Right Alt/Alt Gr/Control to the Atari keys */
! 463: case SDLK_RCTRL: return 0x1d; /* Control */
! 464: case SDLK_RALT: return 0x38; /* Alternate */
! 465:
! 466: default:
! 467: /* Process remaining keys: assume that it's PC101 keyboard
! 468: * and that it is compatible with Atari ST keyboard (basically
! 469: * same scancodes but on different platforms with different
! 470: * base offset (framebuffer = 0, X11 = 8).
! 471: * Try to detect the offset using a little bit of black magic.
! 472: * If offset is known then simply pass the scancode. */
! 473: if (offset == -1)
! 474: {
! 475: offset = Keymap_FindScanCodeOffset(keysym);
! 476: }
! 477:
! 478: if (offset >= 0)
! 479: {
! 480: /* offset is defined so pass the scancode directly */
! 481: return (keysym->scancode - offset);
! 482: }
! 483: else
! 484: {
! 485: /* Failed to detect offset, so use default value 8 */
! 486: fprintf(stderr, "Offset detection failed with "
! 487: "key '%s', scancode = 0x%02x, symcode = 0x%02x\n",
! 488: SDL_GetKeyName(keysym->sym), keysym->scancode, keysym->sym);
! 489: return (keysym->scancode - 8);
! 490: }
! 491: break;
! 492: }
1.1.1.5 root 493: }
494:
495:
496: /*-----------------------------------------------------------------------*/
1.1.1.10! root 497: /**
! 498: * Remap a keypad key to ST scan code. We use a separate function for this
! 499: * so that we can easily toggle between number and cursor mode with the
! 500: * numlock key.
! 501: */
1.1.1.5 root 502: static char Keymap_GetKeyPadScanCode(SDL_keysym* pKeySym)
503: {
1.1.1.10! root 504: if (SDL_GetModState() & KMOD_NUM)
! 505: {
! 506: switch (pKeySym->sym)
! 507: {
! 508: case SDLK_KP0: return 0x70; /* NumPad 0 */
! 509: case SDLK_KP1: return 0x6d; /* NumPad 1 */
! 510: case SDLK_KP2: return 0x6e; /* NumPad 2 */
! 511: case SDLK_KP3: return 0x6f; /* NumPad 3 */
! 512: case SDLK_KP4: return 0x6a; /* NumPad 4 */
! 513: case SDLK_KP5: return 0x6b; /* NumPad 5 */
! 514: case SDLK_KP6: return 0x6c; /* NumPad 6 */
! 515: case SDLK_KP7: return 0x67; /* NumPad 7 */
! 516: case SDLK_KP8: return 0x68; /* NumPad 8 */
! 517: case SDLK_KP9: return 0x69; /* NumPad 9 */
! 518: default: break;
! 519: }
! 520: }
! 521: else
! 522: {
! 523: switch (pKeySym->sym)
! 524: {
! 525: case SDLK_KP0: return 0x70; /* NumPad 0 */
! 526: case SDLK_KP1: return 0x6d; /* NumPad 1 */
! 527: case SDLK_KP2: return 0x50; /* Cursor down */
! 528: case SDLK_KP3: return 0x6f; /* NumPad 3 */
! 529: case SDLK_KP4: return 0x4b; /* Cursor left */
! 530: case SDLK_KP5: return 0x50; /* Cursor down (again?) */
! 531: case SDLK_KP6: return 0x4d; /* Cursor right */
! 532: case SDLK_KP7: return 0x52; /* Insert - good for Dungeon Master */
! 533: case SDLK_KP8: return 0x48; /* Cursor up */
! 534: case SDLK_KP9: return 0x47; /* Home - again for Dungeon Master */
! 535: default: break;
! 536: }
! 537: }
1.1.1.5 root 538:
1.1.1.10! root 539: return -1;
1.1.1.5 root 540: }
1.1 root 541:
542:
1.1.1.2 root 543: /*-----------------------------------------------------------------------*/
1.1.1.10! root 544: /**
! 545: * Remap SDL Key to ST Scan code
! 546: */
1.1.1.5 root 547: char Keymap_RemapKeyToSTScanCode(SDL_keysym* pKeySym)
1.1 root 548: {
1.1.1.10! root 549: if (pKeySym->sym >= SDLK_LAST) return -1; /* Avoid illegal keys */
1.1.1.5 root 550:
1.1.1.10! root 551: /* Check for keypad first so we can handle numlock */
! 552: if (ConfigureParams.Keyboard.nKeymapType != KEYMAP_LOADED)
! 553: {
! 554: if (pKeySym->sym >= SDLK_KP0 && pKeySym->sym <= SDLK_KP9)
! 555: {
! 556: return Keymap_GetKeyPadScanCode(pKeySym);
! 557: }
! 558: }
! 559:
! 560: /* Remap from PC scancodes? */
! 561: if (ConfigureParams.Keyboard.nKeymapType == KEYMAP_SCANCODE)
! 562: {
! 563: /* We sometimes enter here with an illegal (=0) scancode, so we keep
! 564: * track of the right scancodes in a table and then use a value from there.
! 565: */
! 566: if (pKeySym->scancode != 0)
! 567: {
! 568: SdlSymToSdlScan[pKeySym->sym] = pKeySym->scancode;
! 569: }
! 570: else
! 571: {
! 572: pKeySym->scancode = SdlSymToSdlScan[pKeySym->sym];
! 573: if (pKeySym->scancode == 0)
! 574: fprintf(stderr, "Warning: Key scancode is 0!\n");
! 575: }
! 576:
! 577: return Keymap_PcToStScanCode(pKeySym);
! 578: }
! 579:
! 580: /* Use default or loaded? */
! 581: if (ConfigureParams.Keyboard.nKeymapType == KEYMAP_LOADED)
! 582: return LoadedKeyToSTScanCode[pKeySym->sym];
! 583: else
! 584: return SymbolicKeyToSTScanCode[pKeySym->sym];
1.1 root 585: }
586:
1.1.1.2 root 587:
588: /*-----------------------------------------------------------------------*/
1.1.1.10! root 589: /**
! 590: * Load keyboard remap file
! 591: */
1.1 root 592: void Keymap_LoadRemapFile(char *pszFileName)
593: {
1.1.1.10! root 594: char szString[1024];
! 595: int STScanCode, PCKeyCode;
! 596: FILE *in;
! 597:
! 598: /* Initialize table with default values */
! 599: memcpy(LoadedKeyToSTScanCode, SymbolicKeyToSTScanCode, sizeof(LoadedKeyToSTScanCode));
! 600:
! 601: /* Attempt to load file */
! 602: if (strlen(pszFileName) > 0 && !File_DoesFileNameEndWithSlash(pszFileName))
! 603: {
! 604: /* Open file */
! 605: in = fopen(pszFileName, "r");
! 606: if (!in)
! 607: {
! 608: Log_Printf(LOG_DEBUG, "Keymap_LoadRemapFile: failed to "
! 609: " open keymap file '%s'\n", pszFileName);
! 610: return;
! 611: }
! 612:
! 613: while (!feof(in))
! 614: {
! 615: /* Read line from file */
! 616: if (fgets(szString, sizeof(szString), in) == NULL)
! 617: break;
! 618: /* Remove white-space from start of line */
! 619: Misc_RemoveWhiteSpace(szString, sizeof(szString));
! 620: if (strlen(szString)>0)
! 621: {
! 622: /* Is a comment? */
! 623: if ( (szString[0]==';') || (szString[0]=='#') )
! 624: continue;
! 625: /* Read values */
! 626: sscanf(szString, "%d,%d", &PCKeyCode, &STScanCode);
! 627: /* Store into remap table, check both value within range */
! 628: if ( (PCKeyCode>=0) && (PCKeyCode<SDLK_LAST) &&
! 629: (STScanCode>=0) && (STScanCode<256) )
! 630: LoadedKeyToSTScanCode[PCKeyCode] = STScanCode;
! 631: }
! 632: }
! 633:
! 634: fclose(in);
! 635: }
1.1 root 636: }
1.1.1.3 root 637:
638:
639: /*-----------------------------------------------------------------------*/
1.1.1.10! root 640: /**
! 641: * Scan list of keys to NOT de-bounce when running in maximum speed, eg ALT,SHIFT,CTRL etc...
! 642: * Return TRUE if key requires de-bouncing
! 643: */
1.1.1.6 root 644: static BOOL Keymap_DebounceSTKey(char STScanCode)
1.1.1.3 root 645: {
1.1.1.10! root 646: int i=0;
1.1.1.3 root 647:
1.1.1.10! root 648: /* Are we in maximum speed, and have disabled key repeat? */
! 649: if ((ConfigureParams.System.nMinMaxSpeed!=MINMAXSPEED_MIN)
! 650: && (ConfigureParams.Keyboard.bDisableKeyRepeat))
! 651: {
! 652: /* We should de-bounce all non extended keys,
! 653: * e.g. leave ALT, SHIFT, CTRL etc... held */
! 654: while (DebounceExtendedKeys[i])
! 655: {
! 656: if (STScanCode == DebounceExtendedKeys[i])
! 657: return(FALSE);
! 658: i++;
! 659: }
! 660:
! 661: /* De-bounce key */
! 662: return TRUE;
! 663: }
1.1.1.3 root 664:
1.1.1.10! root 665: /* Do not de-bounce key */
! 666: return FALSE;
1.1.1.3 root 667: }
668:
669:
670: /*-----------------------------------------------------------------------*/
1.1.1.10! root 671: /**
! 672: * Debounce any PC key held down if running with key repeat disabled.
! 673: * This is called each ST frame, so keys get held down for one VBL which
! 674: * is enough for 68000 code to scan.
! 675: */
1.1.1.3 root 676: void Keymap_DebounceAllKeys(void)
677: {
1.1.1.10! root 678: SDLKey key;
! 679: char STScanCode;
! 680: SDL_keysym tmpKeySym;
! 681:
! 682: /* Return if we aren't in maximum speed or have not disabled key repeat */
! 683: if ((ConfigureParams.System.nMinMaxSpeed == MINMAXSPEED_MIN)
! 684: || (!ConfigureParams.Keyboard.bDisableKeyRepeat))
! 685: {
! 686: return;
! 687: }
! 688:
! 689: tmpKeySym.mod = KMOD_NONE;
! 690:
! 691: /* Now run through each PC key looking for ones held down */
! 692: for (key = SDLK_FIRST; key < SDLK_LAST; key++)
! 693: {
! 694: /* Is key held? */
! 695: if (Keyboard.KeyStates[key])
! 696: {
! 697: tmpKeySym.sym = key;
! 698: tmpKeySym.scancode = 0;
! 699:
! 700: /* Get scan code */
! 701: STScanCode = Keymap_RemapKeyToSTScanCode(&tmpKeySym);
! 702: if (STScanCode != (char)-1)
! 703: {
! 704: /* Does this require de-bouncing? */
! 705: if (Keymap_DebounceSTKey(STScanCode))
! 706: Keymap_KeyUp(&tmpKeySym);
! 707: }
! 708: }
! 709: }
1.1.1.3 root 710:
711: }
712:
713:
714: /*-----------------------------------------------------------------------*/
1.1.1.10! root 715: /**
! 716: * User press key down
! 717: */
1.1.1.5 root 718: void Keymap_KeyDown(SDL_keysym *sdlkey)
1.1.1.3 root 719: {
1.1.1.10! root 720: BOOL bPreviousKeyState;
! 721: char STScanCode;
! 722: int symkey = sdlkey->sym;
! 723: int modkey = sdlkey->mod;
! 724:
! 725: /*fprintf(stderr, "keydown: sym=%i scan=%i mod=$%x\n",symkey, sdlkey->scancode, modkey);*/
! 726:
! 727: if (ShortCut_CheckKeys(modkey, symkey, 1))
! 728: return;
! 729:
! 730: /* If using joystick emulation via keyboard, DON'T send keys to keyboard processor!!!
! 731: * Some games use keyboard as pause! */
! 732: if (Joy_KeyDown(symkey, modkey))
! 733: return;
! 734:
! 735: /* Handle special keys */
! 736: if (symkey == SDLK_RALT || symkey == SDLK_LMETA || symkey == SDLK_RMETA
! 737: || symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
! 738: {
! 739: /* Ignore modifier keys that aren't passed to the ST */
! 740: return;
! 741: }
! 742: else if (symkey == SDLK_PAUSE && bEnableDebug)
! 743: {
! 744: /* Call the debugger */
! 745: if (bInFullScreen) Screen_ReturnFromFullScreen();
! 746: DebugUI();
! 747: return;
! 748: }
! 749:
! 750: /* Set down */
! 751: bPreviousKeyState = Keyboard.KeyStates[symkey];
! 752: Keyboard.KeyStates[symkey] = TRUE;
! 753:
! 754: STScanCode = Keymap_RemapKeyToSTScanCode(sdlkey);
! 755: if (STScanCode != (char)-1)
! 756: {
! 757: if (!bPreviousKeyState)
! 758: IKBD_PressSTKey(STScanCode, TRUE);
! 759: }
1.1.1.3 root 760: }
761:
762:
763: /*-----------------------------------------------------------------------*/
1.1.1.10! root 764: /**
! 765: * User released key
! 766: */
1.1.1.5 root 767: void Keymap_KeyUp(SDL_keysym *sdlkey)
1.1.1.3 root 768: {
1.1.1.10! root 769: char STScanCode;
! 770: int symkey = sdlkey->sym;
! 771: int modkey = sdlkey->mod;
! 772:
! 773: /*fprintf(stderr, "keyup: sym=%i scan=%i mod=$%x\n",symkey, sdlkey->scancode, modkey);*/
! 774:
! 775: /* Ignore short-cut keys here */
! 776:
! 777: if (ShortCut_CheckKeys(modkey, symkey, 0))
! 778: return;
! 779:
! 780: /* If using keyboard emulation, DON'T send keys to keyboard processor!!!
! 781: * Some games use keyboard as pause! */
! 782: if (Joy_KeyUp(symkey, modkey))
! 783: return;
! 784:
! 785: /* Handle special keys */
! 786: if (symkey == SDLK_RALT || symkey == SDLK_LMETA || symkey == SDLK_RMETA
! 787: || symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
! 788: {
! 789: /* Ignore modifier keys that aren't passed to the ST */
! 790: return;
! 791: }
! 792: else if (symkey == SDLK_CAPSLOCK)
! 793: {
! 794: /* Simulate another capslock key press */
! 795: IKBD_PressSTKey(0x3A, TRUE);
! 796: }
! 797:
! 798: /* Release key (only if was pressed) */
! 799: if (Keyboard.KeyStates[symkey])
! 800: {
! 801: STScanCode = Keymap_RemapKeyToSTScanCode(sdlkey);
! 802: if (STScanCode != (char)-1)
! 803: {
! 804: IKBD_PressSTKey(STScanCode,FALSE);
! 805: }
! 806: }
1.1.1.3 root 807:
1.1.1.10! root 808: Keyboard.KeyStates[symkey] = FALSE;
1.1.1.3 root 809: }
810:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.