mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-11-26 20:50:40 +00:00
SaveDataLib: use param.sfo to store max_blocks instead of txt (#1287)
This commit is contained in:
parent
01fb320f4e
commit
96344873d6
@ -227,6 +227,12 @@ void PSF::AddBinary(std::string key, std::vector<u8> value, bool update) {
|
||||
map_binaries.emplace(entry_list.size() - 1, std::move(value));
|
||||
}
|
||||
|
||||
void PSF::AddBinary(std::string key, uint64_t value, bool update) {
|
||||
std::vector<u8> data(8);
|
||||
std::memcpy(data.data(), &value, 8);
|
||||
return AddBinary(std::move(key), std::move(data), update);
|
||||
}
|
||||
|
||||
void PSF::AddString(std::string key, std::string value, bool update) {
|
||||
auto [it, index] = FindEntry(key);
|
||||
bool exist = it != entry_list.end();
|
||||
|
@ -67,6 +67,7 @@ public:
|
||||
std::optional<s32> GetInteger(std::string_view key) const;
|
||||
|
||||
void AddBinary(std::string key, std::vector<u8> value, bool update = false);
|
||||
void AddBinary(std::string key, uint64_t value, bool update = false); // rsv4 format
|
||||
void AddString(std::string key, std::string value, bool update = false);
|
||||
void AddInteger(std::string key, s32 value, bool update = false);
|
||||
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include "core/file_sys/fs.h"
|
||||
#include "save_instance.h"
|
||||
|
||||
constexpr u32 OrbisSaveDataBlocksMax = 32768; // 1 GiB
|
||||
constexpr auto OrbisSaveDataBlocksMin2 = 96; // 3MiB
|
||||
constexpr auto OrbisSaveDataBlocksMax = 32768; // 1 GiB
|
||||
constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save
|
||||
constexpr std::string_view max_block_file_name = "max_block.txt";
|
||||
|
||||
static Core::FileSys::MntPoints* g_mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
||||
|
||||
@ -58,18 +58,13 @@ std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_
|
||||
game_serial / dir_name;
|
||||
}
|
||||
|
||||
int SaveInstance::GetMaxBlocks(const std::filesystem::path& save_path) {
|
||||
Common::FS::IOFile max_blocks_file{save_path / sce_sys / max_block_file_name,
|
||||
Common::FS::FileAccessMode::Read};
|
||||
int max_blocks = 0;
|
||||
if (max_blocks_file.IsOpen()) {
|
||||
max_blocks = std::atoi(max_blocks_file.ReadString(16).c_str());
|
||||
uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) {
|
||||
const auto vec = psf.GetBinary(std::string{SaveParams::SAVEDATA_BLOCKS});
|
||||
if (!vec.has_value()) {
|
||||
return OrbisSaveDataBlocksMax;
|
||||
}
|
||||
if (max_blocks <= 0) {
|
||||
max_blocks = OrbisSaveDataBlocksMax;
|
||||
}
|
||||
|
||||
return max_blocks;
|
||||
auto value = vec.value();
|
||||
return *(uint64_t*)value.data();
|
||||
}
|
||||
|
||||
std::filesystem::path SaveInstance::GetParamSFOPath(const std::filesystem::path& dir_path) {
|
||||
@ -92,13 +87,15 @@ void SaveInstance::SetupDefaultParamSFO(PSF& param_sfo, std::string dir_name,
|
||||
P(String, SaveParams::SAVEDATA_DIRECTORY, std::move(dir_name));
|
||||
P(Integer, SaveParams::SAVEDATA_LIST_PARAM, 0);
|
||||
P(String, SaveParams::TITLE_ID, std::move(game_serial));
|
||||
P(Binary, SaveParams::SAVEDATA_BLOCKS, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||
#undef P
|
||||
}
|
||||
|
||||
SaveInstance::SaveInstance(int slot_num, OrbisUserServiceUserId user_id, std::string _game_serial,
|
||||
std::string_view _dir_name, int max_blocks)
|
||||
: slot_num(slot_num), user_id(user_id), game_serial(std::move(_game_serial)),
|
||||
dir_name(_dir_name), max_blocks(max_blocks) {
|
||||
dir_name(_dir_name),
|
||||
max_blocks(std::clamp(max_blocks, OrbisSaveDataBlocksMin2, OrbisSaveDataBlocksMax)) {
|
||||
ASSERT(slot_num >= 0 && slot_num < 16);
|
||||
|
||||
save_path = MakeDirSavePath(user_id, game_serial, dir_name);
|
||||
@ -187,7 +184,7 @@ void SaveInstance::SetupAndMount(bool read_only, bool copy_icon, bool ignore_cor
|
||||
}
|
||||
}
|
||||
|
||||
max_blocks = GetMaxBlocks(save_path);
|
||||
max_blocks = static_cast<int>(GetMaxBlockFromSFO(param_sfo));
|
||||
|
||||
g_mnt->Mount(save_path, mount_point, read_only);
|
||||
mounted = true;
|
||||
@ -217,16 +214,13 @@ void SaveInstance::CreateFiles() {
|
||||
fs::create_directories(sce_sys_dir);
|
||||
|
||||
SetupDefaultParamSFO(param_sfo, dir_name, game_serial);
|
||||
param_sfo.AddBinary(std::string{SaveParams::SAVEDATA_BLOCKS}, max_blocks, true);
|
||||
|
||||
const bool ok = param_sfo.Encode(param_sfo_path);
|
||||
if (!ok) {
|
||||
throw std::filesystem::filesystem_error("Failed to write param.sfo", param_sfo_path,
|
||||
std::make_error_code(std::errc::permission_denied));
|
||||
}
|
||||
|
||||
Common::FS::IOFile max_block{sce_sys_dir / max_block_file_name,
|
||||
Common::FS::FileAccessMode::Write};
|
||||
max_block.WriteString(std::to_string(max_blocks == 0 ? OrbisSaveDataBlocksMax : max_blocks));
|
||||
}
|
||||
|
||||
} // namespace Libraries::SaveData
|
@ -62,7 +62,7 @@ public:
|
||||
std::string_view game_serial,
|
||||
std::string_view dir_name);
|
||||
|
||||
static int GetMaxBlocks(const std::filesystem::path& save_path);
|
||||
static uint64_t GetMaxBlockFromSFO(const PSF& psf);
|
||||
|
||||
// Get param.sfo path from a dir_path generated by MakeDirSavePath
|
||||
static std::filesystem::path GetParamSFOPath(const std::filesystem::path& dir_path);
|
||||
|
@ -445,7 +445,7 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info,
|
||||
fs::create_directories(root_save);
|
||||
const auto available = fs::space(root_save).available;
|
||||
|
||||
auto requested_size = mount_info->blocks * OrbisSaveDataBlockSize;
|
||||
auto requested_size = save_instance.GetMaxBlocks() * OrbisSaveDataBlockSize;
|
||||
if (requested_size > available) {
|
||||
mount_result->required_blocks = (requested_size - available) / OrbisSaveDataBlockSize;
|
||||
return Error::NO_SPACE_FS;
|
||||
@ -830,10 +830,11 @@ Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond
|
||||
LOG_ERROR(Lib_SaveData, "Failed to read SFO: {}", fmt::UTF(sfo_path.u8string()));
|
||||
ASSERT_MSG(false, "Failed to read SFO");
|
||||
}
|
||||
map_dir_sfo.emplace(dir_name, std::move(sfo));
|
||||
|
||||
size_t size = Common::FS::GetDirectorySize(dir_path);
|
||||
size_t total = SaveInstance::GetMaxBlocks(dir_path);
|
||||
size_t total = SaveInstance::GetMaxBlockFromSFO(sfo);
|
||||
|
||||
map_dir_sfo.emplace(dir_name, std::move(sfo));
|
||||
map_free_size.emplace(dir_name, total - size / OrbisSaveDataBlockSize);
|
||||
map_max_blocks.emplace(dir_name, total);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user