Backport Added alternate Turbo-Mode 'Single Button' -

For systems supporting only a single button, the turbo-button will toggle firing that button without the need to hold it.
When holding the button turbo will be suspended and resumed when the button is released. Holding the button may have a different function to just tapping it, e.g. charging the beam in R-Type on C64/Amiga.
The original implementation in RA is named 'Classic' because I have no
idea where it originates from.
This commit is contained in:
twinaphex 2019-12-25 07:13:01 +01:00
parent 921e470b05
commit 538f0c534f
12 changed files with 254 additions and 15 deletions

View File

@ -979,6 +979,8 @@ static const float analog_sensitivity = 1.0f;
/* Describes speed of which turbo-enabled buttons toggle. */
static const unsigned turbo_period = 6;
static const unsigned turbo_duty_cycle = 3;
static const unsigned turbo_mode = 0;
static const unsigned turbo_default_btn = RETRO_DEVICE_ID_JOYPAD_B;
/* Enable input auto-detection. Will attempt to autoconfigure
* gamepads, plug-and-play style. */

View File

@ -1735,6 +1735,8 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
SETTING_UINT("input_bind_hold", &settings->uints.input_bind_hold, true, input_bind_hold, false);
SETTING_UINT("input_turbo_period", &settings->uints.input_turbo_period, true, turbo_period, false);
SETTING_UINT("input_duty_cycle", &settings->uints.input_turbo_duty_cycle, true, turbo_duty_cycle, false);
SETTING_UINT("input_turbo_mode", &settings->uints.input_turbo_mode, true, turbo_mode, false);
SETTING_UINT("input_turbo_default_button", &settings->uints.input_turbo_default_button, true, turbo_default_btn, false);
SETTING_UINT("input_max_users", input_driver_get_uint(INPUT_ACTION_MAX_USERS), true, input_max_users, false);
SETTING_UINT("fps_update_interval", &settings->uints.fps_update_interval, true, DEFAULT_FPS_UPDATE_INTERVAL, false);
SETTING_UINT("input_menu_toggle_gamepad_combo", &settings->uints.input_menu_toggle_gamepad_combo, true, menu_toggle_gamepad_combo, false);

View File

@ -464,6 +464,8 @@ typedef struct settings
unsigned input_turbo_period;
unsigned input_turbo_duty_cycle;
unsigned input_turbo_mode;
unsigned input_turbo_default_button;
unsigned input_bind_timeout;
unsigned input_bind_hold;

View File

@ -64,6 +64,28 @@ enum input_toggle_type
INPUT_TOGGLE_LAST
};
enum input_turbo_mode
{
INPUT_TURBO_MODE_CLASSIC = 0,
INPUT_TURBO_MODE_SINGLEBUTTON,
INPUT_TURBO_MODE_LAST
};
enum input_turbo_default_button
{
INPUT_TURBO_DEFAULT_BUTTON_B = 0,
INPUT_TURBO_DEFAULT_BUTTON_Y,
INPUT_TURBO_DEFAULT_BUTTON_A,
INPUT_TURBO_DEFAULT_BUTTON_X,
INPUT_TURBO_DEFAULT_BUTTON_L,
INPUT_TURBO_DEFAULT_BUTTON_R,
INPUT_TURBO_DEFAULT_BUTTON_L2,
INPUT_TURBO_DEFAULT_BUTTON_R2,
INPUT_TURBO_DEFAULT_BUTTON_L3,
INPUT_TURBO_DEFAULT_BUTTON_R3,
INPUT_TURBO_DEFAULT_BUTTON_LAST
};
enum input_action
{
INPUT_ACTION_NONE = 0,

View File

@ -2191,3 +2191,7 @@ MSG_HASH(MENU_ENUM_LABEL_INPUT_MENU_SETTINGS,
"input_menu_settings")
MSG_HASH(MENU_ENUM_LABEL_INPUT_HAPTIC_FEEDBACK_SETTINGS,
"input_haptic_feedback_settings")
MSG_HASH(MENU_ENUM_LABEL_INPUT_TURBO_MODE,
"input_turbo_mode")
MSG_HASH(MENU_ENUM_LABEL_INPUT_TURBO_DEFAULT_BUTTON,
"input_turbo_default_button")

View File

@ -1613,6 +1613,20 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
"Numbers are described in frames."
);
break;
case MENU_ENUM_LABEL_INPUT_TURBO_MODE:
snprintf(s, len,
"Turbo Mode.\n"
" \n"
"Selects the general behavior of turbo mode."
);
break;
case MENU_ENUM_LABEL_INPUT_TURBO_DEFAULT_BUTTON:
snprintf(s, len,
"Turbo Default Button.\n"
" \n"
"Default active button for Turbo Mode 'Single Button'.\n"
);
break;
case MENU_ENUM_LABEL_INPUT_DUTY_CYCLE:
snprintf(s, len,
"Duty cycle.\n"

View File

@ -1565,6 +1565,14 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD,
"Turbo Period"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_TURBO_MODE,
"Turbo Mode"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_TURBO_DEFAULT_BUTTON,
"Turbo Default Button"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_USER_BINDS,
"Port %u Binds"
@ -5615,6 +5623,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_DUTY_CYCLE,
"Describes how long the period of a turbo-enabled button should be. Numbers are described in frames."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_TURBO_MODE,
"Selects the general behavior of turbo mode."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_TURBO_DEFAULT_BUTTON,
"Default active button for Turbo Mode 'Single Button'."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_VIDEO_VSYNC,
"Synchronizes the output video of the graphics card to the refresh rate of the screen. Recommended."

View File

@ -262,6 +262,8 @@ default_sublabel_macro(action_bind_sublabel_input_mouse_scale, MENU_ENUM_SUBLABE
default_sublabel_macro(action_bind_sublabel_axis_threshold, MENU_ENUM_SUBLABEL_INPUT_BUTTON_AXIS_THRESHOLD)
default_sublabel_macro(action_bind_sublabel_input_turbo_period, MENU_ENUM_SUBLABEL_INPUT_TURBO_PERIOD)
default_sublabel_macro(action_bind_sublabel_input_duty_cycle, MENU_ENUM_SUBLABEL_INPUT_DUTY_CYCLE)
default_sublabel_macro(action_bind_sublabel_input_turbo_mode, MENU_ENUM_SUBLABEL_INPUT_TURBO_MODE)
default_sublabel_macro(action_bind_sublabel_input_turbo_default_button, MENU_ENUM_SUBLABEL_INPUT_TURBO_DEFAULT_BUTTON)
default_sublabel_macro(action_bind_sublabel_video_vertical_sync, MENU_ENUM_SUBLABEL_VIDEO_VSYNC)
default_sublabel_macro(action_bind_sublabel_video_adaptive_vsync, MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC)
default_sublabel_macro(action_bind_sublabel_core_allow_rotate, MENU_ENUM_SUBLABEL_VIDEO_ALLOW_ROTATE)
@ -2490,6 +2492,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_INPUT_TURBO_PERIOD:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_turbo_period);
break;
case MENU_ENUM_LABEL_INPUT_TURBO_MODE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_turbo_mode);
break;
case MENU_ENUM_LABEL_INPUT_TURBO_DEFAULT_BUTTON:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_turbo_default_button);
break;
case MENU_ENUM_LABEL_INPUT_BIND_TIMEOUT:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_bind_timeout);
break;

View File

@ -4591,6 +4591,14 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
MENU_ENUM_LABEL_INPUT_DUTY_CYCLE,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(list,
MENU_ENUM_LABEL_INPUT_TURBO_MODE,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(list,
MENU_ENUM_LABEL_INPUT_TURBO_DEFAULT_BUTTON,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(list,
MENU_ENUM_LABEL_INPUT_BIND_MODE,
PARSE_ONLY_UINT, false) == 0)

View File

@ -5475,6 +5475,66 @@ static void setting_get_string_representation_toggle_gamepad_combo(
}
}
static void setting_get_string_representation_turbo_mode(
rarch_setting_t *setting,
char *s, size_t len)
{
if (!setting)
return;
switch (*setting->value.target.unsigned_integer)
{
case INPUT_TURBO_MODE_CLASSIC:
strlcpy(s, "Classic", len);
break;
case INPUT_TURBO_MODE_SINGLEBUTTON:
strlcpy(s, "Single Button", len);
break;
}
}
static void setting_get_string_representation_turbo_default_button(
rarch_setting_t *setting,
char *s, size_t len)
{
if (!setting)
return;
switch (*setting->value.target.unsigned_integer)
{
case INPUT_TURBO_DEFAULT_BUTTON_B:
strlcpy(s, "B / Fire", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_Y:
strlcpy(s, "Y", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_A:
strlcpy(s, "A", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_X:
strlcpy(s, "X", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_L:
strlcpy(s, "L", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_R:
strlcpy(s, "R", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_L2:
strlcpy(s, "L2", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_R2:
strlcpy(s, "R2", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_L3:
strlcpy(s, "L3", len);
break;
case INPUT_TURBO_DEFAULT_BUTTON_R3:
strlcpy(s, "R3", len);
break;
}
}
#ifdef HAVE_NETWORKING
static void setting_get_string_representation_netplay_share_digital(
rarch_setting_t *setting,
@ -11215,6 +11275,40 @@ static bool setting_append_list(
&subgroup_info,
parent_group);
CONFIG_UINT(
list, list_info,
&settings->uints.input_turbo_mode,
MENU_ENUM_LABEL_INPUT_TURBO_MODE,
MENU_ENUM_LABEL_VALUE_INPUT_TURBO_MODE,
turbo_mode,
&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_turbo_mode;
menu_settings_list_current_add_range(list, list_info, 0, (INPUT_TURBO_MODE_LAST-1), 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.input_turbo_default_button,
MENU_ENUM_LABEL_INPUT_TURBO_DEFAULT_BUTTON,
MENU_ENUM_LABEL_VALUE_INPUT_TURBO_DEFAULT_BUTTON,
turbo_default_btn,
&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_turbo_default_button;
menu_settings_list_current_add_range(list, list_info, 0, (INPUT_TURBO_DEFAULT_BUTTON_LAST-1), 1, true, true);
END_SUB_GROUP(list, list_info, parent_group);
START_SUB_GROUP(list, list_info, "Binds", &group_info, &subgroup_info, parent_group);

View File

@ -691,6 +691,8 @@ enum msg_hash_enums
MENU_ENUM_LABEL_INPUT_HOTKEY_BINDS_BEGIN,
MENU_LABEL(INPUT_TURBO_PERIOD),
MENU_LABEL(INPUT_TURBO_MODE),
MENU_LABEL(INPUT_TURBO_DEFAULT_BUTTON),
MENU_ENUM_LABEL_INPUT_PLAYER1_JOYPAD_INDEX,
MENU_ENUM_LABEL_INPUT_PLAYER2_JOYPAD_INDEX,

View File

@ -3216,6 +3216,8 @@ struct turbo_buttons
{
bool frame_enable[MAX_USERS];
uint16_t enable[MAX_USERS];
bool mode1_enable[MAX_USERS];
int32_t turbo_pressed[MAX_USERS];
unsigned count;
};
@ -13630,23 +13632,86 @@ static int16_t input_state_device(
{
/*
* Apply turbo button if activated.
*
* If turbo button is held, all buttons pressed except
* for D-pad will go into a turbo mode. Until the button is
* released again, the input state will be modulated by a
* periodic pulse defined by the configured duty cycle.
*/
if (res && input_driver_turbo_btns.frame_enable[port])
input_driver_turbo_btns.enable[port] |= (1 << id);
else if (!res)
input_driver_turbo_btns.enable[port] &= ~(1 << id);
if (input_driver_turbo_btns.enable[port] & (1 << id))
if (settings->uints.input_turbo_mode == 1)
{
/* if turbo button is enabled for this key ID */
res = res && ((input_driver_turbo_btns.count
% settings->uints.input_turbo_period)
< settings->uints.input_turbo_duty_cycle);
/* Pressing turbo button toggles turbo mode on or off.
* Holding the button will
* pass through, else the pressed state will be modulated by a
* periodic pulse defined by the configured duty cycle.
*/
/* Avoid detecting the turbo button being held as multiple toggles */
if (!input_driver_turbo_btns.frame_enable[port])
input_driver_turbo_btns.turbo_pressed[port] &= ~(1<<31);
else if (input_driver_turbo_btns.turbo_pressed[port]>=0)
{
input_driver_turbo_btns.turbo_pressed[port] |= (1<<31);
/* Toggle turbo for selected buttons. */
if (!input_driver_turbo_btns.enable[port])
{
static const int button_map[]={
RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_Y,
RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_X,
RETRO_DEVICE_ID_JOYPAD_L,
RETRO_DEVICE_ID_JOYPAD_R,
RETRO_DEVICE_ID_JOYPAD_L2,
RETRO_DEVICE_ID_JOYPAD_R2,
RETRO_DEVICE_ID_JOYPAD_L3,
RETRO_DEVICE_ID_JOYPAD_R3};
input_driver_turbo_btns.enable[port] = 1 << button_map[
min(
sizeof(button_map)/sizeof(button_map[0])-1,
settings->uints.input_turbo_default_button)];
}
input_driver_turbo_btns.mode1_enable[port] ^= 1;
}
if (input_driver_turbo_btns.turbo_pressed[port] & 1<<31)
{
/* Avoid detecting buttons being held as multiple toggles */
if (!res)
input_driver_turbo_btns.turbo_pressed[port] &= ~(1 << id);
else if (!(input_driver_turbo_btns.turbo_pressed[port] & (1 << id)))
{
input_driver_turbo_btns.turbo_pressed[port] |= 1 << id;
/* Toggle turbo for pressed button but make sure at least one button has turbo */
uint16_t enable_new = input_driver_turbo_btns.enable[port] ^ (1 << id);
if (enable_new)
input_driver_turbo_btns.enable[port] = enable_new;
}
}
if (!res && input_driver_turbo_btns.mode1_enable[port] &&
input_driver_turbo_btns.enable[port] & (1 << id))
{
/* if turbo button is enabled for this key ID */
res = ((input_driver_turbo_btns.count
% settings->uints.input_turbo_period)
< settings->uints.input_turbo_duty_cycle);
}
}
else
{
/* If turbo button is held, all buttons pressed except
* for D-pad will go into a turbo mode. Until the button is
* released again, the input state will be modulated by a
* periodic pulse defined by the configured duty cycle.
*/
if (res && input_driver_turbo_btns.frame_enable[port])
input_driver_turbo_btns.enable[port] |= (1 << id);
else if (!res)
input_driver_turbo_btns.enable[port] &= ~(1 << id);
if (input_driver_turbo_btns.enable[port] & (1 << id))
{
/* if turbo button is enabled for this key ID */
res = res && ((input_driver_turbo_btns.count
% settings->uints.input_turbo_period)
< settings->uints.input_turbo_duty_cycle);
}
}
}