diff --git a/config.def.h b/config.def.h index 70a91ebea1..54eb968b6a 100644 --- a/config.def.h +++ b/config.def.h @@ -565,7 +565,6 @@ static const struct retro_keybind retro_keybinds_1[] = { { true, RETRO_DEVICE_ID_JOYPAD_L3, RETRO_LBL_JOYPAD_L3, RETROK_UNKNOWN, RETRO_DEF_JOYPAD_L3, 0, AXIS_NONE }, { true, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_LBL_JOYPAD_R3, RETROK_UNKNOWN, RETRO_DEF_JOYPAD_R3, 0, AXIS_NONE }, - { true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_ANALOG_LEFT_X_PLUS, RETRO_LBL_ANALOG_LEFT_X_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_ANALOG_LEFT_X_MINUS, RETRO_LBL_ANALOG_LEFT_X_MINUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_ANALOG_LEFT_Y_PLUS, RETRO_LBL_ANALOG_LEFT_Y_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, @@ -585,6 +584,7 @@ static const struct retro_keybind retro_keybinds_1[] = { { true, RARCH_ANALOG_RIGHT_Y_DPAD_DOWN, RETRO_LBL_ANALOG_RIGHT_Y_DPAD_D,RETROK_UNKNOWN, RETRO_DEF_ANALOGR_DPAD_DOWN, 0, AXIS_NONE }, #endif + { true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_FAST_FORWARD_KEY, RETRO_LBL_FAST_FORWARD_KEY, RETROK_SPACE, NO_BTN, 0, AXIS_NONE }, { true, RARCH_FAST_FORWARD_HOLD_KEY, RETRO_LBL_FAST_FORWARD_HOLD_KEY,RETROK_l, NO_BTN, 0, AXIS_NONE }, { true, RARCH_LOAD_STATE_KEY, RETRO_LBL_LOAD_STATE_KEY, RETROK_F4, NO_BTN, 0, AXIS_NONE }, @@ -640,7 +640,6 @@ static const struct retro_keybind retro_keybinds_rest[] = { { true, RETRO_DEVICE_ID_JOYPAD_L3, RETRO_LBL_JOYPAD_L3, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_LBL_JOYPAD_R3, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, - { true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_ANALOG_LEFT_X_PLUS, RETRO_LBL_ANALOG_LEFT_X_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_ANALOG_LEFT_X_MINUS, RETRO_LBL_ANALOG_LEFT_X_MINUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_ANALOG_LEFT_Y_PLUS, RETRO_LBL_ANALOG_LEFT_Y_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, @@ -659,6 +658,7 @@ static const struct retro_keybind retro_keybinds_rest[] = { { true, RARCH_ANALOG_RIGHT_Y_DPAD_UP, RETRO_LBL_ANALOG_RIGHT_Y_DPAD_U,RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, { true, RARCH_ANALOG_RIGHT_Y_DPAD_DOWN, RETRO_LBL_ANALOG_RIGHT_Y_DPAD_D,RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, #endif + { true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE }, }; #endif diff --git a/driver.h b/driver.h index 2472946c62..f025fb3bc7 100644 --- a/driver.h +++ b/driver.h @@ -56,11 +56,8 @@ extern "C" { enum // RetroArch specific bind IDs. { // Custom binds that extend the scope of RETRO_DEVICE_JOYPAD for RetroArch specifically. - // Turbo - RARCH_TURBO_ENABLE = RARCH_FIRST_CUSTOM_BIND, - // Analogs (RETRO_DEVICE_ANALOG) - RARCH_ANALOG_LEFT_X_PLUS, + RARCH_ANALOG_LEFT_X_PLUS = RARCH_FIRST_CUSTOM_BIND, RARCH_ANALOG_LEFT_X_MINUS, RARCH_ANALOG_LEFT_Y_PLUS, RARCH_ANALOG_LEFT_Y_MINUS, @@ -69,6 +66,7 @@ enum // RetroArch specific bind IDs. RARCH_ANALOG_RIGHT_Y_PLUS, RARCH_ANALOG_RIGHT_Y_MINUS, #ifdef RARCH_CONSOLE + // D-pad emulation RARCH_ANALOG_LEFT_X_DPAD_LEFT, RARCH_ANALOG_LEFT_X_DPAD_RIGHT, RARCH_ANALOG_LEFT_Y_DPAD_UP, @@ -79,6 +77,9 @@ enum // RetroArch specific bind IDs. RARCH_ANALOG_RIGHT_Y_DPAD_DOWN, #endif + // Turbo + RARCH_TURBO_ENABLE, + RARCH_CUSTOM_BIND_LIST_END, // Command binds. Not related to game input, only usable for port 0. @@ -323,6 +324,8 @@ enum keybind_set_id KEYBINDS_ACTION_LAST }; +typedef struct rarch_joypad_driver rarch_joypad_driver_t; + typedef struct input_driver { void *(*init)(void); @@ -336,6 +339,7 @@ typedef struct input_driver void (*grab_mouse)(void *data, bool state); bool (*set_rumble)(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t state); + const rarch_joypad_driver_t *(*get_joypad_driver)(void *data); } input_driver_t; struct rarch_viewport; diff --git a/frontend/frontend.c b/frontend/frontend.c index c65796a18c..799a0eca6b 100644 --- a/frontend/frontend.c +++ b/frontend/frontend.c @@ -215,6 +215,12 @@ int main_entry(int argc, char *argv[]) driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0); } + // Override keyboard callback to redirect to menu instead. + // We'll use this later for something ... + // FIXME: This should probably be moved to menu_common somehow. + retro_keyboard_event_t key_event = g_extern.system.key_event; + g_extern.system.key_event = menu_key_event; + if (driver.audio_data) audio_stop_func(); @@ -236,6 +242,9 @@ int main_entry(int argc, char *argv[]) } g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU); + + // Restore libretro keyboard callback. + g_extern.system.key_event = key_event; } else break; diff --git a/frontend/menu/menu_common.c b/frontend/menu/menu_common.c index 42b5299af0..c5dfd931c8 100644 --- a/frontend/menu/menu_common.c +++ b/frontend/menu/menu_common.c @@ -22,8 +22,10 @@ #include "menu_common.h" #include "../../performance.h" +#include "../../driver.h" #include "../../file.h" #include "menu_context.h" +#include "../../input/input_common.h" #include "../../compat/posix_string.h" @@ -786,4 +788,135 @@ bool menu_save_new_config(void) return ret; } +void menu_poll_bind_state(struct rgui_bind_state *state) +{ + memset(state->state, 0, sizeof(state->state)); + state->skip = input_input_state_func(NULL, 0, RETRO_DEVICE_KEYBOARD, 0, RETROK_RETURN); + + const rarch_joypad_driver_t *joypad = NULL; + if (driver.input && driver.input_data && driver.input->get_joypad_driver) + joypad = driver.input->get_joypad_driver(driver.input_data); + + if (!joypad) + { + RARCH_ERR("Cannot poll raw joypad state."); + return; + } + + input_joypad_poll(joypad); + for (unsigned p = 0; p < MAX_PLAYERS; p++) + { + for (unsigned b = 0; b < RGUI_MAX_BUTTONS; b++) + state->state[p].buttons[b] = input_joypad_button_raw(joypad, p, b); + for (unsigned a = 0; a < RGUI_MAX_AXES; a++) + state->state[p].axes[a] = input_joypad_axis_raw(joypad, p, a); + for (unsigned h = 0; h < RGUI_MAX_HATS; h++) + { + state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_UP_MASK, h) ? HAT_UP_MASK : 0; + state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_DOWN_MASK, h) ? HAT_DOWN_MASK : 0; + state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_LEFT_MASK, h) ? HAT_LEFT_MASK : 0; + state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_RIGHT_MASK, h) ? HAT_RIGHT_MASK : 0; + } + } +} + +void menu_poll_bind_get_rested_axes(struct rgui_bind_state *state) +{ + const rarch_joypad_driver_t *joypad = NULL; + if (driver.input && driver.input_data && driver.input->get_joypad_driver) + joypad = driver.input->get_joypad_driver(driver.input_data); + + if (!joypad) + { + RARCH_ERR("Cannot poll raw joypad state."); + return; + } + + for (unsigned p = 0; p < MAX_PLAYERS; p++) + for (unsigned a = 0; a < RGUI_MAX_AXES; a++) + state->axis_state[p].rested_axes[a] = input_joypad_axis_raw(joypad, p, a); +} + +static bool menu_poll_find_trigger_pad(struct rgui_bind_state *state, struct rgui_bind_state *new_state, unsigned p) +{ + const struct rgui_bind_state_port *n = &new_state->state[p]; + const struct rgui_bind_state_port *o = &state->state[p]; + + for (unsigned b = 0; b < RGUI_MAX_BUTTONS; b++) + { + if (n->buttons[b] && !o->buttons[b]) + { + state->target->joykey = b; + state->target->joyaxis = AXIS_NONE; + return true; + } + } + + // Axes are a bit tricky ... + for (unsigned a = 0; a < RGUI_MAX_AXES; a++) + { + int locked_distance = abs(n->axes[a] - new_state->axis_state[p].locked_axes[a]); + int rested_distance = abs(n->axes[a] - new_state->axis_state[p].rested_axes[a]); + + if (abs(n->axes[a]) >= 20000 && + locked_distance >= 20000 && + rested_distance >= 20000) // Take care of case where axis rests on +/- 0x7fff (e.g. 360 controller on Linux) + { + state->target->joyaxis = n->axes[a] > 0 ? AXIS_POS(a) : AXIS_NEG(a); + state->target->joykey = NO_BTN; + + // Lock the current axis. + new_state->axis_state[p].locked_axes[a] = n->axes[a] > 0 ? 0x7fff : -0x7fff; + return true; + } + + if (locked_distance >= 20000) // Unlock the axis. + new_state->axis_state[p].locked_axes[a] = 0; + } + + for (unsigned h = 0; h < RGUI_MAX_HATS; h++) + { + uint16_t trigged = n->hats[h] & (~o->hats[h]); + uint16_t sane_trigger = 0; + if (trigged & HAT_UP_MASK) + sane_trigger = HAT_UP_MASK; + else if (trigged & HAT_DOWN_MASK) + sane_trigger = HAT_DOWN_MASK; + else if (trigged & HAT_LEFT_MASK) + sane_trigger = HAT_LEFT_MASK; + else if (trigged & HAT_RIGHT_MASK) + sane_trigger = HAT_RIGHT_MASK; + + if (sane_trigger) + { + state->target->joykey = HAT_MAP(h, sane_trigger); + state->target->joyaxis = AXIS_NONE; + return true; + } + } + + return false; +} + +bool menu_poll_find_trigger(struct rgui_bind_state *state, struct rgui_bind_state *new_state) +{ + for (unsigned p = 0; p < MAX_PLAYERS; p++) + { + if (menu_poll_find_trigger_pad(state, new_state, p)) + { + g_settings.input.joypad_map[state->player] = p; // Update the joypad mapping automatically. More friendly that way. + return true; + } + } + return false; +} + +void menu_key_event(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers) +{ + // TODO: Do something with this. Stub for now. + (void)down; + (void)keycode; + (void)character; + (void)key_modifiers; +} diff --git a/frontend/menu/menu_common.h b/frontend/menu/menu_common.h index c2fb9b1080..9c2bbd47b2 100644 --- a/frontend/menu/menu_common.h +++ b/frontend/menu/menu_common.h @@ -147,22 +147,38 @@ typedef enum RGUI_SETTINGS_BIND_DEVICE, RGUI_SETTINGS_BIND_DEVICE_TYPE, RGUI_SETTINGS_BIND_DPAD_EMULATION, + + // Match up with libretro order for simplicity. + RGUI_SETTINGS_BIND_BEGIN, + RGUI_SETTINGS_BIND_B = RGUI_SETTINGS_BIND_BEGIN, + RGUI_SETTINGS_BIND_Y, + RGUI_SETTINGS_BIND_SELECT, + RGUI_SETTINGS_BIND_START, RGUI_SETTINGS_BIND_UP, RGUI_SETTINGS_BIND_DOWN, RGUI_SETTINGS_BIND_LEFT, RGUI_SETTINGS_BIND_RIGHT, RGUI_SETTINGS_BIND_A, - RGUI_SETTINGS_BIND_B, RGUI_SETTINGS_BIND_X, - RGUI_SETTINGS_BIND_Y, - RGUI_SETTINGS_BIND_START, - RGUI_SETTINGS_BIND_SELECT, RGUI_SETTINGS_BIND_L, RGUI_SETTINGS_BIND_R, RGUI_SETTINGS_BIND_L2, RGUI_SETTINGS_BIND_R2, RGUI_SETTINGS_BIND_L3, RGUI_SETTINGS_BIND_R3, + RGUI_SETTINGS_BIND_ANALOG_LEFT_X_PLUS, + RGUI_SETTINGS_BIND_ANALOG_LEFT_X_MINUS, + RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_PLUS, + RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_MINUS, + RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_PLUS, + RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_MINUS, + RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_PLUS, + RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS, + RGUI_SETTINGS_BIND_LAST = RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS, + RGUI_SETTINGS_BIND_MENU_TOGGLE = RGUI_SETTINGS_BIND_BEGIN + RARCH_MENU_TOGGLE, + RGUI_SETTINGS_CUSTOM_BIND, + RGUI_SETTINGS_CUSTOM_BIND_ALL, + RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL, RGUI_SETTINGS_CORE_OPTION_NONE = 0xffff, RGUI_SETTINGS_CORE_OPTION_START = 0x10000 @@ -186,6 +202,38 @@ typedef enum RGUI_ACTION_NOOP } rgui_action_t; +#define RGUI_MAX_BUTTONS 32 +#define RGUI_MAX_AXES 32 +#define RGUI_MAX_HATS 4 +struct rgui_bind_state_port +{ + bool buttons[RGUI_MAX_BUTTONS]; + int16_t axes[RGUI_MAX_AXES]; + uint16_t hats[RGUI_MAX_HATS]; +}; + +struct rgui_bind_axis_state +{ + // Default axis state. + int16_t rested_axes[RGUI_MAX_AXES]; + // Locked axis state. If we configured an axis, avoid having the same axis state trigger something again right away. + int16_t locked_axes[RGUI_MAX_AXES]; +}; + +struct rgui_bind_state +{ + struct retro_keybind *target; + unsigned begin; + unsigned last; + unsigned player; + struct rgui_bind_state_port state[MAX_PLAYERS]; + struct rgui_bind_axis_state axis_state[MAX_PLAYERS]; + bool skip; +}; + +void menu_poll_bind_get_rested_axes(struct rgui_bind_state *state); +void menu_poll_bind_state(struct rgui_bind_state *state); +bool menu_poll_find_trigger(struct rgui_bind_state *state, struct rgui_bind_state *new_state); #ifdef GEKKO enum @@ -264,6 +312,8 @@ typedef struct rom_history_t *history; rarch_time_t last_time; // Used to throttle RGUI in case VSync is broken. + + struct rgui_bind_state binds; } rgui_handle_t; extern rgui_handle_t *rgui; @@ -303,7 +353,8 @@ bool menu_replace_config(const char *path); bool menu_save_new_config(void); int menu_set_settings(unsigned setting, unsigned action); -extern const unsigned rgui_controller_lut[]; + +void menu_key_event(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); #ifdef __cplusplus } diff --git a/frontend/menu/menu_settings.c b/frontend/menu/menu_settings.c index e09c2f1142..4ba5c26e0e 100644 --- a/frontend/menu/menu_settings.c +++ b/frontend/menu/menu_settings.c @@ -26,25 +26,6 @@ #define MAX_GAMMA_SETTING 1 #endif -const unsigned rgui_controller_lut[] = { - RETRO_DEVICE_ID_JOYPAD_UP, - RETRO_DEVICE_ID_JOYPAD_DOWN, - RETRO_DEVICE_ID_JOYPAD_LEFT, - RETRO_DEVICE_ID_JOYPAD_RIGHT, - RETRO_DEVICE_ID_JOYPAD_A, - RETRO_DEVICE_ID_JOYPAD_B, - RETRO_DEVICE_ID_JOYPAD_X, - RETRO_DEVICE_ID_JOYPAD_Y, - RETRO_DEVICE_ID_JOYPAD_START, - RETRO_DEVICE_ID_JOYPAD_SELECT, - RETRO_DEVICE_ID_JOYPAD_L, - RETRO_DEVICE_ID_JOYPAD_R, - RETRO_DEVICE_ID_JOYPAD_L2, - RETRO_DEVICE_ID_JOYPAD_R2, - RETRO_DEVICE_ID_JOYPAD_L3, - RETRO_DEVICE_ID_JOYPAD_R3, -}; - #ifdef HAVE_SHADER_MANAGER static enum rarch_shader_type shader_manager_get_type(const struct gfx_shader *shader) { @@ -486,6 +467,30 @@ int menu_set_settings(unsigned setting, unsigned action) keybind_action); } break; + case RGUI_SETTINGS_CUSTOM_BIND_ALL: + if (action == RGUI_ACTION_OK) + { + rgui->binds.target = &g_settings.input.binds[port][0]; + rgui->binds.begin = RGUI_SETTINGS_BIND_BEGIN; + rgui->binds.last = RGUI_SETTINGS_BIND_LAST; + rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_BIND, rgui->selection_ptr); + menu_poll_bind_get_rested_axes(&rgui->binds); + menu_poll_bind_state(&rgui->binds); + } + break; + case RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL: + if (action == RGUI_ACTION_OK) + { + struct retro_keybind *target = &g_settings.input.binds[port][0]; + rgui->binds.begin = RGUI_SETTINGS_BIND_BEGIN; + rgui->binds.last = RGUI_SETTINGS_BIND_LAST; + for (unsigned i = RGUI_SETTINGS_BIND_BEGIN; i <= RGUI_SETTINGS_BIND_LAST; i++, target++) + { + target->joykey = NO_BTN; + target->joyaxis = AXIS_NONE; + } + } + break; case RGUI_SETTINGS_BIND_UP: case RGUI_SETTINGS_BIND_DOWN: case RGUI_SETTINGS_BIND_LEFT: @@ -502,6 +507,15 @@ int menu_set_settings(unsigned setting, unsigned action) case RGUI_SETTINGS_BIND_R2: case RGUI_SETTINGS_BIND_L3: case RGUI_SETTINGS_BIND_R3: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_MINUS: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_MINUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_MINUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS: + case RGUI_SETTINGS_BIND_MENU_TOGGLE: if (driver.input->set_keybinds) { unsigned keybind_action = KEYBINDS_ACTION_NONE; @@ -513,10 +527,31 @@ int menu_set_settings(unsigned setting, unsigned action) else if (action == RGUI_ACTION_RIGHT) keybind_action = (1ULL << KEYBINDS_ACTION_INCREMENT_BIND); + // FIXME: The array indices here look totally wrong ... Fixed it so it looks kind of sane for now. if (keybind_action != KEYBINDS_ACTION_NONE) - driver.input->set_keybinds(driver.input_data, g_settings.input.device[setting - RGUI_SETTINGS_BIND_UP], port, - rgui_controller_lut[setting - RGUI_SETTINGS_BIND_UP], keybind_action); + driver.input->set_keybinds(driver.input_data, g_settings.input.device[port], port, + setting - RGUI_SETTINGS_BIND_BEGIN, keybind_action); } + else + { + struct retro_keybind *bind = &g_settings.input.binds[port][setting - RGUI_SETTINGS_BIND_BEGIN]; + if (action == RGUI_ACTION_OK) + { + rgui->binds.begin = setting; + rgui->binds.last = setting; + rgui->binds.target = bind; + rgui->binds.player = port; + rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_BIND, rgui->selection_ptr); + menu_poll_bind_get_rested_axes(&rgui->binds); + menu_poll_bind_state(&rgui->binds); + } + else if (action == RGUI_ACTION_START) + { + bind->joykey = NO_BTN; + bind->joyaxis = AXIS_NONE; + } + } + break; case RGUI_BROWSER_DIR_PATH: if (action == RGUI_ACTION_START) { diff --git a/frontend/menu/rgui.c b/frontend/menu/rgui.c index f63be960c1..fe62fea1a5 100644 --- a/frontend/menu/rgui.c +++ b/frontend/menu/rgui.c @@ -33,6 +33,7 @@ #include "../../compat/posix_string.h" #include "../../gfx/shader_parse.h" #include "../../performance.h" +#include "../../input/input_common.h" #ifdef HAVE_OPENGL #include "../../gfx/gl_common.h" @@ -527,25 +528,49 @@ static void rgui_settings_controller_populate_entries(rgui_handle_t *rgui) rgui_list_push(rgui->selection_buf, "Device Type", RGUI_SETTINGS_BIND_DEVICE_TYPE, 0); if (driver.input && driver.input->set_keybinds) - { rgui_list_push(rgui->selection_buf, "DPad Emulation", RGUI_SETTINGS_BIND_DPAD_EMULATION, 0); - rgui_list_push(rgui->selection_buf, "Up", RGUI_SETTINGS_BIND_UP, 0); - rgui_list_push(rgui->selection_buf, "Down", RGUI_SETTINGS_BIND_DOWN, 0); - rgui_list_push(rgui->selection_buf, "Left", RGUI_SETTINGS_BIND_LEFT, 0); - rgui_list_push(rgui->selection_buf, "Right", RGUI_SETTINGS_BIND_RIGHT, 0); - rgui_list_push(rgui->selection_buf, "A", RGUI_SETTINGS_BIND_A, 0); - rgui_list_push(rgui->selection_buf, "B", RGUI_SETTINGS_BIND_B, 0); - rgui_list_push(rgui->selection_buf, "X", RGUI_SETTINGS_BIND_X, 0); - rgui_list_push(rgui->selection_buf, "Y", RGUI_SETTINGS_BIND_Y, 0); - rgui_list_push(rgui->selection_buf, "Start", RGUI_SETTINGS_BIND_START, 0); - rgui_list_push(rgui->selection_buf, "Select", RGUI_SETTINGS_BIND_SELECT, 0); - rgui_list_push(rgui->selection_buf, "L", RGUI_SETTINGS_BIND_L, 0); - rgui_list_push(rgui->selection_buf, "R", RGUI_SETTINGS_BIND_R, 0); - rgui_list_push(rgui->selection_buf, "L2", RGUI_SETTINGS_BIND_L2, 0); - rgui_list_push(rgui->selection_buf, "R2", RGUI_SETTINGS_BIND_R2, 0); - rgui_list_push(rgui->selection_buf, "L3", RGUI_SETTINGS_BIND_L3, 0); - rgui_list_push(rgui->selection_buf, "R3", RGUI_SETTINGS_BIND_R3, 0); + else + { + rgui_list_push(rgui->selection_buf, "Configure All (RetroPad)", RGUI_SETTINGS_CUSTOM_BIND_ALL, 0); // This doesn't make sense on anything else than PC. + rgui_list_push(rgui->selection_buf, "Default All (RetroPad)", RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL, 0); // This doesn't make sense on anything else than PC. } + + if (rgui->current_pad == 0) + rgui_list_push(rgui->selection_buf, "RGUI Menu Toggle", RGUI_SETTINGS_BIND_MENU_TOGGLE, 0); + unsigned last = (driver.input && driver.input->set_keybinds) ? RGUI_SETTINGS_BIND_R3 : RGUI_SETTINGS_BIND_LAST; + for (unsigned i = RGUI_SETTINGS_BIND_BEGIN; i <= last; i++) + rgui_list_push(rgui->selection_buf, input_config_bind_map[i - RGUI_SETTINGS_BIND_BEGIN].desc, i, 0); +} + +// This only makes sense for PC so far. +// Consoles use set_keybind callbacks instead. +static int rgui_custom_bind_iterate(rgui_handle_t *rgui, rgui_action_t action) +{ + (void)action; // Have to ignore action here. Only bind that should work here is Quit RetroArch or something like that. + + render_text(rgui); + + char msg[256]; + snprintf(msg, sizeof(msg), "[%s]\npress joypad\n(RETURN to skip)", input_config_bind_map[rgui->binds.begin - RGUI_SETTINGS_BIND_BEGIN].desc); + render_messagebox(rgui, msg); + + struct rgui_bind_state binds = rgui->binds; + menu_poll_bind_state(&binds); + + if ((binds.skip && !rgui->binds.skip) || menu_poll_find_trigger(&rgui->binds, &binds)) + { + binds.begin++; + if (binds.begin <= binds.last) + binds.target++; + else + rgui_list_pop(rgui->menu_stack, &rgui->selection_ptr); + + // Avoid new binds triggering things right away. + rgui->trigger_state = 0; + rgui->old_input_state = -1ULL; + } + rgui->binds = binds; + return 0; } static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) @@ -1032,6 +1057,8 @@ static int rgui_iterate(void *data, unsigned action) return rgui_settings_iterate(rgui, action); else if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT || menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2) return rgui_viewport_iterate(rgui, action); + else if (menu_type == RGUI_SETTINGS_CUSTOM_BIND) + return rgui_custom_bind_iterate(rgui, action); if (rgui->need_refresh && action != RGUI_ACTION_MESSAGE) action = RGUI_ACTION_NOOP; diff --git a/frontend/menu/rguidisp_bitmap.c b/frontend/menu/rguidisp_bitmap.c index 30b994cc04..1a26173a96 100644 --- a/frontend/menu/rguidisp_bitmap.c +++ b/frontend/menu/rguidisp_bitmap.c @@ -145,17 +145,36 @@ static void render_messagebox(rgui_handle_t *rgui, const char *message) if (!message || !*message) return; - char *msg = strdup(message); - if (strlen(msg) > TERM_WIDTH) + struct string_list *list = string_split(message, "\n"); + if (!list) + return; + if (list->elems == 0) { - msg[TERM_WIDTH - 2] = '.'; - msg[TERM_WIDTH - 1] = '.'; - msg[TERM_WIDTH - 0] = '.'; - msg[TERM_WIDTH + 1] = '\0'; + string_list_free(list); + return; } - unsigned width = strlen(msg) * FONT_WIDTH_STRIDE - 1 + 6 + 10; - unsigned height = FONT_HEIGHT + 6 + 10; + unsigned width = 0; + unsigned glyphs_width = 0; + for (size_t i = 0; i < list->size; i++) + { + char *msg = list->elems[i].data; + unsigned msglen = strlen(msg); + if (msglen > TERM_WIDTH) + { + msg[TERM_WIDTH - 2] = '.'; + msg[TERM_WIDTH - 1] = '.'; + msg[TERM_WIDTH - 0] = '.'; + msg[TERM_WIDTH + 1] = '\0'; + msglen = TERM_WIDTH; + } + + unsigned line_width = msglen * FONT_WIDTH_STRIDE - 1 + 6 + 10; + width = max(width, line_width); + glyphs_width = max(glyphs_width, msglen); + } + + unsigned height = FONT_HEIGHT_STRIDE * list->size + 6 + 10; int x = (RGUI_WIDTH - width) / 2; int y = (RGUI_HEIGHT - height) / 2; @@ -174,8 +193,15 @@ static void render_messagebox(rgui_handle_t *rgui, const char *message) fill_rect(rgui->frame_buf, rgui->frame_buf_pitch, x, y + 5, 5, height - 5, green_filler); - blit_line(rgui, x + 8, y + 8, msg, false); - free(msg); + for (size_t i = 0; i < list->size; i++) + { + const char *msg = list->elems[i].data; + int offset_x = FONT_WIDTH_STRIDE * (glyphs_width - strlen(msg)) / 2; + int offset_y = FONT_HEIGHT_STRIDE * i; + blit_line(rgui, x + 8 + offset_x, y + 8 + offset_y, msg, false); + } + + string_list_free(list); } static void render_text(rgui_handle_t *rgui) @@ -230,6 +256,7 @@ static void render_text(rgui_handle_t *rgui) (menu_type == RGUI_SETTINGS_PATH_OPTIONS) || (menu_type == RGUI_SETTINGS_OPTIONS) || (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT || menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2) || + menu_type == RGUI_SETTINGS_CUSTOM_BIND || menu_type == RGUI_SETTINGS) snprintf(title, sizeof(title), "MENU %s", dir); else if (menu_type == RGUI_SETTINGS_OPEN_HISTORY) @@ -303,7 +330,13 @@ static void render_text(rgui_handle_t *rgui) rgui_list_get_at_offset(rgui->selection_buf, i, &path, &type); char message[256]; char type_str[256]; - unsigned w = (menu_type == RGUI_SETTINGS_INPUT_OPTIONS || menu_type == RGUI_SETTINGS_PATH_OPTIONS) ? 24 : 19; + + unsigned w = 19; + if (menu_type == RGUI_SETTINGS_INPUT_OPTIONS || menu_type == RGUI_SETTINGS_CUSTOM_BIND) + w = 21; + else if (menu_type == RGUI_SETTINGS_PATH_OPTIONS) + w = 24; + unsigned port = rgui->current_pad; #ifdef HAVE_SHADER_MANAGER @@ -533,6 +566,8 @@ static void render_text(rgui_handle_t *rgui) case RGUI_SETTINGS_INPUT_OPTIONS: case RGUI_SETTINGS_PATH_OPTIONS: case RGUI_SETTINGS_OPTIONS: + case RGUI_SETTINGS_CUSTOM_BIND_ALL: + case RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL: strlcpy(type_str, "...", sizeof(type_str)); break; #ifdef HAVE_OVERLAY @@ -624,18 +659,33 @@ static void render_text(rgui_handle_t *rgui) case RGUI_SETTINGS_BIND_R2: case RGUI_SETTINGS_BIND_L3: case RGUI_SETTINGS_BIND_R3: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_MINUS: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_MINUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_MINUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_PLUS: + case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS: + case RGUI_SETTINGS_BIND_MENU_TOGGLE: + { + unsigned id = type - RGUI_SETTINGS_BIND_B; + struct platform_bind key_label; + strlcpy(key_label.desc, "Unknown", sizeof(key_label.desc)); + key_label.joykey = g_settings.input.binds[port][id].joykey; + + if (driver.input->set_keybinds) { - unsigned id = rgui_controller_lut[type - RGUI_SETTINGS_BIND_UP]; - struct platform_bind key_label; - strlcpy(key_label.desc, "Unknown", sizeof(key_label.desc)); - key_label.joykey = g_settings.input.binds[port][id].joykey; - - if (driver.input->set_keybinds) - driver.input->set_keybinds(&key_label, 0, 0, 0, (1ULL << KEYBINDS_ACTION_GET_BIND_LABEL)); - + driver.input->set_keybinds(&key_label, 0, 0, 0, (1ULL << KEYBINDS_ACTION_GET_BIND_LABEL)); strlcpy(type_str, key_label.desc, sizeof(type_str)); } + else + { + const struct retro_keybind *bind = &g_settings.input.binds[port][type - RGUI_SETTINGS_BIND_BEGIN]; + input_get_bind_string(type_str, bind, sizeof(type_str)); + } break; + } default: type_str[0] = 0; w = 0; @@ -679,3 +729,4 @@ static void render_text(rgui_handle_t *rgui) render_messagebox(rgui, message_queue); #endif } + diff --git a/input/autoconf/builtin_win.c b/input/autoconf/builtin_win.c index d28e9de1df..ba1a4e0da5 100644 --- a/input/autoconf/builtin_win.c +++ b/input/autoconf/builtin_win.c @@ -61,32 +61,6 @@ const char* const input_builtin_autoconfs[] = "input_driver = \"winxinput\" \n" XINPUT_DEFAULT_BINDS, - "input_device = \"Dual Trigger 3-in-1\" \n" - "input_driver = \"dinput\" \n" - DECL_BTN(a, 2) - DECL_BTN(b, 1) - DECL_BTN(x, 3) - DECL_BTN(y, 0) - DECL_BTN(start, 9) - DECL_BTN(select, 8) - DECL_BTN(up, h0up) - DECL_BTN(down, h0down) - DECL_BTN(left, h0left) - DECL_BTN(right, h0right) - DECL_BTN(l, 4) - DECL_BTN(r, 5) - DECL_BTN(l2, 6) - DECL_BTN(r2, 7) - DECL_BTN(l3, 10) - DECL_BTN(r3, 11) - DECL_AXIS(l_x_plus, +0) - DECL_AXIS(l_x_minus, -0) - DECL_AXIS(l_y_plus, +1) - DECL_AXIS(l_y_minus, -1) - DECL_AXIS(r_x_plus, +2) - DECL_AXIS(r_x_minus, -2) - DECL_AXIS(r_y_plus, +5) - DECL_AXIS(r_y_minus, -5), - NULL }; + diff --git a/input/dinput.c b/input/dinput.c index ac70e2d64d..e8f5674be2 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -340,6 +340,12 @@ static bool dinput_set_rumble(void *data, unsigned port, enum retro_rumble_effec return input_joypad_set_rumble(di->joypad, port, effect, strength); } +static const rarch_joypad_driver_t *dinput_get_joypad_driver(void *data) +{ + struct dinput_input *di = (struct dinput_input*)data; + return di->joypad; +} + const input_driver_t input_dinput = { dinput_init, dinput_poll, @@ -351,6 +357,7 @@ const input_driver_t input_dinput = { dinput_grab_mouse, dinput_set_rumble, + dinput_get_joypad_driver, }; // Keep track of which pad indexes are 360 controllers diff --git a/input/input_common.c b/input/input_common.c index c938b68128..f0c7e2ae1e 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -642,6 +642,29 @@ enum retro_key input_translate_keysym_to_rk(unsigned sym) return RETROK_UNKNOWN; } +void input_translate_rk_to_str(enum retro_key key, char *buf, size_t size) +{ + rarch_assert(size >= 2); + *buf = '\0'; + + if (key >= RETROK_a && key <= RETROK_z) + { + buf[0] = (key - RETROK_a) + 'a'; + buf[1] = '\0'; + } + else + { + for (unsigned i = 0; input_config_key_map[i].str; i++) + { + if (input_config_key_map[i].key == key) + { + strlcpy(buf, input_config_key_map[i].str, size); + break; + } + } + } +} + unsigned input_translate_rk_to_keysym(enum retro_key key) { return rarch_keysym_lut[key]; @@ -672,13 +695,12 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { 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, RETRO_DEVICE_ID_JOYPAD_L, "L button (shoulder)"), + DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R, "R button (shoulder)"), + DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2, "L2 button (trigger)"), + DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2, "R2 button (trigger)"), + DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3, "L3 button (thumb)"), + DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3, "R3 button (thumb)"), 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)"), @@ -688,6 +710,20 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { 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)"), + // FIXME: Unsure what to do here. + // The D-pad emulation concept really needs a rethink ... +#ifdef RARCH_CONSOLE + DECLARE_BIND(dpad_l_x_l, RARCH_ANALOG_LEFT_X_DPAD_LEFT, "Left analog D-pad left"), + DECLARE_BIND(dpad_l_x_r, RARCH_ANALOG_LEFT_X_DPAD_RIGHT, "Left analog D-pad right"), + DECLARE_BIND(dpad_l_y_u, RARCH_ANALOG_LEFT_Y_DPAD_UP, "Left analog D-pad up"), + DECLARE_BIND(dpad_l_y_d, RARCH_ANALOG_LEFT_Y_DPAD_DOWN, "Left analog D-pad down"), + DECLARE_BIND(dpad_r_x_l, RARCH_ANALOG_RIGHT_X_DPAD_LEFT, "Right analog D-pad left"), + DECLARE_BIND(dpad_r_x_r, RARCH_ANALOG_RIGHT_X_DPAD_RIGHT, "Right analog D-pad right"), + DECLARE_BIND(dpad_r_y_u, RARCH_ANALOG_RIGHT_Y_DPAD_UP, "Right analog D-pad up"), + DECLARE_BIND(dpad_r_y_d, RARCH_ANALOG_RIGHT_Y_DPAD_DOWN, "Right analog D-pad down"), +#endif + DECLARE_BIND(turbo, RARCH_TURBO_ENABLE, "Turbo enable"), + DECLARE_META_BIND(1, toggle_fast_forward, RARCH_FAST_FORWARD_KEY, "Fast forward toggle"), DECLARE_META_BIND(2, hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY, "Fast forward hold"), DECLARE_META_BIND(1, load_state, RARCH_LOAD_STATE_KEY, "Load state"), @@ -794,6 +830,54 @@ const struct input_key_map input_config_key_map[] = { { NULL, RETROK_UNKNOWN }, }; +void input_get_bind_string(char *buf, const struct retro_keybind *bind, size_t size) +{ + *buf = '\0'; + if (bind->joykey != NO_BTN) + { + if (GET_HAT_DIR(bind->joykey)) + { + const char *dir; + switch (GET_HAT_DIR(bind->joykey)) + { + case HAT_UP_MASK: dir = "up"; break; + case HAT_DOWN_MASK: dir = "down"; break; + case HAT_LEFT_MASK: dir = "left"; break; + case HAT_RIGHT_MASK: dir = "right"; break; + default: dir = "?"; break; + } + snprintf(buf, size, "Hat #%u %s ", (unsigned)GET_HAT(bind->joykey), dir); + } + else + snprintf(buf, size, "%u (btn) ", (unsigned)bind->joykey); + } + else if (bind->joyaxis != AXIS_NONE) + { + unsigned axis = 0; + char dir = '\0'; + if (AXIS_NEG_GET(bind->joyaxis) != AXIS_DIR_NONE) + { + dir = '-'; + axis = AXIS_NEG_GET(bind->joyaxis); + } + else if (AXIS_POS_GET(bind->joyaxis) != AXIS_DIR_NONE) + { + dir = '+'; + axis = AXIS_POS_GET(bind->joyaxis); + } + snprintf(buf, size, "%c%u (axis) ", dir, axis); + } + + char key[64]; + input_translate_rk_to_str(bind->key, key, sizeof(key)); + if (!strcmp(key, "nul")) + *key = '\0'; + + char keybuf[64]; + snprintf(keybuf, sizeof(keybuf), "(Key: %s)", key); + strlcat(buf, keybuf, size); +} + static enum retro_key find_sk_bind(const char *str) { for (size_t i = 0; input_config_key_map[i].str; i++) diff --git a/input/input_common.h b/input/input_common.h index 704ce42306..9f2afd2a17 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -132,14 +132,18 @@ struct input_bind_map const char *desc; unsigned retro_key; }; + extern const struct input_bind_map input_config_bind_map[]; +void input_get_bind_string(char *buf, const struct retro_keybind *bind, size_t size); + struct input_key_map { const char *str; enum retro_key key; }; extern const struct input_key_map input_config_key_map[]; +void input_translate_rk_to_str(enum retro_key key, char *buf, size_t size); extern const char* const input_builtin_autoconfs[]; diff --git a/input/linuxraw_input.c b/input/linuxraw_input.c index 5467ccc68d..507f46e20d 100644 --- a/input/linuxraw_input.c +++ b/input/linuxraw_input.c @@ -291,6 +291,12 @@ static bool linuxraw_set_rumble(void *data, unsigned port, enum retro_rumble_eff return input_joypad_set_rumble(linuxraw->joypad, port, effect, strength); } +static const rarch_joypad_driver_t *linuxraw_get_joypad_driver(void *data) +{ + linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; + return linuxraw->joypad; +} + static void linuxraw_input_poll(void *data) { linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; @@ -325,4 +331,5 @@ const input_driver_t input_linuxraw = { "linuxraw", NULL, linuxraw_set_rumble, + linuxraw_get_joypad_driver, }; diff --git a/input/sdl_input.c b/input/sdl_input.c index 64e40b05aa..9b1262938d 100644 --- a/input/sdl_input.c +++ b/input/sdl_input.c @@ -220,6 +220,12 @@ static bool sdl_set_rumble(void *data, unsigned port, enum retro_rumble_effect e return input_joypad_set_rumble(sdl->joypad, port, effect, strength); } +static const rarch_joypad_driver_t *sdl_get_joypad_driver(void *data) +{ + sdl_input_t *sdl = (sdl_input_t*)data; + return sdl->joypad; +} + static void sdl_poll_mouse(sdl_input_t *sdl) { Uint8 btn = SDL_GetRelativeMouseState(&sdl->mouse_x, &sdl->mouse_y); @@ -248,5 +254,6 @@ const input_driver_t input_sdl = { "sdl", NULL, sdl_set_rumble, + sdl_get_joypad_driver, }; diff --git a/input/x11_input.c b/input/x11_input.c index 1783698d42..76c9c19f34 100644 --- a/input/x11_input.c +++ b/input/x11_input.c @@ -275,6 +275,12 @@ static bool x_set_rumble(void *data, unsigned port, enum retro_rumble_effect eff return input_joypad_set_rumble(x11->joypad, port, effect, strength); } +static const rarch_joypad_driver_t *x_get_joypad_driver(void *data) +{ + x11_input_t *x11 = (x11_input_t*)data; + return x11->joypad; +} + const input_driver_t input_x = { x_input_init, x_input_poll, @@ -285,5 +291,6 @@ const input_driver_t input_x = { "x", x_grab_mouse, x_set_rumble, + x_get_joypad_driver, }; diff --git a/settings.c b/settings.c index deebaf7f8f..b4af25ab4c 100644 --- a/settings.c +++ b/settings.c @@ -879,23 +879,8 @@ static void save_keybind_key(config_file_t *conf, const char *prefix, const char char key[64]; snprintf(key, sizeof(key), "%s_%s", prefix, base); - char ascii[2] = {0}; - const char *btn = ascii; - - if (bind->key >= RETROK_a && bind->key <= RETROK_z) - ascii[0] = 'a' + (bind->key - RETROK_a); - else - { - for (unsigned i = 0; input_config_key_map[i].str; i++) - { - if (input_config_key_map[i].key == bind->key) - { - btn = input_config_key_map[i].str; - break; - } - } - } - + char btn[64]; + input_translate_rk_to_str(bind->key, btn, sizeof(btn)); config_set_string(conf, key, btn); } @@ -1119,11 +1104,15 @@ bool config_save_file(const char *path) config_set_int(conf, cfg, g_settings.input.libretro_device[i]); } + for (unsigned i = 0; i < MAX_PLAYERS; i++) + save_keybinds_player(conf, i); + bool ret = config_file_write(conf, path); config_file_free(conf); return ret; } +// FIXME: This is probably obsolete now. bool config_save_keybinds(const char *path) { config_file_t *conf = config_file_new(path); @@ -1179,7 +1168,7 @@ void settings_set(uint64_t settings) } if (settings & (1ULL << S_DEF_INPUT_OVERLAY_SCALE)) - g_settings.input.overlay_opacity = 1.0f; + g_settings.input.overlay_scale = 1.0f; #endif if (settings & (1ULL << S_REWIND_GRANULARITY_INCREMENT))