Input binding rework (#15603)

* Input binding rework

* Controller info logging cleanup
This commit is contained in:
sonninnos 2023-08-16 21:13:14 +03:00 committed by GitHub
parent 4dd3b022f1
commit de45fc2f5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 307 additions and 219 deletions

View File

@ -1520,8 +1520,8 @@
#define DEFAULT_INPUT_MAX_USERS 8 #define DEFAULT_INPUT_MAX_USERS 8
#endif #endif
#define DEFAULT_INPUT_BIND_TIMEOUT 5 #define DEFAULT_INPUT_BIND_TIMEOUT 3
#define DEFAULT_INPUT_BIND_HOLD 2 #define DEFAULT_INPUT_BIND_HOLD 1
#define DEFAULT_INPUT_POLL_TYPE_BEHAVIOR 2 #define DEFAULT_INPUT_POLL_TYPE_BEHAVIOR 2
#define DEFAULT_INPUT_HOTKEY_BLOCK_DELAY 5 #define DEFAULT_INPUT_HOTKEY_BLOCK_DELAY 5

View File

@ -97,10 +97,10 @@ const unsigned input_config_bind_order[24] = {
RETRO_DEVICE_ID_JOYPAD_DOWN, RETRO_DEVICE_ID_JOYPAD_DOWN,
RETRO_DEVICE_ID_JOYPAD_LEFT, RETRO_DEVICE_ID_JOYPAD_LEFT,
RETRO_DEVICE_ID_JOYPAD_RIGHT, RETRO_DEVICE_ID_JOYPAD_RIGHT,
RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_B, RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_X, RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_Y, RETRO_DEVICE_ID_JOYPAD_Y,
RETRO_DEVICE_ID_JOYPAD_X,
RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_SELECT,
RETRO_DEVICE_ID_JOYPAD_START, RETRO_DEVICE_ID_JOYPAD_START,
RETRO_DEVICE_ID_JOYPAD_L, RETRO_DEVICE_ID_JOYPAD_L,
@ -3024,18 +3024,20 @@ void input_config_get_bind_string(
if (bind && bind->joykey != NO_BTN) if (bind && bind->joykey != NO_BTN)
input_config_get_bind_string_joykey( input_config_get_bind_string_joykey(
input_descriptor_label_show, buf, "", bind, size); input_descriptor_label_show,
buf, "", bind, size);
else if (bind && bind->joyaxis != AXIS_NONE) else if (bind && bind->joyaxis != AXIS_NONE)
input_config_get_bind_string_joyaxis( input_config_get_bind_string_joyaxis(
input_descriptor_label_show, input_descriptor_label_show,
buf, "", bind, size); buf, "", bind, size);
else if (auto_bind && auto_bind->joykey != NO_BTN) else if (auto_bind && auto_bind->joykey != NO_BTN)
input_config_get_bind_string_joykey( input_config_get_bind_string_joykey(
input_descriptor_label_show, buf, "Auto: ", auto_bind, size); input_descriptor_label_show,
buf, "(Auto)", auto_bind, size);
else if (auto_bind && auto_bind->joyaxis != AXIS_NONE) else if (auto_bind && auto_bind->joyaxis != AXIS_NONE)
input_config_get_bind_string_joyaxis( input_config_get_bind_string_joyaxis(
input_descriptor_label_show, input_descriptor_label_show,
buf, "Auto: ", auto_bind, size); buf, "(Auto)", auto_bind, size);
if (*buf) if (*buf)
delim = 1; delim = 1;
@ -3118,7 +3120,7 @@ void input_config_get_bind_string(
void input_config_get_bind_string_joykey( void input_config_get_bind_string_joykey(
bool input_descriptor_label_show, bool input_descriptor_label_show,
char *buf, const char *prefix, char *buf, const char *suffix,
const struct retro_keybind *bind, size_t size) const struct retro_keybind *bind, size_t size)
{ {
if (GET_HAT_DIR(bind->joykey)) if (GET_HAT_DIR(bind->joykey))
@ -3127,39 +3129,32 @@ void input_config_get_bind_string_joykey(
&& !string_is_empty(bind->joykey_label) && !string_is_empty(bind->joykey_label)
&& input_descriptor_label_show) && input_descriptor_label_show)
{ {
size_t len = fill_pathname_join_delim(buf, prefix, size_t len = fill_pathname_join_delim(buf,
bind->joykey_label, ' ', size); bind->joykey_label, suffix, ' ', size);
strlcpy(buf + len, " (hat)", size - len);
} }
else else
{ {
size_t len = strlcpy(buf, prefix, size); size_t len = snprintf(buf, size,
len += snprintf(buf + len, size - len, "Hat #%u ", "Hat #%u ", (unsigned)GET_HAT(bind->joykey));
(unsigned)GET_HAT(bind->joykey));
switch (GET_HAT_DIR(bind->joykey)) switch (GET_HAT_DIR(bind->joykey))
{ {
case HAT_UP_MASK: case HAT_UP_MASK:
len += strlcpy(buf + len, "up (", size - len); len += strlcpy(buf + len, "Up", size - len);
break; break;
case HAT_DOWN_MASK: case HAT_DOWN_MASK:
len += strlcpy(buf + len, "down (", size - len); len += strlcpy(buf + len, "Down", size - len);
break; break;
case HAT_LEFT_MASK: case HAT_LEFT_MASK:
len += strlcpy(buf + len, "left (", size - len); len += strlcpy(buf + len, "Left", size - len);
break; break;
case HAT_RIGHT_MASK: case HAT_RIGHT_MASK:
len += strlcpy(buf + len, "right (", size - len); len += strlcpy(buf + len, "Right", size - len);
break; break;
default: default:
len += strlcpy(buf + len, "? (", size - len); len += strlcpy(buf + len, "?", size - len);
break; break;
} }
len += strlcpy(buf + len,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
size - len);
buf[ len] = ')';
buf[++len] = '\0';
} }
} }
else else
@ -3168,43 +3163,35 @@ void input_config_get_bind_string_joykey(
!string_is_empty(bind->joykey_label) !string_is_empty(bind->joykey_label)
&& input_descriptor_label_show) && input_descriptor_label_show)
{ {
size_t len = fill_pathname_join_delim(buf, prefix, size_t len = fill_pathname_join_delim(buf,
bind->joykey_label, ' ', size); bind->joykey_label, suffix, ' ', size);
strlcpy(buf + len, " (btn)", size - len);
} }
else else
snprintf(buf, size, "%s%u (%s)", prefix, (unsigned)bind->joykey, snprintf(buf, size, "%s%u",
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE)); "Button ", (unsigned)bind->joykey);
} }
} }
void input_config_get_bind_string_joyaxis( void input_config_get_bind_string_joyaxis(
bool input_descriptor_label_show, bool input_descriptor_label_show,
char *buf, const char *prefix, char *buf, const char *suffix,
const struct retro_keybind *bind, size_t size) const struct retro_keybind *bind, size_t size)
{ {
if (bind->joyaxis_label && if (bind->joyaxis_label &&
!string_is_empty(bind->joyaxis_label) !string_is_empty(bind->joyaxis_label)
&& input_descriptor_label_show) && input_descriptor_label_show)
{ {
size_t len = fill_pathname_join_delim(buf, prefix, size_t len = fill_pathname_join_delim(buf,
bind->joyaxis_label, ' ', size); bind->joyaxis_label, suffix, ' ', size);
strlcpy(buf + len, " (axis)", size - len);
} }
else else
{ {
if (AXIS_NEG_GET(bind->joyaxis) != AXIS_DIR_NONE) if (AXIS_NEG_GET(bind->joyaxis) != AXIS_DIR_NONE)
{ snprintf(buf, size, "%s-%u",
unsigned axis = AXIS_NEG_GET(bind->joyaxis); "Axis ", (unsigned)AXIS_NEG_GET(bind->joyaxis));
snprintf(buf, size, "%s-%u (%s)", prefix, axis,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE));
}
else if (AXIS_POS_GET(bind->joyaxis) != AXIS_DIR_NONE) else if (AXIS_POS_GET(bind->joyaxis) != AXIS_DIR_NONE)
{ snprintf(buf, size, "%s+%u",
unsigned axis = AXIS_POS_GET(bind->joyaxis); "Axis ", (unsigned)AXIS_POS_GET(bind->joyaxis));
snprintf(buf, size, "%s+%u (%s)", prefix, axis,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE));
}
} }
} }

View File

@ -156,7 +156,8 @@ enum input_driver_state_flags
INP_FLAG_OLD_ANALOG_DPAD_MODE_SET = (1 << 7), INP_FLAG_OLD_ANALOG_DPAD_MODE_SET = (1 << 7),
INP_FLAG_OLD_LIBRETRO_DEVICE_SET = (1 << 8), INP_FLAG_OLD_LIBRETRO_DEVICE_SET = (1 << 8),
INP_FLAG_REMAPPING_CACHE_ACTIVE = (1 << 9), INP_FLAG_REMAPPING_CACHE_ACTIVE = (1 << 9),
INP_FLAG_DEFERRED_WAIT_KEYS = (1 << 10) INP_FLAG_DEFERRED_WAIT_KEYS = (1 << 10),
INP_FLAG_WAIT_INPUT_RELEASE = (1 << 11)
}; };
#ifdef HAVE_BSV_MOVIE #ifdef HAVE_BSV_MOVIE

View File

@ -1891,10 +1891,6 @@ MSG_HASH(
"input_touch_vmouse_gesture" "input_touch_vmouse_gesture"
) )
#endif #endif
MSG_HASH(
MENU_ENUM_LABEL_INPUT_BIND_MODE,
"input_bind_mode"
)
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_INPUT_BIND_TIMEOUT, MENU_ENUM_LABEL_INPUT_BIND_TIMEOUT,
"input_bind_timeout" "input_bind_timeout"

View File

@ -3162,6 +3162,22 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_BIND_HOLD, MENU_ENUM_SUBLABEL_INPUT_BIND_HOLD,
"Amount of seconds to hold an input to bind it." "Amount of seconds to hold an input to bind it."
) )
MSG_HASH(
MSG_INPUT_BIND_PRESS,
"Press keyboard, mouse or controller"
)
MSG_HASH(
MSG_INPUT_BIND_RELEASE,
"Release keys and buttons!"
)
MSG_HASH(
MSG_INPUT_BIND_TIMEOUT,
"Timeout"
)
MSG_HASH(
MSG_INPUT_BIND_HOLD,
"Hold"
)
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD, MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD,
"Turbo Period" "Turbo Period"
@ -10550,7 +10566,7 @@ MSG_HASH(
) )
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_KEY,
"(Key: %s)" "Key %s"
) )
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_LEFT, MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_LEFT,

View File

@ -2406,13 +2406,13 @@ static uintptr_t ozone_entries_icon_get_texture(
if (type == (input_id + 3)) if (type == (input_id + 3))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_DPAD_R]; return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_DPAD_R];
if (type == (input_id + 4)) if (type == (input_id + 4))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_R];
if (type == (input_id + 5))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_D]; return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_D];
if (type == (input_id + 5))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_R];
if (type == (input_id + 6)) if (type == (input_id + 6))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_U];
if (type == (input_id + 7))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_L]; return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_L];
if (type == (input_id + 7))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_BTN_U];
if (type == (input_id + 8)) if (type == (input_id + 8))
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_SELECT]; return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_INPUT_SELECT];
if (type == (input_id + 9)) if (type == (input_id + 9))

View File

@ -3554,13 +3554,13 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb,
else if (type == (input_id + 3)) else if (type == (input_id + 3))
return xmb->textures.list[XMB_TEXTURE_INPUT_DPAD_R]; return xmb->textures.list[XMB_TEXTURE_INPUT_DPAD_R];
else if (type == (input_id + 4)) else if (type == (input_id + 4))
return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_R];
else if (type == (input_id + 5))
return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_D]; return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_D];
else if (type == (input_id + 5))
return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_R];
else if (type == (input_id + 6)) else if (type == (input_id + 6))
return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_U];
else if (type == (input_id + 7))
return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_L]; return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_L];
else if (type == (input_id + 7))
return xmb->textures.list[XMB_TEXTURE_INPUT_BTN_U];
else if (type == (input_id + 8)) else if (type == (input_id + 8))
return xmb->textures.list[XMB_TEXTURE_INPUT_SELECT]; return xmb->textures.list[XMB_TEXTURE_INPUT_SELECT];
else if (type == (input_id + 9)) else if (type == (input_id + 9))

View File

@ -7601,7 +7601,6 @@ unsigned menu_displaylist_build_list(
#endif #endif
{MENU_ENUM_LABEL_INPUT_BIND_TIMEOUT, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_BIND_TIMEOUT, PARSE_ONLY_UINT, true },
{MENU_ENUM_LABEL_INPUT_BIND_HOLD, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_BIND_HOLD, PARSE_ONLY_UINT, true },
{MENU_ENUM_LABEL_INPUT_BIND_MODE, PARSE_ONLY_UINT, true },
{MENU_ENUM_LABEL_QUIT_PRESS_TWICE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_QUIT_PRESS_TWICE, PARSE_ONLY_BOOL, true },
{MENU_ENUM_LABEL_PAUSE_ON_DISCONNECT, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_PAUSE_ON_DISCONNECT, PARSE_ONLY_BOOL, true },
{MENU_ENUM_LABEL_INPUT_AUTO_MOUSE_GRAB, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_AUTO_MOUSE_GRAB, PARSE_ONLY_BOOL, true },

View File

@ -1446,6 +1446,7 @@ static int menu_input_key_bind_set_mode_common(
bind_type = setting->bind_type; bind_type = setting->bind_type;
binds->order = 0;
binds->begin = bind_type; binds->begin = bind_type;
binds->last = bind_type; binds->last = bind_type;
binds->output = keybind; binds->output = keybind;
@ -1472,9 +1473,12 @@ static int menu_input_key_bind_set_mode_common(
menu_displaylist_info_init(&info); menu_displaylist_info_init(&info);
binds->begin = MENU_SETTINGS_BIND_BEGIN; binds->order = 0;
binds->begin = MENU_SETTINGS_BIND_BEGIN
+ input_config_bind_order[0];
binds->last = MENU_SETTINGS_BIND_LAST; binds->last = MENU_SETTINGS_BIND_LAST;
binds->output = &input_config_binds[setting->index_offset][0]; binds->output = &input_config_binds[setting->index_offset][0]
+ input_config_bind_order[0];
binds->buffer = *(binds->output); binds->buffer = *(binds->output);
info.list = menu_stack; info.list = menu_stack;
@ -1496,10 +1500,9 @@ static int menu_input_key_bind_set_mode_common(
return 0; return 0;
} }
#ifdef ANDROID
static bool menu_input_key_bind_poll_find_hold_pad( static bool menu_input_key_bind_poll_find_hold_pad(
struct menu_bind_state *new_state, struct menu_bind_state *new_state,
struct retro_keybind * output, struct retro_keybind *output,
unsigned p) unsigned p)
{ {
unsigned a, b, h; unsigned a, b, h;
@ -1507,11 +1510,22 @@ static bool menu_input_key_bind_poll_find_hold_pad(
(const struct menu_bind_state_port*) (const struct menu_bind_state_port*)
&new_state->state[p]; &new_state->state[p];
for (b = RETROK_BACKSPACE; b < RETROK_LAST; b++)
{
bool found = n->keys[b];
if (!found)
continue;
output->key = b;
return true;
}
for (b = 0; b < MENU_MAX_MBUTTONS; b++) for (b = 0; b < MENU_MAX_MBUTTONS; b++)
{ {
bool iterate = n->mouse_buttons[b]; bool found = n->mouse_buttons[b];
if (!iterate) if (!found)
continue; continue;
switch (b) switch (b)
@ -1532,9 +1546,9 @@ static bool menu_input_key_bind_poll_find_hold_pad(
for (b = 0; b < MENU_MAX_BUTTONS; b++) for (b = 0; b < MENU_MAX_BUTTONS; b++)
{ {
bool iterate = n->buttons[b]; bool found = n->buttons[b];
if (!iterate) if (!found)
continue; continue;
output->joykey = b; output->joykey = b;
@ -1549,10 +1563,8 @@ static bool menu_input_key_bind_poll_find_hold_pad(
{ {
/* Take care of case where axis rests on +/- 0x7fff /* Take care of case where axis rests on +/- 0x7fff
* (e.g. 360 controller on Linux) */ * (e.g. 360 controller on Linux) */
output->joyaxis = n->axes[a] > 0 output->joyaxis = n->axes[a] > 0 ? AXIS_POS(a) : AXIS_NEG(a);
? AXIS_POS(a) : AXIS_NEG(a);
output->joykey = NO_BTN; output->joykey = NO_BTN;
return true; return true;
} }
} }
@ -1585,7 +1597,7 @@ static bool menu_input_key_bind_poll_find_hold_pad(
static bool menu_input_key_bind_poll_find_hold( static bool menu_input_key_bind_poll_find_hold(
unsigned max_users, unsigned max_users,
struct menu_bind_state *new_state, struct menu_bind_state *new_state,
struct retro_keybind * output) struct retro_keybind *output)
{ {
if (new_state) if (new_state)
{ {
@ -1600,12 +1612,11 @@ static bool menu_input_key_bind_poll_find_hold(
return false; return false;
} }
#endif
static bool menu_input_key_bind_poll_find_trigger_pad( static bool menu_input_key_bind_poll_find_trigger_pad(
struct menu_bind_state *state, struct menu_bind_state *state,
struct menu_bind_state *new_state, struct menu_bind_state *new_state,
struct retro_keybind * output, struct retro_keybind *output,
unsigned p) unsigned p)
{ {
unsigned a, b, h; unsigned a, b, h;
@ -1614,11 +1625,22 @@ static bool menu_input_key_bind_poll_find_trigger_pad(
const struct menu_bind_state_port *o = (const struct menu_bind_state_port*) const struct menu_bind_state_port *o = (const struct menu_bind_state_port*)
&state->state[p]; &state->state[p];
for (b = RETROK_BACKSPACE; b < RETROK_LAST; b++)
{
bool found = n->keys[b] && !o->keys[b];
if (!found)
continue;
output->key = b;
return true;
}
for (b = 0; b < MENU_MAX_MBUTTONS; b++) for (b = 0; b < MENU_MAX_MBUTTONS; b++)
{ {
bool iterate = n->mouse_buttons[b] && !o->mouse_buttons[b]; bool found = n->mouse_buttons[b] && !o->mouse_buttons[b];
if (!iterate) if (!found)
continue; continue;
switch (b) switch (b)
@ -1639,9 +1661,9 @@ static bool menu_input_key_bind_poll_find_trigger_pad(
for (b = 0; b < MENU_MAX_BUTTONS; b++) for (b = 0; b < MENU_MAX_BUTTONS; b++)
{ {
bool iterate = n->buttons[b] && !o->buttons[b]; bool found = n->buttons[b] && !o->buttons[b];
if (!iterate) if (!found)
continue; continue;
output->joykey = b; output->joykey = b;
@ -1663,14 +1685,12 @@ static bool menu_input_key_bind_poll_find_trigger_pad(
{ {
/* Take care of case where axis rests on +/- 0x7fff /* Take care of case where axis rests on +/- 0x7fff
* (e.g. 360 controller on Linux) */ * (e.g. 360 controller on Linux) */
output->joyaxis = (n->axes[a] > 0) output->joyaxis = (n->axes[a] > 0) ? AXIS_POS(a) : AXIS_NEG(a);
? AXIS_POS(a) : AXIS_NEG(a);
output->joykey = NO_BTN; output->joykey = NO_BTN;
/* Lock the current axis */ /* Lock the current axis */
new_state->axis_state[p].locked_axes[a] = new_state->axis_state[p].locked_axes[a] = n->axes[a] > 0
n->axes[a] > 0 ? ? 0x7fff : -0x7fff;
0x7fff : -0x7fff;
return true; return true;
} }
@ -1707,7 +1727,7 @@ static bool menu_input_key_bind_poll_find_trigger(
unsigned max_users, unsigned max_users,
struct menu_bind_state *state, struct menu_bind_state *state,
struct menu_bind_state *new_state, struct menu_bind_state *new_state,
struct retro_keybind * output) struct retro_keybind *output)
{ {
if (state && new_state) if (state && new_state)
{ {
@ -3328,7 +3348,6 @@ static void menu_input_key_bind_poll_bind_state(
unsigned b; unsigned b;
rarch_joypad_info_t joypad_info; rarch_joypad_info_t joypad_info;
input_driver_t *current_input = input_st->current_driver; input_driver_t *current_input = input_st->current_driver;
void *input_data = input_st->current_data;
unsigned port = state->port; unsigned port = state->port;
const input_device_driver_t *joypad = input_st->primary_joypad; const input_device_driver_t *joypad = input_st->primary_joypad;
#ifdef HAVE_MFI #ifdef HAVE_MFI
@ -3366,6 +3385,20 @@ static void menu_input_key_bind_poll_bind_state(
port, port,
RETRO_DEVICE_MOUSE, 0, b); RETRO_DEVICE_MOUSE, 0, b);
} }
for (b = RETROK_BACKSPACE; b < RETROK_LAST; b++)
{
state->state[port].keys[b] =
current_input->input_state(
input_st->current_data,
joypad,
sec_joypad,
&joypad_info,
binds,
keyboard_mapping_blocked,
0,
RETRO_DEVICE_KEYBOARD, 0, b);
}
} }
joypad_info.joy_idx = 0; joypad_info.joy_idx = 0;
@ -3373,19 +3406,6 @@ static void menu_input_key_bind_poll_bind_state(
joypad_info.axis_threshold = 0.0f; joypad_info.axis_threshold = 0.0f;
state->skip = timed_out; state->skip = timed_out;
if (current_input->input_state)
state->skip |=
current_input->input_state(
input_data,
joypad,
sec_joypad,
&joypad_info,
NULL,
keyboard_mapping_blocked,
0,
RETRO_DEVICE_KEYBOARD,
0,
RETROK_RETURN);
if (joypad) if (joypad)
{ {
@ -4703,45 +4723,45 @@ const menu_ctx_driver_t *menu_driver_find_driver(
return (const menu_ctx_driver_t*)menu_ctx_drivers[0]; return (const menu_ctx_driver_t*)menu_ctx_drivers[0];
} }
#ifdef USE_CUSTOM_BIND_KEYBOARD_CB
static bool menu_input_key_bind_custom_bind_keyboard_cb( static bool menu_input_key_bind_custom_bind_keyboard_cb(
void *data, unsigned code) void *data, unsigned code)
{ {
uint64_t current_usec;
input_driver_state_t *input_st = input_state_get_ptr();
struct menu_state *menu_st = &menu_driver_state;
settings_t *settings = config_get_ptr(); settings_t *settings = config_get_ptr();
struct menu_state *menu_st = &menu_driver_state;
struct menu_bind_state *binds = &menu_st->input_binds; struct menu_bind_state *binds = &menu_st->input_binds;
uint64_t input_bind_hold_us = settings->uints.input_bind_hold * 1000000; uint64_t input_bind_hold_us = settings->uints.input_bind_hold * 1000000;
uint64_t input_bind_timeout_us = settings->uints.input_bind_timeout * 1000000; uint64_t input_bind_timeout_us = settings->uints.input_bind_timeout * 1000000;
uint64_t current_usec = cpu_features_get_time_usec();
/* Clear old mapping bit */ /* Clear old mapping bit */
BIT512_CLEAR_PTR(&input_st->keyboard_mapping_bits, binds->buffer.key); input_keyboard_mapping_bits(0, binds->buffer.key);
/* store key in bind */ /* Store key in bind */
binds->buffer.key = (enum retro_key)code; binds->buffer.key = (enum retro_key)code;
/* Store new mapping bit */ /* Store new mapping bit */
BIT512_SET_PTR(&input_st->keyboard_mapping_bits, binds->buffer.key); input_keyboard_mapping_bits(1, binds->buffer.key);
/* write out the bind */ /* Write out the bind */
*(binds->output) = binds->buffer; *(binds->output) = binds->buffer;
/* next bind */ /* Next bind */
binds->begin++; binds->begin++;
binds->output++; binds->output++;
binds->buffer =* (binds->output); binds->buffer =* (binds->output);
current_usec = cpu_features_get_time_usec();
binds->timer_hold.timeout_us = input_bind_hold_us; binds->timer_hold.timeout_us = input_bind_hold_us;
binds->timer_hold.current = current_usec; binds->timer_hold.current = current_usec;
binds->timer_hold.timeout_end = current_usec + input_bind_hold_us; binds->timer_hold.timeout_end = current_usec + input_bind_hold_us;
binds->timer_timeout.timeout_us = input_bind_timeout_us; binds->timer_timeout.timeout_us = input_bind_timeout_us;
binds->timer_timeout.current = current_usec; binds->timer_timeout.current = current_usec;
binds->timer_timeout.timeout_end = current_usec +input_bind_timeout_us; binds->timer_timeout.timeout_end = current_usec + input_bind_timeout_us;
return (binds->begin <= binds->last); return (binds->begin <= binds->last);
} }
#endif
bool menu_input_key_bind_set_mode( bool menu_input_key_bind_set_mode(
enum menu_input_binds_ctl_state state, void *data) enum menu_input_binds_ctl_state state, void *data)
@ -4771,6 +4791,7 @@ bool menu_input_key_bind_set_mode(
if (!setting || !menu) if (!setting || !menu)
return false; return false;
if (menu_input_key_bind_set_mode_common(menu_st, if (menu_input_key_bind_set_mode_common(menu_st,
binds, state, setting, settings) == -1) binds, state, setting, settings) == -1)
return false; return false;
@ -4793,20 +4814,25 @@ bool menu_input_key_bind_set_mode(
current_usec = cpu_features_get_time_usec(); current_usec = cpu_features_get_time_usec();
binds->timer_hold . timeout_us = input_bind_hold_us; binds->timer_hold .timeout_us = input_bind_hold_us;
binds->timer_hold . current = current_usec; binds->timer_hold .current = current_usec;
binds->timer_hold . timeout_end = current_usec + input_bind_hold_us; binds->timer_hold .timeout_end = current_usec + input_bind_hold_us;
binds->timer_timeout. timeout_us = input_bind_timeout_us; binds->timer_timeout.timeout_us = input_bind_timeout_us;
binds->timer_timeout. current = current_usec; binds->timer_timeout.current = current_usec;
binds->timer_timeout. timeout_end = current_usec + input_bind_timeout_us; binds->timer_timeout.timeout_end = current_usec + input_bind_timeout_us;
input_st->keyboard_press_cb = #ifdef USE_CUSTOM_BIND_KEYBOARD_CB
menu_input_key_bind_custom_bind_keyboard_cb; input_st->keyboard_press_cb = menu_input_key_bind_custom_bind_keyboard_cb;
input_st->keyboard_press_data = menu; input_st->keyboard_press_data = menu;
#endif
/* While waiting for input, we have to block all hotkeys. */ /* While waiting for input, we have to block all hotkeys. */
input_st->flags |= INP_FLAG_KB_MAPPING_BLOCKED; input_st->flags |= INP_FLAG_KB_MAPPING_BLOCKED;
/* Wait until keys are released before starting bind timeout. */
input_st->flags |= INP_FLAG_WAIT_INPUT_RELEASE;
/* Upon triggering an input bind operation, /* Upon triggering an input bind operation,
* pointer input must be inhibited - otherwise * pointer input must be inhibited - otherwise
* attempting to bind mouse buttons will cause * attempting to bind mouse buttons will cause
@ -4830,40 +4856,43 @@ static bool menu_input_key_bind_iterate(
uint64_t input_bind_hold_us = settings->uints.input_bind_hold * 1000000; uint64_t input_bind_hold_us = settings->uints.input_bind_hold * 1000000;
uint64_t input_bind_timeout_us = settings->uints.input_bind_timeout * 1000000; uint64_t input_bind_timeout_us = settings->uints.input_bind_timeout * 1000000;
/* TODO/FIXME - localize */
snprintf(bind->s, bind->len, snprintf(bind->s, bind->len,
"[%s]\nPress keyboard, mouse or joypad\n(Timeout %d %s)", "%s..\n(%s %1.1f %s)\n \n%s\n \n",
input_config_bind_map_get_desc( msg_hash_to_str(MSG_INPUT_BIND_PRESS),
_binds->begin - MENU_SETTINGS_BIND_BEGIN), msg_hash_to_str(MSG_INPUT_BIND_TIMEOUT),
(int)(_binds->timer_timeout.timeout_us / 1000000), ((float)_binds->timer_timeout.timeout_us / 1000000),
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SECONDS)); msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SECONDS),
input_config_bind_map_get_desc(_binds->begin - MENU_SETTINGS_BIND_BEGIN));
/* Tick main timers */ /* Tick main timers */
_binds->timer_timeout.current = current_time;
_binds->timer_timeout.timeout_us = _binds->timer_timeout.timeout_end -
current_time;
_binds->timer_hold .current = current_time; _binds->timer_hold .current = current_time;
_binds->timer_hold .timeout_us = _binds->timer_hold .timeout_end - _binds->timer_hold .timeout_us = _binds->timer_hold .timeout_end - current_time;
current_time;
_binds->timer_timeout.current = current_time;
_binds->timer_timeout.timeout_us = _binds->timer_timeout.timeout_end - current_time;
if (_binds->timer_timeout.timeout_us <= 0) if (_binds->timer_timeout.timeout_us <= 0)
{ {
uint64_t current_usec = cpu_features_get_time_usec();
input_st->flags &= ~INP_FLAG_KB_MAPPING_BLOCKED; input_st->flags &= ~INP_FLAG_KB_MAPPING_BLOCKED;
/*skip to next bind*/ #if 1
/* Give up on first timeout */
return true;
#else
/* Skip to next bind */
_binds->begin++; _binds->begin++;
_binds->output++; _binds->output++;
_binds->timer_hold . timeout_us = input_bind_hold_us;
_binds->timer_hold . current = current_usec;
_binds->timer_hold . timeout_end = current_usec + input_bind_hold_us;
_binds->timer_timeout. timeout_us = input_bind_timeout_us; _binds->timer_hold .timeout_us = input_bind_hold_us;
_binds->timer_timeout. current = current_usec; _binds->timer_hold .current = current_time;
_binds->timer_timeout. timeout_end = current_usec + input_bind_timeout_us; _binds->timer_hold .timeout_end = current_time + input_bind_hold_us;
_binds->timer_timeout.timeout_us = input_bind_timeout_us;
_binds->timer_timeout.current = current_time;
_binds->timer_timeout.timeout_end = current_time + input_bind_timeout_us;
timed_out = true; timed_out = true;
#endif
} }
/* binds.begin is updated in keyboard_press callback. */ /* binds.begin is updated in keyboard_press callback. */
@ -4889,6 +4918,9 @@ static bool menu_input_key_bind_iterate(
{ {
bool complete = false; bool complete = false;
struct menu_bind_state new_binds = *_binds; struct menu_bind_state new_binds = *_binds;
unsigned bind_index = _binds->begin - MENU_SETTINGS_BIND_BEGIN;
const struct retro_keybind *old_binds = &input_config_binds[new_binds.port][bind_index];
unsigned old_key = old_binds->key;
input_st->flags &= ~INP_FLAG_KB_MAPPING_BLOCKED; input_st->flags &= ~INP_FLAG_KB_MAPPING_BLOCKED;
@ -4900,31 +4932,75 @@ static bool menu_input_key_bind_iterate(
&new_binds, timed_out, &new_binds, timed_out,
(input_st->flags & INP_FLAG_KB_MAPPING_BLOCKED) ? true : false); (input_st->flags & INP_FLAG_KB_MAPPING_BLOCKED) ? true : false);
#ifdef ANDROID /* Wait until keys and buttons are released */
if (input_st->flags & INP_FLAG_WAIT_INPUT_RELEASE)
{
if (input_bind_hold_us)
{
if (!menu_input_key_bind_poll_find_hold(
settings->uints.input_max_users,
&new_binds, &(new_binds.buffer)))
input_st->flags &= ~INP_FLAG_WAIT_INPUT_RELEASE;
}
else
{
if (!menu_input_key_bind_poll_find_trigger(
settings->uints.input_max_users,
_binds, &new_binds, &(new_binds.buffer)))
input_st->flags &= ~INP_FLAG_WAIT_INPUT_RELEASE;
}
if (!(input_st->flags & INP_FLAG_WAIT_INPUT_RELEASE))
{
/* Reset timeout */
new_binds.timer_timeout.timeout_us = input_bind_timeout_us;
new_binds.timer_timeout.current = current_time;
new_binds.timer_timeout.timeout_end = current_time + input_bind_timeout_us;
}
else
snprintf(bind->s, bind->len,
"%s..\n(%s %1.1f %s)\n \n--- %s ---\n \n",
msg_hash_to_str(MSG_INPUT_BIND_PRESS),
msg_hash_to_str(MSG_INPUT_BIND_TIMEOUT),
((float)_binds->timer_timeout.timeout_us / 1000000),
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SECONDS),
msg_hash_to_str(MSG_INPUT_BIND_RELEASE)
);
}
else if (input_bind_hold_us)
{
/* Keep resetting bind during the hold period, /* Keep resetting bind during the hold period,
* or we'll potentially bind joystick and mouse, etc.*/ * or we'll potentially bind joystick and mouse, etc. */
new_binds.buffer = *(new_binds.output); new_binds.buffer = *(new_binds.output);
if (menu_input_key_bind_poll_find_hold( if (menu_input_key_bind_poll_find_hold(
settings->uints.input_max_users, settings->uints.input_max_users,
&new_binds, &new_binds.buffer)) &new_binds, &new_binds.buffer))
{ {
uint64_t current_usec = cpu_features_get_time_usec(); char hold_label[256];
/* Inhibit timeout*/
new_binds.timer_timeout. timeout_us = input_bind_timeout_us;
new_binds.timer_timeout. current = current_usec;
new_binds.timer_timeout. timeout_end = current_usec + input_bind_timeout_us;
/* Run hold timer*/ hold_label[0] = '\0';
/* Inhibit timeout */
new_binds.timer_timeout.timeout_us = input_bind_timeout_us;
new_binds.timer_timeout.current = current_time;
new_binds.timer_timeout.timeout_end = current_time + input_bind_timeout_us;
/* Run hold timer */
new_binds.timer_hold.current = current_time; new_binds.timer_hold.current = current_time;
new_binds.timer_hold.timeout_us = new_binds.timer_hold.timeout_us = new_binds.timer_hold.timeout_end - current_time;
new_binds.timer_hold.timeout_end - current_time;
input_config_get_bind_string(settings, hold_label,
&new_binds.buffer, NULL, sizeof(hold_label));
/* TODO/FIXME - localize */
snprintf(bind->s, bind->len, snprintf(bind->s, bind->len,
"[%s]\nPress keyboard, mouse or joypad\nand hold ...", "%s..\n(%s %1.1f %s)\n \n%s\n %s",
input_config_bind_map_get_desc( msg_hash_to_str(MSG_INPUT_BIND_PRESS),
_binds->begin - MENU_SETTINGS_BIND_BEGIN)); msg_hash_to_str(MSG_INPUT_BIND_HOLD),
((float)new_binds.timer_hold.timeout_us / 1000000),
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SECONDS),
input_config_bind_map_get_desc(_binds->begin - MENU_SETTINGS_BIND_BEGIN),
hold_label);
/* Hold complete? */ /* Hold complete? */
if (new_binds.timer_hold.timeout_us <= 0) if (new_binds.timer_hold.timeout_us <= 0)
@ -4932,28 +5008,29 @@ static bool menu_input_key_bind_iterate(
} }
else else
{ {
uint64_t current_usec = cpu_features_get_time_usec(); /* Reset hold countdown */
new_binds.timer_hold.timeout_us = input_bind_hold_us;
/* Reset hold countdown*/ new_binds.timer_hold.current = current_time;
new_binds.timer_hold .timeout_us = input_bind_hold_us; new_binds.timer_hold.timeout_end = current_time + input_bind_hold_us;
new_binds.timer_hold .current = current_usec;
new_binds.timer_hold .timeout_end = current_usec + input_bind_hold_us;
} }
#else }
if ( (new_binds.skip && !_binds->skip) else if ((new_binds.skip && !_binds->skip)
|| menu_input_key_bind_poll_find_trigger( || menu_input_key_bind_poll_find_trigger(
settings->uints.input_max_users, settings->uints.input_max_users,
_binds, &new_binds, &(new_binds.buffer))) _binds, &new_binds, &(new_binds.buffer)))
complete = true; complete = true;
#endif
if (complete) if (complete)
{ {
/* Update bind */ /* Update bind */
uint64_t current_usec = cpu_features_get_time_usec();
*(new_binds.output) = new_binds.buffer; *(new_binds.output) = new_binds.buffer;
input_st->flags &= ~INP_FLAG_KB_MAPPING_BLOCKED; /* Update keyboard mapping bits */
if (new_binds.buffer.key)
{
input_keyboard_mapping_bits(0, old_key);
input_keyboard_mapping_bits(1, new_binds.buffer.key);
}
/* Avoid new binds triggering things right away. */ /* Avoid new binds triggering things right away. */
/* Inhibits input for 2 frames /* Inhibits input for 2 frames
@ -4961,9 +5038,12 @@ static bool menu_input_key_bind_iterate(
* after certain events - e.g. closing the OSK */ * after certain events - e.g. closing the OSK */
menu_st->input_driver_flushing_input = 2; menu_st->input_driver_flushing_input = 2;
new_binds.begin++; /* Use human readable order instead */
new_binds.order++;
new_binds.begin = MENU_SETTINGS_BIND_BEGIN + input_config_bind_order[new_binds.order];
if (new_binds.begin > new_binds.last) if ( new_binds.order > ARRAY_SIZE(input_config_bind_order) - 1
|| new_binds.last != MENU_SETTINGS_BIND_LAST)
{ {
input_st->keyboard_press_cb = NULL; input_st->keyboard_press_cb = NULL;
input_st->keyboard_press_data = NULL; input_st->keyboard_press_data = NULL;
@ -4971,15 +5051,20 @@ static bool menu_input_key_bind_iterate(
return true; return true;
} }
/*next bind*/ input_st->flags &= ~INP_FLAG_KB_MAPPING_BLOCKED;
new_binds.output++; input_st->flags |= INP_FLAG_WAIT_INPUT_RELEASE;
/* Next bind */
new_binds.output =
&input_config_binds[new_binds.port][0]
+ input_config_bind_order[new_binds.order];
new_binds.buffer = *(new_binds.output); new_binds.buffer = *(new_binds.output);
new_binds.timer_hold .timeout_us = input_bind_hold_us; new_binds.timer_hold .timeout_us = input_bind_hold_us;
new_binds.timer_hold .current = current_usec; new_binds.timer_hold .current = current_time;
new_binds.timer_hold .timeout_end = current_usec + input_bind_hold_us; new_binds.timer_hold .timeout_end = current_time + input_bind_hold_us;
new_binds.timer_timeout. timeout_us = input_bind_timeout_us; new_binds.timer_timeout.timeout_us = input_bind_timeout_us;
new_binds.timer_timeout. current = current_usec; new_binds.timer_timeout.current = current_time;
new_binds.timer_timeout. timeout_end = current_usec + input_bind_timeout_us; new_binds.timer_timeout.timeout_end = current_time + input_bind_timeout_us;
} }
*(_binds) = new_binds; *(_binds) = new_binds;

View File

@ -150,6 +150,7 @@ struct menu_bind_state_port
uint16_t hats[MENU_MAX_HATS]; uint16_t hats[MENU_MAX_HATS];
bool mouse_buttons[MENU_MAX_MBUTTONS]; bool mouse_buttons[MENU_MAX_MBUTTONS];
bool buttons[MENU_MAX_BUTTONS]; bool buttons[MENU_MAX_BUTTONS];
bool keys[RETROK_LAST];
}; };
struct menu_bind_axis_state struct menu_bind_axis_state
@ -174,6 +175,7 @@ struct menu_bind_state
unsigned begin; unsigned begin;
unsigned last; unsigned last;
unsigned order;
unsigned user; unsigned user;
unsigned port; unsigned port;

View File

@ -14883,7 +14883,7 @@ static bool setting_append_list(
general_read_handler); general_read_handler);
(*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].offset_by = 1; (*list)[list_info->index - 1].offset_by = 1;
menu_settings_list_current_add_range(list, list_info, 1, 10, 1, true, true); menu_settings_list_current_add_range(list, list_info, 1, 5, 1, true, true);
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ADVANCED); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ADVANCED);
CONFIG_UINT( CONFIG_UINT(
@ -14898,8 +14898,8 @@ static bool setting_append_list(
general_write_handler, general_write_handler,
general_read_handler); general_read_handler);
(*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].offset_by = 1; (*list)[list_info->index - 1].offset_by = 0;
menu_settings_list_current_add_range(list, list_info, 1, 10, 1, true, true); menu_settings_list_current_add_range(list, list_info, 0, 5, 1, true, true);
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ADVANCED); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ADVANCED);
CONFIG_ACTION( CONFIG_ACTION(

View File

@ -391,6 +391,10 @@ enum msg_hash_enums
MSG_REMAP_FILE_SAVED_SUCCESSFULLY, MSG_REMAP_FILE_SAVED_SUCCESSFULLY,
MSG_REMAP_FILE_REMOVED_SUCCESSFULLY, MSG_REMAP_FILE_REMOVED_SUCCESSFULLY,
MSG_REMAP_FILE_RESET, MSG_REMAP_FILE_RESET,
MSG_INPUT_BIND_PRESS,
MSG_INPUT_BIND_RELEASE,
MSG_INPUT_BIND_TIMEOUT,
MSG_INPUT_BIND_HOLD,
MSG_OVERRIDE_UNLOAD, MSG_OVERRIDE_UNLOAD,
MSG_SHADER_PRESET_SAVED_SUCCESSFULLY, MSG_SHADER_PRESET_SAVED_SUCCESSFULLY,
MSG_SHADER_PRESET_REMOVED_SUCCESSFULLY, MSG_SHADER_PRESET_REMOVED_SUCCESSFULLY,
@ -961,7 +965,6 @@ enum msg_hash_enums
MENU_LABEL(INPUT_REMAPPING_DIRECTORY), MENU_LABEL(INPUT_REMAPPING_DIRECTORY),
MENU_ENUM_LABEL_INPUT_BIND_MODE,
MENU_ENUM_LABEL_INPUT_OVERLAY, MENU_ENUM_LABEL_INPUT_OVERLAY,
MENU_ENUM_LABEL_INPUT_OSK_OVERLAY, MENU_ENUM_LABEL_INPUT_OSK_OVERLAY,

View File

@ -2049,13 +2049,6 @@ bool runloop_environment_cb(unsigned cmd, void *data)
case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS: case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS:
{ {
static const char *libretro_btn_desc[] = {
"B (bottom)", "Y (left)", "Select", "Start",
"D-Pad Up", "D-Pad Down", "D-Pad Left", "D-Pad Right",
"A (right)", "X (up)",
"L", "R", "L2", "R2", "L3", "R3",
};
if (sys_info) if (sys_info)
{ {
unsigned retro_id; unsigned retro_id;
@ -2156,15 +2149,19 @@ bool runloop_environment_cb(unsigned cmd, void *data)
{ {
unsigned mapped_port = settings->uints.input_remap_ports[p]; unsigned mapped_port = settings->uints.input_remap_ports[p];
RARCH_DBG(" %s %u:\n", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT), p + 1);
for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++) for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++)
{ {
const char *description = sys_info->input_desc_btn[mapped_port][retro_id]; unsigned bind_index = input_config_bind_order[retro_id];
const char *description = sys_info->input_desc_btn[mapped_port][bind_index];
if (!description) if (!description)
continue; continue;
RARCH_DBG(" RetroPad, Port %u, Button \"%s\" => \"%s\"\n", RARCH_DBG(" \"%s\" => \"%s\"\n",
p + 1, libretro_btn_desc[retro_id], description); msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B + bind_index),
description);
} }
} }
} }
@ -2802,10 +2799,12 @@ bool runloop_environment_cb(unsigned cmd, void *data)
if (log_level != RETRO_LOG_DEBUG) if (log_level != RETRO_LOG_DEBUG)
continue; continue;
RARCH_DBG(" Controller port: %u\n", i + 1); RARCH_DBG(" %s %u:\n", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT), i + 1);
for (j = 0; j < info[i].num_types; j++) for (j = 0; j < info[i].num_types; j++)
RARCH_DBG(" %s (ID: %u)\n", info[i].types[j].desc, if (info[i].types[j].desc)
RARCH_DBG(" \"%s\" (%u)\n",
info[i].types[j].desc,
info[i].types[j].id); info[i].types[j].id);
} }