static bool find_first_libretro(char *path, size_t size, const char *dir, const char *rom_path) { bool ret = false; const char *ext = path_get_extension(rom_path); if (!ext || !*ext) { RARCH_ERR("Path has no extension. Cannot infer libretro implementation.\n"); return false; } RARCH_LOG("Searching for valid libretro implementation in: \"%s\".\n", dir); struct string_list *list = dir_list_new(dir, DYNAMIC_EXT, false); if (!list) { RARCH_ERR("Couldn't open directory: \"%s\".\n", dir); return false; } for (size_t i = 0; i < list->size && !ret; i++) { RARCH_LOG("Checking library: \"%s\".\n", list->elems[i].data); dylib_t lib = dylib_load(list->elems[i].data); if (!lib) continue; void (*proc)(struct retro_system_info*) = (void (*)(struct retro_system_info*))dylib_proc(lib, "retro_get_system_info"); if (!proc) { dylib_close(lib); continue; } struct retro_system_info info = {0}; proc(&info); if (!info.valid_extensions) { dylib_close(lib); continue; } struct string_list *supported_ext = string_split(info.valid_extensions, "|"); if (string_list_find_elem(supported_ext, ext)) { strlcpy(path, list->elems[i].data, size); ret = true; } string_list_free(supported_ext); dylib_close(lib); } dir_list_free(list); return ret; }
static bool append_softfilter_plugs(rarch_softfilter_t *filt, struct string_list *list) { unsigned i; softfilter_simd_mask_t mask = retro_get_cpu_features(); for (i = 0; i < list->size; i++) { softfilter_get_implementation_t cb; const struct softfilter_implementation *impl = NULL; struct rarch_soft_plug *new_plugs = NULL; dylib_t lib = dylib_load(list->elems[i].data); if (!lib) continue; cb = (softfilter_get_implementation_t) dylib_proc(lib, "softfilter_get_implementation"); if (!cb) { dylib_close(lib); continue; } impl = cb(mask); if (!impl) { dylib_close(lib); continue; } if (impl->api_version != SOFTFILTER_API_VERSION) { dylib_close(lib); continue; } new_plugs = (struct rarch_soft_plug*) realloc(filt->plugs, sizeof(*filt->plugs) * (filt->num_plugs + 1)); if (!new_plugs) { dylib_close(lib); return false; } RARCH_LOG("[SoftFilter]: Found plug: %s (%s).\n", impl->ident, impl->short_ident); filt->plugs = new_plugs; filt->plugs[filt->num_plugs].lib = lib; filt->plugs[filt->num_plugs].impl = impl; filt->num_plugs++; } return true; }
static void gfx_dwm_shutdown(void) { #ifdef HAVE_DYNAMIC if (dwmlib) dylib_close(dwmlib); if (shell32lib) dylib_close(shell32lib); dwmlib = NULL; shell32lib = NULL; #endif }
static bool append_plugs(rarch_dsp_filter_t *dsp, struct string_list *list) { unsigned i; dspfilter_simd_mask_t mask = rarch_get_cpu_features(); for (i = 0; i < list->size; i++) { const struct dspfilter_implementation *impl = NULL; struct rarch_dsp_plug *new_plugs = NULL; dylib_t lib = dylib_load(list->elems[i].data); if (!lib) continue; dspfilter_get_implementation_t cb = (dspfilter_get_implementation_t) dylib_proc(lib, "dspfilter_get_implementation"); if (!cb) { dylib_close(lib); continue; } impl = cb(mask); if (!impl) { dylib_close(lib); continue; } if (impl->api_version != DSPFILTER_API_VERSION) { dylib_close(lib); continue; } new_plugs = (struct rarch_dsp_plug*) realloc(dsp->plugs, sizeof(*dsp->plugs) * (dsp->num_plugs + 1)); if (!new_plugs) { dylib_close(lib); return false; } /* Found plug. */ dsp->plugs = new_plugs; dsp->plugs[dsp->num_plugs].lib = lib; dsp->plugs[dsp->num_plugs].impl = impl; dsp->num_plugs++; } return true; }
void d3d9_deinitialize_symbols(void) { #ifdef HAVE_DYNAMIC_D3D if (g_d3d9_dll) dylib_close(g_d3d9_dll); #ifdef HAVE_D3DX if (g_d3d9x_dll) dylib_close(g_d3d9x_dll); g_d3d9x_dll = NULL; #endif g_d3d9_dll = NULL; d3d9_dylib_initialized = false; #endif }
void rarch_dsp_filter_free(rarch_dsp_filter_t *dsp) { unsigned i; if (!dsp) return; for (i = 0; i < dsp->num_instances; i++) { if (dsp->instances[i].impl_data && dsp->instances[i].impl) dsp->instances[i].impl->free(dsp->instances[i].impl_data); } free(dsp->instances); #ifdef HAVE_DYLIB for (i = 0; i < dsp->num_plugs; i++) { if (dsp->plugs[i].lib) dylib_close(dsp->plugs[i].lib); } free(dsp->plugs); #endif if (dsp->conf) config_file_free(dsp->conf); free(dsp); }
static dylib_t libretro_get_system_info_lib(const char *path, struct retro_system_info *info, bool *load_no_rom) { dylib_t lib = dylib_load(path); if (!lib) return NULL; void (*proc)(struct retro_system_info*) = (void (*)(struct retro_system_info*))dylib_proc(lib, "retro_get_system_info"); if (!proc) { dylib_close(lib); return NULL; } proc(info); if (load_no_rom) { *load_no_rom = false; void (*set_environ)(retro_environment_t) = (void (*)(retro_environment_t))dylib_proc(lib, "retro_set_environment"); if (!set_environ) return lib; libretro_get_environment_info(set_environ, load_no_rom); } return lib; }
void rarch_softfilter_free(rarch_softfilter_t *filt) { unsigned i; i = 0; (void)i; if (!filt) return; free(filt->packets); if (filt->impl && filt->impl_data) filt->impl->destroy(filt->impl_data); #if !defined(HAVE_FILTERS_BUILTIN) && defined(HAVE_DYLIB) if (filt->lib) dylib_close(filt->lib); #endif #ifdef HAVE_THREADS for (i = 0; i < filt->threads; i++) { if (!filt->thread_data[i].thread) continue; slock_lock(filt->thread_data[i].lock); filt->thread_data[i].die = true; scond_signal(filt->thread_data[i].cond); slock_unlock(filt->thread_data[i].lock); sthread_join(filt->thread_data[i].thread); slock_free(filt->thread_data[i].lock); scond_free(filt->thread_data[i].cond); } free(filt->thread_data); #endif free(filt); }
void uninit_libretro_sym(void) { #ifdef HAVE_DYNAMIC if (lib_handle) dylib_close(lib_handle); #endif }
static void deinit_dsp_plugin(void) { if (g_extern.audio_data.dsp_lib && g_extern.audio_data.dsp_plugin) { g_extern.audio_data.dsp_plugin->free(g_extern.audio_data.dsp_handle); dylib_close(g_extern.audio_data.dsp_lib); } }
static void init_dsp_plugin(void) { if (!(*g_settings.audio.dsp_plugin)) return; rarch_dsp_info_t info = {0}; g_extern.audio_data.dsp_lib = dylib_load(g_settings.audio.dsp_plugin); if (!g_extern.audio_data.dsp_lib) { RARCH_ERR("Failed to open DSP plugin: \"%s\" ...\n", g_settings.audio.dsp_plugin); return; } const rarch_dsp_plugin_t* (RARCH_API_CALLTYPE *plugin_init)(void) = (const rarch_dsp_plugin_t *(RARCH_API_CALLTYPE*)(void))dylib_proc(g_extern.audio_data.dsp_lib, "rarch_dsp_plugin_init"); if (!plugin_init) { RARCH_ERR("Failed to find symbol \"rarch_dsp_plugin_init\" in DSP plugin.\n"); goto error; } g_extern.audio_data.dsp_plugin = plugin_init(); if (!g_extern.audio_data.dsp_plugin) { RARCH_ERR("Failed to get a valid DSP plugin.\n"); goto error; } if (g_extern.audio_data.dsp_plugin->api_version != RARCH_DSP_API_VERSION) { RARCH_ERR("DSP plugin API mismatch. RetroArch: %d, Plugin: %d\n", RARCH_DSP_API_VERSION, g_extern.audio_data.dsp_plugin->api_version); goto error; } RARCH_LOG("Loaded DSP plugin: \"%s\"\n", g_extern.audio_data.dsp_plugin->ident ? g_extern.audio_data.dsp_plugin->ident : "Unknown"); info.input_rate = g_settings.audio.in_rate; g_extern.audio_data.dsp_handle = g_extern.audio_data.dsp_plugin->init(&info); if (!g_extern.audio_data.dsp_handle) { RARCH_ERR("Failed to init DSP plugin.\n"); goto error; } return; error: if (g_extern.audio_data.dsp_lib) dylib_close(g_extern.audio_data.dsp_lib); g_extern.audio_data.dsp_plugin = NULL; g_extern.audio_data.dsp_lib = NULL; }
static void audio_ext_free(void *data) { audio_ext_t *ext = (audio_ext_t*)data; if (ext) { if (ext->driver && ext->handle) ext->driver->free(ext->handle); if (ext->lib) dylib_close(ext->lib); free(ext); } }
bool libretro_get_system_info(const char *path, struct retro_system_info *info, bool *load_no_rom) { struct retro_system_info dummy_info = {0}; dylib_t lib = libretro_get_system_info_lib(path, &dummy_info, load_no_rom); if (!lib) return false; memcpy(info, &dummy_info, sizeof(*info)); info->library_name = strdup(dummy_info.library_name); info->library_version = strdup(dummy_info.library_version); if (dummy_info.valid_extensions) info->valid_extensions = strdup(dummy_info.valid_extensions); dylib_close(lib); return true; }
void uninit_libretro_sym(void) { #ifdef HAVE_DYNAMIC if (lib_handle) dylib_close(lib_handle); lib_handle = NULL; #endif if (g_extern.system.core_options) { core_option_flush(g_extern.system.core_options); core_option_free(g_extern.system.core_options); } // No longer valid. memset(&g_extern.system, 0, sizeof(g_extern.system)); }
static void xinput_joypad_destroy(void) { unsigned i; for (i = 0; i < 4; ++i) memset(&g_xinput_states[i], 0, sizeof(xinput_joypad_state)); dylib_close(g_xinput_dll); g_xinput_dll = NULL; g_XInputGetStateEx = NULL; g_XInputSetState = NULL; dinput_joypad.destroy(); g_xinput_block_pads = false; }
/** * uninit_libretro_sym: * * Frees libretro core. * * Frees all core options, * associated state, and * unbind all libretro callback symbols. **/ void uninit_libretro_sym(void) { driver_t *driver = driver_get_ptr(); #ifdef HAVE_DYNAMIC if (lib_handle) dylib_close(lib_handle); lib_handle = NULL; #endif pretro_init = NULL; pretro_deinit = NULL; pretro_api_version = NULL; pretro_get_system_info = NULL; pretro_get_system_av_info = NULL; pretro_set_environment = NULL; pretro_set_video_refresh = NULL; pretro_set_audio_sample = NULL; pretro_set_audio_sample_batch = NULL; pretro_set_input_poll = NULL; pretro_set_input_state = NULL; pretro_set_controller_port_device = NULL; pretro_reset = NULL; pretro_run = NULL; pretro_serialize_size = NULL; pretro_serialize = NULL; pretro_unserialize = NULL; pretro_cheat_reset = NULL; pretro_cheat_set = NULL; pretro_load_game = NULL; pretro_load_game_special = NULL; pretro_unload_game = NULL; pretro_get_region = NULL; pretro_get_memory_data = NULL; pretro_get_memory_size = NULL; rarch_system_info_free(); driver->camera_active = false; driver->location_active = false; /* Performance counters no longer valid. */ retro_perf_clear(); }
static void video_ext_free(void *data) { ext_t *ext = (ext_t*)data; if (ext) { if (ext->driver && ext->handle) ext->driver->free(ext->handle); if (g_input_dead) { dylib_close(g_lib); g_lib = NULL; } g_video_dead = true; free(ext); } }
/** * uninit_libretro_sym: * * Frees libretro core. * * Frees all core options, * associated state, and * unbind all libretro callback symbols. **/ void uninit_libretro_sym(struct retro_core_t *current_core) { #ifdef HAVE_DYNAMIC if (lib_handle) dylib_close(lib_handle); lib_handle = NULL; #endif memset(current_core, 0, sizeof(struct retro_core_t)); runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_DEINIT, NULL); runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_FREE, NULL); runloop_ctl(RUNLOOP_CTL_FRAME_TIME_FREE, NULL); camera_driver_ctl(RARCH_CAMERA_CTL_UNSET_ACTIVE, NULL); location_driver_ctl(RARCH_LOCATION_CTL_UNSET_ACTIVE, NULL); /* Performance counters no longer valid. */ performance_counters_clear(); }
static bool btstack_try_load(void) { #ifdef HAVE_DYNAMIC unsigned i; #endif void *handle = NULL; if (btstack_tested) return btstack_loaded; btstack_tested = true; btstack_loaded = false; handle = btstack_get_handle(); if (!handle) return false; #ifdef HAVE_DYNAMIC for (i = 0; grabbers[i].name; i ++) { *grabbers[i].target = dylib_proc(handle, grabbers[i].name); if (!*grabbers[i].target) { dylib_close(handle); return false; } } #endif #if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) run_loop_init_ptr(RUN_LOOP_COCOA); #else run_loop_init_ptr(RUN_LOOP_POSIX); #endif bt_register_packet_handler_ptr(btpad_packet_handler); btstack_loaded = true; return true; }
static dylib_t libretro_get_system_info_lib(const char *path, struct retro_system_info *info, bool *load_no_content) { dylib_t lib = dylib_load(path); void (*proc)(struct retro_system_info*); if (!lib) { RARCH_ERR("%s: \"%s\"\n", msg_hash_to_str(MSG_FAILED_TO_OPEN_LIBRETRO_CORE), path); RARCH_ERR("Error(s): %s\n", dylib_error()); return NULL; } proc = (void (*)(struct retro_system_info*)) dylib_proc(lib, "retro_get_system_info"); if (!proc) { dylib_close(lib); return NULL; } proc(info); if (load_no_content) { void (*set_environ)(retro_environment_t); *load_no_content = false; set_environ = (void (*)(retro_environment_t)) dylib_proc(lib, "retro_set_environment"); if (!set_environ) return lib; libretro_get_environment_info(set_environ, load_no_content); } return lib; }
/** * uninit_libretro_sym: * * Frees libretro core. * * Frees all core options, * associated state, and * unbind all libretro callback symbols. **/ void uninit_libretro_sym(void) { #ifdef HAVE_DYNAMIC if (lib_handle) dylib_close(lib_handle); lib_handle = NULL; #endif core.retro_init = NULL; core.retro_deinit = NULL; core.retro_api_version = NULL; core.retro_get_system_info = NULL; core.retro_get_system_av_info = NULL; core.retro_set_environment = NULL; core.retro_set_video_refresh = NULL; core.retro_set_audio_sample = NULL; core.retro_set_audio_sample_batch = NULL; core.retro_set_input_poll = NULL; core.retro_set_input_state = NULL; core.retro_set_controller_port_device = NULL; core.retro_reset = NULL; core.retro_run = NULL; core.retro_serialize_size = NULL; core.retro_serialize = NULL; core.retro_unserialize = NULL; core.retro_cheat_reset = NULL; core.retro_cheat_set = NULL; core.retro_load_game = NULL; core.retro_load_game_special = NULL; core.retro_unload_game = NULL; core.retro_get_region = NULL; core.retro_get_memory_data = NULL; core.retro_get_memory_size = NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_FREE, NULL); camera_driver_ctl(RARCH_CAMERA_CTL_UNSET_ACTIVE, NULL); location_driver_ctl(RARCH_LOCATION_CTL_UNSET_ACTIVE, NULL); /* Performance counters no longer valid. */ retro_perf_clear(); }
static dylib_t libretro_get_system_info_lib(const char *path, struct retro_system_info *info, bool *load_no_content) { dylib_t lib = dylib_load(path); void (*proc)(struct retro_system_info*); if (!lib) { RARCH_ERR("Failed to open libretro core: \"%s\"\n", path); RARCH_ERR("Error(s): %s\n", dylib_error()); return NULL; } proc = (void (*)(struct retro_system_info*)) dylib_proc(lib, "retro_get_system_info"); if (!proc) { dylib_close(lib); return NULL; } proc(info); if (load_no_content) { void (*set_environ)(retro_environment_t); *load_no_content = false; set_environ = (void (*)(retro_environment_t)) dylib_proc(lib, "retro_set_environment"); if (!set_environ) return lib; libretro_get_environment_info(set_environ, load_no_content); } return lib; }
/** * libretro_get_system_info: * @path : Path to libretro library. * @info : Pointer to system info information. * @load_no_content : If true, core should be able to auto-start * without any content loaded. * * Gets system info from an arbitrary lib. * The struct returned must be freed as strings are allocated dynamically. * * Returns: true (1) if successful, otherwise false (0). **/ bool libretro_get_system_info(const char *path, struct retro_system_info *info, bool *load_no_content) { #ifdef HAVE_DYNAMIC struct retro_system_info dummy_info = {0}; dylib_t lib = libretro_get_system_info_lib(path, &dummy_info, load_no_content); if (!lib) return false; memcpy(info, &dummy_info, sizeof(*info)); info->library_name = strdup(dummy_info.library_name); info->library_version = strdup(dummy_info.library_version); if (dummy_info.valid_extensions) info->valid_extensions = strdup(dummy_info.valid_extensions); dylib_close(lib); #else if (!libretro_get_system_info_static(info, load_no_content)) return false; #endif return true; }
static bool xinput_joypad_init(void) { unsigned i, autoconf_pad; XINPUT_STATE dummy_state; const char *version = "1.4"; settings_t *settings = config_get_ptr(); g_xinput_dll = NULL; /* Find the correct path to load the DLL from. * Usually this will be from the system directory, * but occasionally a user may wish to use a third-party * wrapper DLL (such as x360ce); support these by checking * the working directory first. * * No need to check for existance as we will be checking dylib_load's * success anyway. */ /* Using dylib_* complicates building joyconfig. */ g_xinput_dll = (HINSTANCE)dylib_load("xinput1_4.dll"); if (!g_xinput_dll) { g_xinput_dll = (HINSTANCE)dylib_load("xinput1_3.dll"); version = "1.3"; } if (!g_xinput_dll) { RARCH_ERR("Failed to load XInput, ensure DirectX and controller drivers are up to date.\n"); return false; } RARCH_LOG("Found XInput v%s.\n", version); /* If we get here then an xinput DLL is correctly loaded. * First try to load ordinal 100 (XInputGetStateEx). */ g_XInputGetStateEx = (XInputGetStateEx_t)dylib_proc(g_xinput_dll, (const char*)100); g_xinput_guide_button_supported = true; if (!g_XInputGetStateEx) { /* no ordinal 100. (Presumably a wrapper.) Load the ordinary * XInputGetState, at the cost of losing guide button support. */ g_xinput_guide_button_supported = false; g_XInputGetStateEx = (XInputGetStateEx_t)dylib_proc(g_xinput_dll, "XInputGetState"); if (!g_XInputGetStateEx) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); dylib_close(g_xinput_dll); return false; /* DLL was loaded but did not contain the correct function. */ } RARCH_WARN("XInput: No guide button support.\n"); } g_XInputSetState = (XInputSetState_t)dylib_proc(g_xinput_dll, "XInputSetState"); if (!g_XInputSetState) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); dylib_close(g_xinput_dll); return false; /* DLL was loaded but did not contain the correct function. */ } /* Zero out the states. */ for (i = 0; i < 4; ++i) memset(&g_xinput_states[i], 0, sizeof(xinput_joypad_state)); /* Do a dummy poll to check which controllers are connected. */ for (i = 0; i < 4; ++i) { g_xinput_states[i].connected = !(g_XInputGetStateEx(i, &dummy_state) == ERROR_DEVICE_NOT_CONNECTED); if (g_xinput_states[i].connected) RARCH_LOG("Found XInput controller, user #%u\n", i); } if ((!g_xinput_states[0].connected) && (!g_xinput_states[1].connected) && (!g_xinput_states[2].connected) && (!g_xinput_states[3].connected)) return false; g_xinput_block_pads = true; /* We're going to have to be buddies with dinput if we want to be able * to use XInput and non-XInput controllers together. */ if (!dinput_joypad.init()) { g_xinput_block_pads = false; return false; } for (autoconf_pad = 0; autoconf_pad < MAX_USERS; autoconf_pad++) { if (pad_index_to_xuser_index(autoconf_pad) > -1) { autoconfig_params_t params = {{0}}; strlcpy(settings->input.device_names[autoconf_pad], xinput_joypad_name(autoconf_pad), sizeof(settings->input.device_names[autoconf_pad])); /* TODO - implement VID/PID? */ params.idx = autoconf_pad; strlcpy(params.name, xinput_joypad_name(autoconf_pad), sizeof(params.name)); strlcpy(params.driver, xinput_joypad.ident, sizeof(params.driver)); input_config_autoconfigure_joypad(¶ms); } } return true; }
static void gfx_dwm_shutdown(void) { if (dwmlib) dylib_close(dwmlib); dwmlib = NULL; }
static void gfx_ctx_wgl_destroy(void *data) { HWND window = win32_get_window(); gfx_ctx_wgl_data_t *wgl = (gfx_ctx_wgl_data_t*)data; switch (win32_api) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL if (win32_hrc) { glFinish(); wglMakeCurrent(NULL, NULL); if (!video_driver_is_video_cache_context()) { if (win32_hw_hrc) wglDeleteContext(win32_hw_hrc); wglDeleteContext(win32_hrc); win32_hrc = NULL; win32_hw_hrc = NULL; } } #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN vulkan_context_destroy(&win32_vk, win32_vk.vk_surface != VK_NULL_HANDLE); if (win32_vk.context.queue_lock) slock_free(win32_vk.context.queue_lock); memset(&win32_vk, 0, sizeof(win32_vk)); #endif break; case GFX_CTX_NONE: default: break; } if (window && win32_hdc) { ReleaseDC(window, win32_hdc); win32_hdc = NULL; } if (window) { win32_monitor_from_window(); win32_destroy_window(); } if (g_win32_restore_desktop) { win32_monitor_get_info(); g_win32_restore_desktop = false; } #ifdef HAVE_DYNAMIC dylib_close(dll_handle); #endif if (wgl) free(wgl); wgl_adaptive_vsync = false; win32_core_hw_context_enable = false; g_win32_inited = false; win32_major = 0; win32_minor = 0; p_swap_interval = NULL; }