/** * fill_short_pathname_representation: * @out_rep : output representation * @in_path : input path * @size : size of output representation * * Generates a short representation of path. It should only * be used for displaying the result; the output representation is not * binding in any meaningful way (for a normal path, this is the same as basename) * In case of more complex URLs, this should cut everything except for * the main image file. * * E.g.: "/path/to/game.img" -> game.img * "/path/to/myarchive.7z#folder/to/game.img" -> game.img */ void fill_short_pathname_representation_wrapper(char* out_rep, const char *in_path, size_t size) { #ifdef HAVE_COMPRESSION char *path_short = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); char *last_slash = NULL; path_short[0] = '\0'; fill_pathname(path_short, path_basename(in_path), "", PATH_MAX_LENGTH * sizeof(char) ); last_slash = find_last_slash(path_short); if (last_slash != NULL) { /* We handle paths like: * /path/to/file.7z#mygame.img * short_name: mygame.img: * * We check whether something is actually * after the hash to avoid going over the buffer. */ retro_assert(strlen(last_slash) > 1); strlcpy(out_rep, last_slash + 1, size); free(path_short); return; } free(path_short); #endif fill_short_pathname_representation(out_rep, in_path, size); }
/** * fill_short_pathname_representation: * @out_rep : output representation * @in_path : input path * @size : size of output representation * * Generates a short representation of path. It should only * be used for displaying the result; the output representation is not * binding in any meaningful way (for a normal path, this is the same as basename) * In case of more complex URLs, this should cut everything except for * the main image file. * * E.g.: "/path/to/game.img" -> game.img * "/path/to/myarchive.7z#folder/to/game.img" -> game.img */ void fill_short_pathname_representation(char* out_rep, const char *in_path, size_t size) { char path_short[PATH_MAX_LENGTH] = {0}; char *last_hash = NULL; fill_pathname(path_short, path_basename(in_path), "", sizeof(path_short)); last_hash = (char*)strchr(path_short,'#'); /* We handle paths like: * /path/to/file.7z#mygame.img * short_name: mygame.img: */ if(last_hash != NULL) { /* We check whether something is actually * after the hash to avoid going over the buffer. */ rarch_assert(strlen(last_hash) > 1); strlcpy(out_rep,last_hash + 1, size); } else strlcpy(out_rep,path_short, size); }
/** * fill_short_pathname_representation: * @out_rep : output representation * @in_path : input path * @size : size of output representation * * Generates a short representation of path. It should only * be used for displaying the result; the output representation is not * binding in any meaningful way (for a normal path, this is the same as basename) * In case of more complex URLs, this should cut everything except for * the main image file. * * E.g.: "/path/to/game.img" -> game.img * "/path/to/myarchive.7z#folder/to/game.img" -> game.img */ void fill_short_pathname_representation(char* out_rep, const char *in_path, size_t size) { char path_short[PATH_MAX_LENGTH]; #ifdef HAVE_COMPRESSION char *last_slash = NULL; #endif path_short[0] = '\0'; fill_pathname(path_short, path_basename(in_path), "", sizeof(path_short)); #ifdef HAVE_COMPRESSION last_slash = find_last_slash(path_short); if (last_slash != NULL) { /* We handle paths like: * /path/to/file.7z#mygame.img * short_name: mygame.img: * * We check whether something is actually * after the hash to avoid going over the buffer. */ retro_assert(strlen(last_slash) > 1); strlcpy(out_rep, last_slash + 1, size); } else #endif strlcpy(out_rep, path_short, size); }
const char *core_info_get_custom_config(const char *core_id, char *buffer, size_t buffer_length) { if (!core_id || !buffer || !buffer_length) return 0; fill_pathname_join(buffer, g_defaults.menu_config_dir, path_basename(core_id), buffer_length); fill_pathname(buffer, buffer, ".cfg", buffer_length); return buffer; }
/** * fill_short_pathname_representation: * @out_rep : output representation * @in_path : input path * @size : size of output representation * * Generates a short representation of path. It should only * be used for displaying the result; the output representation is not * binding in any meaningful way (for a normal path, this is the same as basename) * In case of more complex URLs, this should cut everything except for * the main image file. * * E.g.: "/path/to/game.img" -> game.img * "/path/to/myarchive.7z#folder/to/game.img" -> game.img */ void fill_short_pathname_representation(char* out_rep, const char *in_path, size_t size) { char path_short[PATH_MAX_LENGTH]; path_short[0] = '\0'; fill_pathname(path_short, path_basename(in_path), "", sizeof(path_short)); strlcpy(out_rep, path_short, size); }
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 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); } }
int lutro_load(const char *path) { char mainfile[PATH_MAX_LENGTH]; char gamedir[PATH_MAX_LENGTH]; strlcpy(mainfile, path, PATH_MAX_LENGTH); strlcpy(gamedir, path, PATH_MAX_LENGTH); if (path_is_directory(mainfile)) fill_pathname_join(mainfile, gamedir, "main.lua", sizeof(mainfile)); else path_basedir(gamedir); if (!strcmp(path_get_extension(mainfile), "lutro")) { fill_pathname(gamedir, mainfile, "/", sizeof(gamedir)); lutro_unzip(mainfile, gamedir); fill_pathname_join(mainfile, gamedir, "main.lua", sizeof(mainfile)); } fill_pathname_slash(gamedir, sizeof(gamedir)); char package_path[PATH_MAX_LENGTH]; snprintf(package_path, PATH_MAX_LENGTH, ";%s?.lua;%s?/init.lua", gamedir, gamedir); lutro_set_package_path(L, package_path); if(luaL_dofile(L, mainfile)) { fprintf(stderr, "%s\n", lua_tostring(L, -1)); lua_pop(L, 1); return 0; } lua_getglobal(L, "lutro"); strlcpy(settings.gamedir, gamedir, PATH_MAX_LENGTH); lua_pushnumber(L, 0); lua_setfield(L, -2, "camera_x"); lua_pushnumber(L, 0); lua_setfield(L, -2, "camera_y"); lua_getfield(L, -1, "conf"); if (lua_isnoneornil(L, -1)) { puts("skipping custom configuration."); } else { lua_getfield(L, -2, "settings"); if(lua_pcall(L, 1, 0, 0)) { fprintf(stderr, "%s\n", lua_tostring(L, -1)); lua_pop(L, 1); return 0; } lua_getfield(L, -1, "settings"); lua_getfield(L, -1, "width"); settings.width = lua_tointeger(L, -1); lua_remove(L, -1); lua_getfield(L, -1, "height"); settings.height = lua_tointeger(L, -1); lua_remove(L, -1); lua_getfield(L, -1, "live_enable"); settings.live_enable = lua_toboolean(L, -1); lua_remove(L, -1); lua_getfield(L, -1, "live_call_load"); settings.live_call_load = lua_toboolean(L, -1); lua_remove(L, -1); } lua_pop(L, 1); // either lutro.settings or lutro.conf lutro_graphics_init(); #ifdef HAVE_INOTIFY if (settings.live_enable) lutro_live_init(); #endif lua_getfield(L, -1, "load"); if (lua_isnoneornil(L, -1)) { puts("skipping custom initialization."); } else { if(lua_pcall(L, 0, 0, 0)) { fprintf(stderr, "%s\n", lua_tostring(L, -1)); lua_pop(L, 1); return 0; } } lua_pop(L, 1); return 1; }
static void init_menulist(unsigned menu_id) { XuiListDeleteItems(m_menulist, 0, XuiListGetItemCount(m_menulist)); switch (menu_id) { case INGAME_MENU_CORE_OPTIONS_MODE: if (g_extern.system.core_options) { size_t opts = core_option_size(g_extern.system.core_options); for (size_t i = 0; i < opts; i++) { char label[256]; strlcpy(label, core_option_get_desc(g_extern.system.core_options, i), sizeof(label)); snprintf(label, sizeof(label), "%s : %s", label, core_option_get_val(g_extern.system.core_options, i)); mbstowcs(strw_buffer, label, sizeof(strw_buffer) / sizeof(wchar_t)); XuiListInsertItems(m_menulist, i, 1); XuiListSetText(m_menulist, i, strw_buffer); } } else { XuiListInsertItems(m_menulist, 0, 1); XuiListSetText(m_menulist, 0, L"No options available."); } break; case INGAME_MENU_LOAD_GAME_HISTORY_MODE: { size_t history_size = rom_history_size(rgui->history); if (history_size) { size_t opts = history_size; for (size_t i = 0; i < opts; i++) { const char *path = NULL; const char *core_path = NULL; const char *core_name = NULL; rom_history_get_index(rgui->history, i, &path, &core_path, &core_name); char path_short[PATH_MAX]; fill_pathname(path_short, path_basename(path), "", sizeof(path_short)); char fill_buf[PATH_MAX]; snprintf(fill_buf, sizeof(fill_buf), "%s (%s)", path_short, core_name); mbstowcs(strw_buffer, fill_buf, sizeof(strw_buffer) / sizeof(wchar_t)); XuiListInsertItems(m_menulist, i, 1); XuiListSetText(m_menulist, i, strw_buffer); } } else { XuiListInsertItems(m_menulist, 0, 1); XuiListSetText(m_menulist, 0, L"No history available."); } } break; case INGAME_MENU_INPUT_OPTIONS_MODE: { unsigned i; char buttons[RARCH_FIRST_META_KEY][128]; unsigned keybind_end = RETRO_DEVICE_ID_JOYPAD_R3 + 1; for(i = 0; i < keybind_end; i++) { struct platform_bind key_label; strlcpy(key_label.desc, "Unknown", sizeof(key_label.desc)); key_label.joykey = g_settings.input.binds[rgui->current_pad][i].joykey; if (driver.input->set_keybinds) driver.input->set_keybinds(&key_label, 0, 0, 0, (1ULL << KEYBINDS_ACTION_GET_BIND_LABEL)); snprintf(buttons[i], sizeof(buttons[i]), "%s #%d: %s", g_settings.input.binds[rgui->current_pad][i].desc, rgui->current_pad, key_label.desc); mbstowcs(strw_buffer, buttons[i], sizeof(strw_buffer) / sizeof(wchar_t)); XuiListInsertItems(m_menulist, i, 1); XuiListSetText(m_menulist, i, strw_buffer); } //set_dpad_emulation_label(rgui->current_pad, buttons[0], sizeof(buttons[0])); //mbstowcs(strw_buffer, buttons[0], sizeof(strw_buffer) / sizeof(wchar_t)); XuiListInsertItems(m_menulist, keybind_end, 1); //XuiListSetText(m_menulist, SETTING_CONTROLS_DPAD_EMULATION, strw_buffer); XuiListSetText(m_menulist, SETTING_CONTROLS_DPAD_EMULATION, L"Stub"); XuiListInsertItems(m_menulist, keybind_end + 1, 1); XuiListSetText(m_menulist, SETTING_CONTROLS_DEFAULT_ALL, L"Reset all buttons to default"); } break; case INGAME_MENU_SETTINGS_MODE: XuiListInsertItems(m_menulist, INGAME_MENU_REWIND_ENABLED, 1); XuiListSetText(m_menulist, INGAME_MENU_REWIND_ENABLED, g_settings.rewind_enable ? L"Rewind: ON" : L"Rewind: OFF"); menu_settings_create_menu_item_label_w(strw_buffer, S_LBL_REWIND_GRANULARITY, sizeof(strw_buffer)); XuiListInsertItems(m_menulist, INGAME_MENU_REWIND_GRANULARITY, 1); XuiListSetText(m_menulist, INGAME_MENU_REWIND_GRANULARITY, strw_buffer); XuiListInsertItems(m_menulist, SETTING_EMU_SHOW_DEBUG_INFO_MSG, 1); XuiListSetText(m_menulist, SETTING_EMU_SHOW_DEBUG_INFO_MSG, (g_settings.fps_show) ? L"Show Framerate: ON" : L"Show Framerate: OFF"); break; case INGAME_MENU_MAIN_MODE: XuiListInsertItems(m_menulist, INGAME_MENU_CHANGE_LIBRETRO_CORE, 1); XuiListSetText(m_menulist, INGAME_MENU_CHANGE_LIBRETRO_CORE, L"Core ..."); XuiListInsertItems(m_menulist, INGAME_MENU_LOAD_GAME_HISTORY_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_LOAD_GAME_HISTORY_MODE, L"Load Game (History) ..."); XuiListInsertItems(m_menulist, INGAME_MENU_CHANGE_GAME, 1); XuiListSetText(m_menulist, INGAME_MENU_CHANGE_GAME, L"Load Game ..."); XuiListInsertItems(m_menulist, INGAME_MENU_CORE_OPTIONS_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_CORE_OPTIONS_MODE, L"Core Options ..."); XuiListInsertItems(m_menulist, INGAME_MENU_VIDEO_OPTIONS_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_VIDEO_OPTIONS_MODE, L"Video Options ..."); XuiListInsertItems(m_menulist, INGAME_MENU_AUDIO_OPTIONS_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_AUDIO_OPTIONS_MODE, L"Audio Options ..."); XuiListInsertItems(m_menulist, INGAME_MENU_INPUT_OPTIONS_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_INPUT_OPTIONS_MODE, L"Input Options ..."); XuiListInsertItems(m_menulist, INGAME_MENU_PATH_OPTIONS_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_PATH_OPTIONS_MODE, L"Path Options ..."); XuiListInsertItems(m_menulist, INGAME_MENU_SETTINGS_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_SETTINGS_MODE, L"Settings ..."); menu_settings_create_menu_item_label_w(strw_buffer, S_LBL_LOAD_STATE_SLOT, sizeof(strw_buffer)); XuiListInsertItems(m_menulist, INGAME_MENU_LOAD_STATE, 1); XuiListSetText(m_menulist, INGAME_MENU_LOAD_STATE, strw_buffer); menu_settings_create_menu_item_label_w(strw_buffer, S_LBL_SAVE_STATE_SLOT, sizeof(strw_buffer)); XuiListInsertItems(m_menulist, INGAME_MENU_SAVE_STATE, 1); XuiListSetText(m_menulist, INGAME_MENU_SAVE_STATE, strw_buffer); XuiListInsertItems(m_menulist, INGAME_MENU_SCREENSHOT_MODE, 1); XuiListSetText(m_menulist, INGAME_MENU_SCREENSHOT_MODE, L"Take Screenshot"); XuiListInsertItems(m_menulist, INGAME_MENU_RETURN_TO_GAME, 1); XuiListSetText(m_menulist, INGAME_MENU_RETURN_TO_GAME, L"Resume Game"); XuiListInsertItems(m_menulist, INGAME_MENU_RESET, 1); XuiListSetText(m_menulist, INGAME_MENU_RESET, L"Restart Game"); XuiListInsertItems(m_menulist, INGAME_MENU_QUIT_RETROARCH, 1); XuiListSetText(m_menulist, INGAME_MENU_QUIT_RETROARCH, L"Quit RetroArch"); break; } }
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; }