void rarch_set_paths(const char *path) { settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); set_basename(path); if (!global->has_set_save_path) fill_pathname_noext(global->savefile_name, global->basename, ".srm", sizeof(global->savefile_name)); if (!global->has_set_state_path) fill_pathname_noext(global->savestate_name, global->basename, ".state", sizeof(global->savestate_name)); fill_pathname_noext(global->cheatfile_name, global->basename, ".cht", sizeof(global->cheatfile_name)); set_paths_redirect(path); /* If this is already set, do not overwrite it * as this was initialized before in a menu or otherwise. */ if (*settings->system_directory) return; fill_pathname_basedir(settings->system_directory, path, sizeof(settings->system_directory)); }
void path_fill_names(void) { global_t *global = global_get_ptr(); path_init_savefile_internal(); if (global) bsv_movie_set_path(global->name.savefile); if (string_is_empty(path_main_basename)) return; if (global) { if (string_is_empty(global->name.ups)) fill_pathname_noext(global->name.ups, path_main_basename, file_path_str(FILE_PATH_UPS_EXTENSION), sizeof(global->name.ups)); if (string_is_empty(global->name.bps)) fill_pathname_noext(global->name.bps, path_main_basename, file_path_str(FILE_PATH_BPS_EXTENSION), sizeof(global->name.bps)); if (string_is_empty(global->name.ips)) fill_pathname_noext(global->name.ips, path_main_basename, file_path_str(FILE_PATH_IPS_EXTENSION), sizeof(global->name.ips)); } }
static bool event_save_auto_state(void) { bool ret; char savestate_name_auto[PATH_MAX_LENGTH] = {0}; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); if (!settings->savestate_auto_save) return false; if (rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) return false; if (content_ctl(CONTENT_CTL_DOES_NOT_NEED_CONTENT, NULL)) return false; #ifdef HAVE_CHEEVOS if (settings->cheevos.hardcore_mode_enable) return false; #endif fill_pathname_noext(savestate_name_auto, global->name.savestate, ".auto", sizeof(savestate_name_auto)); ret = content_ctl(CONTENT_CTL_SAVE_STATE, (void*)savestate_name_auto); RARCH_LOG("Auto save state to \"%s\" %s.\n", savestate_name_auto, ret ? "succeeded" : "failed"); return true; }
static void event_load_auto_state(void) { bool ret; char msg[PATH_MAX_LENGTH] = {0}; char savestate_name_auto[PATH_MAX_LENGTH] = {0}; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); #ifdef HAVE_NETPLAY if (global->netplay_enable && !global->netplay_is_spectate) return; #endif if (!settings->savestate_auto_load) return; fill_pathname_noext(savestate_name_auto, global->savestate_name, ".auto", sizeof(savestate_name_auto)); if (!path_file_exists(savestate_name_auto)) return; ret = load_state(savestate_name_auto); RARCH_LOG("Found auto savestate in: %s\n", savestate_name_auto); snprintf(msg, sizeof(msg), "Auto-loading savestate from \"%s\" %s.", savestate_name_auto, ret ? "succeeded" : "failed"); rarch_main_msg_queue_push(msg, 1, 180, false); RARCH_LOG("%s\n", msg); }
void rarch_set_paths(const char *path) { global_t *global = global_get_ptr(); set_basename(path); if (!global->has_set.save_path) fill_pathname_noext(global->name.savefile, global->name.base, ".srm", sizeof(global->name.savefile)); if (!global->has_set.state_path) fill_pathname_noext(global->name.savestate, global->name.base, ".state", sizeof(global->name.savestate)); fill_pathname_noext(global->name.cheatfile, global->name.base, ".cht", sizeof(global->name.cheatfile)); set_paths_redirect(path); }
void fill_pathname_join_concat_noext( char *out_path, const char *dir, const char *path, const char *concat, size_t size) { fill_pathname_noext(out_path, dir, path, size); strlcat(out_path, concat, size); }
static void menu_action_setting_disp_set_label_playlist_associations(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) { char playlist_name_with_ext[255]; bool found_matching_core_association = false; settings_t *settings = config_get_ptr(); struct string_list *str_list = string_split(settings->arrays.playlist_names, ";"); struct string_list *str_list2 = string_split(settings->arrays.playlist_cores, ";"); strlcpy(s2, path, len2); playlist_name_with_ext[0] = '\0'; *s = '\0'; *w = 19; fill_pathname_noext(playlist_name_with_ext, path, file_path_str(FILE_PATH_LPL_EXTENSION), sizeof(playlist_name_with_ext)); for (i = 0; i < str_list->size; i++) { if (string_is_equal(str_list->elems[i].data, playlist_name_with_ext)) { if (str_list->size != str_list2->size) break; if (!str_list2->elems[i].data) break; found_matching_core_association = true; strlcpy(s, str_list2->elems[i].data, len); } } string_list_free(str_list); string_list_free(str_list2); if (string_is_equal(s, file_path_str(FILE_PATH_DETECT)) || !found_matching_core_association) strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), len); else { char buf[PATH_MAX_LENGTH]; core_info_list_t *list = NULL; core_info_get_list(&list); if (core_info_list_get_display_name(list, s, buf, sizeof(buf))) strlcpy(s, buf, len); } strlcpy(s2, path, len2); }
/** * cheat_manager_save: * @path : Path to cheats file (relative path). * * Saves cheats to file on disk. * * Returns: true (1) if successful, otherwise false (0). **/ bool cheat_manager_save(const char *path) { bool ret; unsigned i; config_file_t *conf = NULL; char buf[PATH_MAX_LENGTH] = {0}; char cheats_file[PATH_MAX_LENGTH] = {0}; settings_t *settings = config_get_ptr(); cheat_manager_t *handle = cheat_manager_state; fill_pathname_join(buf, settings->path.cheat_database, path, sizeof(buf)); fill_pathname_noext(cheats_file, buf, ".cht", sizeof(cheats_file)); conf = config_file_new(cheats_file); if (!conf) conf = config_file_new(NULL); if (!conf) return false; if (!handle) { config_file_free(conf); return false; } config_set_int(conf, "cheats", handle->size); for (i = 0; i < handle->size; i++) { char key[64] = {0}; char desc_key[256] = {0}; char code_key[256] = {0}; char enable_key[256] = {0}; snprintf(key, sizeof(key), "cheat%u", i); snprintf(desc_key, sizeof(desc_key), "cheat%u_desc", i); snprintf(code_key, sizeof(code_key), "cheat%u_code", i); snprintf(enable_key, sizeof(enable_key), "cheat%u_enable", i); if (handle->cheats[i].desc) config_set_string(conf, desc_key, handle->cheats[i].desc); else config_set_string(conf, desc_key, handle->cheats[i].code); config_set_string(conf, code_key, handle->cheats[i].code); config_set_bool(conf, enable_key, handle->cheats[i].state); } ret = config_file_write(conf, cheats_file); config_file_free(conf); return ret; }
void rarch_fill_pathnames(void) { global_t *global = global_get_ptr(); rarch_init_savefile_paths(); fill_pathname(global->bsv.movie_path, global->savefile_name, "", sizeof(global->bsv.movie_path)); if (!*global->basename) return; if (!*global->ups_name) fill_pathname_noext(global->ups_name, global->basename, ".ups", sizeof(global->ups_name)); if (!*global->bps_name) fill_pathname_noext(global->bps_name, global->basename, ".bps", sizeof(global->bps_name)); if (!*global->ips_name) fill_pathname_noext(global->ips_name, global->basename, ".ips", sizeof(global->ips_name)); }
static void path_set_names(const char *path) { global_t *global = global_get_ptr(); path_set_basename(path); if (global) { 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 (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL)) fill_pathname_noext(global->name.savestate, path_main_basename, file_path_str(FILE_PATH_STATE_EXTENSION), sizeof(global->name.savestate)); fill_pathname_noext(global->name.cheatfile, path_main_basename, file_path_str(FILE_PATH_CHT_EXTENSION), sizeof(global->name.cheatfile)); } path_set_redirect(); }
/** * fill_pathname: * @out_path : output path * @in_path : input path * @replace : what to replace * @size : buffer size of output path * * FIXME: Verify * * Replaces filename extension with 'replace' and outputs result to out_path. * The extension here is considered to be the string from the last '.' * to the end. * * Only '.'s after the last slash are considered as extensions. * If no '.' is present, in_path and replace will simply be concatenated. * 'size' is buffer size of 'out_path'. * E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => * out_path = "/foo/bar/baz/boo.asm" * E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => * out_path = "/foo/bar/baz/boo" */ void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size) { char tmp_path[PATH_MAX_LENGTH]; char *tok = NULL; tmp_path[0] = '\0'; strlcpy(tmp_path, in_path, sizeof(tmp_path)); if ((tok = (char*)strrchr(path_basename(tmp_path), '.'))) *tok = '\0'; fill_pathname_noext(out_path, tmp_path, replace, size); }
static void set_special_paths(char **argv, unsigned num_content) { unsigned i; union string_list_elem_attr attr; global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); /* First content file is the significant one. */ set_basename(argv[0]); global->subsystem_fullpaths = string_list_new(); rarch_assert(global->subsystem_fullpaths); attr.i = 0; for (i = 0; i < num_content; i++) string_list_append(global->subsystem_fullpaths, argv[i], attr); /* We defer SRAM path updates until we can resolve it. * It is more complicated for special content types. */ if (!global->has_set.state_path) fill_pathname_noext(global->name.savestate, global->name.base, ".state", sizeof(global->name.savestate)); if (path_is_directory(global->name.savestate)) { fill_pathname_dir(global->name.savestate, global->name.base, ".state", sizeof(global->name.savestate)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVESTATE_TO), global->name.savestate); } /* If this is already set, * do not overwrite it as this was initialized before in * a menu or otherwise. */ if (settings->system_directory[0] == '\0') { RARCH_WARN("SYSTEM DIR is empty, assume CONTENT DIR %s\n",argv[0]); /*fill_pathname_basedir(settings->system_directory, argv[0], sizeof(settings->system_directory));*/ } }
static bool event_save_auto_state(void) { bool ret; char savestate_name_auto[PATH_MAX_LENGTH]; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); if (!settings->savestate_auto_save || global->libretro_dummy || global->libretro_no_content) return false; fill_pathname_noext(savestate_name_auto, global->savestate_name, ".auto", sizeof(savestate_name_auto)); ret = save_state(savestate_name_auto); RARCH_LOG("Auto save state to \"%s\" %s.\n", savestate_name_auto, ret ? "succeeded" : "failed"); return true; }
bool input_remapping_remove_file(const char *path) { bool ret = false; size_t path_size = PATH_MAX_LENGTH * sizeof(char); char *buf = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *remap_file = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); settings_t *settings = config_get_ptr(); buf[0] = remap_file[0] = '\0'; fill_pathname_join(buf, settings->paths.directory_input_remapping, path, path_size); fill_pathname_noext(remap_file, buf, ".rmp", path_size); ret = filestream_delete(remap_file) == 0 ? true : false; free(buf); free(remap_file); return ret; }
static bool event_save_auto_state(void) { bool ret; char savestate_name_auto[PATH_MAX_LENGTH] = {0}; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); if (!settings->savestate_auto_save || (global->inited.core.type == CORE_TYPE_DUMMY) || global->inited.core.no_content) return false; fill_pathname_noext(savestate_name_auto, global->name.savestate, ".auto", sizeof(savestate_name_auto)); ret = save_state(savestate_name_auto); RARCH_LOG("Auto save state to \"%s\" %s.\n", savestate_name_auto, ret ? "succeeded" : "failed"); return true; }
static void set_special_paths(char **argv, unsigned num_content) { unsigned i; union string_list_elem_attr attr; global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); /* First content file is the significant one. */ set_basename(argv[0]); global->subsystem_fullpaths = string_list_new(); rarch_assert(global->subsystem_fullpaths); attr.i = 0; for (i = 0; i < num_content; i++) string_list_append(global->subsystem_fullpaths, argv[i], attr); /* We defer SRAM path updates until we can resolve it. * It is more complicated for special content types. */ if (!global->has_set_state_path) fill_pathname_noext(global->savestate_name, global->basename, ".state", sizeof(global->savestate_name)); if (path_is_directory(global->savestate_name)) { fill_pathname_dir(global->savestate_name, global->basename, ".state", sizeof(global->savestate_name)); RARCH_LOG("Redirecting save state to \"%s\".\n", global->savestate_name); } /* If this is already set, * do not overwrite it as this was initialized before in * a menu or otherwise. */ if (!*settings->system_directory) fill_pathname_basedir(settings->system_directory, argv[0], sizeof(settings->system_directory)); }
void path_set_special(char **argv, unsigned num_content) { unsigned i; union string_list_elem_attr attr; global_t *global = global_get_ptr(); /* First content file is the significant one. */ path_set_basename(argv[0]); subsystem_fullpaths = string_list_new(); retro_assert(subsystem_fullpaths); attr.i = 0; for (i = 0; i < num_content; i++) string_list_append(subsystem_fullpaths, argv[i], attr); /* We defer SRAM path updates until we can resolve it. * It is more complicated for special content types. */ if (global) { if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL)) fill_pathname_noext(global->name.savestate, path_main_basename, file_path_str(FILE_PATH_STATE_EXTENSION), sizeof(global->name.savestate)); if (path_is_directory(global->name.savestate)) { fill_pathname_dir(global->name.savestate, path_main_basename, file_path_str(FILE_PATH_STATE_EXTENSION), sizeof(global->name.savestate)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVESTATE_TO), global->name.savestate); } } }
static void event_load_auto_state(void) { bool ret; char msg[128] = {0}; char savestate_name_auto[PATH_MAX_LENGTH] = {0}; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); #ifdef HAVE_NETPLAY if (global->netplay.enable && !global->netplay.is_spectate) return; #endif #ifdef HAVE_CHEEVOS if (settings->cheevos.hardcore_mode_enable) return; #endif if (!settings->savestate_auto_load) return; fill_pathname_noext(savestate_name_auto, global->name.savestate, ".auto", sizeof(savestate_name_auto)); if (!path_file_exists(savestate_name_auto)) return; ret = content_ctl(CONTENT_CTL_LOAD_STATE, (void*)savestate_name_auto); RARCH_LOG("Found auto savestate in: %s\n", savestate_name_auto); snprintf(msg, sizeof(msg), "Auto-loading savestate from \"%s\" %s.", savestate_name_auto, ret ? "succeeded" : "failed"); runloop_msg_queue_push(msg, 1, 180, false); RARCH_LOG("%s\n", msg); }
/** * input_remapping_save_file: * @path : Path to remapping file (relative path). * * Saves remapping values to file. * * Returns: true (1) if successful, otherwise false (0). **/ bool input_remapping_save_file(const char *path) { bool ret; unsigned i, j; char buf[PATH_MAX_LENGTH] = {0}; char remap_file[PATH_MAX_LENGTH] = {0}; config_file_t *conf = NULL; settings_t *settings = config_get_ptr(); fill_pathname_join(buf, settings->directory.input_remapping, path, sizeof(buf)); fill_pathname_noext(remap_file, buf, ".rmp", sizeof(remap_file)); conf = config_file_new(remap_file); if (!conf) { conf = config_file_new(NULL); if (!conf) return false; } for (i = 0; i < settings->input.max_users; i++) { char buf[64] = {0}; char key_ident[RARCH_FIRST_CUSTOM_BIND + 4][128] = {{0}}; char key_strings[RARCH_FIRST_CUSTOM_BIND + 4][128] = { "b", "y", "select", "start", "up", "down", "left", "right", "a", "x", "l", "r", "l2", "r2", "l3", "r3", "l_x", "l_y", "r_x", "r_y" }; snprintf(buf, sizeof(buf), "input_player%u", i + 1); for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 4; j++) { fill_pathname_join_delim(key_ident[j], buf, key_strings[j], '_', sizeof(key_ident[j])); /* only save values that have been modified */ if(j < RARCH_FIRST_CUSTOM_BIND) { if(settings->input.remap_ids[i][j] != j) config_set_int(conf, key_ident[j], settings->input.remap_ids[i][j]); else config_unset(conf,key_ident[j]); } else { if(settings->input.remap_ids[i][j] != j - RARCH_FIRST_CUSTOM_BIND) config_set_int(conf, key_ident[j], settings->input.remap_ids[i][j]); else config_unset(conf,key_ident[j]); } } snprintf(buf, sizeof(buf), "input_libretro_device_p%u", i + 1); config_set_int(conf, buf, settings->input.libretro_device[i]); snprintf(buf, sizeof(buf), "input_player%u_analog_dpad_mode", i + 1); config_set_int(conf, buf, settings->input.analog_dpad_mode[i]); } ret = config_file_write(conf, remap_file); config_file_free(conf); return ret; }
bool rarch_ctl(enum rarch_ctl_state state, void *data) { driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); switch(state) { case RARCH_ACTION_STATE_REPLACE_CONFIG: { char *path = (char*)data; if (!path) return false; /* If config file to be replaced is the same as the * current config file, exit. */ if (!strcmp(path, global->path.config)) return false; if (settings->config_save_on_exit && *global->path.config) config_save_file(global->path.config); strlcpy(global->path.config, path, sizeof(global->path.config)); global->block_config_read = false; *settings->libretro = '\0'; /* Load core in new config. */ } event_command(EVENT_CMD_PREPARE_DUMMY); return true; case RARCH_ACTION_STATE_MENU_RUNNING: #ifdef HAVE_MENU menu_driver_toggle(true); #endif #ifdef HAVE_OVERLAY if (settings->input.overlay_hide_in_menu) event_command(EVENT_CMD_OVERLAY_DEINIT); #endif break; case RARCH_ACTION_STATE_LOAD_CONTENT: #ifdef HAVE_MENU /* If content loading fails, we go back to menu. */ if (!menu_load_content(CORE_TYPE_PLAIN)) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL); #endif if (driver->frontend_ctx && driver->frontend_ctx->content_loaded) driver->frontend_ctx->content_loaded(); break; #ifdef HAVE_FFMPEG case RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG: #ifdef HAVE_MENU /* If content loading fails, we go back to menu. */ if (!menu_load_content(CORE_TYPE_FFMPEG)) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL); #endif if (driver->frontend_ctx && driver->frontend_ctx->content_loaded) driver->frontend_ctx->content_loaded(); break; #endif case RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER: #ifdef HAVE_MENU /* If content loading fails, we go back to menu. */ if (!menu_load_content(CORE_TYPE_IMAGEVIEWER)) rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL); #endif if (driver->frontend_ctx && driver->frontend_ctx->content_loaded) driver->frontend_ctx->content_loaded(); break; case RARCH_ACTION_STATE_MENU_RUNNING_FINISHED: #ifdef HAVE_MENU menu_driver_toggle(false); #endif video_driver_set_texture_enable(false, false); #ifdef HAVE_OVERLAY if (settings && settings->input.overlay_hide_in_menu) event_command(EVENT_CMD_OVERLAY_INIT); #endif break; case RARCH_ACTION_STATE_QUIT: if (global) system->shutdown = true; rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED, NULL); break; case RARCH_ACTION_STATE_FORCE_QUIT: rarch_ctl(RARCH_ACTION_STATE_QUIT, NULL); break; case RARCH_ACTION_STATE_VALIDATE_CPU_FEATURES: { uint64_t cpu = retro_get_cpu_features(); (void)cpu; #ifdef __SSE__ if (!(cpu & RETRO_SIMD_SSE)) FAIL_CPU("SSE"); #endif #ifdef __SSE2__ if (!(cpu & RETRO_SIMD_SSE2)) FAIL_CPU("SSE2"); #endif #ifdef __AVX__ if (!(cpu & RETRO_SIMD_AVX)) FAIL_CPU("AVX"); #endif } break; case RARCH_ACTION_STATE_VERIFY_API_VERSION: RARCH_LOG("Version of libretro API: %u\n", core.retro_api_version()); RARCH_LOG("Compiled against API: %u\n", RETRO_API_VERSION); if (core.retro_api_version() != RETRO_API_VERSION) RARCH_WARN("%s\n", msg_hash_to_str(MSG_LIBRETRO_ABI_BREAK)); break; case RARCH_ACTION_STATE_FILL_PATHNAMES: rarch_init_savefile_paths(); strlcpy(global->bsv.movie_path, global->name.savefile, sizeof(global->bsv.movie_path)); if (!*global->name.base) return false; if (!*global->name.ups) fill_pathname_noext(global->name.ups, global->name.base, ".ups", sizeof(global->name.ups)); if (!*global->name.bps) fill_pathname_noext(global->name.bps, global->name.base, ".bps", sizeof(global->name.bps)); if (!*global->name.ips) fill_pathname_noext(global->name.ips, global->name.base, ".ips", sizeof(global->name.ips)); break; case RARCH_ACTION_STATE_NONE: default: return false; } return true; }
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); } }
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; }
/** * input_remapping_save_file: * @path : Path to remapping file (relative path). * * Saves remapping values to file. * * Returns: true (1) if successful, otherwise false (0). **/ bool input_remapping_save_file(const char *path) { bool ret; unsigned i, j, k; size_t path_size = PATH_MAX_LENGTH * sizeof(char); char *buf = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *remap_file = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); config_file_t *conf = NULL; unsigned max_users = *(input_driver_get_uint(INPUT_ACTION_MAX_USERS)); settings_t *settings = config_get_ptr(); buf[0] = remap_file[0] = '\0'; fill_pathname_join(buf, settings->paths.directory_input_remapping, path, path_size); fill_pathname_noext(remap_file, buf, ".rmp", path_size); free(buf); conf = config_file_new(remap_file); if (!conf) { conf = config_file_new(NULL); if (!conf) { free(remap_file); return false; } } for (i = 0; i < max_users; i++) { char s1[64], s2[64], s3[64]; char btn_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; char key_ident[RARCH_FIRST_CUSTOM_BIND][128] = {{0}}; char stk_ident[8][128] = {{0}}; char key_strings[RARCH_FIRST_CUSTOM_BIND + 8][128] = { "b", "y", "select", "start", "up", "down", "left", "right", "a", "x", "l", "r", "l2", "r2", "l3", "r3", "l_x+", "l_x-", "l_y+", "l_y-", "r_x+", "r_x-", "r_y+", "r_y-" }; s1[0] = '\0'; s2[0] = '\0'; snprintf(s1, sizeof(s1), "input_player%u_btn", i + 1); snprintf(s2, sizeof(s2), "input_player%u_key", i + 1); snprintf(s3, sizeof(s1), "input_player%u_stk", i + 1); for (j = 0; j < RARCH_FIRST_CUSTOM_BIND + 8; j++) { if(j < RARCH_FIRST_CUSTOM_BIND) { fill_pathname_join_delim(btn_ident[j], s1, key_strings[j], '_', sizeof(btn_ident[j])); fill_pathname_join_delim(key_ident[j], s2, key_strings[j], '_', sizeof(btn_ident[j])); /* only save values that have been modified */ if(settings->uints.input_remap_ids[i][j] != j && settings->uints.input_remap_ids[i][j] != RARCH_UNMAPPED) config_set_int(conf, btn_ident[j], settings->uints.input_remap_ids[i][j]); else if (settings->uints.input_remap_ids[i][j] != j && settings->uints.input_remap_ids[i][j] == RARCH_UNMAPPED) config_set_int(conf, btn_ident[j], -1); else config_unset(conf,btn_ident[j]); if (settings->uints.input_keymapper_ids[i][j] != RETROK_UNKNOWN) config_set_int(conf, key_ident[j], settings->uints.input_keymapper_ids[i][j]); } else { k = j - RARCH_FIRST_CUSTOM_BIND; fill_pathname_join_delim(stk_ident[k], s3, key_strings[j], '_', sizeof(stk_ident[k])); if(settings->uints.input_remap_ids[i][j] != j && settings->uints.input_remap_ids[i][j] != RARCH_UNMAPPED) config_set_int(conf, stk_ident[k], settings->uints.input_remap_ids[i][j]); else if(settings->uints.input_remap_ids[i][j] != j && settings->uints.input_remap_ids[i][j] == RARCH_UNMAPPED) config_set_int(conf, stk_ident[k], -1); else config_unset(conf, stk_ident[k]); } } snprintf(s1, sizeof(s1), "input_libretro_device_p%u", i + 1); config_set_int(conf, s1, input_config_get_device(i)); snprintf(s1, sizeof(s1), "input_player%u_analog_dpad_mode", i + 1); config_set_int(conf, s1, settings->uints.input_analog_dpad_mode[i]); } ret = config_file_write(conf, remap_file); config_file_free(conf); free(remap_file); return ret; }