1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 04:32:35 +01:00

Savestates: Facilitate multi slots

This commit is contained in:
Eladash 2023-07-23 10:48:17 +03:00 committed by Elad Ashkenazi
parent 12fe55a258
commit fce8e0fef0
3 changed files with 30 additions and 7 deletions

View File

@ -82,7 +82,7 @@ extern std::pair<std::shared_ptr<lv2_overlay>, CellError> ppu_load_overlay(const
extern bool ppu_load_rel_exec(const ppu_rel_object&); extern bool ppu_load_rel_exec(const ppu_rel_object&);
extern bool is_savestate_version_compatible(const std::vector<std::pair<u16, u16>>& data, bool is_boot_check); extern bool is_savestate_version_compatible(const std::vector<std::pair<u16, u16>>& data, bool is_boot_check);
extern std::vector<std::pair<u16, u16>> read_used_savestate_versions(); extern std::vector<std::pair<u16, u16>> read_used_savestate_versions();
std::string get_savestate_path(std::string_view title_id, std::string_view boot_path); std::string get_savestate_file(std::string_view title_id, std::string_view boot_path, s64 abs_id, s64 rel_id);
extern void send_close_home_menu_cmds(); extern void send_close_home_menu_cmds();
@ -492,7 +492,7 @@ void Emulator::Init()
make_path_verbose(fs::get_cache_dir() + "shaderlog/", false); make_path_verbose(fs::get_cache_dir() + "shaderlog/", false);
make_path_verbose(fs::get_cache_dir() + "spu_progs/", false); make_path_verbose(fs::get_cache_dir() + "spu_progs/", false);
make_path_verbose(fs::get_cache_dir() + "/savestates/", false); make_path_verbose(fs::get_parent_dir(get_savestate_file("NO_ID", "/NO_FILE", -1, -1)), false);
make_path_verbose(fs::get_config_dir() + "captures/", false); make_path_verbose(fs::get_config_dir() + "captures/", false);
make_path_verbose(fs::get_config_dir() + "sounds/", false); make_path_verbose(fs::get_config_dir() + "sounds/", false);
make_path_verbose(patch_engine::get_patches_path(), false); make_path_verbose(patch_engine::get_patches_path(), false);
@ -2180,7 +2180,7 @@ void Emulator::FixGuestTime()
// Mark a known savestate location and the one we try to boot (in case we boot a moved/copied savestate) // Mark a known savestate location and the one we try to boot (in case we boot a moved/copied savestate)
if (g_cfg.savestate.suspend_emu) if (g_cfg.savestate.suspend_emu)
{ {
for (std::string old_path : std::initializer_list<std::string>{m_ar ? m_path_old : "", m_title_id.empty() ? "" : get_savestate_path(m_title_id, m_path_old)}) for (std::string old_path : std::initializer_list<std::string>{m_ar ? m_path_old : "", m_title_id.empty() ? "" : get_savestate_file(m_title_id, m_path_old, 0, 0)})
{ {
if (old_path.empty()) if (old_path.empty())
{ {
@ -2841,7 +2841,12 @@ void Emulator::Kill(bool allow_autoexit, bool savestate)
if (savestate) if (savestate)
{ {
const std::string path = get_savestate_path(m_title_id, m_path); const std::string path = get_savestate_file(m_title_id, m_path, 0, 0);
if (!fs::create_path(fs::get_parent_dir(path)))
{
sys_log.error("Failed to create savestate directory! (path='%s', %s)", fs::get_parent_dir(path), fs::g_tls_error);
}
fs::pending_file file(path); fs::pending_file file(path);

View File

@ -146,9 +146,25 @@ bool is_savestate_version_compatible(const std::vector<std::pair<u16, u16>>& dat
return ok; return ok;
} }
std::string get_savestate_path(std::string_view title_id, std::string_view boot_path) std::string get_savestate_file(std::string_view title_id, std::string_view boot_path, s64 abs_id, s64 rel_id)
{ {
return fs::get_cache_dir() + "/savestates/" + std::string{title_id.empty() ? boot_path.substr(boot_path.find_last_of(fs::delim) + 1) : title_id} + ".SAVESTAT"; const std::string title = std::string{title_id.empty() ? boot_path.substr(boot_path.find_last_of(fs::delim) + 1) : title_id};
if (abs_id == -1 && rel_id == -1)
{
// Return directory
return fs::get_cache_dir() + "/savestates/" + title + "/";
}
ensure(rel_id < 0 || abs_id >= 0, "Unimplemented!");
const std::string save_id = fmt::format("%d", abs_id);
// Make sure that savestate file with higher IDs are placed at the bottom of "by name" file ordering in directory view by adding a single character prefix which tells the ID length
// While not needing to keep a 59 chars long suffix at all times for this purpose
const char prefix = ::at32("0123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"sv, save_id.size());
return fs::get_cache_dir() + "/savestates/" + title + "/" + title + '_' + prefix + '_' + save_id + ".SAVESTAT";
} }
bool is_savestate_compatible(const fs::file& file) bool is_savestate_compatible(const fs::file& file)

View File

@ -50,6 +50,8 @@ LOG_CHANNEL(sys_log, "SYS");
extern atomic_t<bool> g_system_progress_canceled; extern atomic_t<bool> g_system_progress_canceled;
std::string get_savestate_file(std::string_view title_id, std::string_view boot_pat, s64 abs_id, s64 rel_id);
inline std::string sstr(const QString& _in) { return _in.toStdString(); } inline std::string sstr(const QString& _in) { return _in.toStdString(); }
game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std::shared_ptr<emu_settings> emu_settings, std::shared_ptr<persistent_settings> persistent_settings, QWidget* parent) game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std::shared_ptr<emu_settings> emu_settings, std::shared_ptr<persistent_settings> persistent_settings, QWidget* parent)
@ -1078,7 +1080,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
extern bool is_savestate_compatible(const fs::file& file); extern bool is_savestate_compatible(const fs::file& file);
if (const std::string sstate = fs::get_cache_dir() + "/savestates/" + current_game.serial + ".SAVESTAT"; is_savestate_compatible(fs::file(sstate))) if (const std::string sstate = get_savestate_file(current_game.serial, current_game.path, 0, 0); is_savestate_compatible(fs::file(sstate)))
{ {
QAction* boot_state = menu.addAction(is_current_running_game QAction* boot_state = menu.addAction(is_current_running_game
? tr("&Reboot with savestate") ? tr("&Reboot with savestate")