Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for mapping multiple controllers to a single input device #12534

Merged
merged 1 commit into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 49 additions & 18 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -2435,10 +2435,8 @@ void config_set_defaults(void *data)
#endif

input_config_reset();
#ifdef HAVE_CONFIGFILE
input_remapping_deinit();
input_remapping_set_defaults();
#endif
input_remapping_set_defaults(false);

/* Verify that binds are in proper order. */
for (i = 0; i < MAX_USERS; i++)
Expand All @@ -2461,7 +2459,7 @@ void config_set_defaults(void *data)

for (i = 0; i < MAX_USERS; i++)
{
settings->uints.input_joypad_map[i] = i;
settings->uints.input_joypad_index[i] = i;
#ifdef SWITCH /* Switch prefered default dpad mode */
settings->uints.input_analog_dpad_mode[i] = ANALOG_DPAD_LSTICK;
#else
Expand Down Expand Up @@ -3196,7 +3194,7 @@ static bool config_load_file(global_t *global,
buf[0] = '\0';

snprintf(buf, sizeof(buf), "input_player%u_joypad_index", i + 1);
CONFIG_GET_INT_BASE(conf, settings, uints.input_joypad_map[i], buf);
CONFIG_GET_INT_BASE(conf, settings, uints.input_joypad_index[i], buf);

snprintf(buf, sizeof(buf), "input_player%u_analog_dpad_mode", i + 1);
CONFIG_GET_INT_BASE(conf, settings, uints.input_analog_dpad_mode[i], buf);
Expand Down Expand Up @@ -3856,9 +3854,7 @@ bool config_load_remap(const char *directory_input_remapping,
FILE_PATH_REMAP_EXTENSION,
sizeof(game_path));

#ifdef HAVE_CONFIGFILE
input_remapping_set_defaults();
#endif
input_remapping_set_defaults(false);

/* If a game remap file exists, load it. */
if ((new_conf = config_file_new_from_path_to_string(game_path)))
Expand Down Expand Up @@ -4229,7 +4225,7 @@ bool config_save_file(const char *path)
snprintf(cfg, sizeof(cfg), "input_device_p%u", i + 1);
config_set_int(conf, cfg, settings->uints.input_device[i]);
snprintf(cfg, sizeof(cfg), "input_player%u_joypad_index", i + 1);
config_set_int(conf, cfg, settings->uints.input_joypad_map[i]);
config_set_int(conf, cfg, settings->uints.input_joypad_index[i]);
snprintf(cfg, sizeof(cfg), "input_libretro_device_p%u", i + 1);
config_set_int(conf, cfg, input_config_get_device(i));
snprintf(cfg, sizeof(cfg), "input_player%u_analog_dpad_mode", i + 1);
Expand Down Expand Up @@ -4492,11 +4488,11 @@ bool config_save_overrides(enum override_type type, void *data)
config_set_int(conf, cfg, overrides->uints.input_device[i]);
}

if (settings->uints.input_joypad_map[i]
!= overrides->uints.input_joypad_map[i])
if (settings->uints.input_joypad_index[i]
!= overrides->uints.input_joypad_index[i])
{
snprintf(cfg, sizeof(cfg), "input_player%u_joypad_index", i + 1);
config_set_int(conf, cfg, overrides->uints.input_joypad_map[i]);
config_set_int(conf, cfg, overrides->uints.input_joypad_index[i]);
}
}

Expand Down Expand Up @@ -4609,17 +4605,14 @@ bool input_remapping_load_file(void *data, const char *path)
if (!string_is_empty(global->name.remapfile))
{
input_remapping_deinit();
input_remapping_set_defaults();
input_remapping_set_defaults(false);
}
global->name.remapfile = strdup(path);

for (i = 0; i < MAX_USERS; i++)
{
char s1[32], s2[32], s3[32];

global->old_analog_dpad_mode[i] = settings->uints.input_analog_dpad_mode[i];
global->old_libretro_device[i] = settings->uints.input_libretro_device[i];

s1[0] = '\0';
s2[0] = '\0';
s3[0] = '\0';
Expand Down Expand Up @@ -4705,8 +4698,18 @@ bool input_remapping_load_file(void *data, const char *path)

snprintf(s1, sizeof(s1), "input_libretro_device_p%u", i + 1);
CONFIG_GET_INT_BASE(conf, settings, uints.input_libretro_device[i], s1);

snprintf(s1, sizeof(s1), "input_remap_port_p%u", i + 1);
CONFIG_GET_INT_BASE(conf, settings, uints.input_remap_ports[i], s1);
}

input_remapping_update_port_map();

/* Whenever a remap file is loaded, subsequent
* changes to global remap-related parameters
* must be reset at the next core deinitialisation */
input_remapping_enable_global_config_restore();

return true;
}

Expand Down Expand Up @@ -4745,14 +4748,38 @@ bool input_remapping_save_file(const char *path)
return false;
}

for (i = 0; i < max_users; i++)
for (i = 0; i < MAX_USERS; i++)
{
char s1[32], s2[32], s3[32];
bool skip_port = true;
char s1[32];
char s2[32];
char s3[32];

s1[0] = '\0';
s2[0] = '\0';
s3[0] = '\0';

/* We must include all mapped ports + all those
* with an index less than max_users */
if (i < max_users)
skip_port = false;
else
{
/* Check whether current port is mapped
* to an input device */
for (j = 0; j < max_users; j++)
{
if (i == settings->uints.input_remap_ports[j])
{
skip_port = false;
break;
}
}
}

if (skip_port)
continue;

snprintf(s1, sizeof(s1), "input_player%u_btn", i + 1);
snprintf(s2, sizeof(s2), "input_player%u_key", i + 1);
snprintf(s3, sizeof(s3), "input_player%u_stk", i + 1);
Expand Down Expand Up @@ -4825,8 +4852,12 @@ bool input_remapping_save_file(const char *path)

snprintf(s1, sizeof(s1), "input_libretro_device_p%u", i + 1);
config_set_int(conf, s1, input_config_get_device(i));

snprintf(s1, sizeof(s1), "input_player%u_analog_dpad_mode", i + 1);
config_set_int(conf, s1, settings->uints.input_analog_dpad_mode[i]);

snprintf(s1, sizeof(s1), "input_remap_port_p%u", i + 1);
config_set_int(conf, s1, settings->uints.input_remap_ports[i]);
}

ret = config_file_write(conf, remap_file, true);
Expand Down
7 changes: 4 additions & 3 deletions configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,18 @@ typedef struct settings
unsigned placeholder;

unsigned input_split_joycon[MAX_USERS];
unsigned input_joypad_map[MAX_USERS];
unsigned input_joypad_index[MAX_USERS];
unsigned input_device[MAX_USERS];
unsigned input_mouse_index[MAX_USERS];
/* Set by autoconfiguration in joypad_autoconfig_dir.
* Does not override main binds. */
unsigned input_libretro_device[MAX_USERS];
unsigned input_analog_dpad_mode[MAX_USERS];

unsigned input_keymapper_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];

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_port_map[MAX_USERS][MAX_USERS + 1];

unsigned led_map[MAX_LEDS];

Expand Down
4 changes: 2 additions & 2 deletions input/drivers_joypad/gx_joypad.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ static void handle_hotplug(unsigned port, uint32_t ptype)
static void check_port0_active(uint8_t pad_count)
{
settings_t *settings = config_get_ptr();
int idx = settings->uints.input_joypad_map[0];
int idx = settings->uints.input_joypad_index[0];

if(pad_count < 2 && idx != 0)
{
Expand All @@ -229,7 +229,7 @@ static void check_port0_active(uint8_t pad_count)
#else
pad_type[0] = WPAD_EXP_GAMECUBE;
#endif
settings->uints.input_joypad_map[0] = 0;
settings->uints.input_joypad_index[0] = 0;

input_autoconfigure_connect(
gx_joypad_name(0),
Expand Down
28 changes: 26 additions & 2 deletions input/input_remapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,33 @@ bool input_remapping_save_file(const char *path);
bool input_remapping_remove_file(const char *path,
const char *dir_input_remapping);

void input_remapping_deinit(void);
/* Caches any global configuration settings that
* should not be overwritten by input remap
* changes made while content is running.
* Must be called on each core init. */
void input_remapping_cache_global_config(void);
/* Sets flags to enable the restoration of
* global configuration settings from the
* internal cache. Should be called independently
* from 'input_remapping_cache_global_config()'.
* Must be called:
* - Whenever content is loaded
* - Whenever a remap file is loaded */
void input_remapping_enable_global_config_restore(void);
/* Restores any cached global configuration settings
* *if* 'input_remapping_enable_global_config_restore()'
* has been called.
* Must be called on core deint.
* If 'clear_cache' is true, function becomes a NOOP
* until the next time input_remapping_cache_global_config()
* and input_remapping_enable_global_config_restore()
* are called. */
void input_remapping_restore_global_config(bool clear_cache);

void input_remapping_update_port_map(void);

void input_remapping_set_defaults(void);
void input_remapping_deinit(void);
void input_remapping_set_defaults(bool clear_cache);

RETRO_END_DECLS

Expand Down
20 changes: 16 additions & 4 deletions intl/msg_hash_lbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1490,6 +1490,22 @@ MSG_HASH(
MENU_ENUM_LABEL_INPUT_LIBRETRO_DEVICE,
"input_libretro_device_p%u"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE,
"input_player%u_analog_dpad_mode"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_DEVICE_INDEX,
"input_device_p%u"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_MOUSE_INDEX,
"input_player%u_mouse_index"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_REMAP_PORT,
"input_remap_port_p%u"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_MAX_USERS,
"input_max_users"
Expand Down Expand Up @@ -1534,10 +1550,6 @@ MSG_HASH(
MENU_ENUM_LABEL_INPUT_OVERLAY_AUTO_SCALE,
"input_overlay_auto_scale"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE,
"input_player%u_analog_dpad_mode"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR,
"input_poll_type_behavior"
Expand Down
8 changes: 8 additions & 0 deletions intl/msg_hash_us.h
Original file line number Diff line number Diff line change
Expand Up @@ -2668,6 +2668,14 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_INDEX,
"Device Index"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_REMAP_PORT,
"Mapped Port"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_REMAP_PORT,
"Specifies which 'core' port (typically player number) will receive input from frontend controller port %u."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_BIND_ALL,
"Set All Controls"
Expand Down
21 changes: 10 additions & 11 deletions menu/cbs/menu_cbs_get_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,20 +709,20 @@ static void menu_action_setting_disp_set_label_input_desc(
char *s2, size_t len2)
{
unsigned remap_idx;
settings_t *settings = config_get_ptr();
const char* descriptor = NULL;
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 mapped_port;
settings_t *settings = config_get_ptr();
const char* descriptor = NULL;
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;

if (!settings)
return;

remap_idx =
settings->uints.input_remap_ids[user_idx][btn_idx];
mapped_port = settings->uints.input_remap_ports[user_idx];
remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx];

if (remap_idx != RARCH_UNMAPPED)
descriptor =
runloop_get_system_info()->input_desc_btn[user_idx][remap_idx];
descriptor = runloop_get_system_info()->input_desc_btn[mapped_port][remap_idx];

s[0] = '-';
s[1] = '-';
Expand Down Expand Up @@ -754,7 +754,7 @@ static void menu_action_setting_disp_set_label_input_desc_kbd(
char desc[PATH_MAX_LENGTH];
unsigned key_id, btn_idx;
unsigned remap_id;
unsigned user_idx = 0;
unsigned user_idx;

settings_t *settings = config_get_ptr();

Expand All @@ -763,8 +763,7 @@ static void menu_action_setting_disp_set_label_input_desc_kbd(

user_idx = (type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) / RARCH_ANALOG_BIND_LIST_END;
btn_idx = (type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) - RARCH_ANALOG_BIND_LIST_END * user_idx;
remap_id =
settings->uints.input_keymapper_ids[user_idx][btn_idx];
remap_id = settings->uints.input_keymapper_ids[user_idx][btn_idx];

for (key_id = 0; key_id < RARCH_MAX_KEYS - 1; key_id++)
{
Expand Down
13 changes: 9 additions & 4 deletions menu/cbs/menu_cbs_left.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,18 @@ static int action_left_input_desc(unsigned type, const char *label,
{
rarch_system_info_t *system = runloop_get_system_info();
settings_t *settings = config_get_ptr();
unsigned btn_idx, user_idx, remap_idx, bind_idx;
unsigned btn_idx;
unsigned user_idx;
unsigned remap_idx;
unsigned bind_idx;
unsigned mapped_port;

if (!settings || !system)
return 0;

user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8);
btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx;
user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8);
btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx;
mapped_port = settings->uints.input_remap_ports[user_idx];

if (settings->uints.input_remap_ids[user_idx][btn_idx] == RARCH_UNMAPPED)
settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_CUSTOM_BIND_LIST_END - 1;
Expand Down Expand Up @@ -176,7 +181,7 @@ static int action_left_input_desc(unsigned type, const char *label,
also skip all the axes until analog remapping is implemented */
if (remap_idx != RARCH_UNMAPPED)
{
if ((string_is_empty(system->input_desc_btn[user_idx][remap_idx]) && remap_idx < RARCH_CUSTOM_BIND_LIST_END) /*||
if ((string_is_empty(system->input_desc_btn[mapped_port][remap_idx]) && remap_idx < RARCH_CUSTOM_BIND_LIST_END) /*||
(remap_idx >= RARCH_FIRST_CUSTOM_BIND && remap_idx < RARCH_CUSTOM_BIND_LIST_END)*/)
action_left_input_desc(type, label, wraparound);
}
Expand Down
Loading