summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2020-12-31 19:35:29 +0100
committerAdmiral H. Curtiss <pikachu025@gmail.com>2021-01-02 17:46:12 +0100
commitd9c686db3074360698b12d9beaf425b95a4348fd (patch)
tree68d1ada0aeaf4c97323bcd6ba7e151f588da7fd7 /Source/Core
parent700d53e00f285b6471734563c8564c01cf5381f4 (diff)
WiiSave: Delete existing save, if any, before importing one.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/WiiSave.cpp101
-rw-r--r--Source/Core/Core/HW/WiiSaveStructs.h3
2 files changed, 86 insertions, 18 deletions
diff --git a/Source/Core/Core/HW/WiiSave.cpp b/Source/Core/Core/HW/WiiSave.cpp
index dd4108a59b..98498a29cb 100644
--- a/Source/Core/Core/HW/WiiSave.cpp
+++ b/Source/Core/Core/HW/WiiSave.cpp
@@ -69,9 +69,35 @@ public:
ScanForFiles(m_data_dir);
}
- bool SaveExists() override
+ bool SaveExists() const override
{
- return m_uid && m_gid && m_fs->GetMetadata(*m_uid, *m_gid, m_data_dir + "/banner.bin");
+ return !m_files_list.empty() ||
+ (m_uid && m_gid && m_fs->GetMetadata(*m_uid, *m_gid, m_data_dir + "/banner.bin"));
+ }
+
+ bool EraseSave() override
+ {
+ // banner.bin is not in m_files_list, delete separately
+ const auto banner_delete_result =
+ m_fs->Delete(IOS::PID_KERNEL, IOS::PID_KERNEL, m_data_dir + "/banner.bin");
+ if (banner_delete_result != FS::ResultCode::Success)
+ return false;
+
+ for (const SaveFile& file : m_files_list)
+ {
+ // files in subdirs are deleted automatically when the subdir is deleted
+ if (file.path.find('/') != std::string::npos)
+ continue;
+
+ const auto result =
+ m_fs->Delete(IOS::PID_KERNEL, IOS::PID_KERNEL, m_data_dir + "/" + file.path);
+ if (result != FS::ResultCode::Success)
+ return false;
+ }
+
+ m_files_list.clear();
+ m_files_size = 0;
+ return true;
}
std::optional<Header> ReadHeader() override
@@ -246,6 +272,10 @@ public:
m_file = File::IOFile{path, mode};
}
+ bool SaveExists() const override { return m_file.GetSize() > 0; }
+
+ bool EraseSave() override { return m_file.GetSize() == 0 || m_file.Resize(0); }
+
std::optional<Header> ReadHeader() override
{
Header header;
@@ -447,23 +477,60 @@ StoragePointer MakeDataBinStorage(IOS::HLE::IOSC* iosc, const std::string& path,
return StoragePointer{new DataBinStorage{iosc, path, mode}};
}
-template <typename T>
-static bool Copy(std::string_view description, Storage* source,
- std::optional<T> (Storage::*read_fn)(), Storage* dest,
- bool (Storage::*write_fn)(const T&))
-{
- const std::optional<T> data = (source->*read_fn)();
- if (data && (dest->*write_fn)(*data))
- return true;
- ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to {} {}", !data ? "read" : "write", description);
- return false;
-}
-
bool Copy(Storage* source, Storage* dest)
{
- return Copy("header", source, &Storage::ReadHeader, dest, &Storage::WriteHeader) &&
- Copy("bk header", source, &Storage::ReadBkHeader, dest, &Storage::WriteBkHeader) &&
- Copy("files", source, &Storage::ReadFiles, dest, &Storage::WriteFiles);
+ // first make sure we can read all the data from the source
+ const auto header = source->ReadHeader();
+ if (!header)
+ {
+ ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to read header");
+ return false;
+ }
+
+ const auto bk_header = source->ReadBkHeader();
+ if (!bk_header)
+ {
+ ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to read bk header");
+ return false;
+ }
+
+ const auto files = source->ReadFiles();
+ if (!files)
+ {
+ ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to read files");
+ return false;
+ }
+
+ // once we have confirmed we can read the source, erase corresponding save in the destination
+ if (dest->SaveExists())
+ {
+ if (!dest->EraseSave())
+ {
+ ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to erase existing save");
+ return false;
+ }
+ }
+
+ // and then write it to the destination
+ if (!dest->WriteHeader(*header))
+ {
+ ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to write header");
+ return false;
+ }
+
+ if (!dest->WriteBkHeader(*bk_header))
+ {
+ ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to write bk header");
+ return false;
+ }
+
+ if (!dest->WriteFiles(*files))
+ {
+ ERROR_LOG_FMT(CORE, "WiiSave::Copy: Failed to write files");
+ return false;
+ }
+
+ return true;
}
bool Import(const std::string& data_bin_path, std::function<bool()> can_overwrite)
diff --git a/Source/Core/Core/HW/WiiSaveStructs.h b/Source/Core/Core/HW/WiiSaveStructs.h
index 6ef5a38feb..ed6b9aa948 100644
--- a/Source/Core/Core/HW/WiiSaveStructs.h
+++ b/Source/Core/Core/HW/WiiSaveStructs.h
@@ -101,7 +101,8 @@ public:
};
virtual ~Storage() = default;
- virtual bool SaveExists() { return true; }
+ virtual bool SaveExists() const = 0;
+ virtual bool EraseSave() = 0;
virtual std::optional<Header> ReadHeader() = 0;
virtual std::optional<BkHeader> ReadBkHeader() = 0;
virtual std::optional<std::vector<SaveFile>> ReadFiles() = 0;