Skip to content

Commit

Permalink
Add support for mapping multiple controllers to a single input device
Browse files Browse the repository at this point in the history
  • Loading branch information
jdgleaver committed Jun 19, 2021
1 parent a129764 commit ad4e491
Show file tree
Hide file tree
Showing 23 changed files with 777 additions and 279 deletions.
56 changes: 41 additions & 15 deletions configuration.c
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

/* 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

/* 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 @@ -4617,9 +4613,6 @@ bool input_remapping_load_file(void *data, const char *path)
{
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,13 @@ 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();

return true;
}

Expand Down Expand Up @@ -4745,14 +4743,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 +4847,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
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
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
6 changes: 5 additions & 1 deletion input/input_remapping.h
Expand Up @@ -48,8 +48,12 @@ 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);
void input_remapping_cache_global_config(void);
void input_remapping_restore_global_config(void);

void input_remapping_update_port_map(void);

void input_remapping_deinit(void);
void input_remapping_set_defaults(void);

RETRO_END_DECLS
Expand Down
20 changes: 16 additions & 4 deletions intl/msg_hash_lbl.h
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
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
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
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
4 changes: 1 addition & 3 deletions menu/cbs/menu_cbs_ok.c
Expand Up @@ -3411,7 +3411,6 @@ static int generic_action_ok_remap_file_operation(const char *path,
{
if (input_remapping_remove_file(file, path_dir_input_remapping))
{
#ifdef HAVE_CONFIGFILE
switch (action_type)
{
case ACTION_OK_REMAP_FILE_REMOVE_CORE:
Expand All @@ -3436,7 +3435,6 @@ static int generic_action_ok_remap_file_operation(const char *path,
}
break;
}
#endif

runloop_msg_queue_push(
msg_hash_to_str(MSG_REMAP_FILE_REMOVED_SUCCESSFULLY),
Expand Down Expand Up @@ -6520,7 +6518,7 @@ static int action_ok_push_dropdown_item_input_device_index(const char *path,
if (!setting)
return menu_cbs_exit();

settings->uints.input_joypad_map[setting->index_offset] = (unsigned)entry_idx;
settings->uints.input_joypad_index[setting->index_offset] = (unsigned)entry_idx;

return action_cancel_pop_default(NULL, NULL, 0, 0);
}
Expand Down
13 changes: 9 additions & 4 deletions menu/cbs/menu_cbs_right.c
Expand Up @@ -177,13 +177,18 @@ static int action_right_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];

remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx];
for (bind_idx = 0; bind_idx < RARCH_ANALOG_BIND_LIST_END; bind_idx++)
Expand Down Expand Up @@ -221,7 +226,7 @@ static int action_right_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))
action_right_input_desc(type, label, wraparound);
}

Expand Down
4 changes: 2 additions & 2 deletions menu/cbs/menu_cbs_scan.c
Expand Up @@ -168,8 +168,8 @@ static int action_scan_input_desc(const char *path,
{
settings_t *settings = config_get_ptr();
inp_desc_user = atoi(label);
/* Skip 'Device Type' and 'Analog to Digital Type' */
key = (unsigned)(idx - 2);
/* Skip 'Device Type', 'Analog to Digital Type' and 'Mapped Port' */
key = (unsigned)(idx - 3);
/* Select the reorderer bind */
key =
(key < RARCH_ANALOG_BIND_LIST_END) ? input_config_bind_order[key] : key;
Expand Down

0 comments on commit ad4e491

Please sign in to comment.