mirror of
https://github.com/libretro/RetroArch
synced 2025-03-18 13:20:57 +00:00
Sort Remaps by Connected Controller (#16747)
* sort remaps by connected controller if option is enabled * ensure dir name is valid based on input device name * Fix comments * Fix forbidden mixed declarations and code * fixing build errors * fix additional build warning/error * Resolved code review change requests * Changed strlcat to strlcpy as per recommendation * Retrigger checks * Use proper path separator. * Ensure default value is toggled off. * Ensure that gamepad device name is valid.
This commit is contained in:
parent
8c2d2f5d74
commit
e61b3ae2ba
@ -2132,6 +2132,7 @@ static struct config_bool_setting *populate_settings_bool(
|
||||
SETTING_BOOL("input_allow_turbo_dpad", &settings->bools.input_allow_turbo_dpad, true, DEFAULT_ALLOW_TURBO_DPAD, false);
|
||||
SETTING_BOOL("input_auto_mouse_grab", &settings->bools.input_auto_mouse_grab, true, DEFAULT_INPUT_AUTO_MOUSE_GRAB, false);
|
||||
SETTING_BOOL("input_remap_binds_enable", &settings->bools.input_remap_binds_enable, true, true, false);
|
||||
SETTING_BOOL("input_remap_sort_by_controller_enable", &settings->bools.input_remap_sort_by_controller_enable, true, false, false);
|
||||
SETTING_BOOL("input_hotkey_device_merge", &settings->bools.input_hotkey_device_merge, true, DEFAULT_INPUT_HOTKEY_DEVICE_MERGE, false);
|
||||
SETTING_BOOL("all_users_control_menu", &settings->bools.input_all_users_control_menu, true, DEFAULT_ALL_USERS_CONTROL_MENU, false);
|
||||
#ifdef HAVE_MENU
|
||||
@ -4601,6 +4602,7 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
char game_path[PATH_MAX_LENGTH];
|
||||
/* final path for content-dir-specific configuration (prefix+suffix) */
|
||||
char content_path[PATH_MAX_LENGTH];
|
||||
|
||||
config_file_t *new_conf = NULL;
|
||||
rarch_system_info_t *sys_info = (rarch_system_info_t*)data;
|
||||
const char *core_name = sys_info ? sys_info->info.library_name : NULL;
|
||||
@ -4610,6 +4612,13 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
enum msg_hash_enums msg_remap_loaded = MSG_GAME_REMAP_FILE_LOADED;
|
||||
settings_t *settings = config_st;
|
||||
bool notification_show_remap_load = settings->bools.notification_show_remap_load;
|
||||
unsigned joypad_port = settings->uints.input_joypad_index[0];
|
||||
const char *input_device_name = input_config_get_device_display_name(joypad_port);
|
||||
const char *input_device_dir = NULL;
|
||||
char *remap_path = NULL;
|
||||
bool sort_remaps_by_controller = settings->bools.input_remap_sort_by_controller_enable;
|
||||
size_t remap_path_total_len = 0;
|
||||
size_t _len = 0;
|
||||
|
||||
content_dir_name[0] = '\0';
|
||||
core_path[0] = '\0';
|
||||
@ -4622,6 +4631,36 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
|| string_is_empty(directory_input_remapping))
|
||||
return false;
|
||||
|
||||
if ( sort_remaps_by_controller
|
||||
&& input_device_name != NULL
|
||||
&& !string_is_empty(input_device_name))
|
||||
{
|
||||
/* Ensure directory does not contain special chars */
|
||||
input_device_dir = sanitize_path_part(input_device_name, strlen(input_device_name));
|
||||
|
||||
/* Allocate memory for the new path */
|
||||
remap_path_total_len = strlen(core_name) + strlen(input_device_dir) + 2;
|
||||
remap_path = (char *)malloc(remap_path_total_len);
|
||||
|
||||
/* Build the new path with the controller name */
|
||||
_len = strlcpy(remap_path, core_name, remap_path_total_len);
|
||||
_len += strlcpy(remap_path + _len, PATH_DEFAULT_SLASH(), remap_path_total_len - _len);
|
||||
_len += strlcpy(remap_path + _len, input_device_dir, remap_path_total_len - _len);
|
||||
|
||||
/* Deallocate as we no longer this */
|
||||
free((char*)input_device_dir);
|
||||
input_device_dir = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate memory for the new path */
|
||||
remap_path_total_len = strlen(core_name) + 1;
|
||||
remap_path = (char *)malloc(remap_path_total_len);
|
||||
|
||||
/* We're not using controller path, just use core name */
|
||||
strlcpy(remap_path, core_name, remap_path_total_len);
|
||||
}
|
||||
|
||||
/* Concatenate strings into full paths for core_path,
|
||||
* game_path, content_path */
|
||||
if (has_content)
|
||||
@ -4631,24 +4670,26 @@ bool config_load_remap(const char *directory_input_remapping,
|
||||
game_name = path_basename_nocompression(rarch_path_basename);
|
||||
|
||||
fill_pathname_join_special_ext(game_path,
|
||||
directory_input_remapping, core_name,
|
||||
directory_input_remapping, remap_path,
|
||||
game_name,
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(game_path));
|
||||
|
||||
fill_pathname_join_special_ext(content_path,
|
||||
directory_input_remapping, core_name,
|
||||
directory_input_remapping, remap_path,
|
||||
content_dir_name,
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(content_path));
|
||||
}
|
||||
|
||||
fill_pathname_join_special_ext(core_path,
|
||||
directory_input_remapping, core_name,
|
||||
directory_input_remapping, remap_path,
|
||||
core_name,
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(core_path));
|
||||
|
||||
free(remap_path);
|
||||
|
||||
/* If a game remap file exists, load it. */
|
||||
if (has_content && (new_conf = config_file_new_from_path_to_string(game_path)))
|
||||
{
|
||||
|
@ -680,6 +680,7 @@ typedef struct settings
|
||||
|
||||
/* Input */
|
||||
bool input_remap_binds_enable;
|
||||
bool input_remap_sort_by_controller_enable;
|
||||
bool input_autodetect_enable;
|
||||
bool input_sensors_enable;
|
||||
bool input_overlay_enable;
|
||||
|
@ -2152,6 +2152,10 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_INPUT_REMAP_BINDS_ENABLE,
|
||||
"input_remap_binds_enable"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE,
|
||||
"input_remap_sort_by_controller_enable"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_INPUT_SETTINGS,
|
||||
"input_settings"
|
||||
|
@ -3349,6 +3349,14 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE,
|
||||
"Override the input binds with the remapped binds set for the current core."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE,
|
||||
"Sort Remaps By Gamepad"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE,
|
||||
"Remaps will only apply to the active gamepad in which they were saved."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_AUTODETECT_ENABLE,
|
||||
"Autoconfig"
|
||||
|
@ -1172,6 +1172,42 @@ size_t fill_pathname_abbreviate_special(char *out_path,
|
||||
return strlcpy(out_path, in_path, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* sanitize_path_part:
|
||||
*
|
||||
* @path_part : directory or filename
|
||||
*
|
||||
* Takes single part of a path eg. single filename
|
||||
* or directory, and removes any special chars that are
|
||||
* unavailable.
|
||||
*
|
||||
* @returns new string that has been sanitized
|
||||
**/
|
||||
const char *sanitize_path_part(const char *path_part, size_t size)
|
||||
{
|
||||
int i;
|
||||
int j = 0;
|
||||
int len = 0;
|
||||
char *temp = NULL;
|
||||
const char *special_chars = "<>:\"/\\|?*";
|
||||
|
||||
if (string_is_empty(path_part))
|
||||
return NULL;
|
||||
|
||||
temp = (char *)malloc((size + 1) * sizeof(char));
|
||||
|
||||
for (i = 0; path_part[i] != '\0'; i++)
|
||||
/* Check if the current character is one of the special characters */
|
||||
if (strchr(special_chars, path_part[i]) == NULL)
|
||||
/* If not, copy it to the temporary array */
|
||||
temp[j++] = path_part[i];
|
||||
|
||||
temp[j] = '\0';
|
||||
|
||||
/* Return the new string */
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* pathname_conform_slashes_to_os:
|
||||
*
|
||||
|
@ -551,6 +551,20 @@ size_t fill_pathname_abbreviate_special(char *out_path,
|
||||
size_t fill_pathname_abbreviated_or_relative(char *out_path,
|
||||
const char *in_refpath, const char *in_path, size_t size);
|
||||
|
||||
/**
|
||||
* sanitize_path_part:
|
||||
*
|
||||
* @path_part : directory or filename
|
||||
* @size : length of path_part
|
||||
*
|
||||
* Takes single part of a path eg. single filename
|
||||
* or directory, and removes any special chars that are
|
||||
* unavailable.
|
||||
*
|
||||
* @returns new string that has been sanitized
|
||||
**/
|
||||
const char *sanitize_path_part(const char *path_part, size_t size);
|
||||
|
||||
/**
|
||||
* pathname_conform_slashes_to_os:
|
||||
*
|
||||
|
@ -3643,13 +3643,20 @@ static int generic_action_ok_remap_file_operation(const char *path,
|
||||
#ifdef HAVE_CONFIGFILE
|
||||
char content_dir_name[DIR_MAX_LENGTH];
|
||||
char remap_file_path[PATH_MAX_LENGTH];
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
rarch_system_info_t *sys_info = &runloop_state_get_ptr()->system;
|
||||
const char *core_name = sys_info ? sys_info->info.library_name : NULL;
|
||||
const char *rarch_path_basename = path_get(RARCH_PATH_BASENAME);
|
||||
bool has_content = !string_is_empty(rarch_path_basename);
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *directory_input_remapping = settings->paths.directory_input_remapping;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
rarch_system_info_t *sys_info = &runloop_state_get_ptr()->system;
|
||||
const char *core_name = sys_info ? sys_info->info.library_name : NULL;
|
||||
const char *rarch_path_basename = path_get(RARCH_PATH_BASENAME);
|
||||
bool has_content = !string_is_empty(rarch_path_basename);
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *directory_input_remapping = settings->paths.directory_input_remapping;
|
||||
unsigned joypad_port = settings->uints.input_joypad_index[0];
|
||||
const char *input_device_name = input_config_get_device_display_name(joypad_port);
|
||||
const char *input_device_dir = NULL;
|
||||
char *remap_path = NULL;
|
||||
bool sort_remaps_by_controller = settings->bools.input_remap_sort_by_controller_enable;
|
||||
size_t remap_path_total_len = 0;
|
||||
size_t _len = 0;
|
||||
|
||||
content_dir_name[0] = '\0';
|
||||
remap_file_path[0] = '\0';
|
||||
@ -3659,11 +3666,41 @@ static int generic_action_ok_remap_file_operation(const char *path,
|
||||
if (string_is_empty(core_name))
|
||||
return -1;
|
||||
|
||||
if ( sort_remaps_by_controller
|
||||
&& input_device_name != NULL
|
||||
&& !string_is_empty(input_device_name))
|
||||
{
|
||||
/* Ensure directory does not contain special chars */
|
||||
input_device_dir = sanitize_path_part(input_device_name, strlen(input_device_name));
|
||||
|
||||
/* Allocate memory for the new path */
|
||||
remap_path_total_len = strlen(core_name) + strlen(input_device_dir) + 2;
|
||||
remap_path = (char *)malloc(remap_path_total_len);
|
||||
|
||||
/* Build the new path with the controller name */
|
||||
_len = strlcpy(remap_path, core_name, remap_path_total_len);
|
||||
_len += strlcpy(remap_path + _len, PATH_DEFAULT_SLASH(), remap_path_total_len - _len);
|
||||
_len += strlcpy(remap_path + _len, input_device_dir, remap_path_total_len - _len);
|
||||
|
||||
/* Deallocate as we no longer this */
|
||||
free((char*)input_device_dir);
|
||||
input_device_dir = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate memory for the new path */
|
||||
remap_path_total_len = strlen(core_name) + 1;
|
||||
remap_path = (char *)malloc(remap_path_total_len);
|
||||
|
||||
/* We're not using controller path, just use core name */
|
||||
strlcpy(remap_path, core_name, remap_path_total_len);
|
||||
}
|
||||
|
||||
switch (action_type)
|
||||
{
|
||||
case ACTION_OK_REMAP_FILE_SAVE_AS:
|
||||
fill_pathname_join_special_ext(remap_file_path,
|
||||
directory_input_remapping, core_name,
|
||||
directory_input_remapping, remap_path,
|
||||
path,
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(remap_file_path));
|
||||
@ -3671,7 +3708,7 @@ static int generic_action_ok_remap_file_operation(const char *path,
|
||||
case ACTION_OK_REMAP_FILE_SAVE_CORE:
|
||||
case ACTION_OK_REMAP_FILE_REMOVE_CORE:
|
||||
fill_pathname_join_special_ext(remap_file_path,
|
||||
directory_input_remapping, core_name,
|
||||
directory_input_remapping, remap_path,
|
||||
core_name,
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(remap_file_path));
|
||||
@ -3680,7 +3717,7 @@ static int generic_action_ok_remap_file_operation(const char *path,
|
||||
case ACTION_OK_REMAP_FILE_REMOVE_GAME:
|
||||
if (has_content)
|
||||
fill_pathname_join_special_ext(remap_file_path,
|
||||
directory_input_remapping, core_name,
|
||||
directory_input_remapping, remap_path,
|
||||
path_basename(rarch_path_basename),
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(remap_file_path));
|
||||
@ -3693,7 +3730,7 @@ static int generic_action_ok_remap_file_operation(const char *path,
|
||||
rarch_path_basename, sizeof(content_dir_name));
|
||||
|
||||
fill_pathname_join_special_ext(remap_file_path,
|
||||
directory_input_remapping, core_name,
|
||||
directory_input_remapping, remap_path,
|
||||
content_dir_name,
|
||||
FILE_PATH_REMAP_EXTENSION,
|
||||
sizeof(remap_file_path));
|
||||
@ -3701,6 +3738,8 @@ static int generic_action_ok_remap_file_operation(const char *path,
|
||||
break;
|
||||
}
|
||||
|
||||
free(remap_path);
|
||||
|
||||
if (action_type < ACTION_OK_REMAP_FILE_REMOVE_CORE)
|
||||
{
|
||||
if ( !string_is_empty(remap_file_path)
|
||||
|
@ -801,6 +801,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_autosave_interval, MENU_
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_replay_max_keep, MENU_ENUM_SUBLABEL_REPLAY_MAX_KEEP)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_replay_checkpoint_interval, MENU_ENUM_SUBLABEL_REPLAY_CHECKPOINT_INTERVAL)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_remap_binds_enable, MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_remap_sort_by_controller_enable, MENU_ENUM_SUBLABEL_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_autodetect_enable, MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE)
|
||||
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_nowinkey_enable, MENU_ENUM_SUBLABEL_INPUT_NOWINKEY_ENABLE)
|
||||
@ -3992,6 +3993,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_INPUT_REMAP_BINDS_ENABLE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_remap_binds_enable);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_remap_sort_by_controller_enable);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_AUTOSAVE_INTERVAL:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_autosave_interval);
|
||||
break;
|
||||
|
@ -7958,6 +7958,7 @@ unsigned menu_displaylist_build_list(
|
||||
{MENU_ENUM_LABEL_INPUT_MAX_USERS, PARSE_ONLY_UINT, true },
|
||||
{MENU_ENUM_LABEL_INPUT_AUTODETECT_ENABLE, PARSE_ONLY_BOOL, true },
|
||||
{MENU_ENUM_LABEL_INPUT_REMAP_BINDS_ENABLE, PARSE_ONLY_BOOL, true },
|
||||
{MENU_ENUM_LABEL_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE, PARSE_ONLY_BOOL, true },
|
||||
{MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR, PARSE_ONLY_UINT, true },
|
||||
{MENU_ENUM_LABEL_INPUT_ICADE_ENABLE, PARSE_ONLY_BOOL, true },
|
||||
{MENU_ENUM_LABEL_INPUT_SMALL_KEYBOARD_ENABLE, PARSE_ONLY_BOOL, true },
|
||||
|
@ -15671,6 +15671,22 @@ static bool setting_append_list(
|
||||
SD_FLAG_ADVANCED
|
||||
);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.input_remap_sort_by_controller_enable,
|
||||
MENU_ENUM_LABEL_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE,
|
||||
false,
|
||||
MENU_ENUM_LABEL_VALUE_OFF,
|
||||
MENU_ENUM_LABEL_VALUE_ON,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_ADVANCED
|
||||
);
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.input_autodetect_enable,
|
||||
|
@ -1292,6 +1292,7 @@ enum msg_hash_enums
|
||||
MENU_LABEL(INPUT_BIND_TIMEOUT),
|
||||
MENU_LABEL(INPUT_BIND_HOLD),
|
||||
MENU_LABEL(INPUT_REMAP_BINDS_ENABLE),
|
||||
MENU_LABEL(INPUT_REMAP_SORT_BY_CONTROLLER_ENABLE),
|
||||
MENU_LABEL(MENU_INPUT_SWAP_OK_CANCEL),
|
||||
MENU_LABEL(MENU_INPUT_SWAP_SCROLL),
|
||||
MENU_LABEL(INPUT_OVERLAY_ENABLE),
|
||||
|
Loading…
x
Reference in New Issue
Block a user