From 488cdc18a1f428ca4d553f9cd7439fe504059ca4 Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 11:08:51 +0200 Subject: [PATCH 01/10] Refactor input config load and saving. Avoid very large structs (with tons of redundancy). Decouple prefixing from binds to allow autoconfig later. --- settings.c | 295 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 179 insertions(+), 116 deletions(-) diff --git a/settings.c b/settings.c index e3bdfdc6e7..59f8e9a656 100644 --- a/settings.c +++ b/settings.c @@ -698,87 +698,86 @@ bool config_load_file(const char *path) struct bind_map { bool valid; - const char *key; - const char *btn; - const char *axis; - int retro_key; + bool meta; // Meta binds get input as prefix, not input_playerN" + const char *base; + unsigned retro_key; }; -#define DECLARE_BIND(x, bind) { true, "input_" #x, "input_" #x "_btn", "input_" #x "_axis", bind } -#define DECL_PLAYER(P) \ - DECLARE_BIND(player##P##_b, RETRO_DEVICE_ID_JOYPAD_B), \ - DECLARE_BIND(player##P##_y, RETRO_DEVICE_ID_JOYPAD_Y), \ - DECLARE_BIND(player##P##_select, RETRO_DEVICE_ID_JOYPAD_SELECT), \ - DECLARE_BIND(player##P##_start, RETRO_DEVICE_ID_JOYPAD_START), \ - DECLARE_BIND(player##P##_up, RETRO_DEVICE_ID_JOYPAD_UP), \ - DECLARE_BIND(player##P##_down, RETRO_DEVICE_ID_JOYPAD_DOWN), \ - DECLARE_BIND(player##P##_left, RETRO_DEVICE_ID_JOYPAD_LEFT), \ - DECLARE_BIND(player##P##_right, RETRO_DEVICE_ID_JOYPAD_RIGHT), \ - DECLARE_BIND(player##P##_a, RETRO_DEVICE_ID_JOYPAD_A), \ - DECLARE_BIND(player##P##_x, RETRO_DEVICE_ID_JOYPAD_X), \ - DECLARE_BIND(player##P##_l, RETRO_DEVICE_ID_JOYPAD_L), \ - DECLARE_BIND(player##P##_r, RETRO_DEVICE_ID_JOYPAD_R), \ - DECLARE_BIND(player##P##_l2, RETRO_DEVICE_ID_JOYPAD_L2), \ - DECLARE_BIND(player##P##_r2, RETRO_DEVICE_ID_JOYPAD_R2), \ - DECLARE_BIND(player##P##_l3, RETRO_DEVICE_ID_JOYPAD_L3), \ - DECLARE_BIND(player##P##_r3, RETRO_DEVICE_ID_JOYPAD_R3), \ - DECLARE_BIND(player##P##_turbo, RARCH_TURBO_ENABLE), \ - DECLARE_BIND(player##P##_l_x_plus, RARCH_ANALOG_LEFT_X_PLUS), \ - DECLARE_BIND(player##P##_l_x_minus, RARCH_ANALOG_LEFT_X_MINUS), \ - DECLARE_BIND(player##P##_l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS), \ - DECLARE_BIND(player##P##_l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS), \ - DECLARE_BIND(player##P##_r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS), \ - DECLARE_BIND(player##P##_r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS), \ - DECLARE_BIND(player##P##_r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS), \ - DECLARE_BIND(player##P##_r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS) +static const char *bind_player_prefix[MAX_PLAYERS] = { + "input_player1", + "input_player2", + "input_player3", + "input_player4", + "input_player5", + "input_player6", + "input_player7", + "input_player8", +}; -// Big and nasty bind map... :) -static const struct bind_map bind_maps[MAX_PLAYERS][RARCH_BIND_LIST_END_NULL] = { - { - DECL_PLAYER(1), +#define DECLARE_BIND(x, bind) { true, false, #x, bind } - DECLARE_BIND(toggle_fast_forward, RARCH_FAST_FORWARD_KEY), - DECLARE_BIND(hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY), - DECLARE_BIND(load_state, RARCH_LOAD_STATE_KEY), - DECLARE_BIND(save_state, RARCH_SAVE_STATE_KEY), - DECLARE_BIND(toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY), - DECLARE_BIND(exit_emulator, RARCH_QUIT_KEY), - DECLARE_BIND(state_slot_increase, RARCH_STATE_SLOT_PLUS), - DECLARE_BIND(state_slot_decrease, RARCH_STATE_SLOT_MINUS), - DECLARE_BIND(rewind, RARCH_REWIND), - DECLARE_BIND(movie_record_toggle, RARCH_MOVIE_RECORD_TOGGLE), - DECLARE_BIND(pause_toggle, RARCH_PAUSE_TOGGLE), - DECLARE_BIND(frame_advance, RARCH_FRAMEADVANCE), - DECLARE_BIND(reset, RARCH_RESET), - DECLARE_BIND(shader_next, RARCH_SHADER_NEXT), - DECLARE_BIND(shader_prev, RARCH_SHADER_PREV), - DECLARE_BIND(cheat_index_plus, RARCH_CHEAT_INDEX_PLUS), - DECLARE_BIND(cheat_index_minus, RARCH_CHEAT_INDEX_MINUS), - DECLARE_BIND(cheat_toggle, RARCH_CHEAT_TOGGLE), - DECLARE_BIND(screenshot, RARCH_SCREENSHOT), - DECLARE_BIND(dsp_config, RARCH_DSP_CONFIG), - DECLARE_BIND(audio_mute, RARCH_MUTE), - DECLARE_BIND(netplay_flip_players, RARCH_NETPLAY_FLIP), - DECLARE_BIND(slowmotion, RARCH_SLOWMOTION), - DECLARE_BIND(enable_hotkey, RARCH_ENABLE_HOTKEY), - DECLARE_BIND(volume_up, RARCH_VOLUME_UP), - DECLARE_BIND(volume_down, RARCH_VOLUME_DOWN), - DECLARE_BIND(overlay_next, RARCH_OVERLAY_NEXT), - DECLARE_BIND(disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE), - DECLARE_BIND(disk_next, RARCH_DISK_NEXT), - DECLARE_BIND(grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE), +#define DECLARE_META_BIND(x, bind) { true, true, #x, bind } + +static const struct bind_map bind_maps[RARCH_BIND_LIST_END_NULL] = { + DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B), + DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y), + DECLARE_BIND(select, RETRO_DEVICE_ID_JOYPAD_SELECT), + DECLARE_BIND(start, RETRO_DEVICE_ID_JOYPAD_START), + DECLARE_BIND(up, RETRO_DEVICE_ID_JOYPAD_UP), + DECLARE_BIND(down, RETRO_DEVICE_ID_JOYPAD_DOWN), + DECLARE_BIND(left, RETRO_DEVICE_ID_JOYPAD_LEFT), + DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT), + DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A), + DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X), + DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L), + DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R), + DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2), + DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2), + DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3), + DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3), + DECLARE_BIND(turbo, RARCH_TURBO_ENABLE), + DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS), + DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS), + DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS), + DECLARE_BIND(l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS), + DECLARE_BIND(r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS), + DECLARE_BIND(r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS), + DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS), + DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS), + + DECLARE_META_BIND(toggle_fast_forward, RARCH_FAST_FORWARD_KEY), + DECLARE_META_BIND(hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY), + DECLARE_META_BIND(load_state, RARCH_LOAD_STATE_KEY), + DECLARE_META_BIND(save_state, RARCH_SAVE_STATE_KEY), + DECLARE_META_BIND(toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY), + DECLARE_META_BIND(exit_emulator, RARCH_QUIT_KEY), + DECLARE_META_BIND(state_slot_increase, RARCH_STATE_SLOT_PLUS), + DECLARE_META_BIND(state_slot_decrease, RARCH_STATE_SLOT_MINUS), + DECLARE_META_BIND(rewind, RARCH_REWIND), + DECLARE_META_BIND(movie_record_toggle, RARCH_MOVIE_RECORD_TOGGLE), + DECLARE_META_BIND(pause_toggle, RARCH_PAUSE_TOGGLE), + DECLARE_META_BIND(frame_advance, RARCH_FRAMEADVANCE), + DECLARE_META_BIND(reset, RARCH_RESET), + DECLARE_META_BIND(shader_next, RARCH_SHADER_NEXT), + DECLARE_META_BIND(shader_prev, RARCH_SHADER_PREV), + DECLARE_META_BIND(cheat_index_plus, RARCH_CHEAT_INDEX_PLUS), + DECLARE_META_BIND(cheat_index_minus, RARCH_CHEAT_INDEX_MINUS), + DECLARE_META_BIND(cheat_toggle, RARCH_CHEAT_TOGGLE), + DECLARE_META_BIND(screenshot, RARCH_SCREENSHOT), + DECLARE_META_BIND(dsp_config, RARCH_DSP_CONFIG), + DECLARE_META_BIND(audio_mute, RARCH_MUTE), + DECLARE_META_BIND(netplay_flip_players, RARCH_NETPLAY_FLIP), + DECLARE_META_BIND(slowmotion, RARCH_SLOWMOTION), + DECLARE_META_BIND(enable_hotkey, RARCH_ENABLE_HOTKEY), + DECLARE_META_BIND(volume_up, RARCH_VOLUME_UP), + DECLARE_META_BIND(volume_down, RARCH_VOLUME_DOWN), + DECLARE_META_BIND(overlay_next, RARCH_OVERLAY_NEXT), + DECLARE_META_BIND(disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE), + DECLARE_META_BIND(disk_next, RARCH_DISK_NEXT), + DECLARE_META_BIND(grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE), #ifdef HAVE_RGUI - DECLARE_BIND(menu_toggle, RARCH_MENU_TOGGLE), + DECLARE_META_BIND(menu_toggle, RARCH_MENU_TOGGLE), #endif - }, - - { DECL_PLAYER(2) }, - { DECL_PLAYER(3) }, - { DECL_PLAYER(4) }, - { DECL_PLAYER(5) }, - { DECL_PLAYER(6) }, - { DECL_PLAYER(7) }, - { DECL_PLAYER(8) }, }; struct key_map @@ -882,20 +881,42 @@ static int find_sk_key(const char *str) return find_sk_bind(str); } -static void read_keybinds_keyboard(config_file_t *conf, unsigned player, unsigned index, struct retro_keybind *bind) +static void input_config_parse_key(config_file_t *conf, const char *prefix, const char *btn, + struct retro_keybind *bind) { char tmp[64]; + char key[64]; + snprintf(key, sizeof(key), "%s_%s", prefix, btn); - if (bind_maps[player][index].key && - config_get_array(conf, bind_maps[player][index].key, tmp, sizeof(tmp))) + if (config_get_array(conf, key, tmp, sizeof(tmp))) { int key = find_sk_key(tmp); - if (key >= 0) bind->key = (enum retro_key)key; } } +static const char *input_config_get_prefix(unsigned player, bool meta) +{ + if (player == 0) + return meta ? "input" : bind_player_prefix[player]; + else if (player != 0 && !meta) + return bind_player_prefix[player]; + else + return NULL; // Don't bother with meta bind for anyone else than first player. +} + +static void read_keybinds_keyboard(config_file_t *conf, unsigned player, unsigned index, + struct retro_keybind *bind) +{ + if (bind_maps[index].valid && bind_maps[index].base) + { + const char *prefix = input_config_get_prefix(player, bind_maps[index].meta); + if (prefix) + input_config_parse_key(conf, prefix, bind_maps[index].base, bind); + } +} + static void parse_hat(struct retro_keybind *bind, const char *str) { if (!isdigit(*str)) @@ -924,11 +945,14 @@ static void parse_hat(struct retro_keybind *bind, const char *str) bind->joykey = HAT_MAP(hat, hat_dir); } -static void read_keybinds_button(config_file_t *conf, unsigned player, unsigned index, struct retro_keybind *bind) +static void input_config_parse_joy_button(config_file_t *conf, const char *prefix, + const char *btn, struct retro_keybind *bind) { char tmp[64]; - if (bind_maps[player][index].btn && - config_get_array(conf, bind_maps[player][index].btn, tmp, sizeof(tmp))) + char key[64]; + snprintf(key, sizeof(key), "%s_%s_btn", prefix, btn); + + if (config_get_array(conf, key, tmp, sizeof(tmp))) { const char *btn = tmp; if (strcmp(btn, "nul") == 0) @@ -943,11 +967,14 @@ static void read_keybinds_button(config_file_t *conf, unsigned player, unsigned } } -static void read_keybinds_axis(config_file_t *conf, unsigned player, unsigned index, struct retro_keybind *bind) +static void input_config_parse_joy_axis(config_file_t *conf, const char *prefix, + const char *axis, struct retro_keybind *bind) { char tmp[64]; - if (bind_maps[player][index].axis && - config_get_array(conf, bind_maps[player][index].axis, tmp, sizeof(tmp))) + char key[64]; + snprintf(key, sizeof(key), "%s_%s_axis", prefix, axis); + + if (config_get_array(conf, key, tmp, sizeof(tmp))) { if (strcmp(tmp, "nul") == 0) bind->joyaxis = AXIS_NONE; @@ -963,12 +990,35 @@ static void read_keybinds_axis(config_file_t *conf, unsigned player, unsigned in } } +static void read_keybinds_button(config_file_t *conf, unsigned player, unsigned index, + struct retro_keybind *bind) +{ + if (bind_maps[index].valid && bind_maps[index].base) + { + const char *prefix = input_config_get_prefix(player, bind_maps[index].meta); + if (prefix) + input_config_parse_joy_button(conf, prefix, bind_maps[index].base, bind); + } +} + +static void read_keybinds_axis(config_file_t *conf, unsigned player, unsigned index, + struct retro_keybind *bind) +{ + if (bind_maps[index].valid && bind_maps[index].base) + { + const char *prefix = input_config_get_prefix(player, bind_maps[index].meta); + if (prefix) + input_config_parse_joy_axis(conf, prefix, bind_maps[index].base, bind); + } +} + static void read_keybinds_player(config_file_t *conf, unsigned player) { - for (unsigned i = 0; bind_maps[player][i].valid; i++) + for (unsigned i = 0; bind_maps[i].valid; i++) { - struct retro_keybind *bind = find_retro_bind(player, bind_maps[player][i].retro_key); - rarch_assert(bind); + struct retro_keybind *bind = find_retro_bind(player, bind_maps[i].retro_key); + if (!bind) + continue; read_keybinds_keyboard(conf, player, i, bind); read_keybinds_button(conf, player, i, bind); @@ -992,9 +1042,12 @@ bool config_read_keybinds(const char *path) return true; } -static void save_keybind_key(config_file_t *conf, - const struct bind_map *map, const struct retro_keybind *bind) +static void save_keybind_key(config_file_t *conf, const char *prefix, const char *base, + const struct retro_keybind *bind) { + char key[64]; + snprintf(key, sizeof(key), "%s_%s", prefix, base); + char ascii[2] = {0}; const char *btn = ascii; @@ -1012,12 +1065,11 @@ static void save_keybind_key(config_file_t *conf, } } - config_set_string(conf, map->key, btn); + config_set_string(conf, key, btn); } #ifndef RARCH_CONSOLE -static void save_keybind_hat(config_file_t *conf, - const struct bind_map *map, const struct retro_keybind *bind) +static void save_keybind_hat(config_file_t *conf, const char *key, const struct retro_keybind *bind) { unsigned hat = GET_HAT(bind->joykey); const char *dir = NULL; @@ -1046,31 +1098,37 @@ static void save_keybind_hat(config_file_t *conf, char config[16]; snprintf(config, sizeof(config), "h%u%s", hat, dir); - config_set_string(conf, map->btn, config); + config_set_string(conf, key, config); } #endif -static void save_keybind_joykey(config_file_t *conf, - const struct bind_map *map, const struct retro_keybind *bind) +static void save_keybind_joykey(config_file_t *conf, const char *prefix, const char *base, + const struct retro_keybind *bind) { + char key[64]; + snprintf(key, sizeof(key), "%s_%s_btn", prefix, base); + if (bind->joykey == NO_BTN) - config_set_string(conf, map->btn, "nul"); + config_set_string(conf, key, "nul"); #ifndef RARCH_CONSOLE // Consoles don't understand hats. else if (GET_HAT_DIR(bind->joykey)) - save_keybind_hat(conf, map, bind); + save_keybind_hat(conf, key, bind); #endif else - config_set_uint64(conf, map->btn, bind->joykey); + config_set_uint64(conf, key, bind->joykey); } -static void save_keybind_axis(config_file_t *conf, - const struct bind_map *map, const struct retro_keybind *bind) +static void save_keybind_axis(config_file_t *conf, const char *prefix, const char *base, + const struct retro_keybind *bind) { + char key[64]; + snprintf(key, sizeof(key), "%s_%s_axis", prefix, base); + unsigned axis = 0; char dir = '\0'; if (bind->joyaxis == AXIS_NONE) - config_set_string(conf, map->axis, "nul"); + config_set_string(conf, key, "nul"); else if (AXIS_NEG_GET(bind->joyaxis) != AXIS_DIR_NONE) { dir = '-'; @@ -1082,28 +1140,33 @@ static void save_keybind_axis(config_file_t *conf, axis = AXIS_POS_GET(bind->joyaxis); } - char config[16]; - snprintf(config, sizeof(config), "%c%u", dir, axis); - config_set_string(conf, map->axis, config); + if (dir) + { + char config[16]; + snprintf(config, sizeof(config), "%c%u", dir, axis); + config_set_string(conf, key, config); + } } -static void save_keybind(config_file_t *conf, - const struct bind_map *map, const struct retro_keybind *bind) +static void save_keybind(config_file_t *conf, const char *prefix, const char *base, + const struct retro_keybind *bind) { - if (!map->valid) + if (!bind->valid) return; - save_keybind_key(conf, map, bind); - save_keybind_joykey(conf, map, bind); - save_keybind_axis(conf, map, bind); -#ifdef RARCH_CONSOLE -#endif + save_keybind_key(conf, prefix, base, bind); + save_keybind_joykey(conf, prefix, base, bind); + save_keybind_axis(conf, prefix, base, bind); } -static void save_keybinds_player(config_file_t *conf, unsigned i) +static void save_keybinds_player(config_file_t *conf, unsigned player) { - for (unsigned j = 0; j < RARCH_BIND_LIST_END; j++) - save_keybind(conf, &bind_maps[i][j], &g_settings.input.binds[i][j]); + for (unsigned i = 0; bind_maps[i].valid; i++) + { + const char *prefix = input_config_get_prefix(player, bind_maps[i].meta); + if (prefix) + save_keybind(conf, prefix, bind_maps[i].base, &g_settings.input.binds[player][i]); + } } #ifdef RARCH_CONSOLE From 42a9e46cb221390e95327c2322736aac4f43cae9 Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 11:44:54 +0200 Subject: [PATCH 02/10] Input config refactor. Move LUTs to input_common.c. Make LUTs public. --- Makefile | 7 +- input/input_common.c | 271 ++++++++++++++++++++++++++++++++- input/input_common.h | 27 ++++ input/linuxraw_joypad.c | 10 +- settings.c | 321 +++------------------------------------- 5 files changed, 326 insertions(+), 310 deletions(-) diff --git a/Makefile b/Makefile index 2faa52b83e..9d13690ebd 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ RETROLAUNCH_OBJ = tools/retrolaunch/main.o \ tools/retrolaunch/parser.o \ tools/retrolaunch/cd_detect.o \ tools/retrolaunch/rl_fnmatch.o \ + tools/input_common.o \ file_path.o \ compat/compat.o \ conf/config_file.o \ @@ -371,7 +372,11 @@ tools/retrolaunch/retrolaunch: $(RETROLAUNCH_OBJ) tools/linuxraw_joypad.o: input/linuxraw_joypad.c @$(if $(Q), $(shell echo echo CC $<),) - $(Q)$(CC) $(CFLAGS) $(DEFINES) -DNO_MSG_QUEUE -c -o $@ $< + $(Q)$(CC) $(CFLAGS) $(DEFINES) -DIS_JOYCONFIG -c -o $@ $< + +tools/input_common.o: input/input_common.c + @$(if $(Q), $(shell echo echo CC $<),) + $(Q)$(CC) $(CFLAGS) $(DEFINES) -DIS_RETROLAUNCH -c -o $@ $< %.o: %.S config.h config.mk $(HEADERS) @$(if $(Q), $(shell echo echo AS $<),) diff --git a/input/input_common.c b/input/input_common.c index 02c564f247..5df711abb5 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -18,6 +18,7 @@ #include #include "../general.h" +#include "../driver.h" #ifdef HAVE_CONFIG_H #include "../config.h" #endif @@ -37,6 +38,7 @@ #endif static const rarch_joypad_driver_t *joypad_drivers[] = { +#ifndef IS_RETROLAUNCH #ifdef HAVE_DINPUT &dinput_joypad, #endif @@ -46,11 +48,13 @@ static const rarch_joypad_driver_t *joypad_drivers[] = { #ifdef HAVE_SDL &sdl_joypad, #endif +#endif + NULL, }; const rarch_joypad_driver_t *input_joypad_find_driver(const char *ident) { - for (unsigned i = 0; i < ARRAY_SIZE(joypad_drivers); i++) + for (unsigned i = 0; joypad_drivers[i]; i++) { if (strcmp(ident, joypad_drivers[i]->ident) == 0) { @@ -64,7 +68,7 @@ const rarch_joypad_driver_t *input_joypad_find_driver(const char *ident) const rarch_joypad_driver_t *input_joypad_init_first(void) { - for (unsigned i = 0; i < ARRAY_SIZE(joypad_drivers); i++) + for (unsigned i = 0; joypad_drivers[i]; i++) { if (joypad_drivers[i]->init()) { @@ -162,6 +166,7 @@ bool input_joypad_hat_raw(const rarch_joypad_driver_t *driver, return driver->button(joypad, HAT_MAP(hat, hat_dir)); } +#ifndef IS_RETROLAUNCH bool input_translate_coord_viewport(int mouse_x, int mouse_y, int16_t *res_x, int16_t *res_y, int16_t *res_screen_x, int16_t *res_screen_y) { @@ -194,6 +199,7 @@ bool input_translate_coord_viewport(int mouse_x, int mouse_y, *res_screen_y = scaled_screen_y; return true; } +#endif #ifdef HAVE_X11 const struct rarch_key_map rarch_key_map_x11[] = { @@ -489,3 +495,264 @@ unsigned input_translate_rk_to_keysym(enum retro_key key) { return rarch_keysym_lut[key]; } + +static const char *bind_player_prefix[MAX_PLAYERS] = { + "input_player1", + "input_player2", + "input_player3", + "input_player4", + "input_player5", + "input_player6", + "input_player7", + "input_player8", +}; + +#define DECLARE_BIND(x, bind) { true, false, #x, bind } +#define DECLARE_META_BIND(x, bind) { true, true, #x, bind } + +const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { + DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B), + DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y), + DECLARE_BIND(select, RETRO_DEVICE_ID_JOYPAD_SELECT), + DECLARE_BIND(start, RETRO_DEVICE_ID_JOYPAD_START), + DECLARE_BIND(up, RETRO_DEVICE_ID_JOYPAD_UP), + DECLARE_BIND(down, RETRO_DEVICE_ID_JOYPAD_DOWN), + DECLARE_BIND(left, RETRO_DEVICE_ID_JOYPAD_LEFT), + DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT), + DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A), + DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X), + DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L), + DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R), + DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2), + DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2), + DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3), + DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3), + DECLARE_BIND(turbo, RARCH_TURBO_ENABLE), + DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS), + DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS), + DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS), + DECLARE_BIND(l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS), + DECLARE_BIND(r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS), + DECLARE_BIND(r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS), + DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS), + DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS), + + DECLARE_META_BIND(toggle_fast_forward, RARCH_FAST_FORWARD_KEY), + DECLARE_META_BIND(hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY), + DECLARE_META_BIND(load_state, RARCH_LOAD_STATE_KEY), + DECLARE_META_BIND(save_state, RARCH_SAVE_STATE_KEY), + DECLARE_META_BIND(toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY), + DECLARE_META_BIND(exit_emulator, RARCH_QUIT_KEY), + DECLARE_META_BIND(state_slot_increase, RARCH_STATE_SLOT_PLUS), + DECLARE_META_BIND(state_slot_decrease, RARCH_STATE_SLOT_MINUS), + DECLARE_META_BIND(rewind, RARCH_REWIND), + DECLARE_META_BIND(movie_record_toggle, RARCH_MOVIE_RECORD_TOGGLE), + DECLARE_META_BIND(pause_toggle, RARCH_PAUSE_TOGGLE), + DECLARE_META_BIND(frame_advance, RARCH_FRAMEADVANCE), + DECLARE_META_BIND(reset, RARCH_RESET), + DECLARE_META_BIND(shader_next, RARCH_SHADER_NEXT), + DECLARE_META_BIND(shader_prev, RARCH_SHADER_PREV), + DECLARE_META_BIND(cheat_index_plus, RARCH_CHEAT_INDEX_PLUS), + DECLARE_META_BIND(cheat_index_minus, RARCH_CHEAT_INDEX_MINUS), + DECLARE_META_BIND(cheat_toggle, RARCH_CHEAT_TOGGLE), + DECLARE_META_BIND(screenshot, RARCH_SCREENSHOT), + DECLARE_META_BIND(dsp_config, RARCH_DSP_CONFIG), + DECLARE_META_BIND(audio_mute, RARCH_MUTE), + DECLARE_META_BIND(netplay_flip_players, RARCH_NETPLAY_FLIP), + DECLARE_META_BIND(slowmotion, RARCH_SLOWMOTION), + DECLARE_META_BIND(enable_hotkey, RARCH_ENABLE_HOTKEY), + DECLARE_META_BIND(volume_up, RARCH_VOLUME_UP), + DECLARE_META_BIND(volume_down, RARCH_VOLUME_DOWN), + DECLARE_META_BIND(overlay_next, RARCH_OVERLAY_NEXT), + DECLARE_META_BIND(disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE), + DECLARE_META_BIND(disk_next, RARCH_DISK_NEXT), + DECLARE_META_BIND(grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE), +#ifdef HAVE_RGUI + DECLARE_META_BIND(menu_toggle, RARCH_MENU_TOGGLE), +#endif +}; + +const struct input_key_map input_config_key_map[] = { + { "left", RETROK_LEFT }, + { "right", RETROK_RIGHT }, + { "up", RETROK_UP }, + { "down", RETROK_DOWN }, + { "enter", RETROK_RETURN }, + { "kp_enter", RETROK_KP_ENTER }, + { "tab", RETROK_TAB }, + { "insert", RETROK_INSERT }, + { "del", RETROK_DELETE }, + { "end", RETROK_END }, + { "home", RETROK_HOME }, + { "rshift", RETROK_RSHIFT }, + { "shift", RETROK_LSHIFT }, + { "ctrl", RETROK_LCTRL }, + { "alt", RETROK_LALT }, + { "space", RETROK_SPACE }, + { "escape", RETROK_ESCAPE }, + { "add", RETROK_KP_PLUS }, + { "subtract", RETROK_KP_MINUS }, + { "kp_plus", RETROK_KP_PLUS }, + { "kp_minus", RETROK_KP_MINUS }, + { "f1", RETROK_F1 }, + { "f2", RETROK_F2 }, + { "f3", RETROK_F3 }, + { "f4", RETROK_F4 }, + { "f5", RETROK_F5 }, + { "f6", RETROK_F6 }, + { "f7", RETROK_F7 }, + { "f8", RETROK_F8 }, + { "f9", RETROK_F9 }, + { "f10", RETROK_F10 }, + { "f11", RETROK_F11 }, + { "f12", RETROK_F12 }, + { "num0", RETROK_0 }, + { "num1", RETROK_1 }, + { "num2", RETROK_2 }, + { "num3", RETROK_3 }, + { "num4", RETROK_4 }, + { "num5", RETROK_5 }, + { "num6", RETROK_6 }, + { "num7", RETROK_7 }, + { "num8", RETROK_8 }, + { "num9", RETROK_9 }, + { "pageup", RETROK_PAGEUP }, + { "pagedown", RETROK_PAGEDOWN }, + { "keypad0", RETROK_KP0 }, + { "keypad1", RETROK_KP1 }, + { "keypad2", RETROK_KP2 }, + { "keypad3", RETROK_KP3 }, + { "keypad4", RETROK_KP4 }, + { "keypad5", RETROK_KP5 }, + { "keypad6", RETROK_KP6 }, + { "keypad7", RETROK_KP7 }, + { "keypad8", RETROK_KP8 }, + { "keypad9", RETROK_KP9 }, + { "period", RETROK_PERIOD }, + { "capslock", RETROK_CAPSLOCK }, + { "numlock", RETROK_NUMLOCK }, + { "backspace", RETROK_BACKSPACE }, + { "multiply", RETROK_KP_MULTIPLY }, + { "divide", RETROK_KP_DIVIDE }, + { "print_screen", RETROK_PRINT }, + { "scroll_lock", RETROK_SCROLLOCK }, + { "tilde", RETROK_BACKQUOTE }, + { "backquote", RETROK_BACKQUOTE }, + { "pause", RETROK_PAUSE }, + { "nul", RETROK_UNKNOWN }, + { NULL, RETROK_UNKNOWN }, +}; + +static enum retro_key find_sk_bind(const char *str) +{ + for (size_t i = 0; input_config_key_map[i].str; i++) + { + if (strcasecmp(input_config_key_map[i].str, str) == 0) + return input_config_key_map[i].key; + } + + return RETROK_UNKNOWN; +} + +static enum retro_key find_sk_key(const char *str) +{ + if (strlen(str) == 1 && isalpha(*str)) + return (enum retro_key)(RETROK_a + (tolower(*str) - (int)'a')); + else + return find_sk_bind(str); +} + +void input_config_parse_key(config_file_t *conf, const char *prefix, const char *btn, + struct retro_keybind *bind) +{ + char tmp[64]; + char key[64]; + snprintf(key, sizeof(key), "%s_%s", prefix, btn); + + if (config_get_array(conf, key, tmp, sizeof(tmp))) + bind->key = find_sk_key(tmp); +} + +const char *input_config_get_prefix(unsigned player, bool meta) +{ + if (player == 0) + return meta ? "input" : bind_player_prefix[player]; + else if (player != 0 && !meta) + return bind_player_prefix[player]; + else + return NULL; // Don't bother with meta bind for anyone else than first player. +} + +static void parse_hat(struct retro_keybind *bind, const char *str) +{ + if (!isdigit(*str)) + return; + + char *dir = NULL; + uint16_t hat = strtoul(str, &dir, 0); + uint16_t hat_dir = 0; + + if (!dir) + { + RARCH_WARN("Found invalid hat in config!\n"); + return; + } + + if (strcasecmp(dir, "up") == 0) + hat_dir = HAT_UP_MASK; + else if (strcasecmp(dir, "down") == 0) + hat_dir = HAT_DOWN_MASK; + else if (strcasecmp(dir, "left") == 0) + hat_dir = HAT_LEFT_MASK; + else if (strcasecmp(dir, "right") == 0) + hat_dir = HAT_RIGHT_MASK; + + if (hat_dir) + bind->joykey = HAT_MAP(hat, hat_dir); +} + +void input_config_parse_joy_button(config_file_t *conf, const char *prefix, + const char *btn, struct retro_keybind *bind) +{ + char tmp[64]; + char key[64]; + snprintf(key, sizeof(key), "%s_%s_btn", prefix, btn); + + if (config_get_array(conf, key, tmp, sizeof(tmp))) + { + const char *btn = tmp; + if (strcmp(btn, "nul") == 0) + bind->joykey = NO_BTN; + else + { + if (*btn == 'h') + parse_hat(bind, btn + 1); + else + bind->joykey = strtoull(tmp, NULL, 0); + } + } +} + +void input_config_parse_joy_axis(config_file_t *conf, const char *prefix, + const char *axis, struct retro_keybind *bind) +{ + char tmp[64]; + char key[64]; + snprintf(key, sizeof(key), "%s_%s_axis", prefix, axis); + + if (config_get_array(conf, key, tmp, sizeof(tmp))) + { + if (strcmp(tmp, "nul") == 0) + bind->joyaxis = AXIS_NONE; + else if (strlen(tmp) >= 2 && (*tmp == '+' || *tmp == '-')) + { + int axis = strtol(tmp + 1, NULL, 0); + if (*tmp == '+') + bind->joyaxis = AXIS_POS(axis); + else + bind->joyaxis = AXIS_NEG(axis); + + } + } +} + diff --git a/input/input_common.h b/input/input_common.h index 68ac10c561..e5c14584d4 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -17,6 +17,7 @@ #define INPUT_COMMON_H__ #include "../driver.h" +#include "../conf/config_file.h" #include static inline void input_conv_analog_id_to_bind_id(unsigned index, unsigned id, @@ -106,5 +107,31 @@ void input_init_keyboard_lut(const struct rarch_key_map *map); enum retro_key input_translate_keysym_to_rk(unsigned sym); unsigned input_translate_rk_to_keysym(enum retro_key key); +// Input config. +struct input_bind_map +{ + bool valid; + bool meta; // Meta binds get input as prefix, not input_playerN" + const char *base; + unsigned retro_key; +}; +extern const struct input_bind_map input_config_bind_map[]; + +struct input_key_map +{ + const char *str; + enum retro_key key; +}; +extern const struct input_key_map input_config_key_map[]; + +const char *input_config_get_prefix(unsigned player, bool meta); + +void input_config_parse_key(config_file_t *conf, const char *prefix, const char *btn, + struct retro_keybind *bind); +void input_config_parse_joy_button(config_file_t *conf, const char *prefix, + const char *btn, struct retro_keybind *bind); +void input_config_parse_joy_axis(config_file_t *conf, const char *prefix, + const char *axis, struct retro_keybind *bind); + #endif diff --git a/input/linuxraw_joypad.c b/input/linuxraw_joypad.c index 388a5a4485..b9492c2a85 100644 --- a/input/linuxraw_joypad.c +++ b/input/linuxraw_joypad.c @@ -42,7 +42,7 @@ static struct linuxraw_joypad g_pads[MAX_PLAYERS]; static int g_notify; static int g_epoll; -#ifndef NO_MSG_QUEUE +#ifndef IS_JOYCONFIG static bool g_hotplug; #endif @@ -87,7 +87,7 @@ static void linuxraw_joypad_init_pad(const char *path, struct linuxraw_joypad *p { RARCH_LOG("[Joypad]: Found pad: %s on %s.\n", pad->ident, path); -#ifndef NO_MSG_QUEUE +#ifndef IS_JOYCONFIG if (g_hotplug) { char msg[512]; @@ -136,7 +136,7 @@ static void handle_plugged_pad(void) { if (g_pads[index].fd >= 0) { -#ifndef NO_MSG_QUEUE +#ifndef IS_JOYCONFIG if (g_hotplug) { char msg[512]; @@ -223,7 +223,7 @@ static bool linuxraw_joypad_init(void) epoll_ctl(g_epoll, EPOLL_CTL_ADD, g_notify, &event); } -#ifndef NO_MSG_QUEUE +#ifndef IS_JOYCONFIG g_hotplug = true; #endif @@ -250,7 +250,7 @@ static void linuxraw_joypad_destroy(void) close(g_epoll); g_epoll = -1; -#ifndef NO_MSG_QUEUE +#ifndef IS_JOYCONFIG g_hotplug = false; #endif } diff --git a/settings.c b/settings.c index 59f8e9a656..0c2912e40b 100644 --- a/settings.c +++ b/settings.c @@ -20,6 +20,7 @@ #include "config.def.h" #include "file.h" #include "compat/posix_string.h" +#include "input/input_common.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -695,329 +696,45 @@ bool config_load_file(const char *path) return true; } -struct bind_map -{ - bool valid; - bool meta; // Meta binds get input as prefix, not input_playerN" - const char *base; - unsigned retro_key; -}; - -static const char *bind_player_prefix[MAX_PLAYERS] = { - "input_player1", - "input_player2", - "input_player3", - "input_player4", - "input_player5", - "input_player6", - "input_player7", - "input_player8", -}; - -#define DECLARE_BIND(x, bind) { true, false, #x, bind } - -#define DECLARE_META_BIND(x, bind) { true, true, #x, bind } - -static const struct bind_map bind_maps[RARCH_BIND_LIST_END_NULL] = { - DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B), - DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y), - DECLARE_BIND(select, RETRO_DEVICE_ID_JOYPAD_SELECT), - DECLARE_BIND(start, RETRO_DEVICE_ID_JOYPAD_START), - DECLARE_BIND(up, RETRO_DEVICE_ID_JOYPAD_UP), - DECLARE_BIND(down, RETRO_DEVICE_ID_JOYPAD_DOWN), - DECLARE_BIND(left, RETRO_DEVICE_ID_JOYPAD_LEFT), - DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT), - DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A), - DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X), - DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L), - DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R), - DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2), - DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2), - DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3), - DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3), - DECLARE_BIND(turbo, RARCH_TURBO_ENABLE), - DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS), - DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS), - DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS), - DECLARE_BIND(l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS), - DECLARE_BIND(r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS), - DECLARE_BIND(r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS), - DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS), - DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS), - - DECLARE_META_BIND(toggle_fast_forward, RARCH_FAST_FORWARD_KEY), - DECLARE_META_BIND(hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY), - DECLARE_META_BIND(load_state, RARCH_LOAD_STATE_KEY), - DECLARE_META_BIND(save_state, RARCH_SAVE_STATE_KEY), - DECLARE_META_BIND(toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY), - DECLARE_META_BIND(exit_emulator, RARCH_QUIT_KEY), - DECLARE_META_BIND(state_slot_increase, RARCH_STATE_SLOT_PLUS), - DECLARE_META_BIND(state_slot_decrease, RARCH_STATE_SLOT_MINUS), - DECLARE_META_BIND(rewind, RARCH_REWIND), - DECLARE_META_BIND(movie_record_toggle, RARCH_MOVIE_RECORD_TOGGLE), - DECLARE_META_BIND(pause_toggle, RARCH_PAUSE_TOGGLE), - DECLARE_META_BIND(frame_advance, RARCH_FRAMEADVANCE), - DECLARE_META_BIND(reset, RARCH_RESET), - DECLARE_META_BIND(shader_next, RARCH_SHADER_NEXT), - DECLARE_META_BIND(shader_prev, RARCH_SHADER_PREV), - DECLARE_META_BIND(cheat_index_plus, RARCH_CHEAT_INDEX_PLUS), - DECLARE_META_BIND(cheat_index_minus, RARCH_CHEAT_INDEX_MINUS), - DECLARE_META_BIND(cheat_toggle, RARCH_CHEAT_TOGGLE), - DECLARE_META_BIND(screenshot, RARCH_SCREENSHOT), - DECLARE_META_BIND(dsp_config, RARCH_DSP_CONFIG), - DECLARE_META_BIND(audio_mute, RARCH_MUTE), - DECLARE_META_BIND(netplay_flip_players, RARCH_NETPLAY_FLIP), - DECLARE_META_BIND(slowmotion, RARCH_SLOWMOTION), - DECLARE_META_BIND(enable_hotkey, RARCH_ENABLE_HOTKEY), - DECLARE_META_BIND(volume_up, RARCH_VOLUME_UP), - DECLARE_META_BIND(volume_down, RARCH_VOLUME_DOWN), - DECLARE_META_BIND(overlay_next, RARCH_OVERLAY_NEXT), - DECLARE_META_BIND(disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE), - DECLARE_META_BIND(disk_next, RARCH_DISK_NEXT), - DECLARE_META_BIND(grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE), -#ifdef HAVE_RGUI - DECLARE_META_BIND(menu_toggle, RARCH_MENU_TOGGLE), -#endif -}; - -struct key_map -{ - const char *str; - int key; -}; - -static const struct key_map sk_map[] = { - { "left", RETROK_LEFT }, - { "right", RETROK_RIGHT }, - { "up", RETROK_UP }, - { "down", RETROK_DOWN }, - { "enter", RETROK_RETURN }, - { "kp_enter", RETROK_KP_ENTER }, - { "tab", RETROK_TAB }, - { "insert", RETROK_INSERT }, - { "del", RETROK_DELETE }, - { "end", RETROK_END }, - { "home", RETROK_HOME }, - { "rshift", RETROK_RSHIFT }, - { "shift", RETROK_LSHIFT }, - { "ctrl", RETROK_LCTRL }, - { "alt", RETROK_LALT }, - { "space", RETROK_SPACE }, - { "escape", RETROK_ESCAPE }, - { "add", RETROK_KP_PLUS }, - { "subtract", RETROK_KP_MINUS }, - { "kp_plus", RETROK_KP_PLUS }, - { "kp_minus", RETROK_KP_MINUS }, - { "f1", RETROK_F1 }, - { "f2", RETROK_F2 }, - { "f3", RETROK_F3 }, - { "f4", RETROK_F4 }, - { "f5", RETROK_F5 }, - { "f6", RETROK_F6 }, - { "f7", RETROK_F7 }, - { "f8", RETROK_F8 }, - { "f9", RETROK_F9 }, - { "f10", RETROK_F10 }, - { "f11", RETROK_F11 }, - { "f12", RETROK_F12 }, - { "num0", RETROK_0 }, - { "num1", RETROK_1 }, - { "num2", RETROK_2 }, - { "num3", RETROK_3 }, - { "num4", RETROK_4 }, - { "num5", RETROK_5 }, - { "num6", RETROK_6 }, - { "num7", RETROK_7 }, - { "num8", RETROK_8 }, - { "num9", RETROK_9 }, - { "pageup", RETROK_PAGEUP }, - { "pagedown", RETROK_PAGEDOWN }, - { "keypad0", RETROK_KP0 }, - { "keypad1", RETROK_KP1 }, - { "keypad2", RETROK_KP2 }, - { "keypad3", RETROK_KP3 }, - { "keypad4", RETROK_KP4 }, - { "keypad5", RETROK_KP5 }, - { "keypad6", RETROK_KP6 }, - { "keypad7", RETROK_KP7 }, - { "keypad8", RETROK_KP8 }, - { "keypad9", RETROK_KP9 }, - { "period", RETROK_PERIOD }, - { "capslock", RETROK_CAPSLOCK }, - { "numlock", RETROK_NUMLOCK }, - { "backspace", RETROK_BACKSPACE }, - { "multiply", RETROK_KP_MULTIPLY }, - { "divide", RETROK_KP_DIVIDE }, - { "print_screen", RETROK_PRINT }, - { "scroll_lock", RETROK_SCROLLOCK }, - { "tilde", RETROK_BACKQUOTE }, - { "backquote", RETROK_BACKQUOTE }, - { "pause", RETROK_PAUSE }, - { "nul", RETROK_UNKNOWN }, -}; - -static struct retro_keybind *find_retro_bind(unsigned port, int id) -{ - struct retro_keybind *binds = g_settings.input.binds[port]; - return binds[id].valid ? &binds[id] : NULL; -} - -static int find_sk_bind(const char *str) -{ - for (size_t i = 0; i < ARRAY_SIZE(sk_map); i++) - { - if (strcasecmp(sk_map[i].str, str) == 0) - return sk_map[i].key; - } - - return -1; -} - -static int find_sk_key(const char *str) -{ - if (strlen(str) == 1 && isalpha(*str)) - return (int)RETROK_a + (tolower(*str) - (int)'a'); - else - return find_sk_bind(str); -} - -static void input_config_parse_key(config_file_t *conf, const char *prefix, const char *btn, - struct retro_keybind *bind) -{ - char tmp[64]; - char key[64]; - snprintf(key, sizeof(key), "%s_%s", prefix, btn); - - if (config_get_array(conf, key, tmp, sizeof(tmp))) - { - int key = find_sk_key(tmp); - if (key >= 0) - bind->key = (enum retro_key)key; - } -} - -static const char *input_config_get_prefix(unsigned player, bool meta) -{ - if (player == 0) - return meta ? "input" : bind_player_prefix[player]; - else if (player != 0 && !meta) - return bind_player_prefix[player]; - else - return NULL; // Don't bother with meta bind for anyone else than first player. -} - static void read_keybinds_keyboard(config_file_t *conf, unsigned player, unsigned index, struct retro_keybind *bind) { - if (bind_maps[index].valid && bind_maps[index].base) + if (input_config_bind_map[index].valid && input_config_bind_map[index].base) { - const char *prefix = input_config_get_prefix(player, bind_maps[index].meta); + const char *prefix = input_config_get_prefix(player, input_config_bind_map[index].meta); if (prefix) - input_config_parse_key(conf, prefix, bind_maps[index].base, bind); - } -} - -static void parse_hat(struct retro_keybind *bind, const char *str) -{ - if (!isdigit(*str)) - return; - - char *dir = NULL; - uint16_t hat = strtoul(str, &dir, 0); - uint16_t hat_dir = 0; - - if (!dir) - { - RARCH_WARN("Found invalid hat in config!\n"); - return; - } - - if (strcasecmp(dir, "up") == 0) - hat_dir = HAT_UP_MASK; - else if (strcasecmp(dir, "down") == 0) - hat_dir = HAT_DOWN_MASK; - else if (strcasecmp(dir, "left") == 0) - hat_dir = HAT_LEFT_MASK; - else if (strcasecmp(dir, "right") == 0) - hat_dir = HAT_RIGHT_MASK; - - if (hat_dir) - bind->joykey = HAT_MAP(hat, hat_dir); -} - -static void input_config_parse_joy_button(config_file_t *conf, const char *prefix, - const char *btn, struct retro_keybind *bind) -{ - char tmp[64]; - char key[64]; - snprintf(key, sizeof(key), "%s_%s_btn", prefix, btn); - - if (config_get_array(conf, key, tmp, sizeof(tmp))) - { - const char *btn = tmp; - if (strcmp(btn, "nul") == 0) - bind->joykey = NO_BTN; - else - { - if (*btn == 'h') - parse_hat(bind, btn + 1); - else - bind->joykey = strtoull(tmp, NULL, 0); - } - } -} - -static void input_config_parse_joy_axis(config_file_t *conf, const char *prefix, - const char *axis, struct retro_keybind *bind) -{ - char tmp[64]; - char key[64]; - snprintf(key, sizeof(key), "%s_%s_axis", prefix, axis); - - if (config_get_array(conf, key, tmp, sizeof(tmp))) - { - if (strcmp(tmp, "nul") == 0) - bind->joyaxis = AXIS_NONE; - else if (strlen(tmp) >= 2 && (*tmp == '+' || *tmp == '-')) - { - int axis = strtol(tmp + 1, NULL, 0); - if (*tmp == '+') - bind->joyaxis = AXIS_POS(axis); - else - bind->joyaxis = AXIS_NEG(axis); - - } + input_config_parse_key(conf, prefix, input_config_bind_map[index].base, bind); } } static void read_keybinds_button(config_file_t *conf, unsigned player, unsigned index, struct retro_keybind *bind) { - if (bind_maps[index].valid && bind_maps[index].base) + if (input_config_bind_map[index].valid && input_config_bind_map[index].base) { - const char *prefix = input_config_get_prefix(player, bind_maps[index].meta); + const char *prefix = input_config_get_prefix(player, input_config_bind_map[index].meta); if (prefix) - input_config_parse_joy_button(conf, prefix, bind_maps[index].base, bind); + input_config_parse_joy_button(conf, prefix, input_config_bind_map[index].base, bind); } } static void read_keybinds_axis(config_file_t *conf, unsigned player, unsigned index, struct retro_keybind *bind) { - if (bind_maps[index].valid && bind_maps[index].base) + if (input_config_bind_map[index].valid && input_config_bind_map[index].base) { - const char *prefix = input_config_get_prefix(player, bind_maps[index].meta); + const char *prefix = input_config_get_prefix(player, input_config_bind_map[index].meta); if (prefix) - input_config_parse_joy_axis(conf, prefix, bind_maps[index].base, bind); + input_config_parse_joy_axis(conf, prefix, input_config_bind_map[index].base, bind); } } static void read_keybinds_player(config_file_t *conf, unsigned player) { - for (unsigned i = 0; bind_maps[i].valid; i++) + for (unsigned i = 0; input_config_bind_map[i].valid; i++) { - struct retro_keybind *bind = find_retro_bind(player, bind_maps[i].retro_key); - if (!bind) + struct retro_keybind *bind = &g_settings.input.binds[player][i]; + if (!bind->valid) continue; read_keybinds_keyboard(conf, player, i, bind); @@ -1055,11 +772,11 @@ static void save_keybind_key(config_file_t *conf, const char *prefix, const char ascii[0] = 'a' + (bind->key - RETROK_a); else { - for (unsigned i = 0; i < ARRAY_SIZE(sk_map); i++) + for (unsigned i = 0; input_config_key_map[i].str; i++) { - if (sk_map[i].key == bind->key) + if (input_config_key_map[i].key == bind->key) { - btn = sk_map[i].str; + btn = input_config_key_map[i].str; break; } } @@ -1161,11 +878,11 @@ static void save_keybind(config_file_t *conf, const char *prefix, const char *ba static void save_keybinds_player(config_file_t *conf, unsigned player) { - for (unsigned i = 0; bind_maps[i].valid; i++) + for (unsigned i = 0; input_config_bind_map[i].valid; i++) { - const char *prefix = input_config_get_prefix(player, bind_maps[i].meta); + const char *prefix = input_config_get_prefix(player, input_config_bind_map[i].meta); if (prefix) - save_keybind(conf, prefix, bind_maps[i].base, &g_settings.input.binds[player][i]); + save_keybind(conf, prefix, input_config_bind_map[i].base, &g_settings.input.binds[player][i]); } } From 0ac849d825e88aa80d96fd60a97916a920206d0c Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 13:25:40 +0200 Subject: [PATCH 03/10] Let retroarch-joyconfig write autoconfigs. --- docs/retroarch-joyconfig.1 | 4 + input/dinput.c | 8 ++ input/input_common.c | 124 ++++++++++--------- input/input_common.h | 3 + input/linuxraw_joypad.c | 9 ++ input/sdl_joypad.c | 9 ++ tools/retroarch-joyconfig.c | 230 +++++++++++++++++------------------- 7 files changed, 208 insertions(+), 179 deletions(-) diff --git a/docs/retroarch-joyconfig.1 b/docs/retroarch-joyconfig.1 index f36df4d243..c3117fe61b 100644 --- a/docs/retroarch-joyconfig.1 +++ b/docs/retroarch-joyconfig.1 @@ -34,6 +34,10 @@ Use config file found in PATH as a base. Old configuration values can be overwri \fB--output PATH, -o PATH\fR Writes the final config to a file, rather than \fBstdout\fR. If -i and -o point to the same file, the file found in PATH will simply be updated with the new configs. +.TP +\fB-a PATH, --autoconfig PATH\fR +Also writes an autoconfigure file for the joypad which was configured. It can be used by RetroArch to automatically configure a joypad when it's plugged in. + .TP \fB--misc, -m\fR Also configure some binds that aren't directly related to RetroPad, such as save states, fullscreen toggling, etc. diff --git a/input/dinput.c b/input/dinput.c index c7e66f23c9..fd997a575f 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -555,6 +555,13 @@ static bool dinput_joypad_query_pad(unsigned pad) return pad < MAX_PLAYERS && g_pads[pad].joypad; } +static const char *dinput_joypad_name(unsigned pad) +{ + (unsigned)pad; + // FIXME + return NULL; +} + const rarch_joypad_driver_t dinput_joypad = { dinput_joypad_init, dinput_joypad_query_pad, @@ -562,6 +569,7 @@ const rarch_joypad_driver_t dinput_joypad = { dinput_joypad_button, dinput_joypad_axis, dinput_joypad_poll, + dinput_joypad_name, "dinput", }; diff --git a/input/input_common.c b/input/input_common.c index 5df711abb5..8cd9ecdef1 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -86,6 +86,14 @@ void input_joypad_poll(const rarch_joypad_driver_t *driver) driver->poll(); } +const char *input_joypad_name(const rarch_joypad_driver_t *driver, unsigned joypad) +{ + if (!driver) + return NULL; + + return driver->name(joypad); +} + bool input_joypad_pressed(const rarch_joypad_driver_t *driver, unsigned port, const struct retro_keybind *key) { @@ -507,68 +515,68 @@ static const char *bind_player_prefix[MAX_PLAYERS] = { "input_player8", }; -#define DECLARE_BIND(x, bind) { true, false, #x, bind } -#define DECLARE_META_BIND(x, bind) { true, true, #x, bind } +#define DECLARE_BIND(x, bind, desc) { true, false, #x, desc, bind } +#define DECLARE_META_BIND(x, bind, desc) { true, true, #x, desc, bind } const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { - DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B), - DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y), - DECLARE_BIND(select, RETRO_DEVICE_ID_JOYPAD_SELECT), - DECLARE_BIND(start, RETRO_DEVICE_ID_JOYPAD_START), - DECLARE_BIND(up, RETRO_DEVICE_ID_JOYPAD_UP), - DECLARE_BIND(down, RETRO_DEVICE_ID_JOYPAD_DOWN), - DECLARE_BIND(left, RETRO_DEVICE_ID_JOYPAD_LEFT), - DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT), - DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A), - DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X), - DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L), - DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R), - DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2), - DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2), - DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3), - DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3), - DECLARE_BIND(turbo, RARCH_TURBO_ENABLE), - DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS), - DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS), - DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS), - DECLARE_BIND(l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS), - DECLARE_BIND(r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS), - DECLARE_BIND(r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS), - DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS), - DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS), + DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B, "B button (down)"), + DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y, "Y button (left)"), + DECLARE_BIND(select, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select button"), + DECLARE_BIND(start, RETRO_DEVICE_ID_JOYPAD_START, "Start button"), + DECLARE_BIND(up, RETRO_DEVICE_ID_JOYPAD_UP, "Up D-pad"), + DECLARE_BIND(down, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down D-pad"), + DECLARE_BIND(left, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left D-pad"), + DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right D-pad"), + DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A, "A button (right)"), + DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X, "X button (top)"), + DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L, "L button (left shoulder)"), + DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R, "R button (right shoulder)"), + DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2, "L2 button (left shoulder #2)"), + DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2, "R2 button (right shoulder #2)"), + DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3, "L3 button (left analog button)"), + DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3, "R3 button (right analog button)"), + DECLARE_BIND(turbo, RARCH_TURBO_ENABLE, "Turbo enable"), + DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS, "Left analog X+ (right)"), + DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS, "Left analog X- (left)"), + DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS, "Left analog Y+ (down)"), + DECLARE_BIND(l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS, "Left analog Y- (up)"), + DECLARE_BIND(r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS, "Right analog X+ (right)"), + DECLARE_BIND(r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS, "Right analog X- (left)"), + DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS, "Right analog Y+ (down)"), + DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS, "Right analog Y- (up)"), - DECLARE_META_BIND(toggle_fast_forward, RARCH_FAST_FORWARD_KEY), - DECLARE_META_BIND(hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY), - DECLARE_META_BIND(load_state, RARCH_LOAD_STATE_KEY), - DECLARE_META_BIND(save_state, RARCH_SAVE_STATE_KEY), - DECLARE_META_BIND(toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY), - DECLARE_META_BIND(exit_emulator, RARCH_QUIT_KEY), - DECLARE_META_BIND(state_slot_increase, RARCH_STATE_SLOT_PLUS), - DECLARE_META_BIND(state_slot_decrease, RARCH_STATE_SLOT_MINUS), - DECLARE_META_BIND(rewind, RARCH_REWIND), - DECLARE_META_BIND(movie_record_toggle, RARCH_MOVIE_RECORD_TOGGLE), - DECLARE_META_BIND(pause_toggle, RARCH_PAUSE_TOGGLE), - DECLARE_META_BIND(frame_advance, RARCH_FRAMEADVANCE), - DECLARE_META_BIND(reset, RARCH_RESET), - DECLARE_META_BIND(shader_next, RARCH_SHADER_NEXT), - DECLARE_META_BIND(shader_prev, RARCH_SHADER_PREV), - DECLARE_META_BIND(cheat_index_plus, RARCH_CHEAT_INDEX_PLUS), - DECLARE_META_BIND(cheat_index_minus, RARCH_CHEAT_INDEX_MINUS), - DECLARE_META_BIND(cheat_toggle, RARCH_CHEAT_TOGGLE), - DECLARE_META_BIND(screenshot, RARCH_SCREENSHOT), - DECLARE_META_BIND(dsp_config, RARCH_DSP_CONFIG), - DECLARE_META_BIND(audio_mute, RARCH_MUTE), - DECLARE_META_BIND(netplay_flip_players, RARCH_NETPLAY_FLIP), - DECLARE_META_BIND(slowmotion, RARCH_SLOWMOTION), - DECLARE_META_BIND(enable_hotkey, RARCH_ENABLE_HOTKEY), - DECLARE_META_BIND(volume_up, RARCH_VOLUME_UP), - DECLARE_META_BIND(volume_down, RARCH_VOLUME_DOWN), - DECLARE_META_BIND(overlay_next, RARCH_OVERLAY_NEXT), - DECLARE_META_BIND(disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE), - DECLARE_META_BIND(disk_next, RARCH_DISK_NEXT), - DECLARE_META_BIND(grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE), + DECLARE_META_BIND(toggle_fast_forward, RARCH_FAST_FORWARD_KEY, "Fast forward toggle"), + DECLARE_META_BIND(hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY, "Fast forward hold"), + DECLARE_META_BIND(load_state, RARCH_LOAD_STATE_KEY, "Load state"), + DECLARE_META_BIND(save_state, RARCH_SAVE_STATE_KEY, "Save state"), + DECLARE_META_BIND(toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY, "Fullscreen toggle"), + DECLARE_META_BIND(exit_emulator, RARCH_QUIT_KEY, "Quit RetroArch"), + DECLARE_META_BIND(state_slot_increase, RARCH_STATE_SLOT_PLUS, "Savestate slot +"), + DECLARE_META_BIND(state_slot_decrease, RARCH_STATE_SLOT_MINUS, "Savestate slot -"), + DECLARE_META_BIND(rewind, RARCH_REWIND, "Rewind"), + DECLARE_META_BIND(movie_record_toggle, RARCH_MOVIE_RECORD_TOGGLE, "Movie record toggle"), + DECLARE_META_BIND(pause_toggle, RARCH_PAUSE_TOGGLE, "Pause toggle"), + DECLARE_META_BIND(frame_advance, RARCH_FRAMEADVANCE, "Frameadvance"), + DECLARE_META_BIND(reset, RARCH_RESET, "Reset game"), + DECLARE_META_BIND(shader_next, RARCH_SHADER_NEXT, "Next shader"), + DECLARE_META_BIND(shader_prev, RARCH_SHADER_PREV, "Previous shader"), + DECLARE_META_BIND(cheat_index_plus, RARCH_CHEAT_INDEX_PLUS, "Cheat index +"), + DECLARE_META_BIND(cheat_index_minus, RARCH_CHEAT_INDEX_MINUS, "Cheat index -"), + DECLARE_META_BIND(cheat_toggle, RARCH_CHEAT_TOGGLE, "Cheat toggle"), + DECLARE_META_BIND(screenshot, RARCH_SCREENSHOT, "Take screenshot"), + DECLARE_META_BIND(dsp_config, RARCH_DSP_CONFIG, "DSP config"), + DECLARE_META_BIND(audio_mute, RARCH_MUTE, "Audio mute toggle"), + DECLARE_META_BIND(netplay_flip_players, RARCH_NETPLAY_FLIP, "Netplay flip players"), + DECLARE_META_BIND(slowmotion, RARCH_SLOWMOTION, "Slow motion"), + DECLARE_META_BIND(enable_hotkey, RARCH_ENABLE_HOTKEY, "Enable hotkeys"), + DECLARE_META_BIND(volume_up, RARCH_VOLUME_UP, "Volume +"), + DECLARE_META_BIND(volume_down, RARCH_VOLUME_DOWN, "Volume -"), + DECLARE_META_BIND(overlay_next, RARCH_OVERLAY_NEXT, "Overlay next"), + DECLARE_META_BIND(disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE, "Disk eject toggle"), + DECLARE_META_BIND(disk_next, RARCH_DISK_NEXT, "Disk next"), + DECLARE_META_BIND(grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE, "Grab mouse toggle"), #ifdef HAVE_RGUI - DECLARE_META_BIND(menu_toggle, RARCH_MENU_TOGGLE), + DECLARE_META_BIND(menu_toggle, RARCH_MENU_TOGGLE, "RGUI menu toggle"), #endif }; diff --git a/input/input_common.h b/input/input_common.h index e5c14584d4..64c5083d7c 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -66,6 +66,7 @@ typedef struct rarch_joypad_driver bool (*button)(unsigned, uint16_t); int16_t (*axis)(unsigned, uint32_t); void (*poll)(void); + const char *(*name)(unsigned); const char *ident; } rarch_joypad_driver_t; @@ -87,6 +88,7 @@ bool input_joypad_hat_raw(const rarch_joypad_driver_t *driver, unsigned joypad, unsigned hat_dir, unsigned hat); void input_joypad_poll(const rarch_joypad_driver_t *driver); +const char *input_joypad_name(const rarch_joypad_driver_t *driver, unsigned joypad); extern const rarch_joypad_driver_t dinput_joypad; extern const rarch_joypad_driver_t linuxraw_joypad; @@ -113,6 +115,7 @@ struct input_bind_map bool valid; bool meta; // Meta binds get input as prefix, not input_playerN" const char *base; + const char *desc; unsigned retro_key; }; extern const struct input_bind_map input_config_bind_map[]; diff --git a/input/linuxraw_joypad.c b/input/linuxraw_joypad.c index b9492c2a85..983bc75ba0 100644 --- a/input/linuxraw_joypad.c +++ b/input/linuxraw_joypad.c @@ -292,6 +292,14 @@ static bool linuxraw_joypad_query_pad(unsigned pad) return pad < MAX_PLAYERS && g_pads[pad].fd >= 0; } +static const char *linuxraw_joypad_name(unsigned pad) +{ + if (pad >= MAX_PLAYERS) + return NULL; + + return *g_pads[pad].ident ? g_pads[pad].ident : NULL; +} + const rarch_joypad_driver_t linuxraw_joypad = { linuxraw_joypad_init, linuxraw_joypad_query_pad, @@ -299,6 +307,7 @@ const rarch_joypad_driver_t linuxraw_joypad = { linuxraw_joypad_button, linuxraw_joypad_axis, linuxraw_joypad_poll, + linuxraw_joypad_name, "linuxraw", }; diff --git a/input/sdl_joypad.c b/input/sdl_joypad.c index 13bcd8cf34..812936be56 100644 --- a/input/sdl_joypad.c +++ b/input/sdl_joypad.c @@ -155,6 +155,14 @@ static bool sdl_joypad_query_pad(unsigned pad) return pad < MAX_PLAYERS && g_pads[pad].joypad; } +static const char *sdl_joypad_name(unsigned pad) +{ + if (pad >= MAX_PLAYERS) + return NULL; + + return SDL_JoystickName(pad); +} + const rarch_joypad_driver_t sdl_joypad = { sdl_joypad_init, sdl_joypad_query_pad, @@ -162,6 +170,7 @@ const rarch_joypad_driver_t sdl_joypad = { sdl_joypad_button, sdl_joypad_axis, sdl_joypad_poll, + sdl_joypad_name, "sdl", }; diff --git a/tools/retroarch-joyconfig.c b/tools/retroarch-joyconfig.c index ec7910443c..47e4ff4dc6 100644 --- a/tools/retroarch-joyconfig.c +++ b/tools/retroarch-joyconfig.c @@ -37,6 +37,7 @@ static int g_player = 1; static int g_joypad = 0; static char *g_in_path = NULL; static char *g_out_path = NULL; +static char *g_auto_path = NULL; static bool g_use_misc = false; static void print_help(void) @@ -44,91 +45,18 @@ static void print_help(void) puts("=================="); puts("retroarch-joyconfig"); puts("=================="); - puts("Usage: retroarch-joyconfig [ -p/--player <1-5> | -j/--joypad | -i/--input | -o/--output | -h/--help ]"); + puts("Usage: retroarch-joyconfig [ -p/--player <1-8> | -j/--joypad | -i/--input | -o/--output | -h/--help ]"); puts(""); - puts("-p/--player: Which player to configure for (1 up to and including 5)."); + puts("-p/--player: Which player to configure for (1 up to and including 8)."); puts("-j/--joypad: Which joypad to use when configuring (first joypad is 0)."); puts("-i/--input: Input file to configure with. Binds will be added on or overwritten."); puts("\tIf not selected, an empty config will be used as a base."); puts("-o/--output: Output file to write to. If not selected, config file will be dumped to stdout."); + puts("-a/--autoconfig: Outputs an autoconfig file for joypad which was configured."); puts("-m/--misc: Also configure various keybinds that are not directly libretro related. These configurations are for player 1 only."); puts("-h/--help: This help."); } -struct bind -{ - const char *keystr; - const char *confbtn[MAX_PLAYERS]; - const char *confaxis[MAX_PLAYERS]; - bool is_misc; -}; - -#define BIND(x, k) { x, { "input_player1_" #k "_btn", "input_player2_" #k "_btn", "input_player3_" #k "_btn", "input_player4_" #k "_btn", "input_player5_" #k "_btn" }, {"input_player1_" #k "_axis", "input_player2_" #k "_axis", "input_player3_" #k "_axis", "input_player4_" #k "_axis", "input_player5_" #k "_axis"}, false} - -#define MISC_BIND(x, k) { x, { "input_" #k "_btn" }, { "input_" #k "_axis" }, true} - -static struct bind binds[] = { - BIND("A button (right)", a), - BIND("B button (down)", b), - BIND("X button (top)", x), - BIND("Y button (left)", y), - BIND("L button (left shoulder)", l), - BIND("R button (right shoulder)", r), - BIND("L2 button (left shoulder #2)", l2), - BIND("R2 button (right shoulder #2)", r2), - BIND("L3 button (left analog button)", l3), - BIND("R3 button (right analog button)", r3), - BIND("Start button", start), - BIND("Select button", select), - BIND("Left D-pad", left), - BIND("Up D-pad", up), - BIND("Right D-pad", right), - BIND("Down D-pad", down), - - BIND("Left analog X+ (right)", l_x_plus), - BIND("Left analog Y+ (down)", l_y_plus), - BIND("Left analog X- (left)", l_x_minus), - BIND("Left analog Y- (up)", l_y_minus), - BIND("Right analog X+ (right)", r_x_plus), - BIND("Right analog Y+ (down)", r_y_plus), - BIND("Right analog X- (left)", r_x_minus), - BIND("Right analog Y- (up)", r_y_minus), - - MISC_BIND("Save state", save_state), - MISC_BIND("Load state", load_state), - MISC_BIND("Exit emulator", exit_emulator), - MISC_BIND("Toggle fullscreen", toggle_fullscreen), - MISC_BIND("Save state slot increase", state_slot_increase), - MISC_BIND("Save state slot decrease", state_slot_decrease), - MISC_BIND("Toggle fast forward", toggle_fast_forward), - MISC_BIND("Hold fast forward", hold_fast_forward), - MISC_BIND("Audio input rate step up", rate_step_up), - MISC_BIND("Audio input rate step down", rate_step_down), - MISC_BIND("Rewind", rewind), - MISC_BIND("Movie recording toggle", movie_record_toggle), - MISC_BIND("Pause", pause_toggle), - MISC_BIND("Frame advance", frame_advance), - MISC_BIND("Reset", reset), - MISC_BIND("Next shader", shader_next), - MISC_BIND("Previous shader", shader_prev), - MISC_BIND("Toggle cheat on/off", cheat_toggle), - MISC_BIND("Cheat index plus", cheat_index_plus), - MISC_BIND("Cheat index minus", cheat_index_minus), - MISC_BIND("Screenshot", screenshot), - MISC_BIND("DSP config", dsp_config), - MISC_BIND("Audio mute/unmute", audio_mute), - MISC_BIND("Netplay player flip", netplay_flip_players), - MISC_BIND("Slow motion", slowmotion), - MISC_BIND("Hotkey enable", enable_hotkey), - MISC_BIND("Volume up", volume_up), - MISC_BIND("Volume down", volume_down), - MISC_BIND("Next overlay", overlay_next), - MISC_BIND("Disk eject toggle", disk_eject_toggle), - MISC_BIND("Disk next cycle", disk_next), - MISC_BIND("Grab mouse toggle", grab_mouse_toggle), - MISC_BIND("Menu toggle", menu_toggle), -}; - #define MAX_BUTTONS 32 #define MAX_AXES 32 #define MAX_HATS 32 @@ -163,7 +91,7 @@ static void poll_joypad(const rarch_joypad_driver_t *driver, } } -static void get_binds(config_file_t *conf, int player, int joypad) +static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, int joypad) { const rarch_joypad_driver_t *driver = input_joypad_init_first(); if (!driver) @@ -179,6 +107,11 @@ static void get_binds(config_file_t *conf, int player, int joypad) } fprintf(stderr, "Found joypad driver: %s\n", driver->ident); + const char *joypad_name = input_joypad_name(driver, joypad); + fprintf(stderr, "Using joypad: %s\n", joypad_name ? joypad_name : "Unknown"); + + if (joypad_name && auto_conf) + config_set_string(auto_conf, "input_device", joypad_name); int16_t initial_axes[MAX_AXES] = {0}; struct poll_data old_poll = {{0}}; @@ -208,11 +141,15 @@ static void get_binds(config_file_t *conf, int player, int joypad) fprintf(stderr, "Configuring binds for player #%d on joypad #%d.\n\n", player + 1, joypad); - for (unsigned i = 0; i < sizeof(binds) / sizeof(binds[0]) && (g_use_misc || !binds[i].is_misc) ; i++) + for (unsigned i = 0; input_config_bind_map[i].valid && + (g_use_misc || !input_config_bind_map[i].meta); i++) { - fprintf(stderr, "%s\n", binds[i].keystr); + if (i == RARCH_TURBO_ENABLE) + continue; - unsigned player_index = binds[i].is_misc ? 0 : player; + fprintf(stderr, "%s\n", input_config_bind_map[i].desc); + + unsigned player_index = input_config_bind_map[i].meta ? 0 : player; for (;;) { @@ -229,51 +166,74 @@ static void get_binds(config_file_t *conf, int player, int joypad) if (new_poll.buttons[j] && !old_poll.buttons[j]) { fprintf(stderr, "\tJoybutton pressed: %u\n", j); - config_set_int(conf, binds[i].confbtn[player_index], j); + char key[64]; + snprintf(key, sizeof(key), "%s_%s_btn", + input_config_get_prefix(player_index, input_config_bind_map[i].meta), input_config_bind_map[i].base); + config_set_int(conf, key, j); + + if (auto_conf) + { + snprintf(key, sizeof(key), "input_%s_btn", + input_config_bind_map[i].base); + config_set_int(auto_conf, key, j); + } + goto out; } } for (int j = 0; j < MAX_AXES; j++) { - if (new_poll.axes[j] != old_poll.axes[j]) + if (new_poll.axes[j] == old_poll.axes[j]) + continue; + + int16_t value = new_poll.axes[j]; + bool same_axis = last_axis == j; + bool require_negative = initial_axes[j] > 0; + bool require_positive = initial_axes[j] < 0; + + // Block the axis config until we're sure axes have returned to their neutral state. + if (same_axis) { - int16_t value = new_poll.axes[j]; - bool same_axis = last_axis == j; - bool require_negative = initial_axes[j] > 0; - bool require_positive = initial_axes[j] < 0; + if (abs(value) < 10000 || + (require_positive && value < 0) || + (require_negative && value > 0)) + block_axis = false; + } - // Block the axis config until we're sure axes have returned to their neutral state. - if (same_axis) + // If axes are in their neutral state, we can't allow it. + if (require_negative && value >= 0) + continue; + if (require_positive && value <= 0) + continue; + + if (block_axis) + continue; + + if (abs(value) > 20000) + { + last_axis = j; + fprintf(stderr, "\tJoyaxis moved: Axis %d, Value %d\n", j, value); + + char buf[8]; + snprintf(buf, sizeof(buf), + value > 0 ? "+%d" : "-%d", j); + + char key[64]; + snprintf(key, sizeof(key), "%s_%s_axis", + input_config_get_prefix(player_index, input_config_bind_map[i].meta), input_config_bind_map[i].base); + + config_set_string(conf, key, buf); + + if (auto_conf) { - if (abs(value) < 10000 || - (require_positive && value < 0) || - (require_negative && value > 0)) - block_axis = false; + snprintf(key, sizeof(key), "input_%s_axis", + input_config_bind_map[i].base); + config_set_string(auto_conf, key, buf); } - // If axes are in their neutral state, we can't allow it. - if (require_negative && value >= 0) - continue; - if (require_positive && value <= 0) - continue; - - if (block_axis) - continue; - - if (abs(value) > 20000) - { - last_axis = j; - fprintf(stderr, "\tJoyaxis moved: Axis %d, Value %d\n", j, value); - - char buf[8]; - snprintf(buf, sizeof(buf), - value > 0 ? "+%d" : "-%d", j); - - config_set_string(conf, binds[i].confaxis[player_index], buf); - block_axis = true; - goto out; - } + block_axis = true; + goto out; } } @@ -297,7 +257,20 @@ static void get_binds(config_file_t *conf, int player, int joypad) fprintf(stderr, "\tJoyhat moved: Hat %d, direction %s\n", j, quark); char buf[16]; snprintf(buf, sizeof(buf), "h%d%s", j, quark); - config_set_string(conf, binds[i].confbtn[player_index], buf); + + char key[64]; + snprintf(key, sizeof(key), "%s_%s_btn", + input_config_get_prefix(player_index, input_config_bind_map[i].meta), input_config_bind_map[i].base); + + config_set_string(conf, key, buf); + + if (auto_conf) + { + snprintf(key, sizeof(key), "input_%s_btn", + input_config_bind_map[i].base); + config_set_string(auto_conf, key, buf); + } + goto out; } } @@ -309,10 +282,11 @@ out: static void parse_input(int argc, char *argv[]) { - char optstring[] = "i:o:p:j:hm"; + char optstring[] = "i:o:a:p:j:hm"; struct option opts[] = { { "input", 1, NULL, 'i' }, { "output", 1, NULL, 'o' }, + { "autoconfig", 1, NULL, 'a' }, { "player", 1, NULL, 'p' }, { "joypad", 1, NULL, 'j' }, { "help", 0, NULL, 'h' }, @@ -341,6 +315,10 @@ static void parse_input(int argc, char *argv[]) g_out_path = strdup(optarg); break; + case 'a': + g_auto_path = strdup(optarg); + break; + case 'm': g_use_misc = true; break; @@ -410,12 +388,22 @@ int main(int argc, char *argv[]) config_set_int(conf, index_list[g_player - 1], g_joypad); - get_binds(conf, g_player - 1, g_joypad); + config_file_t *auto_conf = NULL; + if (g_auto_path) + auto_conf = config_file_new(NULL); + + get_binds(conf, auto_conf, g_player - 1, g_joypad); config_file_write(conf, g_out_path); config_file_free(conf); - if (g_in_path) - free(g_in_path); - if (g_out_path) - free(g_out_path); + if (auto_conf) + { + fprintf(stderr, "Writing autoconfig profile to: %s.\n", g_auto_path); + config_file_write(auto_conf, g_auto_path); + config_file_free(auto_conf); + } + + free(g_in_path); + free(g_out_path); + free(g_auto_path); return 0; } From 1da31a84ab0ff8e52f43e309114b9eef6e492f02 Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 13:32:11 +0200 Subject: [PATCH 04/10] Prompt user to "reset" joypad state. Many joypad drivers have "stale state" lying around and need some events to be fired to normalize. Broken initial state will break joypad configure like this. --- tools/retroarch-joyconfig.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/retroarch-joyconfig.c b/tools/retroarch-joyconfig.c index 47e4ff4dc6..f3d40c6b6a 100644 --- a/tools/retroarch-joyconfig.c +++ b/tools/retroarch-joyconfig.c @@ -113,6 +113,7 @@ static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, if (joypad_name && auto_conf) config_set_string(auto_conf, "input_device", joypad_name); + int16_t initial_axes[MAX_AXES] = {0}; struct poll_data old_poll = {{0}}; struct poll_data new_poll = {{0}}; @@ -120,6 +121,9 @@ static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, int last_axis = -1; bool block_axis = false; + poll_joypad(driver, joypad, &old_poll); + fprintf(stderr, "\nJoypads tend to have stale state after opened.\nPress some buttons and move some axes around to make sure joypad state is reset properly.\nWhen done, press Enter ... "); + getchar(); poll_joypad(driver, joypad, &old_poll); for (int i = 0; i < MAX_AXES; i++) From e74f150239478781a8d2e667fb04462caa3753e3 Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 13:34:41 +0200 Subject: [PATCH 05/10] Also dump input_driver used in retroarch-joyconfig. --- tools/retroarch-joyconfig.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/retroarch-joyconfig.c b/tools/retroarch-joyconfig.c index f3d40c6b6a..af7aa75327 100644 --- a/tools/retroarch-joyconfig.c +++ b/tools/retroarch-joyconfig.c @@ -111,8 +111,10 @@ static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, fprintf(stderr, "Using joypad: %s\n", joypad_name ? joypad_name : "Unknown"); if (joypad_name && auto_conf) + { config_set_string(auto_conf, "input_device", joypad_name); - + config_set_string(auto_conf, "input_driver", driver->ident); + } int16_t initial_axes[MAX_AXES] = {0}; struct poll_data old_poll = {{0}}; @@ -137,7 +139,7 @@ static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, // If default negative, we can't trigger on the negative axis, and similar with defaulted positive axes. if (initial) - fprintf(stderr, "Axis %d is defaulted to %s axis value of %d\n", i, initial > 0 ? "positive" : "negative", initial); + fprintf(stderr, "Axis %d is defaulted to %s axis value of %d.\n", i, initial > 0 ? "positive" : "negative", initial); initial_axes[i] = initial; } From 04ac1e3efa4227717e7b02668d3ae4e156171611 Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 13:39:03 +0200 Subject: [PATCH 06/10] Clarify when buttons are initially pressed. --- tools/retroarch-joyconfig.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/retroarch-joyconfig.c b/tools/retroarch-joyconfig.c index af7aa75327..dad2e3d7a1 100644 --- a/tools/retroarch-joyconfig.c +++ b/tools/retroarch-joyconfig.c @@ -124,7 +124,7 @@ static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, bool block_axis = false; poll_joypad(driver, joypad, &old_poll); - fprintf(stderr, "\nJoypads tend to have stale state after opened.\nPress some buttons and move some axes around to make sure joypad state is reset properly.\nWhen done, press Enter ... "); + fprintf(stderr, "\nJoypads tend to have stale state after opened.\nPress some buttons and move some axes around to make sure joypad state is completely neutral before proceeding.\nWhen done, press Enter ... "); getchar(); poll_joypad(driver, joypad, &old_poll); @@ -144,6 +144,12 @@ static void get_binds(config_file_t *conf, config_file_t *auto_conf, int player, initial_axes[i] = initial; } + for (int i = 0; i < MAX_BUTTONS; i++) + { + if (old_poll.buttons[i]) + fprintf(stderr, "Button %d was initially pressed. This indicates broken initial state.\n", i); + } + fprintf(stderr, "Configuring binds for player #%d on joypad #%d.\n\n", player + 1, joypad); From cca7fce89cda33417e3a7f7b6723c14d11cef911 Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 14:36:36 +0200 Subject: [PATCH 07/10] Add joypad autoconfig support. --- Makefile | 10 ++- config.def.h | 2 - general.h | 6 ++ input/dinput.c | 2 +- input/input_common.c | 114 +++++++++++++++++++++++++++++--- input/input_common.h | 4 +- input/linuxraw_input.c | 4 +- input/linuxraw_joypad.c | 11 +++ input/sdl_input.c | 16 ++--- input/x11_input.c | 4 +- ios/RetroArch/input/ios_input.c | 8 +-- retroarch.cfg | 16 +++-- settings.c | 8 ++- 13 files changed, 164 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index 9d13690ebd..d9e3548e13 100644 --- a/Makefile +++ b/Makefile @@ -39,14 +39,14 @@ JOYCONFIG_OBJ = tools/retroarch-joyconfig.o \ conf/config_file.o \ file_path.o \ compat/compat.o \ - input/input_common.o + tools/input_common_joyconfig.o RETROLAUNCH_OBJ = tools/retrolaunch/main.o \ tools/retrolaunch/sha1.o \ tools/retrolaunch/parser.o \ tools/retrolaunch/cd_detect.o \ tools/retrolaunch/rl_fnmatch.o \ - tools/input_common.o \ + tools/input_common_launch.o \ file_path.o \ compat/compat.o \ conf/config_file.o \ @@ -374,10 +374,14 @@ tools/linuxraw_joypad.o: input/linuxraw_joypad.c @$(if $(Q), $(shell echo echo CC $<),) $(Q)$(CC) $(CFLAGS) $(DEFINES) -DIS_JOYCONFIG -c -o $@ $< -tools/input_common.o: input/input_common.c +tools/input_common_launch.o: input/input_common.c @$(if $(Q), $(shell echo echo CC $<),) $(Q)$(CC) $(CFLAGS) $(DEFINES) -DIS_RETROLAUNCH -c -o $@ $< +tools/input_common_joyconfig.o: input/input_common.c + @$(if $(Q), $(shell echo echo CC $<),) + $(Q)$(CC) $(CFLAGS) $(DEFINES) -DIS_JOYCONFIG -c -o $@ $< + %.o: %.S config.h config.mk $(HEADERS) @$(if $(Q), $(shell echo echo AS $<),) $(Q)$(CC) $(CFLAGS) $(ASFLAGS) $(DEFINES) -c -o $@ $< diff --git a/config.def.h b/config.def.h index 20d57fa6cc..e561ab5173 100644 --- a/config.def.h +++ b/config.def.h @@ -413,11 +413,9 @@ static const unsigned turbo_duty_cycle = 3; // Enable input debugging output. static const bool input_debug_enable = false; -#ifdef ANDROID // Enable input auto-detection. Will attempt to autoconfigure // gamepads, plug-and-play style. static const bool input_autodetect_enable = true; -#endif #ifndef IS_SALAMANDER diff --git a/general.h b/general.h index 1585c55cf1..76eac149a7 100644 --- a/general.h +++ b/general.h @@ -217,6 +217,10 @@ struct settings { char driver[32]; struct retro_keybind binds[MAX_PLAYERS][RARCH_BIND_LIST_END]; + + // Set by autoconfiguration in joypad_autoconfig_dir. Does not override main binds. + struct retro_keybind autoconf_binds[MAX_PLAYERS][RARCH_BIND_LIST_END]; + float axis_threshold; int joypad_map[MAX_PLAYERS]; unsigned device[MAX_PLAYERS]; @@ -236,6 +240,8 @@ struct settings char overlay[PATH_MAX]; float overlay_opacity; + + char autoconfig_dir[PATH_MAX]; } input; char core_options_path[PATH_MAX]; diff --git a/input/dinput.c b/input/dinput.c index fd997a575f..f30e12862b 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -189,7 +189,7 @@ static bool dinput_is_pressed(struct dinput_input *di, const struct retro_keybin return false; const struct retro_keybind *bind = &binds[id]; - return dinput_keyboard_pressed(di, bind->key) || input_joypad_pressed(di->joypad, port, bind); + return dinput_keyboard_pressed(di, bind->key) || input_joypad_pressed(di->joypad, port, binds, id); } static bool dinput_key_pressed(void *data, int key) diff --git a/input/input_common.c b/input/input_common.c index 8cd9ecdef1..4cb3a5b327 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -37,6 +37,8 @@ #include #endif +#include "../file.h" + static const rarch_joypad_driver_t *joypad_drivers[] = { #ifndef IS_RETROLAUNCH #ifdef HAVE_DINPUT @@ -95,7 +97,7 @@ const char *input_joypad_name(const rarch_joypad_driver_t *driver, unsigned joyp } bool input_joypad_pressed(const rarch_joypad_driver_t *driver, - unsigned port, const struct retro_keybind *key) + unsigned port, const struct retro_keybind *binds, unsigned key) { if (!driver) return false; @@ -104,13 +106,24 @@ bool input_joypad_pressed(const rarch_joypad_driver_t *driver, if (joy_index < 0 || joy_index >= MAX_PLAYERS) return false; - if (!key->valid) + // Auto-binds are per joypad, not per player. + const struct retro_keybind *auto_binds = g_settings.input.autoconf_binds[joy_index]; + + if (!binds[key].valid) return false; - if (driver->button(joy_index, (uint16_t)key->joykey)) + uint64_t joykey = binds[key].joykey; + if (joykey == NO_BTN) + joykey = auto_binds[key].joykey; + + if (driver->button(joy_index, (uint16_t)joykey)) return true; - int16_t axis = driver->axis(joy_index, key->joyaxis); + uint32_t joyaxis = binds[key].joyaxis; + if (joyaxis == AXIS_NONE) + joyaxis = auto_binds[key].joyaxis; + + int16_t axis = driver->axis(joy_index, joyaxis); float scaled_axis = (float)abs(axis) / 0x8000; return scaled_axis > g_settings.input.axis_threshold; } @@ -122,9 +135,12 @@ int16_t input_joypad_analog(const rarch_joypad_driver_t *driver, return 0; int joy_index = g_settings.input.joypad_map[port]; - if (joy_index < 0) + if (joy_index < 0 || joy_index >= MAX_PLAYERS) return 0; + // Auto-binds are per joypad, not per player. + const struct retro_keybind *auto_binds = g_settings.input.autoconf_binds[joy_index]; + unsigned id_minus = 0; unsigned id_plus = 0; input_conv_analog_id_to_bind_id(index, id, &id_minus, &id_plus); @@ -134,16 +150,30 @@ int16_t input_joypad_analog(const rarch_joypad_driver_t *driver, if (!bind_minus->valid || !bind_plus->valid) return 0; - int16_t pressed_minus = abs(driver->axis(joy_index, bind_minus->joyaxis)); - int16_t pressed_plus = abs(driver->axis(joy_index, bind_plus->joyaxis)); + uint32_t axis_minus = bind_minus->joyaxis; + uint32_t axis_plus = bind_plus->joyaxis; + if (axis_minus == AXIS_NONE) + axis_minus = auto_binds[id_minus].joyaxis; + if (axis_plus == AXIS_NONE) + axis_plus = auto_binds[id_plus].joyaxis; + + int16_t pressed_minus = abs(driver->axis(joy_index, axis_minus)); + int16_t pressed_plus = abs(driver->axis(joy_index, axis_plus)); int16_t res = pressed_plus - pressed_minus; if (res != 0) return res; - int16_t digital_left = driver->button(joy_index, (uint16_t)bind_minus->joykey) ? -0x7fff : 0; - int16_t digital_right = driver->button(joy_index, (uint16_t)bind_plus->joykey) ? 0x7fff : 0; + uint64_t key_minus = bind_minus->joykey; + uint64_t key_plus = bind_plus->joykey; + if (key_minus == NO_BTN) + key_minus = auto_binds[id_minus].joykey; + if (key_plus == NO_BTN) + key_plus = auto_binds[id_plus].joykey; + + int16_t digital_left = driver->button(joy_index, (uint16_t)key_minus) ? -0x7fff : 0; + int16_t digital_right = driver->button(joy_index, (uint16_t)key_plus) ? 0x7fff : 0; return digital_right + digital_left; } @@ -764,3 +794,69 @@ void input_config_parse_joy_axis(config_file_t *conf, const char *prefix, } } +#if !defined(IS_JOYCONFIG) && !defined(IS_RETROLAUNCH) +static void input_autoconfigure_joypad_conf(config_file_t *conf, struct retro_keybind *binds) +{ + for (unsigned i = 0; i < RARCH_BIND_LIST_END; i++) + { + input_config_parse_joy_button(conf, "input", input_config_bind_map[i].base, &binds[i]); + input_config_parse_joy_axis(conf, "input", input_config_bind_map[i].base, &binds[i]); + } +} + +void input_config_autoconfigure_joypad(unsigned index, const char *name, const char *driver) +{ + if (!g_settings.input.autodetect_enable) + return; + + for (unsigned i = 0; i < RARCH_BIND_LIST_END; i++) + { + g_settings.input.autoconf_binds[index][i].joykey = NO_BTN; + g_settings.input.autoconf_binds[index][i].joyaxis = AXIS_NONE; + } + + if (!name) + return; + + if (!*g_settings.input.autoconfig_dir) + return; + + struct string_list *list = dir_list_new(g_settings.input.autoconfig_dir, "cfg", false); + if (!list) + return; + + char ident[1024]; + char input_driver[1024]; + for (size_t i = 0; i < list->size; i++) + { + *ident = *input_driver = '\0'; + + config_file_t *conf = config_file_new(list->elems[i].data); + if (!conf) + continue; + + config_get_array(conf, "input_device", ident, sizeof(ident)); + config_get_array(conf, "input_driver", input_driver, sizeof(input_driver)); + + if (!strcmp(ident, name) && !strcmp(driver, input_driver)) + { + input_autoconfigure_joypad_conf(conf, g_settings.input.autoconf_binds[index]); + + char msg[512]; + snprintf(msg, sizeof(msg), "Joypad port #%u (%s) configured.", + index, name); + + msg_queue_push(g_extern.msg_queue, msg, 0, 60); + RARCH_LOG("%s\n", msg); + + config_file_free(conf); + break; + } + else + config_file_free(conf); + } + + string_list_free(list); +} +#endif + diff --git a/input/input_common.h b/input/input_common.h index 64c5083d7c..4061be10bc 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -75,7 +75,7 @@ const rarch_joypad_driver_t *input_joypad_find_driver(const char *ident); const rarch_joypad_driver_t *input_joypad_init_first(void); bool input_joypad_pressed(const rarch_joypad_driver_t *driver, - unsigned port, const struct retro_keybind *key); + unsigned port, const struct retro_keybind *binds, unsigned key); int16_t input_joypad_analog(const rarch_joypad_driver_t *driver, unsigned port, unsigned index, unsigned id, const struct retro_keybind *binds); @@ -136,5 +136,7 @@ void input_config_parse_joy_button(config_file_t *conf, const char *prefix, void input_config_parse_joy_axis(config_file_t *conf, const char *prefix, const char *axis, struct retro_keybind *bind); +void input_config_autoconfigure_joypad(unsigned index, const char *name, const char *driver); + #endif diff --git a/input/linuxraw_input.c b/input/linuxraw_input.c index 9ba370213d..bf1d764a0b 100644 --- a/input/linuxraw_input.c +++ b/input/linuxraw_input.c @@ -253,7 +253,7 @@ static bool linuxraw_bind_button_pressed(void *data, int key) { linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; return linuxraw_is_pressed(linuxraw, g_settings.input.binds[0], key) || - input_joypad_pressed(linuxraw->joypad, 0, &g_settings.input.binds[0][key]); + input_joypad_pressed(linuxraw->joypad, 0, g_settings.input.binds[0], key); } static int16_t linuxraw_input_state(void *data, const struct retro_keybind **binds, unsigned port, unsigned device, unsigned index, unsigned id) @@ -264,7 +264,7 @@ static int16_t linuxraw_input_state(void *data, const struct retro_keybind **bin { case RETRO_DEVICE_JOYPAD: return linuxraw_is_pressed(linuxraw, binds[port], id) || - input_joypad_pressed(linuxraw->joypad, port, &binds[port][id]); + input_joypad_pressed(linuxraw->joypad, port, binds[port], id); case RETRO_DEVICE_ANALOG: return input_joypad_analog(linuxraw->joypad, port, index, id, binds[port]); diff --git a/input/linuxraw_joypad.c b/input/linuxraw_joypad.c index 983bc75ba0..33c64083a9 100644 --- a/input/linuxraw_joypad.c +++ b/input/linuxraw_joypad.c @@ -94,6 +94,8 @@ static void linuxraw_joypad_init_pad(const char *path, struct linuxraw_joypad *p snprintf(msg, sizeof(msg), "Joypad #%u (%s) connected.", (unsigned)(pad - g_pads), pad->ident); msg_queue_push(g_extern.msg_queue, msg, 0, 60); } + + input_config_autoconfigure_joypad(pad - g_pads, pad->ident, "linuxraw"); #endif } @@ -151,6 +153,10 @@ static void handle_plugged_pad(void) memset(g_pads[index].axes, 0, sizeof(g_pads[index].axes)); g_pads[index].fd = -1; *g_pads[index].ident = '\0'; + +#ifndef IS_JOYCONFIG + input_config_autoconfigure_joypad(index, NULL, NULL); +#endif } } // Sometimes, device will be created before acess to it is established. @@ -159,6 +165,11 @@ static void handle_plugged_pad(void) char path[PATH_MAX]; snprintf(path, sizeof(path), "/dev/input/%s", event->name); linuxraw_joypad_init_pad(path, &g_pads[index]); + +#ifndef IS_JOYCONFIG + if (*g_pads[index].ident) + input_config_autoconfigure_joypad(index, g_pads[index].ident, "linuxraw"); +#endif } } } diff --git a/input/sdl_input.c b/input/sdl_input.c index e15ae5be2d..7941ace247 100644 --- a/input/sdl_input.c +++ b/input/sdl_input.c @@ -59,22 +59,19 @@ static bool sdl_key_pressed(int key) return keymap[sym]; } -static bool sdl_is_pressed(sdl_input_t *sdl, unsigned port_num, const struct retro_keybind *key) +static bool sdl_is_pressed(sdl_input_t *sdl, unsigned port_num, const struct retro_keybind *binds, unsigned key) { - if (sdl_key_pressed(key->key)) + if (sdl_key_pressed(binds[key].key)) return true; - return input_joypad_pressed(sdl->joypad, port_num, key); + return input_joypad_pressed(sdl->joypad, port_num, binds, key); } static bool sdl_bind_button_pressed(void *data, int key) { const struct retro_keybind *binds = g_settings.input.binds[0]; if (key >= 0 && key < RARCH_BIND_LIST_END) - { - const struct retro_keybind *bind = &binds[key]; - return sdl_is_pressed((sdl_input_t*)data, 0, bind); - } + return sdl_is_pressed((sdl_input_t*)data, 0, binds, key); else return false; } @@ -84,10 +81,7 @@ static int16_t sdl_joypad_device_state(sdl_input_t *sdl, const struct retro_keyb { const struct retro_keybind *binds = binds_[port_num]; if (id < RARCH_BIND_LIST_END) - { - const struct retro_keybind *bind = &binds[id]; - return bind->valid && sdl_is_pressed(sdl, port_num, bind); - } + return binds[id].valid && sdl_is_pressed(sdl, port_num, binds, id); else return 0; } diff --git a/input/x11_input.c b/input/x11_input.c index 26e252d717..a9ad4a36e7 100644 --- a/input/x11_input.c +++ b/input/x11_input.c @@ -89,7 +89,7 @@ static bool x_bind_button_pressed(void *data, int key) { x11_input_t *x11 = (x11_input_t*)data; return x_is_pressed(x11, g_settings.input.binds[0], key) || - input_joypad_pressed(x11->joypad, 0, &g_settings.input.binds[0][key]); + input_joypad_pressed(x11->joypad, 0, g_settings.input.binds[0], key); } static int16_t x_mouse_state(x11_input_t *x11, unsigned id) @@ -176,7 +176,7 @@ static int16_t x_input_state(void *data, const struct retro_keybind **binds, uns { case RETRO_DEVICE_JOYPAD: return x_is_pressed(x11, binds[port], id) || - input_joypad_pressed(x11->joypad, port, &binds[port][id]); + input_joypad_pressed(x11->joypad, port, binds[port], id); case RETRO_DEVICE_KEYBOARD: return x_key_pressed(x11, id); diff --git a/ios/RetroArch/input/ios_input.c b/ios/RetroArch/input/ios_input.c index aba13ce1de..ae2a6cdf05 100644 --- a/ios/RetroArch/input/ios_input.c +++ b/ios/RetroArch/input/ios_input.c @@ -65,9 +65,9 @@ static bool ios_key_pressed(enum retro_key key) return false; } -static bool ios_is_pressed(unsigned port_num, const struct retro_keybind *key) +static bool ios_is_pressed(unsigned port_num, const struct retro_keybind *binds, unsigned key) { - return ios_key_pressed(key->key) || input_joypad_pressed(g_joydriver, port_num, key); + return ios_key_pressed(binds[key].key) || input_joypad_pressed(g_joydriver, port_num, binds, key); } // Exported input driver @@ -107,7 +107,7 @@ static int16_t ios_input_state(void *data, const struct retro_keybind **binds, u switch (device) { case RETRO_DEVICE_JOYPAD: - return (id < RARCH_BIND_LIST_END) ? ios_is_pressed(port, &binds[port][id]) : false; + return (id < RARCH_BIND_LIST_END) ? ios_is_pressed(port, binds[port], id) : false; case RETRO_DEVICE_ANALOG: return input_joypad_analog(g_joydriver, port, index, id, binds[port]); @@ -143,7 +143,7 @@ static int16_t ios_input_state(void *data, const struct retro_keybind **binds, u static bool ios_bind_button_pressed(void *data, int key) { const struct retro_keybind *binds = g_settings.input.binds[0]; - return (key >= 0 && key < RARCH_BIND_LIST_END) ? ios_is_pressed(0, &binds[key]) : false; + return (key >= 0 && key < RARCH_BIND_LIST_END) ? ios_is_pressed(0, binds, key) : false; } static void ios_input_free_input(void *data) diff --git a/retroarch.cfg b/retroarch.cfg index 36c4c7f54a..40f527d563 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -187,10 +187,18 @@ # Path to input overlay # input_overlay = -# Enable input auto-detection (used on Android). Will attempt to autoconfigure -# gamepads, Plug-and-Play style. +# Enable input auto-detection. Will attempt to autoconfigure +# joypads, Plug-and-Play style. # input_autodetect_enable = true +# Directory for joypad autoconfigs (PC). +# If a joypad is plugged in, that joypad will be autoconfigured if a config file +# corresponding to that joypad is present in joypad_autoconfig_dir. +# Input binds which are made explicit (input_playerN_*_btn/axis) will take priority over autoconfigs. +# Autoconfigs can be created with retroarch-joyconfig, manually, or with a frontend. +# Requires input_autodetect_enable to be enabled. +# joypad_autoconfig_dir = + # Enable debug input key reporting on-screen. # input_debug_enable = false @@ -227,13 +235,13 @@ # input_player1_r_y_plus = # input_player1_r_y_minus = -# If desired, it is possible to override which joypads are being used for player 1 through 5. First joypad available is 0. +# If desired, it is possible to override which joypads are being used for player 1 through 8. +# First joypad available is 0. # input_player1_joypad_index = 0 # input_player2_joypad_index = 1 # input_player3_joypad_index = 2 # input_player4_joypad_index = 3 # input_player5_joypad_index = 4 -# Player 6-8 is not directly expected by libretro API, but we'll futureproof it. # input_player6_joypad_index = 5 # input_player7_joypad_index = 6 # input_player8_joypad_index = 7 diff --git a/settings.c b/settings.c index 0c2912e40b..5a1cd5a8d9 100644 --- a/settings.c +++ b/settings.c @@ -222,6 +222,8 @@ void config_set_defaults(void) for (unsigned i = 1; i < MAX_PLAYERS; i++) memcpy(g_settings.input.binds[i], retro_keybinds_rest, sizeof(retro_keybinds_rest)); + memcpy(g_settings.input.autoconf_binds, g_settings.input.binds, sizeof(g_settings.input.binds)); + // Verify that binds are in proper order. for (int i = 0; i < MAX_PLAYERS; i++) for (int j = 0; j < RARCH_BIND_LIST_END; j++) @@ -234,8 +236,8 @@ void config_set_defaults(void) g_settings.input.turbo_duty_cycle = turbo_duty_cycle; g_settings.input.overlay_opacity = 1.0f; g_settings.input.debug_enable = input_debug_enable; -#ifdef ANDROID g_settings.input.autodetect_enable = input_autodetect_enable; +#ifdef ANDROID g_settings.input.back_behavior = BACK_BUTTON_QUIT; #endif @@ -651,8 +653,10 @@ bool config_load_file(const char *path) CONFIG_GET_FLOAT(input.overlay_opacity, "input_overlay_opacity"); CONFIG_GET_BOOL(input.debug_enable, "input_debug_enable"); -#ifdef ANDROID CONFIG_GET_BOOL(input.autodetect_enable, "input_autodetect_enable"); + CONFIG_GET_PATH(input.autoconfig_dir, "joypad_autoconfig_dir"); + +#ifdef ANDROID CONFIG_GET_INT(input.back_behavior, "input_back_behavior"); CONFIG_GET_INT(input.icade_profile[0], "input_autodetect_icade_profile_pad1"); CONFIG_GET_INT(input.icade_profile[1], "input_autodetect_icade_profile_pad2"); From f06f6e544ec56cb5d741c7ded5b41ef48d898b3d Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 15:02:18 +0200 Subject: [PATCH 08/10] Don't spam OSD messages for autoconfigure. --- general.h | 1 + input/input_common.c | 9 ++++++++- input/linuxraw_joypad.c | 15 +++++++++------ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/general.h b/general.h index 76eac149a7..82aac61198 100644 --- a/general.h +++ b/general.h @@ -220,6 +220,7 @@ struct settings // Set by autoconfiguration in joypad_autoconfig_dir. Does not override main binds. struct retro_keybind autoconf_binds[MAX_PLAYERS][RARCH_BIND_LIST_END]; + bool autoconfigured[MAX_PLAYERS]; float axis_threshold; int joypad_map[MAX_PLAYERS]; diff --git a/input/input_common.c b/input/input_common.c index 4cb3a5b327..1b060e6819 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -809,11 +809,16 @@ void input_config_autoconfigure_joypad(unsigned index, const char *name, const c if (!g_settings.input.autodetect_enable) return; + // This will be the case if input driver is reinit. No reason to spam autoconfigure messages + // every time (fine in log). + bool block_osd_spam = g_settings.input.autoconfigured[index] && name; + for (unsigned i = 0; i < RARCH_BIND_LIST_END; i++) { g_settings.input.autoconf_binds[index][i].joykey = NO_BTN; g_settings.input.autoconf_binds[index][i].joyaxis = AXIS_NONE; } + g_settings.input.autoconfigured[index] = false; if (!name) return; @@ -840,13 +845,15 @@ void input_config_autoconfigure_joypad(unsigned index, const char *name, const c if (!strcmp(ident, name) && !strcmp(driver, input_driver)) { + g_settings.input.autoconfigured[index] = true; input_autoconfigure_joypad_conf(conf, g_settings.input.autoconf_binds[index]); char msg[512]; snprintf(msg, sizeof(msg), "Joypad port #%u (%s) configured.", index, name); - msg_queue_push(g_extern.msg_queue, msg, 0, 60); + if (!block_osd_spam) + msg_queue_push(g_extern.msg_queue, msg, 0, 60); RARCH_LOG("%s\n", msg); config_file_free(conf); diff --git a/input/linuxraw_joypad.c b/input/linuxraw_joypad.c index 33c64083a9..6144340f64 100644 --- a/input/linuxraw_joypad.c +++ b/input/linuxraw_joypad.c @@ -68,15 +68,15 @@ static void poll_pad(struct linuxraw_joypad *pad) } } -static void linuxraw_joypad_init_pad(const char *path, struct linuxraw_joypad *pad) +static bool linuxraw_joypad_init_pad(const char *path, struct linuxraw_joypad *pad) { if (pad->fd >= 0) - return; + return false; // Device can have just been created, but not made accessible (yet). // IN_ATTRIB will signal when permissions change. if (access(path, R_OK) < 0) - return; + return false; pad->fd = open(path, O_RDONLY | O_NONBLOCK); @@ -106,9 +106,13 @@ static void linuxraw_joypad_init_pad(const char *path, struct linuxraw_joypad *p event.events = EPOLLIN; event.data.ptr = pad; epoll_ctl(g_epoll, EPOLL_CTL_ADD, pad->fd, &event); + return true; } else + { RARCH_ERR("[Joypad]: Failed to open pad %s (error: %s).\n", path, strerror(errno)); + return false; + } } static void handle_plugged_pad(void) @@ -164,10 +168,10 @@ static void handle_plugged_pad(void) { char path[PATH_MAX]; snprintf(path, sizeof(path), "/dev/input/%s", event->name); - linuxraw_joypad_init_pad(path, &g_pads[index]); + bool ret = linuxraw_joypad_init_pad(path, &g_pads[index]); #ifndef IS_JOYCONFIG - if (*g_pads[index].ident) + if (*g_pads[index].ident && ret) input_config_autoconfigure_joypad(index, g_pads[index].ident, "linuxraw"); #endif } @@ -220,7 +224,6 @@ static bool linuxraw_joypad_init(void) linuxraw_joypad_init_pad(path, pad); if (pad->fd >= 0) poll_pad(pad); - } g_notify = inotify_init(); From 40d8a42886e3366adf64f3a4a997bcbf386a7bce Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 15:08:18 +0200 Subject: [PATCH 09/10] De-autoconfig lost drivers on reinit. --- input/linuxraw_joypad.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/input/linuxraw_joypad.c b/input/linuxraw_joypad.c index 6144340f64..68700706ac 100644 --- a/input/linuxraw_joypad.c +++ b/input/linuxraw_joypad.c @@ -94,8 +94,6 @@ static bool linuxraw_joypad_init_pad(const char *path, struct linuxraw_joypad *p snprintf(msg, sizeof(msg), "Joypad #%u (%s) connected.", (unsigned)(pad - g_pads), pad->ident); msg_queue_push(g_extern.msg_queue, msg, 0, 60); } - - input_config_autoconfigure_joypad(pad - g_pads, pad->ident, "linuxraw"); #endif } @@ -221,9 +219,17 @@ static bool linuxraw_joypad_init(void) char path[PATH_MAX]; snprintf(path, sizeof(path), "/dev/input/js%u", i); - linuxraw_joypad_init_pad(path, pad); - if (pad->fd >= 0) + if (linuxraw_joypad_init_pad(path, pad)) + { +#ifndef IS_JOYCONFIG + input_config_autoconfigure_joypad(i, pad->ident, "linuxraw"); +#endif poll_pad(pad); + } +#ifndef IS_JOYCONFIG + else + input_config_autoconfigure_joypad(i, NULL, NULL); +#endif } g_notify = inotify_init(); From 34170974844244be1034baacd3639481f776b563 Mon Sep 17 00:00:00 2001 From: Themaister Date: Fri, 26 Apr 2013 15:10:52 +0200 Subject: [PATCH 10/10] Fix Win32 build. --- Makefile.win | 6 +++++- input/dinput.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile.win b/Makefile.win index 61f096c903..35a3e76472 100644 --- a/Makefile.win +++ b/Makefile.win @@ -42,7 +42,7 @@ JOBJ := conf/config_file.o \ tools/retroarch-joyconfig.o \ compat/compat.o \ file_path.o \ - input/input_common.o \ + tools/input_common_joyconfig.o \ input/dinput.o CC = gcc @@ -254,6 +254,10 @@ $(TARGET): $(OBJ) @$(if $(Q), $(shell echo echo CC $<),) $(Q)$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< +tools/input_common_joyconfig.o: input/input_common.c + @$(if $(Q), $(shell echo echo CC $<),) + $(Q)$(CC) $(CFLAGS) $(DEFINES) -DIS_JOYCONFIG -c -o $@ $< + %.o: %.cpp @$(if $(Q), $(shell echo echo CXX $<),) $(Q)$(CXX) $(CXXFLAGS) $(DEFINES) -c -o $@ $< diff --git a/input/dinput.c b/input/dinput.c index f30e12862b..8865395e23 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -557,7 +557,7 @@ static bool dinput_joypad_query_pad(unsigned pad) static const char *dinput_joypad_name(unsigned pad) { - (unsigned)pad; + (void)pad; // FIXME return NULL; }