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 const struct retro_subsystem_info *init_content_file_subsystem( bool *ret, rarch_system_info_t *system) { global_t *global = global_get_ptr(); const struct retro_subsystem_info *special = libretro_find_subsystem_info(system->special, system->num_special, global->subsystem); if (!special) { RARCH_ERR( "Failed to find subsystem \"%s\" in libretro implementation.\n", global->subsystem); goto error; } if (special->num_roms && !global->subsystem_fullpaths) { RARCH_ERR("libretro core requires special content, " "but none were provided.\n"); goto error; } else if (special->num_roms && special->num_roms != global->subsystem_fullpaths->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)global->subsystem_fullpaths->size); goto error; } else if (!special->num_roms && global->subsystem_fullpaths && global->subsystem_fullpaths->size) { RARCH_ERR("libretro core takes no content for subsystem \"%s\", " "but %u content files were provided.\n", special->desc, (unsigned)global->subsystem_fullpaths->size); goto error; } *ret = true; return special; error: *ret = false; return NULL; }
bool init_content_file(void) { unsigned i; g_extern.temporary_content = string_list_new(); if (!g_extern.temporary_content) return false; const struct retro_subsystem_info *special = NULL; if (*g_extern.subsystem) { special = libretro_find_subsystem_info(g_extern.system.special, g_extern.system.num_special, g_extern.subsystem); if (!special) { RARCH_ERR( "Failed to find subsystem \"%s\" in libretro implementation.\n", g_extern.subsystem); return false; } if (special->num_roms && !g_extern.subsystem_fullpaths) { RARCH_ERR("libretro core requires special content, but none were provided.\n"); return false; } else if (special->num_roms && special->num_roms != g_extern.subsystem_fullpaths->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)g_extern.subsystem_fullpaths->size); return false; } else if (!special->num_roms && g_extern.subsystem_fullpaths && g_extern.subsystem_fullpaths->size) { RARCH_ERR("libretro core takes no content for subsystem \"%s\", but %u content files were provided.\n", special->desc, (unsigned)g_extern.subsystem_fullpaths->size); return false; } } union string_list_elem_attr attr; attr.i = 0; struct string_list *content = (struct string_list*)string_list_new(); if (!content) return false; if (*g_extern.subsystem) { for (i = 0; i < g_extern.subsystem_fullpaths->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, g_extern.subsystem_fullpaths->elems[i].data, attr); } } else { attr.i = g_extern.system.info.block_extract; attr.i |= g_extern.system.info.need_fullpath << 1; attr.i |= (!g_extern.system.no_content) << 2; string_list_append(content, g_extern.libretro_no_content ? "" : g_extern.fullpath, attr); } #ifdef HAVE_ZLIB /* Try to extract all content we're going to load if appropriate. */ for (i = 0; i < content->size; i++) { /* Block extract check. */ if (content->elems[i].attr.i & 1) continue; const char *ext = path_get_extension(content->elems[i].data); const char *valid_ext = special ? special->roms[i].valid_extensions : g_extern.system.info.valid_extensions; if (ext && !strcasecmp(ext, "zip")) { char temporary_content[PATH_MAX]; strlcpy(temporary_content, content->elems[i].data, sizeof(temporary_content)); if (!zlib_extract_first_content_file(temporary_content, sizeof(temporary_content), valid_ext, *g_settings.extraction_directory ? g_settings.extraction_directory : NULL)) { RARCH_ERR("Failed to extract content from zipped file: %s.\n", temporary_content); string_list_free(content); return false; } string_list_set(content, i, temporary_content); string_list_append(g_extern.temporary_content, temporary_content, attr); } } #endif /* Set attr to need_fullpath as appropriate. */ bool ret = load_content(special, content); string_list_free(content); return ret; }
static void rarch_init_savefile_paths(void) { global_t *global = global_get_ptr(); event_command(EVENT_CMD_SAVEFILES_DEINIT); global->savefiles = string_list_new(); rarch_assert(global->savefiles); if (*global->subsystem) { /* For subsystems, we know exactly which RAM types are supported. */ unsigned i, j; const struct retro_subsystem_info *info = libretro_find_subsystem_info( global->system.special, global->system.num_special, global->subsystem); /* We'll handle this error gracefully later. */ unsigned num_content = min(info ? info->num_roms : 0, global->subsystem_fullpaths ? global->subsystem_fullpaths->size : 0); bool use_sram_dir = path_is_directory(global->savefile_dir); 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], ext[32]; const struct retro_subsystem_memory_info *mem = (const struct retro_subsystem_memory_info*) &info->roms[i].memory[j]; snprintf(ext, sizeof(ext), ".%s", mem->extension); if (use_sram_dir) { /* Redirect content fullpath to save directory. */ strlcpy(path, global->savefile_dir, sizeof(path)); fill_pathname_dir(path, global->subsystem_fullpaths->elems[i].data, ext, sizeof(path)); } else { fill_pathname(path, global->subsystem_fullpaths->elems[i].data, ext, sizeof(path)); } attr.i = mem->type; string_list_append(global->savefiles, path, attr); } } /* Let other relevant paths be inferred from the main SRAM location. */ if (!global->has_set_save_path) fill_pathname_noext(global->savefile_name, global->basename, ".srm", sizeof(global->savefile_name)); if (path_is_directory(global->savefile_name)) { fill_pathname_dir(global->savefile_name, global->basename, ".srm", sizeof(global->savefile_name)); RARCH_LOG("Redirecting save file to \"%s\".\n", global->savefile_name); } } else { char savefile_name_rtc[PATH_MAX_LENGTH]; union string_list_elem_attr attr; attr.i = RETRO_MEMORY_SAVE_RAM; string_list_append(global->savefiles, global->savefile_name, attr); /* Infer .rtc save path from save ram path. */ attr.i = RETRO_MEMORY_RTC; fill_pathname(savefile_name_rtc, global->savefile_name, ".rtc", sizeof(savefile_name_rtc)); string_list_append(global->savefiles, savefile_name_rtc, attr); } }
/** * init_content_file: * * Initializes and loads a content file for the currently * selected libretro core. * * global->content_is_init will be set to the return value * on exit. * * Returns : true if successful, otherwise false. **/ bool init_content_file(void) { unsigned i; union string_list_elem_attr attr; bool ret = false; struct string_list *content = NULL; const struct retro_subsystem_info *special = NULL; settings_t *settings = config_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); global_t *global = global_get_ptr(); global->temporary_content = string_list_new(); if (!global->temporary_content) goto error; if (*global->subsystem) { special = libretro_find_subsystem_info(system->special, system->num_special, global->subsystem); if (!special) { RARCH_ERR( "Failed to find subsystem \"%s\" in libretro implementation.\n", global->subsystem); goto error; } if (special->num_roms && !global->subsystem_fullpaths) { RARCH_ERR("libretro core requires special content, but none were provided.\n"); goto error; } else if (special->num_roms && special->num_roms != global->subsystem_fullpaths->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)global->subsystem_fullpaths->size); goto error; } else if (!special->num_roms && global->subsystem_fullpaths && global->subsystem_fullpaths->size) { RARCH_ERR("libretro core takes no content for subsystem \"%s\", but %u content files were provided.\n", special->desc, (unsigned)global->subsystem_fullpaths->size); goto error; } } content = string_list_new(); attr.i = 0; if (!content) goto error; if (*global->subsystem) { for (i = 0; i < global->subsystem_fullpaths->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, global->subsystem_fullpaths->elems[i].data, attr); } } else { attr.i = system->info.block_extract; attr.i |= system->info.need_fullpath << 1; attr.i |= (!system->no_content) << 2; string_list_append(content, (global->inited.core.no_content && settings->core.set_supports_no_game_enable) ? "" : global->path.fullpath, attr); } #ifdef HAVE_ZLIB /* Try to extract all content we're going to load if appropriate. */ for (i = 0; i < content->size; i++) { const char *ext = NULL; const char *valid_ext = NULL; /* Block extract check. */ if (content->elems[i].attr.i & 1) continue; ext = path_get_extension(content->elems[i].data); valid_ext = special ? special->roms[i].valid_extensions : system->info.valid_extensions; if (ext && !strcasecmp(ext, "zip")) { char temporary_content[PATH_MAX_LENGTH] = {0}; strlcpy(temporary_content, content->elems[i].data, sizeof(temporary_content)); if (!zlib_extract_first_content_file(temporary_content, sizeof(temporary_content), valid_ext, *settings->extraction_directory ? settings->extraction_directory : NULL)) { RARCH_ERR("Failed to extract content from zipped file: %s.\n", temporary_content); goto error; } string_list_set(content, i, temporary_content); string_list_append(global->temporary_content, temporary_content, attr); } } #endif /* Set attr to need_fullpath as appropriate. */ ret = load_content(special, content); error: global->inited.content = (ret) ? true : false; if (content) string_list_free(content); return ret; }
static const struct retro_subsystem_info *content_file_init_subsystem( content_information_ctx_t *content_ctx, char **error_string, bool *ret) { char msg[1024]; struct string_list *subsystem = path_get_subsystem_list(); const struct retro_subsystem_info *special = libretro_find_subsystem_info( content_ctx->subsystem.data, content_ctx->subsystem.size, path_get(RARCH_PATH_SUBSYSTEM)); msg[0] = '\0'; if (!special) { snprintf(msg, sizeof(msg), "Failed to find subsystem \"%s\" in libretro implementation.\n", path_get(RARCH_PATH_SUBSYSTEM)); if (error_string) free(error_string); *error_string = strdup(msg); goto error; } if (special->num_roms && !subsystem) { snprintf(msg, sizeof(msg), "%s\n", msg_hash_to_str(MSG_ERROR_LIBRETRO_CORE_REQUIRES_SPECIAL_CONTENT)); if (error_string) free(error_string); *error_string = strdup(msg); goto error; } else if (special->num_roms && (special->num_roms != subsystem->size)) { snprintf(msg, sizeof(msg), "Libretro core requires %u content files for " "subsystem \"%s\", but %u content files were provided.\n", special->num_roms, special->desc, (unsigned)subsystem->size); if (error_string) free(error_string); *error_string = strdup(msg); goto error; } else if (!special->num_roms && subsystem && subsystem->size) { snprintf(msg, sizeof(msg), "Libretro core takes no content for subsystem \"%s\", " "but %u content files were provided.\n", special->desc, (unsigned)subsystem->size); if (error_string) free(error_string); *error_string = strdup(msg); goto error; } *ret = true; return special; error: *ret = false; return NULL; }
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; }