Merge pull request #6988 from leoetlino/wii-save-refactor
WiiSave: Refactor the import/export code
This commit is contained in:
commit
1e51e263e0
File diff suppressed because it is too large
Load Diff
|
@ -4,138 +4,43 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Swap.h"
|
||||
|
||||
namespace IOS
|
||||
{
|
||||
namespace HLE
|
||||
{
|
||||
class Kernel;
|
||||
namespace FS
|
||||
{
|
||||
class FileSystem;
|
||||
}
|
||||
class IOSC;
|
||||
}
|
||||
} // namespace IOS::HLE
|
||||
|
||||
class WiiSave
|
||||
namespace WiiSave
|
||||
{
|
||||
public:
|
||||
/// Import a save into the NAND from a .bin file.
|
||||
static bool Import(std::string filename);
|
||||
/// Export a save to a .bin file.
|
||||
static bool Export(u64 title_id, std::string export_path);
|
||||
/// Export all saves that are in the NAND. Returns the number of exported saves.
|
||||
static size_t ExportAll(std::string export_path);
|
||||
|
||||
private:
|
||||
WiiSave(IOS::HLE::Kernel& ios, std::string filename);
|
||||
WiiSave(IOS::HLE::Kernel& ios, u64 title_id, std::string export_path);
|
||||
~WiiSave();
|
||||
|
||||
bool Import();
|
||||
bool Export();
|
||||
|
||||
void ReadHDR();
|
||||
void ReadBKHDR();
|
||||
void WriteHDR();
|
||||
void WriteBKHDR();
|
||||
void ImportWiiSaveFiles();
|
||||
void ExportWiiSaveFiles();
|
||||
void do_sig();
|
||||
bool getPaths(bool for_export = false);
|
||||
void ScanForFiles(const std::string& save_directory, std::vector<std::string>& file_list,
|
||||
u32* num_files, u32* size_files);
|
||||
|
||||
IOS::HLE::Kernel& m_ios;
|
||||
|
||||
std::array<u8, 0x10> m_sd_iv;
|
||||
std::vector<std::string> m_files_list;
|
||||
|
||||
std::string m_encrypted_save_path;
|
||||
|
||||
std::string m_wii_title_path;
|
||||
|
||||
std::array<u8, 0x10> m_iv;
|
||||
|
||||
u64 m_title_id;
|
||||
|
||||
bool m_valid;
|
||||
|
||||
enum
|
||||
{
|
||||
BLOCK_SZ = 0x40,
|
||||
HDR_SZ = 0x20,
|
||||
ICON_SZ = 0x1200,
|
||||
BNR_SZ = 0x60a0,
|
||||
FULL_BNR_MIN = 0x72a0, // BNR_SZ + 1*ICON_SZ
|
||||
FULL_BNR_MAX = 0xF0A0, // BNR_SZ + 8*ICON_SZ
|
||||
HEADER_SZ = 0xF0C0, // HDR_SZ + FULL_BNR_MAX
|
||||
BK_LISTED_SZ = 0x70, // Size before rounding to nearest block
|
||||
BK_SZ = 0x80,
|
||||
FILE_HDR_SZ = 0x80,
|
||||
|
||||
SIG_SZ = 0x40,
|
||||
NG_CERT_SZ = 0x180,
|
||||
AP_CERT_SZ = 0x180,
|
||||
FULL_CERT_SZ = 0x3C0, // SIG_SZ + NG_CERT_SZ + AP_CERT_SZ + 0x80?
|
||||
|
||||
BK_HDR_MAGIC = 0x426B0001,
|
||||
FILE_HDR_MAGIC = 0x03adf17e
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct DataBinHeader // encrypted
|
||||
{
|
||||
Common::BigEndianValue<u64> save_game_title;
|
||||
Common::BigEndianValue<u32> banner_size; // (0x72A0 or 0xF0A0, also seen 0xBAA0)
|
||||
u8 permissions;
|
||||
u8 unk1; // maybe permissions is a be16
|
||||
std::array<u8, 0x10> md5; // md5 of plaintext header with md5 blanker applied
|
||||
Common::BigEndianValue<u16> unk2;
|
||||
};
|
||||
|
||||
struct Header
|
||||
{
|
||||
DataBinHeader hdr;
|
||||
u8 banner[FULL_BNR_MAX];
|
||||
};
|
||||
|
||||
struct BkHeader // Not encrypted
|
||||
{
|
||||
Common::BigEndianValue<u32> size; // 0x00000070
|
||||
// u16 magic; // 'Bk'
|
||||
// u16 magic2; // or version (0x0001)
|
||||
Common::BigEndianValue<u32> magic; // 0x426B0001
|
||||
Common::BigEndianValue<u32> ngid;
|
||||
Common::BigEndianValue<u32> number_of_files;
|
||||
Common::BigEndianValue<u32> size_of_files;
|
||||
Common::BigEndianValue<u32> unk1;
|
||||
Common::BigEndianValue<u32> unk2;
|
||||
Common::BigEndianValue<u32> total_size;
|
||||
std::array<u8, 64> unk3;
|
||||
Common::BigEndianValue<u64> save_game_title;
|
||||
std::array<u8, 6> mac_address;
|
||||
std::array<u8, 0x12> padding;
|
||||
};
|
||||
|
||||
struct FileHDR // encrypted
|
||||
{
|
||||
Common::BigEndianValue<u32> magic; // 0x03adf17e
|
||||
Common::BigEndianValue<u32> size;
|
||||
u8 permissions;
|
||||
u8 attrib;
|
||||
u8 type; // (1=file, 2=directory)
|
||||
std::array<char, 0x45> name;
|
||||
std::array<u8, 0x10> iv;
|
||||
std::array<u8, 0x20> unk;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
Header m_header;
|
||||
Header m_encrypted_header;
|
||||
BkHeader m_bk_hdr;
|
||||
class Storage;
|
||||
struct StorageDeleter
|
||||
{
|
||||
void operator()(Storage* p) const;
|
||||
};
|
||||
|
||||
using StoragePointer = std::unique_ptr<Storage, StorageDeleter>;
|
||||
StoragePointer MakeNandStorage(IOS::HLE::FS::FileSystem* fs, u64 tid);
|
||||
StoragePointer MakeDataBinStorage(IOS::HLE::IOSC* iosc, const std::string& path, const char* mode);
|
||||
|
||||
bool Copy(Storage* source, Storage* destination);
|
||||
|
||||
/// Import a save into the NAND from a .bin file.
|
||||
bool Import(const std::string& data_bin_path, std::function<bool()> can_overwrite);
|
||||
/// Export a save to a .bin file.
|
||||
bool Export(u64 tid, const std::string& export_path);
|
||||
/// Export all saves that are in the NAND. Returns the number of exported saves.
|
||||
size_t ExportAll(const std::string& export_path);
|
||||
} // namespace WiiSave
|
||||
|
|
|
@ -958,9 +958,18 @@ void MenuBar::ImportWiiSave()
|
|||
if (file.isEmpty())
|
||||
return;
|
||||
|
||||
if (WiiSave::Import(file.toStdString()))
|
||||
bool cancelled = false;
|
||||
auto can_overwrite = [&] {
|
||||
bool yes = QMessageBox::question(
|
||||
this, tr("Save Import"),
|
||||
tr("Save data for this title already exists in the NAND. Consider backing up "
|
||||
"the current data before overwriting.\nOverwrite now?")) == QMessageBox::Yes;
|
||||
cancelled = !yes;
|
||||
return yes;
|
||||
};
|
||||
if (WiiSave::Import(file.toStdString(), can_overwrite))
|
||||
QMessageBox::information(this, tr("Save Import"), tr("Successfully imported save files."));
|
||||
else
|
||||
else if (!cancelled)
|
||||
QMessageBox::critical(this, tr("Save Import"), tr("Failed to import save files."));
|
||||
}
|
||||
|
||||
|
|
|
@ -1214,8 +1214,14 @@ void CFrame::OnImportSave(wxCommandEvent& WXUNUSED(event))
|
|||
_("Wii save files (*.bin)") + "|*.bin|" + wxGetTranslation(wxALL_FILES),
|
||||
wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST, this);
|
||||
|
||||
auto can_overwrite = [this] {
|
||||
return wxMessageBox(_("Save data for this title already exists in the NAND. Consider backing "
|
||||
"up the current data before overwriting.\nOverwrite now?"),
|
||||
_("Save Import"), wxYES_NO, this) == wxYES;
|
||||
};
|
||||
|
||||
if (!path.IsEmpty())
|
||||
WiiSave::Import(WxStrToStr(path));
|
||||
WiiSave::Import(WxStrToStr(path), can_overwrite);
|
||||
}
|
||||
|
||||
void CFrame::OnShowCheatsWindow(wxCommandEvent& WXUNUSED(event))
|
||||
|
|
Loading…
Reference in New Issue