@@ -5990,6 +5990,104 @@ static void input_keys_pressed(
59905990 input_st -> input_hotkey_block_counter = 0 ;
59915991}
59925992
5993+ /* Ignore d-pad buttons to avoid false positives.
5994+ * Some wireless gamepad receivers report 0 values for all axes when the
5995+ * gamepad is powered off or not yet connected. Since 0 represents the
5996+ * "left" and "up" positions for d-pad axes, this creates false button
5997+ * presses that could trigger unwanted input mapping.
5998+ */
5999+ static bool any_button_ex_dpad_pressed (int32_t state )
6000+ {
6001+ static const uint32_t button_mask =
6002+ (1 << RETRO_DEVICE_ID_JOYPAD_A ) |
6003+ (1 << RETRO_DEVICE_ID_JOYPAD_B ) |
6004+ (1 << RETRO_DEVICE_ID_JOYPAD_X ) |
6005+ (1 << RETRO_DEVICE_ID_JOYPAD_Y ) |
6006+ (1 << RETRO_DEVICE_ID_JOYPAD_L ) |
6007+ (1 << RETRO_DEVICE_ID_JOYPAD_R ) |
6008+ (1 << RETRO_DEVICE_ID_JOYPAD_L2 ) |
6009+ (1 << RETRO_DEVICE_ID_JOYPAD_R2 ) |
6010+ (1 << RETRO_DEVICE_ID_JOYPAD_L3 ) |
6011+ (1 << RETRO_DEVICE_ID_JOYPAD_R3 ) |
6012+ (1 << RETRO_DEVICE_ID_JOYPAD_START ) |
6013+ (1 << RETRO_DEVICE_ID_JOYPAD_SELECT );
6014+
6015+ return (state & button_mask ) != 0 ;
6016+ }
6017+
6018+ /* Returns MAX_USERS if all core ports are mapped to a user. */
6019+ static unsigned get_first_free_core_port (settings_t * settings )
6020+ {
6021+ unsigned core_port_idx ;
6022+ for (core_port_idx = 0 ; core_port_idx < MAX_USERS ; core_port_idx ++ )
6023+ {
6024+ unsigned * core_port_users = settings -> uints .input_remap_port_map [core_port_idx ];
6025+ if (core_port_users [0 ] == MAX_USERS )
6026+ return core_port_idx ;
6027+ }
6028+
6029+ return MAX_USERS ;
6030+ }
6031+
6032+ static void map_user_to_first_free_core_port (unsigned user_idx , settings_t * settings )
6033+ {
6034+ unsigned core_port_idx ;
6035+ unsigned joypad_idx ;
6036+ const char * device_display_name ;
6037+ char msg [128 ];
6038+
6039+ msg [0 ] = '\0' ;
6040+
6041+ if (!settings || user_idx >= MAX_USERS )
6042+ {
6043+ RARCH_ERR ("[Automap] Invalid parameters\n" );
6044+ return ;
6045+ }
6046+
6047+ /* Check if user is already mapped */
6048+ if (settings -> uints .input_remap_ports [user_idx ] < MAX_USERS )
6049+ {
6050+ RARCH_LOG ("[Automap] User %u already mapped to core port %u\n" ,
6051+ user_idx , settings -> uints .input_remap_ports [user_idx ]);
6052+ return ;
6053+ }
6054+
6055+ core_port_idx = get_first_free_core_port (settings );
6056+ joypad_idx = settings -> uints .input_joypad_index [user_idx ];
6057+ device_display_name = input_config_get_device_display_name (joypad_idx );
6058+
6059+ if (string_is_empty (device_display_name ))
6060+ device_display_name = msg_hash_to_str (MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE );
6061+
6062+ if (core_port_idx < MAX_USERS )
6063+ {
6064+ configuration_set_uint (settings ,
6065+ settings -> uints .input_remap_ports [user_idx ], core_port_idx );
6066+ configuration_set_uint (settings ,
6067+ settings -> uints .input_libretro_device [core_port_idx ], RETRO_DEVICE_JOYPAD );
6068+
6069+ input_remapping_update_port_map ();
6070+
6071+ RARCH_LOG ("[Automap] %s (user %u) mapped to core port %u\n" ,
6072+ device_display_name , user_idx , core_port_idx );
6073+
6074+ if (settings -> bools .notification_show_user_mapped_to_core_port )
6075+ {
6076+ snprintf (msg , sizeof (msg ),
6077+ msg_hash_to_str (MSG_USER_MAPPED_TO_CORE_PORT_NR ),
6078+ device_display_name ,
6079+ core_port_idx + 1 );
6080+ runloop_msg_queue_push (msg , strlen (msg ), 1 , 180 , true, NULL ,
6081+ MESSAGE_QUEUE_ICON_DEFAULT , MESSAGE_QUEUE_CATEGORY_INFO );
6082+ }
6083+ }
6084+ else
6085+ {
6086+ RARCH_LOG ("[Automap] No free core ports - %s (user %u) not mapped\n" ,
6087+ device_display_name , user_idx );
6088+ }
6089+ }
6090+
59936091void input_driver_poll (void )
59946092{
59956093 size_t i , j ;
@@ -6006,9 +6104,15 @@ void input_driver_poll(void)
60066104 * sec_joypad = NULL ;
60076105#endif
60086106 bool input_remap_binds_enable = settings -> bools .input_remap_binds_enable ;
6107+ bool input_remap_ports_on_button_press
6108+ = settings -> bools .input_remap_ports_on_button_press ;
60096109 float input_axis_threshold = settings -> floats .input_axis_threshold ;
60106110 uint8_t max_users = (uint8_t )settings -> uints .input_max_users ;
60116111
6112+ #ifdef HAVE_MENU
6113+ input_remap_ports_on_button_press = input_remap_ports_on_button_press && !(menu_state_get_ptr ()-> flags & MENU_ST_FLAG_ALIVE );
6114+ #endif
6115+
60126116 if (joypad && joypad -> poll )
60136117 joypad -> poll ();
60146118 if (sec_joypad && sec_joypad -> poll )
@@ -6040,6 +6144,22 @@ void input_driver_poll(void)
60406144 joypad_info [i ].joy_idx = settings -> uints .input_joypad_index [i ];
60416145 joypad_info [i ].auto_binds = input_autoconf_binds [joypad_info [i ].joy_idx ];
60426146
6147+ if (input_remap_ports_on_button_press )
6148+ {
6149+ if (!(settings -> uints .input_remap_ports [i ] < MAX_USERS ))
6150+ {
6151+ int32_t buttons_st = input_state_wrap (input_st -> current_driver , input_st -> current_data ,
6152+ joypad , sec_joypad , & joypad_info [i ],
6153+ (* input_st -> libretro_input_binds ),
6154+ (input_st -> flags & INP_FLAG_KB_MAPPING_BLOCKED ) ? true : false,
6155+ (unsigned )i ,
6156+ RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_MASK );
6157+
6158+ if (any_button_ex_dpad_pressed (buttons_st ))
6159+ map_user_to_first_free_core_port (i , settings );
6160+ }
6161+ }
6162+
60436163 input_st -> turbo_btns .frame_enable [i ] =
60446164 (* input_st -> libretro_input_binds [i ])[button_id ].valid
60456165 && settings -> bools .input_turbo_enable ?
@@ -6672,6 +6792,11 @@ void input_remapping_update_port_map(void)
66726792 port_map_index [remap_port ]++ ;
66736793 }
66746794 }
6795+
6796+ /* Changing mapped port may leave a core port unused;
6797+ * reinitialise controllers to ensure that any such
6798+ * ports are set to 'RETRO_DEVICE_NONE' */
6799+ command_event (CMD_EVENT_CONTROLLER_INIT , NULL );
66756800}
66766801
66776802void input_remapping_deinit (bool save_remap )
@@ -6690,6 +6815,29 @@ void input_remapping_deinit(bool save_remap)
66906815 | RUNLOOP_FLAG_REMAPS_GAME_ACTIVE );
66916816}
66926817
6818+ void input_remapping_set_remap_ports_defaults (void )
6819+ {
6820+ unsigned i ;
6821+ settings_t * settings = config_get_ptr ();
6822+ bool remap_on_button_press = settings -> bools .input_remap_ports_on_button_press ;
6823+
6824+ for (i = 0 ; i < MAX_USERS ; i ++ )
6825+ {
6826+ configuration_set_uint (settings ,
6827+ settings -> uints .input_remap_ports [i ],
6828+ remap_on_button_press ? MAX_USERS : i );
6829+
6830+ configuration_set_uint (settings ,
6831+ settings -> uints .input_libretro_device [i ],
6832+ remap_on_button_press ? RETRO_DEVICE_NONE : RETRO_DEVICE_JOYPAD );
6833+ }
6834+
6835+ /* Need to call 'input_remapping_update_port_map()'
6836+ * whenever 'settings->uints.input_remap_ports'
6837+ * is modified */
6838+ input_remapping_update_port_map ();
6839+ }
6840+
66936841void input_remapping_set_defaults (bool clear_cache )
66946842{
66956843 unsigned i , j ;
@@ -6714,16 +6862,9 @@ void input_remapping_set_defaults(bool clear_cache)
67146862 for (j = RARCH_FIRST_CUSTOM_BIND ; j < (RARCH_FIRST_CUSTOM_BIND + 8 ); j ++ )
67156863 configuration_set_uint (settings ,
67166864 settings -> uints .input_remap_ids [i ][j ], j );
6717-
6718- /* Controller port remaps */
6719- configuration_set_uint (settings ,
6720- settings -> uints .input_remap_ports [i ], i );
67216865 }
67226866
6723- /* Need to call 'input_remapping_update_port_map()'
6724- * whenever 'settings->uints.input_remap_ports'
6725- * is modified */
6726- input_remapping_update_port_map ();
6867+ input_remapping_set_remap_ports_defaults ();
67276868
67286869 /* Restore 'global' settings that were cached on
67296870 * the last core init
0 commit comments