New feature: Use gamepad combo to quit Retroarch (#13017)

* Refactor menu toggle combo button logic to allow quit combo button

* Quit gamepad combo

* Fixes from @jdgleaver
This commit is contained in:
Ben Hamilton (Ben Gertzfield) 2021-09-24 10:30:46 -06:00 committed by GitHub
parent 50bb7afa9d
commit 1970786932
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 172 additions and 82 deletions

View file

@ -801,21 +801,23 @@ static const bool default_systemfiles_in_content_dir = false;
static const bool default_screenshots_in_content_dir = false;
#if defined(RS90) || defined(RETROFW)
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_START_SELECT
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_START_SELECT
#elif defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_L3_R3
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_L3_R3
#elif defined(PS2) || defined(PSP)
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_HOLD_START
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_HOLD_START
#elif defined(VITA)
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_L1_R1_START_SELECT
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_L1_R1_START_SELECT
#elif defined(SWITCH) || defined(ORBIS)
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_START_SELECT
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_START_SELECT
#elif TARGET_OS_TV
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_DOWN_Y_L_R
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_DOWN_Y_L_R
#else
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_NONE
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_NONE
#endif
#define DEFAULT_QUIT_GAMEPAD_COMBO INPUT_COMBO_NONE
#if defined(VITA)
static const unsigned input_backtouch_enable = false;
static const unsigned input_backtouch_toggle = false;

View file

@ -2075,6 +2075,7 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("fps_update_interval", &settings->uints.fps_update_interval, true, DEFAULT_FPS_UPDATE_INTERVAL, false);
SETTING_UINT("memory_update_interval", &settings->uints.memory_update_interval, true, DEFAULT_MEMORY_UPDATE_INTERVAL, false);
SETTING_UINT("input_menu_toggle_gamepad_combo", &settings->uints.input_menu_toggle_gamepad_combo, true, DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO, false);
SETTING_UINT("input_quit_gamepad_combo", &settings->uints.input_quit_gamepad_combo, true, DEFAULT_QUIT_GAMEPAD_COMBO, false);
SETTING_UINT("input_hotkey_block_delay", &settings->uints.input_hotkey_block_delay, true, DEFAULT_INPUT_HOTKEY_BLOCK_DELAY, false);
#ifdef GEKKO
SETTING_UINT("input_mouse_scale", &settings->uints.input_mouse_scale, true, DEFAULT_MOUSE_SCALE, false);

View file

@ -187,6 +187,7 @@ typedef struct settings
#endif
unsigned input_touch_scale;
unsigned input_hotkey_block_delay;
unsigned input_quit_gamepad_combo;
unsigned input_menu_toggle_gamepad_combo;
unsigned input_keyboard_gamepad_mapping_type;
unsigned input_poll_type_behavior;

View file

@ -135,20 +135,20 @@ enum analog_dpad_mode
ANALOG_DPAD_LAST
};
enum input_toggle_type
enum input_combo_type
{
INPUT_TOGGLE_NONE = 0,
INPUT_TOGGLE_DOWN_Y_L_R,
INPUT_TOGGLE_L3_R3,
INPUT_TOGGLE_L1_R1_START_SELECT,
INPUT_TOGGLE_START_SELECT,
INPUT_TOGGLE_L3_R,
INPUT_TOGGLE_L_R,
INPUT_TOGGLE_HOLD_START,
INPUT_TOGGLE_HOLD_SELECT,
INPUT_TOGGLE_DOWN_SELECT,
INPUT_TOGGLE_L2_R2,
INPUT_TOGGLE_LAST
INPUT_COMBO_NONE = 0,
INPUT_COMBO_DOWN_Y_L_R,
INPUT_COMBO_L3_R3,
INPUT_COMBO_L1_R1_START_SELECT,
INPUT_COMBO_START_SELECT,
INPUT_COMBO_L3_R,
INPUT_COMBO_L_R,
INPUT_COMBO_HOLD_START,
INPUT_COMBO_HOLD_SELECT,
INPUT_COMBO_DOWN_SELECT,
INPUT_COMBO_L2_R2,
INPUT_COMBO_LAST
};
enum input_turbo_mode

View file

@ -21,6 +21,7 @@
#include <string/stdstring.h>
#include <encodings/utf.h>
#include <clamping.h>
#include <retro_assert.h>
#include "input_driver.h"
#include "input_keymaps.h"
@ -457,136 +458,140 @@ static const input_device_driver_t *input_joypad_init_first(void *data)
return NULL;
}
bool input_driver_toggle_button_combo(
bool input_driver_button_combo(
input_driver_state_t *input_driver_state,
unsigned mode,
retro_time_t current_time,
input_bits_t* p_input)
{
retro_assert(input_driver_state != NULL);
retro_assert(p_input != NULL);
switch (mode)
{
case INPUT_TOGGLE_DOWN_Y_L_R:
case INPUT_COMBO_DOWN_Y_L_R:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_DOWN) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_Y) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_L) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_R))
return true;
break;
case INPUT_TOGGLE_L3_R3:
case INPUT_COMBO_L3_R3:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_L3) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_R3))
return true;
break;
case INPUT_TOGGLE_L1_R1_START_SELECT:
case INPUT_COMBO_L1_R1_START_SELECT:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_L) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_R) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_START) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_SELECT))
return true;
break;
case INPUT_TOGGLE_START_SELECT:
case INPUT_COMBO_START_SELECT:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_START) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_SELECT))
return true;
break;
case INPUT_TOGGLE_L3_R:
case INPUT_COMBO_L3_R:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_L3) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_R))
return true;
break;
case INPUT_TOGGLE_L_R:
case INPUT_COMBO_L_R:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_L) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_R))
return true;
break;
case INPUT_TOGGLE_DOWN_SELECT:
case INPUT_COMBO_DOWN_SELECT:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_DOWN) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_SELECT))
return true;
break;
case INPUT_TOGGLE_L2_R2:
case INPUT_COMBO_L2_R2:
if (BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_L2) &&
BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_R2))
return true;
break;
case INPUT_TOGGLE_HOLD_START:
case INPUT_COMBO_HOLD_START:
{
static rarch_timer_t timer = {0};
rarch_timer_t *timer = &input_driver_state->combo_timers[INPUT_COMBO_HOLD_START];
if (!BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_START))
{
/* timer only runs while start is held down */
timer.timer_end = true;
timer.timer_begin = false;
timer.timeout_end = 0;
timer->timer_end = true;
timer->timer_begin = false;
timer->timeout_end = 0;
return false;
}
/* User started holding down the start button, start the timer */
if (!timer.timer_begin)
if (!timer->timer_begin)
{
uint64_t current_usec = cpu_features_get_time_usec();
timer.timeout_us = HOLD_BTN_DELAY_SEC * 1000000;
timer.current = current_usec;
timer.timeout_end = timer.current + timer.timeout_us;
timer.timer_begin = true;
timer.timer_end = false;
timer->timeout_us = HOLD_BTN_DELAY_SEC * 1000000;
timer->current = current_usec;
timer->timeout_end = timer->current + timer->timeout_us;
timer->timer_begin = true;
timer->timer_end = false;
}
timer.current = current_time;
timer.timeout_us = (timer.timeout_end - timer.current);
timer->current = current_time;
timer->timeout_us = (timer->timeout_end - timer->current);
if (!timer.timer_end && (timer.timeout_us <= 0))
if (!timer->timer_end && (timer->timeout_us <= 0))
{
/* start has been held down long enough,
* stop timer and enter menu */
timer.timer_end = true;
timer.timer_begin = false;
timer.timeout_end = 0;
timer->timer_end = true;
timer->timer_begin = false;
timer->timeout_end = 0;
return true;
}
}
break;
case INPUT_TOGGLE_HOLD_SELECT:
case INPUT_COMBO_HOLD_SELECT:
{
static rarch_timer_t timer = {0};
rarch_timer_t *timer = &input_driver_state->combo_timers[INPUT_COMBO_HOLD_SELECT];
if (!BIT256_GET_PTR(p_input, RETRO_DEVICE_ID_JOYPAD_SELECT))
{
/* timer only runs while select is held down */
timer.timer_end = true;
timer.timer_begin = false;
timer.timeout_end = 0;
timer->timer_end = true;
timer->timer_begin = false;
timer->timeout_end = 0;
return false;
}
/* user started holding down the select button, start the timer */
if (!timer.timer_begin)
if (!timer->timer_begin)
{
uint64_t current_usec = cpu_features_get_time_usec();
timer.timeout_us = HOLD_BTN_DELAY_SEC * 1000000;
timer.current = current_usec;
timer.timeout_end = timer.current + timer.timeout_us;
timer.timer_begin = true;
timer.timer_end = false;
timer->timeout_us = HOLD_BTN_DELAY_SEC * 1000000;
timer->current = current_usec;
timer->timeout_end = timer->current + timer->timeout_us;
timer->timer_begin = true;
timer->timer_end = false;
}
timer.current = current_time;
timer.timeout_us = (timer.timeout_end - timer.current);
timer->current = current_time;
timer->timeout_us = (timer->timeout_end - timer->current);
if (!timer.timer_end && (timer.timeout_us <= 0))
if (!timer->timer_end && (timer->timeout_us <= 0))
{
/* select has been held down long enough,
* stop timer and enter menu */
timer.timer_end = true;
timer.timer_begin = false;
timer.timeout_end = 0;
timer->timer_end = true;
timer->timer_begin = false;
timer->timeout_end = 0;
return true;
}
}
break;
default:
case INPUT_TOGGLE_NONE:
case INPUT_COMBO_NONE:
break;
}

View file

@ -43,6 +43,7 @@
#include "include/hid_driver.h"
#include "include/gamepad.h"
#include "../configuration.h"
#include "../performance_counters.h"
RETRO_BEGIN_DECLS
@ -356,6 +357,11 @@ typedef struct
/* primitives */
bool nonblocking_flag;
/**
* Array of timers, one for each entry in enum input_combo_type.
*/
rarch_timer_t combo_timers[INPUT_COMBO_LAST];
} input_driver_state_t;
@ -718,7 +724,8 @@ char *input_config_get_device_name_ptr(unsigned port);
*/
size_t input_config_get_device_name_size(unsigned port);
bool input_driver_toggle_button_combo(
bool input_driver_button_combo(
input_driver_state_t *input_driver_state,
unsigned mode,
retro_time_t current_time,
input_bits_t* p_input);

View file

@ -1534,6 +1534,10 @@ MSG_HASH(
MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO,
"input_menu_toggle_gamepad_combo"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_QUIT_GAMEPAD_COMBO,
"input_quit_gamepad_combo"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_OVERLAY,
"input_overlay"

View file

@ -2011,6 +2011,16 @@ int msg_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
"2 - Press L3 + R3 simultaneously. \n"
"3 - Press Start + Select simultaneously.");
break;
case MENU_ENUM_LABEL_INPUT_QUIT_GAMEPAD_COMBO:
snprintf(s, len,
"Gamepad button combination to quit. \n"
" \n"
"0 - None \n"
"1 - Press L + R + Y + D-Pad Down \n"
"simultaneously. \n"
"2 - Press L3 + R3 simultaneously. \n"
"3 - Press Start + Select simultaneously.");
break;
case MENU_ENUM_LABEL_INPUT_ALL_USERS_CONTROL_MENU:
snprintf(s, len, "Allows any user to control the menu. \n"
" \n"

View file

@ -2416,6 +2416,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO,
"Controller button combination to toggle menu."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_QUIT_GAMEPAD_COMBO,
"Quit Controller Combo"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_QUIT_GAMEPAD_COMBO,
"Controller button combination to quit RetroArch."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BLOCK_DELAY,
"Hotkey Enable Delay (Frames)"

View file

@ -316,6 +316,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_shader_delay, MENU_
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_black_frame_insertion, MENU_ENUM_SUBLABEL_VIDEO_BLACK_FRAME_INSERTION)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_systeminfo_cpu_cores, MENU_ENUM_SUBLABEL_CPU_CORES)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_toggle_gamepad_combo, MENU_ENUM_SUBLABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_quit_gamepad_combo, MENU_ENUM_SUBLABEL_INPUT_QUIT_GAMEPAD_COMBO)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_show_hidden_files, MENU_ENUM_SUBLABEL_SHOW_HIDDEN_FILES)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_log_verbosity, MENU_ENUM_SUBLABEL_LOG_VERBOSITY)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_log_to_file, MENU_ENUM_SUBLABEL_LOG_TO_FILE)
@ -3783,6 +3784,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_toggle_gamepad_combo);
break;
case MENU_ENUM_LABEL_INPUT_QUIT_GAMEPAD_COMBO:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_quit_gamepad_combo);
break;
case MENU_ENUM_LABEL_CPU_CORES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_systeminfo_cpu_cores);
break;

View file

@ -5626,6 +5626,10 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO,
PARSE_ONLY_UINT, false) == 0)
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_INPUT_QUIT_GAMEPAD_COMBO,
PARSE_ONLY_UINT, false) == 0)
count++;
/* Hotkey enable bind comes first - due to the
* way binds are implemented, have to search the

View file

@ -6477,7 +6477,7 @@ static void setting_get_string_representation_netplay_share_analog(
}
#endif
static void setting_get_string_representation_toggle_gamepad_combo(
static void setting_get_string_representation_gamepad_combo(
rarch_setting_t *setting,
char *s, size_t len)
{
@ -6486,37 +6486,37 @@ static void setting_get_string_representation_toggle_gamepad_combo(
switch (*setting->value.target.unsigned_integer)
{
case INPUT_TOGGLE_NONE:
case INPUT_COMBO_NONE:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE), len);
break;
case INPUT_TOGGLE_DOWN_Y_L_R:
case INPUT_COMBO_DOWN_Y_L_R:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWN_Y_L_R), len);
break;
case INPUT_TOGGLE_L3_R3:
case INPUT_COMBO_L3_R3:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L3_R3), len);
break;
case INPUT_TOGGLE_L1_R1_START_SELECT:
case INPUT_COMBO_L1_R1_START_SELECT:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L1_R1_START_SELECT), len);
break;
case INPUT_TOGGLE_START_SELECT:
case INPUT_COMBO_START_SELECT:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_START_SELECT), len);
break;
case INPUT_TOGGLE_L3_R:
case INPUT_COMBO_L3_R:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L3_R), len);
break;
case INPUT_TOGGLE_L_R:
case INPUT_COMBO_L_R:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L_R), len);
break;
case INPUT_TOGGLE_HOLD_START:
case INPUT_COMBO_HOLD_START:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HOLD_START), len);
break;
case INPUT_TOGGLE_HOLD_SELECT:
case INPUT_COMBO_HOLD_SELECT:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HOLD_SELECT), len);
break;
case INPUT_TOGGLE_DOWN_SELECT:
case INPUT_COMBO_DOWN_SELECT:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWN_SELECT), len);
break;
case INPUT_TOGGLE_L2_R2:
case INPUT_COMBO_L2_R2:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L2_R2), len);
break;
}
@ -13089,8 +13089,25 @@ static bool setting_append_list(
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_toggle_gamepad_combo;
menu_settings_list_current_add_range(list, list_info, 0, (INPUT_TOGGLE_LAST-1), 1, true, true);
&setting_get_string_representation_gamepad_combo;
menu_settings_list_current_add_range(list, list_info, 0, (INPUT_COMBO_LAST-1), 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.input_quit_gamepad_combo,
MENU_ENUM_LABEL_INPUT_QUIT_GAMEPAD_COMBO,
MENU_ENUM_LABEL_VALUE_INPUT_QUIT_GAMEPAD_COMBO,
DEFAULT_QUIT_GAMEPAD_COMBO,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_gamepad_combo;
menu_settings_list_current_add_range(list, list_info, 0, (INPUT_COMBO_LAST-1), 1, true, true);
CONFIG_UINT(
list, list_info,

View file

@ -976,6 +976,7 @@ enum msg_hash_enums
MENU_LABEL(INPUT_OVERLAY_ENABLE),
MENU_LABEL(INPUT_OSK_OVERLAY_ENABLE),
MENU_LABEL(INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO),
MENU_LABEL(INPUT_QUIT_GAMEPAD_COMBO),
MENU_LABEL(INPUT_OVERLAY_HIDE_IN_MENU),
MENU_LABEL(INPUT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED),
#if defined(ANDROID)

View file

@ -27951,6 +27951,7 @@ static enum runloop_state runloop_check_state(
struct menu_state *menu_st = menu_state_get_ptr();
menu_handle_t *menu = menu_st->driver_data;
unsigned menu_toggle_gamepad_combo = settings->uints.input_menu_toggle_gamepad_combo;
unsigned quit_gamepad_combo = settings->uints.input_quit_gamepad_combo;
bool menu_driver_binding_state = p_rarch->menu_driver_is_binding;
bool menu_is_alive = p_rarch->menu_driver_alive;
bool display_kb = menu_input_dialog_get_display_kb();
@ -28155,9 +28156,11 @@ static enum runloop_state runloop_check_state(
#ifdef HAVE_MENU
last_input = current_bits;
if (
((menu_toggle_gamepad_combo != INPUT_TOGGLE_NONE) &&
input_driver_toggle_button_combo(
menu_toggle_gamepad_combo, current_time,
((menu_toggle_gamepad_combo != INPUT_COMBO_NONE) &&
input_driver_button_combo(
input_driver_st,
menu_toggle_gamepad_combo,
current_time,
&last_input)))
BIT256_SET(current_bits, RARCH_MENU_TOGGLE);
@ -28324,6 +28327,15 @@ static enum runloop_state runloop_check_state(
quit_key = BIT256_GET(
current_bits, RARCH_QUIT_KEY);
trig_quit_key = quit_key && !old_quit_key;
/* Check for quit gamepad combo */
if (!trig_quit_key &&
((quit_gamepad_combo != INPUT_COMBO_NONE) &&
input_driver_button_combo(
input_driver_st,
quit_gamepad_combo,
current_time,
&current_bits)))
trig_quit_key = true;
old_quit_key = quit_key;
quit_press_twice = settings->bools.quit_press_twice;

View file

@ -653,6 +653,20 @@
# 10: L2 + R2
# input_menu_toggle_gamepad_combo = 0
# RetroPad button combination to quit
# 0: None
# 1: Down + Y + L1 + R1
# 2: L3 + R3
# 3: L1 + R1 + Start + Select
# 4: Start + Select
# 5: L3 + R1
# 6: L1 + R1
# 7: Hold Start (2 seconds)
# 8: Hold Select (2 seconds)
# 9: Down + Select
# 10: L2 + R2
# input_quit_gamepad_combo = 0
# allow any RetroPad to control the menu
# all_users_control_menu = false