SaveDataLib: use param.sfo to store max_blocks instead of txt (#1287)

This commit is contained in:
Vinicius Rangel 2024-10-08 03:16:06 -03:00 committed by GitHub
parent 01fb320f4e
commit 96344873d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 25 additions and 23 deletions

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);
}