diff --git a/android/native/jni/Android.mk b/android/native/jni/Android.mk index 1039768f1c..7c9579fa7f 100644 --- a/android/native/jni/Android.mk +++ b/android/native/jni/Android.mk @@ -51,7 +51,7 @@ ifeq ($(PERF_TEST), 1) LOCAL_CFLAGS += -DPERF_TEST endif -LOCAL_CFLAGS += -Wall -pthread -Wno-unused-function -O3 -fno-stack-protector -funroll-loops -DNDEBUG -DHAVE_GRIFFIN -DANDROID -DHAVE_DYNAMIC -DHAVE_OPENGL -DHAVE_FBO -DHAVE_OVERLAY -DHAVE_OPENGLES -DHAVE_VID_CONTEXT -DHAVE_OPENGLES2 -DGLSL_DEBUG -DHAVE_GLSL -DWANT_MINIZ -DHAVE_ZLIB -DINLINE=inline -DLSB_FIRST -DHAVE_THREADS -D__LIBRETRO__ -DRARCH_PERFORMANCE_MODE -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -std=gnu99 -I../../../deps/miniz +LOCAL_CFLAGS += -Wall -pthread -Wno-unused-function -O3 -fno-stack-protector -funroll-loops -DNDEBUG -DHAVE_GRIFFIN -DANDROID -DHAVE_DYNAMIC -DHAVE_OPENGL -DHAVE_FBO -DHAVE_OVERLAY -DHAVE_OPENGLES -DHAVE_VID_CONTEXT -DHAVE_OPENGLES2 -DGLSL_DEBUG -DHAVE_GLSL -DHAVE_RMENU -DHAVE_RGUI -DHAVE_SCREENSHOTS -DWANT_MINIZ -DHAVE_ZLIB -DINLINE=inline -DLSB_FIRST -DHAVE_THREADS -D__LIBRETRO__ -DRARCH_PERFORMANCE_MODE -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -std=gnu99 -I../../../deps/miniz LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -landroid -lEGL -lGLESv2 $(LOGGER_LDLIBS) -ldl diff --git a/android/native/jni/input_android.c b/android/native/jni/input_android.c index 5e30de86f4..ee3d722449 100644 --- a/android/native/jni/input_android.c +++ b/android/native/jni/input_android.c @@ -301,7 +301,7 @@ static void android_input_poll(void *data) uint64_t *lifecycle_state = &g_extern.lifecycle_state; AInputEvent* event = NULL; - *lifecycle_state &= ~((1ULL << RARCH_RESET) | (1ULL << RARCH_REWIND) | (1ULL << RARCH_FAST_FORWARD_KEY) | (1ULL << RARCH_FAST_FORWARD_HOLD_KEY) | (1ULL << RARCH_MUTE) | (1ULL << RARCH_SAVE_STATE_KEY) | (1ULL << RARCH_LOAD_STATE_KEY) | (1ULL << RARCH_STATE_SLOT_PLUS) | (1ULL << RARCH_STATE_SLOT_MINUS)); + *lifecycle_state &= ~((1ULL << RARCH_RESET) | (1ULL << RARCH_REWIND) | (1ULL << RARCH_FAST_FORWARD_KEY) | (1ULL << RARCH_FAST_FORWARD_HOLD_KEY) | (1ULL << RARCH_MUTE) | (1ULL << RARCH_SAVE_STATE_KEY) | (1ULL << RARCH_LOAD_STATE_KEY) | (1ULL << RARCH_STATE_SLOT_PLUS) | (1ULL << RARCH_STATE_SLOT_MINUS) | (1ULL << RARCH_QUIT_KEY)); // Read all pending events. while (AInputQueue_hasEvents(android_app->inputQueue)) diff --git a/android/native/jni/input_autodetect.c b/android/native/jni/input_autodetect.c index 131db9603e..568d6d98b7 100644 --- a/android/native/jni/input_autodetect.c +++ b/android/native/jni/input_autodetect.c @@ -139,6 +139,8 @@ void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned } } + keycode_lut[AKEYCODE_MENU] |= ((RARCH_RMENU_TOGGLE + 1) << shift); + if (g_settings.input.autodetect_enable) { diff --git a/console/griffin/griffin.c b/console/griffin/griffin.c index 20d3fbfe21..0c0195b00b 100644 --- a/console/griffin/griffin.c +++ b/console/griffin/griffin.c @@ -33,8 +33,6 @@ CONSOLE EXTENSIONS ============================================================ */ #ifdef RARCH_CONSOLE -#include "../rarch_console_video.c" - #ifdef HW_DOL #include "../../ngc/ssaram.c" #endif @@ -440,12 +438,15 @@ MENU #endif #ifdef HAVE_RMENU +#include "../rarch_console_video.c" #include "../../frontend/menu/rmenu_settings.c" #if defined(_XBOX360) #include "../../frontend/menu/rmenu_xui.cpp" #elif defined(GEKKO) #include "../../frontend/menu/rmenu_gx.c" +#elif defined(ANDROID) +#include "../../frontend/menu/rmenu_generic.c" #endif #endif diff --git a/console/griffin/hook_context.h b/console/griffin/hook_context.h index 3184a420df..f638edba24 100644 --- a/console/griffin/hook_context.h +++ b/console/griffin/hook_context.h @@ -42,6 +42,7 @@ #ifdef HAVE_RMENU #define context_rmenu_init_func() gl->ctx_driver->rmenu_init() #define context_rmenu_frame_func(ctx) gl->ctx_driver->rmenu_frame(ctx) +#define context_rmenu_free_func() gl->ctx_driver->rmenu_free() #endif #ifdef HAVE_EGL diff --git a/frontend/frontend_android.c b/frontend/frontend_android.c index 1747a0dc16..7f8a7dd930 100644 --- a/frontend/frontend_android.c +++ b/frontend/frontend_android.c @@ -25,6 +25,7 @@ #include "../general.h" #include "../performance.h" #include "../driver.h" +#include "menu/rmenu.h" #include "../config.def.h" @@ -212,9 +213,17 @@ static void *android_app_entry(void *data) if (!android_app_start_main(android_app, &init_ret)) goto exit; - if (g_extern.main_is_init) + menu_init(); + + g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); +begin_loop: + if(g_extern.lifecycle_mode_state & (1ULL << MODE_GAME)) { - RARCH_LOG("RetroArch started.\n"); + driver.input->poll(NULL); + driver.video->set_aspect_ratio(driver.video_data, g_settings.video.aspect_ratio_idx); + + if (g_extern.lifecycle_mode_state & (1ULL << MODE_VIDEO_THROTTLE_ENABLE)) + audio_start_func(); // Main loop do @@ -222,13 +231,29 @@ static void *android_app_entry(void *data) input_async_poll_func(); } while (rarch_main_iterate()); - RARCH_LOG("RetroArch stopped.\n"); + if (g_extern.lifecycle_mode_state & (1ULL << MODE_VIDEO_THROTTLE_ENABLE)) + audio_stop_func(); + g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME); } + else if(g_extern.lifecycle_mode_state & (1ULL << MODE_MENU)) + { + g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU_PREINIT); + while((input_key_pressed_func(RARCH_PAUSE_TOGGLE)) ? + android_run_events(android_app) : + rmenu_iterate()); + g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU); + } + else + goto exit; + + goto begin_loop; exit: android_app->activityState = APP_CMD_DEAD; RARCH_LOG("Deinitializing RetroArch...\n"); + menu_free(); + if (g_extern.main_is_init) rarch_main_deinit(); diff --git a/frontend/menu/rgui.c b/frontend/menu/rgui.c index ed035fa0d8..f69a356adc 100644 --- a/frontend/menu/rgui.c +++ b/frontend/menu/rgui.c @@ -116,6 +116,13 @@ unsigned rgui_gx_resolutions[GX_RESOLUTIONS_LAST][2] = { }; unsigned rgui_current_gx_resolution = GX_RESOLUTIONS_640_480; + +static const char *rgui_device_labels[] = { + "GameCube Controller", + "Wiimote", + "Wiimote + Nunchuk", + "Classic Controller", +}; #endif unsigned RGUI_WIDTH = 320; @@ -141,13 +148,6 @@ struct rgui_handle bool alloc_font; }; -static const char *rgui_device_labels[] = { - "GameCube Controller", - "Wiimote", - "Wiimote + Nunchuk", - "Classic Controller", -}; - static const unsigned rgui_controller_lut[] = { RETRO_DEVICE_ID_JOYPAD_UP, RETRO_DEVICE_ID_JOYPAD_DOWN, @@ -177,7 +177,7 @@ static inline bool rgui_is_viewport_menu(rgui_file_type_t menu_type) return (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT || menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2); } -static void copy_glyph(uint8_t *glyph, const uint8_t *buf) +static void rgui_copy_glyph(uint8_t *glyph, const uint8_t *buf) { for (int y = 0; y < FONT_HEIGHT; y++) { @@ -205,7 +205,7 @@ static void init_font(rgui_handle_t *rgui, const uint8_t *font_bmp_buf) { unsigned y = i / 16; unsigned x = i % 16; - copy_glyph(&font[FONT_OFFSET(i)], + rgui_copy_glyph(&font[FONT_OFFSET(i)], font_bmp_buf + 54 + 3 * (256 * (255 - 16 * y) + 16 * x)); } @@ -227,7 +227,11 @@ rgui_handle_t *rgui_init(const char *base_path, rgui->path_stack = rgui_list_new(); rgui->folder_buf = rgui_list_new(); +#ifdef RARCH_CONSOLE rgui_list_push(rgui->path_stack, base_path, RGUI_FILE_DIRECTORY, 0); +#else + rgui_list_push(rgui->path_stack, base_path, RGUI_SETTINGS, 0); +#endif if (font_bmp_buf) init_font(rgui, font_bmp_buf); @@ -257,7 +261,11 @@ static uint16_t gray_filler(unsigned x, unsigned y) x >>= 1; y >>= 1; unsigned col = ((x + y) & 1) + 1; +#ifdef GEKKO return (6 << 12) | (col << 8) | (col << 4) | (col << 0); +#else + return (col << 13) | (col << 9) | (col << 5) | (12 << 0); +#endif } static uint16_t green_filler(unsigned x, unsigned y) @@ -265,7 +273,11 @@ static uint16_t green_filler(unsigned x, unsigned y) x >>= 1; y >>= 1; unsigned col = ((x + y) & 1) + 1; +#ifdef GEKKO return (6 << 12) | (col << 8) | (col << 5) | (col << 0); +#else + return (col << 13) | (col << 10) | (col << 5) | (12 << 0); +#endif } static void fill_rect(uint16_t *buf, unsigned pitch, @@ -293,7 +305,11 @@ static void blit_line(rgui_handle_t *rgui, if (col) rgui->frame_buf[(y + j) * (rgui->frame_buf_pitch >> 1) + (x + i)] = green ? +#ifdef GEKKO (3 << 0) | (10 << 4) | (3 << 8) | (7 << 12) : 0x7FFF; +#else + (15 << 0) | (7 << 4) | (15 << 8) | (7 << 12) : 0xFFFF; +#endif } } @@ -406,7 +422,9 @@ static void render_text(rgui_handle_t *rgui) char message[TERM_WIDTH + 1]; char type_str[TERM_WIDTH + 1]; int w = rgui_is_controller_menu(menu_type) ? 26 : 19; +#ifdef RARCH_CONSOLE unsigned port = menu_type - RGUI_SETTINGS_CONTROLLER_1; +#endif switch (type) { case RGUI_FILE_PLAIN: @@ -493,9 +511,12 @@ static void render_text(rgui_handle_t *rgui) case RGUI_SETTINGS_CONTROLLER_4: snprintf(type_str, sizeof(type_str), "..."); break; +#ifdef GEKKO case RGUI_SETTINGS_BIND_DEVICE: snprintf(type_str, sizeof(type_str), "%s", rgui_device_labels[g_settings.input.device[port]]); break; +#endif +#ifdef RARCH_CONSOLE case RGUI_SETTINGS_BIND_DPAD_EMULATION: snprintf(type_str, sizeof(type_str), "%s", rarch_dpad_emulation_name_lut[g_settings.input.dpad_emulation[port]]); break; @@ -517,6 +538,7 @@ static void render_text(rgui_handle_t *rgui) case RGUI_SETTINGS_BIND_R3: snprintf(type_str, sizeof(type_str), "%s", rarch_input_find_platform_key_label(g_settings.input.binds[port][rgui_controller_lut[type - RGUI_SETTINGS_BIND_UP]].joykey)); break; +#endif default: type_str[0] = 0; w = 0; @@ -573,7 +595,9 @@ static void render_text(rgui_handle_t *rgui) static int rgui_settings_toggle_setting(rgui_file_type_t setting, rgui_action_t action, rgui_file_type_t menu_type) { - unsigned port = menu_type - RGUI_SETTINGS_CONTROLLER_1; +#ifdef RARCH_CONSOLE + unsigned port = menu_type - RGUI_SETTINGS_CONTROLLER_1; +#endif switch (setting) { @@ -625,9 +649,15 @@ static int rgui_settings_toggle_setting(rgui_file_type_t setting, rgui_action_t unsigned height = g_extern.frame_cache.height; int pitch = g_extern.frame_cache.pitch; +#ifdef RARCH_CONSOLE + const char *screenshot_dir = default_paths.port_dir; +#else + const char *screenshot_dir = g_settings.screenshot_directory; +#endif + // Negative pitch is needed as screenshot takes bottom-up, // but we use top-down. - bool r = screenshot_dump(default_paths.port_dir, + bool r = screenshot_dump(screenshot_dir, data + (height - 1) * (pitch >> 1), width, height, -pitch, false); @@ -838,6 +868,7 @@ static int rgui_settings_toggle_setting(rgui_file_type_t setting, rgui_action_t } break; // controllers +#ifdef GEKKO case RGUI_SETTINGS_BIND_DEVICE: g_settings.input.device[port] += RARCH_DEVICE_LAST; if (action == RGUI_ACTION_START) @@ -851,6 +882,8 @@ static int rgui_settings_toggle_setting(rgui_file_type_t setting, rgui_action_t rarch_input_set_default_keybinds(port); driver.input->set_analog_dpad_mapping(g_settings.input.device[port], g_settings.input.dpad_emulation[port], port); break; +#endif +#ifdef RARCH_CONSOLE case RGUI_SETTINGS_BIND_DPAD_EMULATION: g_settings.input.dpad_emulation[port] += DPAD_EMULATION_LAST; if (action == RGUI_ACTION_START) @@ -892,6 +925,7 @@ static int rgui_settings_toggle_setting(rgui_file_type_t setting, rgui_action_t rarch_input_set_keybind(port, keybind_action, rgui_controller_lut[setting - RGUI_SETTINGS_BIND_UP]); } +#endif default: break; } @@ -905,6 +939,7 @@ static void rgui_settings_populate_entries(rgui_handle_t *rgui) { rgui_list_clear(rgui->folder_buf); +#ifdef RARCH_CONSOLE RGUI_MENU_ITEM("Rewind", RGUI_SETTINGS_REWIND_ENABLE); RGUI_MENU_ITEM("Rewind granularity", RGUI_SETTINGS_REWIND_GRANULARITY); if (g_extern.main_is_init) @@ -941,10 +976,24 @@ static void rgui_settings_populate_entries(rgui_handle_t *rgui) RGUI_MENU_ITEM("Debug Text", RGUI_SETTINGS_DEBUG_TEXT); RGUI_MENU_ITEM("Restart RetroArch", RGUI_SETTINGS_RESTART_EMULATOR); RGUI_MENU_ITEM("Exit RetroArch", RGUI_SETTINGS_QUIT_EMULATOR); +#else + RGUI_MENU_ITEM("Save State", RGUI_SETTINGS_SAVESTATE_SAVE); + RGUI_MENU_ITEM("Load State", RGUI_SETTINGS_SAVESTATE_LOAD); + RGUI_MENU_ITEM("Take Screenshot", RGUI_SETTINGS_SCREENSHOT); + RGUI_MENU_ITEM("Restart Game", RGUI_SETTINGS_RESTART_GAME); + RGUI_MENU_ITEM("Hardware filtering", RGUI_SETTINGS_VIDEO_FILTER); + RGUI_MENU_ITEM("Aspect Ratio", RGUI_SETTINGS_VIDEO_ASPECT_RATIO); + RGUI_MENU_ITEM("Rotation", RGUI_SETTINGS_VIDEO_ROTATION); + RGUI_MENU_ITEM("Mute Audio", RGUI_SETTINGS_AUDIO_MUTE); + RGUI_MENU_ITEM("Audio Control Rate", RGUI_SETTINGS_AUDIO_CONTROL_RATE); + RGUI_MENU_ITEM("Audio Resampler", RGUI_SETTINGS_RESAMPLER_TYPE); + RGUI_MENU_ITEM("Exit RetroArch", RGUI_SETTINGS_QUIT_EMULATOR); +#endif } static void rgui_settings_controller_populate_entries(rgui_handle_t *rgui) { +#ifdef RARCH_CONSOLE rgui_list_clear(rgui->folder_buf); RGUI_MENU_ITEM("Device", RGUI_SETTINGS_BIND_DEVICE); @@ -965,10 +1014,10 @@ static void rgui_settings_controller_populate_entries(rgui_handle_t *rgui) RGUI_MENU_ITEM("R2", RGUI_SETTINGS_BIND_R2); RGUI_MENU_ITEM("L3", RGUI_SETTINGS_BIND_L3); RGUI_MENU_ITEM("R3", RGUI_SETTINGS_BIND_R3); +#endif } - -int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) +static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) { #ifdef GEKKO gx_video_t *gx = (gx_video_t*)driver.video_data; @@ -1088,12 +1137,13 @@ int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action) return 0; } -int rgui_settings_iterate(rgui_handle_t *rgui, rgui_action_t action) +static int rgui_settings_iterate(rgui_handle_t *rgui, rgui_action_t action) { rgui->frame_buf_pitch = RGUI_WIDTH * 2; rgui_file_type_t type = 0; const char *label = 0; - rgui_list_at(rgui->folder_buf, rgui->directory_ptr, &label, &type, NULL); + if (action != RGUI_ACTION_REFRESH) + rgui_list_at(rgui->folder_buf, rgui->directory_ptr, &label, &type, NULL); #ifdef HAVE_LIBRETRO_MANAGEMENT if (type == RGUI_SETTINGS_CORE) label = default_paths.core_dir; diff --git a/frontend/menu/rmenu_generic.c b/frontend/menu/rmenu_generic.c new file mode 100644 index 0000000000..747fb957a8 --- /dev/null +++ b/frontend/menu/rmenu_generic.c @@ -0,0 +1,257 @@ +/* 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 "../../gfx/gl_common.h" + +#include "../../gfx/fonts/bitmap.h" + +static uint16_t menu_framebuf[400 * 240]; +static rgui_handle_t *rgui; + +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; +} + +/*============================================================ +RMENU API +============================================================ */ + +void menu_init(void) +{ + gl_t *gl = (gl_t*)driver.video_data; + + gl->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 = ((g_extern.lifecycle_mode_state & (1ULL << RARCH_RMENU_TOGGLE)) && 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 const struct retro_keybind *binds[] = { + g_settings.input.binds[0] + }; + + static uint16_t old_input_state = 0; + static bool initial_held = true; + static bool first_held = false; + + 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 + + if (input_key_pressed_func(RARCH_QUIT_KEY) || !video_alive_func()) + { + g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); + goto deinit; + } + + g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU_DRAW); + + driver.video->apply_state_changes(); + + g_extern.frame_count++; + + uint16_t input_state = 0; + + for (unsigned i = 0; i < 16; i++) + { + input_state |= driver.input->input_state(NULL, binds, 0, RETRO_DEVICE_JOYPAD, 0, i) ? (1ULL << i) : 0; +#ifdef HAVE_OVERLAY + input_state |= driver.overlay_state & (1ULL << i) ? (1ULL << i) : 0; +#endif + } + + trigger_state = input_state & ~old_input_state; + bool do_held = input_state & ((1ULL << RETRO_DEVICE_ID_JOYPAD_UP) | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) | (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT)); + + 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 << RETRO_DEVICE_ID_JOYPAD_UP)) + action = RGUI_ACTION_UP; + else if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)) + action = RGUI_ACTION_DOWN; + else if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT)) + action = RGUI_ACTION_LEFT; + else if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT)) + action = RGUI_ACTION_RIGHT; + else if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_B)) + action = RGUI_ACTION_CANCEL; + else if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_A)) + action = RGUI_ACTION_OK; + else if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_START)) + action = RGUI_ACTION_START; + //else if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_SELECT)) + // action = RGUI_ACTION_SETTINGS; + + 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/gfx/gl.c b/gfx/gl.c index 4a7ff4d0f8..92865af2cb 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -49,6 +49,10 @@ #include "shader_common.h" +#ifdef HAVE_RMENU +#include "../console/rarch_console_video.h" +#endif + #ifdef __CELLOS_LV2__ #define FPS_COUNTER #endif @@ -57,6 +61,10 @@ #include "../frontend/frontend_android.h" #endif +#ifdef HAVE_RGUI +#include "../frontend/menu/rgui.h" +#endif + // Used for the last pass when rendering to the back buffer. const GLfloat vertexes_flipped[] = { 0, 1, @@ -668,14 +676,12 @@ void gl_init_fbo(void *data, unsigned width, unsigned height) void gl_set_projection(void *data, struct gl_ortho *ortho, bool allow_rotate) { gl_t *gl = (gl_t*)data; -#ifdef RARCH_CONSOLE if (g_extern.lifecycle_mode_state & (1ULL << MODE_VIDEO_OVERSCAN_ENABLE)) { ortho->left = -g_extern.console.screen.overscan_amount / 2; ortho->right = 1 + g_extern.console.screen.overscan_amount / 2; ortho->bottom = -g_extern.console.screen.overscan_amount / 2; } -#endif // Calculate projection. matrix_ortho(&gl->mvp_no_rot, ortho->left, ortho->right, @@ -715,7 +721,7 @@ void gl_set_viewport(void *data, unsigned width, unsigned height, bool force_ful float desired_aspect = g_settings.video.aspect_ratio; float delta; -#ifdef RARCH_CONSOLE +#ifdef HAVE_RGUI if (g_settings.video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM) { x = g_extern.console.screen.viewports.custom_vp.x; @@ -1076,6 +1082,15 @@ static void gl_init_textures(void *data, const video_info_t *video) glGenTextures(TEXTURES, gl->texture); +#ifdef HAVE_RGUI + glGenTextures(1, &gl->rgui_texture); + glBindTexture(GL_TEXTURE_2D, gl->rgui_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#endif + for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); @@ -1184,6 +1199,16 @@ static void gl_init_textures(void *data, const video_info_t *video) #endif glGenTextures(TEXTURES, gl->texture); + +#ifdef HAVE_RGUI + glGenTextures(1, &gl->rgui_texture); + glBindTexture(GL_TEXTURE_2D, gl->rgui_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#endif + for (unsigned i = 0; i < TEXTURES; i++) { glBindTexture(GL_TEXTURE_2D, gl->texture[i]); @@ -1243,6 +1268,31 @@ static void gl_pbo_async_readback(void *data) } #endif +#ifdef HAVE_RGUI +static inline void gl_draw_rgui(void *data) +{ + gl_t *gl = (gl_t*)data; + gl->coords.tex_coord = tex_coords; + + glBindTexture(GL_TEXTURE_2D, gl->rgui_texture); + + glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(RGUI_WIDTH * 2)); + // RGUI is always packed so pitch = width * bpp + glTexImage2D(GL_TEXTURE_2D, + 0, GL_RGBA, RGUI_WIDTH, RGUI_HEIGHT, 0, GL_RGBA, + GL_UNSIGNED_SHORT_4_4_4_4, gl->menu_data); + + gl_shader_use_func(gl, 0); + gl_shader_set_coords_func(gl, &gl->coords, &gl->mvp_no_rot); + + glEnable(GL_BLEND); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisable(GL_BLEND); + + gl->coords.tex_coord = gl->tex_coords; +} +#endif + static bool gl_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg) { RARCH_PERFORMANCE_INIT(frame_run); @@ -1316,6 +1366,11 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei gl_set_prev_texture(gl, &tex_info); +#ifdef HAVE_RGUI + if (lifecycle_mode_state & (1ULL << MODE_MENU_DRAW)) + gl_draw_rgui(gl); +#endif + #ifdef FPS_COUNTER if (lifecycle_mode_state & (1ULL << MODE_FPS_DRAW)) { @@ -1343,7 +1398,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei RARCH_PERFORMANCE_STOP(frame_run); -#ifdef HAVE_RMENU +#if defined(HAVE_RMENU) && !defined(HAVE_RGUI) if (lifecycle_mode_state & (1ULL << MODE_MENU_DRAW)) context_rmenu_frame_func(gl); else @@ -1391,6 +1446,10 @@ static void gl_free(void *data) glDeleteTextures(TEXTURES, gl->texture); +#ifdef HAVE_RGUI + glDeleteTextures(1, &gl->rgui_texture); +#endif + #ifdef HAVE_OVERLAY if (gl->tex_overlay) glDeleteTextures(1, &gl->tex_overlay); @@ -1513,6 +1572,10 @@ static inline void gl_reinit_textures(void *data, const video_info_t *video) glBindTexture(GL_TEXTURE_2D, 0); glDeleteTextures(TEXTURES, gl->texture); +#ifdef HAVE_RGUI + glDeleteTextures(1, &gl->rgui_texture); +#endif + gl_init_textures(gl, video); gl_init_textures_data(gl); @@ -2047,6 +2110,7 @@ static void gl_set_aspect_ratio(void *data, unsigned aspectratio_index) g_settings.video.aspect_ratio = aspectratio_lut[g_settings.video.aspect_ratio_idx].value; g_settings.video.force_aspect = false; gl->keep_aspect = true; + gl->should_resize = true; } #endif diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 2617f84d28..b7db8c3d59 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -301,6 +301,11 @@ typedef struct gl struct scaler_ctx pbo_readback_scaler; #endif +#ifdef HAVE_RGUI + GLuint rgui_texture; + uint32_t *menu_data; +#endif + } gl_t; // Windows ... <_< diff --git a/gfx/thread_wrapper.c b/gfx/thread_wrapper.c index 39d8397458..2f513eaa17 100644 --- a/gfx/thread_wrapper.c +++ b/gfx/thread_wrapper.c @@ -535,6 +535,17 @@ static void thread_get_overlay_interface(void *data, const video_overlay_interfa } #endif +#if defined(HAVE_RMENU) + +// all stubs for now, might not have to implement them unless we want to port this to consoles +static void thread_start(void) {} +static void thread_stop(void) {} +static void thread_restart(void) {} +static void thread_apply_state_changes(void) {} +static void thread_set_aspect_ratio(void *data, unsigned aspectratio_index) {} + +#endif + static const video_driver_t video_thread = { thread_init_never_call, // Should never be called directly. thread_frame, @@ -544,6 +555,13 @@ static const video_driver_t video_thread = { thread_set_shader, thread_free, "Thread wrapper", +#if defined(HAVE_RMENU) + thread_start, + thread_stop, + thread_restart, + thread_apply_state_changes, + thread_set_aspect_ratio, +#endif thread_set_rotation, thread_viewport_info, thread_read_viewport,