aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorneonloop2021-08-12 15:29:39 +0000
committerneonloop2021-08-12 15:29:39 +0000
commit4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51 (patch)
tree88bf75a3ffac4017fe5124f935fe5e5f67dd6e48
parentc17d20ab28e0ac7dd527ff840559d96e98931a80 (diff)
downloadpicoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.tar.gz
picoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.tar.bz2
picoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.zip
Adds combo key support to libpicofe
-rw-r--r--Makefile10
-rw-r--r--patches/libpicofe/0001-key-combos.patch157
-rw-r--r--plat_linux.c18
-rw-r--r--plat_trimui.c30
4 files changed, 208 insertions, 7 deletions
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"