const char *path_get(enum rarch_path_type type) { switch (type) { case RARCH_PATH_CONTENT: return path_content; case RARCH_PATH_DEFAULT_SHADER_PRESET: return path_default_shader_preset; case RARCH_PATH_BASENAME: return path_main_basename; case RARCH_PATH_CORE_OPTIONS: if (!path_is_empty(RARCH_PATH_CORE_OPTIONS)) return path_core_options_file; break; case RARCH_PATH_SUBSYSTEM: return subsystem_path; case RARCH_PATH_CONFIG: if (!path_is_empty(RARCH_PATH_CONFIG)) return path_config_file; break; case RARCH_PATH_CONFIG_APPEND: if (!path_is_empty(RARCH_PATH_CONFIG_APPEND)) return path_config_append_file; break; case RARCH_PATH_CORE: return path_libretro; case RARCH_PATH_NONE: case RARCH_PATH_NAMES: break; } return NULL; }
static void menu_content_environment_get(int *argc, char *argv[], void *args, void *params_data) { struct rarch_main_wrap *wrap_args = (struct rarch_main_wrap*)params_data; if (!wrap_args) return; wrap_args->no_content = menu_driver_ctl( RARCH_MENU_CTL_HAS_LOAD_NO_CONTENT, NULL); if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_VERBOSITY, NULL)) wrap_args->verbose = verbosity_is_enabled(); wrap_args->touched = true; wrap_args->config_path = NULL; wrap_args->sram_path = NULL; wrap_args->state_path = NULL; wrap_args->content_path = NULL; if (!path_is_empty(RARCH_PATH_CONFIG)) wrap_args->config_path = path_get(RARCH_PATH_CONFIG); if (!dir_is_empty(RARCH_DIR_SAVEFILE)) wrap_args->sram_path = dir_get(RARCH_DIR_SAVEFILE); if (!dir_is_empty(RARCH_DIR_SAVESTATE)) wrap_args->state_path = dir_get(RARCH_DIR_SAVESTATE); if (!path_is_empty(RARCH_PATH_CONTENT)) wrap_args->content_path = path_get(RARCH_PATH_CONTENT); if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_LIBRETRO, NULL)) wrap_args->libretro_path = string_is_empty(path_get(RARCH_PATH_CORE)) ? NULL : path_get(RARCH_PATH_CORE); }
static bool init_content_file_set_attribs( struct string_list *temporary_content, struct string_list *content, const struct retro_subsystem_info *special) { union string_list_elem_attr attr; struct string_list *subsystem = path_get_subsystem_list(); attr.i = 0; if (!path_is_empty(RARCH_PATH_SUBSYSTEM) && special) { unsigned i; for (i = 0; i < subsystem->size; i++) { attr.i = special->roms[i].block_extract; attr.i |= special->roms[i].need_fullpath << 1; attr.i |= special->roms[i].required << 2; string_list_append(content, subsystem->elems[i].data, attr); } } else { rarch_system_info_t *system = NULL; settings_t *settings = config_get_ptr(); runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (system) { attr.i = system->info.block_extract; attr.i |= system->info.need_fullpath << 1; } attr.i |= (!content_does_not_need_content()) << 2; if (path_is_empty(RARCH_PATH_CONTENT) && content_does_not_need_content() && settings->set_supports_no_game_enable) string_list_append(content, "", attr); else { if (!path_is_empty(RARCH_PATH_CONTENT)) string_list_append(content, path_get(RARCH_PATH_CONTENT), attr); } } #ifdef HAVE_COMPRESSION /* Try to extract all content we're going to load if appropriate. */ init_content_file_extract(temporary_content, content, special, &attr); #endif return true; }
static bool content_file_init_set_attribs( struct string_list *content, const struct retro_subsystem_info *special, content_information_ctx_t *content_ctx, char **error_string) { union string_list_elem_attr attr; struct string_list *subsystem = path_get_subsystem_list(); attr.i = 0; if (!path_is_empty(RARCH_PATH_SUBSYSTEM) && special) { unsigned i; for (i = 0; i < subsystem->size; i++) { attr.i = special->roms[i].block_extract; attr.i |= special->roms[i].need_fullpath << 1; attr.i |= special->roms[i].required << 2; string_list_append(content, subsystem->elems[i].data, attr); } } else { attr.i = content_ctx->block_extract; attr.i |= content_ctx->need_fullpath << 1; attr.i |= (!content_does_not_need_content()) << 2; if (path_is_empty(RARCH_PATH_CONTENT) && content_does_not_need_content() && content_ctx->set_supports_no_game_enable) string_list_append(content, "", attr); else { if (!path_is_empty(RARCH_PATH_CONTENT)) string_list_append(content, path_get(RARCH_PATH_CONTENT), attr); } } #ifdef HAVE_COMPRESSION /* Try to extract all content we're going to load if appropriate. */ content_file_init_extract(content, content_ctx, special, &attr, error_string); #endif return true; }
static const struct retro_subsystem_info *init_content_file_subsystem(bool *ret) { const struct retro_subsystem_info *special = NULL; rarch_system_info_t *system = NULL; struct string_list *subsystem = path_get_subsystem_list(); if (path_is_empty(RARCH_PATH_SUBSYSTEM)) { *ret = true; return NULL; } runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (system) special = libretro_find_subsystem_info(system->subsystem.data, system->subsystem.size, path_get(RARCH_PATH_SUBSYSTEM)); if (!special) { RARCH_ERR( "Failed to find subsystem \"%s\" in libretro implementation.\n", path_get(RARCH_PATH_SUBSYSTEM)); goto error; } if (special->num_roms && !subsystem) { RARCH_ERR("%s\n", msg_hash_to_str(MSG_ERROR_LIBRETRO_CORE_REQUIRES_SPECIAL_CONTENT)); goto error; } else if (special->num_roms && (special->num_roms != subsystem->size)) { RARCH_ERR("Libretro core requires %u content files for " "subsystem \"%s\", but %u content files were provided.\n", special->num_roms, special->desc, (unsigned)subsystem->size); goto error; } else if (!special->num_roms && subsystem && subsystem->size) { RARCH_ERR("Libretro core takes no content for subsystem \"%s\", " "but %u content files were provided.\n", special->desc, (unsigned)subsystem->size); goto error; } *ret = true; return special; error: *ret = false; return NULL; }
static void frontend_xdk_exec(const char *path, bool should_load_game) { #ifndef IS_SALAMANDER bool original_verbose = verbosity_is_enabled(); #endif #if defined(_XBOX1) LAUNCH_DATA ptr; #elif defined(_XBOX360) char game_path[1024] = {0}; #endif (void)should_load_game; #ifdef IS_SALAMANDER if (!string_is_empty(path)) XLaunchNewImage(path, NULL); #else #if defined(_XBOX1) memset(&ptr, 0, sizeof(ptr)); if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) snprintf((char*)ptr.Data, sizeof(ptr.Data), "%s", path_get(RARCH_PATH_CONTENT)); if (!string_is_empty(path)) XLaunchNewImage(path, !string_is_empty((const char*)ptr.Data) ? &ptr : NULL); #elif defined(_XBOX360) if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) { strlcpy(game_path, path_get(RARCH_PATH_CONTENT), sizeof(game_path)); XSetLaunchData(game_path, MAX_LAUNCH_DATA_SIZE); } if (!string_is_empty(path)) XLaunchNewImage(path, 0); #endif #endif #ifndef IS_SALAMANDER if (original_verbose) verbosity_enable(); else verbosity_disable(); #endif }
/** * content_init_file: * * Initializes and loads a content file for the currently * selected libretro core. * * Returns : true if successful, otherwise false. **/ static bool content_file_init( content_information_ctx_t *content_ctx, char **error_string) { struct retro_game_info *info = NULL; struct string_list *content = NULL; bool ret = path_is_empty(RARCH_PATH_SUBSYSTEM) ? true : false; const struct retro_subsystem_info *special = path_is_empty(RARCH_PATH_SUBSYSTEM) ? NULL : content_file_init_subsystem(content_ctx, error_string, &ret); if (!ret) goto error; content = string_list_new(); if (!content) goto error; if (!content_file_init_set_attribs(content, special, content_ctx, error_string)) goto error; info = (struct retro_game_info*) calloc(content->size, sizeof(*info)); if (info) { unsigned i; ret = content_file_load(info, content, content_ctx, error_string, special); for (i = 0; i < content->size; i++) free((void*)info[i].data); free(info); } error: if (content) string_list_free(content); return ret; }
static void frontend_wiiu_exec(const char *path, bool should_load_game) { struct { u32 magic; u32 argc; char * argv[3]; char args[]; }*param = getApplicationEndAddr(); int len = 0; param->argc = 0; if(!path || !*path) { RARCH_LOG("No executable path provided, cannot Restart\n"); } DEBUG_STR(path); strcpy(param->args + len, elf_path_cst); param->argv[param->argc] = param->args + len; len += strlen(param->args + len) + 1; param->argc++; RARCH_LOG("Attempt to load core: [%s].\n", path); #ifndef IS_SALAMANDER if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) { strcpy(param->args + len, path_get(RARCH_PATH_CONTENT)); param->argv[param->argc] = param->args + len; len += strlen(param->args + len) + 1; param->argc++; RARCH_LOG("content path: [%s].\n", path_get(RARCH_PATH_CONTENT)); } #endif param->argv[param->argc] = NULL; { if (HBL_loadToMemory(path, (u32)param->args - (u32)param + len) < 0) RARCH_LOG("Failed to load core\n"); else { param->magic = ARGV_MAGIC; ARGV_PTR = param; DEBUG_VAR(param->argc); DEBUG_VAR(param->argv); } } }
static void frontend_gx_process_args(int *argc, char *argv[]) { #ifndef IS_SALAMANDER /* A big hack: sometimes Salamander doesn't save the new core * it loads on first boot, so we make sure * active core path is set here. */ if (path_is_empty(RARCH_PATH_CORE) && *argc >= 1 && strrchr(argv[0], '/')) { char path[PATH_MAX_LENGTH] = {0}; strlcpy(path, strrchr(argv[0], '/') + 1, sizeof(path)); if (path_file_exists(path)) rarch_ctl(RARCH_CTL_SET_LIBRETRO_PATH, path); } #endif }
static boolean clean_path(Path * p, dBGraph * db_graph){ if(path_is_empty(p)){ return false; } boolean clean = true; pathStep last; path_get_last_step(&last, p); if(path_step_has_unvisited_edge_all_colours(&last)){ Nucleotide n = path_step_get_unvisited_edge_all_colours(&last); path_modfy_last_label(n, p); clean = false; } return clean; }
static void menu_action_setting_disp_set_label_configurations( file_list_t* list, unsigned *w, unsigned type, unsigned i, const char *label, char *s, size_t len, const char *entry_label, const char *path, char *s2, size_t len2) { *w = 19; strlcpy(s2, path, len2); if (!path_is_empty(RARCH_PATH_CONFIG)) fill_pathname_base(s, path_get(RARCH_PATH_CONFIG), len); else strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DIRECTORY_DEFAULT), len); }
void vgDrawPath(VGPath path, VGbitfield paintModes) { struct vg_context *ctx = vg_current_context(); if (path == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } if (!(paintModes & (VG_STROKE_PATH | VG_FILL_PATH))) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } if (path_is_empty((struct path*)path)) return; path_render((struct path*)path, paintModes); }
static void frontend_ps3_exec(const char *path, bool should_load_game) { #ifndef IS_SALAMANDER bool original_verbose = verbosity_is_enabled(); verbosity_enable(); #endif (void)should_load_game; RARCH_LOG("Attempt to load executable: [%s].\n", path); #ifndef IS_SALAMANDER if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) { char game_path[256]; strlcpy(game_path, path_get(RARCH_PATH_CONTENT), sizeof(game_path)); const char * const spawn_argv[] = { game_path, NULL }; frontend_ps3_exec_exitspawn(path, (const char** const)spawn_argv, NULL); } else #endif { frontend_ps3_exec_exitspawn(path, NULL, NULL); } sceNpTerm(); sys_net_finalize_network(); cellSysmoduleUnloadModule(CELL_SYSMODULE_SYSUTIL_NP); cellSysmoduleUnloadModule(CELL_SYSMODULE_NET); #ifndef IS_SALAMANDER if (original_verbose) verbosity_enable(); else verbosity_disable(); #endif }
static void frontend_psp_exec(const char *path, bool should_load_game) { #if defined(HAVE_KERNEL_PRX) || defined(IS_SALAMANDER) || defined(VITA) char argp[512] = {0}; SceSize args = 0; #if !defined(VITA) strlcpy(argp, eboot_path, sizeof(argp)); args = strlen(argp) + 1; #endif #ifndef IS_SALAMANDER if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) { argp[args] = '\0'; strlcat(argp + args, path_get(RARCH_PATH_CONTENT), sizeof(argp) - args); args += strlen(argp + args) + 1; } #endif RARCH_LOG("Attempt to load executable: [%s].\n", path); #if defined(VITA) RARCH_LOG("Attempt to load executable: %d [%s].\n", args, argp); int ret = sceAppMgrLoadExec(path, args==0? NULL : (char * const*)((const char*[]){argp, 0}), NULL);
static void frontend_ps2_exec(const char *path, bool should_load_game) { #if defined(IS_SALAMANDER) char argp[512] = {0}; SceSize args = 0; strlcpy(argp, eboot_path, sizeof(argp)); args = strlen(argp) + 1; #ifndef IS_SALAMANDER if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) { argp[args] = '\0'; strlcat(argp + args, path_get(RARCH_PATH_CONTENT), sizeof(argp) - args); args += strlen(argp + args) + 1; } #endif RARCH_LOG("Attempt to load executable: [%s].\n", path); #if 0 exitspawn_kernel(path, args, argp); /* I don't know what this is doing */ #endif #endif }
static boolean clean_path(Path * p, dBGraph * db_graph) { return !path_is_empty(p); }
/* Get the count of the files dropped */ static int win32_drag_query_file(HWND hwnd, WPARAM wparam) { char szFilename[1024]; szFilename[0] = '\0'; if (DragQueryFile((HDROP)wparam, 0xFFFFFFFF, NULL, 0)) { /*poll list of current cores */ size_t list_size; content_ctx_info_t content_info = {0}; core_info_list_t *core_info_list = NULL; const core_info_t *core_info = NULL; DragQueryFile((HDROP)wparam, 0, szFilename, sizeof(szFilename)); core_info_get_list(&core_info_list); if (!core_info_list) return 0; core_info_list_get_supported_cores(core_info_list, (const char*)szFilename, &core_info, &list_size); if (!list_size) return 0; path_set(RARCH_PATH_CONTENT, szFilename); if (!path_is_empty(RARCH_PATH_CONTENT)) { unsigned i; core_info_t *current_core = NULL; core_info_get_current_core(¤t_core); /*we already have path for libretro core */ for (i = 0; i < list_size; i++) { const core_info_t *info = (const core_info_t*)&core_info[i]; if(!string_is_equal(info->systemname, current_core->systemname)) break; if(string_is_equal(path_get(RARCH_PATH_CORE), info->path)) { /* Our previous core supports the current rom */ content_ctx_info_t content_info = {0}; task_push_content_load_default( NULL, NULL, &content_info, CORE_TYPE_PLAIN, CONTENT_MODE_LOAD_CONTENT_WITH_CURRENT_CORE_FROM_COMPANION_UI, NULL, NULL); return 0; } } } /* Poll for cores for current rom since none exist. */ if(list_size ==1) { /*pick core that only exists and is bound to work. Ish. */ const core_info_t *info = (const core_info_t*)&core_info[0]; if (info) task_push_content_load_default( info->path, NULL, &content_info, CORE_TYPE_PLAIN, CONTENT_MODE_LOAD_CONTENT_WITH_NEW_CORE_FROM_COMPANION_UI, NULL, NULL); } else { /* Pick one core that could be compatible, ew */ if(DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_PICKCORE), hwnd,PickCoreProc,(LPARAM)NULL)==IDOK) { task_push_content_load_default( NULL, NULL, &content_info, CORE_TYPE_PLAIN, CONTENT_MODE_LOAD_CONTENT_WITH_CURRENT_CORE_FROM_COMPANION_UI, NULL, NULL); } } } return 0; }
/** * menu_shader_manager_save_preset: * @basename : basename of preset * @apply : immediately set preset after saving * * Save a shader preset to disk. **/ bool menu_shader_manager_save_preset( const char *basename, bool apply, bool fullpath) { #ifdef HAVE_SHADER_MANAGER char buffer[PATH_MAX_LENGTH]; char config_directory[PATH_MAX_LENGTH]; char preset_path[PATH_MAX_LENGTH]; unsigned d, type = RARCH_SHADER_NONE; const char *dirs[3] = {0}; config_file_t *conf = NULL; bool ret = false; struct video_shader *shader = NULL; settings_t *settings = config_get_ptr(); menu_handle_t *menu = NULL; buffer[0] = config_directory[0] = '\0'; preset_path[0] = '\0'; if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) { RARCH_ERR("Cannot save shader preset.\n"); return false; } menu_driver_ctl(RARCH_MENU_CTL_SHADER_GET, &shader); if (!shader) return false; type = menu_shader_manager_get_type(shader); if (type == RARCH_SHADER_NONE) return false; *config_directory = '\0'; if (basename) { strlcpy(buffer, basename, sizeof(buffer)); /* Append extension automatically as appropriate. */ if ( !strstr(basename, file_path_str(FILE_PATH_CGP_EXTENSION)) && !strstr(basename, file_path_str(FILE_PATH_GLSLP_EXTENSION)) && !strstr(basename, file_path_str(FILE_PATH_SLANGP_EXTENSION))) { switch (type) { case RARCH_SHADER_GLSL: strlcat(buffer, file_path_str(FILE_PATH_GLSLP_EXTENSION), sizeof(buffer)); break; case RARCH_SHADER_SLANG: strlcat(buffer, file_path_str(FILE_PATH_SLANGP_EXTENSION), sizeof(buffer)); break; case RARCH_SHADER_CG: strlcat(buffer, file_path_str(FILE_PATH_CGP_EXTENSION), sizeof(buffer)); break; } } } else { const char *conf_path = NULL; switch (type) { case RARCH_SHADER_GLSL: conf_path = default_glslp; break; case RARCH_SHADER_SLANG: conf_path = default_slangp; break; default: case RARCH_SHADER_CG: conf_path = default_cgp; break; } if (!string_is_empty(conf_path)) strlcpy(buffer, conf_path, sizeof(buffer)); } if (!path_is_empty(RARCH_PATH_CONFIG)) fill_pathname_basedir( config_directory, path_get(RARCH_PATH_CONFIG), sizeof(config_directory)); if (!fullpath) { dirs[0] = settings->directory.video_shader; dirs[1] = settings->directory.menu_config; dirs[2] = config_directory; } if (!(conf = (config_file_t*)config_file_new(NULL))) return false; video_shader_write_conf_cgp(conf, shader); if (!fullpath) { for (d = 0; d < ARRAY_SIZE(dirs); d++) { if (!*dirs[d]) continue; fill_pathname_join(preset_path, dirs[d], buffer, sizeof(preset_path)); if (config_file_write(conf, preset_path)) { RARCH_LOG("Saved shader preset to %s.\n", preset_path); if (apply) menu_shader_manager_set_preset(NULL, type, preset_path); ret = true; break; } else RARCH_LOG("Failed writing shader preset to %s.\n", preset_path); } } else { if (!string_is_empty(basename)) strlcpy(preset_path, buffer, sizeof(preset_path)); if (config_file_write(conf, preset_path)) { RARCH_LOG("Saved shader preset to %s.\n", preset_path); if (apply) menu_shader_manager_set_preset(NULL, type, preset_path); ret = true; } else RARCH_LOG("Failed writing shader preset to %s.\n", preset_path); } config_file_free(conf); if (ret) return true; RARCH_ERR("Failed to save shader preset. Make sure config directory" " and/or shader dir are writable.\n"); #endif return false; }
void fill_pathname_application_special(char *s, size_t len, enum application_special_type type) { switch (type) { case APPLICATION_SPECIAL_DIRECTORY_AUTOCONFIG: { settings_t *settings = config_get_ptr(); fill_pathname_join(s, settings->paths.directory_autoconfig, settings->arrays.input_joypad_driver, len); } break; case APPLICATION_SPECIAL_DIRECTORY_CONFIG: { settings_t *settings = config_get_ptr(); /* Try config directory setting first, * fallback to the location of the current configuration file. */ if (!string_is_empty(settings->paths.directory_menu_config)) strlcpy(s, settings->paths.directory_menu_config, len); else if (!path_is_empty(RARCH_PATH_CONFIG)) fill_pathname_basedir(s, path_get(RARCH_PATH_CONFIG), len); } break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_ICONS: #ifdef HAVE_ZARCH { } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_FONT: #ifdef HAVE_ZARCH { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); s1[0] = '\0'; fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH); fill_pathname_join(s, s1, "Roboto-Condensed.ttf", len); free(s1); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH: #ifdef HAVE_ZARCH { settings_t *settings = config_get_ptr(); fill_pathname_join(s, settings->paths.directory_assets, "zarch", len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_ICONS: #ifdef HAVE_XMB { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *s2 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); s1[0] = s2[0] = '\0'; fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB); fill_pathname_join(s2, s1, "png", PATH_MAX_LENGTH * sizeof(char) ); fill_pathname_slash(s2, PATH_MAX_LENGTH * sizeof(char) ); strlcpy(s, s2, len); free(s1); free(s2); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_BG: #ifdef HAVE_XMB { settings_t *settings = config_get_ptr(); if (!string_is_empty(settings->paths.path_menu_wallpaper)) strlcpy(s, settings->paths.path_menu_wallpaper, len); else { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); s1[0] = '\0'; fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_ICONS); fill_pathname_join(s, s1, file_path_str(FILE_PATH_BACKGROUND_IMAGE), len); free(s1); } } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB: #ifdef HAVE_XMB { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *s2 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); settings_t *settings = config_get_ptr(); s1[0] = s2[0] = '\0'; fill_pathname_join( s1, settings->paths.directory_assets, "xmb", PATH_MAX_LENGTH * sizeof(char) ); fill_pathname_join(s2, s1, xmb_theme_ident(), PATH_MAX_LENGTH * sizeof(char) ); strlcpy(s, s2, len); free(s1); free(s2); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI: #ifdef HAVE_MATERIALUI { settings_t *settings = config_get_ptr(); fill_pathname_join( s, settings->paths.directory_assets, "glui", len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI_ICONS: #ifdef HAVE_MATERIALUI { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); s1[0] = '\0'; fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI); fill_pathname_slash(s1, PATH_MAX_LENGTH * sizeof(char) ); strlcpy(s, s1, len); free(s1); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI_FONT: #ifdef HAVE_MATERIALUI { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); s1[0] = '\0'; fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI); fill_pathname_join(s, s1, "font.ttf", len); free(s1); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_FONT: #ifdef HAVE_XMB { settings_t *settings = config_get_ptr(); if (!string_is_empty(settings->paths.path_menu_xmb_font)) strlcpy(s, settings->paths.path_menu_xmb_font, len); else { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); s1[0] = '\0'; fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB); fill_pathname_join(s, s1, file_path_str(FILE_PATH_TTF_FONT), len); free(s1); } } #endif break; case APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES: { char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *s2 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); settings_t *settings = config_get_ptr(); s1[0] = s2[0] = '\0'; fill_pathname_join(s1, settings->paths.directory_thumbnails, "cheevos", len); fill_pathname_join(s2, s1, "badges", PATH_MAX_LENGTH * sizeof(char) ); fill_pathname_slash(s2, PATH_MAX_LENGTH * sizeof(char) ); strlcpy(s, s2, len); free(s1); free(s2); } break; case APPLICATION_SPECIAL_NONE: default: break; } }
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 = 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_GET: { rarch_system_info_t **system = (rarch_system_info_t**)data; if (!system) return false; *system = &runloop_system; } 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_enable = true; 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_GAME_OPTIONS_ACTIVE: runloop_game_options_active = true; break; case RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE: runloop_game_options_active = false; break; case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE: return runloop_game_options_active; case RUNLOOP_CTL_SET_FRAME_LIMIT: runloop_set_frame_limit = true; 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_frame_time_last_enable = false; runloop_set_frame_limit = false; runloop_overrides_active = 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_IS_SLOWMOTION: return runloop_slowmotion; case RUNLOOP_CTL_SET_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_slowmotion = *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_PULL: #ifdef HAVE_THREADS slock_lock(_runloop_msg_queue_lock); #endif { const char **ret = (const char**)data; if (!ret) { #ifdef HAVE_THREADS slock_unlock(_runloop_msg_queue_lock); #endif return false; } *ret = msg_queue_pull(runloop_msg_queue); } #ifdef HAVE_THREADS slock_unlock(_runloop_msg_queue_lock); #endif break; 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->threaded_data_runloop_enable; #else bool threaded_enable = false; #endif task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL); task_queue_ctl(TASK_QUEUE_CTL_INIT, &threaded_enable); } 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_SET_EXEC: runloop_exec = true; break; case RUNLOOP_CTL_DATA_DEINIT: task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL); 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->game_specific_options) ret = rarch_game_specific_options(&game_options_path); if(ret) { runloop_ctl(RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE, NULL); 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->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_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); 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_ctl(RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE, NULL)) runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); 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; }
/** * task_load_content: * * Loads content into currently selected core. * Will also optionally push the content entry to the history playlist. * * Returns: true (1) if successful, otherwise false (0). **/ static bool task_load_content(content_ctx_info_t *content_info, content_information_ctx_t *content_ctx, bool launched_from_menu, enum content_mode_load mode, char **error_string) { char name[255]; char msg[255]; name[0] = msg[0] = '\0'; if (!content_load(content_info)) goto error; /* Push entry to top of history playlist */ if (_content_is_inited || content_does_not_need_content()) { char tmp[PATH_MAX_LENGTH]; struct retro_system_info *info = NULL; rarch_system_info_t *sys_info = NULL; tmp[0] = '\0'; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &sys_info); if (sys_info) info = &sys_info->info; #ifdef HAVE_MENU if (launched_from_menu) menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &info); #endif strlcpy(tmp, path_get(RARCH_PATH_CONTENT), sizeof(tmp)); if (!launched_from_menu) { /* Path can be relative here. * Ensure we're pushing absolute path. */ if (!string_is_empty(tmp)) path_resolve_realpath(tmp, sizeof(tmp)); } if (info && !string_is_empty(tmp)) { const char *core_path = NULL; const char *core_name = NULL; playlist_t *playlist_tmp = g_defaults.content_history; switch (path_is_media_type(tmp)) { case RARCH_CONTENT_MOVIE: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.video_history; core_name = "movieplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_MUSIC: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.music_history; core_name = "musicplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_IMAGE: #ifdef HAVE_IMAGEVIEWER playlist_tmp = g_defaults.image_history; core_name = "imageviewer"; core_path = "builtin"; #endif break; default: core_path = path_get(RARCH_PATH_CORE); core_name = info->library_name; break; } if (mode == CONTENT_MODE_LOAD_FROM_CLI) { settings_t *settings = config_get_ptr(); content_ctx->history_list_enable = settings->history_list_enable; } if ( content_ctx->history_list_enable && playlist_tmp && playlist_push( playlist_tmp, tmp, NULL, core_path, core_name, NULL, NULL) ) playlist_write_file(playlist_tmp); } } return true; error: if (launched_from_menu) { if (!path_is_empty(RARCH_PATH_CONTENT) && !string_is_empty(name)) { snprintf(msg, sizeof(msg), "%s %s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD), name); if (error_string) free(error_string); *error_string = strdup(msg); } } return false; }
/** * task_load_content: * * Loads content into currently selected core. * Will also optionally push the content entry to the history playlist. * * Returns: true (1) if successful, otherwise false (0). **/ static bool task_load_content(content_ctx_info_t *content_info, bool launched_from_menu, enum content_mode_load mode) { char name[256]; char msg[256]; name[0] = msg[0] = '\0'; if (launched_from_menu) { #ifdef HAVE_MENU /* redraw menu frame */ menu_display_set_msg_force(true); menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); if (!path_is_empty(RARCH_PATH_CONTENT)) fill_pathname_base(name, path_get(RARCH_PATH_CONTENT), sizeof(name)); #endif /** Show loading OSD message */ if (!string_is_empty(path_get(RARCH_PATH_CONTENT))) { snprintf(msg, sizeof(msg), "%s %s ...", msg_hash_to_str(MSG_LOADING), name); runloop_msg_queue_push(msg, 2, 1, true); } } if (!content_load(content_info)) goto error; /* Push entry to top of history playlist */ if (content_is_inited() || content_does_not_need_content()) { char tmp[PATH_MAX_LENGTH]; struct retro_system_info *info = NULL; rarch_system_info_t *system = NULL; tmp[0] = '\0'; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (system) info = &system->info; #ifdef HAVE_MENU if (launched_from_menu) menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &info); #endif strlcpy(tmp, path_get(RARCH_PATH_CONTENT), sizeof(tmp)); if (!launched_from_menu) { /* Path can be relative here. * Ensure we're pushing absolute path. */ if (!string_is_empty(tmp)) path_resolve_realpath(tmp, sizeof(tmp)); } if (info && *tmp) { const char *core_path = NULL; const char *core_name = NULL; playlist_t *playlist_tmp = g_defaults.content_history; switch (path_is_media_type(tmp)) { case RARCH_CONTENT_MOVIE: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.video_history; core_name = "movieplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_MUSIC: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.music_history; core_name = "musicplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_IMAGE: #ifdef HAVE_IMAGEVIEWER playlist_tmp = g_defaults.image_history; core_name = "imageviewer"; core_path = "builtin"; #endif break; default: core_path = path_get(RARCH_PATH_CORE); core_name = info->library_name; break; } if (content_push_to_history_playlist(playlist_tmp, tmp, core_name, core_path)) playlist_write_file(playlist_tmp); } } return true; error: if (launched_from_menu) { if (!path_is_empty(RARCH_PATH_CONTENT) && !string_is_empty(name)) { snprintf(msg, sizeof(msg), "%s %s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD), name); runloop_msg_queue_push(msg, 2, 90, true); } } return false; }
static bool path_init_subsystem(void) { unsigned i, j; const struct retro_subsystem_info *info = NULL; rarch_system_info_t *system = NULL; global_t *global = global_get_ptr(); runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (!system) return false; if (path_is_empty(RARCH_PATH_SUBSYSTEM)) return false; /* For subsystems, we know exactly which RAM types are supported. */ info = libretro_find_subsystem_info( system->subsystem.data, system->subsystem.size, path_get(RARCH_PATH_SUBSYSTEM)); /* We'll handle this error gracefully later. */ if (info) { unsigned num_content = MIN(info->num_roms, path_is_empty(RARCH_PATH_SUBSYSTEM) ? 0 : subsystem_fullpaths->size); for (i = 0; i < num_content; i++) { for (j = 0; j < info->roms[i].num_memory; j++) { union string_list_elem_attr attr; char path[PATH_MAX_LENGTH]; char ext[32]; const struct retro_subsystem_memory_info *mem = (const struct retro_subsystem_memory_info*) &info->roms[i].memory[j]; path[0] = ext[0] = '\0'; snprintf(ext, sizeof(ext), ".%s", mem->extension); if (path_is_directory(dir_get(RARCH_DIR_SAVEFILE))) { /* Use SRAM dir */ /* Redirect content fullpath to save directory. */ strlcpy(path, dir_get(RARCH_DIR_SAVEFILE), sizeof(path)); fill_pathname_dir(path, subsystem_fullpaths->elems[i].data, ext, sizeof(path)); } else { fill_pathname(path, subsystem_fullpaths->elems[i].data, ext, sizeof(path)); } attr.i = mem->type; string_list_append((struct string_list*)savefile_ptr_get(), path, attr); } } } if (global) { /* Let other relevant paths be inferred from the main SRAM location. */ if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL)) fill_pathname_noext(global->name.savefile, path_main_basename, file_path_str(FILE_PATH_SRM_EXTENSION), sizeof(global->name.savefile)); if (path_is_directory(global->name.savefile)) { fill_pathname_dir(global->name.savefile, path_main_basename, file_path_str(FILE_PATH_SRM_EXTENSION), sizeof(global->name.savefile)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVEFILE_TO), global->name.savefile); } } return true; }
/* Take frame bottom-up. */ static bool screenshot_dump( const char *name_base, const void *frame, unsigned width, unsigned height, int pitch, bool bgr24, void *userbuf, bool savestate, bool is_idle, bool is_paused, bool fullpath, bool use_thread) { char screenshot_path[PATH_MAX_LENGTH]; uint8_t *buf = NULL; settings_t *settings = config_get_ptr(); retro_task_t *task; screenshot_task_state_t *state; const char *screenshot_dir = settings->paths.directory_screenshot; struct retro_system_info system_info; screenshot_path[0] = '\0'; if (!core_get_system_info(&system_info)) return false; task = task_init(); state = (screenshot_task_state_t*)calloc(1, sizeof(*state)); state->shotname[0] = '\0'; /* If fullpath is true, name_base already contains a static path + filename to save the screenshot to. */ if (fullpath) strlcpy(state->filename, name_base, sizeof(state->filename)); else { if (string_is_empty(screenshot_dir) || settings->bools.screenshots_in_content_dir) { fill_pathname_basedir(screenshot_path, name_base, sizeof(screenshot_path)); screenshot_dir = screenshot_path; } } state->is_idle = is_idle; state->is_paused = is_paused; state->bgr24 = bgr24; state->height = height; state->width = width; state->pitch = pitch; state->frame = frame; state->userbuf = userbuf; state->silence = savestate; state->history_list_enable = settings->bools.history_list_enable; state->pixel_format_type = video_driver_get_pixel_format(); if (!fullpath) { if (savestate) snprintf(state->filename, sizeof(state->filename), "%s.png", name_base); else { if (settings->bools.auto_screenshot_filename) { const char *screenshot_name = NULL; if (path_is_empty(RARCH_PATH_CONTENT)) { if (string_is_empty(system_info.library_name)) screenshot_name = "RetroArch"; else screenshot_name = system_info.library_name; } else screenshot_name = path_basename(name_base); fill_str_dated_filename(state->shotname, screenshot_name, IMG_EXT, sizeof(state->shotname)); } else snprintf(state->shotname, sizeof(state->shotname), "%s.png", path_basename(name_base)); fill_pathname_join(state->filename, screenshot_dir, state->shotname, sizeof(state->filename)); } } #if defined(HAVE_RPNG) buf = (uint8_t*)malloc(width * height * 3); if (!buf) { if (task) free(task); free(state); return false; } state->out_buffer = buf; #endif task->type = TASK_TYPE_BLOCKING; task->state = state; task->handler = task_screenshot_handler; if (use_thread) { if (!savestate) task->title = strdup(msg_hash_to_str(MSG_TAKING_SCREENSHOT)); if (!task_queue_push(task)) { /* There is already a blocking task going on */ if (task->title) task_free_title(task); free(task); if (state->out_buffer) free(state->out_buffer); free(state); return false; } } else { if (task) free(task); return screenshot_dump_direct(state); } return true; }