diff options
| -rw-r--r-- | Makefile | 10 | ||||
| -rw-r--r-- | patches/libpicofe/0001-key-combos.patch | 157 | ||||
| -rw-r--r-- | plat_linux.c | 18 | ||||
| -rw-r--r-- | plat_trimui.c | 30 | 
4 files changed, 208 insertions, 7 deletions
| @@ -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" | 
