Annotation of hatari/src/keymap.c, revision 1.1.1.17

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.