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 --- Makefile | 10 +- patches/libpicofe/0001-key-combos.patch | 157 ++++++++++++++++++++++++++++++++ plat_linux.c | 18 +++- plat_trimui.c | 30 ++++++ 4 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 patches/libpicofe/0001-key-combos.patch diff --git a/Makefile b/Makefile index db30344..dda2537 100644 --- a/Makefile +++ b/Makefile @@ -78,10 +78,16 @@ print-%: all: $(BIN) cores +libpicofe/.patched: + cd libpicofe && patch -p1 < ../patches/libpicofe/0001-key-combos.patch && touch .patched + +clean-libpicofe: + test ! -f libpicofe/.patched || (cd libpicofe && patch -p1 -R < ../patches/libpicofe/0001-key-combos.patch && rm .patched) + plat_trimui.o: plat_sdl.c plat_linux.o: plat_sdl.c -$(BIN): $(OBJS) +$(BIN): libpicofe/.patched $(OBJS) $(CC) $(OBJS) $(LDFLAGS) -o $(BIN) define CORE_template = @@ -110,7 +116,7 @@ $(foreach core,$(CORES),$(eval $(call CORE_template,$(core)))) cores: $(SOFILES) -clean: +clean: clean-libpicofe rm -f $(OBJS) $(BIN) $(SOFILES) rm -rf pkg 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 */ diff --git a/plat_linux.c b/plat_linux.c index bce33ab..a087ca6 100644 --- a/plat_linux.c +++ b/plat_linux.c @@ -53,12 +53,20 @@ const struct menu_keymap in_sdl_joy_map[] = { SDLK_WORLD_3, PBTN_MA3 }, }; +static const struct mod_keymap in_sdl_mod_keymap[] = { + { SDLK_TAB, SDLK_q }, /* mod+L1 = L2 */ + { SDLK_BACKSPACE, SDLK_BACKSLASH }, /* mod+R1 = R2 */ +}; + static const struct in_pdata in_sdl_platform_data = { - .defbinds = in_sdl_defbinds, - .key_map = in_sdl_key_map, - .kmap_size = array_size(in_sdl_key_map), - .joy_map = in_sdl_joy_map, - .jmap_size = array_size(in_sdl_joy_map), + .defbinds = in_sdl_defbinds, + .key_map = in_sdl_key_map, + .kmap_size = array_size(in_sdl_key_map), + .joy_map = in_sdl_joy_map, + .jmap_size = array_size(in_sdl_joy_map), + .mod_key = SDLK_ESCAPE, + .mod_keymap = in_sdl_mod_keymap, + .modmap_size = array_size(in_sdl_mod_keymap), }; #include "plat_sdl.c" diff --git a/plat_trimui.c b/plat_trimui.c index c91a416..0d9cdae 100644 --- a/plat_trimui.c +++ b/plat_trimui.c @@ -66,9 +66,36 @@ static const char * const in_sdl_key_names[SDLK_LAST] = { [SDLK_RCTRL] = "select", [SDLK_TAB] = "l", [SDLK_BACKSPACE] = "r", + [SDLK_1] = "menu+up", + [SDLK_2] = "menu+down", + [SDLK_3] = "menu+left", + [SDLK_4] = "menu+right", + [SDLK_5] = "menu+b", + [SDLK_6] = "menu+a", + [SDLK_7] = "menu+x", + [SDLK_8] = "menu+y", + [SDLK_9] = "menu+start", + [SDLK_0] = "menu+select", + [SDLK_q] = "menu+l", + [SDLK_BACKSLASH] = "menu+r", [SDLK_ESCAPE] = "menu", }; +static const struct mod_keymap in_sdl_mod_keymap[] = { + { SDLK_UP, SDLK_1 }, + { SDLK_DOWN, SDLK_2 }, + { SDLK_LEFT, SDLK_3 }, + { SDLK_RIGHT, SDLK_4 }, + { SDLK_LCTRL, SDLK_5 }, + { SDLK_SPACE, SDLK_6 }, + { SDLK_LSHIFT, SDLK_7 }, + { SDLK_LALT, SDLK_8 }, + { SDLK_RETURN, SDLK_9 }, + { SDLK_RCTRL, SDLK_0 }, + { SDLK_TAB, SDLK_q }, /* mod+L1 = L2 */ + { SDLK_BACKSPACE, SDLK_BACKSLASH }, /* mod+R1 = R2 */ +}; + static const struct in_pdata in_sdl_platform_data = { .defbinds = in_sdl_defbinds, .key_map = in_sdl_key_map, @@ -76,6 +103,9 @@ static const struct in_pdata in_sdl_platform_data = { .joy_map = in_sdl_joy_map, .jmap_size = array_size(in_sdl_joy_map), .key_names = in_sdl_key_names, + .mod_key = SDLK_ESCAPE, + .mod_keymap = in_sdl_mod_keymap, + .modmap_size = array_size(in_sdl_mod_keymap), }; #include "plat_sdl.c" -- cgit v1.2.3