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; static const bool default_screenshots_in_content_dir = false;
#if defined(RS90) || defined(RETROFW) #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) #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) #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) #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) #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 #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 #else
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_NONE #define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_COMBO_NONE
#endif #endif
#define DEFAULT_QUIT_GAMEPAD_COMBO INPUT_COMBO_NONE
#if defined(VITA) #if defined(VITA)
static const unsigned input_backtouch_enable = false; static const unsigned input_backtouch_enable = false;
static const unsigned input_backtouch_toggle = 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("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("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_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); SETTING_UINT("input_hotkey_block_delay", &settings->uints.input_hotkey_block_delay, true, DEFAULT_INPUT_HOTKEY_BLOCK_DELAY, false);
#ifdef GEKKO #ifdef GEKKO
SETTING_UINT("input_mouse_scale", &settings->uints.input_mouse_scale, true, DEFAULT_MOUSE_SCALE, false); 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 #endif
unsigned input_touch_scale; unsigned input_touch_scale;
unsigned input_hotkey_block_delay; unsigned input_hotkey_block_delay;
unsigned input_quit_gamepad_combo;
unsigned input_menu_toggle_gamepad_combo; unsigned input_menu_toggle_gamepad_combo;
unsigned input_keyboard_gamepad_mapping_type; unsigned input_keyboard_gamepad_mapping_type;
unsigned input_poll_type_behavior; unsigned input_poll_type_behavior;

View File

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

View File

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

View File

@ -43,6 +43,7 @@
#include "include/hid_driver.h" #include "include/hid_driver.h"
#include "include/gamepad.h" #include "include/gamepad.h"
#include "../configuration.h" #include "../configuration.h"
#include "../performance_counters.h"
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
@ -356,6 +357,11 @@ typedef struct
/* primitives */ /* primitives */
bool nonblocking_flag; 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; } 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); 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, unsigned mode,
retro_time_t current_time, retro_time_t current_time,
input_bits_t* p_input); input_bits_t* p_input);

View File

@ -1534,6 +1534,10 @@ MSG_HASH(
MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO,
"input_menu_toggle_gamepad_combo" "input_menu_toggle_gamepad_combo"
) )
MSG_HASH(
MENU_ENUM_LABEL_INPUT_QUIT_GAMEPAD_COMBO,
"input_quit_gamepad_combo"
)
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_INPUT_OVERLAY, MENU_ENUM_LABEL_INPUT_OVERLAY,
"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" "2 - Press L3 + R3 simultaneously. \n"
"3 - Press Start + Select simultaneously."); "3 - Press Start + Select simultaneously.");
break; 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: case MENU_ENUM_LABEL_INPUT_ALL_USERS_CONTROL_MENU:
snprintf(s, len, "Allows any user to control the menu. \n" snprintf(s, len, "Allows any user to control the menu. \n"
" \n" " \n"

View File

@ -2416,6 +2416,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, MENU_ENUM_SUBLABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO,
"Controller button combination to toggle menu." "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( MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BLOCK_DELAY, MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BLOCK_DELAY,
"Hotkey Enable Delay (Frames)" "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_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_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_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_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_verbosity, MENU_ENUM_SUBLABEL_LOG_VERBOSITY)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_log_to_file, MENU_ENUM_SUBLABEL_LOG_TO_FILE) 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: case MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_toggle_gamepad_combo); BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_toggle_gamepad_combo);
break; 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: case MENU_ENUM_LABEL_CPU_CORES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_systeminfo_cpu_cores); BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_systeminfo_cpu_cores);
break; break;

View File

@ -5626,6 +5626,10 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO,
PARSE_ONLY_UINT, false) == 0) PARSE_ONLY_UINT, false) == 0)
count++; 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 /* Hotkey enable bind comes first - due to the
* way binds are implemented, have to search 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 #endif
static void setting_get_string_representation_toggle_gamepad_combo( static void setting_get_string_representation_gamepad_combo(
rarch_setting_t *setting, rarch_setting_t *setting,
char *s, size_t len) char *s, size_t len)
{ {
@ -6486,37 +6486,37 @@ static void setting_get_string_representation_toggle_gamepad_combo(
switch (*setting->value.target.unsigned_integer) 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); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE), len);
break; 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); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWN_Y_L_R), len);
break; break;
case INPUT_TOGGLE_L3_R3: case INPUT_COMBO_L3_R3:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L3_R3), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L3_R3), len);
break; 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); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L1_R1_START_SELECT), len);
break; break;
case INPUT_TOGGLE_START_SELECT: case INPUT_COMBO_START_SELECT:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_START_SELECT), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_START_SELECT), len);
break; break;
case INPUT_TOGGLE_L3_R: case INPUT_COMBO_L3_R:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L3_R), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L3_R), len);
break; break;
case INPUT_TOGGLE_L_R: case INPUT_COMBO_L_R:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L_R), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L_R), len);
break; break;
case INPUT_TOGGLE_HOLD_START: case INPUT_COMBO_HOLD_START:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HOLD_START), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HOLD_START), len);
break; break;
case INPUT_TOGGLE_HOLD_SELECT: case INPUT_COMBO_HOLD_SELECT:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HOLD_SELECT), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HOLD_SELECT), len);
break; break;
case INPUT_TOGGLE_DOWN_SELECT: case INPUT_COMBO_DOWN_SELECT:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWN_SELECT), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWN_SELECT), len);
break; break;
case INPUT_TOGGLE_L2_R2: case INPUT_COMBO_L2_R2:
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L2_R2), len); strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_L2_R2), len);
break; 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].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation = (*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_toggle_gamepad_combo; &setting_get_string_representation_gamepad_combo;
menu_settings_list_current_add_range(list, list_info, 0, (INPUT_TOGGLE_LAST-1), 1, true, true); 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( CONFIG_UINT(
list, list_info, list, list_info,

View File

@ -976,6 +976,7 @@ enum msg_hash_enums
MENU_LABEL(INPUT_OVERLAY_ENABLE), MENU_LABEL(INPUT_OVERLAY_ENABLE),
MENU_LABEL(INPUT_OSK_OVERLAY_ENABLE), MENU_LABEL(INPUT_OSK_OVERLAY_ENABLE),
MENU_LABEL(INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO), 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_IN_MENU),
MENU_LABEL(INPUT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED), MENU_LABEL(INPUT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED),
#if defined(ANDROID) #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(); struct menu_state *menu_st = menu_state_get_ptr();
menu_handle_t *menu = menu_st->driver_data; menu_handle_t *menu = menu_st->driver_data;
unsigned menu_toggle_gamepad_combo = settings->uints.input_menu_toggle_gamepad_combo; 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_driver_binding_state = p_rarch->menu_driver_is_binding;
bool menu_is_alive = p_rarch->menu_driver_alive; bool menu_is_alive = p_rarch->menu_driver_alive;
bool display_kb = menu_input_dialog_get_display_kb(); bool display_kb = menu_input_dialog_get_display_kb();
@ -28155,9 +28156,11 @@ static enum runloop_state runloop_check_state(
#ifdef HAVE_MENU #ifdef HAVE_MENU
last_input = current_bits; last_input = current_bits;
if ( if (
((menu_toggle_gamepad_combo != INPUT_TOGGLE_NONE) && ((menu_toggle_gamepad_combo != INPUT_COMBO_NONE) &&
input_driver_toggle_button_combo( input_driver_button_combo(
menu_toggle_gamepad_combo, current_time, input_driver_st,
menu_toggle_gamepad_combo,
current_time,
&last_input))) &last_input)))
BIT256_SET(current_bits, RARCH_MENU_TOGGLE); BIT256_SET(current_bits, RARCH_MENU_TOGGLE);
@ -28324,6 +28327,15 @@ static enum runloop_state runloop_check_state(
quit_key = BIT256_GET( quit_key = BIT256_GET(
current_bits, RARCH_QUIT_KEY); current_bits, RARCH_QUIT_KEY);
trig_quit_key = quit_key && !old_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; old_quit_key = quit_key;
quit_press_twice = settings->bools.quit_press_twice; quit_press_twice = settings->bools.quit_press_twice;

View File

@ -653,6 +653,20 @@
# 10: L2 + R2 # 10: L2 + R2
# input_menu_toggle_gamepad_combo = 0 # 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 # allow any RetroPad to control the menu
# all_users_control_menu = false # all_users_control_menu = false