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