From 4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51 Mon Sep 17 00:00:00 2001 From: neonloop Date: Thu, 12 Aug 2021 15:29:39 +0000 Subject: Adds combo key support to libpicofe --- patches/libpicofe/0001-key-combos.patch | 157 ++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 patches/libpicofe/0001-key-combos.patch (limited to 'patches') diff --git a/patches/libpicofe/0001-key-combos.patch b/patches/libpicofe/0001-key-combos.patch new file mode 100644 index 0000000..69cb4be --- /dev/null +++ b/patches/libpicofe/0001-key-combos.patch @@ -0,0 +1,157 @@ +diff --git a/in_sdl.c b/in_sdl.c +index a84c781..518e8cf 100644 +--- a/in_sdl.c ++++ b/in_sdl.c +@@ -19,11 +19,18 @@ + typedef unsigned long keybits_t; + #define KEYBITS_WORD_BITS (sizeof(keybits_t) * 8) + ++enum mod_state { ++ MOD_NO, ++ MOD_MAYBE, ++ MOD_YES ++}; ++ + struct in_sdl_state { + const in_drv_t *drv; + SDL_Joystick *joy; + int joy_id; + int axis_keydown[2]; ++ enum mod_state mod_state; + keybits_t keystate[SDLK_LAST / KEYBITS_WORD_BITS + 1]; + // emulator keys should always be processed immediately lest one is lost + keybits_t emu_keys[SDLK_LAST / KEYBITS_WORD_BITS + 1]; +@@ -259,6 +266,97 @@ static int get_keystate(keybits_t *keystate, int sym) + return !!(*ks_word & mask); + } + ++static int translate_keystate(struct in_sdl_state *state, SDL_Event *event) ++{ ++ const struct in_pdata *pdata = state->drv->pdata; ++ const struct mod_keymap *map; ++ SDL_Event new_event; ++ short key = (short)event->key.keysym.sym; ++ uint8_t type = event->type; ++ short mod_key = pdata->mod_key; ++ int i; ++ int ret = 1; ++ ++ if (!mod_key) ++ return 1; ++ ++ if (state->mod_state == MOD_NO && key != mod_key) ++ return 1; ++ ++ if (key == mod_key) { ++ if (type == SDL_KEYDOWN) { ++ /* Pressed mod, maybe a combo? Ignore the keypress ++ * until it's determined */ ++ state->mod_state = MOD_MAYBE; ++ ++ for (i = 0; i < pdata->modmap_size; i++) { ++ map = &pdata->mod_keymap[i]; ++ ++ if (get_keystate(state->keystate, map->inkey)) { ++ state->mod_state = MOD_YES; ++ new_event.type = SDL_KEYUP; ++ new_event.key.state = SDL_RELEASED; ++ new_event.key.keysym.sym = map->inkey; ++ SDL_PushEvent(&new_event); ++ ++ new_event.type = SDL_KEYDOWN; ++ new_event.key.state = SDL_PRESSED; ++ new_event.key.keysym.sym = map->outkey; ++ SDL_PushEvent(&new_event); ++ } ++ } ++ ++ ret = -1; ++ } else if (state->mod_state == MOD_MAYBE) { ++ /* Released mod without combo, simulate down and up */ ++ SDL_PushEvent(event); ++ state->mod_state = MOD_NO; ++ event->type = SDL_KEYDOWN; ++ ret = 1; ++ } else if (state->mod_state == MOD_YES) { ++ /* Released mod, switch all mod keys to unmod */ ++ state->mod_state = MOD_NO; ++ ++ for (i = 0; i < pdata->modmap_size; i++) { ++ map = &pdata->mod_keymap[i]; ++ ++ if (get_keystate(state->keystate, map->outkey)) { ++ state->mod_state = MOD_NO; ++ new_event.type = SDL_KEYUP; ++ new_event.key.state = SDL_RELEASED; ++ new_event.key.keysym.sym = map->outkey; ++ SDL_PushEvent(&new_event); ++ ++ new_event.type = SDL_KEYDOWN; ++ new_event.key.state = SDL_PRESSED; ++ new_event.key.keysym.sym = map->inkey; ++ SDL_PushEvent(&new_event); ++ } ++ } ++ ret = -1; ++ } ++ } else { ++ for (i = 0; i < pdata->modmap_size; i++) { ++ map = &pdata->mod_keymap[i]; ++ ++ if (map->inkey == key) { ++ state->mod_state = MOD_YES; ++ ++ /* Releasing the original key? Allow it through, ++ * Otherwise, replace with modified key. */ ++ if (!(event->type == SDL_KEYUP && ++ get_keystate(state->keystate, map->inkey))) ++ event->key.keysym.sym = map->outkey; ++ ++ break; ++ } ++ } ++ ret = 1; ++ } ++ ++ return ret; ++} ++ + static int handle_event(struct in_sdl_state *state, SDL_Event *event, + int *kc_out, int *down_out, int *emu_out) + { +@@ -267,6 +365,9 @@ static int handle_event(struct in_sdl_state *state, SDL_Event *event, + if (event->type != SDL_KEYDOWN && event->type != SDL_KEYUP) + return -1; + ++ if (translate_keystate(state, event) < 0) ++ return -1; ++ + emu = get_keystate(state->emu_keys, event->key.keysym.sym); + update_keystate(state->keystate, event->key.keysym.sym, + event->type == SDL_KEYDOWN); +diff --git a/input.h b/input.h +index 360b65b..895ad61 100644 +--- a/input.h ++++ b/input.h +@@ -110,6 +110,11 @@ struct menu_keymap { + short pbtn; + }; + ++struct mod_keymap { ++ short inkey; ++ short outkey; ++}; ++ + struct in_pdata { + const struct in_default_bind *defbinds; + const struct menu_keymap *key_map; +@@ -117,6 +122,9 @@ struct in_pdata { + const struct menu_keymap *joy_map; + size_t jmap_size; + const char * const *key_names; ++ short mod_key; ++ const struct mod_keymap *mod_keymap; ++ size_t modmap_size; + }; + + /* to be called by drivers */ -- cgit v1.2.3