From 18ba3ef3e50fcf8555499152d80db465658442cc Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 9 Mar 2013 15:33:44 +0100 Subject: [PATCH] Integrate rmenu_genric.c into rgui.c --- console/griffin/griffin.c | 2 - frontend/menu/rgui.c | 394 ++++++++++++++++++++++++++++++++ frontend/menu/rmenu_generic.c | 413 ---------------------------------- 3 files changed, 394 insertions(+), 415 deletions(-) delete mode 100644 frontend/menu/rmenu_generic.c diff --git a/console/griffin/griffin.c b/console/griffin/griffin.c index 3414acb4e1..2fa09cc89a 100644 --- a/console/griffin/griffin.c +++ b/console/griffin/griffin.c @@ -442,8 +442,6 @@ MENU #if defined(_XBOX360) #include "../../frontend/menu/rmenu_xui.cpp" -#elif defined(HAVE_RGUI) -#include "../../frontend/menu/rmenu_generic.c" #endif #endif diff --git a/frontend/menu/rgui.c b/frontend/menu/rgui.c index 7b1cd69357..1bc66e0d96 100644 --- a/frontend/menu/rgui.c +++ b/frontend/menu/rgui.c @@ -22,7 +22,14 @@ #include "rgui.h" #include "utils/file_list.h" #include "rmenu_settings.h" +#include "../../general.h" #include "../../gfx/gfx_common.h" + +#ifdef HAVE_OPENGL +#include "../../gfx/gl_common.h" +#endif + +#include "../../gfx/fonts/bitmap.h" #include "../../screenshot.h" #define TERM_START_X 15 @@ -127,6 +134,8 @@ static const char *rgui_device_labels[] = { unsigned RGUI_WIDTH = 320; unsigned RGUI_HEIGHT = 240; +uint16_t menu_framebuf[400 * 240]; +rgui_handle_t *rgui; struct rgui_handle { @@ -1424,3 +1433,388 @@ int rgui_iterate(rgui_handle_t *rgui, rgui_action_t action) return ret; } + +static const struct retro_keybind _rmenu_nav_binds[] = { +#if defined(HW_RVL) + { 0, 0, NULL, 0, GX_GC_UP | GX_GC_LSTICK_UP | GX_GC_RSTICK_UP | GX_CLASSIC_UP | GX_CLASSIC_LSTICK_UP | GX_CLASSIC_RSTICK_UP | GX_WIIMOTE_UP | GX_NUNCHUK_UP, 0 }, + { 0, 0, NULL, 0, GX_GC_DOWN | GX_GC_LSTICK_DOWN | GX_GC_RSTICK_DOWN | GX_CLASSIC_DOWN | GX_CLASSIC_LSTICK_DOWN | GX_CLASSIC_RSTICK_DOWN | GX_WIIMOTE_DOWN | GX_NUNCHUK_DOWN, 0 }, + { 0, 0, NULL, 0, GX_GC_LEFT | GX_GC_LSTICK_LEFT | GX_GC_RSTICK_LEFT | GX_CLASSIC_LEFT | GX_CLASSIC_LSTICK_LEFT | GX_CLASSIC_RSTICK_LEFT | GX_WIIMOTE_LEFT | GX_NUNCHUK_LEFT, 0 }, + { 0, 0, NULL, 0, GX_GC_RIGHT | GX_GC_LSTICK_RIGHT | GX_GC_RSTICK_RIGHT | GX_CLASSIC_RIGHT | GX_CLASSIC_LSTICK_RIGHT | GX_CLASSIC_RSTICK_RIGHT | GX_WIIMOTE_RIGHT | GX_NUNCHUK_RIGHT, 0 }, + { 0, 0, NULL, 0, GX_GC_A | GX_CLASSIC_A | GX_WIIMOTE_A | GX_WIIMOTE_2, 0 }, + { 0, 0, NULL, 0, GX_GC_B | GX_CLASSIC_B | GX_WIIMOTE_B | GX_WIIMOTE_1, 0 }, + { 0, 0, NULL, 0, GX_GC_START | GX_CLASSIC_PLUS | GX_WIIMOTE_PLUS, 0 }, + { 0, 0, NULL, 0, GX_GC_Z_TRIGGER | GX_CLASSIC_MINUS | GX_WIIMOTE_MINUS, 0 }, + { 0, 0, NULL, 0, GX_WIIMOTE_HOME | GX_CLASSIC_HOME, 0 }, +#elif defined(HW_DOL) + { 0, 0, NULL, 0, GX_GC_UP | GX_GC_LSTICK_UP | GX_GC_RSTICK_UP, 0 }, + { 0, 0, NULL, 0, GX_GC_DOWN | GX_GC_LSTICK_DOWN | GX_GC_RSTICK_DOWN, 0 }, + { 0, 0, NULL, 0, GX_GC_LEFT | GX_GC_LSTICK_LEFT | GX_GC_RSTICK_LEFT, 0 }, + { 0, 0, NULL, 0, GX_GC_RIGHT | GX_GC_LSTICK_RIGHT | GX_GC_RSTICK_RIGHT, 0 }, + { 0, 0, NULL, 0, GX_GC_A, 0 }, + { 0, 0, NULL, 0, GX_GC_B, 0 }, + { 0, 0, NULL, 0, GX_GC_START, 0 }, + { 0, 0, NULL, 0, GX_GC_Z_TRIGGER, 0 }, + { 0, 0, NULL, 0, GX_WIIMOTE_HOME, 0 }, + { 0, 0, NULL, 0, GX_QUIT_KEY, 0 }, +#else + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_UP), 0 }, + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN), 0 }, + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT), 0 }, + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT), 0 }, + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_A), 0 }, + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_B), 0 }, + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_START), 0 }, + { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_SELECT), 0 }, + { 0, 0, NULL, 0, (1ULL << RARCH_RMENU_TOGGLE), 0 }, + { 0, 0, NULL, 0, (1ULL << RARCH_QUIT_KEY), 0 }, +#endif +}; + +static const struct retro_keybind *rmenu_nav_binds[] = { + _rmenu_nav_binds +}; + +enum +{ + GX_DEVICE_NAV_UP = 0, + GX_DEVICE_NAV_DOWN, + GX_DEVICE_NAV_LEFT, + GX_DEVICE_NAV_RIGHT, + GX_DEVICE_NAV_A, + GX_DEVICE_NAV_B, + GX_DEVICE_NAV_START, + GX_DEVICE_NAV_SELECT, + GX_DEVICE_NAV_MENU, + GX_DEVICE_NAV_QUIT, + RMENU_DEVICE_NAV_LAST +}; + +#ifdef GEKKO +static bool folder_cb(const char *directory, rgui_file_enum_cb_t file_cb, + void *userdata, void *ctx) +{ +#ifdef HAVE_LIBRETRO_MANAGEMENT + bool core_chooser = (userdata) ? *(rgui_file_type_t *)userdata == RGUI_SETTINGS_CORE : false; +#else + bool core_chooser = false; +#endif + + if (!*directory) + { +#ifdef HW_RVL + file_cb(ctx, "sd:", RGUI_FILE_DEVICE, 0); + file_cb(ctx, "usb:", RGUI_FILE_DEVICE, 0); +#endif + file_cb(ctx, "carda:", RGUI_FILE_DEVICE, 0); + file_cb(ctx, "cardb:", RGUI_FILE_DEVICE, 0); + return true; + } + +#ifdef HW_RVL + LWP_MutexLock(gx_device_mutex); + int dev = gx_get_device_from_path(directory); + + if (dev != -1 && !gx_devices[dev].mounted && gx_devices[dev].interface->isInserted()) + fatMountSimple(gx_devices[dev].name, gx_devices[dev].interface); + + LWP_MutexUnlock(gx_device_mutex); +#endif + + char exts[256]; + if (core_chooser) + strlcpy(exts, "dol|DOL", sizeof(exts)); + else + strlcpy(exts, g_extern.system.valid_extensions, sizeof(exts)); + + struct string_list *ext_list = string_split(exts, "|"); + + char _dir[PATH_MAX]; + snprintf(_dir, sizeof(_dir), "%s/", directory); + DIR *dir = opendir(_dir); + if (!dir) + return false; + + struct dirent *entry; + while ((entry = readdir(dir))) + { + char stat_path[PATH_MAX]; + const char *file_ext = path_get_extension(entry->d_name); + snprintf(stat_path, sizeof(stat_path), "%s/%s", directory, entry->d_name); + bool is_dir; + +#ifdef _DIRENT_HAVE_D_TYPE + is_dir = (entry->d_type == DT_DIR); + if (entry->d_type != DT_REG && !is_dir) + continue; +#else + struct stat st; + if (stat(stat_path, &st) < 0) + continue; + + is_dir = S_ISDIR(st.st_mode); + if (!S_ISREG(st.st_mode) && !is_dir) + continue; +#endif + + if (core_chooser && (is_dir || strcasecmp(entry->d_name, default_paths.salamander_file) == 0)) + continue; + + if (!is_dir && ext_list && !string_list_find_elem_prefix(ext_list, ".", file_ext)) + continue; + + file_cb(ctx, + entry->d_name, + is_dir ? RGUI_FILE_DIRECTORY : RGUI_FILE_PLAIN, 0); + } + + closedir(dir); + string_list_free(ext_list); + return true; +} +#else +static bool folder_cb(const char *directory, rgui_file_enum_cb_t file_cb, + void *userdata, void *ctx) +{ + struct string_list *ext_list = string_split(g_extern.system.valid_extensions, "|"); + + char _dir[PATH_MAX]; + snprintf(_dir, sizeof(_dir), "%s/", directory); + DIR *dir = opendir(_dir); + if (!dir) + return false; + + struct dirent *entry; + while ((entry = readdir(dir))) + { + char stat_path[PATH_MAX]; + const char *file_ext = path_get_extension(entry->d_name); + snprintf(stat_path, sizeof(stat_path), "%s/%s", directory, entry->d_name); + bool is_dir; + +#ifdef _DIRENT_HAVE_D_TYPE + is_dir = (entry->d_type == DT_DIR); + if (entry->d_type != DT_REG && !is_dir) + continue; +#else + struct stat st; + if (stat(stat_path, &st) < 0) + continue; + + is_dir = S_ISDIR(st.st_mode); + if (!S_ISREG(st.st_mode) && !is_dir) + continue; +#endif + + if (!is_dir && ext_list && !string_list_find_elem_prefix(ext_list, ".", file_ext)) + continue; + + file_cb(ctx, + entry->d_name, + is_dir ? RGUI_FILE_DIRECTORY : RGUI_FILE_PLAIN, 0); + } + + closedir(dir); + string_list_free(ext_list); + return true; +} +#endif + +/*============================================================ +RMENU API +============================================================ */ + +void menu_init(void) +{ +#if defined(HAVE_OPENGL) + gl_t *device_ptr = (gl_t*)driver.video_data; +#elif defined(GEKKO) + gx_video_t *device_ptr = (gx_video_t*)driver.video_data; +#endif + + device_ptr->menu_data = (uint32_t *) menu_framebuf; + + rgui = rgui_init("", + menu_framebuf, RGUI_WIDTH * sizeof(uint16_t), + NULL, bitmap_bin, folder_cb, NULL); + + rgui_iterate(rgui, RGUI_ACTION_REFRESH); +} + +void menu_free(void) +{ + rgui_free(rgui); +} + +static uint16_t trigger_state = 0; + +int rmenu_input_process(void *data, void *state) +{ + if (g_extern.lifecycle_mode_state & (1ULL << MODE_LOAD_GAME)) + { + if (g_extern.lifecycle_mode_state & (1ULL << MODE_INFO_DRAW)) + rmenu_settings_msg(S_MSG_LOADING_ROM, 100); + + if (g_extern.fullpath) + g_extern.lifecycle_mode_state |= (1ULL << MODE_INIT); + + g_extern.lifecycle_mode_state &= ~(1ULL << MODE_LOAD_GAME); + return -1; + } + + if (!(g_extern.frame_count < g_extern.delay_timer[0])) + { + bool return_to_game_enable = ((trigger_state & (1ULL << GX_DEVICE_NAV_MENU)) && g_extern.main_is_init); + + if (return_to_game_enable) + { + g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); + return -1; + } + } + + return 0; +} + +bool rmenu_iterate(void) +{ + static uint16_t old_input_state = 0; + static bool initial_held = true; + static bool first_held = false; + + g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU_DRAW); + driver.video->apply_state_changes(); + + g_extern.frame_count++; + + uint16_t input_state = 0; + + driver.input->poll(NULL); + +#ifdef HAVE_OVERLAY + if (driver.overlay) + { + driver.overlay_state = 0; + + unsigned device = input_overlay_full_screen(driver.overlay) ? + RARCH_DEVICE_POINTER_SCREEN : RETRO_DEVICE_POINTER; + + bool polled = false; + for (unsigned i = 0; + input_input_state_func(NULL, 0, device, i, RETRO_DEVICE_ID_POINTER_PRESSED); + i++) + { + int16_t x = input_input_state_func(NULL, 0, + device, i, RETRO_DEVICE_ID_POINTER_X); + int16_t y = input_input_state_func(NULL, 0, + device, i, RETRO_DEVICE_ID_POINTER_Y); + + driver.overlay_state |= input_overlay_poll(driver.overlay, x, y); + polled = true; + } + + if (!polled) + input_overlay_poll_clear(driver.overlay); + } +#endif + +#ifndef GEKKO + /* TODO - not sure if correct regarding RARCH_QUIT_KEY */ + if (input_key_pressed_func(RARCH_QUIT_KEY) || !video_alive_func()) + { + g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); + goto deinit; + } +#endif + + for (unsigned i = 0; i < RMENU_DEVICE_NAV_LAST; i++) + input_state |= driver.input->input_state(NULL, rmenu_nav_binds, 0, + RETRO_DEVICE_JOYPAD, 0, i) ? (1ULL << i) : 0; + + input_state |= driver.input->key_pressed(driver.input_data, RARCH_RMENU_TOGGLE) ? (1ULL << GX_DEVICE_NAV_MENU) : 0; + input_state |= driver.input->key_pressed(driver.input_data, RARCH_QUIT_KEY) ? (1ULL << GX_DEVICE_NAV_QUIT) : 0; + +#ifdef HAVE_OVERLAY + for (unsigned i = 0; i < RMENU_DEVICE_NAV_LAST; i++) + input_state |= driver.overlay_state & rmenu_nav_binds[0][i].joykey ? (1ULL << i) : 0; +#endif + + trigger_state = input_state & ~old_input_state; + bool do_held = (input_state & ((1ULL << GX_DEVICE_NAV_UP) | (1ULL << GX_DEVICE_NAV_DOWN) | (1ULL << GX_DEVICE_NAV_LEFT) | (1ULL << GX_DEVICE_NAV_RIGHT))) && !(input_state & ((1ULL << GX_DEVICE_NAV_MENU) | (1ULL << GX_DEVICE_NAV_QUIT))); + + if(do_held) + { + if(!first_held) + { + first_held = true; + g_extern.delay_timer[1] = g_extern.frame_count + (initial_held ? 15 : 7); + } + + if (!(g_extern.frame_count < g_extern.delay_timer[1])) + { + first_held = false; + trigger_state = input_state; //second input frame set as current frame + } + + initial_held = false; + } + else + { + first_held = false; + initial_held = true; + } + + old_input_state = input_state; + + rgui_action_t action = RGUI_ACTION_NOOP; + + // don't run anything first frame, only capture held inputs for old_input_state + if (trigger_state & (1ULL << GX_DEVICE_NAV_UP)) + action = RGUI_ACTION_UP; + else if (trigger_state & (1ULL << GX_DEVICE_NAV_DOWN)) + action = RGUI_ACTION_DOWN; + else if (trigger_state & (1ULL << GX_DEVICE_NAV_LEFT)) + action = RGUI_ACTION_LEFT; + else if (trigger_state & (1ULL << GX_DEVICE_NAV_RIGHT)) + action = RGUI_ACTION_RIGHT; + else if (trigger_state & (1ULL << GX_DEVICE_NAV_B)) + action = RGUI_ACTION_CANCEL; + else if (trigger_state & (1ULL << GX_DEVICE_NAV_A)) + action = RGUI_ACTION_OK; + else if (trigger_state & (1ULL << GX_DEVICE_NAV_START)) + action = RGUI_ACTION_START; + else if (trigger_state & (1ULL << GX_DEVICE_NAV_SELECT)) + action = RGUI_ACTION_SETTINGS; +#ifdef GEKKO + else if (trigger_state & (1ULL << GX_DEVICE_NAV_QUIT)) + { + g_extern.lifecycle_mode_state |= (1ULL << MODE_EXIT); + goto deinit; + } +#endif + + int input_entry_ret = 0; + int input_process_ret = 0; + + input_entry_ret = rgui_iterate(rgui, action); + + // draw last frame for loading messages + rarch_render_cached_frame(); + + input_process_ret = rmenu_input_process(NULL, NULL); + + if (input_entry_ret != 0 || input_process_ret != 0) + goto deinit; + + return true; + +deinit: + // set a timer delay so that we don't instantly switch back to the menu when + // press and holding QUIT in the emulation loop (lasts for 30 frame ticks) + if (!(g_extern.lifecycle_state & (1ULL << RARCH_FRAMEADVANCE))) + g_extern.delay_timer[0] = g_extern.frame_count + 30; + + g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU_DRAW); + g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU_INGAME); + + return false; +} diff --git a/frontend/menu/rmenu_generic.c b/frontend/menu/rmenu_generic.c deleted file mode 100644 index 1ca0e4a800..0000000000 --- a/frontend/menu/rmenu_generic.c +++ /dev/null @@ -1,413 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2013 - Hans-Kristian Arntzen - * Copyright (C) 2011-2013 - Daniel De Matteis - * - * 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 . - */ - -#include "rmenu.h" -#include "rgui.h" -#include "../../general.h" - -#ifdef HAVE_OPENGL -#include "../../gfx/gl_common.h" -#endif - -#include "../../gfx/fonts/bitmap.h" - -uint16_t menu_framebuf[400 * 240]; -rgui_handle_t *rgui; - -static const struct retro_keybind _rmenu_nav_binds[] = { -#if defined(HW_RVL) - { 0, 0, NULL, 0, GX_GC_UP | GX_GC_LSTICK_UP | GX_GC_RSTICK_UP | GX_CLASSIC_UP | GX_CLASSIC_LSTICK_UP | GX_CLASSIC_RSTICK_UP | GX_WIIMOTE_UP | GX_NUNCHUK_UP, 0 }, - { 0, 0, NULL, 0, GX_GC_DOWN | GX_GC_LSTICK_DOWN | GX_GC_RSTICK_DOWN | GX_CLASSIC_DOWN | GX_CLASSIC_LSTICK_DOWN | GX_CLASSIC_RSTICK_DOWN | GX_WIIMOTE_DOWN | GX_NUNCHUK_DOWN, 0 }, - { 0, 0, NULL, 0, GX_GC_LEFT | GX_GC_LSTICK_LEFT | GX_GC_RSTICK_LEFT | GX_CLASSIC_LEFT | GX_CLASSIC_LSTICK_LEFT | GX_CLASSIC_RSTICK_LEFT | GX_WIIMOTE_LEFT | GX_NUNCHUK_LEFT, 0 }, - { 0, 0, NULL, 0, GX_GC_RIGHT | GX_GC_LSTICK_RIGHT | GX_GC_RSTICK_RIGHT | GX_CLASSIC_RIGHT | GX_CLASSIC_LSTICK_RIGHT | GX_CLASSIC_RSTICK_RIGHT | GX_WIIMOTE_RIGHT | GX_NUNCHUK_RIGHT, 0 }, - { 0, 0, NULL, 0, GX_GC_A | GX_CLASSIC_A | GX_WIIMOTE_A | GX_WIIMOTE_2, 0 }, - { 0, 0, NULL, 0, GX_GC_B | GX_CLASSIC_B | GX_WIIMOTE_B | GX_WIIMOTE_1, 0 }, - { 0, 0, NULL, 0, GX_GC_START | GX_CLASSIC_PLUS | GX_WIIMOTE_PLUS, 0 }, - { 0, 0, NULL, 0, GX_GC_Z_TRIGGER | GX_CLASSIC_MINUS | GX_WIIMOTE_MINUS, 0 }, - { 0, 0, NULL, 0, GX_WIIMOTE_HOME | GX_CLASSIC_HOME, 0 }, -#elif defined(HW_DOL) - { 0, 0, NULL, 0, GX_GC_UP | GX_GC_LSTICK_UP | GX_GC_RSTICK_UP, 0 }, - { 0, 0, NULL, 0, GX_GC_DOWN | GX_GC_LSTICK_DOWN | GX_GC_RSTICK_DOWN, 0 }, - { 0, 0, NULL, 0, GX_GC_LEFT | GX_GC_LSTICK_LEFT | GX_GC_RSTICK_LEFT, 0 }, - { 0, 0, NULL, 0, GX_GC_RIGHT | GX_GC_LSTICK_RIGHT | GX_GC_RSTICK_RIGHT, 0 }, - { 0, 0, NULL, 0, GX_GC_A, 0 }, - { 0, 0, NULL, 0, GX_GC_B, 0 }, - { 0, 0, NULL, 0, GX_GC_START, 0 }, - { 0, 0, NULL, 0, GX_GC_Z_TRIGGER, 0 }, - { 0, 0, NULL, 0, GX_WIIMOTE_HOME, 0 }, - { 0, 0, NULL, 0, GX_QUIT_KEY, 0 }, -#else - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_UP), 0 }, - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN), 0 }, - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT), 0 }, - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT), 0 }, - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_A), 0 }, - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_B), 0 }, - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_START), 0 }, - { 0, 0, NULL, 0, (1ULL << RETRO_DEVICE_ID_JOYPAD_SELECT), 0 }, - { 0, 0, NULL, 0, (1ULL << RARCH_RMENU_TOGGLE), 0 }, - { 0, 0, NULL, 0, (1ULL << RARCH_QUIT_KEY), 0 }, -#endif -}; - -static const struct retro_keybind *rmenu_nav_binds[] = { - _rmenu_nav_binds -}; - -enum -{ - GX_DEVICE_NAV_UP = 0, - GX_DEVICE_NAV_DOWN, - GX_DEVICE_NAV_LEFT, - GX_DEVICE_NAV_RIGHT, - GX_DEVICE_NAV_A, - GX_DEVICE_NAV_B, - GX_DEVICE_NAV_START, - GX_DEVICE_NAV_SELECT, - GX_DEVICE_NAV_MENU, - GX_DEVICE_NAV_QUIT, - RMENU_DEVICE_NAV_LAST -}; - -#ifdef GEKKO -static bool folder_cb(const char *directory, rgui_file_enum_cb_t file_cb, - void *userdata, void *ctx) -{ -#ifdef HAVE_LIBRETRO_MANAGEMENT - bool core_chooser = (userdata) ? *(rgui_file_type_t *)userdata == RGUI_SETTINGS_CORE : false; -#else - bool core_chooser = false; -#endif - - if (!*directory) - { -#ifdef HW_RVL - file_cb(ctx, "sd:", RGUI_FILE_DEVICE, 0); - file_cb(ctx, "usb:", RGUI_FILE_DEVICE, 0); -#endif - file_cb(ctx, "carda:", RGUI_FILE_DEVICE, 0); - file_cb(ctx, "cardb:", RGUI_FILE_DEVICE, 0); - return true; - } - -#ifdef HW_RVL - LWP_MutexLock(gx_device_mutex); - int dev = gx_get_device_from_path(directory); - - if (dev != -1 && !gx_devices[dev].mounted && gx_devices[dev].interface->isInserted()) - fatMountSimple(gx_devices[dev].name, gx_devices[dev].interface); - - LWP_MutexUnlock(gx_device_mutex); -#endif - - char exts[256]; - if (core_chooser) - strlcpy(exts, "dol|DOL", sizeof(exts)); - else - strlcpy(exts, g_extern.system.valid_extensions, sizeof(exts)); - - struct string_list *ext_list = string_split(exts, "|"); - - char _dir[PATH_MAX]; - snprintf(_dir, sizeof(_dir), "%s/", directory); - DIR *dir = opendir(_dir); - if (!dir) - return false; - - struct dirent *entry; - while ((entry = readdir(dir))) - { - char stat_path[PATH_MAX]; - const char *file_ext = path_get_extension(entry->d_name); - snprintf(stat_path, sizeof(stat_path), "%s/%s", directory, entry->d_name); - bool is_dir; - -#ifdef _DIRENT_HAVE_D_TYPE - is_dir = (entry->d_type == DT_DIR); - if (entry->d_type != DT_REG && !is_dir) - continue; -#else - struct stat st; - if (stat(stat_path, &st) < 0) - continue; - - is_dir = S_ISDIR(st.st_mode); - if (!S_ISREG(st.st_mode) && !is_dir) - continue; -#endif - - if (core_chooser && (is_dir || strcasecmp(entry->d_name, default_paths.salamander_file) == 0)) - continue; - - if (!is_dir && ext_list && !string_list_find_elem_prefix(ext_list, ".", file_ext)) - continue; - - file_cb(ctx, - entry->d_name, - is_dir ? RGUI_FILE_DIRECTORY : RGUI_FILE_PLAIN, 0); - } - - closedir(dir); - string_list_free(ext_list); - return true; -} -#else -static bool folder_cb(const char *directory, rgui_file_enum_cb_t file_cb, - void *userdata, void *ctx) -{ - struct string_list *ext_list = string_split(g_extern.system.valid_extensions, "|"); - - char _dir[PATH_MAX]; - snprintf(_dir, sizeof(_dir), "%s/", directory); - DIR *dir = opendir(_dir); - if (!dir) - return false; - - struct dirent *entry; - while ((entry = readdir(dir))) - { - char stat_path[PATH_MAX]; - const char *file_ext = path_get_extension(entry->d_name); - snprintf(stat_path, sizeof(stat_path), "%s/%s", directory, entry->d_name); - bool is_dir; - -#ifdef _DIRENT_HAVE_D_TYPE - is_dir = (entry->d_type == DT_DIR); - if (entry->d_type != DT_REG && !is_dir) - continue; -#else - struct stat st; - if (stat(stat_path, &st) < 0) - continue; - - is_dir = S_ISDIR(st.st_mode); - if (!S_ISREG(st.st_mode) && !is_dir) - continue; -#endif - - if (!is_dir && ext_list && !string_list_find_elem_prefix(ext_list, ".", file_ext)) - continue; - - file_cb(ctx, - entry->d_name, - is_dir ? RGUI_FILE_DIRECTORY : RGUI_FILE_PLAIN, 0); - } - - closedir(dir); - string_list_free(ext_list); - return true; -} -#endif - -/*============================================================ -RMENU API -============================================================ */ - -void menu_init(void) -{ -#if defined(HAVE_OPENGL) - gl_t *device_ptr = (gl_t*)driver.video_data; -#elif defined(GEKKO) - gx_video_t *device_ptr = (gx_video_t*)driver.video_data; -#endif - - device_ptr->menu_data = (uint32_t *) menu_framebuf; - - rgui = rgui_init("", - menu_framebuf, RGUI_WIDTH * sizeof(uint16_t), - NULL, bitmap_bin, folder_cb, NULL); - - rgui_iterate(rgui, RGUI_ACTION_REFRESH); -} - -void menu_free(void) -{ - rgui_free(rgui); -} - -static uint16_t trigger_state = 0; - -int rmenu_input_process(void *data, void *state) -{ - if (g_extern.lifecycle_mode_state & (1ULL << MODE_LOAD_GAME)) - { - if (g_extern.lifecycle_mode_state & (1ULL << MODE_INFO_DRAW)) - rmenu_settings_msg(S_MSG_LOADING_ROM, 100); - - if (g_extern.fullpath) - g_extern.lifecycle_mode_state |= (1ULL << MODE_INIT); - - g_extern.lifecycle_mode_state &= ~(1ULL << MODE_LOAD_GAME); - return -1; - } - - if (!(g_extern.frame_count < g_extern.delay_timer[0])) - { - bool return_to_game_enable = ((trigger_state & (1ULL << GX_DEVICE_NAV_MENU)) && g_extern.main_is_init); - - if (return_to_game_enable) - { - g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); - return -1; - } - } - - return 0; -} - -bool rmenu_iterate(void) -{ - static uint16_t old_input_state = 0; - static bool initial_held = true; - static bool first_held = false; - - g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU_DRAW); - driver.video->apply_state_changes(); - - g_extern.frame_count++; - - uint16_t input_state = 0; - - driver.input->poll(NULL); - -#ifdef HAVE_OVERLAY - if (driver.overlay) - { - driver.overlay_state = 0; - - unsigned device = input_overlay_full_screen(driver.overlay) ? - RARCH_DEVICE_POINTER_SCREEN : RETRO_DEVICE_POINTER; - - bool polled = false; - for (unsigned i = 0; - input_input_state_func(NULL, 0, device, i, RETRO_DEVICE_ID_POINTER_PRESSED); - i++) - { - int16_t x = input_input_state_func(NULL, 0, - device, i, RETRO_DEVICE_ID_POINTER_X); - int16_t y = input_input_state_func(NULL, 0, - device, i, RETRO_DEVICE_ID_POINTER_Y); - - driver.overlay_state |= input_overlay_poll(driver.overlay, x, y); - polled = true; - } - - if (!polled) - input_overlay_poll_clear(driver.overlay); - } -#endif - -#ifndef GEKKO - /* TODO - not sure if correct regarding RARCH_QUIT_KEY */ - if (input_key_pressed_func(RARCH_QUIT_KEY) || !video_alive_func()) - { - g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); - goto deinit; - } -#endif - - for (unsigned i = 0; i < RMENU_DEVICE_NAV_LAST; i++) - input_state |= driver.input->input_state(NULL, rmenu_nav_binds, 0, - RETRO_DEVICE_JOYPAD, 0, i) ? (1ULL << i) : 0; - - input_state |= driver.input->key_pressed(driver.input_data, RARCH_RMENU_TOGGLE) ? (1ULL << GX_DEVICE_NAV_MENU) : 0; - input_state |= driver.input->key_pressed(driver.input_data, RARCH_QUIT_KEY) ? (1ULL << GX_DEVICE_NAV_QUIT) : 0; - -#ifdef HAVE_OVERLAY - for (unsigned i = 0; i < RMENU_DEVICE_NAV_LAST; i++) - input_state |= driver.overlay_state & rmenu_nav_binds[0][i].joykey ? (1ULL << i) : 0; -#endif - - trigger_state = input_state & ~old_input_state; - bool do_held = (input_state & ((1ULL << GX_DEVICE_NAV_UP) | (1ULL << GX_DEVICE_NAV_DOWN) | (1ULL << GX_DEVICE_NAV_LEFT) | (1ULL << GX_DEVICE_NAV_RIGHT))) && !(input_state & ((1ULL << GX_DEVICE_NAV_MENU) | (1ULL << GX_DEVICE_NAV_QUIT))); - - if(do_held) - { - if(!first_held) - { - first_held = true; - g_extern.delay_timer[1] = g_extern.frame_count + (initial_held ? 15 : 7); - } - - if (!(g_extern.frame_count < g_extern.delay_timer[1])) - { - first_held = false; - trigger_state = input_state; //second input frame set as current frame - } - - initial_held = false; - } - else - { - first_held = false; - initial_held = true; - } - - old_input_state = input_state; - - rgui_action_t action = RGUI_ACTION_NOOP; - - // don't run anything first frame, only capture held inputs for old_input_state - if (trigger_state & (1ULL << GX_DEVICE_NAV_UP)) - action = RGUI_ACTION_UP; - else if (trigger_state & (1ULL << GX_DEVICE_NAV_DOWN)) - action = RGUI_ACTION_DOWN; - else if (trigger_state & (1ULL << GX_DEVICE_NAV_LEFT)) - action = RGUI_ACTION_LEFT; - else if (trigger_state & (1ULL << GX_DEVICE_NAV_RIGHT)) - action = RGUI_ACTION_RIGHT; - else if (trigger_state & (1ULL << GX_DEVICE_NAV_B)) - action = RGUI_ACTION_CANCEL; - else if (trigger_state & (1ULL << GX_DEVICE_NAV_A)) - action = RGUI_ACTION_OK; - else if (trigger_state & (1ULL << GX_DEVICE_NAV_START)) - action = RGUI_ACTION_START; - else if (trigger_state & (1ULL << GX_DEVICE_NAV_SELECT)) - action = RGUI_ACTION_SETTINGS; -#ifdef GEKKO - else if (trigger_state & (1ULL << GX_DEVICE_NAV_QUIT)) - { - g_extern.lifecycle_mode_state |= (1ULL << MODE_EXIT); - goto deinit; - } -#endif - - int input_entry_ret = 0; - int input_process_ret = 0; - - input_entry_ret = rgui_iterate(rgui, action); - - // draw last frame for loading messages - rarch_render_cached_frame(); - - input_process_ret = rmenu_input_process(NULL, NULL); - - if (input_entry_ret != 0 || input_process_ret != 0) - goto deinit; - - return true; - -deinit: - // set a timer delay so that we don't instantly switch back to the menu when - // press and holding QUIT in the emulation loop (lasts for 30 frame ticks) - if (!(g_extern.lifecycle_state & (1ULL << RARCH_FRAMEADVANCE))) - g_extern.delay_timer[0] = g_extern.frame_count + 30; - - g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU_DRAW); - g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU_INGAME); - - return false; -}