mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-20 22:05:12 +00:00
Atomic PARAM.SFO writes
This commit is contained in:
parent
0878db4e17
commit
932f31e37b
9 changed files with 108 additions and 11 deletions
|
|
@ -666,7 +666,9 @@ error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPa
|
|||
if (!perm->temp.empty())
|
||||
{
|
||||
// Create PARAM.SFO
|
||||
psf::save_object(fs::file(perm->temp + "/PARAM.SFO", fs::rewrite), perm->sfo);
|
||||
fs::pending_file temp(perm->temp + "/PARAM.SFO");
|
||||
temp.file.write(psf::save_object(perm->sfo));
|
||||
ensure(temp.commit());
|
||||
|
||||
// Make temporary directory persistent (atomically)
|
||||
if (vfs::host::rename(perm->temp, vfs::get(dir), &g_mp_sys_dev_hdd0, false))
|
||||
|
|
@ -684,7 +686,9 @@ error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPa
|
|||
else if (perm->can_create)
|
||||
{
|
||||
// Update PARAM.SFO
|
||||
psf::save_object(fs::file(vfs::get(dir + "/PARAM.SFO"), fs::rewrite), perm->sfo);
|
||||
fs::pending_file temp(vfs::get(dir + "/PARAM.SFO"));
|
||||
temp.file.write(psf::save_object(perm->sfo));
|
||||
ensure(temp.commit());
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
|
|
@ -806,7 +810,9 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
|||
psf::assign(sfo, fmt::format("TITLE_%02d", i), psf::string(CELL_GAME_SYSP_TITLE_SIZE, setParam->titleLang[i]));
|
||||
}
|
||||
|
||||
psf::save_object(fs::file(vfs::get(dir + "/PARAM.SFO"), fs::rewrite), sfo);
|
||||
fs::pending_file temp(vfs::get(dir + "/PARAM.SFO"));
|
||||
temp.file.write(psf::save_object(sfo));
|
||||
ensure(temp.commit());
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
|
|
|||
|
|
@ -1306,7 +1306,12 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
|
||||
if (!entry.is_directory)
|
||||
{
|
||||
if (entry.name == "PARAM.SFO" || entry.name == "PARAM.PFD")
|
||||
if (entry.name == "."sv)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.name == "PARAM.SFO"sv || entry.name == "PARAM.PFD"sv)
|
||||
{
|
||||
continue; // system files are not included in the file list
|
||||
}
|
||||
|
|
@ -1899,7 +1904,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
// Write all files in temporary directory
|
||||
auto& fsfo = all_files["PARAM.SFO"];
|
||||
fsfo = fs::make_stream<std::vector<uchar>>();
|
||||
psf::save_object(fsfo, psf);
|
||||
fsfo.write(psf::save_object(psf));
|
||||
|
||||
for (auto&& pair : all_files)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -768,6 +768,13 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
|
|||
// Preprocess entries
|
||||
data.back().name = vfs::unescape(data.back().name);
|
||||
|
||||
if (!data.back().is_directory && data.back().name == "."sv)
|
||||
{
|
||||
// Files hidden from emulation
|
||||
data.resize(data.size() - 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add additional entries for split file candidates (while ends with .66600)
|
||||
while (data.back().name.ends_with(".66600"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1299,8 +1299,10 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
games[m_title_id] = bdvd_dir;
|
||||
YAML::Emitter out;
|
||||
out << games;
|
||||
fs::file(fs::get_config_dir() + "/games.yml.tmp", fs::rewrite).write(out.c_str(), out.size());
|
||||
fs::rename(fs::get_config_dir() + "/games.yml.tmp", fs::get_config_dir() + "/games.yml", true);
|
||||
|
||||
fs::pending_file temp(fs::get_config_dir() + "/games.yml");
|
||||
temp.file.write(out.c_str(), out.size());
|
||||
temp.commit();
|
||||
}
|
||||
else if (m_cat == "1P" && from_hdd0_game)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ namespace psf
|
|||
return result;
|
||||
}
|
||||
|
||||
stream.seek(0);
|
||||
|
||||
// Get header
|
||||
header_t header;
|
||||
ensure(stream.read(header));
|
||||
|
|
@ -186,8 +188,10 @@ namespace psf
|
|||
return result;
|
||||
}
|
||||
|
||||
void save_object(const fs::file& stream, const psf::registry& psf)
|
||||
std::vector<u8> save_object(const psf::registry& psf, std::vector<u8>&& init)
|
||||
{
|
||||
fs::file stream = fs::make_stream<std::vector<u8>>(std::move(init));
|
||||
|
||||
std::vector<def_table_t> indices; indices.reserve(psf.size());
|
||||
|
||||
// Generate indices and calculate key table length
|
||||
|
|
@ -264,6 +268,8 @@ namespace psf
|
|||
fmt::throw_exception("Invalid entry format (key='%s', fmt=0x%x)", entry.first, fmt);
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(static_cast<fs::container_stream<std::vector<u8>>*>(stream.release().get())->obj);
|
||||
}
|
||||
|
||||
std::string_view get_string(const registry& psf, const std::string& key, std::string_view def)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace psf
|
|||
registry load_object(const fs::file&);
|
||||
|
||||
// Convert PSF registry to SFO binary format
|
||||
void save_object(const fs::file&, const registry&);
|
||||
std::vector<u8> save_object(const registry&, std::vector<u8>&& init = std::vector<u8>{});
|
||||
|
||||
// Get string value or default value
|
||||
std::string_view get_string(const registry& psf, const std::string& key, std::string_view def = ""sv);
|
||||
|
|
|
|||
|
|
@ -190,8 +190,9 @@ void emu_settings::SaveSettings()
|
|||
}
|
||||
|
||||
// Save config atomically
|
||||
fs::file(config_name + ".tmp", fs::rewrite).write(out.c_str(), out.size());
|
||||
fs::rename(config_name + ".tmp", config_name, true);
|
||||
fs::pending_file temp(config_name);
|
||||
temp.file.write(out.c_str(), out.size());
|
||||
temp.commit();
|
||||
|
||||
// Check if the running config/title is the same as the edited config/title.
|
||||
if (config_name == g_cfg.name || m_title_id == Emu.GetTitleID())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue