diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 26ab98f803..9b1094dd48 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -150,7 +150,7 @@ add_library(core
HW/WiimoteEmu/Encryption.cpp
HW/WiimoteEmu/Speaker.cpp
HW/WiimoteReal/WiimoteReal.cpp
- HW/WiiSaveCrypted.cpp
+ HW/WiiSave.cpp
IOS/Device.cpp
IOS/DeviceStub.cpp
IOS/IOS.cpp
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index 3a1aeee2ea..ad815d88a4 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -179,7 +179,7 @@
-
+
@@ -437,7 +437,7 @@
-
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index 25a151d371..a16e67b8e1 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -561,7 +561,7 @@
HW %28Flipper/Hollywood%29
-
+
HW %28Flipper/Hollywood%29
@@ -1242,7 +1242,7 @@
HW %28Flipper/Hollywood%29
-
+
HW %28Flipper/Hollywood%29
@@ -1578,4 +1578,4 @@
-
\ No newline at end of file
+
diff --git a/Source/Core/Core/HW/WiiSaveCrypted.cpp b/Source/Core/Core/HW/WiiSave.cpp
similarity index 68%
rename from Source/Core/Core/HW/WiiSaveCrypted.cpp
rename to Source/Core/Core/HW/WiiSave.cpp
index 28c9150b34..5909c00e7f 100644
--- a/Source/Core/Core/HW/WiiSaveCrypted.cpp
+++ b/Source/Core/Core/HW/WiiSave.cpp
@@ -7,7 +7,7 @@
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
-#include "Core/HW/WiiSaveCrypted.h"
+#include "Core/HW/WiiSave.h"
#include
#include
@@ -29,35 +29,30 @@
#include "Common/MsgHandler.h"
#include "Common/NandPaths.h"
#include "Common/StringUtil.h"
-#include "Common/Swap.h"
-const u8 CWiiSaveCrypted::s_sd_key[16] = {0xAB, 0x01, 0xB9, 0xD8, 0xE1, 0x62, 0x2B, 0x08,
- 0xAF, 0xBA, 0xD8, 0x4D, 0xBF, 0xC2, 0xA5, 0x5D};
-const u8 CWiiSaveCrypted::s_md5_blanker[16] = {0x0E, 0x65, 0x37, 0x81, 0x99, 0xBE, 0x45, 0x17,
- 0xAB, 0x06, 0xEC, 0x22, 0x45, 0x1A, 0x57, 0x93};
-const u32 CWiiSaveCrypted::s_ng_id = 0x0403AC68;
+using Md5 = std::array;
-bool CWiiSaveCrypted::ImportWiiSave(const std::string& filename)
+constexpr std::array s_sd_initial_iv{{0x21, 0x67, 0x12, 0xE6, 0xAA, 0x1F, 0x68, 0x9F,
+ 0x95, 0xC5, 0xA2, 0x23, 0x24, 0xDC, 0x6A, 0x98}};
+constexpr std::array s_sd_key{{0xAB, 0x01, 0xB9, 0xD8, 0xE1, 0x62, 0x2B, 0x08, 0xAF, 0xBA,
+ 0xD8, 0x4D, 0xBF, 0xC2, 0xA5, 0x5D}};
+constexpr Md5 s_md5_blanker{{0x0E, 0x65, 0x37, 0x81, 0x99, 0xBE, 0x45, 0x17, 0xAB, 0x06, 0xEC, 0x22,
+ 0x45, 0x1A, 0x57, 0x93}};
+constexpr u32 s_ng_id = 0x0403AC68;
+
+bool WiiSave::Import(std::string filename)
{
- CWiiSaveCrypted save_file(filename);
- return save_file.m_valid;
+ WiiSave save_file{std::move(filename)};
+ return save_file.Import();
}
-bool CWiiSaveCrypted::ExportWiiSave(u64 title_id)
+bool WiiSave::Export(u64 title_id, std::string export_path)
{
- CWiiSaveCrypted export_save("", title_id);
- if (export_save.m_valid)
- {
- SuccessAlertT("Successfully exported file to %s", export_save.m_encrypted_save_path.c_str());
- }
- else
- {
- PanicAlertT("Export failed");
- }
- return export_save.m_valid;
+ WiiSave export_save{title_id, std::move(export_path)};
+ return export_save.Export();
}
-void CWiiSaveCrypted::ExportAllSaves()
+size_t WiiSave::ExportAll(std::string export_path)
{
std::string title_folder = File::GetUserPath(D_WIIROOT_IDX) + "/title";
std::vector titles;
@@ -85,56 +80,50 @@ void CWiiSaveCrypted::ExportAllSaves()
}
}
}
- SuccessAlertT("Found %zu save file(s)", titles.size());
- u32 success = 0;
+ size_t exported_save_count = 0;
for (const u64& title : titles)
{
- CWiiSaveCrypted export_save{"", title};
- if (export_save.m_valid)
- success++;
+ WiiSave export_save{title, export_path};
+ if (export_save.Export())
+ ++exported_save_count;
}
- SuccessAlertT("Successfully exported %u save(s) to %s", success,
- (File::GetUserPath(D_USER_IDX) + "private/wii/title/").c_str());
+ return exported_save_count;
}
-CWiiSaveCrypted::CWiiSaveCrypted(const std::string& filename, u64 title_id)
- : m_encrypted_save_path(filename), m_title_id(title_id)
+WiiSave::WiiSave(std::string filename)
+ : m_sd_iv{s_sd_initial_iv}, m_encrypted_save_path(std::move(filename)), m_valid{true}
{
- memcpy(m_sd_iv, "\x21\x67\x12\xE6\xAA\x1F\x68\x9F\x95\xC5\xA2\x23\x24\xDC\x6A\x98", 0x10);
-
- if (!title_id) // Import
- {
- mbedtls_aes_setkey_dec(&m_aes_ctx, s_sd_key, 128);
- m_valid = true;
- ReadHDR();
- ReadBKHDR();
- ImportWiiSaveFiles();
- // TODO: check_sig()
- if (m_valid)
- {
- SuccessAlertT("Successfully imported save file(s)");
- }
- else
- {
- PanicAlertT("Import failed");
- }
- }
- else
- {
- mbedtls_aes_setkey_enc(&m_aes_ctx, s_sd_key, 128);
-
- if (getPaths(true))
- {
- m_valid = true;
- WriteHDR();
- WriteBKHDR();
- ExportWiiSaveFiles();
- do_sig();
- }
- }
+ mbedtls_aes_setkey_dec(&m_aes_ctx, s_sd_key.data(), 128);
}
-void CWiiSaveCrypted::ReadHDR()
+bool WiiSave::Import()
+{
+ ReadHDR();
+ ReadBKHDR();
+ ImportWiiSaveFiles();
+ // TODO: check_sig()
+ return m_valid;
+}
+
+WiiSave::WiiSave(u64 title_id, std::string export_path)
+ : m_sd_iv{s_sd_initial_iv}, m_encrypted_save_path(std::move(export_path)), m_title_id{title_id}
+{
+ mbedtls_aes_setkey_enc(&m_aes_ctx, s_sd_key.data(), 128);
+
+ if (getPaths(true))
+ m_valid = true;
+}
+
+bool WiiSave::Export()
+{
+ WriteHDR();
+ WriteBKHDR();
+ ExportWiiSaveFiles();
+ do_sig();
+ return m_valid;
+}
+
+void WiiSave::ReadHDR()
{
File::IOFile data_file(m_encrypted_save_path, "rb");
if (!data_file)
@@ -151,9 +140,9 @@ void CWiiSaveCrypted::ReadHDR()
}
data_file.Close();
- mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_DECRYPT, HEADER_SZ, m_sd_iv,
+ mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_DECRYPT, HEADER_SZ, m_sd_iv.data(),
(const u8*)&m_encrypted_header, (u8*)&m_header);
- u32 banner_size = Common::swap32(m_header.hdr.BannerSize);
+ u32 banner_size = m_header.hdr.banner_size;
if ((banner_size < FULL_BNR_MIN) || (banner_size > FULL_BNR_MAX) ||
(((banner_size - BNR_SZ) % ICON_SZ) != 0))
{
@@ -161,18 +150,17 @@ void CWiiSaveCrypted::ReadHDR()
m_valid = false;
return;
}
- m_title_id = Common::swap64(m_header.hdr.SaveGameTitle);
+ m_title_id = m_header.hdr.save_game_title;
- u8 md5_file[16];
- u8 md5_calc[16];
- memcpy(md5_file, m_header.hdr.Md5, 0x10);
- memcpy(m_header.hdr.Md5, s_md5_blanker, 0x10);
- mbedtls_md5((u8*)&m_header, HEADER_SZ, md5_calc);
- if (memcmp(md5_file, md5_calc, 0x10))
+ Md5 md5_file = m_header.hdr.md5;
+ m_header.hdr.md5 = s_md5_blanker;
+ Md5 md5_calc;
+ mbedtls_md5((u8*)&m_header, HEADER_SZ, md5_calc.data());
+ if (md5_file == md5_calc)
{
ERROR_LOG(CONSOLE, "MD5 mismatch\n %016" PRIx64 "%016" PRIx64 " != %016" PRIx64 "%016" PRIx64,
- Common::swap64(md5_file), Common::swap64(md5_file + 8), Common::swap64(md5_calc),
- Common::swap64(md5_calc + 8));
+ Common::swap64(md5_file.data()), Common::swap64(md5_file.data() + 8),
+ Common::swap64(md5_calc.data()), Common::swap64(md5_calc.data() + 8));
m_valid = false;
}
@@ -189,7 +177,7 @@ void CWiiSaveCrypted::ReadHDR()
{
INFO_LOG(CONSOLE, "Creating file %s", banner_file_path.c_str());
File::IOFile banner_file(banner_file_path, "wb");
- banner_file.WriteBytes(m_header.BNR, banner_size);
+ banner_file.WriteBytes(m_header.banner, banner_size);
}
else
{
@@ -197,7 +185,7 @@ void CWiiSaveCrypted::ReadHDR()
}
}
-void CWiiSaveCrypted::WriteHDR()
+void WiiSave::WriteHDR()
{
if (!m_valid)
return;
@@ -205,28 +193,28 @@ void CWiiSaveCrypted::WriteHDR()
std::string banner_file_path = m_wii_title_path + "/banner.bin";
u32 banner_size = static_cast(File::GetSize(banner_file_path));
- m_header.hdr.BannerSize = Common::swap32(banner_size);
+ m_header.hdr.banner_size = banner_size;
- m_header.hdr.SaveGameTitle = Common::swap64(m_title_id);
- memcpy(m_header.hdr.Md5, s_md5_blanker, 0x10);
- m_header.hdr.Permissions = 0x3C;
+ m_header.hdr.save_game_title = m_title_id;
+ m_header.hdr.md5 = s_md5_blanker;
+ m_header.hdr.permissions = 0x3C;
File::IOFile banner_file(banner_file_path, "rb");
- if (!banner_file.ReadBytes(m_header.BNR, banner_size))
+ if (!banner_file.ReadBytes(m_header.banner, banner_size))
{
ERROR_LOG(CONSOLE, "Failed to read banner.bin");
m_valid = false;
return;
}
// remove nocopy flag
- m_header.BNR[7] &= ~1;
+ m_header.banner[7] &= ~1;
- u8 md5_calc[16];
- mbedtls_md5((u8*)&m_header, HEADER_SZ, md5_calc);
- memcpy(m_header.hdr.Md5, md5_calc, 0x10);
+ Md5 md5_calc;
+ mbedtls_md5((u8*)&m_header, HEADER_SZ, md5_calc.data());
+ m_header.hdr.md5 = std::move(md5_calc);
- mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_ENCRYPT, HEADER_SZ, m_sd_iv, (const u8*)&m_header,
- (u8*)&m_encrypted_header);
+ mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_ENCRYPT, HEADER_SZ, m_sd_iv.data(),
+ (const u8*)&m_header, (u8*)&m_encrypted_header);
File::IOFile data_file(m_encrypted_save_path, "wb");
if (!data_file.WriteBytes(&m_encrypted_header, HEADER_SZ))
@@ -236,7 +224,7 @@ void CWiiSaveCrypted::WriteHDR()
}
}
-void CWiiSaveCrypted::ReadBKHDR()
+void WiiSave::ReadBKHDR()
{
if (!m_valid)
return;
@@ -257,47 +245,41 @@ void CWiiSaveCrypted::ReadBKHDR()
}
fpData_bin.Close();
- if (m_bk_hdr.size != Common::swap32(BK_LISTED_SZ) ||
- m_bk_hdr.magic != Common::swap32(BK_HDR_MAGIC))
+ if (m_bk_hdr.size != BK_LISTED_SZ || m_bk_hdr.magic != BK_HDR_MAGIC)
{
- ERROR_LOG(CONSOLE, "Invalid Size(%x) or Magic word (%x)", m_bk_hdr.size, m_bk_hdr.magic);
+ ERROR_LOG(CONSOLE, "Invalid Size(%x) or Magic word (%x)", u32(m_bk_hdr.size),
+ u32(m_bk_hdr.magic));
m_valid = false;
return;
}
- m_files_list_size = Common::swap32(m_bk_hdr.numberOfFiles);
- m_size_of_files = Common::swap32(m_bk_hdr.sizeOfFiles);
- m_total_size = Common::swap32(m_bk_hdr.totalSize);
-
- if (m_size_of_files + FULL_CERT_SZ != m_total_size)
+ if (m_bk_hdr.size_of_files + FULL_CERT_SZ != m_bk_hdr.total_size)
{
- WARN_LOG(CONSOLE, "Size(%x) + cert(%x) does not equal totalsize(%x)", m_size_of_files,
- FULL_CERT_SZ, m_total_size);
+ WARN_LOG(CONSOLE, "Size(%x) + cert(%x) does not equal totalsize(%x)",
+ u32(m_bk_hdr.size_of_files), FULL_CERT_SZ, u32(m_bk_hdr.total_size));
}
- if (m_title_id != Common::swap64(m_bk_hdr.SaveGameTitle))
+ if (m_title_id != m_bk_hdr.save_game_title)
{
WARN_LOG(CONSOLE,
"Encrypted title (%" PRIx64 ") does not match unencrypted title (%" PRIx64 ")",
- m_title_id, Common::swap64(m_bk_hdr.SaveGameTitle));
+ m_title_id, u64(m_bk_hdr.save_game_title));
}
}
-void CWiiSaveCrypted::WriteBKHDR()
+void WiiSave::WriteBKHDR()
{
if (!m_valid)
return;
- m_files_list_size = 0;
- m_size_of_files = 0;
-
- ScanForFiles(m_wii_title_path, m_files_list, &m_files_list_size, &m_size_of_files);
+ u32 number_of_files = 0, size_of_files = 0;
+ ScanForFiles(m_wii_title_path, m_files_list, &number_of_files, &size_of_files);
memset(&m_bk_hdr, 0, BK_SZ);
- m_bk_hdr.size = Common::swap32(BK_LISTED_SZ);
- m_bk_hdr.magic = Common::swap32(BK_HDR_MAGIC);
- m_bk_hdr.NGid = s_ng_id;
- m_bk_hdr.numberOfFiles = Common::swap32(m_files_list_size);
- m_bk_hdr.sizeOfFiles = Common::swap32(m_size_of_files);
- m_bk_hdr.totalSize = Common::swap32(m_size_of_files + FULL_CERT_SZ);
- m_bk_hdr.SaveGameTitle = Common::swap64(m_title_id);
+ m_bk_hdr.size = BK_LISTED_SZ;
+ m_bk_hdr.magic = BK_HDR_MAGIC;
+ m_bk_hdr.ngid = s_ng_id;
+ m_bk_hdr.number_of_files = number_of_files;
+ m_bk_hdr.size_of_files = size_of_files;
+ m_bk_hdr.total_size = size_of_files + FULL_CERT_SZ;
+ m_bk_hdr.save_game_title = m_title_id;
File::IOFile data_file(m_encrypted_save_path, "ab");
if (!data_file.WriteBytes(&m_bk_hdr, BK_SZ))
@@ -307,7 +289,7 @@ void CWiiSaveCrypted::WriteBKHDR()
}
}
-void CWiiSaveCrypted::ImportWiiSaveFiles()
+void WiiSave::ImportWiiSaveFiles()
{
if (!m_valid)
return;
@@ -324,11 +306,10 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
FileHDR file_hdr_tmp;
- for (u32 i = 0; i < m_files_list_size; ++i)
+ for (u32 i = 0; i < m_bk_hdr.number_of_files; ++i)
{
memset(&file_hdr_tmp, 0, FILE_HDR_SZ);
- memset(m_iv, 0, 0x10);
- u32 file_size = 0;
+ m_iv.fill(0);
if (!data_file.ReadBytes(&file_hdr_tmp, FILE_HDR_SZ))
{
@@ -336,7 +317,7 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
m_valid = false;
}
- if (Common::swap32(file_hdr_tmp.magic) != FILE_HDR_MAGIC)
+ if (file_hdr_tmp.magic != FILE_HDR_MAGIC)
{
ERROR_LOG(CONSOLE, "Bad File Header");
break;
@@ -345,15 +326,14 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
{
// Allows files in subfolders to be escaped properly (ex: "nocopy/data00")
// Special characters in path components will be escaped such as /../
- std::string file_path = Common::EscapePath(reinterpret_cast(file_hdr_tmp.name));
+ std::string file_path = Common::EscapePath(file_hdr_tmp.name.data());
std::string file_path_full = m_wii_title_path + '/' + file_path;
File::CreateFullPath(file_path_full);
const File::FileInfo file_info(file_path_full);
if (file_hdr_tmp.type == 1)
{
- file_size = Common::swap32(file_hdr_tmp.size);
- u32 file_size_rounded = Common::AlignUp(file_size, BLOCK_SZ);
+ u32 file_size_rounded = Common::AlignUp(file_hdr_tmp.size, BLOCK_SZ);
std::vector file_data(file_size_rounded);
std::vector file_data_enc(file_size_rounded);
@@ -364,14 +344,14 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
break;
}
- memcpy(m_iv, file_hdr_tmp.IV, 0x10);
- mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_DECRYPT, file_size_rounded, m_iv,
+ m_iv = file_hdr_tmp.iv;
+ mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_DECRYPT, file_size_rounded, m_iv.data(),
static_cast(file_data_enc.data()), file_data.data());
INFO_LOG(CONSOLE, "Creating file %s", file_path_full.c_str());
File::IOFile raw_save_file(file_path_full, "wb");
- raw_save_file.WriteBytes(file_data.data(), file_size);
+ raw_save_file.WriteBytes(file_data.data(), file_hdr_tmp.size);
}
else if (file_hdr_tmp.type == 2)
{
@@ -391,12 +371,12 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
}
}
-void CWiiSaveCrypted::ExportWiiSaveFiles()
+void WiiSave::ExportWiiSaveFiles()
{
if (!m_valid)
return;
- for (u32 i = 0; i < m_files_list_size; i++)
+ for (u32 i = 0; i < m_bk_hdr.number_of_files; i++)
{
FileHDR file_hdr_tmp;
memset(&file_hdr_tmp, 0, FILE_HDR_SZ);
@@ -414,9 +394,9 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
}
u32 file_size_rounded = Common::AlignUp(file_size, BLOCK_SZ);
- file_hdr_tmp.magic = Common::swap32(FILE_HDR_MAGIC);
- file_hdr_tmp.size = Common::swap32(file_size);
- file_hdr_tmp.Permissions = 0x3c;
+ file_hdr_tmp.magic = FILE_HDR_MAGIC;
+ file_hdr_tmp.size = file_size;
+ file_hdr_tmp.permissions = 0x3c;
std::string name =
Common::UnescapeFileName(m_files_list[i].substr(m_wii_title_path.length() + 1));
@@ -428,7 +408,7 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
m_valid = false;
return;
}
- strncpy((char*)file_hdr_tmp.name, name.c_str(), sizeof(file_hdr_tmp.name));
+ std::strncpy(file_hdr_tmp.name.data(), name.c_str(), file_hdr_tmp.name.size());
{
File::IOFile fpData_bin(m_encrypted_save_path, "ab");
@@ -459,8 +439,9 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
m_valid = false;
}
- mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_ENCRYPT, file_size_rounded, file_hdr_tmp.IV,
- static_cast(file_data.data()), file_data_enc.data());
+ mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_ENCRYPT, file_size_rounded,
+ file_hdr_tmp.iv.data(), static_cast(file_data.data()),
+ file_data_enc.data());
File::IOFile fpData_bin(m_encrypted_save_path, "ab");
if (!fpData_bin.WriteBytes(file_data_enc.data(), file_size_rounded))
@@ -471,7 +452,7 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
}
}
-void CWiiSaveCrypted::do_sig()
+void WiiSave::do_sig()
{
if (!m_valid)
return;
@@ -514,7 +495,7 @@ void CWiiSaveCrypted::do_sig()
generate_ecdsa(ap_sig, ap_sig + 30, ng_priv, hash);
make_ec_cert(ap_cert, ap_sig, signer, name, ap_priv, 0);
- data_size = Common::swap32(m_bk_hdr.sizeOfFiles) + 0x80;
+ data_size = m_bk_hdr.size_of_files + 0x80;
File::IOFile data_file(m_encrypted_save_path, "rb");
if (!data_file)
@@ -550,8 +531,8 @@ void CWiiSaveCrypted::do_sig()
m_valid = data_file.IsGood();
}
-void CWiiSaveCrypted::make_ec_cert(u8* cert, const u8* sig, const char* signer, const char* name,
- const u8* priv, const u32 key_id)
+void WiiSave::make_ec_cert(u8* cert, const u8* sig, const char* signer, const char* name,
+ const u8* priv, const u32 key_id)
{
memset(cert, 0, 0x180);
*(u32*)cert = Common::swap32(0x10002);
@@ -564,7 +545,7 @@ void CWiiSaveCrypted::make_ec_cert(u8* cert, const u8* sig, const char* signer,
ec_priv_to_pub(priv, cert + 0x108);
}
-bool CWiiSaveCrypted::getPaths(bool for_export)
+bool WiiSave::getPaths(bool for_export)
{
if (m_title_id)
{
@@ -591,12 +572,7 @@ bool CWiiSaveCrypted::getPaths(bool for_export)
ERROR_LOG(CONSOLE, "No banner file found for title %s", game_id);
return false;
}
- if (m_encrypted_save_path.length() == 0)
- {
- // If no path was passed, use User folder
- m_encrypted_save_path = File::GetUserPath(D_USER_IDX);
- }
- m_encrypted_save_path += StringFromFormat("private/wii/title/%s/data.bin", game_id);
+ m_encrypted_save_path += StringFromFormat("/private/wii/title/%s/data.bin", game_id);
File::CreateFullPath(m_encrypted_save_path);
}
else
@@ -606,9 +582,8 @@ bool CWiiSaveCrypted::getPaths(bool for_export)
return true;
}
-void CWiiSaveCrypted::ScanForFiles(const std::string& save_directory,
- std::vector& file_list, u32* num_files,
- u32* size_files)
+void WiiSave::ScanForFiles(const std::string& save_directory, std::vector& file_list,
+ u32* num_files, u32* size_files)
{
std::vector directories;
directories.push_back(save_directory);
@@ -653,6 +628,6 @@ void CWiiSaveCrypted::ScanForFiles(const std::string& save_directory,
*size_files = size;
}
-CWiiSaveCrypted::~CWiiSaveCrypted()
+WiiSave::~WiiSave()
{
}
diff --git a/Source/Core/Core/HW/WiiSave.h b/Source/Core/Core/HW/WiiSave.h
new file mode 100644
index 0000000000..995082eebd
--- /dev/null
+++ b/Source/Core/Core/HW/WiiSave.h
@@ -0,0 +1,135 @@
+// Copyright 2010 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include "Common/CommonTypes.h"
+#include "Common/Swap.h"
+
+class 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:
+ explicit WiiSave(std::string filename);
+ explicit WiiSave(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();
+ void make_ec_cert(u8* cert, const u8* sig, const char* signer, const char* name, const u8* priv,
+ const u32 key_id);
+ bool getPaths(bool for_export = false);
+ void ScanForFiles(const std::string& save_directory, std::vector& file_list,
+ u32* num_files, u32* size_files);
+
+ mbedtls_aes_context m_aes_ctx;
+ std::array m_sd_iv;
+ std::vector m_files_list;
+
+ std::string m_encrypted_save_path;
+
+ std::string m_wii_title_path;
+
+ std::array 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 save_game_title;
+ Common::BigEndianValue banner_size; // (0x72A0 or 0xF0A0, also seen 0xBAA0)
+ u8 permissions;
+ u8 unk1; // maybe permissions is a be16
+ std::array md5; // md5 of plaintext header with md5 blanker applied
+ Common::BigEndianValue unk2;
+ };
+
+ struct Header
+ {
+ DataBinHeader hdr;
+ u8 banner[FULL_BNR_MAX];
+ };
+
+ struct BkHeader // Not encrypted
+ {
+ Common::BigEndianValue size; // 0x00000070
+ // u16 magic; // 'Bk'
+ // u16 magic2; // or version (0x0001)
+ Common::BigEndianValue magic; // 0x426B0001
+ Common::BigEndianValue ngid;
+ Common::BigEndianValue number_of_files;
+ Common::BigEndianValue size_of_files;
+ Common::BigEndianValue unk1;
+ Common::BigEndianValue unk2;
+ Common::BigEndianValue total_size;
+ std::array unk3;
+ Common::BigEndianValue save_game_title;
+ std::array mac_address;
+ std::array padding;
+ };
+
+ struct FileHDR // encrypted
+ {
+ Common::BigEndianValue magic; // 0x03adf17e
+ Common::BigEndianValue size;
+ u8 permissions;
+ u8 attrib;
+ u8 type; // (1=file, 2=directory)
+ std::array name;
+ std::array iv;
+ std::array unk;
+ };
+#pragma pack(pop)
+
+ Header m_header;
+ Header m_encrypted_header;
+ BkHeader m_bk_hdr;
+};
diff --git a/Source/Core/Core/HW/WiiSaveCrypted.h b/Source/Core/Core/HW/WiiSaveCrypted.h
deleted file mode 100644
index bd4f74838c..0000000000
--- a/Source/Core/Core/HW/WiiSaveCrypted.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2010 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include
-#include
-#include
-
-#include "Common/CommonTypes.h"
-
-class CWiiSaveCrypted
-{
-public:
- bool static ImportWiiSave(const std::string& filename);
- bool static ExportWiiSave(u64 title_id);
- void static ExportAllSaves();
-
-private:
- CWiiSaveCrypted(const std::string& filename, u64 title_id = 0);
- ~CWiiSaveCrypted();
- void ReadHDR();
- void ReadBKHDR();
- void WriteHDR();
- void WriteBKHDR();
- void Extract() {}
- void ImportWiiSaveFiles();
- void ExportWiiSaveFiles();
- void do_sig();
- void make_ec_cert(u8* cert, const u8* sig, const char* signer, const char* name, const u8* priv,
- const u32 key_id);
- bool getPaths(bool for_export = false);
- void ScanForFiles(const std::string& save_directory, std::vector& file_list,
- u32* num_files, u32* size_files);
-
- static const u8 s_sd_key[16];
- static const u8 s_md5_blanker[16];
- static const u32 s_ng_id;
-
- mbedtls_aes_context m_aes_ctx;
- u8 m_sd_iv[0x10];
- std::vector m_files_list;
-
- std::string m_encrypted_save_path;
-
- std::string m_wii_title_path;
-
- u8 m_iv[0x10];
-
- u32 m_files_list_size;
- u32 m_size_of_files;
- u32 m_total_size;
-
- 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 Data_Bin_HDR // encrypted
- {
- u64 SaveGameTitle;
- u32 BannerSize; // (0x72A0 or 0xF0A0, also seen 0xBAA0)
- u8 Permissions;
- u8 unk1; // maybe permissions is a be16
- u8 Md5[0x10]; // md5 of plaintext header with md5 blanker applied
- u16 unk2;
- };
-
- struct HEADER
- {
- Data_Bin_HDR hdr;
- u8 BNR[FULL_BNR_MAX];
- };
-
- struct BK_Header // Not encrypted
- {
- u32 size; // 0x00000070
- // u16 magic; // 'Bk'
- // u16 magic2; // or version (0x0001)
- u32 magic; // 0x426B0001
- u32 NGid;
- u32 numberOfFiles;
- u32 sizeOfFiles;
- u32 unk1;
- u32 unk2;
- u32 totalSize;
- u8 unk3[64];
- u64 SaveGameTitle;
- u8 MACaddress[6];
- u8 padding[0x12];
- };
-
- struct FileHDR // encrypted
- {
- u32 magic; // 0x03adf17e
- u32 size;
- u8 Permissions;
- u8 attrib;
- u8 type; // (1=file, 2=directory)
- u8 name[0x45];
- u8 IV[0x10];
- u8 unk[0x20];
- };
-#pragma pack(pop)
-
- HEADER m_header;
- HEADER m_encrypted_header;
- BK_Header m_bk_hdr;
-};
diff --git a/Source/Core/DolphinQt2/GameList/GameList.cpp b/Source/Core/DolphinQt2/GameList/GameList.cpp
index 76aef93609..00e30abace 100644
--- a/Source/Core/DolphinQt2/GameList/GameList.cpp
+++ b/Source/Core/DolphinQt2/GameList/GameList.cpp
@@ -20,7 +20,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/DVD/DVDInterface.h"
-#include "Core/HW/WiiSaveCrypted.h"
+#include "Core/HW/WiiSave.h"
#include "Core/WiiUtils.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
@@ -258,14 +258,16 @@ void GameList::OpenProperties()
void GameList::ExportWiiSave()
{
- QMessageBox result_dialog(this);
+ const QString export_dir = QFileDialog::getExistingDirectory(
+ this, tr("Select Export Directory"), QString::fromStdString(File::GetUserPath(D_USER_IDX)),
+ QFileDialog::ShowDirsOnly);
+ if (export_dir.isEmpty())
+ return;
- const bool success = CWiiSaveCrypted::ExportWiiSave(GetSelectedGame()->GetTitleID());
-
- result_dialog.setIcon(success ? QMessageBox::Information : QMessageBox::Critical);
- result_dialog.setText(success ? tr("Successfully exported save files") :
- tr("Failed to export save files!"));
- result_dialog.exec();
+ if (WiiSave::Export(GetSelectedGame()->GetTitleID(), export_dir.toStdString()))
+ QMessageBox::information(this, tr("Save Export"), tr("Successfully exported save files"));
+ else
+ QMessageBox::critical(this, tr("Save Export"), tr("Failed to export save files."));
}
void GameList::OpenWiki()
diff --git a/Source/Core/DolphinQt2/MenuBar.cpp b/Source/Core/DolphinQt2/MenuBar.cpp
index 7d4e46ceba..5f939fb087 100644
--- a/Source/Core/DolphinQt2/MenuBar.cpp
+++ b/Source/Core/DolphinQt2/MenuBar.cpp
@@ -26,7 +26,7 @@
#include "Core/Core.h"
#include "Core/Debugger/RSO.h"
#include "Core/HLE/HLE.h"
-#include "Core/HW/WiiSaveCrypted.h"
+#include "Core/HW/WiiSave.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IOS/ES/ES.h"
@@ -896,13 +896,26 @@ void MenuBar::ImportWiiSave()
tr("Wii save files (*.bin);;"
"All Files (*)"));
- if (!file.isEmpty())
- CWiiSaveCrypted::ImportWiiSave(file.toStdString());
+ if (file.isEmpty())
+ return;
+
+ if (WiiSave::Import(file.toStdString()))
+ QMessageBox::information(this, tr("Save Import"), tr("Successfully imported save files."));
+ else
+ QMessageBox::critical(this, tr("Save Import"), tr("Failed to import save files."));
}
void MenuBar::ExportWiiSaves()
{
- CWiiSaveCrypted::ExportAllSaves();
+ const QString export_dir = QFileDialog::getExistingDirectory(
+ this, tr("Select Export Directory"), QString::fromStdString(File::GetUserPath(D_USER_IDX)),
+ QFileDialog::ShowDirsOnly);
+ if (export_dir.isEmpty())
+ return;
+
+ const size_t count = WiiSave::ExportAll(export_dir.toStdString());
+ QMessageBox::information(this, tr("Save Export"),
+ tr("Exported %n save(s)", "", static_cast(count)));
}
void MenuBar::CheckNAND()
diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp
index d123d3ccca..ea6f504e7c 100644
--- a/Source/Core/DolphinWX/FrameTools.cpp
+++ b/Source/Core/DolphinWX/FrameTools.cpp
@@ -45,7 +45,7 @@
#include "Core/HW/GCPad.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SI/SI_Device.h"
-#include "Core/HW/WiiSaveCrypted.h"
+#include "Core/HW/WiiSave.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/HotkeyManager.h"
@@ -1204,7 +1204,7 @@ void CFrame::OnLoadGameCubeIPLEUR(wxCommandEvent&)
void CFrame::OnExportAllSaves(wxCommandEvent& WXUNUSED(event))
{
- CWiiSaveCrypted::ExportAllSaves();
+ WiiSave::ExportAll(File::GetUserPath(D_USER_IDX));
}
void CFrame::OnImportSave(wxCommandEvent& WXUNUSED(event))
@@ -1215,7 +1215,7 @@ void CFrame::OnImportSave(wxCommandEvent& WXUNUSED(event))
wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST, this);
if (!path.IsEmpty())
- CWiiSaveCrypted::ImportWiiSave(WxStrToStr(path));
+ WiiSave::Import(WxStrToStr(path));
}
void CFrame::OnShowCheatsWindow(wxCommandEvent& WXUNUSED(event))
diff --git a/Source/Core/DolphinWX/GameListCtrl.cpp b/Source/Core/DolphinWX/GameListCtrl.cpp
index 30c973eb42..fcf0aa3d0f 100644
--- a/Source/Core/DolphinWX/GameListCtrl.cpp
+++ b/Source/Core/DolphinWX/GameListCtrl.cpp
@@ -45,7 +45,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/DVD/DVDInterface.h"
-#include "Core/HW/WiiSaveCrypted.h"
+#include "Core/HW/WiiSave.h"
#include "Core/Movie.h"
#include "Core/SysConf.h"
#include "Core/TitleDatabase.h"
@@ -988,7 +988,7 @@ void GameListCtrl::OnExportSave(wxCommandEvent& WXUNUSED(event))
{
const UICommon::GameFile* iso = GetSelectedISO();
if (iso)
- CWiiSaveCrypted::ExportWiiSave(iso->GetTitleID());
+ WiiSave::Export(iso->GetTitleID(), File::GetUserPath(D_USER_IDX));
}
// Save this file as the default file