diff --git a/.gitignore b/.gitignore index 996bbf24375..edf85f05ed0 100644 --- a/.gitignore +++ b/.gitignore @@ -57,7 +57,6 @@ xcuserdata profile *.moved-aside DerivedData -.idea/ *.hmap apple/tmp apple/*.mobileprovision @@ -249,3 +248,4 @@ param.sfo # Visual Studio Code .vscode/ +/.gdbinit diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000000..13566b81b01 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/fileColors.xml b/.idea/fileColors.xml new file mode 100644 index 00000000000..42fef831cf9 --- /dev/null +++ b/.idea/fileColors.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000000..8d66637cb9f --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000000..2e8a9ca1aa4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/scopes/Dependencies.xml b/.idea/scopes/Dependencies.xml new file mode 100644 index 00000000000..b457b64c18e --- /dev/null +++ b/.idea/scopes/Dependencies.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000000..35eb1ddfbbc --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/config.def.keybinds.h b/config.def.keybinds.h index d86c8b6413e..0ed94fde2f3 100644 --- a/config.def.keybinds.h +++ b/config.def.keybinds.h @@ -18,6 +18,36 @@ #ifndef __CONFIG_DEF_KEYBINDS_H #define __CONFIG_DEF_KEYBINDS_H +#define JOYPAD_LOGICAL_ENTRY(index) {\ + NULL, NULL,\ + AXIS_NONE, AXIS_NONE, AXIS_NONE,\ + MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LOGICAL, RETROK_UNKNOWN,\ + RARCH_EXTRA_CORE_COMMAND_START + (index), NO_BTN, NO_BTN, 0,\ + true\ + } +#define JOYPAD_LOGICAL_ENTRY_TEN(base) \ + JOYPAD_LOGICAL_ENTRY(base), \ + JOYPAD_LOGICAL_ENTRY(base + 1), \ + JOYPAD_LOGICAL_ENTRY(base + 2), \ + JOYPAD_LOGICAL_ENTRY(base + 3), \ + JOYPAD_LOGICAL_ENTRY(base + 4), \ + JOYPAD_LOGICAL_ENTRY(base + 5), \ + JOYPAD_LOGICAL_ENTRY(base + 6), \ + JOYPAD_LOGICAL_ENTRY(base + 7), \ + JOYPAD_LOGICAL_ENTRY(base + 8), \ + JOYPAD_LOGICAL_ENTRY(base + 9) +#define JOYPAD_LOGICAL_ENTRY_HUNDRED(base) \ + JOYPAD_LOGICAL_ENTRY_TEN(base), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 10), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 20), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 30), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 40), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 50), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 60), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 70), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 80), \ + JOYPAD_LOGICAL_ENTRY_TEN(base + 90) + #ifndef IS_SALAMANDER /* User 1 */ @@ -1927,6 +1957,20 @@ static const struct retro_keybind retro_keybinds_1[] = { RARCH_OSK, NO_BTN, NO_BTN, 0, true }, + + /* 128 Logical extra joypad buttons. */ + JOYPAD_LOGICAL_ENTRY_HUNDRED(0), + JOYPAD_LOGICAL_ENTRY_TEN(100), + JOYPAD_LOGICAL_ENTRY_TEN(110), + JOYPAD_LOGICAL_ENTRY(120), + JOYPAD_LOGICAL_ENTRY(121), + JOYPAD_LOGICAL_ENTRY(122), + JOYPAD_LOGICAL_ENTRY(123), + JOYPAD_LOGICAL_ENTRY(124), + JOYPAD_LOGICAL_ENTRY(125), + JOYPAD_LOGICAL_ENTRY(126), + JOYPAD_LOGICAL_ENTRY(127), + #if 0 /* Deprecated */ { @@ -2194,6 +2238,27 @@ static const struct retro_keybind retro_keybinds_rest[] = { RARCH_TURBO_ENABLE, NO_BTN, NO_BTN, 0, true }, + + { + NULL, NULL, + AXIS_NONE, AXIS_NONE, AXIS_NONE, + MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LOGICAL, RETROK_UNKNOWN, + RARCH_EXTRA_CORE_COMMAND_START, NO_BTN, NO_BTN, 0, + true + }, + + /* 128 Logical extra joypad buttons. */ + JOYPAD_LOGICAL_ENTRY_HUNDRED(0), + JOYPAD_LOGICAL_ENTRY_TEN(100), + JOYPAD_LOGICAL_ENTRY_TEN(110), + JOYPAD_LOGICAL_ENTRY(120), + JOYPAD_LOGICAL_ENTRY(121), + JOYPAD_LOGICAL_ENTRY(122), + JOYPAD_LOGICAL_ENTRY(123), + JOYPAD_LOGICAL_ENTRY(124), + JOYPAD_LOGICAL_ENTRY(125), + JOYPAD_LOGICAL_ENTRY(126), + JOYPAD_LOGICAL_ENTRY(127), }; #endif diff --git a/configuration.c b/configuration.c index 4bdaa69509f..d1bc1c6e318 100644 --- a/configuration.c +++ b/configuration.c @@ -282,6 +282,26 @@ enum midi_driver_enum #define DECLARE_BIND(base, bind, desc) { #base, desc, 0, bind, true } #define DECLARE_META_BIND(level, base, bind, desc) { #base, desc, level, bind, true } +#define DECLARE_EXTRA_BIND_PASTE2(a, b) a##b +#define DECLARE_EXTRA_BIND_PASTE(a, b) DECLARE_EXTRA_BIND_PASTE2(a, b) +#define DECLARE_EXTRA_BIND_STRINGY2(a) #a +#define DECLARE_EXTRA_BIND_STRINGY(a) DECLARE_EXTRA_BIND_STRINGY2(a) + +/** Declare an extra logical bind, the label used depends on the core. */ +#define DECLARE_EXTRA_BIND(id) {DECLARE_EXTRA_BIND_STRINGY(DECLARE_EXTRA_BIND_PASTE(log, id)), MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LOGICAL, 0, id, true } + +/** Declare ten binds. */ +#define DECLARE_EXTRA_BIND_10(dig) \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 0)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 1)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 2)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 3)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 4)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 5)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 6)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 7)), \ + DECLARE_EXTRA_BIND(DECLARE_EXTRA_BIND_PASTE(dig, 9)) + const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B), DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_Y), @@ -394,12 +414,50 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { DECLARE_META_BIND(2, overlay_next, RARCH_OVERLAY_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_OVERLAY_NEXT), DECLARE_META_BIND(2, osk_toggle, RARCH_OSK, MENU_ENUM_LABEL_VALUE_INPUT_META_OSK), + + /* Extra keys, all of them. */ + DECLARE_EXTRA_BIND(0), + DECLARE_EXTRA_BIND(1), + DECLARE_EXTRA_BIND(2), + DECLARE_EXTRA_BIND(3), + DECLARE_EXTRA_BIND(4), + DECLARE_EXTRA_BIND(5), + DECLARE_EXTRA_BIND(6), + DECLARE_EXTRA_BIND(7), + DECLARE_EXTRA_BIND(8), + DECLARE_EXTRA_BIND(9), + DECLARE_EXTRA_BIND_10(1), + DECLARE_EXTRA_BIND_10(2), + DECLARE_EXTRA_BIND_10(3), + DECLARE_EXTRA_BIND_10(4), + DECLARE_EXTRA_BIND_10(5), + DECLARE_EXTRA_BIND_10(6), + DECLARE_EXTRA_BIND_10(7), + DECLARE_EXTRA_BIND_10(8), + DECLARE_EXTRA_BIND_10(9), + DECLARE_EXTRA_BIND_10(10), + DECLARE_EXTRA_BIND_10(11), + DECLARE_EXTRA_BIND(120), + DECLARE_EXTRA_BIND(121), + DECLARE_EXTRA_BIND(122), + DECLARE_EXTRA_BIND(123), + DECLARE_EXTRA_BIND(124), + DECLARE_EXTRA_BIND(125), + DECLARE_EXTRA_BIND(126), + DECLARE_EXTRA_BIND(127), + #if 0 /* Deprecated */ DECLARE_META_BIND(2, send_debug_info, RARCH_SEND_DEBUG_INFO, MENU_ENUM_LABEL_VALUE_INPUT_META_SEND_DEBUG_INFO), #endif }; +#undef DECLARE_EXTRA_BIND_PASTE2 +#undef DECLARE_EXTRA_BIND_PASTE +#undef DECLARE_EXTRA_BIND_STRINGY2 +#undef DECLARE_EXTRA_BIND_STRINGY +#undef DECLARE_EXTRA_BIND_10 + #if defined(HAVE_METAL) #if defined(HAVE_VULKAN) /* Default to Vulkan/MoltenVK when available */ @@ -5669,6 +5727,61 @@ bool config_replace(bool config_replace_save_on_exit, char *path) return task_push_start_dummy_core(&content_info); } +/** + * Returns the key string for a given logical game controller button. + * + * @param logical The input logical button. + * @return The character string for the given key. + * @since 2023/12/24 + */ +static const char* rarch_input_get_key_string(rarch_logical_bind_id logical) +{ +#define BUF_SIZE 8 + static char key_strings[rarch_num_bind_game_controller()][BUF_SIZE] = + { + "b", "y", "select", "start", + "up", "down", "left", "right", + "a", "x", "l", "r", + "l2", "r2", "l3", "r3", + "l_x+", "l_x-", "l_y+", "l_y-", + "r_x+", "r_x-", "r_y+", "r_y-", + + /* Light gun is only here because of the mixing between defines, + * This creates a difficult situation where we do not want to + * include it, but we must. */ + "loggtr", + "loggrl", + "loggaa", + "loggab", + "loggac", + "loggst", + "loggsl", + "loggdu", + "loggdd", + "loggdl", + "loggdr", + + /* Turbo as well. */ + "logtrb" + }; + + /* Not valid at all. */ + if (logical < 0 || logical >= rarch_num_bind_game_controller()) + return NULL; + + /* Is the key already filled in? */ + if (key_strings[logical][0] != 0) + return key_strings[logical]; + + /* Just use a generic logical name for the key. */ + snprintf(key_strings[logical], BUF_SIZE - 1, "log%d", logical); + key_strings[logical][BUF_SIZE - 1] = 0; + + /* It can now be used. */ + return key_strings[logical]; +#undef BUF_SIZE +} + /** * input_remapping_load_file: * @data : Path to config file. @@ -5679,15 +5792,10 @@ bool config_replace(bool config_replace_save_on_exit, char *path) **/ bool input_remapping_load_file(void *data, const char *path) { - unsigned i, j; + unsigned usernum, logical; config_file_t *conf = (config_file_t*)data; settings_t *settings = config_st; runloop_state_t *runloop_st = runloop_state_get_ptr(); - char key_strings[RARCH_FIRST_CUSTOM_BIND + 8][8] = { - "b", "y", "select", "start", - "up", "down", "left", "right", - "a", "x", "l", "r", "l2", "r2", - "l3", "r3", "l_x+", "l_x-", "l_y+", "l_y-", "r_x+", "r_x-", "r_y+", "r_y-" }; if ( !conf || string_is_empty(path)) @@ -5699,14 +5807,14 @@ bool input_remapping_load_file(void *data, const char *path) input_remapping_set_defaults(false); runloop_st->name.remapfile = strdup(path); - for (i = 0; i < MAX_USERS; i++) + for (usernum = 0; usernum < MAX_USERS; usernum++) { size_t _len; char prefix[16]; char s1[32], s2[32], s3[32]; char formatted_number[4]; formatted_number[0] = '\0'; - snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1); + snprintf(formatted_number, sizeof(formatted_number), "%u", usernum + 1); _len = strlcpy(prefix, "input_player", sizeof(prefix)); strlcpy(prefix + _len, formatted_number, sizeof(prefix) - _len); _len = strlcpy(s1, prefix, sizeof(s1)); @@ -5716,11 +5824,11 @@ bool input_remapping_load_file(void *data, const char *path) _len = strlcpy(s3, prefix, sizeof(s3)); strlcpy(s3 + _len, "_stk", sizeof(s3) - _len); - for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 8; j++) + for (logical = 0; logical < rarch_num_bind_game_controller(); logical++) { - const char *key_string = key_strings[j]; + const char *key_string = rarch_input_get_key_string(logical); - if (j < RARCH_FIRST_CUSTOM_BIND) + if (rarch_logical_bind_is_basic(logical)) { int btn_remap = -1; int key_remap = -1; @@ -5738,14 +5846,14 @@ bool input_remapping_load_file(void *data, const char *path) btn_remap = RARCH_UNMAPPED; configuration_set_uint(settings, - settings->uints.input_remap_ids[i][j], btn_remap); + settings->uints.input_remap_ids[usernum][logical], btn_remap); } if (!config_get_int(conf, key_ident, &key_remap)) key_remap = RETROK_UNKNOWN; configuration_set_uint(settings, - settings->uints.input_keymapper_ids[i][j], key_remap); + settings->uints.input_keymapper_ids[usernum][logical], key_remap); } else { @@ -5763,7 +5871,7 @@ bool input_remapping_load_file(void *data, const char *path) stk_remap = RARCH_UNMAPPED; configuration_set_uint(settings, - settings->uints.input_remap_ids[i][j], stk_remap); + settings->uints.input_remap_ids[usernum][logical], stk_remap); } fill_pathname_join_delim(key_ident, s2, @@ -5773,21 +5881,21 @@ bool input_remapping_load_file(void *data, const char *path) key_remap = RETROK_UNKNOWN; configuration_set_uint(settings, - settings->uints.input_keymapper_ids[i][j], key_remap); + settings->uints.input_keymapper_ids[usernum][logical], key_remap); } } _len = strlcpy(s1, prefix, sizeof(s1)); strlcpy(s1 + _len, "_analog_dpad_mode", sizeof(s1) - _len); - CONFIG_GET_INT_BASE(conf, settings, uints.input_analog_dpad_mode[i], s1); + CONFIG_GET_INT_BASE(conf, settings, uints.input_analog_dpad_mode[usernum], s1); _len = strlcpy(s1, "input_libretro_device_p", sizeof(s1)); strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len); - CONFIG_GET_INT_BASE(conf, settings, uints.input_libretro_device[i], s1); + CONFIG_GET_INT_BASE(conf, settings, uints.input_libretro_device[usernum], s1); _len = strlcpy(s1, "input_remap_port_p", sizeof(s1)); strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len); - CONFIG_GET_INT_BASE(conf, settings, uints.input_remap_ports[i], s1); + CONFIG_GET_INT_BASE(conf, settings, uints.input_remap_ports[usernum], s1); } input_remapping_update_port_map(); @@ -5812,17 +5920,8 @@ bool input_remapping_save_file(const char *path) { size_t _len; bool ret; - unsigned i, j; + unsigned usernum, logical; char remap_file_dir[PATH_MAX_LENGTH]; - char key_strings[RARCH_FIRST_CUSTOM_BIND + 8][8] = - { - "b", "y", "select", "start", - "up", "down", "left", "right", - "a", "x", "l", "r", - "l2", "r2", "l3", "r3", - "l_x+", "l_x-", "l_y+", "l_y-", - "r_x+", "r_x-", "r_y+", "r_y-" - }; config_file_t *conf = NULL; runloop_state_t *runloop_st = runloop_state_get_ptr(); settings_t *settings = config_st; @@ -5844,7 +5943,7 @@ bool input_remapping_save_file(const char *path) if (!(conf = config_file_new_alloc())) return false; - for (i = 0; i < MAX_USERS; i++) + for (usernum = 0; usernum < MAX_USERS; usernum++) { size_t _len; bool skip_port = true; @@ -5858,15 +5957,15 @@ bool input_remapping_save_file(const char *path) /* We must include all mapped ports + all those * with an index less than max_users */ - if (i < max_users) + if (usernum < max_users) skip_port = false; else { /* Check whether current port is mapped * to an input device */ - for (j = 0; j < max_users; j++) + for (logical = 0; logical < max_users; logical++) { - if (i == settings->uints.input_remap_ports[j]) + if (usernum == settings->uints.input_remap_ports[logical]) { skip_port = false; break; @@ -5877,7 +5976,7 @@ bool input_remapping_save_file(const char *path) if (skip_port) continue; - snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1); + snprintf(formatted_number, sizeof(formatted_number), "%u", usernum + 1); _len = strlcpy(prefix, "input_player", sizeof(prefix)); strlcpy(prefix + _len, formatted_number, sizeof(prefix) - _len); _len = strlcpy(s1, prefix, sizeof(s1)); @@ -5887,13 +5986,17 @@ bool input_remapping_save_file(const char *path) _len = strlcpy(s3, prefix, sizeof(s3)); strlcpy(s3 + _len, "_stk", sizeof(s3) - _len); - for (j = 0; j < RARCH_FIRST_CUSTOM_BIND; j++) + for (logical = 0; logical < rarch_num_bind_game_controller(); logical++) { + /* Ignore the analog/gun binds. */ + if (!rarch_logical_bind_is_basic(logical)) + continue; + char btn_ident[128]; char key_ident[128]; - const char *key_string = key_strings[j]; - unsigned remap_id = settings->uints.input_remap_ids[i][j]; - unsigned keymap_id = settings->uints.input_keymapper_ids[i][j]; + const char *key_string = rarch_input_get_key_string(logical); + unsigned remap_id = settings->uints.input_remap_ids[usernum][logical]; + unsigned keymap_id = settings->uints.input_keymapper_ids[usernum][logical]; fill_pathname_join_delim(btn_ident, s1, key_string, '_', sizeof(btn_ident)); @@ -5901,7 +6004,7 @@ bool input_remapping_save_file(const char *path) key_string, '_', sizeof(key_ident)); /* Only save modified button values */ - if (remap_id == j) + if (remap_id == logical) config_unset(conf, btn_ident); else { @@ -5909,7 +6012,7 @@ bool input_remapping_save_file(const char *path) config_set_int(conf, btn_ident, -1); else config_set_int(conf, btn_ident, - settings->uints.input_remap_ids[i][j]); + settings->uints.input_remap_ids[usernum][logical]); } /* Only save non-empty keymapper values */ @@ -5917,16 +6020,17 @@ bool input_remapping_save_file(const char *path) config_unset(conf, key_ident); else config_set_int(conf, key_ident, - settings->uints.input_keymapper_ids[i][j]); + settings->uints.input_keymapper_ids[usernum][logical]); } - for (j = RARCH_FIRST_CUSTOM_BIND; j < (RARCH_FIRST_CUSTOM_BIND + 8); j++) + /* This goes through axis and otherwise, so should keep the + 8 here. */ + for (logical = RARCH_FIRST_CUSTOM_BIND; logical < (RARCH_FIRST_CUSTOM_BIND + 8); logical++) { char stk_ident[128]; char key_ident[128]; - const char *key_string = key_strings[j]; - unsigned remap_id = settings->uints.input_remap_ids[i][j]; - unsigned keymap_id = settings->uints.input_keymapper_ids[i][j]; + const char *key_string = rarch_input_get_key_string(logical); + unsigned remap_id = settings->uints.input_remap_ids[usernum][logical]; + unsigned keymap_id = settings->uints.input_keymapper_ids[usernum][logical]; fill_pathname_join_delim(stk_ident, s3, key_string, '_', sizeof(stk_ident)); @@ -5934,7 +6038,7 @@ bool input_remapping_save_file(const char *path) key_string, '_', sizeof(key_ident)); /* Only save modified button values */ - if (remap_id == j) + if (remap_id == logical) config_unset(conf, stk_ident); else { @@ -5942,7 +6046,7 @@ bool input_remapping_save_file(const char *path) config_set_int(conf, stk_ident, -1); else config_set_int(conf, stk_ident, - settings->uints.input_remap_ids[i][j]); + settings->uints.input_remap_ids[usernum][logical]); } /* Only save non-empty keymapper values */ @@ -5950,20 +6054,20 @@ bool input_remapping_save_file(const char *path) config_unset(conf, key_ident); else config_set_int(conf, key_ident, - settings->uints.input_keymapper_ids[i][j]); + settings->uints.input_keymapper_ids[usernum][logical]); } _len = strlcpy(s1, "input_libretro_device_p", sizeof(s1)); strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len); - config_set_int(conf, s1, input_config_get_device(i)); + config_set_int(conf, s1, input_config_get_device(usernum)); _len = strlcpy(s1, prefix, sizeof(s1)); strlcpy(s1 + _len, "_analog_dpad_mode", sizeof(s1) - _len); - config_set_int(conf, s1, settings->uints.input_analog_dpad_mode[i]); + config_set_int(conf, s1, settings->uints.input_analog_dpad_mode[usernum]); _len = strlcpy(s1, "input_remap_port_p", sizeof(s1)); strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len); - config_set_int(conf, s1, settings->uints.input_remap_ports[i]); + config_set_int(conf, s1, settings->uints.input_remap_ports[usernum]); } ret = config_file_write(conf, path, true); diff --git a/configuration.h b/configuration.h index 786f1f439c8..b51b8534ab8 100644 --- a/configuration.h +++ b/configuration.h @@ -150,8 +150,8 @@ typedef struct settings unsigned input_analog_dpad_mode[MAX_USERS]; unsigned input_remap_ports[MAX_USERS]; - unsigned input_remap_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END]; - unsigned input_keymapper_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END]; + unsigned input_remap_ids[MAX_USERS][rarch_num_bind_game_controller()]; + unsigned input_keymapper_ids[MAX_USERS][rarch_num_bind_game_controller()]; unsigned input_remap_port_map[MAX_USERS][MAX_USERS + 1]; unsigned led_map[MAX_LEDS]; diff --git a/cores/libretro-net-retropad/net_retropad_core.c b/cores/libretro-net-retropad/net_retropad_core.c index bedf072ad00..e69a264e704 100644 --- a/cores/libretro-net-retropad/net_retropad_core.c +++ b/cores/libretro-net-retropad/net_retropad_core.c @@ -92,7 +92,7 @@ static struct descriptor joypad = { .index_min = 0, .index_max = 0, .id_min = RETRO_DEVICE_ID_JOYPAD_B, - .id_max = RETRO_DEVICE_ID_JOYPAD_R3 + .id_max = RETRO_DEVICE_ID_JOYPAD_MAX_BUTTONS }; static struct descriptor analog = { diff --git a/dynamic.h b/dynamic.h index 79ed70ab16d..76ac7a534e7 100644 --- a/dynamic.h +++ b/dynamic.h @@ -33,7 +33,8 @@ enum retro_core_flags RETRO_CORE_FLAG_GAME_LOADED = (1 << 2), RETRO_CORE_FLAG_INPUT_POLLED = (1 << 3), RETRO_CORE_FLAG_HAS_SET_SUBSYSTEMS = (1 << 4), - RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS = (1 << 5) + RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS = (1 << 5), + RETRO_CORE_FLAG_HAS_SET_EXTENDED_INPUT = (1 << 6), }; struct retro_core_t diff --git a/input/input_defines.h b/input/input_defines.h index bdd36fc37a1..2d343a7224f 100644 --- a/input/input_defines.h +++ b/input/input_defines.h @@ -21,6 +21,7 @@ #include #include +#include #define MAX_USERS 16 @@ -28,7 +29,18 @@ #define RARCH_MAX_KEYS 137 +/** + * When using this to check if a bind is part of a game controller use + * instead @c rarch_bind_is_game_controller() . + * + * Instead of using @code RARCH_FIRST_CUSTOM_BIND + 8 @endcode use + * instead @c rarch_num_bind_game_controller() . + * + * Instead of using this to check if a bind is just a plain button + * with no axis, instead use @c rarch_logical_bind_is_basic() . + */ #define RARCH_FIRST_CUSTOM_BIND 16 + #define RARCH_FIRST_LIGHTGUN_BIND RARCH_ANALOG_BIND_LIST_END #define RARCH_FIRST_MISC_CUSTOM_BIND RARCH_LIGHTGUN_BIND_LIST_END #define RARCH_FIRST_META_KEY RARCH_CUSTOM_BIND_LIST_END @@ -83,6 +95,9 @@ #endif +/** The number of extra core commands available, used with @c RETRO_ENVIRONMENT_SET_EXTENDED_RETROPAD . */ +#define RARCH_EXTRA_CORE_COMMAND_COUNT 128 + RETRO_BEGIN_DECLS /* RetroArch specific bind IDs. */ @@ -118,6 +133,16 @@ enum /* Turbo */ RARCH_TURBO_ENABLE = RARCH_FIRST_MISC_CUSTOM_BIND, + /** + * End of the custom bind list. + * + * Instead of using this to check whether a button is part of + * a game controller, use @c rarch_bind_is_game_controller() or + * instead @c rarch_num_bind_game_controller() . + * + * To get the starting ID for logical buttons use + * instead @c rarch_first_logical_bind_game_controller() . + */ RARCH_CUSTOM_BIND_LIST_END, /* Command binds. Not related to game input, @@ -187,6 +212,12 @@ enum RARCH_OVERLAY_NEXT, RARCH_OSK, + /** Custom core command start, used with @c RETRO_ENVIRONMENT_SET_EXTENDED_RETROPAD. */ + RARCH_EXTRA_CORE_COMMAND_START, + + /** Custom core command end, used with @c RETRO_ENVIRONMENT_SET_EXTENDED_RETROPAD. */ + RARCH_EXTRA_CORE_COMMAND_END = RARCH_EXTRA_CORE_COMMAND_START + RARCH_EXTRA_CORE_COMMAND_COUNT, + RARCH_BIND_LIST_END, /* Deprecated */ @@ -246,4 +277,132 @@ enum input_turbo_default_button RETRO_END_DECLS +/** + * Represents an actual bind id. + * + * @since 2023/12/24 + */ +typedef unsigned rarch_bind_id; + +/** + * Represents a logical bind id. + * + * @since 2023/12/24 + */ +typedef unsigned rarch_logical_bind_id; + +/** + * The first logical bind index. + * + * @since 2023/12/24 + */ +#define rarch_first_logical_bind_game_controller() RARCH_CUSTOM_BIND_LIST_END + +/** + * Is the given logical bind a basic button, one with no axis or otherwise? + * + * @param bind The logical bind to check. + * @return If the bind is simple. + * @since 2023/12/24 + */ +static INLINE bool rarch_logical_bind_is_basic(rarch_logical_bind_id bind) +{ + return (bind < RARCH_FIRST_CUSTOM_BIND) || (bind >= RARCH_CUSTOM_BIND_LIST_END); +} + +/** + * Is the given logical bind an extended basic button, one with no axis or otherwise? + * + * @param bind The logical bind to check. + * @return If the bind is simple and an extended button. + * @since 2023/12/24 + */ +static INLINE bool rarch_logical_bind_is_extended_basic(rarch_logical_bind_id bind) +{ + return (bind >= RARCH_CUSTOM_BIND_LIST_END); +} + +/** + * Returns the extended index of a given key. + * + * @param bind The bind to get the extended index of. + * @return The index of then given key or @c -1 if not valid. + * @since 2023/12/24 + */ +static INLINE int rarch_logical_bind_get_extended_index(rarch_logical_bind_id bind) +{ + if (bind < RARCH_CUSTOM_BIND_LIST_END) + return -1; + return bind - RARCH_CUSTOM_BIND_LIST_END; +} + +/** + * Translates a real bind id to a logical bind id. + * + * @param bind The input bind. + * @return The resultant logical index. + * @since 2023/12/24 + */ +static INLINE rarch_logical_bind_id rarch_bind_to_logical_game_controller(rarch_bind_id bind) +{ + if (bind < RARCH_CUSTOM_BIND_LIST_END) + return bind; + + if (bind >= RARCH_EXTRA_CORE_COMMAND_START && bind < RARCH_EXTRA_CORE_COMMAND_END) + return RARCH_CUSTOM_BIND_LIST_END + (bind - RARCH_EXTRA_CORE_COMMAND_START); + + return RARCH_BIND_LIST_END_NULL; +} + +/** + * Translates a logical bind id to an actual one. + * + * @param bind The logical game controller bind. + * @return The resultant bind id. + * @since 2023/12/24 + */ +static INLINE rarch_bind_id rarch_logical_to_bind_game_controller(rarch_logical_bind_id bind) +{ + if (bind >= RARCH_CUSTOM_BIND_LIST_END) + return (RARCH_EXTRA_CORE_COMMAND_START + bind); + + return bind; +} + +/** + * Returns the number of binds that are part of game controllers. + * + * Use this instead of @c RARCH_FIRST_CUSTOM_BIND; + * Use this instead of @code RARCH_FIRST_CUSTOM_BIND + 8 @endcode. + * + * @return The number of binds that are part of game controllers. + * @since 2023/12/24 + */ +#define rarch_num_bind_game_controller() (RARCH_CUSTOM_BIND_LIST_END + RARCH_EXTRA_CORE_COMMAND_COUNT) + +/** + * Checks whether the given bind is considered to be part of a controller. + * + * @param bind The bind id to check. + * @return If it is a game controller bind. + * @since 2023/12/24 + */ +static INLINE bool rarch_bind_is_game_controller(rarch_bind_id bind) +{ + return (bind < RARCH_CUSTOM_BIND_LIST_END) || + (bind >= RARCH_EXTRA_CORE_COMMAND_START && bind < RARCH_EXTRA_CORE_COMMAND_END); +} + +/** + * Checks whether the given bind is valid for a logical bind. + * + * @param bind The logical bind to check. + * @return If it is a valid logical bind. + * @since 2023/12/24 + */ +static INLINE bool rarch_logical_bind_is_game_controller(rarch_logical_bind_id bind) +{ + return bind < rarch_num_bind_game_controller(); +} + #endif diff --git a/input/input_driver.c b/input/input_driver.c index 177d5df2b86..baa3a92fe29 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -91,8 +91,32 @@ || ((autoconf_bind)->joyaxis != AXIS_NONE)) \ ) +#define INPUT_CONFIG_MASS_BIND_ORDER(x) (36 + x) +#define INPUT_CONFIG_MASS_BIND_ORDER_TEN(base) \ + INPUT_CONFIG_MASS_BIND_ORDER(base), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 1), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 2), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 3), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 4), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 5), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 6), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 7), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 8), \ + INPUT_CONFIG_MASS_BIND_ORDER(base + 9) +#define INPUT_CONFIG_MASS_BIND_ORDER_HUNDRED(base) \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 1), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 2), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 3), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 4), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 5), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 6), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 7), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 8), \ + INPUT_CONFIG_MASS_BIND_ORDER_TEN(base + 9) + /* Human readable order of input binds */ -const unsigned input_config_bind_order[24] = { +const unsigned input_config_bind_order[rarch_num_bind_game_controller()] = { RETRO_DEVICE_ID_JOYPAD_UP, RETRO_DEVICE_ID_JOYPAD_DOWN, RETRO_DEVICE_ID_JOYPAD_LEFT, @@ -109,16 +133,49 @@ const unsigned input_config_bind_order[24] = { RETRO_DEVICE_ID_JOYPAD_R2, RETRO_DEVICE_ID_JOYPAD_L3, RETRO_DEVICE_ID_JOYPAD_R3, - 19, /* Left Analog Up */ - 18, /* Left Analog Down */ - 17, /* Left Analog Left */ - 16, /* Left Analog Right */ - 23, /* Right Analog Up */ - 22, /* Right Analog Down */ - 21, /* Right Analog Left */ - 20, /* Right Analog Right */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_L_UP, /* Left Analog Up */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_L_DOWN, /* Left Analog Down */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_L_LEFT, /* Left Analog Left */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_L_RIGHT, /* Left Analog Right */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_R_UP, /* Right Analog Up */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_R_DOWN, /* Right Analog Down */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_R_LEFT, /* Right Analog Left */ + RETRO_DEVICE_ID_JOYPAD_ANALOG_R_RIGHT, /* Right Analog Right */ + + /* The remaining 36 + 128 = 164 entries, just 1:1 mapped... starts at 36. */ + INPUT_CONFIG_MASS_BIND_ORDER_HUNDRED(0), + INPUT_CONFIG_MASS_BIND_ORDER_TEN(100), + INPUT_CONFIG_MASS_BIND_ORDER_TEN(110), + INPUT_CONFIG_MASS_BIND_ORDER(120), + INPUT_CONFIG_MASS_BIND_ORDER(121), + INPUT_CONFIG_MASS_BIND_ORDER(122), + INPUT_CONFIG_MASS_BIND_ORDER(123), + INPUT_CONFIG_MASS_BIND_ORDER(124), + INPUT_CONFIG_MASS_BIND_ORDER(125), + INPUT_CONFIG_MASS_BIND_ORDER(126), + INPUT_CONFIG_MASS_BIND_ORDER(127), + + /* Light gun order, this is here because there has been mix and match + * between buttons, analogs, etc. */ + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + RARCH_UNMAPPED, + + /* Same goes for turbo. */ + RARCH_UNMAPPED, }; +#undef INPUT_CONFIG_MASS_BIND_ORDER +#undef INPUT_CONFIG_MASS_BIND_ORDER_TEN + /**************************************/ /* TODO/FIXME - turn these into static global variable */ retro_keybind_set input_config_binds[MAX_USERS]; @@ -6116,32 +6173,46 @@ void input_remapping_deinit(bool save_remap) void input_remapping_set_defaults(bool clear_cache) { - unsigned i, j; + unsigned usernum, logical; settings_t *settings = config_get_ptr(); + const struct retro_keybind *keybind; + bool is_ext; - for (i = 0; i < MAX_USERS; i++) + for (usernum = 0; usernum < MAX_USERS; usernum++) { /* Button/keyboard remaps */ - for (j = 0; j < RARCH_FIRST_CUSTOM_BIND; j++) + for (logical = 0; logical < rarch_num_bind_game_controller(); logical++) { - const struct retro_keybind *keybind = &input_config_binds[i][j]; + /* Ignore the analog/gun binds. */ + if (!rarch_logical_bind_is_basic(logical)) + continue; + + is_ext = rarch_logical_bind_is_extended_basic(logical); + + keybind = &input_config_binds[usernum][logical]; + + /* Debug. */ + RARCH_LOG("Keybind user %d log %d -> %p %d\n", + usernum, logical, keybind, (keybind != NULL ? keybind->id : -1)); + /* Force defaults for extended keys to be unmapped by default. */ configuration_set_uint(settings, - settings->uints.input_remap_ids[i][j], - keybind ? keybind->id : RARCH_UNMAPPED); + settings->uints.input_remap_ids[usernum][logical], + (/*!rarch_logical_bind_is_extended_basic(logical) &&*/ keybind) ? + keybind->id : RARCH_UNMAPPED); configuration_set_uint(settings, - settings->uints.input_keymapper_ids[i][j], RETROK_UNKNOWN); + settings->uints.input_keymapper_ids[usernum][logical], RETROK_UNKNOWN); } - /* Analog stick remaps */ - for (j = RARCH_FIRST_CUSTOM_BIND; j < (RARCH_FIRST_CUSTOM_BIND + 8); j++) + /* Analog stick remaps, use +8 still here for compatibility purposes. */ + for (logical = RARCH_FIRST_CUSTOM_BIND; logical < (RARCH_FIRST_CUSTOM_BIND + 8); logical++) configuration_set_uint(settings, - settings->uints.input_remap_ids[i][j], j); + settings->uints.input_remap_ids[usernum][logical], logical); /* Controller port remaps */ configuration_set_uint(settings, - settings->uints.input_remap_ports[i], i); + settings->uints.input_remap_ports[usernum], usernum); } /* Need to call 'input_remapping_update_port_map()' diff --git a/input/input_driver.h b/input/input_driver.h index 6fa75a3b353..7a39b985228 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -1058,7 +1058,7 @@ void input_driver_collect_system_input(input_driver_state_t *input_st, void input_keyboard_event(bool down, unsigned code, uint32_t character, uint16_t mod, unsigned device); -extern const unsigned input_config_bind_order[24]; +extern const unsigned input_config_bind_order[rarch_num_bind_game_controller()]; extern input_device_driver_t *joypad_drivers[]; extern input_driver_t *input_drivers[]; diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 999390dab45..9c0360414f8 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -15970,3 +15970,9 @@ MSG_HASH( MSG_IOS_TOUCH_MOUSE_DISABLED, "Touch mouse is disabled" ) + +/* Extra logical buttons. */ +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LOGICAL, + "Logical Button %d" + ) \ No newline at end of file diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index b16228b272d..72ecf9b6177 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -202,6 +202,18 @@ extern "C" { #define RETRO_DEVICE_ID_JOYPAD_L3 14 #define RETRO_DEVICE_ID_JOYPAD_R3 15 +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_L_RIGHT 16 +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_L_LEFT 17 +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_L_DOWN 18 +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_L_UP 19 + +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_R_RIGHT 20 +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_R_LEFT 21 +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_R_DOWN 22 +#define RETRO_DEVICE_ID_JOYPAD_ANALOG_R_UP 23 + +#define RETRO_DEVICE_ID_JOYPAD_MAX_BUTTONS 24 + #define RETRO_DEVICE_ID_JOYPAD_MASK 256 /* Index / Id values for ANALOG device. */ @@ -1852,6 +1864,12 @@ enum retro_mod * multiplayer, where a deterministic core supporting multiple * input devices does not need to take any action on its own. */ +#define RETRO_ENVIRONMENT_SET_EXTENDED_RETROPAD (79 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_core_extended_retropad* -- + * Similar to the setting of controls, this allows for + * the addition of additional button inputs which are not + * bound to anything. + */ /* VFS functionality */ @@ -3360,6 +3378,50 @@ struct retro_input_descriptor const char *description; }; +/** Used with @c retro_core_extended_retropad , similar to @c retro_input_descriptor. */ +struct retro_core_extended_retropad_button +{ + /** The controller port or player this is attached to. */ + unsigned port; + + /** The device that this is associated with, either @c RETRO_DEVICE_JOYPAD or @c RETRO_DEVICE_ANALOG. */ + unsigned device; + + /** The index of the device. */ + unsigned index; + + /** + * The logical bind ID number of the specific command. + * The value will be between @c 0 and @c out_num_extra . + */ + unsigned logical_id; + + /** The description of the command, @c NULL terminates the list. + * Must remain allocated until retro_unload_game() is called. */ + const char* description; + + /** The glyph to use for this command, it is up to the front end to provide a picture. + * Must remain allocated until retro_unload_game() is called.*/ + const char* glyph; +}; + +/** Used with @c RETRO_ENVIRONMENT_SET_EXTENDED_RETROPAD to set extra core buttons. */ +struct retro_core_extended_retropad_info +{ + /** Output: The number of extra buttons which are available. */ + unsigned out_num_extra; +}; + +/** Used with @c RETRO_ENVIRONMENT_SET_EXTENDED_RETROPAD to set extra core buttons. */ +struct retro_core_extended_retropad +{ + /** The core commands that exist, NULL description ends. */ + const struct retro_core_extended_retropad_button* actions; + + /** Extended RetroPad information output. */ + struct retro_core_extended_retropad_info* out_info; +}; + struct retro_system_info { /* All pointers are owned by libretro implementation, and pointers must diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c index 1fa79fdf566..9e0eb0f9f5b 100644 --- a/menu/cbs/menu_cbs_get_value.c +++ b/menu/cbs/menu_cbs_get_value.c @@ -828,8 +828,8 @@ static void menu_action_setting_disp_set_label_input_desc( { unsigned remap_idx; settings_t *settings = config_get_ptr(); - unsigned user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); - unsigned btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; + unsigned user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (rarch_num_bind_game_controller()); + unsigned btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (rarch_num_bind_game_controller()) * user_idx; if (!settings) return; @@ -845,7 +845,7 @@ static void menu_action_setting_disp_set_label_input_desc( if (!string_is_empty(descriptor)) { size_t _len = strlcpy(s, descriptor, len); - if (remap_idx < RARCH_FIRST_CUSTOM_BIND) { } + if (rarch_logical_bind_is_basic(remap_idx)) { } else if (remap_idx % 2 == 0) { s[ _len] = ' '; diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index d5858a3c816..c0e8b51e1c5 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -7137,17 +7137,17 @@ static int action_ok_push_dropdown_item_input_description(const char *path, if ( !settings || (entry_type < MENU_SETTINGS_INPUT_DESC_BEGIN) - || ((remap_idx >= RARCH_CUSTOM_BIND_LIST_END) + || ((remap_idx >= rarch_num_bind_game_controller()) && (remap_idx != RARCH_UNMAPPED))) return -1; /* Determine user/button indices */ user_idx = (entry_type - MENU_SETTINGS_INPUT_DESC_BEGIN) - / (RARCH_FIRST_CUSTOM_BIND + 8); + / (rarch_num_bind_game_controller()); btn_idx = (entry_type - MENU_SETTINGS_INPUT_DESC_BEGIN) - - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; + - (rarch_num_bind_game_controller()) * user_idx; - if ((user_idx >= MAX_USERS) || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END)) + if ((user_idx >= MAX_USERS) || (btn_idx >= rarch_num_bind_game_controller())) return -1; /* Assign new mapping */ diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 828ea697d0e..d2a67b8721b 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -245,13 +245,13 @@ static int action_start_input_desc( if (settings && sys_info) { - unsigned user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); - unsigned btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; + unsigned user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (rarch_num_bind_game_controller()); + unsigned btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (rarch_num_bind_game_controller()) * user_idx; unsigned mapped_port = settings->uints.input_remap_ports[user_idx]; if ( (user_idx >= MAX_USERS) || (mapped_port >= MAX_USERS) - || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END)) + || !rarch_logical_bind_is_game_controller(btn_idx)) return 0; /* Check whether core has defined this input */ diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 530d73d95ca..e56cd4780dc 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -1579,7 +1579,7 @@ static int action_bind_sublabel_remap_sublabel( { settings_t *settings = config_get_ptr(); unsigned port = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - / (RARCH_FIRST_CUSTOM_BIND + 8); + / (rarch_num_bind_game_controller()); if (settings && (port < MAX_USERS)) { diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index ac4d526cdb6..d3d13c4c65f 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -549,7 +549,7 @@ static int action_get_title_dropdown_input_description( const char *path, const char *label, unsigned menu_type, char *s, size_t len) { unsigned port = (menu_type - MENU_SETTINGS_INPUT_DESC_BEGIN) / - (RARCH_FIRST_CUSTOM_BIND + 8); + (rarch_num_bind_game_controller()); return action_get_title_dropdown_input_description_common( path, port, s, len); diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index ee71e2dc8e1..0536532a9cd 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -5466,11 +5466,11 @@ static int menu_displaylist_parse_input_description_list( return 0; /* Determine user/button indices */ - user_idx = (info->type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); - btn_idx = (info->type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; + user_idx = (info->type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (rarch_num_bind_game_controller()); + btn_idx = (info->type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (rarch_num_bind_game_controller()) * user_idx; if ( (user_idx >= MAX_USERS) - || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END)) + || (btn_idx >= rarch_num_bind_game_controller())) return 0; mapped_port = settings->uints.input_remap_ports[user_idx]; @@ -5481,7 +5481,7 @@ static int menu_displaylist_parse_input_description_list( /* Get current mapping for selected button */ current_remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx]; - if (current_remap_idx >= RARCH_CUSTOM_BIND_LIST_END) + if (current_remap_idx < 0 || current_remap_idx >= rarch_num_bind_game_controller()) current_remap_idx = RARCH_UNMAPPED; /* An annoyance: Menu entries do not have @@ -5494,11 +5494,11 @@ static int menu_displaylist_parse_input_description_list( snprintf(entry_label, sizeof(entry_label), "%u", info->type); /* Loop over core input definitions */ - for (j = 0; j < RARCH_CUSTOM_BIND_LIST_END; j++) + for (j = 0; j < rarch_num_bind_game_controller(); j++) { const char *input_desc_btn; - i = (j < RARCH_ANALOG_BIND_LIST_END) ? input_config_bind_order[j] : j; + i = (rarch_logical_bind_is_basic(j) ? input_config_bind_order[j] : j); input_desc_btn = sys_info->input_desc_btn[mapped_port][i]; /* Check whether an input is defined for @@ -5514,7 +5514,7 @@ static int menu_displaylist_parse_input_description_list( * indicators */ size_t _len = strlcpy(input_description, input_desc_btn, sizeof(input_description)); - if (i >= RARCH_FIRST_CUSTOM_BIND) + if (!rarch_logical_bind_is_basic(i)) { input_description [ _len] = ' '; if ((i % 2) == 0) @@ -11687,7 +11687,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, if (menu_entries_append(list, descriptor, info->path, MSG_UNKNOWN, MENU_SETTINGS_INPUT_DESC_BEGIN + - (port * (RARCH_FIRST_CUSTOM_BIND + 8)) + retro_id, 0, 0, NULL)) + (port * rarch_num_bind_game_controller()) + retro_id, 0, 0, NULL)) count++; } } diff --git a/menu/menu_driver.h b/menu/menu_driver.h index e56be9fdd75..69622ad8708 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -217,9 +217,11 @@ enum menu_settings_type MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS, + + /* Binds in the menu, note that every single bind needs to fit! */ MENU_SETTINGS_BIND_BEGIN, - MENU_SETTINGS_BIND_LAST = MENU_SETTINGS_BIND_BEGIN + RARCH_ANALOG_RIGHT_Y_MINUS, - MENU_SETTINGS_BIND_ALL_LAST = MENU_SETTINGS_BIND_BEGIN + RARCH_MENU_TOGGLE, + MENU_SETTINGS_BIND_LAST = MENU_SETTINGS_BIND_BEGIN + rarch_num_bind_game_controller(), + MENU_SETTINGS_BIND_ALL_LAST = MENU_SETTINGS_BIND_BEGIN + RARCH_EXTRA_CORE_COMMAND_COUNT + RARCH_MENU_TOGGLE, MENU_SETTINGS_CUSTOM_BIND, MENU_SETTINGS_CUSTOM_BIND_KEYBOARD, @@ -232,13 +234,14 @@ enum menu_settings_type MENU_SETTINGS_CHEAT_BEGIN, MENU_SETTINGS_CHEAT_END = MENU_SETTINGS_CHEAT_BEGIN + (MAX_CHEAT_COUNTERS - 1), + /* Within @c MENU_SETTINGS_INPUT_END , the + 6 are these following keys. */ MENU_SETTINGS_INPUT_LIBRETRO_DEVICE, MENU_SETTINGS_INPUT_ANALOG_DPAD_MODE, MENU_SETTINGS_INPUT_INPUT_REMAP_PORT, MENU_SETTINGS_INPUT_BEGIN, - MENU_SETTINGS_INPUT_END = MENU_SETTINGS_INPUT_BEGIN + RARCH_CUSTOM_BIND_LIST_END + 6, + MENU_SETTINGS_INPUT_END = MENU_SETTINGS_INPUT_BEGIN + rarch_num_bind_game_controller() + 6, MENU_SETTINGS_INPUT_DESC_BEGIN, - MENU_SETTINGS_INPUT_DESC_END = MENU_SETTINGS_INPUT_DESC_BEGIN + ((RARCH_FIRST_CUSTOM_BIND + 8) * MAX_USERS), + MENU_SETTINGS_INPUT_DESC_END = MENU_SETTINGS_INPUT_DESC_BEGIN + (rarch_num_bind_game_controller() * MAX_USERS), MENU_SETTINGS_INPUT_DESC_KBD_BEGIN, MENU_SETTINGS_INPUT_DESC_KBD_END = MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + (RARCH_MAX_KEYS * MAX_USERS), MENU_SETTINGS_REMAPPING_PORT_BEGIN, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 80a43f75c76..5ec3c643e5b 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -224,9 +224,9 @@ if (SETTINGS_LIST_APPEND(a, b)) \ config_hex(a, b, c, d, e, f, g, h, i, j, k, l) -#define CONFIG_BIND_ALT(a, b, c, d, e, f, g, h, i, j, k) \ - if (SETTINGS_LIST_APPEND(a, b)) \ - config_bind_alt(a, b, c, d, e, f, g, h, i, j, k) +#define CONFIG_BIND_ALT(list, list_info, target, player, player_offset, name, SHORT, default_value, group_info, subgroup_info, parent_group) \ + if (SETTINGS_LIST_APPEND(list, list_info)) \ + config_bind_alt(list, list_info, target, player, player_offset, name, SHORT, default_value, group_info, subgroup_info, parent_group) #define CONFIG_BIND(a, b, c, d, e, f, g, h, i, j, k, l) \ if (SETTINGS_LIST_APPEND(a, b)) \ @@ -9021,7 +9021,7 @@ static bool setting_append_list_input_player_options( */ static char buffer[MAX_USERS][13+2+1]; static char group_label[MAX_USERS][255]; - unsigned i, j; + unsigned bindish, bindid; rarch_setting_group_info_t group_info; rarch_setting_group_info_t subgroup_info; settings_t *settings = config_get_ptr(); @@ -9254,16 +9254,41 @@ static bool setting_append_list_input_player_options( { const char *value_na = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE); - for (j = 0; j < RARCH_BIND_LIST_END; j++) + + RARCH_LOG("Filling in bind menu for user %d.\n", user); + + for (bindid = 0; bindid < RARCH_BIND_LIST_END; bindid++) { char label[NAME_MAX_LENGTH]; char name[NAME_MAX_LENGTH]; + bool is_game; + rarch_logical_bind_id logical_bind; size_t _len = 0; - i = (j < RARCH_ANALOG_BIND_LIST_END) - ? input_config_bind_order[j] - : j; - if (input_config_bind_map_get_meta(i)) + /* Is this a game button or similar? */ + is_game = rarch_bind_is_game_controller(bindid); + + /* Which button does this belong to? */ + if (is_game) + { + logical_bind = rarch_bind_to_logical_game_controller(bindid); + + /* For extended basic buttons we go really deep into the actual bind + * map as it is not at the start which @c input_config_bind_order + * assumes, so effectively use the real bind id for its position. */ + if (rarch_logical_bind_is_extended_basic(logical_bind)) + bindish = bindid; + else + bindish = input_config_bind_order[logical_bind]; + } + else + { + logical_bind = (rarch_logical_bind_id)-1; + bindish = bindid; + } + + /* Checks keybind->meta, where 0 is for game controllers. */ + if (0 != input_config_bind_map_get_meta(bindish)) continue; name[0] = '\0'; @@ -9279,20 +9304,35 @@ static bool setting_append_list_input_player_options( if ( settings->bools.input_descriptor_label_show - && (i < RARCH_FIRST_META_KEY) - && core_has_set_input_descriptor() - && (i != RARCH_TURBO_ENABLE) + && is_game + && (core_has_set_input_descriptor()) + && (bindish != RARCH_TURBO_ENABLE) ) { - if (sys_info->input_desc_btn[user][i]) + /* For core defined keys, we use the label provided by the core... if any. */ + if (sys_info->input_desc_btn[user][logical_bind]) + { strlcpy(label + _len, - sys_info->input_desc_btn[user][i], + sys_info->input_desc_btn[user][logical_bind], sizeof(label) - _len); + } + + /* Otherwise we just label it with the description of the key. */ else { - snprintf(label, sizeof(label), "%s (%s)", - input_config_bind_map_get_desc(i), - value_na); + /* For logical keys they have no true label, so use a generic name for them. */ + if (rarch_logical_bind_is_extended_basic(logical_bind)) + { + snprintf(label, sizeof(label), "Logical %d (%s)", + rarch_logical_bind_get_extended_index(logical_bind), + value_na); + } + else + { + snprintf(label, sizeof(label), "%s (%s)", + input_config_bind_map_get_desc(bindish), + value_na); + } if (settings->bools.input_descriptor_hide_unbound) continue; @@ -9300,23 +9340,25 @@ static bool setting_append_list_input_player_options( } else strlcpy(label + _len, - input_config_bind_map_get_desc(i), + input_config_bind_map_get_desc(bindish), sizeof(label) - _len); - snprintf(name, sizeof(name), "p%u_%s", user + 1, input_config_bind_map_get_base(i)); + /* Essentially p1_y. */ + snprintf(name, sizeof(name), "p%u_%s", + user + 1, input_config_bind_map_get_base(bindish)); CONFIG_BIND_ALT( list, list_info, - &input_config_binds[user][i], + &input_config_binds[user][bindish], user + 1, user, strdup(name), strdup(label), - &defaults[i], + &defaults[bindish], &group_info, &subgroup_info, parent_group); - (*list)[list_info->index - 1].bind_type = i + MENU_SETTINGS_BIND_BEGIN; + (*list)[list_info->index - 1].bind_type = bindish + MENU_SETTINGS_BIND_BEGIN; } } diff --git a/msg_hash.h b/msg_hash.h index c3ccb278372..eb1e5cc9aa9 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -4121,6 +4121,9 @@ enum msg_hash_enums MSG_3DS_BOTTOM_MENU_SAVE_STATE, MSG_3DS_BOTTOM_MENU_LOAD_STATE, + /* Logical menu input. */ + MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LOGICAL, + MSG_LAST, /* Ensure sizeof(enum) == sizeof(int) */ diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index c53b81f4e7e..f8f30caed8c 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -7744,7 +7744,7 @@ static bool get_self_input_state( /* no break */ case RETRO_DEVICE_JOYPAD: - for (i = 0; i <= RETRO_DEVICE_ID_JOYPAD_R3; i++) + for (i = 0; i <= RETRO_DEVICE_ID_JOYPAD_MAX_BUTTONS; i++) { int16_t tmp = cb(local_device, RETRO_DEVICE_JOYPAD, 0, (unsigned)i); diff --git a/network/netplay/netplay_protocol.h b/network/netplay/netplay_protocol.h index 7583a2e2561..608fca18b77 100644 --- a/network/netplay/netplay_protocol.h +++ b/network/netplay/netplay_protocol.h @@ -19,7 +19,7 @@ #define __RARCH_NETPLAY_PROTOCOL_H #define LOW_NETPLAY_PROTOCOL_VERSION 5 -#define HIGH_NETPLAY_PROTOCOL_VERSION 6 +#define HIGH_NETPLAY_PROTOCOL_VERSION 7 #define NETPLAY_PROTOCOL_VERSION HIGH_NETPLAY_PROTOCOL_VERSION diff --git a/retroarch.c b/retroarch.c index 896598c9902..99c0e163709 100644 --- a/retroarch.c +++ b/retroarch.c @@ -5535,6 +5535,7 @@ static void global_free(struct rarch_state *p_rarch) #endif runloop_st->current_core.flags &= ~(RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS + | RETRO_CORE_FLAG_HAS_SET_EXTENDED_INPUT | RETRO_CORE_FLAG_HAS_SET_SUBSYSTEMS); global = global_get_ptr(); @@ -6734,6 +6735,7 @@ static bool retroarch_parse_input_and_config( /* Flush out some states that could have been set * by core environment variables. */ runloop_st->current_core.flags &= ~(RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS + | RETRO_CORE_FLAG_HAS_SET_EXTENDED_INPUT | RETRO_CORE_FLAG_HAS_SET_SUBSYSTEMS); /* Load the config file now that we know what it is */ diff --git a/retroarch_types.h b/retroarch_types.h index 37e6492d150..e6d068bc985 100644 --- a/retroarch_types.h +++ b/retroarch_types.h @@ -169,7 +169,7 @@ typedef struct rarch_system_info disk_control_interface_t disk_control; /* ptr alignment */ struct retro_system_info info; /* ptr alignment */ rarch_memory_map_t mmaps; /* ptr alignment */ - const char *input_desc_btn[MAX_USERS][RARCH_FIRST_META_KEY]; + const char *input_desc_btn[MAX_USERS][rarch_num_bind_game_controller()]; struct { struct retro_subsystem_info *data; diff --git a/runloop.c b/runloop.c index 43bed44704c..b785bdeafea 100644 --- a/runloop.c +++ b/runloop.c @@ -1401,6 +1401,253 @@ static void core_performance_counter_stop(struct retro_perf_counter *perf) perf->total += cpu_features_get_perf_counter() - perf->start; } +/** + * Erases input descriptor buttons. + * + * @param sys_info The current state of the front end. + * @param from The starting index, inclusive. + * @param to The ending index, exclusive. + */ +static void rarch_erase_input_desc_btn(rarch_system_info_t *sys_info, unsigned from, unsigned to) +{ + unsigned usernum, at; + const char** user_inputs; + + /* Erase all the previous extended binds for all users. */ + for (usernum = 0; usernum < MAX_USERS; usernum++) + { + /* For simpler access. */ + user_inputs = sys_info->input_desc_btn[usernum]; + + /* Invalidate all entries. */ + for (at = rarch_first_logical_bind_game_controller(); + at < rarch_num_bind_game_controller(); + at++) + user_inputs[at] = NULL; + } +} + +static void rarch_set_core_extended_retropad(rarch_system_info_t *sys_info, + runloop_state_t *runloop_st, + const struct retro_core_extended_retropad *input) { + const struct retro_core_extended_retropad_button* action; + unsigned at, bind, usernum; + const char** user_inputs; + bool did_standard; + + /* Debug. */ + RARCH_LOG("[Environ]: Setting extended retropad buttons.\n"); + + /* Check if standard inputs were set. */ + did_standard = (runloop_st->current_core.flags & RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS) != 0; + if (!did_standard) + RARCH_LOG("[Environ]: Standard was not previously set.\n"); + + /* Erase all the previous extended binds for all users. */ + if (did_standard) + rarch_erase_input_desc_btn(sys_info, + rarch_first_logical_bind_game_controller(), + rarch_num_bind_game_controller()); + + /* Otherwise erase everything as it has never been set before. */ + else + rarch_erase_input_desc_btn(sys_info, 0, rarch_num_bind_game_controller()); + + /* Set output details, if requested. */ + if (input->out_info != NULL) { + input->out_info->out_num_extra = RARCH_EXTRA_CORE_COMMAND_COUNT; + } + + /* Go through the commands and process them. */ + if (input->actions != NULL) + { + for (at = 0; input->actions[at].description != NULL; at++) + { + /* Get base action. */ + action = &input->actions[at]; + + /* Debug. */ + RARCH_LOG("[Environ]: Wanting extra button %d %d %d %d %d %s %s.\n", + at, action->port, action->device, action->port, action->logical_id, + action->description, action->glyph); + + /* Map player. */ + usernum = action->port; + if (usernum < 0 || usernum >= MAX_USERS) + continue; + + /* We only care about gamepads and their analog equivalents. */ + if (action->device != RETRO_DEVICE_JOYPAD && + action->device != RETRO_DEVICE_ANALOG) + continue; + + /* Ignore logical binds which are out of bounds. */ + bind = action->logical_id; + if (bind < 0 || bind >= RARCH_EXTRA_CORE_COMMAND_COUNT) + continue; + + /* Map to logical button internally. */ + bind = rarch_first_logical_bind_game_controller() + bind; + + /* Set description. */ + sys_info->input_desc_btn[usernum][bind] = action->description; + + /* Debug. */ + RARCH_LOG("[Environ]: Bound %d to %s.\n", + bind, action->description); + } + + /* Debug. */ + RARCH_LOG("[Environ]: Set %d extended buttons.\n", at); + } + + /* Indicate that the input descriptors changed. */ + runloop_st->current_core.flags |= + RETRO_CORE_FLAG_HAS_SET_EXTENDED_INPUT; +} + +static void rarch_set_input_descriptors(const void *data, + runloop_state_t *runloop_st, const settings_t *settings, + rarch_system_info_t *sys_info) { + unsigned retro_id; + const struct retro_input_descriptor *desc = NULL; + unsigned int p; + bool did_extra; + + /* Check if extended inputs were set. */ + did_extra = (runloop_st->current_core.flags & RETRO_CORE_FLAG_HAS_SET_EXTENDED_INPUT) != 0; + if (!did_extra) + RARCH_LOG("[Environ]: SET_INPUT_DESCRIPTORS: Extra was not previously set.\n"); + + /* If extended descriptors were set, only erase the standard ones. */ + if (did_extra) + rarch_erase_input_desc_btn(sys_info, 0, rarch_first_logical_bind_game_controller()); + + /* Otherwise, erase everything to keep legacy behavior. */ + else + rarch_erase_input_desc_btn(sys_info, 0, rarch_num_bind_game_controller()); + + desc = (const struct retro_input_descriptor*)data; + + for (; desc->description; desc++) + { + unsigned retro_port = desc->port; + + retro_id = desc->id; + + if (desc->port >= MAX_USERS) + continue; + + /* Ignore extended custom binds. */ + if (desc->id >= RARCH_FIRST_CUSTOM_BIND) + continue; + + switch (desc->device) + { + case RETRO_DEVICE_JOYPAD: + sys_info->input_desc_btn[retro_port] + [retro_id] = desc->description; + break; + case RETRO_DEVICE_ANALOG: + switch (retro_id) + { + case RETRO_DEVICE_ID_ANALOG_X: + switch (desc->index) + { + case RETRO_DEVICE_INDEX_ANALOG_LEFT: + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_LEFT_X_PLUS] = desc->description; + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_LEFT_X_MINUS] = desc->description; + break; + case RETRO_DEVICE_INDEX_ANALOG_RIGHT: + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_RIGHT_X_PLUS] = desc->description; + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_RIGHT_X_MINUS] = desc->description; + break; + } + break; + case RETRO_DEVICE_ID_ANALOG_Y: + switch (desc->index) + { + case RETRO_DEVICE_INDEX_ANALOG_LEFT: + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_LEFT_Y_PLUS] = desc->description; + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_LEFT_Y_MINUS] = desc->description; + break; + case RETRO_DEVICE_INDEX_ANALOG_RIGHT: + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_RIGHT_Y_PLUS] = desc->description; + sys_info->input_desc_btn[retro_port] + [RARCH_ANALOG_RIGHT_Y_MINUS] = desc->description; + break; + } + break; + case RETRO_DEVICE_ID_JOYPAD_R2: + switch (desc->index) + { + case RETRO_DEVICE_INDEX_ANALOG_BUTTON: + sys_info->input_desc_btn[retro_port] + [retro_id] = desc->description; + break; + } + break; + case RETRO_DEVICE_ID_JOYPAD_L2: + switch (desc->index) + { + case RETRO_DEVICE_INDEX_ANALOG_BUTTON: + sys_info->input_desc_btn[retro_port] + [retro_id] = desc->description; + break; + } + break; + } + break; + } + } + + RARCH_LOG("[Environ]: SET_INPUT_DESCRIPTORS:\n"); + + { + unsigned log_level = settings->uints.libretro_log_level; + + if (log_level == RETRO_LOG_DEBUG) + { + unsigned input_driver_max_users = settings->uints.input_max_users; + unsigned bind_index; + const char *description; + + for (p = 0; p < input_driver_max_users; p++) + { + unsigned mapped_port = settings->uints.input_remap_ports[p]; + + RARCH_DBG(" %s %u:\n", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT), p + 1); + + for (retro_id = 0; retro_id < RETRO_DEVICE_ID_JOYPAD_MAX_BUTTONS; retro_id++) + { + bind_index = input_config_bind_order[retro_id]; + + if (bind_index == RARCH_UNMAPPED) + continue; + + description = sys_info->input_desc_btn[mapped_port][bind_index]; + + if (!description) + continue; + + RARCH_DBG(" \"%s\" => \"%s\"\n", + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B + bind_index), + description); + } + } + } + } + + runloop_st->current_core.flags |= + RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS; +} bool runloop_environment_cb(unsigned cmd, void *data) { @@ -2049,124 +2296,7 @@ bool runloop_environment_cb(unsigned cmd, void *data) { if (sys_info) { - unsigned retro_id; - const struct retro_input_descriptor *desc = NULL; - memset((void*)&sys_info->input_desc_btn, 0, - sizeof(sys_info->input_desc_btn)); - - desc = (const struct retro_input_descriptor*)data; - - for (; desc->description; desc++) - { - unsigned retro_port = desc->port; - - retro_id = desc->id; - - if (desc->port >= MAX_USERS) - continue; - - if (desc->id >= RARCH_FIRST_CUSTOM_BIND) - continue; - - switch (desc->device) - { - case RETRO_DEVICE_JOYPAD: - sys_info->input_desc_btn[retro_port] - [retro_id] = desc->description; - break; - case RETRO_DEVICE_ANALOG: - switch (retro_id) - { - case RETRO_DEVICE_ID_ANALOG_X: - switch (desc->index) - { - case RETRO_DEVICE_INDEX_ANALOG_LEFT: - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_LEFT_X_PLUS] = desc->description; - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_LEFT_X_MINUS] = desc->description; - break; - case RETRO_DEVICE_INDEX_ANALOG_RIGHT: - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_RIGHT_X_PLUS] = desc->description; - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_RIGHT_X_MINUS] = desc->description; - break; - } - break; - case RETRO_DEVICE_ID_ANALOG_Y: - switch (desc->index) - { - case RETRO_DEVICE_INDEX_ANALOG_LEFT: - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_LEFT_Y_PLUS] = desc->description; - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_LEFT_Y_MINUS] = desc->description; - break; - case RETRO_DEVICE_INDEX_ANALOG_RIGHT: - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_RIGHT_Y_PLUS] = desc->description; - sys_info->input_desc_btn[retro_port] - [RARCH_ANALOG_RIGHT_Y_MINUS] = desc->description; - break; - } - break; - case RETRO_DEVICE_ID_JOYPAD_R2: - switch (desc->index) - { - case RETRO_DEVICE_INDEX_ANALOG_BUTTON: - sys_info->input_desc_btn[retro_port] - [retro_id] = desc->description; - break; - } - break; - case RETRO_DEVICE_ID_JOYPAD_L2: - switch (desc->index) - { - case RETRO_DEVICE_INDEX_ANALOG_BUTTON: - sys_info->input_desc_btn[retro_port] - [retro_id] = desc->description; - break; - } - break; - } - break; - } - } - - RARCH_LOG("[Environ]: SET_INPUT_DESCRIPTORS:\n"); - - { - unsigned log_level = settings->uints.libretro_log_level; - - if (log_level == RETRO_LOG_DEBUG) - { - unsigned input_driver_max_users = settings->uints.input_max_users; - - for (p = 0; p < input_driver_max_users; p++) - { - unsigned mapped_port = settings->uints.input_remap_ports[p]; - - RARCH_DBG(" %s %u:\n", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT), p + 1); - - for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++) - { - unsigned bind_index = input_config_bind_order[retro_id]; - const char *description = sys_info->input_desc_btn[mapped_port][bind_index]; - - if (!description) - continue; - - RARCH_DBG(" \"%s\" => \"%s\"\n", - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B + bind_index), - description); - } - } - } - } - - runloop_st->current_core.flags |= - RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS; + rarch_set_input_descriptors(data, runloop_st, settings, sys_info); } break; } @@ -3551,6 +3681,12 @@ bool runloop_environment_cb(unsigned cmd, void *data) } } break; + + case RETRO_ENVIRONMENT_SET_EXTENDED_RETROPAD: + rarch_set_core_extended_retropad(sys_info, runloop_st, + (struct retro_core_extended_retropad*)data); + break; + default: RARCH_LOG("[Environ]: UNSUPPORTED (#%u).\n", cmd); return false; @@ -7793,7 +7929,8 @@ bool core_has_set_input_descriptor(void) { runloop_state_t *runloop_st = &runloop_state; return ((runloop_st->current_core.flags & - RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS) > 0); + (RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS | + RETRO_CORE_FLAG_HAS_SET_EXTENDED_INPUT)) != 0); } void runloop_path_set_basename(const char *path)