savedata_factory: Implement savedata creation and don't create dir on open

Matches hardware behavior and eliminates some nasty behavior we were doing that wasn't hw-accurate at all.
master
Zach Hilman 2019-04-10 12:30:49 +07:00
parent 62d772eaed
commit 49c44e3fae
2 changed files with 41 additions and 27 deletions

@ -15,22 +15,8 @@ namespace FileSys {
constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
std::string SaveDataDescriptor::DebugInfo() const {
return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, "
"rank={}, index={}]",
static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id,
static_cast<u8>(rank), index);
}
SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save_directory)) {
// Delete all temporary storages
// On hardware, it is expected that temporary storage be empty at first use.
dir->DeleteSubdirectoryRecursive("temp");
}
SaveDataFactory::~SaveDataFactory() = default;
ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataDescriptor& meta) {
namespace {
void PrintSaveDataDescriptorWarnings(SaveDataDescriptor meta) {
if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
if (meta.zero_1 != 0) {
LOG_WARNING(Service_FS,
@ -65,23 +51,50 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, const SaveDat
"non-zero ({:016X}{:016X})",
meta.user_id[1], meta.user_id[0]);
}
}
} // Anonymous namespace
std::string save_directory =
std::string SaveDataDescriptor::DebugInfo() const {
return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, "
"save_id={:016X}, "
"rank={}, index={}]",
static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id,
static_cast<u8>(rank), index);
}
SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save_directory)) {
// Delete all temporary storages
// On hardware, it is expected that temporary storage be empty at first use.
dir->DeleteSubdirectoryRecursive("temp");
}
SaveDataFactory::~SaveDataFactory() = default;
ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
const SaveDataDescriptor& meta) {
PrintSaveDataDescriptorWarnings(meta);
const auto save_directory =
GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id);
// TODO(DarkLordZach): Try to not create when opening, there are dedicated create save methods.
// But, user_ids don't match so this works for now.
auto out = dir->CreateDirectoryRelative(save_directory);
// Return an error if the save data doesn't actually exist.
if (out == nullptr) {
// TODO(DarkLordZach): Find out correct error code.
return ResultCode(-1);
}
return MakeResult<VirtualDir>(std::move(out));
}
ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataDescriptor& meta) {
const auto save_directory =
GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id);
auto out = dir->GetDirectoryRelative(save_directory);
if (out == nullptr) {
// TODO(bunnei): This is a work-around to always create a save data directory if it does not
// already exist. This is a hack, as we do not understand yet how this works on hardware.
// Without a save data directory, many games will assert on boot. This should not have any
// bad side-effects.
out = dir->CreateDirectoryRelative(save_directory);
}
// Return an error if the save data doesn't actually exist.
if (out == nullptr) {
// TODO(Subv): Find out correct error code.

@ -64,6 +64,7 @@ public:
explicit SaveDataFactory(VirtualDir dir);
~SaveDataFactory();
ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataDescriptor& meta);
ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataDescriptor& meta);
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;