diff --git a/Makefile.common b/Makefile.common
index 7103b379cb..a48f3d7399 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -1048,6 +1048,7 @@ endif
ifeq ($(HAVE_MENU_COMMON), 1)
OBJ += menu/menu_setting.o \
+ menu/menu_driver.o \
menu/cbs/menu_cbs_ok.o \
menu/cbs/menu_cbs_cancel.o \
menu/cbs/menu_cbs_select.o \
diff --git a/gfx/gfx_widgets.c b/gfx/gfx_widgets.c
index c9c147b587..457c6ed495 100644
--- a/gfx/gfx_widgets.c
+++ b/gfx/gfx_widgets.c
@@ -159,6 +159,7 @@ static float gfx_display_get_widget_dpi_scale(
return adjusted_scale;
}
+#if defined(HAVE_MENU) && defined(HAVE_XMB)
static float gfx_display_get_widget_pixel_scale(
gfx_display_t *p_disp,
settings_t *settings,
@@ -237,7 +238,7 @@ static float gfx_display_get_widget_pixel_scale(
return adjusted_scale;
}
-
+#endif
static void msg_widget_msg_transition_animation_done(void *userdata)
{
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 22154db23b..bc90340ce9 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -1369,6 +1369,7 @@ MENU
#endif
#ifdef HAVE_MENU
+#include "../menu/menu_driver.c"
#include "../menu/menu_setting.c"
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
#include "../menu/menu_screensaver.c"
diff --git a/menu/menu_driver.c b/menu/menu_driver.c
new file mode 100644
index 0000000000..496d7dc44a
--- /dev/null
+++ b/menu/menu_driver.c
@@ -0,0 +1,1375 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2011-2021 - Daniel De Matteis
+ * Copyright (C) 2014-2017 - Jean-André Santoni
+ * Copyright (C) 2016-2019 - Andrés Suárez
+ * Copyright (C) 2016-2019 - Brad Parker
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#if defined(HAVE_CONFIG_H)
+#include "../config.h"
+#endif
+
+#include
+#include "menu_driver.h"
+
+#ifdef HAVE_LANGEXTRA
+/* This file has a UTF8 BOM, we assume HAVE_LANGEXTRA
+ * is only enabled for compilers that can support this. */
+#include "../input/input_osk_utf8_pages.h"
+#endif
+
+#ifdef HAVE_CHEEVOS
+#include "../cheevos/cheevos_menu.h"
+#endif
+
+#include "../input/input_driver.h"
+#include "../input/input_remapping.h"
+#include "../performance_counters.h"
+
+static bool menu_should_pop_stack(const char *label)
+{
+ /* > Info box */
+ if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_INFO_SCREEN)))
+ return true;
+ /* > Help box */
+ if (string_starts_with_size(label, "help", STRLEN_CONST("help")))
+ if (
+ string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_CONTROLS))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_WHAT_IS_A_CORE))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_LOADING_CONTENT))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_SCANNING_CONTENT))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_CHANGE_VIRTUAL_GAMEPAD))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_AUDIO_VIDEO_TROUBLESHOOTING))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_SEND_DEBUG_INFO))
+ || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_DESCRIPTION)))
+ return true;
+ if (
+ string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_DESCRIPTION)))
+ return true;
+ return false;
+}
+
+/* Used to close an active message box (help or info)
+ * TODO/FIXME: The way that message boxes are handled
+ * is complete garbage. generic_menu_iterate() and
+ * message boxes in general need a total rewrite.
+ * I consider this current 'close_messagebox' a hack,
+ * but at least it prevents undefined/dangerous
+ * behaviour... */
+void menu_input_pointer_close_messagebox(struct menu_state *menu_st)
+{
+ const char *label = NULL;
+
+ /* Determine whether this is a help or info
+ * message box */
+ file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
+ NULL, &label, NULL, NULL);
+
+ /* Pop stack, if required */
+ if (menu_should_pop_stack(label))
+ {
+ size_t selection = menu_st->selection_ptr;
+ size_t new_selection = selection;
+
+ menu_entries_pop_stack(&new_selection, 0, 0);
+ menu_st->selection_ptr = selection;
+ }
+}
+
+
+float menu_input_get_dpi(
+ menu_handle_t *menu,
+ gfx_display_t *p_disp,
+ unsigned video_width,
+ unsigned video_height)
+{
+ static unsigned last_video_width = 0;
+ static unsigned last_video_height = 0;
+ static float dpi = 0.0f;
+ static bool dpi_cached = false;
+
+ /* Regardless of menu driver, need 'actual' screen DPI
+ * Note: DPI is a fixed hardware property. To minimise performance
+ * overheads we therefore only call video_context_driver_get_metrics()
+ * on first run, or when the current video resolution changes */
+ if (!dpi_cached ||
+ (video_width != last_video_width) ||
+ (video_height != last_video_height))
+ {
+ gfx_ctx_metrics_t mets;
+ /* Note: If video_context_driver_get_metrics() fails,
+ * we don't know what happened to dpi - so ensure it
+ * is reset to a sane value */
+
+ mets.type = DISPLAY_METRIC_DPI;
+ mets.value = &dpi;
+ if (!video_context_driver_get_metrics(&mets))
+ dpi = 0.0f;
+
+ dpi_cached = true;
+ last_video_width = video_width;
+ last_video_height = video_height;
+ }
+
+ /* RGUI uses a framebuffer texture, which means we
+ * operate in menu space, not screen space.
+ * DPI in a traditional sense is therefore meaningless,
+ * so generate a substitute value based upon framebuffer
+ * dimensions */
+ if (dpi > 0.0f)
+ {
+ bool menu_has_fb =
+ menu->driver_ctx
+ && menu->driver_ctx->set_texture;
+
+ /* Read framebuffer info? */
+ if (menu_has_fb)
+ {
+ unsigned fb_height = p_disp->framebuf_height;
+ /* Rationale for current 'DPI' determination method:
+ * - Divide screen height by DPI, to get number of vertical
+ * '1 inch' squares
+ * - Divide RGUI framebuffer height by number of vertical
+ * '1 inch' squares to get number of menu space pixels
+ * per inch
+ * This is crude, but should be sufficient... */
+ return ((float)fb_height / (float)video_height) * dpi;
+ }
+ }
+
+ return dpi;
+}
+
+bool input_event_osk_show_symbol_pages(
+ menu_handle_t *menu)
+{
+#if defined(HAVE_LANGEXTRA)
+#if defined(HAVE_RGUI)
+ bool menu_has_fb = (menu &&
+ menu->driver_ctx &&
+ menu->driver_ctx->set_texture);
+ unsigned language = *msg_hash_get_uint(MSG_HASH_USER_LANGUAGE);
+ return !menu_has_fb ||
+ ((language == RETRO_LANGUAGE_JAPANESE) ||
+ (language == RETRO_LANGUAGE_KOREAN) ||
+ (language == RETRO_LANGUAGE_CHINESE_SIMPLIFIED) ||
+ (language == RETRO_LANGUAGE_CHINESE_TRADITIONAL));
+#else /* HAVE_RGUI */
+ return true;
+#endif /* HAVE_RGUI */
+#else /* HAVE_LANGEXTRA */
+ return false;
+#endif /* HAVE_LANGEXTRA */
+}
+
+static void menu_driver_list_free(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ menu_ctx_list_t *list)
+{
+ if (menu_driver_ctx)
+ if (menu_driver_ctx->list_free)
+ menu_driver_ctx->list_free(
+ list->list, list->idx, list->list_size);
+
+ if (list->list)
+ {
+ file_list_free_userdata (list->list, list->idx);
+ file_list_free_actiondata(list->list, list->idx);
+ }
+}
+
+static void menu_list_free_list(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ file_list_t *list)
+{
+ unsigned i;
+
+ for (i = 0; i < list->size; i++)
+ {
+ menu_ctx_list_t list_info;
+
+ list_info.list = list;
+ list_info.idx = i;
+ list_info.list_size = list->size;
+
+ menu_driver_list_free(menu_driver_ctx, &list_info);
+ }
+
+ file_list_free(list);
+}
+
+bool menu_list_pop_stack(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ void *menu_userdata,
+ menu_list_t *list,
+ size_t idx,
+ size_t *directory_ptr)
+{
+ file_list_t *menu_list = MENU_LIST_GET(list, (unsigned)idx);
+
+ if (!menu_list)
+ return false;
+
+ if (menu_list->size != 0)
+ {
+ menu_ctx_list_t list_info;
+
+ list_info.list = menu_list;
+ list_info.idx = menu_list->size - 1;
+ list_info.list_size = menu_list->size - 1;
+
+ menu_driver_list_free(menu_driver_ctx, &list_info);
+ }
+
+ file_list_pop(menu_list, directory_ptr);
+ if ( menu_driver_ctx &&
+ menu_driver_ctx->list_set_selection)
+ menu_driver_ctx->list_set_selection(menu_userdata,
+ menu_list);
+
+ return true;
+}
+
+static int menu_list_flush_stack_type(const char *needle, const char *label,
+ unsigned type, unsigned final_type)
+{
+ return needle ? !string_is_equal(needle, label) : (type != final_type);
+}
+
+void menu_list_flush_stack(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ void *menu_userdata,
+ struct menu_state *menu_st,
+ menu_list_t *list,
+ size_t idx, const char *needle, unsigned final_type)
+{
+ bool refresh = false;
+ const char *path = NULL;
+ const char *label = NULL;
+ unsigned type = 0;
+ size_t entry_idx = 0;
+ file_list_t *menu_list = MENU_LIST_GET(list, (unsigned)idx);
+
+ menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
+
+ if (menu_list && menu_list->size)
+ file_list_get_at_offset(menu_list, menu_list->size - 1, &path, &label, &type, &entry_idx);
+
+ while (menu_list_flush_stack_type(
+ needle, label, type, final_type) != 0)
+ {
+ bool refresh = false;
+ size_t new_selection_ptr = menu_st->selection_ptr;
+ bool wont_pop_stack = (MENU_LIST_GET_STACK_SIZE(list, idx) <= 1);
+ if (wont_pop_stack)
+ break;
+
+ if (menu_driver_ctx->list_cache)
+ menu_driver_ctx->list_cache(menu_userdata,
+ MENU_LIST_PLAIN, 0);
+
+ menu_list_pop_stack(menu_driver_ctx,
+ menu_userdata,
+ list, idx, &new_selection_ptr);
+
+ menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
+
+ menu_st->selection_ptr = new_selection_ptr;
+ menu_list = MENU_LIST_GET(list, (unsigned)idx);
+
+ if (menu_list && menu_list->size)
+ file_list_get_at_offset(menu_list, menu_list->size - 1, &path, &label, &type, &entry_idx);
+ }
+}
+
+static void menu_list_free(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ menu_list_t *menu_list)
+{
+ if (!menu_list)
+ return;
+
+ if (menu_list->menu_stack)
+ {
+ unsigned i;
+
+ for (i = 0; i < menu_list->menu_stack_size; i++)
+ {
+ if (!menu_list->menu_stack[i])
+ continue;
+
+ menu_list_free_list(menu_driver_ctx,
+ menu_list->menu_stack[i]);
+ menu_list->menu_stack[i] = NULL;
+ }
+
+ free(menu_list->menu_stack);
+ }
+
+ if (menu_list->selection_buf)
+ {
+ unsigned i;
+
+ for (i = 0; i < menu_list->selection_buf_size; i++)
+ {
+ if (!menu_list->selection_buf[i])
+ continue;
+
+ menu_list_free_list(menu_driver_ctx,
+ menu_list->selection_buf[i]);
+ menu_list->selection_buf[i] = NULL;
+ }
+
+ free(menu_list->selection_buf);
+ }
+
+ free(menu_list);
+}
+
+static menu_list_t *menu_list_new(const menu_ctx_driver_t *menu_driver_ctx)
+{
+ unsigned i;
+ menu_list_t *list = (menu_list_t*)malloc(sizeof(*list));
+
+ if (!list)
+ return NULL;
+
+ list->menu_stack_size = 1;
+ list->selection_buf_size = 1;
+ list->selection_buf = NULL;
+ list->menu_stack = (file_list_t**)
+ calloc(list->menu_stack_size, sizeof(*list->menu_stack));
+
+ if (!list->menu_stack)
+ goto error;
+
+ list->selection_buf = (file_list_t**)
+ calloc(list->selection_buf_size, sizeof(*list->selection_buf));
+
+ if (!list->selection_buf)
+ goto error;
+
+ for (i = 0; i < list->menu_stack_size; i++)
+ {
+ list->menu_stack[i] = (file_list_t*)
+ malloc(sizeof(*list->menu_stack[i]));
+ list->menu_stack[i]->list = NULL;
+ list->menu_stack[i]->capacity = 0;
+ list->menu_stack[i]->size = 0;
+ }
+
+ for (i = 0; i < list->selection_buf_size; i++)
+ {
+ list->selection_buf[i] = (file_list_t*)
+ malloc(sizeof(*list->selection_buf[i]));
+ list->selection_buf[i]->list = NULL;
+ list->selection_buf[i]->capacity = 0;
+ list->selection_buf[i]->size = 0;
+ }
+
+ return list;
+
+error:
+ menu_list_free(menu_driver_ctx, list);
+ return NULL;
+}
+
+
+int menu_input_key_bind_set_mode_common(
+ struct menu_state *menu_st,
+ struct menu_bind_state *binds,
+ enum menu_input_binds_ctl_state state,
+ rarch_setting_t *setting,
+ settings_t *settings)
+{
+ menu_displaylist_info_t info;
+ unsigned bind_type = 0;
+ struct retro_keybind *keybind = NULL;
+ unsigned index_offset = setting->index_offset;
+ menu_list_t *menu_list = menu_st->entries.list;
+ file_list_t *menu_stack = menu_list ? MENU_LIST_GET(menu_list, (unsigned)0) : NULL;
+ size_t selection = menu_st->selection_ptr;
+
+ menu_displaylist_info_init(&info);
+
+ switch (state)
+ {
+ case MENU_INPUT_BINDS_CTL_BIND_SINGLE:
+ keybind = (struct retro_keybind*)setting->value.target.keybind;
+
+ if (!keybind)
+ return -1;
+
+ bind_type = setting_get_bind_type(setting);
+
+ binds->begin = bind_type;
+ binds->last = bind_type;
+ binds->output = keybind;
+ binds->buffer = *(binds->output);
+ binds->user = index_offset;
+
+ info.list = menu_stack;
+ info.type = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD;
+ info.directory_ptr = selection;
+ info.enum_idx = MENU_ENUM_LABEL_CUSTOM_BIND;
+ info.label = strdup(
+ msg_hash_to_str(MENU_ENUM_LABEL_CUSTOM_BIND));
+ break;
+ case MENU_INPUT_BINDS_CTL_BIND_ALL:
+ binds->output = &input_config_binds[index_offset][0];
+ binds->buffer = *(binds->output);
+ binds->begin = MENU_SETTINGS_BIND_BEGIN;
+ binds->last = MENU_SETTINGS_BIND_LAST;
+
+ info.list = menu_stack;
+ info.type = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD;
+ info.directory_ptr = selection;
+ info.enum_idx = MENU_ENUM_LABEL_CUSTOM_BIND_ALL;
+ info.label = strdup(
+ msg_hash_to_str(MENU_ENUM_LABEL_CUSTOM_BIND_ALL));
+ break;
+ default:
+ case MENU_INPUT_BINDS_CTL_BIND_NONE:
+ return 0;
+ }
+
+ if (menu_displaylist_ctl(DISPLAYLIST_INFO, &info, settings))
+ menu_displaylist_process(&info);
+ menu_displaylist_info_free(&info);
+
+ return 0;
+}
+
+#ifdef ANDROID
+bool menu_input_key_bind_poll_find_hold_pad(
+ struct menu_bind_state *new_state,
+ struct retro_keybind * output,
+ unsigned p)
+{
+ unsigned a, b, h;
+ const struct menu_bind_state_port *n =
+ (const struct menu_bind_state_port*)
+ &new_state->state[p];
+
+ for (b = 0; b < MENU_MAX_MBUTTONS; b++)
+ {
+ bool iterate = n->mouse_buttons[b];
+
+ if (!iterate)
+ continue;
+
+ switch (b)
+ {
+ case RETRO_DEVICE_ID_MOUSE_LEFT:
+ case RETRO_DEVICE_ID_MOUSE_RIGHT:
+ case RETRO_DEVICE_ID_MOUSE_MIDDLE:
+ case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
+ case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
+ case RETRO_DEVICE_ID_MOUSE_WHEELUP:
+ case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
+ case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
+ case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
+ output->mbutton = b;
+ return true;
+ }
+ }
+
+ for (b = 0; b < MENU_MAX_BUTTONS; b++)
+ {
+ bool iterate = n->buttons[b];
+
+ if (!iterate)
+ continue;
+
+ output->joykey = b;
+ output->joyaxis = AXIS_NONE;
+ return true;
+ }
+
+ /* Axes are a bit tricky ... */
+ for (a = 0; a < MENU_MAX_AXES; a++)
+ {
+ if (abs(n->axes[a]) >= 20000)
+ {
+ /* Take care of case where axis rests on +/- 0x7fff
+ * (e.g. 360 controller on Linux) */
+ output->joyaxis = n->axes[a] > 0
+ ? AXIS_POS(a) : AXIS_NEG(a);
+ output->joykey = NO_BTN;
+
+ return true;
+ }
+ }
+
+ for (h = 0; h < MENU_MAX_HATS; h++)
+ {
+ uint16_t trigged = n->hats[h];
+ uint16_t sane_trigger = 0;
+
+ if (trigged & HAT_UP_MASK)
+ sane_trigger = HAT_UP_MASK;
+ else if (trigged & HAT_DOWN_MASK)
+ sane_trigger = HAT_DOWN_MASK;
+ else if (trigged & HAT_LEFT_MASK)
+ sane_trigger = HAT_LEFT_MASK;
+ else if (trigged & HAT_RIGHT_MASK)
+ sane_trigger = HAT_RIGHT_MASK;
+
+ if (sane_trigger)
+ {
+ output->joykey = HAT_MAP(h, sane_trigger);
+ output->joyaxis = AXIS_NONE;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool menu_input_key_bind_poll_find_hold(
+ unsigned max_users,
+ struct menu_bind_state *new_state,
+ struct retro_keybind * output)
+{
+ if (new_state)
+ {
+ unsigned i;
+
+ for (i = 0; i < max_users; i++)
+ {
+ if (menu_input_key_bind_poll_find_hold_pad(new_state, output, i))
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
+
+bool menu_input_key_bind_poll_find_trigger_pad(
+ struct menu_bind_state *state,
+ struct menu_bind_state *new_state,
+ struct retro_keybind * output,
+ unsigned p)
+{
+ unsigned a, b, h;
+ const struct menu_bind_state_port *n = (const struct menu_bind_state_port*)
+ &new_state->state[p];
+ const struct menu_bind_state_port *o = (const struct menu_bind_state_port*)
+ &state->state[p];
+
+ for (b = 0; b < MENU_MAX_MBUTTONS; b++)
+ {
+ bool iterate = n->mouse_buttons[b] && !o->mouse_buttons[b];
+
+ if (!iterate)
+ continue;
+
+ switch (b)
+ {
+ case RETRO_DEVICE_ID_MOUSE_LEFT:
+ case RETRO_DEVICE_ID_MOUSE_RIGHT:
+ case RETRO_DEVICE_ID_MOUSE_MIDDLE:
+ case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
+ case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
+ case RETRO_DEVICE_ID_MOUSE_WHEELUP:
+ case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
+ case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
+ case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
+ output->mbutton = b;
+ return true;
+ }
+ }
+
+ for (b = 0; b < MENU_MAX_BUTTONS; b++)
+ {
+ bool iterate = n->buttons[b] && !o->buttons[b];
+
+ if (!iterate)
+ continue;
+
+ output->joykey = b;
+ output->joyaxis = AXIS_NONE;
+ return true;
+ }
+
+ /* Axes are a bit tricky ... */
+ for (a = 0; a < MENU_MAX_AXES; a++)
+ {
+ int locked_distance = abs(n->axes[a] -
+ new_state->axis_state[p].locked_axes[a]);
+ int rested_distance = abs(n->axes[a] -
+ new_state->axis_state[p].rested_axes[a]);
+
+ if (abs(n->axes[a]) >= 20000 &&
+ locked_distance >= 20000 &&
+ rested_distance >= 20000)
+ {
+ /* Take care of case where axis rests on +/- 0x7fff
+ * (e.g. 360 controller on Linux) */
+ output->joyaxis = n->axes[a] > 0
+ ? AXIS_POS(a) : AXIS_NEG(a);
+ output->joykey = NO_BTN;
+
+ /* Lock the current axis */
+ new_state->axis_state[p].locked_axes[a] =
+ n->axes[a] > 0 ?
+ 0x7fff : -0x7fff;
+ return true;
+ }
+
+ if (locked_distance >= 20000) /* Unlock the axis. */
+ new_state->axis_state[p].locked_axes[a] = 0;
+ }
+
+ for (h = 0; h < MENU_MAX_HATS; h++)
+ {
+ uint16_t trigged = n->hats[h] & (~o->hats[h]);
+ uint16_t sane_trigger = 0;
+
+ if (trigged & HAT_UP_MASK)
+ sane_trigger = HAT_UP_MASK;
+ else if (trigged & HAT_DOWN_MASK)
+ sane_trigger = HAT_DOWN_MASK;
+ else if (trigged & HAT_LEFT_MASK)
+ sane_trigger = HAT_LEFT_MASK;
+ else if (trigged & HAT_RIGHT_MASK)
+ sane_trigger = HAT_RIGHT_MASK;
+
+ if (sane_trigger)
+ {
+ output->joykey = HAT_MAP(h, sane_trigger);
+ output->joyaxis = AXIS_NONE;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool menu_input_key_bind_poll_find_trigger(
+ unsigned max_users,
+ struct menu_bind_state *state,
+ struct menu_bind_state *new_state,
+ struct retro_keybind * output)
+{
+ if (state && new_state)
+ {
+ unsigned i;
+
+ for (i = 0; i < max_users; i++)
+ {
+ if (menu_input_key_bind_poll_find_trigger_pad(
+ state, new_state, output, i))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+void menu_input_key_bind_poll_bind_get_rested_axes(
+ const input_device_driver_t *joypad,
+ const input_device_driver_t *sec_joypad,
+ struct menu_bind_state *state)
+{
+ unsigned a;
+ unsigned port = state->port;
+
+ if (joypad)
+ {
+ /* poll only the relevant port */
+ for (a = 0; a < MENU_MAX_AXES; a++)
+ {
+ if (AXIS_POS(a) != AXIS_NONE)
+ state->axis_state[port].rested_axes[a] =
+ joypad->axis(port, AXIS_POS(a));
+ if (AXIS_NEG(a) != AXIS_NONE)
+ state->axis_state[port].rested_axes[a] +=
+ joypad->axis(port, AXIS_NEG(a));
+ }
+ }
+
+ if (sec_joypad)
+ {
+ /* poll only the relevant port */
+ for (a = 0; a < MENU_MAX_AXES; a++)
+ {
+ if (AXIS_POS(a) != AXIS_NONE)
+ state->axis_state[port].rested_axes[a] = sec_joypad->axis(port, AXIS_POS(a));
+
+ if (AXIS_NEG(a) != AXIS_NONE)
+ state->axis_state[port].rested_axes[a] += sec_joypad->axis(port, AXIS_NEG(a));
+ }
+ }
+}
+
+void input_event_osk_iterate(
+ void *osk_grid,
+ enum osk_type osk_idx)
+{
+#ifndef HAVE_LANGEXTRA
+ /* If HAVE_LANGEXTRA is not defined, define some ASCII-friendly pages. */
+ static const char *uppercase_grid[] = {
+ "1","2","3","4","5","6","7","8","9","0","Bksp",
+ "Q","W","E","R","T","Y","U","I","O","P","Enter",
+ "A","S","D","F","G","H","J","K","L","+","Lower",
+ "Z","X","C","V","B","N","M"," ","_","/","Next"};
+ static const char *lowercase_grid[] = {
+ "1","2","3","4","5","6","7","8","9","0","Bksp",
+ "q","w","e","r","t","y","u","i","o","p","Enter",
+ "a","s","d","f","g","h","j","k","l","@","Upper",
+ "z","x","c","v","b","n","m"," ","-",".","Next"};
+ static const char *symbols_page1_grid[] = {
+ "1","2","3","4","5","6","7","8","9","0","Bksp",
+ "!","\"","#","$","%","&","'","*","(",")","Enter",
+ "+",",","-","~","/",":",";","=","<",">","Lower",
+ "?","@","[","\\","]","^","_","|","{","}","Next"};
+#endif
+ switch (osk_idx)
+ {
+#ifdef HAVE_LANGEXTRA
+ case OSK_HIRAGANA_PAGE1:
+ memcpy(osk_grid,
+ hiragana_page1_grid,
+ sizeof(hiragana_page1_grid));
+ break;
+ case OSK_HIRAGANA_PAGE2:
+ memcpy(osk_grid,
+ hiragana_page2_grid,
+ sizeof(hiragana_page2_grid));
+ break;
+ case OSK_KATAKANA_PAGE1:
+ memcpy(osk_grid,
+ katakana_page1_grid,
+ sizeof(katakana_page1_grid));
+ break;
+ case OSK_KATAKANA_PAGE2:
+ memcpy(osk_grid,
+ katakana_page2_grid,
+ sizeof(katakana_page2_grid));
+ break;
+#endif
+ case OSK_SYMBOLS_PAGE1:
+ memcpy(osk_grid,
+ symbols_page1_grid,
+ sizeof(uppercase_grid));
+ break;
+ case OSK_UPPERCASE_LATIN:
+ memcpy(osk_grid,
+ uppercase_grid,
+ sizeof(uppercase_grid));
+ break;
+ case OSK_LOWERCASE_LATIN:
+ default:
+ memcpy(osk_grid,
+ lowercase_grid,
+ sizeof(lowercase_grid));
+ break;
+ }
+}
+
+void menu_input_get_mouse_hw_state(
+ gfx_display_t *p_disp,
+ menu_handle_t *menu,
+ input_driver_state_t *input_driver_st,
+ input_driver_t *current_input,
+ const input_device_driver_t *joypad,
+ const input_device_driver_t *sec_joypad,
+ bool keyboard_mapping_blocked,
+ bool menu_mouse_enable,
+ bool input_overlay_enable,
+ bool overlay_active,
+ menu_input_pointer_hw_state_t *hw_state)
+{
+ rarch_joypad_info_t joypad_info;
+ static int16_t last_x = 0;
+ static int16_t last_y = 0;
+ static bool last_select_pressed = false;
+ static bool last_cancel_pressed = false;
+ bool menu_has_fb =
+ (menu &&
+ menu->driver_ctx &&
+ menu->driver_ctx->set_texture);
+ bool state_inited = current_input &&
+ current_input->input_state;
+#ifdef HAVE_OVERLAY
+ /* Menu pointer controls are ignored when overlays are enabled. */
+ if (overlay_active)
+ menu_mouse_enable = false;
+#endif
+
+ /* Easiest to set inactive by default, and toggle
+ * when input is detected */
+ hw_state->active = false;
+ hw_state->x = 0;
+ hw_state->y = 0;
+ hw_state->select_pressed = false;
+ hw_state->cancel_pressed = false;
+ hw_state->up_pressed = false;
+ hw_state->down_pressed = false;
+ hw_state->left_pressed = false;
+ hw_state->right_pressed = false;
+
+ if (!menu_mouse_enable)
+ return;
+
+ joypad_info.joy_idx = 0;
+ joypad_info.auto_binds = NULL;
+ joypad_info.axis_threshold = 0.0f;
+
+ /* X/Y position */
+ if (state_inited)
+ {
+ if ((hw_state->x = current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RARCH_DEVICE_MOUSE_SCREEN,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_X)) != last_x)
+ hw_state->active = true;
+ if ((hw_state->y = current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RARCH_DEVICE_MOUSE_SCREEN,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_Y)) != last_y)
+ hw_state->active = true;
+ }
+
+ last_x = hw_state->x;
+ last_y = hw_state->y;
+
+ /* > X/Y position adjustment */
+ if (menu_has_fb)
+ {
+ /* RGUI uses a framebuffer texture + custom viewports,
+ * which means we have to convert from screen space to
+ * menu space... */
+ struct video_viewport vp = {0};
+ /* Read display/framebuffer info */
+ unsigned fb_width = p_disp->framebuf_width;
+ unsigned fb_height = p_disp->framebuf_height;
+
+ video_driver_get_viewport_info(&vp);
+
+ /* Adjust X position */
+ hw_state->x = (int16_t)(((float)(hw_state->x - vp.x) / (float)vp.width) * (float)fb_width);
+ hw_state->x = (hw_state->x < 0) ? (0 ) : hw_state->x;
+ hw_state->x = (hw_state->x >= fb_width) ? (fb_width -1) : hw_state->x;
+
+ /* Adjust Y position */
+ hw_state->y = (int16_t)(((float)(hw_state->y - vp.y) / (float)vp.height) * (float)fb_height);
+ hw_state->y = (hw_state->y < 0) ? (0 ) : hw_state->y;
+ hw_state->y = (hw_state->y >= fb_height) ? (fb_height-1) : hw_state->y;
+ }
+
+ if (state_inited)
+ {
+ /* Select (LMB)
+ * Note that releasing select also counts as activity */
+ hw_state->select_pressed = (bool)
+ current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RETRO_DEVICE_MOUSE,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_LEFT);
+ /* Cancel (RMB)
+ * Note that releasing cancel also counts as activity */
+ hw_state->cancel_pressed = (bool)
+ current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RETRO_DEVICE_MOUSE,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_RIGHT);
+ /* Up (mouse wheel up) */
+ if ((hw_state->up_pressed = (bool)
+ current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RETRO_DEVICE_MOUSE,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_WHEELUP)))
+ hw_state->active = true;
+ /* Down (mouse wheel down) */
+ if ((hw_state->down_pressed = (bool)
+ current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RETRO_DEVICE_MOUSE,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_WHEELDOWN)))
+ hw_state->active = true;
+ /* Left (mouse wheel horizontal left) */
+ if ((hw_state->left_pressed = (bool)
+ current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RETRO_DEVICE_MOUSE,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN)))
+ hw_state->active = true;
+ /* Right (mouse wheel horizontal right) */
+ if ((hw_state->right_pressed = (bool)
+ current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info,
+ NULL,
+ keyboard_mapping_blocked,
+ 0,
+ RETRO_DEVICE_MOUSE,
+ 0,
+ RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP)))
+ hw_state->active = true;
+ }
+
+ if (hw_state->select_pressed || (hw_state->select_pressed != last_select_pressed))
+ hw_state->active = true;
+ if (hw_state->cancel_pressed || (hw_state->cancel_pressed != last_cancel_pressed))
+ hw_state->active = true;
+ last_select_pressed = hw_state->select_pressed;
+ last_cancel_pressed = hw_state->cancel_pressed;
+}
+
+void menu_input_get_touchscreen_hw_state(
+ gfx_display_t *p_disp,
+ menu_handle_t *menu,
+ input_driver_state_t *input_driver_st,
+ input_driver_t *current_input,
+ const input_device_driver_t *joypad,
+ const input_device_driver_t *sec_joypad,
+ bool keyboard_mapping_blocked,
+ bool overlay_active,
+ bool pointer_enabled,
+ unsigned input_touch_scale,
+ menu_input_pointer_hw_state_t *hw_state)
+{
+ rarch_joypad_info_t joypad_info;
+ unsigned fb_width, fb_height;
+ int pointer_x = 0;
+ int pointer_y = 0;
+ const struct retro_keybind *binds[MAX_USERS] = {NULL};
+ /* Is a background texture set for the current menu driver?
+ * Checks if the menu framebuffer is set.
+ * This would usually only return true
+ * for framebuffer-based menu drivers, like RGUI. */
+ int pointer_device =
+ (menu && menu->driver_ctx && menu->driver_ctx->set_texture) ?
+ RETRO_DEVICE_POINTER : RARCH_DEVICE_POINTER_SCREEN;
+ static int16_t last_x = 0;
+ static int16_t last_y = 0;
+ static bool last_select_pressed = false;
+ static bool last_cancel_pressed = false;
+
+ /* Easiest to set inactive by default, and toggle
+ * when input is detected */
+ hw_state->active = false;
+
+ /* Touch screens don't have mouse wheels, so these
+ * are always disabled */
+ hw_state->up_pressed = false;
+ hw_state->down_pressed = false;
+ hw_state->left_pressed = false;
+ hw_state->right_pressed = false;
+
+#ifdef HAVE_OVERLAY
+ /* Menu pointer controls are ignored when overlays are enabled. */
+ if (overlay_active)
+ pointer_enabled = false;
+#endif
+
+ /* If touchscreen is disabled, ignore all input */
+ if (!pointer_enabled)
+ {
+ hw_state->x = 0;
+ hw_state->y = 0;
+ hw_state->select_pressed = false;
+ hw_state->cancel_pressed = false;
+ return;
+ }
+
+ /* TODO/FIXME - this should only be used for framebuffer-based
+ * menu drivers like RGUI. Touchscreen input as a whole should
+ * NOT be dependent on this
+ */
+ fb_width = p_disp->framebuf_width;
+ fb_height = p_disp->framebuf_height;
+
+ joypad_info.joy_idx = 0;
+ joypad_info.auto_binds = NULL;
+ joypad_info.axis_threshold = 0.0f;
+
+ /* X pos */
+ if (current_input->input_state)
+ pointer_x = current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info, binds,
+ keyboard_mapping_blocked,
+ 0, pointer_device,
+ 0, RETRO_DEVICE_ID_POINTER_X);
+ hw_state->x = ((pointer_x + 0x7fff) * (int)fb_width) / 0xFFFF;
+ hw_state->x *= input_touch_scale;
+
+ /* > An annoyance - we get different starting positions
+ * depending upon whether pointer_device is
+ * RETRO_DEVICE_POINTER or RARCH_DEVICE_POINTER_SCREEN,
+ * so different 'activity' checks are required to prevent
+ * false positives on first run */
+ if (pointer_device == RARCH_DEVICE_POINTER_SCREEN)
+ {
+ if (hw_state->x != last_x)
+ hw_state->active = true;
+ last_x = hw_state->x;
+ }
+ else
+ {
+ if (pointer_x != last_x)
+ hw_state->active = true;
+ last_x = pointer_x;
+ }
+
+ /* Y pos */
+ if (current_input->input_state)
+ pointer_y = current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info, binds,
+ keyboard_mapping_blocked,
+ 0, pointer_device,
+ 0, RETRO_DEVICE_ID_POINTER_Y);
+ hw_state->y = ((pointer_y + 0x7fff) * (int)fb_height) / 0xFFFF;
+ hw_state->y *= input_touch_scale;
+
+ if (pointer_device == RARCH_DEVICE_POINTER_SCREEN)
+ {
+ if (hw_state->y != last_y)
+ hw_state->active = true;
+ last_y = hw_state->y;
+ }
+ else
+ {
+ if (pointer_y != last_y)
+ hw_state->active = true;
+ last_y = pointer_y;
+ }
+
+ /* Select (touch screen contact)
+ * Note that releasing select also counts as activity */
+ if (current_input->input_state)
+ hw_state->select_pressed = (bool)current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info, binds,
+ keyboard_mapping_blocked,
+ 0, pointer_device,
+ 0, RETRO_DEVICE_ID_POINTER_PRESSED);
+ if (hw_state->select_pressed || (hw_state->select_pressed != last_select_pressed))
+ hw_state->active = true;
+ last_select_pressed = hw_state->select_pressed;
+
+ /* Cancel (touch screen 'back' - don't know what is this, but whatever...)
+ * Note that releasing cancel also counts as activity */
+ if (current_input->input_state)
+ hw_state->cancel_pressed = (bool)current_input->input_state(
+ input_driver_st->current_data,
+ joypad,
+ sec_joypad,
+ &joypad_info, binds,
+ keyboard_mapping_blocked,
+ 0, pointer_device,
+ 0, RARCH_DEVICE_ID_POINTER_BACK);
+ if (hw_state->cancel_pressed || (hw_state->cancel_pressed != last_cancel_pressed))
+ hw_state->active = true;
+ last_cancel_pressed = hw_state->cancel_pressed;
+}
+
+void menu_entries_settings_deinit(struct menu_state *menu_st)
+{
+ menu_setting_free(menu_st->entries.list_settings);
+ if (menu_st->entries.list_settings)
+ free(menu_st->entries.list_settings);
+ menu_st->entries.list_settings = NULL;
+}
+
+int menu_dialog_iterate(
+ menu_dialog_t *p_dialog,
+ settings_t *settings,
+ char *s, size_t len,
+ retro_time_t current_time
+)
+{
+ switch (p_dialog->current_type)
+ {
+ case MENU_DIALOG_WELCOME:
+ {
+ static rarch_timer_t timer;
+
+ if (!timer.timer_begin)
+ {
+ timer.timeout_us = 3 * 1000000;
+ timer.current = cpu_features_get_time_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);
+
+ msg_hash_get_help_enum(
+ MENU_ENUM_LABEL_WELCOME_TO_RETROARCH,
+ s, len);
+
+ if (!timer.timer_end && (timer.timeout_us <= 0))
+ {
+ timer.timer_end = true;
+ timer.timer_begin = false;
+ timer.timeout_end = 0;
+ p_dialog->current_type = MENU_DIALOG_NONE;
+ return 1;
+ }
+ }
+ break;
+ case MENU_DIALOG_HELP_CONTROLS:
+ {
+ unsigned i;
+ char s2[PATH_MAX_LENGTH];
+ const unsigned binds[] = {
+ RETRO_DEVICE_ID_JOYPAD_UP,
+ RETRO_DEVICE_ID_JOYPAD_DOWN,
+ RETRO_DEVICE_ID_JOYPAD_A,
+ RETRO_DEVICE_ID_JOYPAD_B,
+ RETRO_DEVICE_ID_JOYPAD_SELECT,
+ RETRO_DEVICE_ID_JOYPAD_START,
+ RARCH_MENU_TOGGLE,
+ RARCH_QUIT_KEY,
+ RETRO_DEVICE_ID_JOYPAD_X,
+ RETRO_DEVICE_ID_JOYPAD_Y,
+ };
+ char desc[ARRAY_SIZE(binds)][64];
+
+ for (i = 0; i < ARRAY_SIZE(binds); i++)
+ desc[i][0] = '\0';
+
+ for (i = 0; i < ARRAY_SIZE(binds); i++)
+ {
+ const struct retro_keybind *keybind = &input_config_binds[0][binds[i]];
+ const struct retro_keybind *auto_bind =
+ (const struct retro_keybind*)
+ input_config_get_bind_auto(0, binds[i]);
+
+ input_config_get_bind_string(desc[i],
+ keybind, auto_bind, sizeof(desc[i]));
+ }
+
+ s2[0] = '\0';
+
+ msg_hash_get_help_enum(
+ MENU_ENUM_LABEL_VALUE_MENU_ENUM_CONTROLS_PROLOG,
+ s2, sizeof(s2));
+
+ snprintf(s, len,
+ "%s"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n"
+ "[%s]: "
+ "%-20s\n",
+
+ s2,
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_UP),
+ desc[0],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_DOWN),
+ desc[1],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_CONFIRM),
+ desc[2],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_BACK),
+ desc[3],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_INFO),
+ desc[4],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_START),
+ desc[5],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_MENU),
+ desc[6],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_QUIT),
+ desc[7],
+
+ msg_hash_to_str(
+ MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_KEYBOARD),
+ desc[8]
+
+ );
+ }
+ break;
+
+#ifdef HAVE_CHEEVOS
+ case MENU_DIALOG_HELP_CHEEVOS_DESCRIPTION:
+ if (!rcheevos_menu_get_sublabel(p_dialog->current_id, s, len))
+ return 1;
+ break;
+#endif
+
+ case MENU_DIALOG_HELP_WHAT_IS_A_CORE:
+ msg_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_WHAT_IS_A_CORE_DESC,
+ s, len);
+ break;
+ case MENU_DIALOG_HELP_LOADING_CONTENT:
+ msg_hash_get_help_enum(MENU_ENUM_LABEL_LOAD_CONTENT_LIST,
+ s, len);
+ break;
+ case MENU_DIALOG_HELP_CHANGE_VIRTUAL_GAMEPAD:
+ msg_hash_get_help_enum(
+ MENU_ENUM_LABEL_VALUE_HELP_CHANGE_VIRTUAL_GAMEPAD_DESC,
+ s, len);
+ break;
+ case MENU_DIALOG_HELP_AUDIO_VIDEO_TROUBLESHOOTING:
+ msg_hash_get_help_enum(
+ MENU_ENUM_LABEL_VALUE_HELP_AUDIO_VIDEO_TROUBLESHOOTING_DESC,
+ s, len);
+ break;
+ case MENU_DIALOG_HELP_SEND_DEBUG_INFO:
+ msg_hash_get_help_enum(
+ MENU_ENUM_LABEL_VALUE_HELP_SEND_DEBUG_INFO_DESC,
+ s, len);
+ break;
+ case MENU_DIALOG_HELP_SCANNING_CONTENT:
+ msg_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_HELP_SCANNING_CONTENT_DESC,
+ s, len);
+ break;
+ case MENU_DIALOG_HELP_EXTRACT:
+ {
+ bool bundle_finished = settings->bools.bundle_finished;
+
+ msg_hash_get_help_enum(
+ MENU_ENUM_LABEL_VALUE_EXTRACTING_PLEASE_WAIT,
+ s, len);
+
+ if (bundle_finished)
+ {
+ configuration_set_bool(settings,
+ settings->bools.bundle_finished, false);
+ p_dialog->current_type = MENU_DIALOG_NONE;
+ return 1;
+ }
+ }
+ break;
+ case MENU_DIALOG_QUIT_CONFIRM:
+ case MENU_DIALOG_INFORMATION:
+ case MENU_DIALOG_QUESTION:
+ case MENU_DIALOG_WARNING:
+ case MENU_DIALOG_ERROR:
+ msg_hash_get_help_enum(MSG_UNKNOWN,
+ s, len);
+ break;
+ case MENU_DIALOG_NONE:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void menu_entries_list_deinit(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ struct menu_state *menu_st)
+{
+ if (menu_st->entries.list)
+ menu_list_free(menu_driver_ctx, menu_st->entries.list);
+ menu_st->entries.list = NULL;
+}
+
+bool menu_entries_init(
+ struct menu_state *menu_st,
+ const menu_ctx_driver_t *menu_driver_ctx)
+{
+ if (!(menu_st->entries.list = (menu_list_t*)menu_list_new(menu_driver_ctx)))
+ return false;
+ if (!(menu_st->entries.list_settings = menu_setting_new()))
+ return false;
+ return true;
+}
diff --git a/menu/menu_driver.h b/menu/menu_driver.h
index 007baffc5b..0ef6ca69db 100644
--- a/menu/menu_driver.h
+++ b/menu/menu_driver.h
@@ -29,17 +29,22 @@
#include
#include
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
#include "menu_defines.h"
+#include "menu_dialog.h"
#include "menu_input.h"
+#include "../input/input_osk.h"
+#include "menu_input_bind_dialog.h"
#include "menu_entries.h"
#include "menu_shader.h"
#include "../gfx/gfx_display.h"
#include "../gfx/font_driver.h"
+#include "../performance_counters.h"
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
RETRO_BEGIN_DECLS
@@ -51,6 +56,25 @@ RETRO_BEGIN_DECLS
#define MAX_CHEAT_COUNTERS 6000
#endif
+#define SCROLL_INDEX_SIZE (2 * (26 + 2) + 1)
+
+#define POWERSTATE_CHECK_INTERVAL (30 * 1000000)
+#define DATETIME_CHECK_INTERVAL 1000000
+
+#define MENU_MAX_BUTTONS 219
+#define MENU_MAX_AXES 32
+#define MENU_MAX_HATS 4
+#define MENU_MAX_MBUTTONS 32 /* Enough to cover largest libretro constant*/
+
+#define MENU_LIST_GET(list, idx) ((list) ? ((list)->menu_stack[(idx)]) : NULL)
+
+#define MENU_LIST_GET_SELECTION(list, idx) ((list) ? ((list)->selection_buf[(idx)]) : NULL)
+
+#define MENU_LIST_GET_STACK_SIZE(list, idx) ((list)->menu_stack[(idx)]->size)
+
+#define MENU_ENTRIES_GET_SELECTION_BUF_PTR_INTERNAL(menu_st, idx) ((menu_st->entries.list) ? MENU_LIST_GET_SELECTION(menu_st->entries.list, (unsigned)idx) : NULL)
+#define MENU_ENTRIES_NEEDS_REFRESH(menu_st) (!(menu_st->entries_nonblocking_refresh || !menu_st->entries_need_refresh))
+
#define MENU_SETTINGS_CORE_INFO_NONE 0xffff
#define MENU_SETTINGS_CORE_OPTION_NONE 0xffff
#define MENU_SETTINGS_CHEEVOS_NONE 0xffff
@@ -249,6 +273,112 @@ enum menu_settings_type
MENU_SETTINGS_LAST
};
+struct menu_list
+{
+ file_list_t **menu_stack;
+ size_t menu_stack_size;
+ file_list_t **selection_buf;
+ size_t selection_buf_size;
+};
+
+typedef struct menu_list menu_list_t;
+
+struct menu_state
+{
+ /* Timers */
+ retro_time_t current_time_us;
+ retro_time_t powerstate_last_time_us;
+ retro_time_t datetime_last_time_us;
+ retro_time_t input_last_time_us;
+
+ struct
+ {
+ rarch_setting_t *list_settings;
+ menu_list_t *list;
+ size_t begin;
+ } entries;
+ size_t selection_ptr;
+
+ /* Quick jumping indices with L/R.
+ * Rebuilt when parsing directory. */
+ struct
+ {
+ size_t index_list[SCROLL_INDEX_SIZE];
+ unsigned index_size;
+ unsigned acceleration;
+ } scroll;
+
+ /* Storage container for current menu datetime
+ * representation string */
+ char datetime_cache[255];
+
+ /* When generating a menu list in menu_displaylist_build_list(),
+ * the entry with a label matching 'pending_selection' will
+ * be selected automatically */
+ char pending_selection[PATH_MAX_LENGTH];
+
+ /* when enabled, on next iteration the 'Quick Menu' list will
+ * be pushed onto the stack */
+ bool pending_quick_menu;
+ bool prevent_populate;
+ /* The menu driver owns the userdata */
+ bool data_own;
+ /* Flagged when menu entries need to be refreshed */
+ bool entries_need_refresh;
+ bool entries_nonblocking_refresh;
+ /* 'Close Content'-hotkey menu resetting */
+ bool pending_close_content;
+ /* Screensaver status
+ * - Does menu driver support screensaver functionality?
+ * - Is screensaver currently active? */
+ bool screensaver_supported;
+ bool screensaver_active;
+};
+
+typedef struct menu_ctx_load_image
+{
+ void *data;
+ enum menu_image_type type;
+} menu_ctx_load_image_t;
+
+
+
+struct menu_bind_state_port
+{
+ int16_t axes[MENU_MAX_AXES];
+ uint16_t hats[MENU_MAX_HATS];
+ bool mouse_buttons[MENU_MAX_MBUTTONS];
+ bool buttons[MENU_MAX_BUTTONS];
+};
+
+struct menu_bind_axis_state
+{
+ /* Default axis state. */
+ int16_t rested_axes[MENU_MAX_AXES];
+ /* Locked axis state. If we configured an axis,
+ * avoid having the same axis state trigger something again right away. */
+ int16_t locked_axes[MENU_MAX_AXES];
+};
+
+struct menu_bind_state
+{
+ rarch_timer_t timer_timeout;
+ rarch_timer_t timer_hold;
+
+ struct retro_keybind *output;
+ struct retro_keybind buffer;
+
+ struct menu_bind_state_port state[MAX_USERS];
+ struct menu_bind_axis_state axis_state[MAX_USERS];
+
+ unsigned begin;
+ unsigned last;
+ unsigned user;
+ unsigned port;
+
+ bool skip;
+};
+
typedef struct menu_ctx_driver
{
/* Set a framebuffer texture. This is used for instance by RGUI. */
@@ -537,6 +667,108 @@ enum action_iterate_type
ITERATE_TYPE_BIND
};
+int menu_dialog_iterate(
+ menu_dialog_t *p_dialog,
+ settings_t *settings,
+ char *s, size_t len,
+ retro_time_t current_time);
+
+void menu_entries_settings_deinit(struct menu_state *menu_st);
+
+int menu_input_key_bind_set_mode_common(
+ struct menu_state *menu_st,
+ struct menu_bind_state *binds,
+ enum menu_input_binds_ctl_state state,
+ rarch_setting_t *setting,
+ settings_t *settings);
+
+void menu_input_key_bind_poll_bind_get_rested_axes(
+ const input_device_driver_t *joypad,
+ const input_device_driver_t *sec_joypad,
+ struct menu_bind_state *state);
+
+#ifdef ANDROID
+bool menu_input_key_bind_poll_find_hold_pad(
+ struct menu_bind_state *new_state,
+ struct retro_keybind * output,
+ unsigned p);
+#endif
+
+bool menu_input_key_bind_poll_find_trigger_pad(
+ struct menu_bind_state *state,
+ struct menu_bind_state *new_state,
+ struct retro_keybind * output,
+ unsigned p);
+
+bool menu_input_key_bind_poll_find_trigger(
+ unsigned max_users,
+ struct menu_bind_state *state,
+ struct menu_bind_state *new_state,
+ struct retro_keybind * output);
+
+void input_event_osk_iterate(
+ void *osk_grid,
+ enum osk_type osk_idx);
+
+void menu_input_get_mouse_hw_state(
+ gfx_display_t *p_disp,
+ menu_handle_t *menu,
+ input_driver_state_t *input_driver_st,
+ input_driver_t *current_input,
+ const input_device_driver_t *joypad,
+ const input_device_driver_t *sec_joypad,
+ bool keyboard_mapping_blocked,
+ bool menu_mouse_enable,
+ bool input_overlay_enable,
+ bool overlay_active,
+ menu_input_pointer_hw_state_t *hw_state);
+
+void menu_input_get_touchscreen_hw_state(
+ gfx_display_t *p_disp,
+ menu_handle_t *menu,
+ input_driver_state_t *input_driver_st,
+ input_driver_t *current_input,
+ const input_device_driver_t *joypad,
+ const input_device_driver_t *sec_joypad,
+ bool keyboard_mapping_blocked,
+ bool overlay_active,
+ bool pointer_enabled,
+ unsigned input_touch_scale,
+ menu_input_pointer_hw_state_t *hw_state);
+
+bool menu_entries_init(
+ struct menu_state *menu_st,
+ const menu_ctx_driver_t *menu_driver_ctx);
+
+void menu_entries_list_deinit(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ struct menu_state *menu_st);
+
+void menu_list_flush_stack(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ void *menu_userdata,
+ struct menu_state *menu_st,
+ menu_list_t *list,
+ size_t idx, const char *needle, unsigned final_type);
+
+bool menu_list_pop_stack(
+ const menu_ctx_driver_t *menu_driver_ctx,
+ void *menu_userdata,
+ menu_list_t *list,
+ size_t idx,
+ size_t *directory_ptr);
+
+bool input_event_osk_show_symbol_pages(
+ menu_handle_t *menu);
+
+float menu_input_get_dpi(
+ menu_handle_t *menu,
+ gfx_display_t *p_disp,
+ unsigned video_width,
+ unsigned video_height);
+
+void menu_input_pointer_close_messagebox(struct menu_state *menu_st);
+
int generic_menu_entry_action(void *userdata, menu_entry_t *entry, size_t i, enum menu_action action);
extern menu_ctx_driver_t menu_ctx_ozone;
diff --git a/retroarch.c b/retroarch.c
index e3746583f9..1a09cdd4bb 100644
--- a/retroarch.c
+++ b/retroarch.c
@@ -269,12 +269,6 @@
#include "audio/audio_thread_wrapper.h"
#endif
-#ifdef HAVE_LANGEXTRA
-/* This file has a UTF8 BOM, we assume HAVE_LANGEXTRA
- * is only enabled for compilers that can support this. */
-#include "input/input_osk_utf8_pages.h"
-#endif
-
#if defined(HAVE_SDL) || defined(HAVE_SDL2) || defined(HAVE_SDL_DINGUX)
#include "SDL.h"
#endif
@@ -661,210 +655,6 @@ void input_keyboard_mapping_bits(unsigned mode, unsigned key)
#ifdef HAVE_MENU
-static int menu_dialog_iterate(
- menu_dialog_t *p_dialog,
- char *s, size_t len,
- retro_time_t current_time)
-{
- switch (p_dialog->current_type)
- {
- case MENU_DIALOG_WELCOME:
- {
- static rarch_timer_t timer;
-
- if (!timer.timer_begin)
- {
- RARCH_TIMER_BEGIN_NEW_TIME_USEC(timer,
- cpu_features_get_time_usec(),
- 3 * 1000000);
- timer.timer_begin = true;
- timer.timer_end = false;
- }
-
- RARCH_TIMER_TICK(timer, current_time);
-
- msg_hash_get_help_enum(
- MENU_ENUM_LABEL_WELCOME_TO_RETROARCH,
- s, len);
-
- if (!timer.timer_end && RARCH_TIMER_HAS_EXPIRED(timer))
- {
- RARCH_TIMER_END(timer);
- p_dialog->current_type = MENU_DIALOG_NONE;
- return 1;
- }
- }
- break;
- case MENU_DIALOG_HELP_CONTROLS:
- {
- unsigned i;
- char s2[PATH_MAX_LENGTH];
- const unsigned binds[] = {
- RETRO_DEVICE_ID_JOYPAD_UP,
- RETRO_DEVICE_ID_JOYPAD_DOWN,
- RETRO_DEVICE_ID_JOYPAD_A,
- RETRO_DEVICE_ID_JOYPAD_B,
- RETRO_DEVICE_ID_JOYPAD_SELECT,
- RETRO_DEVICE_ID_JOYPAD_START,
- RARCH_MENU_TOGGLE,
- RARCH_QUIT_KEY,
- RETRO_DEVICE_ID_JOYPAD_X,
- RETRO_DEVICE_ID_JOYPAD_Y,
- };
- char desc[ARRAY_SIZE(binds)][64];
-
- for (i = 0; i < ARRAY_SIZE(binds); i++)
- desc[i][0] = '\0';
-
- for (i = 0; i < ARRAY_SIZE(binds); i++)
- {
- const struct retro_keybind *keybind = &input_config_binds[0][binds[i]];
- const struct retro_keybind *auto_bind =
- (const struct retro_keybind*)
- input_config_get_bind_auto(0, binds[i]);
-
- input_config_get_bind_string(desc[i],
- keybind, auto_bind, sizeof(desc[i]));
- }
-
- s2[0] = '\0';
-
- msg_hash_get_help_enum(
- MENU_ENUM_LABEL_VALUE_MENU_ENUM_CONTROLS_PROLOG,
- s2, sizeof(s2));
-
- snprintf(s, len,
- "%s"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n"
- "[%s]: "
- "%-20s\n",
-
- s2,
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_UP),
- desc[0],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_DOWN),
- desc[1],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_CONFIRM),
- desc[2],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_BACK),
- desc[3],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_INFO),
- desc[4],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_START),
- desc[5],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_MENU),
- desc[6],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_QUIT),
- desc[7],
-
- msg_hash_to_str(
- MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_KEYBOARD),
- desc[8]
-
- );
- }
- break;
-
-#ifdef HAVE_CHEEVOS
- case MENU_DIALOG_HELP_CHEEVOS_DESCRIPTION:
- if (!rcheevos_menu_get_sublabel(p_dialog->current_id, s, len))
- return 1;
- break;
-#endif
-
- case MENU_DIALOG_HELP_WHAT_IS_A_CORE:
- msg_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_WHAT_IS_A_CORE_DESC,
- s, len);
- break;
- case MENU_DIALOG_HELP_LOADING_CONTENT:
- msg_hash_get_help_enum(MENU_ENUM_LABEL_LOAD_CONTENT_LIST,
- s, len);
- break;
- case MENU_DIALOG_HELP_CHANGE_VIRTUAL_GAMEPAD:
- msg_hash_get_help_enum(
- MENU_ENUM_LABEL_VALUE_HELP_CHANGE_VIRTUAL_GAMEPAD_DESC,
- s, len);
- break;
- case MENU_DIALOG_HELP_AUDIO_VIDEO_TROUBLESHOOTING:
- msg_hash_get_help_enum(
- MENU_ENUM_LABEL_VALUE_HELP_AUDIO_VIDEO_TROUBLESHOOTING_DESC,
- s, len);
- break;
- case MENU_DIALOG_HELP_SEND_DEBUG_INFO:
- msg_hash_get_help_enum(
- MENU_ENUM_LABEL_VALUE_HELP_SEND_DEBUG_INFO_DESC,
- s, len);
- break;
- case MENU_DIALOG_HELP_SCANNING_CONTENT:
- msg_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_HELP_SCANNING_CONTENT_DESC,
- s, len);
- break;
- case MENU_DIALOG_HELP_EXTRACT:
- {
- struct rarch_state *p_rarch = &rarch_st;
- settings_t *settings = p_rarch->configuration_settings;
- bool bundle_finished = settings->bools.bundle_finished;
-
- msg_hash_get_help_enum(
- MENU_ENUM_LABEL_VALUE_EXTRACTING_PLEASE_WAIT,
- s, len);
-
- if (bundle_finished)
- {
- configuration_set_bool(settings,
- settings->bools.bundle_finished, false);
- p_dialog->current_type = MENU_DIALOG_NONE;
- return 1;
- }
- }
- break;
- case MENU_DIALOG_QUIT_CONFIRM:
- case MENU_DIALOG_INFORMATION:
- case MENU_DIALOG_QUESTION:
- case MENU_DIALOG_WARNING:
- case MENU_DIALOG_ERROR:
- msg_hash_get_help_enum(MSG_UNKNOWN,
- s, len);
- break;
- case MENU_DIALOG_NONE:
- default:
- break;
- }
-
- return 0;
-}
-
void menu_dialog_unset_pending_push(void)
{
struct rarch_state *p_rarch = &rarch_st;
@@ -929,107 +719,6 @@ static bool menu_input_key_bind_custom_bind_keyboard_cb(
return (binds->begin <= binds->last);
}
-static int menu_input_key_bind_set_mode_common(
- struct menu_state *menu_st,
- struct menu_bind_state *binds,
- enum menu_input_binds_ctl_state state,
- rarch_setting_t *setting,
- settings_t *settings)
-{
- menu_displaylist_info_t info;
- unsigned bind_type = 0;
- struct retro_keybind *keybind = NULL;
- unsigned index_offset = setting->index_offset;
- menu_list_t *menu_list = menu_st->entries.list;
- file_list_t *menu_stack = menu_list ? MENU_LIST_GET(menu_list, (unsigned)0) : NULL;
- size_t selection = menu_st->selection_ptr;
-
- menu_displaylist_info_init(&info);
-
- switch (state)
- {
- case MENU_INPUT_BINDS_CTL_BIND_SINGLE:
- keybind = (struct retro_keybind*)setting->value.target.keybind;
-
- if (!keybind)
- return -1;
-
- bind_type = setting_get_bind_type(setting);
-
- binds->begin = bind_type;
- binds->last = bind_type;
- binds->output = keybind;
- binds->buffer = *(binds->output);
- binds->user = index_offset;
-
- info.list = menu_stack;
- info.type = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD;
- info.directory_ptr = selection;
- info.enum_idx = MENU_ENUM_LABEL_CUSTOM_BIND;
- info.label = strdup(
- msg_hash_to_str(MENU_ENUM_LABEL_CUSTOM_BIND));
- break;
- case MENU_INPUT_BINDS_CTL_BIND_ALL:
- binds->output = &input_config_binds[index_offset][0];
- binds->buffer = *(binds->output);
- binds->begin = MENU_SETTINGS_BIND_BEGIN;
- binds->last = MENU_SETTINGS_BIND_LAST;
-
- info.list = menu_stack;
- info.type = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD;
- info.directory_ptr = selection;
- info.enum_idx = MENU_ENUM_LABEL_CUSTOM_BIND_ALL;
- info.label = strdup(
- msg_hash_to_str(MENU_ENUM_LABEL_CUSTOM_BIND_ALL));
- break;
- default:
- case MENU_INPUT_BINDS_CTL_BIND_NONE:
- return 0;
- }
-
- if (menu_displaylist_ctl(DISPLAYLIST_INFO, &info, settings))
- menu_displaylist_process(&info);
- menu_displaylist_info_free(&info);
-
- return 0;
-}
-
-static void menu_input_key_bind_poll_bind_get_rested_axes(
- const input_device_driver_t *joypad,
- const input_device_driver_t *sec_joypad,
- struct menu_bind_state *state)
-{
- unsigned a;
- unsigned port = state->port;
-
- if (joypad)
- {
- /* poll only the relevant port */
- for (a = 0; a < MENU_MAX_AXES; a++)
- {
- if (AXIS_POS(a) != AXIS_NONE)
- state->axis_state[port].rested_axes[a] =
- joypad->axis(port, AXIS_POS(a));
- if (AXIS_NEG(a) != AXIS_NONE)
- state->axis_state[port].rested_axes[a] +=
- joypad->axis(port, AXIS_NEG(a));
- }
- }
-
- if (sec_joypad)
- {
- /* poll only the relevant port */
- for (a = 0; a < MENU_MAX_AXES; a++)
- {
- if (AXIS_POS(a) != AXIS_NONE)
- state->axis_state[port].rested_axes[a] = sec_joypad->axis(port, AXIS_POS(a));
-
- if (AXIS_NEG(a) != AXIS_NONE)
- state->axis_state[port].rested_axes[a] += sec_joypad->axis(port, AXIS_NEG(a));
- }
- }
-}
-
static void menu_input_key_bind_poll_bind_state_internal(
const input_device_driver_t *joypad,
struct menu_bind_state *state,
@@ -1151,236 +840,6 @@ static void menu_input_key_bind_poll_bind_state(
}
}
-static bool menu_input_key_bind_poll_find_trigger_pad(
- struct menu_bind_state *state,
- struct menu_bind_state *new_state,
- struct retro_keybind * output,
- unsigned p)
-{
- unsigned a, b, h;
- const struct menu_bind_state_port *n = (const struct menu_bind_state_port*)
- &new_state->state[p];
- const struct menu_bind_state_port *o = (const struct menu_bind_state_port*)
- &state->state[p];
-
- for (b = 0; b < MENU_MAX_MBUTTONS; b++)
- {
- bool iterate = n->mouse_buttons[b] && !o->mouse_buttons[b];
-
- if (!iterate)
- continue;
-
- switch (b)
- {
- case RETRO_DEVICE_ID_MOUSE_LEFT:
- case RETRO_DEVICE_ID_MOUSE_RIGHT:
- case RETRO_DEVICE_ID_MOUSE_MIDDLE:
- case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
- case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
- case RETRO_DEVICE_ID_MOUSE_WHEELUP:
- case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
- case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
- case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
- output->mbutton = b;
- return true;
- }
- }
-
- for (b = 0; b < MENU_MAX_BUTTONS; b++)
- {
- bool iterate = n->buttons[b] && !o->buttons[b];
-
- if (!iterate)
- continue;
-
- output->joykey = b;
- output->joyaxis = AXIS_NONE;
- return true;
- }
-
- /* Axes are a bit tricky ... */
- for (a = 0; a < MENU_MAX_AXES; a++)
- {
- int locked_distance = abs(n->axes[a] -
- new_state->axis_state[p].locked_axes[a]);
- int rested_distance = abs(n->axes[a] -
- new_state->axis_state[p].rested_axes[a]);
-
- if (abs(n->axes[a]) >= 20000 &&
- locked_distance >= 20000 &&
- rested_distance >= 20000)
- {
- /* Take care of case where axis rests on +/- 0x7fff
- * (e.g. 360 controller on Linux) */
- output->joyaxis = n->axes[a] > 0
- ? AXIS_POS(a) : AXIS_NEG(a);
- output->joykey = NO_BTN;
-
- /* Lock the current axis */
- new_state->axis_state[p].locked_axes[a] =
- n->axes[a] > 0 ?
- 0x7fff : -0x7fff;
- return true;
- }
-
- if (locked_distance >= 20000) /* Unlock the axis. */
- new_state->axis_state[p].locked_axes[a] = 0;
- }
-
- for (h = 0; h < MENU_MAX_HATS; h++)
- {
- uint16_t trigged = n->hats[h] & (~o->hats[h]);
- uint16_t sane_trigger = 0;
-
- if (trigged & HAT_UP_MASK)
- sane_trigger = HAT_UP_MASK;
- else if (trigged & HAT_DOWN_MASK)
- sane_trigger = HAT_DOWN_MASK;
- else if (trigged & HAT_LEFT_MASK)
- sane_trigger = HAT_LEFT_MASK;
- else if (trigged & HAT_RIGHT_MASK)
- sane_trigger = HAT_RIGHT_MASK;
-
- if (sane_trigger)
- {
- output->joykey = HAT_MAP(h, sane_trigger);
- output->joyaxis = AXIS_NONE;
- return true;
- }
- }
-
- return false;
-}
-
-#ifdef ANDROID
-static bool menu_input_key_bind_poll_find_hold_pad(
- struct menu_bind_state *new_state,
- struct retro_keybind * output,
- unsigned p)
-{
- unsigned a, b, h;
- const struct menu_bind_state_port *n =
- (const struct menu_bind_state_port*)
- &new_state->state[p];
-
- for (b = 0; b < MENU_MAX_MBUTTONS; b++)
- {
- bool iterate = n->mouse_buttons[b];
-
- if (!iterate)
- continue;
-
- switch (b)
- {
- case RETRO_DEVICE_ID_MOUSE_LEFT:
- case RETRO_DEVICE_ID_MOUSE_RIGHT:
- case RETRO_DEVICE_ID_MOUSE_MIDDLE:
- case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
- case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
- case RETRO_DEVICE_ID_MOUSE_WHEELUP:
- case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
- case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
- case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
- output->mbutton = b;
- return true;
- }
- }
-
- for (b = 0; b < MENU_MAX_BUTTONS; b++)
- {
- bool iterate = n->buttons[b];
-
- if (!iterate)
- continue;
-
- output->joykey = b;
- output->joyaxis = AXIS_NONE;
- return true;
- }
-
- /* Axes are a bit tricky ... */
- for (a = 0; a < MENU_MAX_AXES; a++)
- {
- if (abs(n->axes[a]) >= 20000)
- {
- /* Take care of case where axis rests on +/- 0x7fff
- * (e.g. 360 controller on Linux) */
- output->joyaxis = n->axes[a] > 0
- ? AXIS_POS(a) : AXIS_NEG(a);
- output->joykey = NO_BTN;
-
- return true;
- }
- }
-
- for (h = 0; h < MENU_MAX_HATS; h++)
- {
- uint16_t trigged = n->hats[h];
- uint16_t sane_trigger = 0;
-
- if (trigged & HAT_UP_MASK)
- sane_trigger = HAT_UP_MASK;
- else if (trigged & HAT_DOWN_MASK)
- sane_trigger = HAT_DOWN_MASK;
- else if (trigged & HAT_LEFT_MASK)
- sane_trigger = HAT_LEFT_MASK;
- else if (trigged & HAT_RIGHT_MASK)
- sane_trigger = HAT_RIGHT_MASK;
-
- if (sane_trigger)
- {
- output->joykey = HAT_MAP(h, sane_trigger);
- output->joyaxis = AXIS_NONE;
- return true;
- }
- }
-
- return false;
-}
-#endif
-
-static bool menu_input_key_bind_poll_find_trigger(
- unsigned max_users,
- struct menu_bind_state *state,
- struct menu_bind_state *new_state,
- struct retro_keybind * output)
-{
- if (state && new_state)
- {
- unsigned i;
-
- for (i = 0; i < max_users; i++)
- {
- if (menu_input_key_bind_poll_find_trigger_pad(
- state, new_state, output, i))
- return true;
- }
- }
-
- return false;
-}
-
-#ifdef ANDROID
-static bool menu_input_key_bind_poll_find_hold(
- unsigned max_users,
- struct menu_bind_state *new_state,
- struct retro_keybind * output)
-{
- if (new_state)
- {
- unsigned i;
-
- for (i = 0; i < max_users; i++)
- {
- if (menu_input_key_bind_poll_find_hold_pad(new_state, output, i))
- return true;
- }
- }
-
- return false;
-}
-#endif
-
bool menu_input_key_bind_set_mode(
enum menu_input_binds_ctl_state state, void *data)
{
@@ -1930,7 +1389,7 @@ static int generic_menu_iterate(
{
case ITERATE_TYPE_HELP:
ret = menu_dialog_iterate(
- &p_rarch->dialog_st,
+ &p_rarch->dialog_st, settings,
menu->menu_state_msg, sizeof(menu->menu_state_msg),
current_time);
@@ -2893,202 +2352,6 @@ int menu_entry_action(
return -1;
}
-static void menu_list_free_list(
- const menu_ctx_driver_t *menu_driver_ctx,
- file_list_t *list)
-{
- unsigned i;
-
- for (i = 0; i < list->size; i++)
- {
- menu_ctx_list_t list_info;
-
- list_info.list = list;
- list_info.idx = i;
- list_info.list_size = list->size;
-
- menu_driver_list_free(menu_driver_ctx, &list_info);
- }
-
- file_list_free(list);
-}
-
-static void menu_list_free(
- const menu_ctx_driver_t *menu_driver_ctx,
- menu_list_t *menu_list)
-{
- if (!menu_list)
- return;
-
- if (menu_list->menu_stack)
- {
- unsigned i;
-
- for (i = 0; i < menu_list->menu_stack_size; i++)
- {
- if (!menu_list->menu_stack[i])
- continue;
-
- menu_list_free_list(menu_driver_ctx,
- menu_list->menu_stack[i]);
- menu_list->menu_stack[i] = NULL;
- }
-
- free(menu_list->menu_stack);
- }
-
- if (menu_list->selection_buf)
- {
- unsigned i;
-
- for (i = 0; i < menu_list->selection_buf_size; i++)
- {
- if (!menu_list->selection_buf[i])
- continue;
-
- menu_list_free_list(menu_driver_ctx,
- menu_list->selection_buf[i]);
- menu_list->selection_buf[i] = NULL;
- }
-
- free(menu_list->selection_buf);
- }
-
- free(menu_list);
-}
-
-static menu_list_t *menu_list_new(const menu_ctx_driver_t *menu_driver_ctx)
-{
- unsigned i;
- menu_list_t *list = (menu_list_t*)malloc(sizeof(*list));
-
- if (!list)
- return NULL;
-
- list->menu_stack_size = 1;
- list->selection_buf_size = 1;
- list->selection_buf = NULL;
- list->menu_stack = (file_list_t**)
- calloc(list->menu_stack_size, sizeof(*list->menu_stack));
-
- if (!list->menu_stack)
- goto error;
-
- list->selection_buf = (file_list_t**)
- calloc(list->selection_buf_size, sizeof(*list->selection_buf));
-
- if (!list->selection_buf)
- goto error;
-
- for (i = 0; i < list->menu_stack_size; i++)
- {
- list->menu_stack[i] = (file_list_t*)
- malloc(sizeof(*list->menu_stack[i]));
- list->menu_stack[i]->list = NULL;
- list->menu_stack[i]->capacity = 0;
- list->menu_stack[i]->size = 0;
- }
-
- for (i = 0; i < list->selection_buf_size; i++)
- {
- list->selection_buf[i] = (file_list_t*)
- malloc(sizeof(*list->selection_buf[i]));
- list->selection_buf[i]->list = NULL;
- list->selection_buf[i]->capacity = 0;
- list->selection_buf[i]->size = 0;
- }
-
- return list;
-
-error:
- menu_list_free(menu_driver_ctx, list);
- return NULL;
-}
-
-static int menu_list_flush_stack_type(const char *needle, const char *label,
- unsigned type, unsigned final_type)
-{
- return needle ? !string_is_equal(needle, label) : (type != final_type);
-}
-
-static bool menu_list_pop_stack(
- const menu_ctx_driver_t *menu_driver_ctx,
- void *menu_userdata,
- menu_list_t *list,
- size_t idx,
- size_t *directory_ptr)
-{
- file_list_t *menu_list = MENU_LIST_GET(list, (unsigned)idx);
-
- if (!menu_list)
- return false;
-
- if (menu_list->size != 0)
- {
- menu_ctx_list_t list_info;
-
- list_info.list = menu_list;
- list_info.idx = menu_list->size - 1;
- list_info.list_size = menu_list->size - 1;
-
- menu_driver_list_free(menu_driver_ctx, &list_info);
- }
-
- file_list_pop(menu_list, directory_ptr);
- if ( menu_driver_ctx &&
- menu_driver_ctx->list_set_selection)
- menu_driver_ctx->list_set_selection(menu_userdata,
- menu_list);
-
- return true;
-}
-
-static void menu_list_flush_stack(
- const menu_ctx_driver_t *menu_driver_ctx,
- void *menu_userdata,
- struct menu_state *menu_st,
- menu_list_t *list,
- size_t idx, const char *needle, unsigned final_type)
-{
- bool refresh = false;
- const char *path = NULL;
- const char *label = NULL;
- unsigned type = 0;
- size_t entry_idx = 0;
- file_list_t *menu_list = MENU_LIST_GET(list, (unsigned)idx);
-
- menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
-
- if (menu_list && menu_list->size)
- file_list_get_at_offset(menu_list, menu_list->size - 1, &path, &label, &type, &entry_idx);
-
- while (menu_list_flush_stack_type(
- needle, label, type, final_type) != 0)
- {
- bool refresh = false;
- size_t new_selection_ptr = menu_st->selection_ptr;
- bool wont_pop_stack = (MENU_LIST_GET_STACK_SIZE(list, idx) <= 1);
- if (wont_pop_stack)
- break;
-
- if (menu_driver_ctx->list_cache)
- menu_driver_ctx->list_cache(menu_userdata,
- MENU_LIST_PLAIN, 0);
-
- menu_list_pop_stack(menu_driver_ctx,
- menu_userdata,
- list, idx, &new_selection_ptr);
-
- menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
-
- menu_st->selection_ptr = new_selection_ptr;
- menu_list = MENU_LIST_GET(list, (unsigned)idx);
-
- if (menu_list && menu_list->size)
- file_list_get_at_offset(menu_list, menu_list->size - 1, &path, &label, &type, &entry_idx);
- }
-}
-
/**
* menu_entries_elem_get_first_char:
* @list : File list handle.
@@ -3291,36 +2554,6 @@ file_list_t *menu_entries_get_selection_buf_ptr(size_t idx)
return MENU_LIST_GET_SELECTION(menu_list, (unsigned)idx);
}
-static void menu_entries_list_deinit(
- const menu_ctx_driver_t *menu_driver_ctx,
- struct menu_state *menu_st)
-{
- if (menu_st->entries.list)
- menu_list_free(menu_driver_ctx, menu_st->entries.list);
- menu_st->entries.list = NULL;
-}
-
-static void menu_entries_settings_deinit(struct menu_state *menu_st)
-{
- menu_setting_free(menu_st->entries.list_settings);
- if (menu_st->entries.list_settings)
- free(menu_st->entries.list_settings);
- menu_st->entries.list_settings = NULL;
-}
-
-
-static bool menu_entries_init(
- struct menu_state *menu_st,
- const menu_ctx_driver_t *menu_driver_ctx
- )
-{
- if (!(menu_st->entries.list = (menu_list_t*)menu_list_new(menu_driver_ctx)))
- return false;
- if (!(menu_st->entries.list_settings = menu_setting_new()))
- return false;
- return true;
-}
-
void menu_entries_append(
file_list_t *list,
const char *path,
@@ -4999,22 +4232,6 @@ retro_time_t menu_driver_get_current_time(void)
return menu_st->current_time_us;
}
-static void menu_driver_list_free(
- const menu_ctx_driver_t *menu_driver_ctx,
- menu_ctx_list_t *list)
-{
- if (menu_driver_ctx)
- if (menu_driver_ctx->list_free)
- menu_driver_ctx->list_free(
- list->list, list->idx, list->list_size);
-
- if (list->list)
- {
- file_list_free_userdata (list->list, list->idx);
- file_list_free_actiondata(list->list, list->idx);
- }
-}
-
/* Returns true if search filter is enabled
* for the specified menu list */
bool menu_driver_search_filter_enabled(const char *label, unsigned type)
@@ -16543,10 +15760,10 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
RARCH_LOG("[Environ]: SET_VARIABLES.\n");
if (runloop_state.core_options)
- retroarch_deinit_core_options(p_rarch,
+ retroarch_deinit_core_options(
path_get(RARCH_PATH_CORE_OPTIONS));
- retroarch_init_core_variables(p_rarch,
+ retroarch_init_core_variables(settings,
(const struct retro_variable *)data);
break;
@@ -16562,13 +15779,13 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
(const struct retro_core_option_definition*)data);
if (runloop_state.core_options)
- retroarch_deinit_core_options(p_rarch,
+ retroarch_deinit_core_options(
path_get(RARCH_PATH_CORE_OPTIONS));
if (options_v2)
{
/* Initialise core options */
- rarch_init_core_options(p_rarch, options_v2);
+ rarch_init_core_options(settings, options_v2);
/* Clean up */
core_option_manager_free_converted(options_v2);
@@ -16587,13 +15804,13 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
(const struct retro_core_options_intl*)data);
if (runloop_state.core_options)
- retroarch_deinit_core_options(p_rarch,
+ retroarch_deinit_core_options(
path_get(RARCH_PATH_CORE_OPTIONS));
if (options_v2)
{
/* Initialise core options */
- rarch_init_core_options(p_rarch, options_v2);
+ rarch_init_core_options(settings, options_v2);
/* Clean up */
core_option_manager_free_converted(options_v2);
@@ -16611,11 +15828,11 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
settings->bools.core_option_category_enable;
if (runloop_state.core_options)
- retroarch_deinit_core_options(p_rarch,
+ retroarch_deinit_core_options(
path_get(RARCH_PATH_CORE_OPTIONS));
if (options_v2)
- rarch_init_core_options(p_rarch, options_v2);
+ rarch_init_core_options(settings, options_v2);
/* Return value does not indicate success.
* Callback returns 'true' if core option
@@ -16638,13 +15855,13 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
settings->bools.core_option_category_enable;
if (runloop_state.core_options)
- retroarch_deinit_core_options(p_rarch,
+ retroarch_deinit_core_options(
path_get(RARCH_PATH_CORE_OPTIONS));
if (options_v2)
{
/* Initialise core options */
- rarch_init_core_options(p_rarch, options_v2);
+ rarch_init_core_options(settings, options_v2);
/* Clean up */
core_option_manager_free_converted(options_v2);
@@ -18429,7 +17646,7 @@ static void uninit_libretro_symbols(
p_rarch->core_set_shared_context = false;
if (runloop_state.core_options)
- retroarch_deinit_core_options(p_rarch,
+ retroarch_deinit_core_options(
path_get(RARCH_PATH_CORE_OPTIONS));
retroarch_system_info_free(p_rarch);
retroarch_frame_time_free(p_rarch);
@@ -23013,385 +22230,6 @@ static int16_t input_joypad_axis(
/* MENU INPUT */
#ifdef HAVE_MENU
-static void menu_input_get_mouse_hw_state(
- gfx_display_t *p_disp,
- menu_handle_t *menu,
- input_driver_state_t *input_driver_st,
- input_driver_t *current_input,
- const input_device_driver_t *joypad,
- const input_device_driver_t *sec_joypad,
- bool keyboard_mapping_blocked,
- bool menu_mouse_enable,
- bool input_overlay_enable,
- bool overlay_active,
- menu_input_pointer_hw_state_t *hw_state)
-{
- rarch_joypad_info_t joypad_info;
- static int16_t last_x = 0;
- static int16_t last_y = 0;
- static bool last_select_pressed = false;
- static bool last_cancel_pressed = false;
- bool menu_has_fb =
- (menu &&
- menu->driver_ctx &&
- menu->driver_ctx->set_texture);
- bool state_inited = current_input &&
- current_input->input_state;
-#ifdef HAVE_OVERLAY
- /* Menu pointer controls are ignored when overlays are enabled. */
- if (overlay_active)
- menu_mouse_enable = false;
-#endif
-
- /* Easiest to set inactive by default, and toggle
- * when input is detected */
- hw_state->active = false;
- hw_state->x = 0;
- hw_state->y = 0;
- hw_state->select_pressed = false;
- hw_state->cancel_pressed = false;
- hw_state->up_pressed = false;
- hw_state->down_pressed = false;
- hw_state->left_pressed = false;
- hw_state->right_pressed = false;
-
- if (!menu_mouse_enable)
- return;
-
- joypad_info.joy_idx = 0;
- joypad_info.auto_binds = NULL;
- joypad_info.axis_threshold = 0.0f;
-
- /* X/Y position */
- if (state_inited)
- {
- if ((hw_state->x = current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RARCH_DEVICE_MOUSE_SCREEN,
- 0,
- RETRO_DEVICE_ID_MOUSE_X)) != last_x)
- hw_state->active = true;
- if ((hw_state->y = current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RARCH_DEVICE_MOUSE_SCREEN,
- 0,
- RETRO_DEVICE_ID_MOUSE_Y)) != last_y)
- hw_state->active = true;
- }
-
- last_x = hw_state->x;
- last_y = hw_state->y;
-
- /* > X/Y position adjustment */
- if (menu_has_fb)
- {
- /* RGUI uses a framebuffer texture + custom viewports,
- * which means we have to convert from screen space to
- * menu space... */
- struct video_viewport vp = {0};
- /* Read display/framebuffer info */
- unsigned fb_width = p_disp->framebuf_width;
- unsigned fb_height = p_disp->framebuf_height;
-
- video_driver_get_viewport_info(&vp);
-
- /* Adjust X position */
- hw_state->x = (int16_t)(((float)(hw_state->x - vp.x) / (float)vp.width) * (float)fb_width);
- hw_state->x = (hw_state->x < 0) ? (0 ) : hw_state->x;
- hw_state->x = (hw_state->x >= fb_width) ? (fb_width -1) : hw_state->x;
-
- /* Adjust Y position */
- hw_state->y = (int16_t)(((float)(hw_state->y - vp.y) / (float)vp.height) * (float)fb_height);
- hw_state->y = (hw_state->y < 0) ? (0 ) : hw_state->y;
- hw_state->y = (hw_state->y >= fb_height) ? (fb_height-1) : hw_state->y;
- }
-
- if (state_inited)
- {
- /* Select (LMB)
- * Note that releasing select also counts as activity */
- hw_state->select_pressed = (bool)
- current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RETRO_DEVICE_MOUSE,
- 0,
- RETRO_DEVICE_ID_MOUSE_LEFT);
- /* Cancel (RMB)
- * Note that releasing cancel also counts as activity */
- hw_state->cancel_pressed = (bool)
- current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RETRO_DEVICE_MOUSE,
- 0,
- RETRO_DEVICE_ID_MOUSE_RIGHT);
- /* Up (mouse wheel up) */
- if ((hw_state->up_pressed = (bool)
- current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RETRO_DEVICE_MOUSE,
- 0,
- RETRO_DEVICE_ID_MOUSE_WHEELUP)))
- hw_state->active = true;
- /* Down (mouse wheel down) */
- if ((hw_state->down_pressed = (bool)
- current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RETRO_DEVICE_MOUSE,
- 0,
- RETRO_DEVICE_ID_MOUSE_WHEELDOWN)))
- hw_state->active = true;
- /* Left (mouse wheel horizontal left) */
- if ((hw_state->left_pressed = (bool)
- current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RETRO_DEVICE_MOUSE,
- 0,
- RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN)))
- hw_state->active = true;
- /* Right (mouse wheel horizontal right) */
- if ((hw_state->right_pressed = (bool)
- current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info,
- NULL,
- keyboard_mapping_blocked,
- 0,
- RETRO_DEVICE_MOUSE,
- 0,
- RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP)))
- hw_state->active = true;
- }
-
- if (hw_state->select_pressed || (hw_state->select_pressed != last_select_pressed))
- hw_state->active = true;
- if (hw_state->cancel_pressed || (hw_state->cancel_pressed != last_cancel_pressed))
- hw_state->active = true;
- last_select_pressed = hw_state->select_pressed;
- last_cancel_pressed = hw_state->cancel_pressed;
-}
-
-static void menu_input_get_touchscreen_hw_state(
- gfx_display_t *p_disp,
- menu_handle_t *menu,
- input_driver_state_t *input_driver_st,
- input_driver_t *current_input,
- const input_device_driver_t *joypad,
- const input_device_driver_t *sec_joypad,
- bool keyboard_mapping_blocked,
- bool overlay_active,
- bool pointer_enabled,
- unsigned input_touch_scale,
- menu_input_pointer_hw_state_t *hw_state)
-{
- rarch_joypad_info_t joypad_info;
- unsigned fb_width, fb_height;
- int pointer_x = 0;
- int pointer_y = 0;
- const struct retro_keybind *binds[MAX_USERS] = {NULL};
- /* Is a background texture set for the current menu driver?
- * Checks if the menu framebuffer is set.
- * This would usually only return true
- * for framebuffer-based menu drivers, like RGUI. */
- int pointer_device =
- (menu && menu->driver_ctx && menu->driver_ctx->set_texture) ?
- RETRO_DEVICE_POINTER : RARCH_DEVICE_POINTER_SCREEN;
- static int16_t last_x = 0;
- static int16_t last_y = 0;
- static bool last_select_pressed = false;
- static bool last_cancel_pressed = false;
-
- /* Easiest to set inactive by default, and toggle
- * when input is detected */
- hw_state->active = false;
-
- /* Touch screens don't have mouse wheels, so these
- * are always disabled */
- hw_state->up_pressed = false;
- hw_state->down_pressed = false;
- hw_state->left_pressed = false;
- hw_state->right_pressed = false;
-
-#ifdef HAVE_OVERLAY
- /* Menu pointer controls are ignored when overlays are enabled. */
- if (overlay_active)
- pointer_enabled = false;
-#endif
-
- /* If touchscreen is disabled, ignore all input */
- if (!pointer_enabled)
- {
- hw_state->x = 0;
- hw_state->y = 0;
- hw_state->select_pressed = false;
- hw_state->cancel_pressed = false;
- return;
- }
-
- /* TODO/FIXME - this should only be used for framebuffer-based
- * menu drivers like RGUI. Touchscreen input as a whole should
- * NOT be dependent on this
- */
- fb_width = p_disp->framebuf_width;
- fb_height = p_disp->framebuf_height;
-
- joypad_info.joy_idx = 0;
- joypad_info.auto_binds = NULL;
- joypad_info.axis_threshold = 0.0f;
-
- /* X pos */
- if (current_input->input_state)
- pointer_x = current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info, binds,
- keyboard_mapping_blocked,
- 0, pointer_device,
- 0, RETRO_DEVICE_ID_POINTER_X);
- hw_state->x = ((pointer_x + 0x7fff) * (int)fb_width) / 0xFFFF;
- hw_state->x *= input_touch_scale;
-
- /* > An annoyance - we get different starting positions
- * depending upon whether pointer_device is
- * RETRO_DEVICE_POINTER or RARCH_DEVICE_POINTER_SCREEN,
- * so different 'activity' checks are required to prevent
- * false positives on first run */
- if (pointer_device == RARCH_DEVICE_POINTER_SCREEN)
- {
- if (hw_state->x != last_x)
- hw_state->active = true;
- last_x = hw_state->x;
- }
- else
- {
- if (pointer_x != last_x)
- hw_state->active = true;
- last_x = pointer_x;
- }
-
- /* Y pos */
- if (current_input->input_state)
- pointer_y = current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info, binds,
- keyboard_mapping_blocked,
- 0, pointer_device,
- 0, RETRO_DEVICE_ID_POINTER_Y);
- hw_state->y = ((pointer_y + 0x7fff) * (int)fb_height) / 0xFFFF;
- hw_state->y *= input_touch_scale;
-
- if (pointer_device == RARCH_DEVICE_POINTER_SCREEN)
- {
- if (hw_state->y != last_y)
- hw_state->active = true;
- last_y = hw_state->y;
- }
- else
- {
- if (pointer_y != last_y)
- hw_state->active = true;
- last_y = pointer_y;
- }
-
- /* Select (touch screen contact)
- * Note that releasing select also counts as activity */
- if (current_input->input_state)
- hw_state->select_pressed = (bool)current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info, binds,
- keyboard_mapping_blocked,
- 0, pointer_device,
- 0, RETRO_DEVICE_ID_POINTER_PRESSED);
- if (hw_state->select_pressed || (hw_state->select_pressed != last_select_pressed))
- hw_state->active = true;
- last_select_pressed = hw_state->select_pressed;
-
- /* Cancel (touch screen 'back' - don't know what is this, but whatever...)
- * Note that releasing cancel also counts as activity */
- if (current_input->input_state)
- hw_state->cancel_pressed = (bool)current_input->input_state(
- input_driver_st->current_data,
- joypad,
- sec_joypad,
- &joypad_info, binds,
- keyboard_mapping_blocked,
- 0, pointer_device,
- 0, RARCH_DEVICE_ID_POINTER_BACK);
- if (hw_state->cancel_pressed || (hw_state->cancel_pressed != last_cancel_pressed))
- hw_state->active = true;
- last_cancel_pressed = hw_state->cancel_pressed;
-}
-
-static INLINE bool input_event_osk_show_symbol_pages(
- menu_handle_t *menu)
-{
-#if defined(HAVE_LANGEXTRA)
-#if defined(HAVE_RGUI)
- bool menu_has_fb = (menu &&
- menu->driver_ctx &&
- menu->driver_ctx->set_texture);
- unsigned language = *msg_hash_get_uint(MSG_HASH_USER_LANGUAGE);
- return !menu_has_fb ||
- ((language == RETRO_LANGUAGE_JAPANESE) ||
- (language == RETRO_LANGUAGE_KOREAN) ||
- (language == RETRO_LANGUAGE_CHINESE_SIMPLIFIED) ||
- (language == RETRO_LANGUAGE_CHINESE_TRADITIONAL));
-#else /* HAVE_RGUI */
- return true;
-#endif /* HAVE_RGUI */
-#else /* HAVE_LANGEXTRA */
- return false;
-#endif /* HAVE_LANGEXTRA */
-}
-
static void input_event_osk_append(
struct rarch_state *p_rarch,
enum osk_type *osk_idx, int ptr,
@@ -23441,71 +22279,6 @@ static void input_event_osk_append(
}
}
-static void input_event_osk_iterate(
- void *osk_grid,
- enum osk_type osk_idx)
-{
-#ifndef HAVE_LANGEXTRA
- /* If HAVE_LANGEXTRA is not defined, define some ASCII-friendly pages. */
- static const char *uppercase_grid[] = {
- "1","2","3","4","5","6","7","8","9","0","Bksp",
- "Q","W","E","R","T","Y","U","I","O","P","Enter",
- "A","S","D","F","G","H","J","K","L","+","Lower",
- "Z","X","C","V","B","N","M"," ","_","/","Next"};
- static const char *lowercase_grid[] = {
- "1","2","3","4","5","6","7","8","9","0","Bksp",
- "q","w","e","r","t","y","u","i","o","p","Enter",
- "a","s","d","f","g","h","j","k","l","@","Upper",
- "z","x","c","v","b","n","m"," ","-",".","Next"};
- static const char *symbols_page1_grid[] = {
- "1","2","3","4","5","6","7","8","9","0","Bksp",
- "!","\"","#","$","%","&","'","*","(",")","Enter",
- "+",",","-","~","/",":",";","=","<",">","Lower",
- "?","@","[","\\","]","^","_","|","{","}","Next"};
-#endif
- switch (osk_idx)
- {
-#ifdef HAVE_LANGEXTRA
- case OSK_HIRAGANA_PAGE1:
- memcpy(osk_grid,
- hiragana_page1_grid,
- sizeof(hiragana_page1_grid));
- break;
- case OSK_HIRAGANA_PAGE2:
- memcpy(osk_grid,
- hiragana_page2_grid,
- sizeof(hiragana_page2_grid));
- break;
- case OSK_KATAKANA_PAGE1:
- memcpy(osk_grid,
- katakana_page1_grid,
- sizeof(katakana_page1_grid));
- break;
- case OSK_KATAKANA_PAGE2:
- memcpy(osk_grid,
- katakana_page2_grid,
- sizeof(katakana_page2_grid));
- break;
-#endif
- case OSK_SYMBOLS_PAGE1:
- memcpy(osk_grid,
- symbols_page1_grid,
- sizeof(uppercase_grid));
- break;
- case OSK_UPPERCASE_LATIN:
- memcpy(osk_grid,
- uppercase_grid,
- sizeof(uppercase_grid));
- break;
- case OSK_LOWERCASE_LATIN:
- default:
- memcpy(osk_grid,
- lowercase_grid,
- sizeof(lowercase_grid));
- break;
- }
-}
-
/*
* This function gets called in order to process all input events
* for the current frame.
@@ -23934,118 +22707,6 @@ void menu_input_set_pointer_y_accel(float y_accel)
menu_input->pointer.y_accel = y_accel;
}
-static float menu_input_get_dpi(struct rarch_state *p_rarch,
- menu_handle_t *menu,
- gfx_display_t *p_disp)
-{
- static unsigned last_video_width = 0;
- static unsigned last_video_height = 0;
- static float dpi = 0.0f;
- static bool dpi_cached = false;
-
- /* Regardless of menu driver, need 'actual' screen DPI
- * Note: DPI is a fixed hardware property. To minimise performance
- * overheads we therefore only call video_context_driver_get_metrics()
- * on first run, or when the current video resolution changes */
- if (!dpi_cached ||
- (p_rarch->video_driver_width != last_video_width) ||
- (p_rarch->video_driver_height != last_video_height))
- {
- gfx_ctx_metrics_t mets;
- /* Note: If video_context_driver_get_metrics() fails,
- * we don't know what happened to dpi - so ensure it
- * is reset to a sane value */
-
- mets.type = DISPLAY_METRIC_DPI;
- mets.value = &dpi;
- if (!video_context_driver_get_metrics(&mets))
- dpi = 0.0f;
-
- dpi_cached = true;
- last_video_width = p_rarch->video_driver_width;
- last_video_height = p_rarch->video_driver_height;
- }
-
- /* RGUI uses a framebuffer texture, which means we
- * operate in menu space, not screen space.
- * DPI in a traditional sense is therefore meaningless,
- * so generate a substitute value based upon framebuffer
- * dimensions */
- if (dpi > 0.0f)
- {
- bool menu_has_fb =
- menu->driver_ctx
- && menu->driver_ctx->set_texture;
-
- /* Read framebuffer info? */
- if (menu_has_fb)
- {
- unsigned fb_height = p_disp->framebuf_height;
- /* Rationale for current 'DPI' determination method:
- * - Divide screen height by DPI, to get number of vertical
- * '1 inch' squares
- * - Divide RGUI framebuffer height by number of vertical
- * '1 inch' squares to get number of menu space pixels
- * per inch
- * This is crude, but should be sufficient... */
- return ((float)fb_height / (float)p_rarch->video_driver_height) * dpi;
- }
- }
-
- return dpi;
-}
-
-static bool menu_should_pop_stack(const char *label)
-{
- /* > Info box */
- if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_INFO_SCREEN)))
- return true;
- /* > Help box */
- if (string_starts_with_size(label, "help", STRLEN_CONST("help")))
- if (
- string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_CONTROLS))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_WHAT_IS_A_CORE))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_LOADING_CONTENT))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_SCANNING_CONTENT))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_CHANGE_VIRTUAL_GAMEPAD))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_AUDIO_VIDEO_TROUBLESHOOTING))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_HELP_SEND_DEBUG_INFO))
- || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_DESCRIPTION)))
- return true;
- if (
- string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CHEEVOS_DESCRIPTION)))
- return true;
- return false;
-}
-
-/* Used to close an active message box (help or info)
- * TODO/FIXME: The way that message boxes are handled
- * is complete garbage. generic_menu_iterate() and
- * message boxes in general need a total rewrite.
- * I consider this current 'close_messagebox' a hack,
- * but at least it prevents undefined/dangerous
- * behaviour... */
-static void menu_input_pointer_close_messagebox(struct menu_state *menu_st)
-{
- const char *label = NULL;
-
- /* Determine whether this is a help or info
- * message box */
- file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
- NULL, &label, NULL, NULL);
-
- /* Pop stack, if required */
- if (menu_should_pop_stack(label))
- {
- size_t selection = menu_st->selection_ptr;
- size_t new_selection = selection;
-
- menu_entries_pop_stack(&new_selection, 0, 0);
- menu_st->selection_ptr = selection;
- }
-}
-
static int menu_input_pointer_post_iterate(
struct rarch_state *p_rarch,
gfx_display_t *p_disp,
@@ -24162,7 +22823,8 @@ static int menu_input_pointer_post_iterate(
{
/* Pointer is being held down
* (i.e. for more than one frame) */
- float dpi = menu ? menu_input_get_dpi(p_rarch, menu, p_disp) : 0.0f;
+ float dpi = menu ? menu_input_get_dpi(menu, p_disp,
+ p_rarch->video_driver_width, p_rarch->video_driver_height) : 0.0f;
/* > Update deltas + acceleration & detect press direction
* Note: We only do this if the pointer has moved above
@@ -24431,7 +23093,7 @@ static int menu_input_pointer_post_iterate(
else
{
/* Pointer has moved - check if this is a swipe */
- float dpi = menu ? menu_input_get_dpi(p_rarch, menu, p_disp) : 0.0f;
+ float dpi = menu ? menu_input_get_dpi(menu, p_disp, p_rarch->video_driver_width, p_rarch->video_driver_height) : 0.0f;
if ((dpi > 0.0f)
&&
@@ -34535,11 +33197,10 @@ static bool retroarch_validate_per_core_options(char *s,
}
static bool retroarch_validate_game_options(
+ const char *core_name,
char *s, size_t len, bool mkdir)
{
- const char *core_name = runloop_state.system.info.library_name;
const char *game_name = path_basename(path_get(RARCH_PATH_BASENAME));
-
return retroarch_validate_per_core_options(s, len, mkdir,
core_name, game_name);
}
@@ -35222,7 +33883,7 @@ void retroarch_menu_running(void)
void retroarch_menu_running_finished(bool quit)
{
struct rarch_state *p_rarch = &rarch_st;
-#if defined(HAVE_MENU) || defined(HAVE_OVERLAY)
+#ifdef HAVE_OVERLAY
settings_t *settings = p_rarch->configuration_settings;
#endif
#ifdef HAVE_MENU
@@ -35311,13 +33972,13 @@ void retroarch_menu_running_finished(bool quit)
* options path has been found,
* otherwise false (0).
**/
-static bool rarch_game_specific_options(struct rarch_state *p_rarch,
- char **output)
+static bool rarch_game_specific_options(char **output)
{
char game_options_path[PATH_MAX_LENGTH];
game_options_path[0] ='\0';
if (!retroarch_validate_game_options(
+ runloop_state.system.info.library_name,
game_options_path,
sizeof(game_options_path), false) ||
!path_is_valid(game_options_path))
@@ -35338,7 +33999,6 @@ static bool rarch_game_specific_options(struct rarch_state *p_rarch,
* otherwise false (0).
**/
static bool rarch_folder_specific_options(
- struct rarch_state *p_rarch,
char **output)
{
char folder_options_path[PATH_MAX_LENGTH];
@@ -35419,19 +34079,18 @@ static void runloop_task_msg_queue_push(
* path and src_path are NULL-terminated
* */
static void rarch_init_core_options_path(
- struct rarch_state *p_rarch,
+ settings_t *settings,
char *path, size_t len,
char *src_path, size_t src_len)
{
char *game_options_path = NULL;
char *folder_options_path = NULL;
- settings_t *settings = p_rarch->configuration_settings;
bool game_specific_options = settings->bools.game_specific_options;
/* Check whether game-specific options exist */
if (game_specific_options &&
- rarch_game_specific_options(p_rarch, &game_options_path))
+ rarch_game_specific_options(&game_options_path))
{
/* Notify system that we have a valid core options
* override */
@@ -35446,7 +34105,7 @@ static void rarch_init_core_options_path(
}
/* Check whether folder-specific options exist */
else if (game_specific_options &&
- rarch_folder_specific_options(p_rarch,
+ rarch_folder_specific_options(
&folder_options_path))
{
/* Notify system that we have a valid core options
@@ -35522,10 +34181,9 @@ static void rarch_init_core_options_path(
}
static void rarch_init_core_options(
- struct rarch_state *p_rarch,
+ settings_t *settings,
const struct retro_core_options_v2 *options_v2)
{
- settings_t *settings = p_rarch->configuration_settings;
bool categories_enabled = settings->bools.core_option_category_enable;
char options_path[PATH_MAX_LENGTH];
char src_options_path[PATH_MAX_LENGTH];
@@ -35535,7 +34193,7 @@ static void rarch_init_core_options(
src_options_path[0] = '\0';
/* Get core options file path */
- rarch_init_core_options_path(p_rarch,
+ rarch_init_core_options_path(settings,
options_path, sizeof(options_path),
src_options_path, sizeof(src_options_path));
@@ -35839,7 +34497,7 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
return true;
}
-static void retroarch_deinit_core_options(struct rarch_state *p_rarch,
+static void retroarch_deinit_core_options(
const char *path_core_options)
{
/* Check whether game-specific options file is being used */
@@ -35892,7 +34550,7 @@ static void retroarch_deinit_core_options(struct rarch_state *p_rarch,
}
static void retroarch_init_core_variables(
- struct rarch_state *p_rarch,
+ settings_t *settings,
const struct retro_variable *vars)
{
char options_path[PATH_MAX_LENGTH];
@@ -35903,7 +34561,8 @@ static void retroarch_init_core_variables(
src_options_path[0] = '\0';
/* Get core options file path */
- rarch_init_core_options_path(p_rarch,
+ rarch_init_core_options_path(
+ settings,
options_path, sizeof(options_path),
src_options_path, sizeof(src_options_path));
@@ -38972,6 +37631,7 @@ bool core_options_create_override(bool game_specific)
{
/* Get options file path (game-specific) */
if (!retroarch_validate_game_options(
+ runloop_state.system.info.library_name,
options_path,
sizeof(options_path), true))
goto error;
diff --git a/retroarch_data.h b/retroarch_data.h
index 728032145d..518e761025 100644
--- a/retroarch_data.h
+++ b/retroarch_data.h
@@ -268,18 +268,6 @@
#define MAPPER_SET_KEY(state, key) (state)->keys[(key) / 32] |= 1 << ((key) % 32)
#define MAPPER_UNSET_KEY(state, key) (state)->keys[(key) / 32] &= ~(1 << ((key) % 32))
-
-#ifdef HAVE_MENU
-#define MENU_LIST_GET(list, idx) ((list) ? ((list)->menu_stack[(idx)]) : NULL)
-
-#define MENU_LIST_GET_SELECTION(list, idx) ((list) ? ((list)->selection_buf[(idx)]) : NULL)
-
-#define MENU_LIST_GET_STACK_SIZE(list, idx) ((list)->menu_stack[(idx)]->size)
-
-#define MENU_ENTRIES_GET_SELECTION_BUF_PTR_INTERNAL(menu_st, idx) ((menu_st->entries.list) ? MENU_LIST_GET_SELECTION(menu_st->entries.list, (unsigned)idx) : NULL)
-#define MENU_ENTRIES_NEEDS_REFRESH(menu_st) (!(menu_st->entries_nonblocking_refresh || !menu_st->entries_need_refresh))
-#endif
-
#define CDN_URL "https://cdn.discordapp.com/avatars"
#ifdef HAVE_DYNAMIC
@@ -388,18 +376,6 @@
#define PERF_LOG_FMT "[PERF]: Avg (%s): %llu ticks, %llu runs.\n"
#endif
-#ifdef HAVE_MENU
-#define SCROLL_INDEX_SIZE (2 * (26 + 2) + 1)
-
-#define POWERSTATE_CHECK_INTERVAL (30 * 1000000)
-#define DATETIME_CHECK_INTERVAL 1000000
-
-#define MENU_MAX_BUTTONS 219
-#define MENU_MAX_AXES 32
-#define MENU_MAX_HATS 4
-#define MENU_MAX_MBUTTONS 32 /* Enough to cover largest libretro constant*/
-#endif
-
/* DRIVERS */
audio_driver_t audio_null = {
@@ -1244,112 +1220,6 @@ typedef struct input_game_focus_state
typedef bool(*runahead_load_state_function)(const void*, size_t);
#endif
-#ifdef HAVE_MENU
-typedef struct menu_ctx_load_image
-{
- void *data;
- enum menu_image_type type;
-} menu_ctx_load_image_t;
-
-struct menu_list
-{
- file_list_t **menu_stack;
- size_t menu_stack_size;
- file_list_t **selection_buf;
- size_t selection_buf_size;
-};
-
-typedef struct menu_list menu_list_t;
-
-struct menu_state
-{
- /* Timers */
- retro_time_t current_time_us;
- retro_time_t powerstate_last_time_us;
- retro_time_t datetime_last_time_us;
- retro_time_t input_last_time_us;
-
- struct
- {
- rarch_setting_t *list_settings;
- menu_list_t *list;
- size_t begin;
- } entries;
- size_t selection_ptr;
-
- /* Quick jumping indices with L/R.
- * Rebuilt when parsing directory. */
- struct
- {
- size_t index_list[SCROLL_INDEX_SIZE];
- unsigned index_size;
- unsigned acceleration;
- } scroll;
-
- /* Storage container for current menu datetime
- * representation string */
- char datetime_cache[255];
-
- /* When generating a menu list in menu_displaylist_build_list(),
- * the entry with a label matching 'pending_selection' will
- * be selected automatically */
- char pending_selection[PATH_MAX_LENGTH];
-
- /* when enabled, on next iteration the 'Quick Menu' list will
- * be pushed onto the stack */
- bool pending_quick_menu;
- bool prevent_populate;
- /* The menu driver owns the userdata */
- bool data_own;
- /* Flagged when menu entries need to be refreshed */
- bool entries_need_refresh;
- bool entries_nonblocking_refresh;
- /* 'Close Content'-hotkey menu resetting */
- bool pending_close_content;
- /* Screensaver status
- * - Does menu driver support screensaver functionality?
- * - Is screensaver currently active? */
- bool screensaver_supported;
- bool screensaver_active;
-};
-
-struct menu_bind_state_port
-{
- int16_t axes[MENU_MAX_AXES];
- uint16_t hats[MENU_MAX_HATS];
- bool mouse_buttons[MENU_MAX_MBUTTONS];
- bool buttons[MENU_MAX_BUTTONS];
-};
-
-struct menu_bind_axis_state
-{
- /* Default axis state. */
- int16_t rested_axes[MENU_MAX_AXES];
- /* Locked axis state. If we configured an axis,
- * avoid having the same axis state trigger something again right away. */
- int16_t locked_axes[MENU_MAX_AXES];
-};
-
-struct menu_bind_state
-{
- rarch_timer_t timer_timeout;
- rarch_timer_t timer_hold;
-
- struct retro_keybind *output;
- struct retro_keybind buffer;
-
- struct menu_bind_state_port state[MAX_USERS];
- struct menu_bind_axis_state axis_state[MAX_USERS];
-
- unsigned begin;
- unsigned last;
- unsigned user;
- unsigned port;
-
- bool skip;
-};
-#endif
-
typedef struct input_mapper
{
/* Left X, Left Y, Right X, Right Y */
diff --git a/retroarch_fwd_decls.h b/retroarch_fwd_decls.h
index 295ffd85dc..897c39ea9c 100644
--- a/retroarch_fwd_decls.h
+++ b/retroarch_fwd_decls.h
@@ -44,13 +44,13 @@ static bool midi_driver_set_all_sounds_off(struct rarch_state *p_rarch);
static const void *midi_driver_find_handle(int index);
static bool midi_driver_flush(void);
-static void retroarch_deinit_core_options(struct rarch_state *p_rarch,
+static void retroarch_deinit_core_options(
const char *p);
static void retroarch_init_core_variables(
- struct rarch_state *p_rarch,
+ settings_t *settings,
const struct retro_variable *vars);
static void rarch_init_core_options(
- struct rarch_state *p_rarch,
+ settings_t *settings,
const struct retro_core_options_v2 *options_v2);
#ifdef HAVE_RUNAHEAD
#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)