From d5ed9a26be39d6025382bd333c971093e7675ed7 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 16 Apr 2025 19:42:33 +0200 Subject: [PATCH] unix_main: Support configuring modifier keys The new `-k` argument takes some comma-separated assignments, such as `-k ctrl=option,alt=command`. In this configuration, the SDL control keys are mapped to the mac option key, and the SDL alt keys are mapped to the Mac command key. The SDL "gui" keys remain associated with the Mac command key, and so the (non-existent on mac plus) Mac control key cannot be pressed with this particular configuration. When `-k` is not specified, the behavior is intended to be unchanged. --- README.md | 4 ++++ include/keymap_sdl.h | 9 ++++++--- src/unix_main.c | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2ccf9b8..9cb4747 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,10 @@ screen memory (see `tools/mem2scr.c`). For a `DEBUG` build, add `-i` to get a disassembly trace of execution. +To use a different modifier layout, use `-k`. For instance, to map +host ctrl keys to mac Option and host Alt keys to mac Command, use +`ctrl=option,alt=command`. + Finally, the `-W ` parameter writes out the ROM image after patches are applied. This can be useful to prepare a ROM image for embedded builds, so as to avoid having to patch the ROM at runtime. diff --git a/include/keymap_sdl.h b/include/keymap_sdl.h index 6998b85..1ab789c 100644 --- a/include/keymap_sdl.h +++ b/include/keymap_sdl.h @@ -9,6 +9,9 @@ #include "keymap.h" +enum { UNIX_CTRL, UNIX_ALT, UNIX_GUI }; +static int sdl_mods[3] = { MKC_Control, MKC_Option, MKC_Command }; + static inline int SDLScan2MacKeyCode(SDL_Scancode i) { int v = MKC_None; @@ -103,11 +106,11 @@ static inline int SDLScan2MacKeyCode(SDL_Scancode i) case SDL_SCANCODE_RSHIFT: case SDL_SCANCODE_LSHIFT: v = MKC_Shift; break; case SDL_SCANCODE_RCTRL: - case SDL_SCANCODE_LCTRL: v = MKC_Control; break; + case SDL_SCANCODE_LCTRL: v = sdl_mods[UNIX_CTRL]; break; case SDL_SCANCODE_RALT: - case SDL_SCANCODE_LALT: v = MKC_Option; break; + case SDL_SCANCODE_LALT: v = sdl_mods[UNIX_ALT]; break; case SDL_SCANCODE_RGUI: - case SDL_SCANCODE_LGUI: v = MKC_Command; break; + case SDL_SCANCODE_LGUI: v = sdl_mods[UNIX_GUI]; break; case SDL_SCANCODE_KP_A: v = MKC_A; break; case SDL_SCANCODE_KP_B: v = MKC_B; break; diff --git a/src/unix_main.c b/src/unix_main.c index 588dba4..75c3506 100644 --- a/src/unix_main.c +++ b/src/unix_main.c @@ -78,6 +78,33 @@ static void copy_fb(uint32_t *fb_out, uint8_t *fb_in) } } +/* Accept a keyboard modifier configuration string */ +static void parse_modifier_config(const char *arg) { + while(*arg) { + int src, mod; + if(!strncmp(arg, "ctrl", 4)) { src = UNIX_CTRL; arg += 4; } + else if(!strncmp(arg, "alt", 3)) { src = UNIX_ALT; arg += 3; } + else if(!strncmp(arg, "gui", 3)) { src = UNIX_GUI; arg += 3; } + else { +parse_error: + printf("Unrecognized modifier configuration starting at '%s'\n", arg); + abort(); + } + if(*arg != '=') goto parse_error; + arg++; + if(!strncmp(arg, "option", 6)) { mod = MKC_Option; arg += 6; } + else if(!strncmp(arg, "control", 7)) { mod = MKC_Control; arg += 7; } + else if(!strncmp(arg, "command", 7)) { mod = MKC_Command; arg += 7; } + else goto parse_error; + + sdl_mods[src] = mod; + if (!*arg) break; + if (*arg != ',') goto parse_error; + arg++; + } +} + + /**********************************************************************/ /* The emulator core expects to be given ROM and RAM pointers, @@ -104,7 +131,7 @@ int main(int argc, char *argv[]) //////////////////////////////////////////////////////////////////////// // Args - while ((ch = getopt(argc, argv, "r:d:W:ihw")) != -1) { + while ((ch = getopt(argc, argv, "r:d:k:W:ihw")) != -1) { switch (ch) { case 'r': rom_filename = strdup(optarg); @@ -118,6 +145,10 @@ int main(int argc, char *argv[]) disc_filename = strdup(optarg); break; + case 'k': + parse_modifier_config(optarg); + break; + case 'w': opt_write = 1; break;