#define RARCH_TIMER_TICK(_timer, current_time) \ _timer.current = current_time; \ _timer.timeout_us = (_timer.timeout_end - _timer.current) \ #define RARCH_TIMER_END(_timer) \ _timer.timer_end = true; \ _timer.timer_begin = false; \ _timer.timeout_end = 0 #define RARCH_TIMER_BEGIN_NEW_TIME_USEC(_timer, current_usec, timeout_usec) \ _timer.timeout_us = timeout_usec; \ _timer.current = current_usec; \ _timer.timeout_end = _timer.current + _timer.timeout_us #define RARCH_TIMER_HAS_EXPIRED(_timer) ((_timer.timeout_us <= 0)) #define DRIVERS_CMD_ALL \ ( DRIVER_AUDIO_MASK \ | DRIVER_VIDEO_MASK \ | DRIVER_INPUT_MASK \ | DRIVER_CAMERA_MASK \ | DRIVER_LOCATION_MASK \ | DRIVER_MENU_MASK \ | DRIVERS_VIDEO_INPUT_MASK \ | DRIVER_BLUETOOTH_MASK \ | DRIVER_WIFI_MASK \ | DRIVER_LED_MASK \ | DRIVER_MIDI_MASK ) #define DRIVERS_CMD_ALL_BUT_MENU \ ( DRIVER_AUDIO_MASK \ | DRIVER_VIDEO_MASK \ | DRIVER_INPUT_MASK \ | DRIVER_CAMERA_MASK \ | DRIVER_LOCATION_MASK \ | DRIVERS_VIDEO_INPUT_MASK \ | DRIVER_BLUETOOTH_MASK \ | DRIVER_WIFI_MASK \ | DRIVER_LED_MASK \ | DRIVER_MIDI_MASK ) #define _PSUPP(var, name, desc) printf(" %s:\n\t\t%s: %s\n", name, desc, var ? "yes" : "no") #define FAIL_CPU(p_rarch, simd_type) do { \ RARCH_ERR(simd_type " code is compiled in, but CPU does not support this feature. Cannot continue.\n"); \ retroarch_fail(p_rarch, 1, "validate_cpu_features()"); \ } while (0) #ifdef HAVE_ZLIB #define DEFAULT_EXT "zip" #else #define DEFAULT_EXT "" #endif #define SHADER_FILE_WATCH_DELAY_MSEC 500 #define QUIT_DELAY_USEC 3 * 1000000 /* 3 seconds */ #define DEBUG_INFO_FILENAME "debug_info.txt" #define TIME_TO_FPS(last_time, new_time, frames) ((1000000.0f * (frames)) / ((new_time) - (last_time))) #define DEFAULT_NETWORK_GAMEPAD_PORT 55400 #define UDP_FRAME_PACKETS 16 #ifdef HAVE_BSV_MOVIE #define BSV_MOVIE_IS_EOF(p_rarch) || (input_st->bsv_movie_state.movie_end && \ input_st->bsv_movie_state.eof_exit) #else #define BSV_MOVIE_IS_EOF(p_rarch) #endif #define VIDEO_HAS_FOCUS(video_st) (video_st->current_video->focus ? (video_st->current_video->focus(video_st->data)) : true) #if HAVE_DYNAMIC #define RUNAHEAD_RUN_SECONDARY(p_rarch) \ if (!secondary_core_run_use_last_input(p_rarch)) \ p_rarch->runahead_secondary_core_available = false #endif #define RUNAHEAD_RESUME_VIDEO(p_rarch) \ if (video_st->runahead_is_active) \ video_st->active = true; \ else \ video_st->active = false #define _PSUPP_BUF(buf, var, name, desc) \ strlcat(buf, " ", sizeof(buf)); \ strlcat(buf, name, sizeof(buf)); \ strlcat(buf, ":\n\t\t", sizeof(buf)); \ strlcat(buf, desc, sizeof(buf)); \ strlcat(buf, ": ", sizeof(buf)); \ strlcat(buf, var ? "yes\n" : "no\n", sizeof(buf)) #define HOTKEY_CHECK(cmd1, cmd2, cond, cond2) \ { \ static bool old_pressed = false; \ bool pressed = BIT256_GET(current_bits, cmd1); \ if (pressed && !old_pressed) \ if (cond) \ command_event(cmd2, cond2); \ old_pressed = pressed; \ } #define HOTKEY_CHECK3(cmd1, cmd2, cmd3, cmd4, cmd5, cmd6) \ { \ static bool old_pressed = false; \ static bool old_pressed2 = false; \ static bool old_pressed3 = false; \ bool pressed = BIT256_GET(current_bits, cmd1); \ bool pressed2 = BIT256_GET(current_bits, cmd3); \ bool pressed3 = BIT256_GET(current_bits, cmd5); \ if (pressed && !old_pressed) \ command_event(cmd2, (void*)(intptr_t)0); \ else if (pressed2 && !old_pressed2) \ command_event(cmd4, (void*)(intptr_t)0); \ else if (pressed3 && !old_pressed3) \ command_event(cmd6, (void*)(intptr_t)0); \ old_pressed = pressed; \ old_pressed2 = pressed2; \ old_pressed3 = pressed3; \ } #define INHERIT_JOYAXIS(binds) (((binds)[x_plus].joyaxis == (binds)[x_minus].joyaxis) || ( (binds)[y_plus].joyaxis == (binds)[y_minus].joyaxis)) #define CDN_URL "https://cdn.discordapp.com/avatars" #ifdef HAVE_DYNAMIC #define SYMBOL(x) do { \ function_t func = dylib_proc(lib_handle_local, #x); \ memcpy(¤t_core->x, &func, sizeof(func)); \ if (!current_core->x) { RARCH_ERR("Failed to load symbol: \"%s\"\n", #x); retroarch_fail(p_rarch, 1, "init_libretro_symbols()"); } \ } while (0) #else #define SYMBOL(x) current_core->x = x #endif #define SYMBOL_DUMMY(x) current_core->x = libretro_dummy_##x #ifdef HAVE_FFMPEG #define SYMBOL_FFMPEG(x) current_core->x = libretro_ffmpeg_##x #endif #ifdef HAVE_MPV #define SYMBOL_MPV(x) current_core->x = libretro_mpv_##x #endif #ifdef HAVE_IMAGEVIEWER #define SYMBOL_IMAGEVIEWER(x) current_core->x = libretro_imageviewer_##x #endif #if defined(HAVE_NETWORKING) && defined(HAVE_NETWORKGAMEPAD) #define SYMBOL_NETRETROPAD(x) current_core->x = libretro_netretropad_##x #endif #if defined(HAVE_VIDEOPROCESSOR) #define SYMBOL_VIDEOPROCESSOR(x) current_core->x = libretro_videoprocessor_##x #endif #ifdef HAVE_GONG #define SYMBOL_GONG(x) current_core->x = libretro_gong_##x #endif #define CORE_SYMBOLS(x) \ x(retro_init); \ x(retro_deinit); \ x(retro_api_version); \ x(retro_get_system_info); \ x(retro_get_system_av_info); \ x(retro_set_environment); \ x(retro_set_video_refresh); \ x(retro_set_audio_sample); \ x(retro_set_audio_sample_batch); \ x(retro_set_input_poll); \ x(retro_set_input_state); \ x(retro_set_controller_port_device); \ x(retro_reset); \ x(retro_run); \ x(retro_serialize_size); \ x(retro_serialize); \ x(retro_unserialize); \ x(retro_cheat_reset); \ x(retro_cheat_set); \ x(retro_load_game); \ x(retro_load_game_special); \ x(retro_unload_game); \ x(retro_get_region); \ x(retro_get_memory_data); \ x(retro_get_memory_size); #define FFMPEG_RECORD_ARG "r:" #ifdef HAVE_DYNAMIC #define DYNAMIC_ARG "L:" #else #define DYNAMIC_ARG #endif #ifdef HAVE_NETWORKING #define NETPLAY_ARG "HC:F:" #else #define NETPLAY_ARG #endif #ifdef HAVE_CONFIGFILE #define CONFIG_FILE_ARG "c:" #else #define CONFIG_FILE_ARG #endif #ifdef HAVE_BSV_MOVIE #define BSV_MOVIE_ARG "P:R:M:" #else #define BSV_MOVIE_ARG #endif /* Griffin hack */ #ifdef HAVE_QT #ifndef HAVE_MAIN #define HAVE_MAIN #endif #endif #ifdef _WIN32 #define PERF_LOG_FMT "[PERF]: Avg (%s): %I64u ticks, %I64u runs.\n" #else #define PERF_LOG_FMT "[PERF]: Avg (%s): %llu ticks, %llu runs.\n" #endif /* DRIVERS */ #ifdef HAVE_VULKAN static const gfx_ctx_driver_t *gfx_ctx_vk_drivers[] = { #if defined(__APPLE__) &gfx_ctx_cocoavk, #endif #if defined(_WIN32) && !defined(__WINRT__) &gfx_ctx_w_vk, #endif #if defined(ANDROID) &gfx_ctx_vk_android, #endif #if defined(HAVE_WAYLAND) &gfx_ctx_vk_wayland, #endif #if defined(HAVE_X11) &gfx_ctx_vk_x, #endif #if defined(HAVE_VULKAN_DISPLAY) &gfx_ctx_khr_display, #endif &gfx_ctx_null, NULL }; #endif static const gfx_ctx_driver_t *gfx_ctx_gl_drivers[] = { #if defined(ORBIS) &orbis_ctx, #endif #if defined(HAVE_VITAGL) | defined(HAVE_VITAGLES) &vita_ctx, #endif #if !defined(__PSL1GHT__) && defined(__PS3__) &gfx_ctx_ps3, #endif #if defined(HAVE_LIBNX) && defined(HAVE_OPENGL) &switch_ctx, #endif #if defined(HAVE_VIDEOCORE) &gfx_ctx_videocore, #endif #if defined(HAVE_MALI_FBDEV) &gfx_ctx_mali_fbdev, #endif #if defined(HAVE_VIVANTE_FBDEV) &gfx_ctx_vivante_fbdev, #endif #if defined(HAVE_OPENDINGUX_FBDEV) &gfx_ctx_opendingux_fbdev, #endif #if defined(_WIN32) && !defined(__WINRT__) && (defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)) &gfx_ctx_wgl, #endif #if defined(__WINRT__) && defined(HAVE_OPENGLES) &gfx_ctx_uwp, #endif #if defined(HAVE_WAYLAND) &gfx_ctx_wayland, #endif #if defined(HAVE_X11) && !defined(HAVE_OPENGLES) #if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE) &gfx_ctx_x, #endif #endif #if defined(HAVE_X11) && defined(HAVE_OPENGL) && defined(HAVE_EGL) &gfx_ctx_x_egl, #endif #if defined(HAVE_KMS) #if defined(HAVE_ODROIDGO2) &gfx_ctx_go2_drm, #endif &gfx_ctx_drm, #endif #if defined(ANDROID) &gfx_ctx_android, #endif #if defined(__QNX__) &gfx_ctx_qnx, #endif #if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL) #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) &gfx_ctx_cocoagl, #endif #endif #if (defined(HAVE_SDL) || defined(HAVE_SDL2)) && (defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)) &gfx_ctx_sdl_gl, #endif #ifdef HAVE_OSMESA &gfx_ctx_osmesa, #endif #ifdef EMSCRIPTEN &gfx_ctx_emscripten, #endif &gfx_ctx_null, NULL }; static bluetooth_driver_t bluetooth_null = { NULL, /* init */ NULL, /* free */ NULL, /* scan */ NULL, /* get_devices */ NULL, /* device_is_connected */ NULL, /* device_get_sublabel */ NULL, /* connect_device */ "null", }; static const bluetooth_driver_t *bluetooth_drivers[] = { #ifdef HAVE_BLUETOOTH &bluetooth_bluetoothctl, #ifdef HAVE_DBUS &bluetooth_bluez, #endif #endif &bluetooth_null, NULL, }; static wifi_driver_t wifi_null = { NULL, /* init */ NULL, /* free */ NULL, /* start */ NULL, /* stop */ NULL, /* enable */ NULL, /* connection_info */ NULL, /* scan */ NULL, /* get_ssids */ NULL, /* ssid_is_online */ NULL, /* connect_ssid */ NULL, /* disconnect_ssid */ NULL, /* tether_start_stop */ "null", }; static const wifi_driver_t *wifi_drivers[] = { #ifdef HAVE_LAKKA &wifi_connmanctl, #endif #ifdef HAVE_WIFI &wifi_nmcli, #endif &wifi_null, NULL, }; static ui_companion_driver_t ui_companion_null = { NULL, /* init */ NULL, /* deinit */ NULL, /* toggle */ NULL, /* event_command */ NULL, /* notify_content_loaded */ NULL, /* notify_list_loaded */ NULL, /* notify_refresh */ NULL, /* msg_queue_push */ NULL, /* render_messagebox */ NULL, /* get_main_window */ NULL, /* log_msg */ NULL, /* is_active */ NULL, /* browser_window */ NULL, /* msg_window */ NULL, /* window */ NULL, /* application */ "null", /* ident */ }; static const ui_companion_driver_t *ui_companion_drivers[] = { #if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) &ui_companion_win32, #endif #if defined(OSX) &ui_companion_cocoa, #endif &ui_companion_null, NULL }; static const record_driver_t record_null = { NULL, /* new */ NULL, /* free */ NULL, /* push_video */ NULL, /* push_audio */ NULL, /* finalize */ "null", }; static const record_driver_t *record_drivers[] = { #ifdef HAVE_FFMPEG &record_ffmpeg, #endif &record_null, NULL, }; static void *nullcamera_init(const char *device, uint64_t caps, unsigned width, unsigned height) { return (void*)-1; } static void nullcamera_free(void *data) { } static void nullcamera_stop(void *data) { } static bool nullcamera_start(void *data) { return true; } static bool nullcamera_poll(void *a, retro_camera_frame_raw_framebuffer_t b, retro_camera_frame_opengl_texture_t c) { return true; } static camera_driver_t camera_null = { nullcamera_init, nullcamera_free, nullcamera_start, nullcamera_stop, nullcamera_poll, "null", }; static const camera_driver_t *camera_drivers[] = { #ifdef HAVE_V4L2 &camera_v4l2, #endif #ifdef EMSCRIPTEN &camera_rwebcam, #endif #ifdef ANDROID &camera_android, #endif &camera_null, NULL, }; /* MAIN GLOBAL VARIABLES */ /* Descriptive names for options without short variant. * * Please keep the name in sync with the option name. * Order does not matter. */ enum { RA_OPT_MENU = 256, /* must be outside the range of a char */ RA_OPT_STATELESS, RA_OPT_CHECK_FRAMES, RA_OPT_PORT, RA_OPT_SPECTATE, RA_OPT_NICK, RA_OPT_COMMAND, RA_OPT_APPENDCONFIG, RA_OPT_BPS, RA_OPT_IPS, RA_OPT_NO_PATCH, RA_OPT_RECORDCONFIG, RA_OPT_SUBSYSTEM, RA_OPT_SIZE, RA_OPT_FEATURES, RA_OPT_VERSION, RA_OPT_EOF_EXIT, RA_OPT_LOG_FILE, RA_OPT_MAX_FRAMES, RA_OPT_MAX_FRAMES_SCREENSHOT, RA_OPT_MAX_FRAMES_SCREENSHOT_PATH, RA_OPT_SET_SHADER, RA_OPT_ACCESSIBILITY, RA_OPT_LOAD_MENU_ON_ERROR }; typedef void *(*constructor_t)(void); typedef void (*destructor_t )(void*); typedef struct my_list_t { void **data; constructor_t constructor; destructor_t destructor; int capacity; int size; } my_list; #ifdef HAVE_DISCORD /* The Discord API specifies these variables: - userId --------- char[24] - the userId of the player asking to join - username ------- char[344] - the username of the player asking to join - discriminator -- char[8] - the discriminator of the player asking to join - spectateSecret - char[128] - secret used for spectatin matches - joinSecret - char[128] - secret used to join matches - partyId - char[128] - the party you would be joining */ struct discord_state { int64_t start_time; int64_t pause_time; int64_t elapsed_time; DiscordRichPresence presence; /* int64_t alignment */ unsigned status; char self_party_id[128]; char peer_party_id[128]; char user_name[344]; char user_avatar[344]; bool ready; bool avatar_ready; bool connecting; }; typedef struct discord_state discord_state_t; #endif struct rarch_state { struct global g_extern; /* retro_time_t alignment */ #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) rarch_timer_t shader_delay_timer; /* int64_t alignment */ #endif #ifdef HAVE_DISCORD discord_state_t discord_st; /* int64_t alignment */ #endif #ifdef HAVE_RUNAHEAD uint64_t runahead_last_frame_count; #endif struct retro_camera_callback camera_cb; /* uint64_t alignment */ #if defined(HAVE_RUNAHEAD) #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) char *secondary_library_path; #endif retro_ctx_load_content_info_t *load_content_info; #endif const camera_driver_t *camera_driver; void *camera_data; const ui_companion_driver_t *ui_companion; void *ui_companion_data; #ifdef HAVE_QT void *ui_companion_qt_data; #endif const bluetooth_driver_t *bluetooth_driver; void *bluetooth_data; const wifi_driver_t *wifi_driver; void *wifi_data; settings_t *configuration_settings; #ifdef HAVE_NETWORKING /* Used while Netplay is running */ netplay_t *netplay_data; #endif #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) struct video_shader *menu_driver_shader; #endif frontend_ctx_driver_t *current_frontend_ctx; #ifdef HAVE_RUNAHEAD my_list *runahead_save_state_list; my_list *input_state_list; #endif struct retro_perf_counter *perf_counters_rarch[MAX_COUNTERS]; struct retro_perf_counter *perf_counters_libretro[MAX_COUNTERS]; #ifdef HAVE_REWIND struct state_manager_rewind_state rewind_st; #endif content_state_t content_st; /* ptr alignment */ #ifdef HAVE_NETWORKING struct netplay_room netplay_host_room; /* ptr alignment */ #endif #ifdef HAVE_DYNAMIC dylib_t lib_handle; /* ptr alignment */ #endif #if defined(HAVE_RUNAHEAD) #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) dylib_t secondary_lib_handle; /* ptr alignment */ #endif size_t runahead_save_state_size; #endif jmp_buf error_sjlj_context; /* 4-byte alignment, put it right before long */ #if defined(HAVE_COMMAND) #ifdef HAVE_NETWORK_CMD int lastcmd_net_fd; #endif #endif #if defined(HAVE_RUNAHEAD) #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) int port_map[MAX_USERS]; #endif #endif #if defined(HAVE_TRANSLATE) int ai_service_auto; #if defined(HAVE_ACCESSIBILITY) int ai_gamepad_state[MAX_USERS]; #endif #endif #ifdef HAVE_NETWORKING int reannounce; #endif #ifdef HAVE_THREAD_STORAGE sthread_tls_t rarch_tls; /* unsigned alignment */ #endif #ifdef HAVE_NETWORKING unsigned server_port_deferred; #endif unsigned perf_ptr_rarch; unsigned perf_ptr_libretro; #if defined(HAVE_COMMAND) enum cmd_source_t lastcmd_source; #endif #if defined(HAVE_RUNAHEAD) enum rarch_core_type last_core_type; #endif retro_bits_t has_set_libretro_device; /* uint32_t alignment */ char error_string[255]; #ifdef HAVE_NETWORKING char server_address_deferred[512]; #endif char launch_arguments[4096]; #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) char cli_shader[PATH_MAX_LENGTH]; #endif char path_default_shader_preset[PATH_MAX_LENGTH]; char path_content[PATH_MAX_LENGTH]; char path_libretro[PATH_MAX_LENGTH]; char path_config_file[PATH_MAX_LENGTH]; char path_config_append_file[256]; char path_core_options_file[PATH_MAX_LENGTH]; char dir_system[PATH_MAX_LENGTH]; char dir_savefile[PATH_MAX_LENGTH]; char current_savefile_dir[PATH_MAX_LENGTH]; char current_savestate_dir[PATH_MAX_LENGTH]; char dir_savestate[PATH_MAX_LENGTH]; #ifdef HAVE_NETWORKING /* Only used before init_netplay */ bool netplay_enabled; bool netplay_is_client; /* Used to avoid recursive netplay calls */ bool in_netplay; bool netplay_client_deferred; bool is_mitm; #endif bool has_set_username; bool rarch_error_on_init; bool has_set_verbosity; bool has_set_libretro; bool has_set_libretro_directory; bool has_set_save_path; bool has_set_state_path; #ifdef HAVE_PATCH bool has_set_ups_pref; bool has_set_bps_pref; bool has_set_ips_pref; #endif #ifdef HAVE_QT bool qt_is_inited; #endif bool has_set_log_to_file; bool rarch_is_inited; bool rarch_ups_pref; bool rarch_bps_pref; bool rarch_ips_pref; #ifdef HAVE_PATCH bool rarch_patch_blocked; #endif #ifdef HAVE_ACCESSIBILITY /* Is text-to-speech accessibility turned on? */ bool accessibility_enabled; #endif #ifdef HAVE_CONFIGFILE bool rarch_block_config_read; #endif #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) bool cli_shader_disable; #endif bool location_driver_active; bool bluetooth_driver_active; bool wifi_driver_active; bool camera_driver_active; #ifdef HAVE_RUNAHEAD bool runahead_save_state_size_known; bool request_fast_savestate; #endif #if defined(HAVE_NETWORKING) bool has_set_netplay_mode; bool has_set_netplay_ip_address; bool has_set_netplay_ip_port; bool has_set_netplay_stateless_mode; bool has_set_netplay_check_frames; #endif bool streaming_enable; bool main_ui_companion_is_on_foreground; #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) bool shader_presets_need_reload; #endif #ifdef HAVE_RUNAHEAD bool runahead_available; bool runahead_secondary_core_available; bool runahead_force_input_dirty; #endif };