diff --git a/Makefile.common b/Makefile.common index 3d86328675..bd46db375e 100644 --- a/Makefile.common +++ b/Makefile.common @@ -160,7 +160,6 @@ OBJ += frontend/frontend.o \ command.o \ msg_hash.o \ intl/msg_hash_us.o \ - runloop.o \ $(LIBRETRO_COMM_DIR)/queues/task_queue.o \ tasks/task_content.o \ tasks/task_save.o \ diff --git a/audio/audio_driver.c b/audio/audio_driver.c index 1333d5352e..3750dc8f0b 100644 --- a/audio/audio_driver.c +++ b/audio/audio_driver.c @@ -41,7 +41,6 @@ #include "../driver.h" #include "../configuration.h" #include "../retroarch.h" -#include "../runloop.h" #include "../verbosity.h" #include "../list_special.h" diff --git a/camera/camera_driver.c b/camera/camera_driver.c index ce35c4797b..34a5a31d88 100644 --- a/camera/camera_driver.c +++ b/camera/camera_driver.c @@ -25,7 +25,6 @@ #include "../configuration.h" #include "../driver.h" #include "../retroarch.h" -#include "../runloop.h" #include "../list_special.h" #include "../verbosity.h" diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index 60379436a6..f3ff53455d 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -38,7 +38,7 @@ #include "../configuration.h" #include "../performance_counters.h" #include "../msg_hash.h" -#include "../runloop.h" +#include "../retroarch.h" #include "../core.h" #include "../network/net_http_special.h" diff --git a/command.c b/command.c index 83ceb28e04..bd5af8a8d9 100644 --- a/command.c +++ b/command.c @@ -87,7 +87,7 @@ #include "core.h" #include "verbosity.h" -#include "runloop.h" +#include "retroarch.h" #include "configuration.h" #include "input/input_remapping.h" diff --git a/configuration.c b/configuration.c index 00d816d859..b7b516ecc5 100644 --- a/configuration.c +++ b/configuration.c @@ -44,7 +44,6 @@ #include "dirs.h" #include "paths.h" #include "retroarch.h" -#include "runloop.h" #include "verbosity.h" #include "lakka.h" diff --git a/core_info.c b/core_info.c index 749ae7ec55..9376b797d5 100644 --- a/core_info.c +++ b/core_info.c @@ -27,7 +27,7 @@ #include "config.h" #endif -#include "runloop.h" +#include "retroarch.h" #include "verbosity.h" #include "config.def.h" diff --git a/dirs.c b/dirs.c index c830af1f20..d41cc5bc6a 100644 --- a/dirs.c +++ b/dirs.c @@ -32,7 +32,7 @@ #include "msg_hash.h" #include "paths.h" #include "content.h" -#include "runloop.h" +#include "retroarch.h" #include "verbosity.h" struct rarch_dir_list diff --git a/driver.c b/driver.c index 9ab8c2fe9a..494d18302f 100644 --- a/driver.c +++ b/driver.c @@ -40,7 +40,7 @@ #include "core.h" #include "core_info.h" #include "driver.h" -#include "runloop.h" +#include "retroarch.h" #include "verbosity.h" #define HASH_LOCATION_DRIVER 0x09189689U diff --git a/dynamic.c b/dynamic.c index 7928715481..c0be244829 100644 --- a/dynamic.c +++ b/dynamic.c @@ -58,7 +58,6 @@ #include "dirs.h" #include "paths.h" #include "retroarch.h" -#include "runloop.h" #include "configuration.h" #include "msg_hash.h" #include "verbosity.h" diff --git a/frontend/drivers/platform_darwin.m b/frontend/drivers/platform_darwin.m index 36e0f0449f..a0787d967c 100644 --- a/frontend/drivers/platform_darwin.m +++ b/frontend/drivers/platform_darwin.m @@ -60,7 +60,7 @@ #include "../../file_path_special.h" #include "../../configuration.h" #include "../../defaults.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../verbosity.h" #include "../../ui/ui_companion_driver.h" diff --git a/frontend/drivers/platform_emscripten.c b/frontend/drivers/platform_emscripten.c index e1f6b66955..481e0dc849 100644 --- a/frontend/drivers/platform_emscripten.c +++ b/frontend/drivers/platform_emscripten.c @@ -37,7 +37,6 @@ #include "../../defaults.h" #include "../../content.h" #include "../../retroarch.h" -#include "../../runloop.h" #include "../../command.h" #include "../../tasks/tasks_internal.h" #include "../../file_path_special.h" diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c index 955a7f82d1..822c437d1d 100644 --- a/frontend/drivers/platform_wiiu.c +++ b/frontend/drivers/platform_wiiu.c @@ -37,7 +37,7 @@ #include "tasks/tasks_internal.h" -#include "runloop.h" +#include "../../retroarch.h" #include #include "fs/fs_utils.h" #include "fs/sd_fat_devoptab.h" diff --git a/frontend/drivers/platform_win32.c b/frontend/drivers/platform_win32.c index d62df7c9c4..f294186ceb 100644 --- a/frontend/drivers/platform_win32.c +++ b/frontend/drivers/platform_win32.c @@ -37,7 +37,7 @@ #include "../frontend_driver.h" #include "../../configuration.h" #include "../../defaults.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../verbosity.h" /* We only load this library once, so we let it be diff --git a/frontend/frontend.c b/frontend/frontend.c index 82d7ba1f9f..13eacec33e 100644 --- a/frontend/frontend.c +++ b/frontend/frontend.c @@ -36,7 +36,7 @@ #include "../retroarch.h" #ifndef HAVE_MAIN -#include "../runloop.h" +#include "../retroarch.h" #endif /** diff --git a/gfx/common/win32_common.cpp b/gfx/common/win32_common.cpp index 05cbd428d0..d900882a53 100644 --- a/gfx/common/win32_common.cpp +++ b/gfx/common/win32_common.cpp @@ -26,7 +26,7 @@ #include "../../verbosity.h" #include "../../driver.h" #include "../../paths.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../tasks/tasks_internal.h" #include "../../core_info.h" diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 7e2f630079..96ee681a97 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -52,7 +52,6 @@ #include "../configuration.h" #include "../driver.h" #include "../retroarch.h" -#include "../runloop.h" #include "../input/input_driver.h" #include "../list_special.h" #include "../core.h" diff --git a/gfx/video_thread_wrapper.c b/gfx/video_thread_wrapper.c index f573e397aa..c3995aaed4 100644 --- a/gfx/video_thread_wrapper.c +++ b/gfx/video_thread_wrapper.c @@ -26,7 +26,7 @@ #include "font_driver.h" #include "video_shader_driver.h" -#include "../runloop.h" +#include "../retroarch.h" #include "../verbosity.h" enum thread_cmd diff --git a/griffin/griffin.c b/griffin/griffin.c index b1a513415d..b53d7783cb 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -832,7 +832,6 @@ RETROARCH #include "../retroarch.c" #include "../dirs.c" #include "../paths.c" -#include "../runloop.c" #include "../libretro-common/queues/task_queue.c" #include "../msg_hash.c" diff --git a/input/drivers_keyboard/keyboard_event_apple.c b/input/drivers_keyboard/keyboard_event_apple.c index 507d8640b9..4373204562 100644 --- a/input/drivers_keyboard/keyboard_event_apple.c +++ b/input/drivers_keyboard/keyboard_event_apple.c @@ -25,8 +25,8 @@ #include "../input_keymaps.h" #include "../input_keyboard.h" -#include "../../runloop.h" #include "../../driver.h" +#include "../../retroarch.h" #include "keyboard_event_apple.h" diff --git a/input/drivers_keyboard/keyboard_event_win32.cpp b/input/drivers_keyboard/keyboard_event_win32.cpp index 936607cba9..e81d365838 100644 --- a/input/drivers_keyboard/keyboard_event_win32.cpp +++ b/input/drivers_keyboard/keyboard_event_win32.cpp @@ -21,7 +21,7 @@ #include "../input_config.h" #include "../input_keymaps.h" #include "../input_keyboard.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../gfx/common/win32_common.h" LRESULT win32_handle_keyboard_event(HWND hwnd, UINT message, diff --git a/input/input_keyboard.c b/input/input_keyboard.c index ddf97e9a73..1a85e21f3f 100644 --- a/input/input_keyboard.c +++ b/input/input_keyboard.c @@ -19,13 +19,13 @@ #include #include +#include + #include "input_keyboard.h" #include "input_driver.h" -#include - -#include "../runloop.h" +#include "../retroarch.h" struct input_keyboard_line { diff --git a/input/input_remapping.c b/input/input_remapping.c index 5dfccaa040..17aae07ab3 100644 --- a/input/input_remapping.c +++ b/input/input_remapping.c @@ -22,7 +22,6 @@ #include "input_remapping.h" #include "../configuration.h" #include "../retroarch.h" -#include "../runloop.h" /** * input_remapping_load_file: diff --git a/location/location_driver.c b/location/location_driver.c index d1dd32d782..193f36c90b 100644 --- a/location/location_driver.c +++ b/location/location_driver.c @@ -26,7 +26,6 @@ #include "../core.h" #include "../driver.h" #include "../retroarch.h" -#include "../runloop.h" #include "../list_special.h" #include "../verbosity.h" diff --git a/managers/cheat_manager.c b/managers/cheat_manager.c index 10d4974d51..b0e824f3b1 100644 --- a/managers/cheat_manager.c +++ b/managers/cheat_manager.c @@ -36,7 +36,7 @@ #include "cheat_manager.h" #include "../msg_hash.h" -#include "../runloop.h" +#include "../retroarch.h" #include "../dynamic.h" #include "../core.h" #include "../verbosity.h" diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index bc159d93f0..0ff2f66845 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -33,7 +33,7 @@ #include "../../configuration.h" #include "../../core.h" #include "../../core_info.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../verbosity.h" #ifndef BIND_ACTION_DEFERRED_PUSH diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c index 2b5e775f24..778339bdf9 100644 --- a/menu/cbs/menu_cbs_get_value.c +++ b/menu/cbs/menu_cbs_get_value.c @@ -39,7 +39,7 @@ #include "../../managers/cheat_manager.h" #include "../../performance_counters.h" #include "../../paths.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../wifi/wifi_driver.h" #ifndef BIND_ACTION_GET_VALUE diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index 3f7210ad67..112977a96e 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -38,7 +38,6 @@ #include "../../managers/cheat_manager.h" #include "../../file_path_special.h" #include "../../retroarch.h" -#include "../../runloop.h" #ifndef BIND_ACTION_LEFT #define BIND_ACTION_LEFT(cbs, name) \ diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 036c31efa6..66e0e0118e 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -48,7 +48,6 @@ #include "../../input/input_remapping.h" #include "../../paths.h" #include "../../retroarch.h" -#include "../../runloop.h" #include "../../verbosity.h" #include "../../lakka.h" #include "../../wifi/wifi_driver.h" diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index 1f2b05a302..c8bdfacd4c 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -38,7 +38,6 @@ #include "../../managers/cheat_manager.h" #include "../../file_path_special.h" #include "../../retroarch.h" -#include "../../runloop.h" #include "../../ui/ui_companion_driver.h" #ifndef BIND_ACTION_RIGHT diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 0c07b0656d..6deacaa7fa 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -34,7 +34,6 @@ #include "../../managers/core_option_manager.h" #include "../../managers/cheat_manager.h" #include "../../retroarch.h" -#include "../../runloop.h" #include "../../performance_counters.h" #include "../../gfx/video_shader_driver.h" diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index 02b68e5580..c0374cc2af 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -54,7 +54,6 @@ #include "../../core.h" #include "../../configuration.h" #include "../../retroarch.h" -#include "../../runloop.h" #include "../../verbosity.h" #include "../../tasks/tasks_internal.h" diff --git a/menu/drivers/nuklear.c b/menu/drivers/nuklear.c index 8d0dcc773b..7a0e119be4 100644 --- a/menu/drivers/nuklear.c +++ b/menu/drivers/nuklear.c @@ -44,7 +44,7 @@ #include "../../core_info.h" #include "../../configuration.h" #include "../../frontend/frontend_driver.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../verbosity.h" #include "../../tasks/tasks_internal.h" diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index eea6d6d7eb..c4b759b41c 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -46,7 +46,7 @@ #include "../widgets/menu_input_dialog.h" #include "../../configuration.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../gfx/drivers_font_renderer/bitmap.h" #define RGUI_TERM_START_X(width) (width / 21) diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 09b72eab23..91f1131c25 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -57,7 +57,7 @@ #include "../../configuration.h" #include "../../retroarch.h" #include "../../playlist.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../tasks/tasks_internal.h" diff --git a/menu/drivers/xui.cpp b/menu/drivers/xui.cpp index 03fe13f12e..a9f3f89fb1 100644 --- a/menu/drivers/xui.cpp +++ b/menu/drivers/xui.cpp @@ -43,7 +43,7 @@ #include "../../gfx/video_driver.h" #include "../../configuration.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../gfx/drivers/d3d.h" diff --git a/menu/drivers/zarch.c b/menu/drivers/zarch.c index 497adb73ac..8b7ce607c7 100644 --- a/menu/drivers/zarch.c +++ b/menu/drivers/zarch.c @@ -50,7 +50,7 @@ #include "../../core_info.h" #include "../../configuration.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../verbosity.h" #include "../../tasks/tasks_internal.h" diff --git a/menu/menu_display.c b/menu/menu_display.c index 05576bb547..a2913fa5fc 100644 --- a/menu/menu_display.c +++ b/menu/menu_display.c @@ -35,7 +35,6 @@ #include "../config.def.h" #include "../retroarch.h" #include "../configuration.h" -#include "../runloop.h" #include "../core.h" #include "../gfx/video_driver.h" #include "../gfx/video_thread_wrapper.h" diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index f005dc708b..dda0f6a537 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -65,7 +65,6 @@ #include "../managers/core_option_manager.h" #include "../paths.h" #include "../retroarch.h" -#include "../runloop.h" #include "../core.h" #include "../frontend/frontend_driver.h" #include "../ui/ui_companion_driver.h" diff --git a/menu/menu_driver.c b/menu/menu_driver.c index 6060df062f..9b19644a09 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -45,7 +45,6 @@ #include "../list_special.h" #include "../tasks/tasks_internal.h" #include "../ui/ui_companion_driver.h" -#include "../runloop.h" #include "../verbosity.h" static const menu_ctx_driver_t *menu_ctx_drivers[] = { diff --git a/menu/menu_entries.c b/menu/menu_entries.c index 413e7f745f..1bb745120c 100644 --- a/menu/menu_entries.c +++ b/menu/menu_entries.c @@ -27,7 +27,7 @@ #include "widgets/menu_list.h" #include "../core.h" -#include "../runloop.h" +#include "../retroarch.h" #include "../version.h" void menu_entries_get_at_offset(const file_list_t *list, size_t idx, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 66afd2652c..37594d6f0e 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -67,7 +67,6 @@ #include "../paths.h" #include "../dynamic.h" #include "../list_special.h" -#include "../runloop.h" #include "../verbosity.h" #include "../camera/camera_driver.h" #include "../wifi/wifi_driver.h" diff --git a/movie.c b/movie.c index db91d37f06..4034ee3712 100644 --- a/movie.c +++ b/movie.c @@ -27,7 +27,6 @@ #include "core.h" #include "content.h" #include "retroarch.h" -#include "runloop.h" #include "msg_hash.h" #include "verbosity.h" diff --git a/network/httpserver/httpserver.c b/network/httpserver/httpserver.c index 77b7c79a16..7844230b99 100644 --- a/network/httpserver/httpserver.c +++ b/network/httpserver/httpserver.c @@ -25,7 +25,7 @@ #include #include "../../core.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../core.h" #include "../../gfx/video_driver.h" #include "../../managers/core_option_manager.h" diff --git a/network/netplay/netplay_discovery.c b/network/netplay/netplay_discovery.c index 36d720fde4..8d45a86a3e 100644 --- a/network/netplay/netplay_discovery.c +++ b/network/netplay/netplay_discovery.c @@ -43,7 +43,7 @@ #include #include -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../version.h" #include "netplay.h" #include "netplay_discovery.h" diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 2c471f063b..56543d3a91 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -24,17 +24,17 @@ #include #include +#include + #include "netplay_private.h" #include "../../configuration.h" #include "../../input/input_driver.h" -#include "../../runloop.h" - #include "../../tasks/tasks_internal.h" -#include #include "../../file_path_special.h" #include "../../paths.h" #include "../../command.h" +#include "../../retroarch.h" /* Only used before init_netplay */ static bool netplay_enabled = false; diff --git a/network/netplay/netplay_handshake.c b/network/netplay/netplay_handshake.c index 95464ae402..7ff75230ab 100644 --- a/network/netplay/netplay_handshake.c +++ b/network/netplay/netplay_handshake.c @@ -33,7 +33,6 @@ #include "../../configuration.h" #include "../../content.h" #include "../../retroarch.h" -#include "../../runloop.h" #include "../../version.h" #include "../../input/input_config.h" diff --git a/network/netplay/netplay_init.c b/network/netplay/netplay_init.c index cf02a2d001..6325918f7e 100644 --- a/network/netplay/netplay_init.c +++ b/network/netplay/netplay_init.c @@ -31,7 +31,7 @@ #include "netplay_discovery.h" #include "../../autosave.h" -#include "../../runloop.h" +#include "../../retroarch.h" #if defined(AF_INET6) && !defined(HAVE_SOCKET_LEGACY) #define HAVE_INET6 1 diff --git a/network/netplay/netplay_io.c b/network/netplay/netplay_io.c index f1106dad1d..fdba8ebf74 100644 --- a/network/netplay/netplay_io.c +++ b/network/netplay/netplay_io.c @@ -25,7 +25,7 @@ #include "netplay_private.h" #include "../../configuration.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../tasks/tasks_internal.h" #if 0 diff --git a/paths.c b/paths.c index 3752c9193b..fd36464cc4 100644 --- a/paths.c +++ b/paths.c @@ -42,7 +42,6 @@ #include "core.h" #include "msg_hash.h" #include "retroarch.h" -#include "runloop.h" #include "verbosity.h" #include "tasks/tasks_internal.h" diff --git a/performance_counters.c b/performance_counters.c index e1661ffcc6..0b275fc2e7 100644 --- a/performance_counters.c +++ b/performance_counters.c @@ -27,7 +27,7 @@ #include "performance_counters.h" -#include "runloop.h" +#include "retroarch.h" #include "verbosity.h" #ifdef _WIN32 diff --git a/record/record_driver.c b/record/record_driver.c index 5adb9842db..467d24e9d5 100644 --- a/record/record_driver.c +++ b/record/record_driver.c @@ -31,7 +31,6 @@ #include "../driver.h" #include "../gfx/video_driver.h" #include "../retroarch.h" -#include "../runloop.h" #include "../verbosity.h" #include "../msg_hash.h" #include "../list_special.h" diff --git a/retroarch.c b/retroarch.c index 259827db50..045fc7fc93 100644 --- a/retroarch.c +++ b/retroarch.c @@ -25,11 +25,13 @@ #endif #include +#include #include #include #include #include #include +#include #include #include @@ -42,6 +44,8 @@ #include #include #include +#include +#include #include #include @@ -55,33 +59,55 @@ #ifdef HAVE_MENU #include "menu/menu_driver.h" +#include "menu/menu_display.h" +#include "menu/menu_event.h" +#include "menu/widgets/menu_dialog.h" +#endif + +#ifdef HAVE_CHEEVOS +#include "cheevos/cheevos.h" #endif #ifdef HAVE_NETWORKING #include "network/netplay/netplay.h" #endif +#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) +#include "network/httpserver/httpserver.h" +#endif + +#ifdef HAVE_THREADS +#include +#endif + +#include "autosave.h" #include "config.features.h" #include "content.h" #include "core_type.h" #include "core_info.h" #include "dynamic.h" #include "driver.h" +#include "input/input_driver.h" #include "input/input_config.h" +#include "input/input_keyboard.h" #include "msg_hash.h" #include "movie.h" #include "dirs.h" #include "paths.h" #include "file_path_special.h" +#include "ui/ui_companion_driver.h" #include "verbosity.h" #include "frontend/frontend_driver.h" #include "audio/audio_driver.h" +#include "camera/camera_driver.h" #include "record/record_driver.h" #include "core.h" #include "configuration.h" -#include "runloop.h" +#include "list_special.h" +#include "managers/core_option_manager.h" #include "managers/cheat_manager.h" +#include "managers/state_manager.h" #include "tasks/tasks_internal.h" #include "version.h" @@ -98,6 +124,15 @@ retroarch_fail(1, "validate_cpu_features()"); \ } while(0) +#ifdef HAVE_ZLIB +#define DEFAULT_EXT "zip" +#else +#define DEFAULT_EXT "" +#endif + +#define runloop_cmd_triggered(trigger_input, id) (BIT64_GET(trigger_input, id)) +#define runloop_cmd_pressed(old_input, id) (BIT64_GET(old_input, id)) + /* Descriptive names for options without short variant. * * Please keep the name in sync with the option name. @@ -125,6 +160,24 @@ enum RA_OPT_MAX_FRAMES }; +enum runloop_state +{ + RUNLOOP_STATE_NONE = 0, + RUNLOOP_STATE_ITERATE, + RUNLOOP_STATE_SLEEP, + RUNLOOP_STATE_MENU_ITERATE, + RUNLOOP_STATE_END, + RUNLOOP_STATE_QUIT +}; + +typedef struct runloop_ctx_msg_info +{ + const char *msg; + unsigned prio; + unsigned duration; + bool flush; +} runloop_ctx_msg_info_t; + static jmp_buf error_sjlj_context; static enum rarch_core_type current_core_type = CORE_TYPE_PLAIN; static enum rarch_core_type explicit_current_core_type = CORE_TYPE_PLAIN; @@ -151,6 +204,33 @@ static bool has_set_ups_pref = false; static bool has_set_bps_pref = false; static bool has_set_ips_pref = false; +static rarch_system_info_t runloop_system; +static struct retro_frame_time_callback runloop_frame_time; +static retro_keyboard_event_t runloop_key_event = NULL; +static retro_keyboard_event_t runloop_frontend_key_event = NULL; +static core_option_manager_t *runloop_core_options = NULL; +#ifdef HAVE_THREADS +static slock_t *_runloop_msg_queue_lock = NULL; +#endif +static msg_queue_t *runloop_msg_queue = NULL; +static unsigned runloop_pending_windowed_scale = 0; +static retro_usec_t runloop_frame_time_last = 0; +static unsigned runloop_max_frames = false; +static bool runloop_force_nonblock = false; +static bool runloop_paused = false; +static bool runloop_idle = false; +static bool runloop_exec = false; +static bool runloop_slowmotion = false; +static bool runloop_shutdown_initiated = false; +static bool runloop_core_shutdown_initiated = false; +static bool runloop_perfcnt_enable = false; +static bool runloop_overrides_active = false; +static bool runloop_game_options_active = false; +static bool runloop_missing_bios = false; +static bool runloop_autosave = false; +static retro_time_t frame_limit_minimum_time = 0.0; +static retro_time_t frame_limit_last_time = 0.0; + static void retroarch_print_features(void) { puts(""); @@ -1683,3 +1763,1098 @@ bool retroarch_main_quit(void) return true; } + +global_t *global_get_ptr(void) +{ + static struct global g_extern; + return &g_extern; +} + +void runloop_msg_queue_push(const char *msg, + unsigned prio, unsigned duration, + bool flush) +{ + runloop_ctx_msg_info_t msg_info; + +#ifdef HAVE_THREADS + slock_lock(_runloop_msg_queue_lock); +#endif + + if (flush) + msg_queue_clear(runloop_msg_queue); + + msg_info.msg = msg; + msg_info.prio = prio; + msg_info.duration = duration; + msg_info.flush = flush; + + if (runloop_msg_queue) + { + msg_queue_push(runloop_msg_queue, msg_info.msg, + msg_info.prio, msg_info.duration); + + if (ui_companion_is_on_foreground()) + { + const ui_companion_driver_t *ui = ui_companion_get_ptr(); + if (ui->msg_queue_push) + ui->msg_queue_push(msg_info.msg, + msg_info.prio, msg_info.duration, msg_info.flush); + } + } + +#ifdef HAVE_THREADS + slock_unlock(_runloop_msg_queue_lock); +#endif +} + +/** + * rarch_game_specific_options: + * + * Returns: true (1) if a game specific core + * options path has been found, + * otherwise false (0). + **/ +static bool rarch_game_specific_options(char **output) +{ + char game_path[8192]; + + game_path[0] ='\0'; + + if (!retroarch_validate_game_options(game_path, + sizeof(game_path), false)) + return false; + + if (!config_file_exists(game_path)) + return false; + + RARCH_LOG("%s %s\n", + msg_hash_to_str(MSG_GAME_SPECIFIC_CORE_OPTIONS_FOUND_AT), + game_path); + *output = strdup(game_path); + return true; +} + +void runloop_get_status(bool *is_paused, bool *is_idle, + bool *is_slowmotion, bool *is_perfcnt_enable) +{ + *is_paused = runloop_paused; + *is_idle = runloop_idle; + *is_slowmotion = runloop_slowmotion; + *is_perfcnt_enable = runloop_perfcnt_enable; +} + +bool runloop_msg_queue_pull(const char **ret) +{ + if (!ret) + return false; +#ifdef HAVE_THREADS + slock_lock(_runloop_msg_queue_lock); +#endif + *ret = msg_queue_pull(runloop_msg_queue); +#ifdef HAVE_THREADS + slock_unlock(_runloop_msg_queue_lock); +#endif + return true; +} + +bool runloop_ctl(enum runloop_ctl_state state, void *data) +{ + + switch (state) + { + case RUNLOOP_CTL_SYSTEM_INFO_INIT: + core_get_system_info(&runloop_system.info); + + if (!runloop_system.info.library_name) + runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN); + if (!runloop_system.info.library_version) + runloop_system.info.library_version = "v0"; + + video_driver_set_title_buf(); + + strlcpy(runloop_system.valid_extensions, + runloop_system.info.valid_extensions ? + runloop_system.info.valid_extensions : DEFAULT_EXT, + sizeof(runloop_system.valid_extensions)); + break; + case RUNLOOP_CTL_GET_CORE_OPTION_SIZE: + { + unsigned *idx = (unsigned*)data; + if (!idx) + return false; + *idx = (unsigned)core_option_manager_size(runloop_core_options); + } + break; + case RUNLOOP_CTL_HAS_CORE_OPTIONS: + return runloop_core_options; + case RUNLOOP_CTL_CORE_OPTIONS_LIST_GET: + { + core_option_manager_t **coreopts = (core_option_manager_t**)data; + if (!coreopts) + return false; + *coreopts = runloop_core_options; + } + break; + case RUNLOOP_CTL_SYSTEM_INFO_FREE: + + /* No longer valid. */ + if (runloop_system.subsystem.data) + free(runloop_system.subsystem.data); + runloop_system.subsystem.data = NULL; + runloop_system.subsystem.size = 0; + + if (runloop_system.ports.data) + free(runloop_system.ports.data); + runloop_system.ports.data = NULL; + runloop_system.ports.size = 0; + + if (runloop_system.mmaps.descriptors) + free((void *)runloop_system.mmaps.descriptors); + runloop_system.mmaps.descriptors = NULL; + runloop_system.mmaps.num_descriptors = 0; + + runloop_key_event = NULL; + runloop_frontend_key_event = NULL; + + audio_driver_unset_callback(); + memset(&runloop_system, 0, sizeof(rarch_system_info_t)); + break; + case RUNLOOP_CTL_SET_FRAME_TIME_LAST: + runloop_frame_time_last = 0; + break; + case RUNLOOP_CTL_SET_OVERRIDES_ACTIVE: + runloop_overrides_active = true; + break; + case RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE: + runloop_overrides_active = false; + break; + case RUNLOOP_CTL_IS_OVERRIDES_ACTIVE: + return runloop_overrides_active; + case RUNLOOP_CTL_SET_MISSING_BIOS: + runloop_missing_bios = true; + break; + case RUNLOOP_CTL_UNSET_MISSING_BIOS: + runloop_missing_bios = false; + break; + case RUNLOOP_CTL_IS_MISSING_BIOS: + return runloop_missing_bios; + case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE: + return runloop_game_options_active; + case RUNLOOP_CTL_SET_FRAME_LIMIT: + { + settings_t *settings = config_get_ptr(); + struct retro_system_av_info *av_info = + video_viewport_get_system_av_info(); + float fastforward_ratio = + (settings->floats.fastforward_ratio == 0.0f) + ? 1.0f : settings->floats.fastforward_ratio; + + frame_limit_last_time = cpu_features_get_time_usec(); + frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f + / (av_info->timing.fps * fastforward_ratio)); + } + break; + case RUNLOOP_CTL_GET_PERFCNT: + { + bool **perfcnt = (bool**)data; + if (!perfcnt) + return false; + *perfcnt = &runloop_perfcnt_enable; + } + break; + case RUNLOOP_CTL_SET_PERFCNT_ENABLE: + runloop_perfcnt_enable = true; + break; + case RUNLOOP_CTL_UNSET_PERFCNT_ENABLE: + runloop_perfcnt_enable = false; + break; + case RUNLOOP_CTL_IS_PERFCNT_ENABLE: + return runloop_perfcnt_enable; + case RUNLOOP_CTL_SET_NONBLOCK_FORCED: + runloop_force_nonblock = true; + break; + case RUNLOOP_CTL_UNSET_NONBLOCK_FORCED: + runloop_force_nonblock = false; + break; + case RUNLOOP_CTL_IS_NONBLOCK_FORCED: + return runloop_force_nonblock; + case RUNLOOP_CTL_SET_FRAME_TIME: + { + const struct retro_frame_time_callback *info = + (const struct retro_frame_time_callback*)data; +#ifdef HAVE_NETWORKING + /* retro_run() will be called in very strange and + * mysterious ways, have to disable it. */ + if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL)) + return false; +#endif + runloop_frame_time = *info; + } + break; + case RUNLOOP_CTL_GET_WINDOWED_SCALE: + { + unsigned **scale = (unsigned**)data; + if (!scale) + return false; + *scale = (unsigned*)&runloop_pending_windowed_scale; + } + break; + case RUNLOOP_CTL_SET_WINDOWED_SCALE: + { + unsigned *idx = (unsigned*)data; + if (!idx) + return false; + runloop_pending_windowed_scale = *idx; + } + break; + case RUNLOOP_CTL_SET_LIBRETRO_PATH: + return path_set(RARCH_PATH_CORE, (const char*)data); + case RUNLOOP_CTL_FRAME_TIME_FREE: + memset(&runloop_frame_time, 0, + sizeof(struct retro_frame_time_callback)); + runloop_frame_time_last = 0; + runloop_max_frames = 0; + break; + case RUNLOOP_CTL_STATE_FREE: + runloop_perfcnt_enable = false; + runloop_idle = false; + runloop_paused = false; + runloop_slowmotion = false; + runloop_overrides_active = false; + runloop_autosave = false; + runloop_ctl(RUNLOOP_CTL_FRAME_TIME_FREE, NULL); + break; + case RUNLOOP_CTL_GLOBAL_FREE: + { + global_t *global = NULL; + command_event(CMD_EVENT_TEMPORARY_CONTENT_DEINIT, NULL); + + path_deinit_subsystem(); + command_event(CMD_EVENT_RECORD_DEINIT, NULL); + command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL); + + rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL); + rarch_ctl(RARCH_CTL_UNSET_SRAM_LOAD_DISABLED, NULL); + rarch_ctl(RARCH_CTL_UNSET_SRAM_SAVE_DISABLED, NULL); + rarch_ctl(RARCH_CTL_UNSET_SRAM_ENABLE, NULL); + rarch_ctl(RARCH_CTL_UNSET_BPS_PREF, NULL); + rarch_ctl(RARCH_CTL_UNSET_IPS_PREF, NULL); + rarch_ctl(RARCH_CTL_UNSET_UPS_PREF, NULL); + rarch_ctl(RARCH_CTL_UNSET_PATCH_BLOCKED, NULL); + runloop_overrides_active = false; + + core_unset_input_descriptors(); + + global = global_get_ptr(); + path_clear_all(); + dir_clear_all(); + memset(global, 0, sizeof(struct global)); + retroarch_override_setting_free_state(); + } + break; + case RUNLOOP_CTL_CLEAR_STATE: + driver_ctl(RARCH_DRIVER_CTL_DEINIT, NULL); + runloop_ctl(RUNLOOP_CTL_STATE_FREE, NULL); + runloop_ctl(RUNLOOP_CTL_GLOBAL_FREE, NULL); + break; + case RUNLOOP_CTL_SET_MAX_FRAMES: + { + unsigned *ptr = (unsigned*)data; + if (!ptr) + return false; + runloop_max_frames = *ptr; + } + break; + case RUNLOOP_CTL_IS_IDLE: + return runloop_idle; + case RUNLOOP_CTL_SET_IDLE: + { + bool *ptr = (bool*)data; + if (!ptr) + return false; + runloop_idle = *ptr; + } + break; + case RUNLOOP_CTL_SET_PAUSED: + { + bool *ptr = (bool*)data; + if (!ptr) + return false; + runloop_paused = *ptr; + } + break; + case RUNLOOP_CTL_IS_PAUSED: + return runloop_paused; + case RUNLOOP_CTL_MSG_QUEUE_DEINIT: + if (!runloop_msg_queue) + return true; + +#ifdef HAVE_THREADS + slock_lock(_runloop_msg_queue_lock); +#endif + + msg_queue_free(runloop_msg_queue); + +#ifdef HAVE_THREADS + slock_unlock(_runloop_msg_queue_lock); +#endif + +#ifdef HAVE_THREADS + slock_free(_runloop_msg_queue_lock); + _runloop_msg_queue_lock = NULL; +#endif + + runloop_msg_queue = NULL; + break; + case RUNLOOP_CTL_MSG_QUEUE_INIT: + runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL); + runloop_msg_queue = msg_queue_new(8); + retro_assert(runloop_msg_queue); + +#ifdef HAVE_THREADS + _runloop_msg_queue_lock = slock_new(); + retro_assert(_runloop_msg_queue_lock); +#endif + break; + case RUNLOOP_CTL_TASK_INIT: + { +#ifdef HAVE_THREADS + settings_t *settings = config_get_ptr(); + bool threaded_enable = settings->bools.threaded_data_runloop_enable; +#else + bool threaded_enable = false; +#endif + task_queue_deinit(); + task_queue_init(threaded_enable, runloop_msg_queue_push); + } + break; + case RUNLOOP_CTL_SET_CORE_SHUTDOWN: + runloop_core_shutdown_initiated = true; + break; + case RUNLOOP_CTL_SET_SHUTDOWN: + runloop_shutdown_initiated = true; + break; + case RUNLOOP_CTL_IS_SHUTDOWN: + return runloop_shutdown_initiated; + case RUNLOOP_CTL_DATA_DEINIT: + task_queue_deinit(); + break; + case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED: + if (!runloop_core_options) + return false; + return core_option_manager_updated(runloop_core_options); + case RUNLOOP_CTL_CORE_OPTION_PREV: + { + unsigned *idx = (unsigned*)data; + if (!idx) + return false; + core_option_manager_prev(runloop_core_options, *idx); + if (ui_companion_is_on_foreground()) + ui_companion_driver_notify_refresh(); + } + break; + case RUNLOOP_CTL_CORE_OPTION_NEXT: + { + unsigned *idx = (unsigned*)data; + if (!idx) + return false; + core_option_manager_next(runloop_core_options, *idx); + if (ui_companion_is_on_foreground()) + ui_companion_driver_notify_refresh(); + } + break; + case RUNLOOP_CTL_CORE_OPTIONS_GET: + { + struct retro_variable *var = (struct retro_variable*)data; + + if (!runloop_core_options || !var) + return false; + + RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key); + core_option_manager_get(runloop_core_options, var); + RARCH_LOG("\t%s\n", var->value ? var->value : + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE)); + } + break; + case RUNLOOP_CTL_CORE_OPTIONS_INIT: + { + settings_t *settings = config_get_ptr(); + char *game_options_path = NULL; + bool ret = false; + const struct retro_variable *vars = + (const struct retro_variable*)data; + + if (settings && settings->bools.game_specific_options) + ret = rarch_game_specific_options(&game_options_path); + + if(ret) + { + runloop_game_options_active = true; + runloop_core_options = + core_option_manager_new(game_options_path, vars); + free(game_options_path); + } + else + { + char buf[PATH_MAX_LENGTH]; + const char *options_path = NULL; + + buf[0] = '\0'; + + if (settings) + options_path = settings->paths.path_core_options; + + if (string_is_empty(options_path) && !path_is_empty(RARCH_PATH_CONFIG)) + { + fill_pathname_resolve_relative(buf, path_get(RARCH_PATH_CONFIG), + file_path_str(FILE_PATH_CORE_OPTIONS_CONFIG), sizeof(buf)); + options_path = buf; + } + + runloop_game_options_active = false; + + if (!string_is_empty(options_path)) + runloop_core_options = + core_option_manager_new(options_path, vars); + } + + } + break; + case RUNLOOP_CTL_CORE_OPTIONS_FREE: + if (runloop_core_options) + core_option_manager_free(runloop_core_options); + runloop_core_options = NULL; + break; + case RUNLOOP_CTL_CORE_OPTIONS_DEINIT: + { + if (!runloop_core_options) + return false; + + /* check if game options file was just created and flush + to that file instead */ + if(!path_is_empty(RARCH_PATH_CORE_OPTIONS)) + { + core_option_manager_flush_game_specific(runloop_core_options, + path_get(RARCH_PATH_CORE_OPTIONS)); + path_clear(RARCH_PATH_CORE_OPTIONS); + } + else + core_option_manager_flush(runloop_core_options); + + if (runloop_game_options_active) + runloop_game_options_active = false; + + runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_FREE, NULL); + } + break; + case RUNLOOP_CTL_KEY_EVENT_GET: + { + retro_keyboard_event_t **key_event = + (retro_keyboard_event_t**)data; + if (!key_event) + return false; + *key_event = &runloop_key_event; + } + break; + case RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET: + { + retro_keyboard_event_t **key_event = + (retro_keyboard_event_t**)data; + if (!key_event) + return false; + *key_event = &runloop_frontend_key_event; + } + break; + case RUNLOOP_CTL_HTTPSERVER_INIT: +#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) + httpserver_init(8888); +#endif + break; + case RUNLOOP_CTL_HTTPSERVER_DESTROY: +#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) + httpserver_destroy(); +#endif + break; + case RUNLOOP_CTL_NONE: + default: + break; + } + + return true; +} + +/* Time to exit out of the main loop? + * Reasons for exiting: + * a) Shutdown environment callback was invoked. + * b) Quit key was pressed. + * c) Frame count exceeds or equals maximum amount of frames to run. + * d) Video driver no longer alive. + * e) End of BSV movie and BSV EOF exit is true. (TODO/FIXME - explain better) + */ +#define time_to_exit(quit_key_pressed) (runloop_shutdown_initiated || quit_key_pressed || !is_alive || bsv_movie_is_end_of_file() || (runloop_max_frames && (frame_count >= runloop_max_frames)) || runloop_exec) + +#define runloop_check_cheevos() (settings->bools.cheevos_enable && cheevos_loaded && (!cheats_are_enabled && !cheats_were_enabled)) + +static enum runloop_state runloop_check_state( + settings_t *settings, + uint64_t current_input, + uint64_t old_input, + uint64_t trigger_input, + bool input_driver_is_nonblock, + unsigned *sleep_ms) +{ + static bool old_focus = true; +#ifdef HAVE_OVERLAY + static char prev_overlay_restore = false; +#endif +#ifdef HAVE_NETWORKING + bool tmp = false; +#endif + bool is_focused = false; + bool is_alive = false; + uint64_t frame_count = 0; + bool focused = true; + bool pause_pressed = runloop_cmd_triggered(trigger_input, RARCH_PAUSE_TOGGLE); + + video_driver_get_status(&frame_count, &is_alive, &is_focused); + + if (runloop_cmd_triggered(trigger_input, RARCH_OVERLAY_NEXT)) + command_event(CMD_EVENT_OVERLAY_NEXT, NULL); + + if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY)) + { + bool fullscreen_toggled = !runloop_paused +#ifdef HAVE_MENU + || menu_driver_is_alive(); +#endif + ; + + if (fullscreen_toggled) + command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL); + } + + if (runloop_cmd_triggered(trigger_input, RARCH_GRAB_MOUSE_TOGGLE)) + command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL); + + +#ifdef HAVE_OVERLAY + if (input_keyboard_ctl( + RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL)) + { + prev_overlay_restore = false; + command_event(CMD_EVENT_OVERLAY_INIT, NULL); + } + else if (prev_overlay_restore) + { + if (!settings->bools.input_overlay_hide_in_menu) + command_event(CMD_EVENT_OVERLAY_INIT, NULL); + prev_overlay_restore = false; + } +#endif + + if (time_to_exit(runloop_cmd_press(trigger_input, RARCH_QUIT_KEY))) + { + if (runloop_exec) + runloop_exec = false; + + if (runloop_core_shutdown_initiated && settings->bools.load_dummy_on_core_shutdown) + { + content_ctx_info_t content_info; + + content_info.argc = 0; + content_info.argv = NULL; + content_info.args = NULL; + content_info.environ_get = NULL; + + if (!task_push_start_dummy_core(&content_info)) + { + retroarch_main_quit(); + return RUNLOOP_STATE_QUIT; + } + + /* Loads dummy core instead of exiting RetroArch completely. + * Aborts core shutdown if invoked. */ + runloop_shutdown_initiated = false; + runloop_core_shutdown_initiated = false; + } + else + { + retroarch_main_quit(); + return RUNLOOP_STATE_QUIT; + } + } + +#ifdef HAVE_MENU + if (menu_driver_is_alive()) + { + menu_ctx_iterate_t iter; + core_poll(); + + { + enum menu_action action = (enum menu_action)menu_event(current_input, trigger_input); + bool focused = settings->bools.pause_nonactive ? is_focused : true; + + focused = focused && !ui_companion_is_on_foreground(); + + iter.action = action; + + if (!menu_driver_iterate(&iter)) + rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); + + if (focused || !runloop_idle) + menu_driver_render(runloop_idle); + + if (!focused) + return RUNLOOP_STATE_SLEEP; + + if (action == MENU_ACTION_QUIT && !menu_driver_is_binding_state()) + return RUNLOOP_STATE_QUIT; + } + } +#endif + + if (runloop_idle) + return RUNLOOP_STATE_SLEEP; + + if (runloop_cmd_triggered(trigger_input, RARCH_GAME_FOCUS_TOGGLE)) + command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, (void*)(intptr_t)0); + +#ifdef HAVE_MENU + if (menu_event_kb_is_set(RETROK_F1) == 1) + { + if (menu_driver_is_alive()) + { + if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && + !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) + { + rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); + menu_event_kb_set(false, RETROK_F1); + } + } + } + else if ((!menu_event_kb_is_set(RETROK_F1) && + runloop_cmd_triggered(trigger_input, RARCH_MENU_TOGGLE)) || + rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) + { + if (menu_driver_is_alive()) + { + if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && + !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) + rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); + } + else + { + menu_display_toggle_set_reason(MENU_TOGGLE_REASON_USER); + rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); + } + } + else + menu_event_kb_set(false, RETROK_F1); + + if (menu_driver_is_alive()) + { + if (!settings->bools.menu_throttle_framerate && !settings->floats.fastforward_ratio) + return RUNLOOP_STATE_MENU_ITERATE; + + return RUNLOOP_STATE_END; + } +#endif + + if (settings->bools.pause_nonactive) + focused = is_focused; + + if (runloop_cmd_triggered(trigger_input, RARCH_SCREENSHOT)) + command_event(CMD_EVENT_TAKE_SCREENSHOT, NULL); + + if (runloop_cmd_triggered(trigger_input, RARCH_MUTE)) + command_event(CMD_EVENT_AUDIO_MUTE_TOGGLE, NULL); + + if (runloop_cmd_triggered(trigger_input, RARCH_OSK)) + { + if (input_keyboard_ctl( + RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL)) + input_keyboard_ctl( + RARCH_INPUT_KEYBOARD_CTL_UNSET_LINEFEED_ENABLED, NULL); + else + input_keyboard_ctl( + RARCH_INPUT_KEYBOARD_CTL_SET_LINEFEED_ENABLED, NULL); + } + + if (runloop_cmd_press(current_input, RARCH_VOLUME_UP)) + command_event(CMD_EVENT_VOLUME_UP, NULL); + else if (runloop_cmd_press(current_input, RARCH_VOLUME_DOWN)) + command_event(CMD_EVENT_VOLUME_DOWN, NULL); + +#ifdef HAVE_NETWORKING + tmp = runloop_cmd_triggered(trigger_input, RARCH_NETPLAY_FLIP); + netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, &tmp); + tmp = runloop_cmd_triggered(trigger_input, RARCH_NETPLAY_GAME_WATCH); + if (tmp) + netplay_driver_ctl(RARCH_NETPLAY_CTL_GAME_WATCH, NULL); + tmp = runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY); +#endif + + /* Check if libretro pause key was pressed. If so, pause or + * unpause the libretro core. */ + + /* FRAMEADVANCE will set us into pause mode. */ + pause_pressed |= !runloop_paused + && runloop_cmd_triggered(trigger_input, RARCH_FRAMEADVANCE); + + if (focused && pause_pressed) + command_event(CMD_EVENT_PAUSE_TOGGLE, NULL); + else if (focused && !old_focus) + command_event(CMD_EVENT_UNPAUSE, NULL); + else if (!focused && old_focus) + command_event(CMD_EVENT_PAUSE, NULL); + + old_focus = focused; + + if (!focused) + return RUNLOOP_STATE_SLEEP; + + if (runloop_paused) + { + /* check pause state */ + + bool check_is_oneshot = runloop_cmd_triggered(trigger_input, + RARCH_FRAMEADVANCE) + || runloop_cmd_press(current_input, RARCH_REWIND); + if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY)) + { + command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL); + if (!runloop_idle) + video_driver_cached_frame(); + } + + if (!check_is_oneshot) + return RUNLOOP_STATE_SLEEP; + } + + /* To avoid continous switching if we hold the button down, we require + * that the button must go from pressed to unpressed back to pressed + * to be able to toggle between then. + */ + if (runloop_cmd_triggered(trigger_input, RARCH_FAST_FORWARD_KEY)) + { + if (input_driver_is_nonblock) + input_driver_unset_nonblock_state(); + else + input_driver_set_nonblock_state(); + driver_set_nonblock_state(); + } + else if ((runloop_cmd_pressed(old_input, RARCH_FAST_FORWARD_HOLD_KEY) + != runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY))) + { + if (runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY)) + input_driver_set_nonblock_state(); + else + input_driver_unset_nonblock_state(); + driver_set_nonblock_state(); + } + + /* Checks if the state increase/decrease keys have been pressed + * for this frame. */ + if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_PLUS)) + { + char msg[128]; + int new_state_slot = settings->ints.state_slot + 1; + + msg[0] = '\0'; + + configuration_set_int(settings, settings->ints.state_slot, new_state_slot); + + snprintf(msg, sizeof(msg), "%s: %d", + msg_hash_to_str(MSG_STATE_SLOT), + settings->ints.state_slot); + + runloop_msg_queue_push(msg, 2, 180, true); + + RARCH_LOG("%s\n", msg); + } + else if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_MINUS)) + { + char msg[128]; + int new_state_slot = settings->ints.state_slot - 1; + + msg[0] = '\0'; + + if (settings->ints.state_slot > 0) + { + configuration_set_int(settings, settings->ints.state_slot, new_state_slot); + } + + snprintf(msg, sizeof(msg), "%s: %d", + msg_hash_to_str(MSG_STATE_SLOT), + settings->ints.state_slot); + + runloop_msg_queue_push(msg, 2, 180, true); + + RARCH_LOG("%s\n", msg); + } + + if (runloop_cmd_triggered(trigger_input, RARCH_SAVE_STATE_KEY)) + command_event(CMD_EVENT_SAVE_STATE, NULL); + else if (runloop_cmd_triggered(trigger_input, RARCH_LOAD_STATE_KEY)) + command_event(CMD_EVENT_LOAD_STATE, NULL); + +#ifdef HAVE_CHEEVOS + if (!settings->bools.cheevos_hardcore_mode_enable) +#endif + { + char s[128]; + unsigned t = 0; + + s[0] = '\0'; + + if (state_manager_check_rewind(runloop_cmd_press(current_input, RARCH_REWIND), + settings->uints.rewind_granularity, runloop_paused, s, sizeof(s), &t)) + runloop_msg_queue_push(s, 0, t, true); + } + + runloop_slowmotion = runloop_cmd_press(current_input, RARCH_SLOWMOTION); + + if (runloop_slowmotion) + { + /* Checks if slowmotion toggle/hold was being pressed and/or held. */ + if (settings->bools.video_black_frame_insertion) + { + if (!runloop_idle) + video_driver_cached_frame(); + } + + if (state_manager_frame_is_reversed()) + runloop_msg_queue_push( + msg_hash_to_str(MSG_SLOW_MOTION_REWIND), 2, 30, true); + else + runloop_msg_queue_push( + msg_hash_to_str(MSG_SLOW_MOTION), 2, 30, true); + } + + if (runloop_cmd_triggered(trigger_input, RARCH_MOVIE_RECORD_TOGGLE)) + bsv_movie_check(); + + if (runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT) || + runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV)) + dir_check_shader( + runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT), + runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV)); + + if (runloop_cmd_triggered(trigger_input, RARCH_DISK_EJECT_TOGGLE)) + command_event(CMD_EVENT_DISK_EJECT_TOGGLE, NULL); + else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_NEXT)) + command_event(CMD_EVENT_DISK_NEXT, NULL); + else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_PREV)) + command_event(CMD_EVENT_DISK_PREV, NULL); + + if (runloop_cmd_triggered(trigger_input, RARCH_RESET)) + command_event(CMD_EVENT_RESET, NULL); + + cheat_manager_state_checks( + runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_PLUS), + runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_MINUS), + runloop_cmd_triggered(trigger_input, RARCH_CHEAT_TOGGLE)); + + return RUNLOOP_STATE_ITERATE; +} + +#ifdef HAVE_NETWORKING +/* FIXME: This is an ugly way to tell Netplay this... */ +#define runloop_netplay_pause() netplay_driver_ctl(RARCH_NETPLAY_CTL_PAUSE, NULL) +#else +#define runloop_netplay_pause() ((void)0) +#endif + +void runloop_set(enum runloop_action action) +{ + switch (action) + { + case RUNLOOP_ACTION_AUTOSAVE: + runloop_autosave = true; + break; + case RUNLOOP_ACTION_NONE: + break; + } +} + +void runloop_unset(enum runloop_action action) +{ + switch (action) + { + case RUNLOOP_ACTION_AUTOSAVE: + runloop_autosave = false; + break; + case RUNLOOP_ACTION_NONE: + break; + } +} + +/** + * runloop_iterate: + * + * Run Libretro core in RetroArch for one frame. + * + * Returns: 0 on success, 1 if we have to wait until + * button input in order to wake up the loop, + * -1 if we forcibly quit out of the RetroArch iteration loop. + **/ +int runloop_iterate(unsigned *sleep_ms) +{ + unsigned i; + retro_time_t current, target, to_sleep_ms; + uint64_t trigger_input = 0; + static uint64_t last_input = 0; + bool input_driver_is_nonblock = false; + settings_t *settings = config_get_ptr(); + uint64_t old_input = last_input; +#ifdef HAVE_MENU + bool menu_is_alive = menu_driver_is_alive(); +#else + bool menu_is_alive = false; +#endif + unsigned max_users = *(input_driver_get_uint(INPUT_ACTION_MAX_USERS)); + uint64_t current_input = + +#ifdef HAVE_MENU + menu_is_alive ? + input_menu_keys_pressed(settings, old_input, + &last_input, &trigger_input, runloop_paused, + &input_driver_is_nonblock) : +#endif + input_keys_pressed(settings, old_input, &last_input, + &trigger_input, runloop_paused, + &input_driver_is_nonblock); + + if (runloop_frame_time.callback) + { + /* Updates frame timing if frame timing callback is in use by the core. + * Limits frame time if fast forward ratio throttle is enabled. */ + + retro_time_t current = cpu_features_get_time_usec(); + retro_time_t delta = current - runloop_frame_time_last; + bool is_locked_fps = (runloop_paused || + input_driver_is_nonblock) | + !!recording_data; + + + if (!runloop_frame_time_last || is_locked_fps) + delta = runloop_frame_time.reference; + + if (!is_locked_fps && runloop_slowmotion) + delta /= settings->floats.slowmotion_ratio; + + runloop_frame_time_last = current; + + if (is_locked_fps) + runloop_frame_time_last = 0; + + runloop_frame_time.callback(delta); + } + + switch ((enum runloop_state) + runloop_check_state( + settings, + current_input, + old_input, + trigger_input, + input_driver_is_nonblock, + sleep_ms)) + { + case RUNLOOP_STATE_QUIT: + frame_limit_last_time = 0.0; + command_event(CMD_EVENT_QUIT, NULL); + return -1; + case RUNLOOP_STATE_SLEEP: + core_poll(); + runloop_netplay_pause(); + *sleep_ms = 10; + return 1; + case RUNLOOP_STATE_END: + core_poll(); + runloop_netplay_pause(); + goto end; + case RUNLOOP_STATE_MENU_ITERATE: + core_poll(); + runloop_netplay_pause(); + return 0; + case RUNLOOP_STATE_ITERATE: + case RUNLOOP_STATE_NONE: + break; + } + + if (runloop_autosave) + autosave_lock(); + + bsv_movie_set_frame_start(); + + camera_driver_poll(); + + /* Update binds for analog dpad modes. */ + for (i = 0; i < max_users; i++) + { + struct retro_keybind *general_binds = input_config_binds[i]; + struct retro_keybind *auto_binds = input_autoconf_binds[i]; + enum analog_dpad_mode dpad_mode = (enum analog_dpad_mode)settings->uints.input_analog_dpad_mode[i]; + + if (dpad_mode == ANALOG_DPAD_NONE) + continue; + + input_push_analog_dpad(general_binds, dpad_mode); + input_push_analog_dpad(auto_binds, dpad_mode); + } + + if ((settings->uints.video_frame_delay > 0) && !input_driver_is_nonblock) + retro_sleep(settings->uints.video_frame_delay); + + core_run(); + +#ifdef HAVE_CHEEVOS + if (runloop_check_cheevos()) + cheevos_test(); +#endif + + for (i = 0; i < max_users; i++) + { + struct retro_keybind *general_binds = input_config_binds[i]; + struct retro_keybind *auto_binds = input_autoconf_binds[i]; + enum analog_dpad_mode dpad_mode = (enum analog_dpad_mode)settings->uints.input_analog_dpad_mode[i]; + + if (dpad_mode == ANALOG_DPAD_NONE) + continue; + + input_pop_analog_dpad(general_binds); + input_pop_analog_dpad(auto_binds); + } + + bsv_movie_set_frame_end(); + + if (runloop_autosave) + autosave_unlock(); + + if (!settings->floats.fastforward_ratio) + return 0; + +end: + + current = cpu_features_get_time_usec(); + target = frame_limit_last_time + + frame_limit_minimum_time; + to_sleep_ms = (target - current) / 1000; + + if (to_sleep_ms > 0) + { + *sleep_ms = (unsigned)to_sleep_ms; + /* Combat jitter a bit. */ + frame_limit_last_time += frame_limit_minimum_time; + return 1; + } + + frame_limit_last_time = cpu_features_get_time_usec(); + + return 0; +} + +rarch_system_info_t *runloop_get_system_info(void) +{ + return &runloop_system; +} diff --git a/retroarch.h b/retroarch.h index 3e22d5ac08..bea653751a 100644 --- a/retroarch.h +++ b/retroarch.h @@ -17,11 +17,16 @@ #ifndef __RETROARCH_H #define __RETROARCH_H -#include +#include +#include +#include #include +#include #include "core_type.h" +#include "core.h" +#include "runloop_defines.h" RETRO_BEGIN_DECLS @@ -129,6 +134,96 @@ enum rarch_override_setting RARCH_OVERRIDE_SETTING_LAST }; +enum runloop_action +{ + RUNLOOP_ACTION_NONE = 0, + RUNLOOP_ACTION_AUTOSAVE +}; + +enum runloop_ctl_state +{ + RUNLOOP_CTL_NONE = 0, + + RUNLOOP_CTL_SET_FRAME_LIMIT, + + RUNLOOP_CTL_TASK_INIT, + + RUNLOOP_CTL_FRAME_TIME_FREE, + RUNLOOP_CTL_SET_FRAME_TIME_LAST, + RUNLOOP_CTL_SET_FRAME_TIME, + + RUNLOOP_CTL_IS_IDLE, + RUNLOOP_CTL_SET_IDLE, + + RUNLOOP_CTL_GET_WINDOWED_SCALE, + RUNLOOP_CTL_SET_WINDOWED_SCALE, + + RUNLOOP_CTL_IS_OVERRIDES_ACTIVE, + RUNLOOP_CTL_SET_OVERRIDES_ACTIVE, + RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE, + + RUNLOOP_CTL_IS_MISSING_BIOS, + RUNLOOP_CTL_SET_MISSING_BIOS, + RUNLOOP_CTL_UNSET_MISSING_BIOS, + + RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE, + + RUNLOOP_CTL_IS_NONBLOCK_FORCED, + RUNLOOP_CTL_SET_NONBLOCK_FORCED, + RUNLOOP_CTL_UNSET_NONBLOCK_FORCED, + + RUNLOOP_CTL_SET_LIBRETRO_PATH, + + RUNLOOP_CTL_IS_PAUSED, + RUNLOOP_CTL_SET_PAUSED, + RUNLOOP_CTL_SET_MAX_FRAMES, + RUNLOOP_CTL_GLOBAL_FREE, + + RUNLOOP_CTL_SET_CORE_SHUTDOWN, + + RUNLOOP_CTL_SET_SHUTDOWN, + RUNLOOP_CTL_IS_SHUTDOWN, + + /* Runloop state */ + RUNLOOP_CTL_CLEAR_STATE, + RUNLOOP_CTL_STATE_FREE, + + /* Performance counters */ + RUNLOOP_CTL_GET_PERFCNT, + RUNLOOP_CTL_SET_PERFCNT_ENABLE, + RUNLOOP_CTL_UNSET_PERFCNT_ENABLE, + RUNLOOP_CTL_IS_PERFCNT_ENABLE, + + /* Key event */ + RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET, + RUNLOOP_CTL_KEY_EVENT_GET, + RUNLOOP_CTL_DATA_DEINIT, + + /* Message queue */ + RUNLOOP_CTL_MSG_QUEUE_INIT, + RUNLOOP_CTL_MSG_QUEUE_DEINIT, + + /* Core options */ + RUNLOOP_CTL_HAS_CORE_OPTIONS, + RUNLOOP_CTL_GET_CORE_OPTION_SIZE, + RUNLOOP_CTL_IS_CORE_OPTION_UPDATED, + RUNLOOP_CTL_CORE_OPTIONS_LIST_GET, + RUNLOOP_CTL_CORE_OPTION_PREV, + RUNLOOP_CTL_CORE_OPTION_NEXT, + RUNLOOP_CTL_CORE_OPTIONS_GET, + RUNLOOP_CTL_CORE_OPTIONS_INIT, + RUNLOOP_CTL_CORE_OPTIONS_DEINIT, + RUNLOOP_CTL_CORE_OPTIONS_FREE, + + /* System info */ + RUNLOOP_CTL_SYSTEM_INFO_INIT, + RUNLOOP_CTL_SYSTEM_INFO_FREE, + + /* HTTP server */ + RUNLOOP_CTL_HTTPSERVER_INIT, + RUNLOOP_CTL_HTTPSERVER_DESTROY +}; + struct rarch_main_wrap { int argc; @@ -144,6 +239,73 @@ struct rarch_main_wrap bool touched; }; +typedef struct rarch_resolution +{ + unsigned idx; + unsigned id; +} rarch_resolution_t; + +/* All run-time- / command line flag-related globals go here. */ + +typedef struct global +{ + struct + { + char savefile[8192]; + char savestate[8192]; + char cheatfile[8192]; + char ups[8192]; + char bps[8192]; + char ips[8192]; + char remapfile[8192]; + } name; + + /* Recording. */ + struct + { + char path[8192]; + char config[8192]; + unsigned width; + unsigned height; + + size_t gpu_width; + size_t gpu_height; + char output_dir[8192]; + char config_dir[8192]; + bool use_output_dir; + } record; + + /* Settings and/or global state that is specific to + * a console-style implementation. */ + struct + { + struct + { + struct + { + rarch_resolution_t current; + rarch_resolution_t initial; + uint32_t *list; + unsigned count; + bool check; + } resolutions; + + unsigned gamma_correction; + unsigned int flicker_filter_index; + unsigned char soft_filter_index; + bool pal_enable; + bool pal60_enable; + } screen; + + struct + { + bool system_bgm_enable; + } sound; + + bool flickerfilter_enable; + bool softfilter_enable; + } console; +} global_t; bool rarch_ctl(enum rarch_ctl_state state, void *data); @@ -184,6 +346,37 @@ bool retroarch_main_init(int argc, char *argv[]); bool retroarch_main_quit(void); +global_t *global_get_ptr(void); + +/** + * runloop_iterate: + * + * Run Libretro core in RetroArch for one frame. + * + * Returns: 0 on successful run, + * Returns 1 if we have to wait until button input in order + * to wake up the loop. + * Returns -1 if we forcibly quit out of the + * RetroArch iteration loop. + **/ +int runloop_iterate(unsigned *sleep_ms); + +void runloop_msg_queue_push(const char *msg, unsigned prio, + unsigned duration, bool flush); + +bool runloop_msg_queue_pull(const char **ret); + +void runloop_get_status(bool *is_paused, bool *is_idle, bool *is_slowmotion, + bool *is_perfcnt_enable); + +bool runloop_ctl(enum runloop_ctl_state state, void *data); + +void runloop_set(enum runloop_action action); + +void runloop_unset(enum runloop_action action); + +rarch_system_info_t *runloop_get_system_info(void); + RETRO_END_DECLS #endif diff --git a/runloop.c b/runloop.c deleted file mode 100644 index 68b574317a..0000000000 --- a/runloop.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * Copyright (C) 2011-2017 - Daniel De Matteis - * Copyright (C) 2012-2015 - Michael Lelli - * Copyright (C) 2014-2015 - Jay McCarthy - * Copyright (C) 2016-2017 - 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 . - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_THREADS -#include -#endif - -#ifdef HAVE_CHEEVOS -#include "cheevos/cheevos.h" -#endif - -#ifdef HAVE_MENU -#include "menu/menu_display.h" -#include "menu/menu_driver.h" -#include "menu/menu_event.h" -#include "menu/widgets/menu_dialog.h" -#endif - -#ifdef HAVE_NETWORKING -#include "network/netplay/netplay.h" -#endif - -#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) -#include "network/httpserver/httpserver.h" -#endif - -#include "autosave.h" -#include "command.h" -#include "configuration.h" -#include "driver.h" -#include "movie.h" -#include "dirs.h" -#include "paths.h" -#include "retroarch.h" -#include "runloop.h" -#include "file_path_special.h" -#include "managers/core_option_manager.h" -#include "managers/cheat_manager.h" -#include "managers/state_manager.h" -#include "list_special.h" -#include "audio/audio_driver.h" -#include "camera/camera_driver.h" -#include "record/record_driver.h" -#include "input/input_config.h" -#include "input/input_driver.h" -#include "ui/ui_companion_driver.h" -#include "core.h" - -#include "msg_hash.h" - -#include "input/input_keyboard.h" -#include "tasks/tasks_internal.h" -#include "verbosity.h" - -#ifdef HAVE_ZLIB -#define DEFAULT_EXT "zip" -#else -#define DEFAULT_EXT "" -#endif - -#define runloop_cmd_triggered(trigger_input, id) (BIT64_GET(trigger_input, id)) -#define runloop_cmd_pressed(old_input, id) (BIT64_GET(old_input, id)) - -enum runloop_state -{ - RUNLOOP_STATE_NONE = 0, - RUNLOOP_STATE_ITERATE, - RUNLOOP_STATE_SLEEP, - RUNLOOP_STATE_MENU_ITERATE, - RUNLOOP_STATE_END, - RUNLOOP_STATE_QUIT -}; - -typedef struct runloop_ctx_msg_info -{ - const char *msg; - unsigned prio; - unsigned duration; - bool flush; -} runloop_ctx_msg_info_t; - -static rarch_system_info_t runloop_system; -static struct retro_frame_time_callback runloop_frame_time; -static retro_keyboard_event_t runloop_key_event = NULL; -static retro_keyboard_event_t runloop_frontend_key_event = NULL; -static core_option_manager_t *runloop_core_options = NULL; -#ifdef HAVE_THREADS -static slock_t *_runloop_msg_queue_lock = NULL; -#endif -static msg_queue_t *runloop_msg_queue = NULL; -static unsigned runloop_pending_windowed_scale = 0; -static retro_usec_t runloop_frame_time_last = 0; -static unsigned runloop_max_frames = false; -static bool runloop_force_nonblock = false; -static bool runloop_paused = false; -static bool runloop_idle = false; -static bool runloop_exec = false; -static bool runloop_slowmotion = false; -static bool runloop_shutdown_initiated = false; -static bool runloop_core_shutdown_initiated = false; -static bool runloop_perfcnt_enable = false; -static bool runloop_overrides_active = false; -static bool runloop_game_options_active = false; -static bool runloop_missing_bios = false; -static bool runloop_autosave = false; -static retro_time_t frame_limit_minimum_time = 0.0; -static retro_time_t frame_limit_last_time = 0.0; - -global_t *global_get_ptr(void) -{ - static struct global g_extern; - return &g_extern; -} - -void runloop_msg_queue_push(const char *msg, - unsigned prio, unsigned duration, - bool flush) -{ - runloop_ctx_msg_info_t msg_info; - -#ifdef HAVE_THREADS - slock_lock(_runloop_msg_queue_lock); -#endif - - if (flush) - msg_queue_clear(runloop_msg_queue); - - msg_info.msg = msg; - msg_info.prio = prio; - msg_info.duration = duration; - msg_info.flush = flush; - - if (runloop_msg_queue) - { - msg_queue_push(runloop_msg_queue, msg_info.msg, - msg_info.prio, msg_info.duration); - - if (ui_companion_is_on_foreground()) - { - const ui_companion_driver_t *ui = ui_companion_get_ptr(); - if (ui->msg_queue_push) - ui->msg_queue_push(msg_info.msg, - msg_info.prio, msg_info.duration, msg_info.flush); - } - } - -#ifdef HAVE_THREADS - slock_unlock(_runloop_msg_queue_lock); -#endif -} - -/** - * rarch_game_specific_options: - * - * Returns: true (1) if a game specific core - * options path has been found, - * otherwise false (0). - **/ -static bool rarch_game_specific_options(char **output) -{ - char game_path[8192]; - - game_path[0] ='\0'; - - if (!retroarch_validate_game_options(game_path, - sizeof(game_path), false)) - return false; - - if (!config_file_exists(game_path)) - return false; - - RARCH_LOG("%s %s\n", - msg_hash_to_str(MSG_GAME_SPECIFIC_CORE_OPTIONS_FOUND_AT), - game_path); - *output = strdup(game_path); - return true; -} - -void runloop_get_status(bool *is_paused, bool *is_idle, - bool *is_slowmotion, bool *is_perfcnt_enable) -{ - *is_paused = runloop_paused; - *is_idle = runloop_idle; - *is_slowmotion = runloop_slowmotion; - *is_perfcnt_enable = runloop_perfcnt_enable; -} - -bool runloop_msg_queue_pull(const char **ret) -{ - if (!ret) - return false; -#ifdef HAVE_THREADS - slock_lock(_runloop_msg_queue_lock); -#endif - *ret = msg_queue_pull(runloop_msg_queue); -#ifdef HAVE_THREADS - slock_unlock(_runloop_msg_queue_lock); -#endif - return true; -} - -bool runloop_ctl(enum runloop_ctl_state state, void *data) -{ - - switch (state) - { - case RUNLOOP_CTL_SYSTEM_INFO_INIT: - core_get_system_info(&runloop_system.info); - - if (!runloop_system.info.library_name) - runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN); - if (!runloop_system.info.library_version) - runloop_system.info.library_version = "v0"; - - video_driver_set_title_buf(); - - strlcpy(runloop_system.valid_extensions, - runloop_system.info.valid_extensions ? - runloop_system.info.valid_extensions : DEFAULT_EXT, - sizeof(runloop_system.valid_extensions)); - break; - case RUNLOOP_CTL_GET_CORE_OPTION_SIZE: - { - unsigned *idx = (unsigned*)data; - if (!idx) - return false; - *idx = (unsigned)core_option_manager_size(runloop_core_options); - } - break; - case RUNLOOP_CTL_HAS_CORE_OPTIONS: - return runloop_core_options; - case RUNLOOP_CTL_CORE_OPTIONS_LIST_GET: - { - core_option_manager_t **coreopts = (core_option_manager_t**)data; - if (!coreopts) - return false; - *coreopts = runloop_core_options; - } - break; - case RUNLOOP_CTL_SYSTEM_INFO_FREE: - - /* No longer valid. */ - if (runloop_system.subsystem.data) - free(runloop_system.subsystem.data); - runloop_system.subsystem.data = NULL; - runloop_system.subsystem.size = 0; - - if (runloop_system.ports.data) - free(runloop_system.ports.data); - runloop_system.ports.data = NULL; - runloop_system.ports.size = 0; - - if (runloop_system.mmaps.descriptors) - free((void *)runloop_system.mmaps.descriptors); - runloop_system.mmaps.descriptors = NULL; - runloop_system.mmaps.num_descriptors = 0; - - runloop_key_event = NULL; - runloop_frontend_key_event = NULL; - - audio_driver_unset_callback(); - memset(&runloop_system, 0, sizeof(rarch_system_info_t)); - break; - case RUNLOOP_CTL_SET_FRAME_TIME_LAST: - runloop_frame_time_last = 0; - break; - case RUNLOOP_CTL_SET_OVERRIDES_ACTIVE: - runloop_overrides_active = true; - break; - case RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE: - runloop_overrides_active = false; - break; - case RUNLOOP_CTL_IS_OVERRIDES_ACTIVE: - return runloop_overrides_active; - case RUNLOOP_CTL_SET_MISSING_BIOS: - runloop_missing_bios = true; - break; - case RUNLOOP_CTL_UNSET_MISSING_BIOS: - runloop_missing_bios = false; - break; - case RUNLOOP_CTL_IS_MISSING_BIOS: - return runloop_missing_bios; - case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE: - return runloop_game_options_active; - case RUNLOOP_CTL_SET_FRAME_LIMIT: - { - settings_t *settings = config_get_ptr(); - struct retro_system_av_info *av_info = - video_viewport_get_system_av_info(); - float fastforward_ratio = - (settings->floats.fastforward_ratio == 0.0f) - ? 1.0f : settings->floats.fastforward_ratio; - - frame_limit_last_time = cpu_features_get_time_usec(); - frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f - / (av_info->timing.fps * fastforward_ratio)); - } - break; - case RUNLOOP_CTL_GET_PERFCNT: - { - bool **perfcnt = (bool**)data; - if (!perfcnt) - return false; - *perfcnt = &runloop_perfcnt_enable; - } - break; - case RUNLOOP_CTL_SET_PERFCNT_ENABLE: - runloop_perfcnt_enable = true; - break; - case RUNLOOP_CTL_UNSET_PERFCNT_ENABLE: - runloop_perfcnt_enable = false; - break; - case RUNLOOP_CTL_IS_PERFCNT_ENABLE: - return runloop_perfcnt_enable; - case RUNLOOP_CTL_SET_NONBLOCK_FORCED: - runloop_force_nonblock = true; - break; - case RUNLOOP_CTL_UNSET_NONBLOCK_FORCED: - runloop_force_nonblock = false; - break; - case RUNLOOP_CTL_IS_NONBLOCK_FORCED: - return runloop_force_nonblock; - case RUNLOOP_CTL_SET_FRAME_TIME: - { - const struct retro_frame_time_callback *info = - (const struct retro_frame_time_callback*)data; -#ifdef HAVE_NETWORKING - /* retro_run() will be called in very strange and - * mysterious ways, have to disable it. */ - if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL)) - return false; -#endif - runloop_frame_time = *info; - } - break; - case RUNLOOP_CTL_GET_WINDOWED_SCALE: - { - unsigned **scale = (unsigned**)data; - if (!scale) - return false; - *scale = (unsigned*)&runloop_pending_windowed_scale; - } - break; - case RUNLOOP_CTL_SET_WINDOWED_SCALE: - { - unsigned *idx = (unsigned*)data; - if (!idx) - return false; - runloop_pending_windowed_scale = *idx; - } - break; - case RUNLOOP_CTL_SET_LIBRETRO_PATH: - return path_set(RARCH_PATH_CORE, (const char*)data); - case RUNLOOP_CTL_FRAME_TIME_FREE: - memset(&runloop_frame_time, 0, - sizeof(struct retro_frame_time_callback)); - runloop_frame_time_last = 0; - runloop_max_frames = 0; - break; - case RUNLOOP_CTL_STATE_FREE: - runloop_perfcnt_enable = false; - runloop_idle = false; - runloop_paused = false; - runloop_slowmotion = false; - runloop_overrides_active = false; - runloop_autosave = false; - runloop_ctl(RUNLOOP_CTL_FRAME_TIME_FREE, NULL); - break; - case RUNLOOP_CTL_GLOBAL_FREE: - { - global_t *global = NULL; - command_event(CMD_EVENT_TEMPORARY_CONTENT_DEINIT, NULL); - - path_deinit_subsystem(); - command_event(CMD_EVENT_RECORD_DEINIT, NULL); - command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL); - - rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL); - rarch_ctl(RARCH_CTL_UNSET_SRAM_LOAD_DISABLED, NULL); - rarch_ctl(RARCH_CTL_UNSET_SRAM_SAVE_DISABLED, NULL); - rarch_ctl(RARCH_CTL_UNSET_SRAM_ENABLE, NULL); - rarch_ctl(RARCH_CTL_UNSET_BPS_PREF, NULL); - rarch_ctl(RARCH_CTL_UNSET_IPS_PREF, NULL); - rarch_ctl(RARCH_CTL_UNSET_UPS_PREF, NULL); - rarch_ctl(RARCH_CTL_UNSET_PATCH_BLOCKED, NULL); - runloop_overrides_active = false; - - core_unset_input_descriptors(); - - global = global_get_ptr(); - path_clear_all(); - dir_clear_all(); - memset(global, 0, sizeof(struct global)); - retroarch_override_setting_free_state(); - } - break; - case RUNLOOP_CTL_CLEAR_STATE: - driver_ctl(RARCH_DRIVER_CTL_DEINIT, NULL); - runloop_ctl(RUNLOOP_CTL_STATE_FREE, NULL); - runloop_ctl(RUNLOOP_CTL_GLOBAL_FREE, NULL); - break; - case RUNLOOP_CTL_SET_MAX_FRAMES: - { - unsigned *ptr = (unsigned*)data; - if (!ptr) - return false; - runloop_max_frames = *ptr; - } - break; - case RUNLOOP_CTL_IS_IDLE: - return runloop_idle; - case RUNLOOP_CTL_SET_IDLE: - { - bool *ptr = (bool*)data; - if (!ptr) - return false; - runloop_idle = *ptr; - } - break; - case RUNLOOP_CTL_SET_PAUSED: - { - bool *ptr = (bool*)data; - if (!ptr) - return false; - runloop_paused = *ptr; - } - break; - case RUNLOOP_CTL_IS_PAUSED: - return runloop_paused; - case RUNLOOP_CTL_MSG_QUEUE_DEINIT: - if (!runloop_msg_queue) - return true; - -#ifdef HAVE_THREADS - slock_lock(_runloop_msg_queue_lock); -#endif - - msg_queue_free(runloop_msg_queue); - -#ifdef HAVE_THREADS - slock_unlock(_runloop_msg_queue_lock); -#endif - -#ifdef HAVE_THREADS - slock_free(_runloop_msg_queue_lock); - _runloop_msg_queue_lock = NULL; -#endif - - runloop_msg_queue = NULL; - break; - case RUNLOOP_CTL_MSG_QUEUE_INIT: - runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL); - runloop_msg_queue = msg_queue_new(8); - retro_assert(runloop_msg_queue); - -#ifdef HAVE_THREADS - _runloop_msg_queue_lock = slock_new(); - retro_assert(_runloop_msg_queue_lock); -#endif - break; - case RUNLOOP_CTL_TASK_INIT: - { -#ifdef HAVE_THREADS - settings_t *settings = config_get_ptr(); - bool threaded_enable = settings->bools.threaded_data_runloop_enable; -#else - bool threaded_enable = false; -#endif - task_queue_deinit(); - task_queue_init(threaded_enable, runloop_msg_queue_push); - } - break; - case RUNLOOP_CTL_SET_CORE_SHUTDOWN: - runloop_core_shutdown_initiated = true; - break; - case RUNLOOP_CTL_SET_SHUTDOWN: - runloop_shutdown_initiated = true; - break; - case RUNLOOP_CTL_IS_SHUTDOWN: - return runloop_shutdown_initiated; - case RUNLOOP_CTL_DATA_DEINIT: - task_queue_deinit(); - break; - case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED: - if (!runloop_core_options) - return false; - return core_option_manager_updated(runloop_core_options); - case RUNLOOP_CTL_CORE_OPTION_PREV: - { - unsigned *idx = (unsigned*)data; - if (!idx) - return false; - core_option_manager_prev(runloop_core_options, *idx); - if (ui_companion_is_on_foreground()) - ui_companion_driver_notify_refresh(); - } - break; - case RUNLOOP_CTL_CORE_OPTION_NEXT: - { - unsigned *idx = (unsigned*)data; - if (!idx) - return false; - core_option_manager_next(runloop_core_options, *idx); - if (ui_companion_is_on_foreground()) - ui_companion_driver_notify_refresh(); - } - break; - case RUNLOOP_CTL_CORE_OPTIONS_GET: - { - struct retro_variable *var = (struct retro_variable*)data; - - if (!runloop_core_options || !var) - return false; - - RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key); - core_option_manager_get(runloop_core_options, var); - RARCH_LOG("\t%s\n", var->value ? var->value : - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE)); - } - break; - case RUNLOOP_CTL_CORE_OPTIONS_INIT: - { - settings_t *settings = config_get_ptr(); - char *game_options_path = NULL; - bool ret = false; - const struct retro_variable *vars = - (const struct retro_variable*)data; - - if (settings && settings->bools.game_specific_options) - ret = rarch_game_specific_options(&game_options_path); - - if(ret) - { - runloop_game_options_active = true; - runloop_core_options = - core_option_manager_new(game_options_path, vars); - free(game_options_path); - } - else - { - char buf[PATH_MAX_LENGTH]; - const char *options_path = NULL; - - buf[0] = '\0'; - - if (settings) - options_path = settings->paths.path_core_options; - - if (string_is_empty(options_path) && !path_is_empty(RARCH_PATH_CONFIG)) - { - fill_pathname_resolve_relative(buf, path_get(RARCH_PATH_CONFIG), - file_path_str(FILE_PATH_CORE_OPTIONS_CONFIG), sizeof(buf)); - options_path = buf; - } - - runloop_game_options_active = false; - - if (!string_is_empty(options_path)) - runloop_core_options = - core_option_manager_new(options_path, vars); - } - - } - break; - case RUNLOOP_CTL_CORE_OPTIONS_FREE: - if (runloop_core_options) - core_option_manager_free(runloop_core_options); - runloop_core_options = NULL; - break; - case RUNLOOP_CTL_CORE_OPTIONS_DEINIT: - { - if (!runloop_core_options) - return false; - - /* check if game options file was just created and flush - to that file instead */ - if(!path_is_empty(RARCH_PATH_CORE_OPTIONS)) - { - core_option_manager_flush_game_specific(runloop_core_options, - path_get(RARCH_PATH_CORE_OPTIONS)); - path_clear(RARCH_PATH_CORE_OPTIONS); - } - else - core_option_manager_flush(runloop_core_options); - - if (runloop_game_options_active) - runloop_game_options_active = false; - - runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_FREE, NULL); - } - break; - case RUNLOOP_CTL_KEY_EVENT_GET: - { - retro_keyboard_event_t **key_event = - (retro_keyboard_event_t**)data; - if (!key_event) - return false; - *key_event = &runloop_key_event; - } - break; - case RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET: - { - retro_keyboard_event_t **key_event = - (retro_keyboard_event_t**)data; - if (!key_event) - return false; - *key_event = &runloop_frontend_key_event; - } - break; - case RUNLOOP_CTL_HTTPSERVER_INIT: -#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) - httpserver_init(8888); -#endif - break; - case RUNLOOP_CTL_HTTPSERVER_DESTROY: -#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB) - httpserver_destroy(); -#endif - break; - case RUNLOOP_CTL_NONE: - default: - break; - } - - return true; -} - -/* Time to exit out of the main loop? - * Reasons for exiting: - * a) Shutdown environment callback was invoked. - * b) Quit key was pressed. - * c) Frame count exceeds or equals maximum amount of frames to run. - * d) Video driver no longer alive. - * e) End of BSV movie and BSV EOF exit is true. (TODO/FIXME - explain better) - */ -#define time_to_exit(quit_key_pressed) (runloop_shutdown_initiated || quit_key_pressed || !is_alive || bsv_movie_is_end_of_file() || (runloop_max_frames && (frame_count >= runloop_max_frames)) || runloop_exec) - -#define runloop_check_cheevos() (settings->bools.cheevos_enable && cheevos_loaded && (!cheats_are_enabled && !cheats_were_enabled)) - -static enum runloop_state runloop_check_state( - settings_t *settings, - uint64_t current_input, - uint64_t old_input, - uint64_t trigger_input, - bool input_driver_is_nonblock, - unsigned *sleep_ms) -{ - static bool old_focus = true; -#ifdef HAVE_OVERLAY - static char prev_overlay_restore = false; -#endif -#ifdef HAVE_NETWORKING - bool tmp = false; -#endif - bool is_focused = false; - bool is_alive = false; - uint64_t frame_count = 0; - bool focused = true; - bool pause_pressed = runloop_cmd_triggered(trigger_input, RARCH_PAUSE_TOGGLE); - - video_driver_get_status(&frame_count, &is_alive, &is_focused); - - if (runloop_cmd_triggered(trigger_input, RARCH_OVERLAY_NEXT)) - command_event(CMD_EVENT_OVERLAY_NEXT, NULL); - - if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY)) - { - bool fullscreen_toggled = !runloop_paused -#ifdef HAVE_MENU - || menu_driver_is_alive(); -#endif - ; - - if (fullscreen_toggled) - command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL); - } - - if (runloop_cmd_triggered(trigger_input, RARCH_GRAB_MOUSE_TOGGLE)) - command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL); - - -#ifdef HAVE_OVERLAY - if (input_keyboard_ctl( - RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL)) - { - prev_overlay_restore = false; - command_event(CMD_EVENT_OVERLAY_INIT, NULL); - } - else if (prev_overlay_restore) - { - if (!settings->bools.input_overlay_hide_in_menu) - command_event(CMD_EVENT_OVERLAY_INIT, NULL); - prev_overlay_restore = false; - } -#endif - - if (time_to_exit(runloop_cmd_press(trigger_input, RARCH_QUIT_KEY))) - { - if (runloop_exec) - runloop_exec = false; - - if (runloop_core_shutdown_initiated && settings->bools.load_dummy_on_core_shutdown) - { - content_ctx_info_t content_info; - - content_info.argc = 0; - content_info.argv = NULL; - content_info.args = NULL; - content_info.environ_get = NULL; - - if (!task_push_start_dummy_core(&content_info)) - { - retroarch_main_quit(); - return RUNLOOP_STATE_QUIT; - } - - /* Loads dummy core instead of exiting RetroArch completely. - * Aborts core shutdown if invoked. */ - runloop_shutdown_initiated = false; - runloop_core_shutdown_initiated = false; - } - else - { - retroarch_main_quit(); - return RUNLOOP_STATE_QUIT; - } - } - -#ifdef HAVE_MENU - if (menu_driver_is_alive()) - { - menu_ctx_iterate_t iter; - core_poll(); - - { - enum menu_action action = (enum menu_action)menu_event(current_input, trigger_input); - bool focused = settings->bools.pause_nonactive ? is_focused : true; - - focused = focused && !ui_companion_is_on_foreground(); - - iter.action = action; - - if (!menu_driver_iterate(&iter)) - rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); - - if (focused || !runloop_idle) - menu_driver_render(runloop_idle); - - if (!focused) - return RUNLOOP_STATE_SLEEP; - - if (action == MENU_ACTION_QUIT && !menu_driver_is_binding_state()) - return RUNLOOP_STATE_QUIT; - } - } -#endif - - if (runloop_idle) - return RUNLOOP_STATE_SLEEP; - - if (runloop_cmd_triggered(trigger_input, RARCH_GAME_FOCUS_TOGGLE)) - command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, (void*)(intptr_t)0); - -#ifdef HAVE_MENU - if (menu_event_kb_is_set(RETROK_F1) == 1) - { - if (menu_driver_is_alive()) - { - if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && - !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) - { - rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); - menu_event_kb_set(false, RETROK_F1); - } - } - } - else if ((!menu_event_kb_is_set(RETROK_F1) && - runloop_cmd_triggered(trigger_input, RARCH_MENU_TOGGLE)) || - rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) - { - if (menu_driver_is_alive()) - { - if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && - !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) - rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); - } - else - { - menu_display_toggle_set_reason(MENU_TOGGLE_REASON_USER); - rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); - } - } - else - menu_event_kb_set(false, RETROK_F1); - - if (menu_driver_is_alive()) - { - if (!settings->bools.menu_throttle_framerate && !settings->floats.fastforward_ratio) - return RUNLOOP_STATE_MENU_ITERATE; - - return RUNLOOP_STATE_END; - } -#endif - - if (settings->bools.pause_nonactive) - focused = is_focused; - - if (runloop_cmd_triggered(trigger_input, RARCH_SCREENSHOT)) - command_event(CMD_EVENT_TAKE_SCREENSHOT, NULL); - - if (runloop_cmd_triggered(trigger_input, RARCH_MUTE)) - command_event(CMD_EVENT_AUDIO_MUTE_TOGGLE, NULL); - - if (runloop_cmd_triggered(trigger_input, RARCH_OSK)) - { - if (input_keyboard_ctl( - RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL)) - input_keyboard_ctl( - RARCH_INPUT_KEYBOARD_CTL_UNSET_LINEFEED_ENABLED, NULL); - else - input_keyboard_ctl( - RARCH_INPUT_KEYBOARD_CTL_SET_LINEFEED_ENABLED, NULL); - } - - if (runloop_cmd_press(current_input, RARCH_VOLUME_UP)) - command_event(CMD_EVENT_VOLUME_UP, NULL); - else if (runloop_cmd_press(current_input, RARCH_VOLUME_DOWN)) - command_event(CMD_EVENT_VOLUME_DOWN, NULL); - -#ifdef HAVE_NETWORKING - tmp = runloop_cmd_triggered(trigger_input, RARCH_NETPLAY_FLIP); - netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, &tmp); - tmp = runloop_cmd_triggered(trigger_input, RARCH_NETPLAY_GAME_WATCH); - if (tmp) - netplay_driver_ctl(RARCH_NETPLAY_CTL_GAME_WATCH, NULL); - tmp = runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY); -#endif - - /* Check if libretro pause key was pressed. If so, pause or - * unpause the libretro core. */ - - /* FRAMEADVANCE will set us into pause mode. */ - pause_pressed |= !runloop_paused - && runloop_cmd_triggered(trigger_input, RARCH_FRAMEADVANCE); - - if (focused && pause_pressed) - command_event(CMD_EVENT_PAUSE_TOGGLE, NULL); - else if (focused && !old_focus) - command_event(CMD_EVENT_UNPAUSE, NULL); - else if (!focused && old_focus) - command_event(CMD_EVENT_PAUSE, NULL); - - old_focus = focused; - - if (!focused) - return RUNLOOP_STATE_SLEEP; - - if (runloop_paused) - { - /* check pause state */ - - bool check_is_oneshot = runloop_cmd_triggered(trigger_input, - RARCH_FRAMEADVANCE) - || runloop_cmd_press(current_input, RARCH_REWIND); - if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY)) - { - command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL); - if (!runloop_idle) - video_driver_cached_frame(); - } - - if (!check_is_oneshot) - return RUNLOOP_STATE_SLEEP; - } - - /* To avoid continous switching if we hold the button down, we require - * that the button must go from pressed to unpressed back to pressed - * to be able to toggle between then. - */ - if (runloop_cmd_triggered(trigger_input, RARCH_FAST_FORWARD_KEY)) - { - if (input_driver_is_nonblock) - input_driver_unset_nonblock_state(); - else - input_driver_set_nonblock_state(); - driver_set_nonblock_state(); - } - else if ((runloop_cmd_pressed(old_input, RARCH_FAST_FORWARD_HOLD_KEY) - != runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY))) - { - if (runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY)) - input_driver_set_nonblock_state(); - else - input_driver_unset_nonblock_state(); - driver_set_nonblock_state(); - } - - /* Checks if the state increase/decrease keys have been pressed - * for this frame. */ - if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_PLUS)) - { - char msg[128]; - int new_state_slot = settings->ints.state_slot + 1; - - msg[0] = '\0'; - - configuration_set_int(settings, settings->ints.state_slot, new_state_slot); - - snprintf(msg, sizeof(msg), "%s: %d", - msg_hash_to_str(MSG_STATE_SLOT), - settings->ints.state_slot); - - runloop_msg_queue_push(msg, 2, 180, true); - - RARCH_LOG("%s\n", msg); - } - else if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_MINUS)) - { - char msg[128]; - int new_state_slot = settings->ints.state_slot - 1; - - msg[0] = '\0'; - - if (settings->ints.state_slot > 0) - { - configuration_set_int(settings, settings->ints.state_slot, new_state_slot); - } - - snprintf(msg, sizeof(msg), "%s: %d", - msg_hash_to_str(MSG_STATE_SLOT), - settings->ints.state_slot); - - runloop_msg_queue_push(msg, 2, 180, true); - - RARCH_LOG("%s\n", msg); - } - - if (runloop_cmd_triggered(trigger_input, RARCH_SAVE_STATE_KEY)) - command_event(CMD_EVENT_SAVE_STATE, NULL); - else if (runloop_cmd_triggered(trigger_input, RARCH_LOAD_STATE_KEY)) - command_event(CMD_EVENT_LOAD_STATE, NULL); - -#ifdef HAVE_CHEEVOS - if (!settings->bools.cheevos_hardcore_mode_enable) -#endif - { - char s[128]; - unsigned t = 0; - - s[0] = '\0'; - - if (state_manager_check_rewind(runloop_cmd_press(current_input, RARCH_REWIND), - settings->uints.rewind_granularity, runloop_paused, s, sizeof(s), &t)) - runloop_msg_queue_push(s, 0, t, true); - } - - runloop_slowmotion = runloop_cmd_press(current_input, RARCH_SLOWMOTION); - - if (runloop_slowmotion) - { - /* Checks if slowmotion toggle/hold was being pressed and/or held. */ - if (settings->bools.video_black_frame_insertion) - { - if (!runloop_idle) - video_driver_cached_frame(); - } - - if (state_manager_frame_is_reversed()) - runloop_msg_queue_push( - msg_hash_to_str(MSG_SLOW_MOTION_REWIND), 2, 30, true); - else - runloop_msg_queue_push( - msg_hash_to_str(MSG_SLOW_MOTION), 2, 30, true); - } - - if (runloop_cmd_triggered(trigger_input, RARCH_MOVIE_RECORD_TOGGLE)) - bsv_movie_check(); - - if (runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT) || - runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV)) - dir_check_shader( - runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT), - runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV)); - - if (runloop_cmd_triggered(trigger_input, RARCH_DISK_EJECT_TOGGLE)) - command_event(CMD_EVENT_DISK_EJECT_TOGGLE, NULL); - else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_NEXT)) - command_event(CMD_EVENT_DISK_NEXT, NULL); - else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_PREV)) - command_event(CMD_EVENT_DISK_PREV, NULL); - - if (runloop_cmd_triggered(trigger_input, RARCH_RESET)) - command_event(CMD_EVENT_RESET, NULL); - - cheat_manager_state_checks( - runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_PLUS), - runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_MINUS), - runloop_cmd_triggered(trigger_input, RARCH_CHEAT_TOGGLE)); - - return RUNLOOP_STATE_ITERATE; -} - -#ifdef HAVE_NETWORKING -/* FIXME: This is an ugly way to tell Netplay this... */ -#define runloop_netplay_pause() netplay_driver_ctl(RARCH_NETPLAY_CTL_PAUSE, NULL) -#else -#define runloop_netplay_pause() ((void)0) -#endif - -void runloop_set(enum runloop_action action) -{ - switch (action) - { - case RUNLOOP_ACTION_AUTOSAVE: - runloop_autosave = true; - break; - case RUNLOOP_ACTION_NONE: - break; - } -} - -void runloop_unset(enum runloop_action action) -{ - switch (action) - { - case RUNLOOP_ACTION_AUTOSAVE: - runloop_autosave = false; - break; - case RUNLOOP_ACTION_NONE: - break; - } -} - -/** - * runloop_iterate: - * - * Run Libretro core in RetroArch for one frame. - * - * Returns: 0 on success, 1 if we have to wait until - * button input in order to wake up the loop, - * -1 if we forcibly quit out of the RetroArch iteration loop. - **/ -int runloop_iterate(unsigned *sleep_ms) -{ - unsigned i; - retro_time_t current, target, to_sleep_ms; - uint64_t trigger_input = 0; - static uint64_t last_input = 0; - bool input_driver_is_nonblock = false; - settings_t *settings = config_get_ptr(); - uint64_t old_input = last_input; -#ifdef HAVE_MENU - bool menu_is_alive = menu_driver_is_alive(); -#else - bool menu_is_alive = false; -#endif - unsigned max_users = *(input_driver_get_uint(INPUT_ACTION_MAX_USERS)); - uint64_t current_input = - -#ifdef HAVE_MENU - menu_is_alive ? - input_menu_keys_pressed(settings, old_input, - &last_input, &trigger_input, runloop_paused, - &input_driver_is_nonblock) : -#endif - input_keys_pressed(settings, old_input, &last_input, - &trigger_input, runloop_paused, - &input_driver_is_nonblock); - - if (runloop_frame_time.callback) - { - /* Updates frame timing if frame timing callback is in use by the core. - * Limits frame time if fast forward ratio throttle is enabled. */ - - retro_time_t current = cpu_features_get_time_usec(); - retro_time_t delta = current - runloop_frame_time_last; - bool is_locked_fps = (runloop_paused || - input_driver_is_nonblock) | - !!recording_data; - - - if (!runloop_frame_time_last || is_locked_fps) - delta = runloop_frame_time.reference; - - if (!is_locked_fps && runloop_slowmotion) - delta /= settings->floats.slowmotion_ratio; - - runloop_frame_time_last = current; - - if (is_locked_fps) - runloop_frame_time_last = 0; - - runloop_frame_time.callback(delta); - } - - switch ((enum runloop_state) - runloop_check_state( - settings, - current_input, - old_input, - trigger_input, - input_driver_is_nonblock, - sleep_ms)) - { - case RUNLOOP_STATE_QUIT: - frame_limit_last_time = 0.0; - command_event(CMD_EVENT_QUIT, NULL); - return -1; - case RUNLOOP_STATE_SLEEP: - core_poll(); - runloop_netplay_pause(); - *sleep_ms = 10; - return 1; - case RUNLOOP_STATE_END: - core_poll(); - runloop_netplay_pause(); - goto end; - case RUNLOOP_STATE_MENU_ITERATE: - core_poll(); - runloop_netplay_pause(); - return 0; - case RUNLOOP_STATE_ITERATE: - case RUNLOOP_STATE_NONE: - break; - } - - if (runloop_autosave) - autosave_lock(); - - bsv_movie_set_frame_start(); - - camera_driver_poll(); - - /* Update binds for analog dpad modes. */ - for (i = 0; i < max_users; i++) - { - struct retro_keybind *general_binds = input_config_binds[i]; - struct retro_keybind *auto_binds = input_autoconf_binds[i]; - enum analog_dpad_mode dpad_mode = (enum analog_dpad_mode)settings->uints.input_analog_dpad_mode[i]; - - if (dpad_mode == ANALOG_DPAD_NONE) - continue; - - input_push_analog_dpad(general_binds, dpad_mode); - input_push_analog_dpad(auto_binds, dpad_mode); - } - - if ((settings->uints.video_frame_delay > 0) && !input_driver_is_nonblock) - retro_sleep(settings->uints.video_frame_delay); - - core_run(); - -#ifdef HAVE_CHEEVOS - if (runloop_check_cheevos()) - cheevos_test(); -#endif - - for (i = 0; i < max_users; i++) - { - struct retro_keybind *general_binds = input_config_binds[i]; - struct retro_keybind *auto_binds = input_autoconf_binds[i]; - enum analog_dpad_mode dpad_mode = (enum analog_dpad_mode)settings->uints.input_analog_dpad_mode[i]; - - if (dpad_mode == ANALOG_DPAD_NONE) - continue; - - input_pop_analog_dpad(general_binds); - input_pop_analog_dpad(auto_binds); - } - - bsv_movie_set_frame_end(); - - if (runloop_autosave) - autosave_unlock(); - - if (!settings->floats.fastforward_ratio) - return 0; - -end: - - current = cpu_features_get_time_usec(); - target = frame_limit_last_time + - frame_limit_minimum_time; - to_sleep_ms = (target - current) / 1000; - - if (to_sleep_ms > 0) - { - *sleep_ms = (unsigned)to_sleep_ms; - /* Combat jitter a bit. */ - frame_limit_last_time += frame_limit_minimum_time; - return 1; - } - - frame_limit_last_time = cpu_features_get_time_usec(); - - return 0; -} - -rarch_system_info_t *runloop_get_system_info(void) -{ - return &runloop_system; -} diff --git a/runloop.h b/runloop.h deleted file mode 100644 index 363dae314e..0000000000 --- a/runloop.h +++ /dev/null @@ -1,222 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2011-2016 - Daniel De Matteis - * Copyright (C) 2016 - 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 . - */ - -#ifndef __RETROARCH_RUNLOOP_H -#define __RETROARCH_RUNLOOP_H - -#include -#include -#include -#include -#include - -#include "core.h" -#include "runloop_defines.h" - -RETRO_BEGIN_DECLS - -enum runloop_action -{ - RUNLOOP_ACTION_NONE = 0, - RUNLOOP_ACTION_AUTOSAVE -}; - -enum runloop_ctl_state -{ - RUNLOOP_CTL_NONE = 0, - - RUNLOOP_CTL_SET_FRAME_LIMIT, - - RUNLOOP_CTL_TASK_INIT, - - RUNLOOP_CTL_FRAME_TIME_FREE, - RUNLOOP_CTL_SET_FRAME_TIME_LAST, - RUNLOOP_CTL_SET_FRAME_TIME, - - RUNLOOP_CTL_IS_IDLE, - RUNLOOP_CTL_SET_IDLE, - - RUNLOOP_CTL_GET_WINDOWED_SCALE, - RUNLOOP_CTL_SET_WINDOWED_SCALE, - - RUNLOOP_CTL_IS_OVERRIDES_ACTIVE, - RUNLOOP_CTL_SET_OVERRIDES_ACTIVE, - RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE, - - RUNLOOP_CTL_IS_MISSING_BIOS, - RUNLOOP_CTL_SET_MISSING_BIOS, - RUNLOOP_CTL_UNSET_MISSING_BIOS, - - RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE, - - RUNLOOP_CTL_IS_NONBLOCK_FORCED, - RUNLOOP_CTL_SET_NONBLOCK_FORCED, - RUNLOOP_CTL_UNSET_NONBLOCK_FORCED, - - RUNLOOP_CTL_SET_LIBRETRO_PATH, - - RUNLOOP_CTL_IS_PAUSED, - RUNLOOP_CTL_SET_PAUSED, - RUNLOOP_CTL_SET_MAX_FRAMES, - RUNLOOP_CTL_GLOBAL_FREE, - - RUNLOOP_CTL_SET_CORE_SHUTDOWN, - - RUNLOOP_CTL_SET_SHUTDOWN, - RUNLOOP_CTL_IS_SHUTDOWN, - - /* Runloop state */ - RUNLOOP_CTL_CLEAR_STATE, - RUNLOOP_CTL_STATE_FREE, - - /* Performance counters */ - RUNLOOP_CTL_GET_PERFCNT, - RUNLOOP_CTL_SET_PERFCNT_ENABLE, - RUNLOOP_CTL_UNSET_PERFCNT_ENABLE, - RUNLOOP_CTL_IS_PERFCNT_ENABLE, - - /* Key event */ - RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET, - RUNLOOP_CTL_KEY_EVENT_GET, - RUNLOOP_CTL_DATA_DEINIT, - - /* Message queue */ - RUNLOOP_CTL_MSG_QUEUE_INIT, - RUNLOOP_CTL_MSG_QUEUE_DEINIT, - - /* Core options */ - RUNLOOP_CTL_HAS_CORE_OPTIONS, - RUNLOOP_CTL_GET_CORE_OPTION_SIZE, - RUNLOOP_CTL_IS_CORE_OPTION_UPDATED, - RUNLOOP_CTL_CORE_OPTIONS_LIST_GET, - RUNLOOP_CTL_CORE_OPTION_PREV, - RUNLOOP_CTL_CORE_OPTION_NEXT, - RUNLOOP_CTL_CORE_OPTIONS_GET, - RUNLOOP_CTL_CORE_OPTIONS_INIT, - RUNLOOP_CTL_CORE_OPTIONS_DEINIT, - RUNLOOP_CTL_CORE_OPTIONS_FREE, - - /* System info */ - RUNLOOP_CTL_SYSTEM_INFO_INIT, - RUNLOOP_CTL_SYSTEM_INFO_FREE, - - /* HTTP server */ - RUNLOOP_CTL_HTTPSERVER_INIT, - RUNLOOP_CTL_HTTPSERVER_DESTROY -}; - -typedef struct rarch_resolution -{ - unsigned idx; - unsigned id; -} rarch_resolution_t; - -/* All run-time- / command line flag-related globals go here. */ - -typedef struct global -{ - struct - { - char savefile[8192]; - char savestate[8192]; - char cheatfile[8192]; - char ups[8192]; - char bps[8192]; - char ips[8192]; - char remapfile[8192]; - } name; - - /* Recording. */ - struct - { - char path[8192]; - char config[8192]; - unsigned width; - unsigned height; - - size_t gpu_width; - size_t gpu_height; - char output_dir[8192]; - char config_dir[8192]; - bool use_output_dir; - } record; - - /* Settings and/or global state that is specific to - * a console-style implementation. */ - struct - { - struct - { - struct - { - rarch_resolution_t current; - rarch_resolution_t initial; - uint32_t *list; - unsigned count; - bool check; - } resolutions; - - unsigned gamma_correction; - unsigned int flicker_filter_index; - unsigned char soft_filter_index; - bool pal_enable; - bool pal60_enable; - } screen; - - struct - { - bool system_bgm_enable; - } sound; - - bool flickerfilter_enable; - bool softfilter_enable; - } console; -} global_t; - -global_t *global_get_ptr(void); - -/** - * runloop_iterate: - * - * Run Libretro core in RetroArch for one frame. - * - * Returns: 0 on successful run, - * Returns 1 if we have to wait until button input in order - * to wake up the loop. - * Returns -1 if we forcibly quit out of the - * RetroArch iteration loop. - **/ -int runloop_iterate(unsigned *sleep_ms); - -void runloop_msg_queue_push(const char *msg, unsigned prio, - unsigned duration, bool flush); - -bool runloop_msg_queue_pull(const char **ret); - -void runloop_get_status(bool *is_paused, bool *is_idle, bool *is_slowmotion, - bool *is_perfcnt_enable); - -bool runloop_ctl(enum runloop_ctl_state state, void *data); - -void runloop_set(enum runloop_action action); - -void runloop_unset(enum runloop_action action); - -rarch_system_info_t *runloop_get_system_info(void); - -RETRO_END_DECLS - -#endif diff --git a/tasks/task_content.c b/tasks/task_content.c index 77caf2358b..600b0af1c9 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -85,7 +85,6 @@ #include "../msg_hash.h" #include "../content.h" #include "../dynamic.h" -#include "../runloop.h" #include "../retroarch.h" #include "../file_path_special.h" #include "../core.h" diff --git a/tasks/task_database.c b/tasks/task_database.c index 5a1b59ffb0..88eb8bc7cb 100644 --- a/tasks/task_database.c +++ b/tasks/task_database.c @@ -32,7 +32,7 @@ #include "../list_special.h" #include "../msg_hash.h" #include "../playlist.h" -#include "../runloop.h" +#include "../retroarch.h" #include "../verbosity.h" #include "../core_info.h" diff --git a/tasks/task_netplay_find_content.c b/tasks/task_netplay_find_content.c index 5f2fb6b226..3d5b6bb9a4 100644 --- a/tasks/task_netplay_find_content.c +++ b/tasks/task_netplay_find_content.c @@ -34,7 +34,7 @@ #include "../playlist.h" #include "../command.h" #include "../core_info.h" -#include "../../runloop.h" +#include "../../retroarch.h" typedef struct { diff --git a/tasks/task_screenshot.c b/tasks/task_screenshot.c index 84fff0873a..d739b1d9a9 100644 --- a/tasks/task_screenshot.c +++ b/tasks/task_screenshot.c @@ -50,7 +50,7 @@ #include "../defaults.h" #include "../configuration.h" -#include "../runloop.h" +#include "../retroarch.h" #include "../paths.h" #include "../msg_hash.h" diff --git a/ui/drivers/cocoa/cocoatouch_menu.m b/ui/drivers/cocoa/cocoatouch_menu.m index e65a058a68..31d0220f0d 100644 --- a/ui/drivers/cocoa/cocoatouch_menu.m +++ b/ui/drivers/cocoa/cocoatouch_menu.m @@ -30,7 +30,7 @@ #include "../../../input/drivers/cocoa_input.h" #include "../../../configuration.h" -#include "../../../runloop.h" +#include "../../../retroarch.h" #ifdef HAVE_MENU #include "../../../menu/widgets/menu_entry.h" diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index 913f94f5db..9031f1edde 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -34,7 +34,6 @@ #include "../../paths.h" #include "../../core.h" #include "../../retroarch.h" -#include "../../runloop.h" #include "../../tasks/tasks_internal.h" id apple_platform; diff --git a/ui/drivers/ui_cocoatouch.m b/ui/drivers/ui_cocoatouch.m index 1517502fc2..d6134f3da6 100644 --- a/ui/drivers/ui_cocoatouch.m +++ b/ui/drivers/ui_cocoatouch.m @@ -33,7 +33,7 @@ #endif #include "../../configuration.h" #include "../../frontend/frontend.h" -#include "../../runloop.h" +#include "../../retroarch.h" #ifdef HAVE_MENU #include "../../menu/menu_setting.h" diff --git a/ui/drivers/ui_qt.cpp b/ui/drivers/ui_qt.cpp index cdbce779f6..7f71aa121e 100644 --- a/ui/drivers/ui_qt.cpp +++ b/ui/drivers/ui_qt.cpp @@ -35,7 +35,7 @@ #include "../ui_companion_driver.h" #include "../../core.h" #include "../../configuration.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../tasks/tasks_internal.h" #ifdef HAVE_QT_WRAPPER diff --git a/ui/drivers/ui_win32.c b/ui/drivers/ui_win32.c index 81d17b6a63..dca9767f99 100644 --- a/ui/drivers/ui_win32.c +++ b/ui/drivers/ui_win32.c @@ -49,7 +49,7 @@ #include "../../configuration.h" #include "../../driver.h" #include "../../paths.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../gfx/video_driver.h" #include "../../gfx/video_shader_driver.h" #include "../../tasks/tasks_internal.h" diff --git a/ui/drivers/win32/ui_win32_window.cpp b/ui/drivers/win32/ui_win32_window.cpp index afa19a8346..8a0d1e981a 100644 --- a/ui/drivers/win32/ui_win32_window.cpp +++ b/ui/drivers/win32/ui_win32_window.cpp @@ -47,7 +47,7 @@ #include "../../ui_companion_driver.h" #include "../../../driver.h" -#include "../../../runloop.h" +#include "../../../retroarch.h" #include "../../../tasks/tasks_internal.h" static void ui_window_win32_destroy(void *data) diff --git a/wifi/drivers/connmanctl.c b/wifi/drivers/connmanctl.c index 5af68d2f4d..ddf6f7a6fc 100644 --- a/wifi/drivers/connmanctl.c +++ b/wifi/drivers/connmanctl.c @@ -19,7 +19,7 @@ #include #include "../wifi_driver.h" -#include "../../runloop.h" +#include "../../retroarch.h" #include "../../lakka.h" static bool connman_cache[256] = {0};