From 1b8eda827bc16acc449ad66ed9cb5d228d515c3b Mon Sep 17 00:00:00 2001 From: Techjar Date: Mon, 8 Apr 2019 07:06:21 -0400 Subject: [PATCH] NetPlay: Synchronize Mii data It's bundled with the Wii saves for simplicity, since it's quite small. --- Source/Core/Common/NandPaths.cpp | 7 +++- Source/Core/Common/NandPaths.h | 3 +- Source/Core/Core/NetPlayClient.cpp | 29 +++++++++++++-- Source/Core/Core/NetPlayServer.cpp | 23 ++++++++++++ Source/Core/Core/WiiRoot.cpp | 57 ++++++++++++++++++++++++++++-- 5 files changed, 111 insertions(+), 8 deletions(-) diff --git a/Source/Core/Common/NandPaths.cpp b/Source/Core/Common/NandPaths.cpp index 336c1bb7bb..390d95033c 100644 --- a/Source/Core/Common/NandPaths.cpp +++ b/Source/Core/Common/NandPaths.cpp @@ -60,6 +60,11 @@ std::string GetTMDFileName(u64 title_id, std::optional from) return GetTitleContentPath(title_id, from) + "/title.tmd"; } +std::string GetMiiDatabasePath(std::optional from) +{ + return StringFromFormat("%s/shared2/menu/FaceLib/RFL_DB.dat", RootUserPath(from).c_str()); +} + bool IsTitlePath(const std::string& path, std::optional from, u64* title_id) { std::string expected_prefix = RootUserPath(from) + "/title/"; @@ -145,4 +150,4 @@ std::string UnescapeFileName(const std::string& filename) return result; } -} +} // namespace Common diff --git a/Source/Core/Common/NandPaths.h b/Source/Core/Common/NandPaths.h index 068a240f43..97fd0649c8 100644 --- a/Source/Core/Common/NandPaths.h +++ b/Source/Core/Common/NandPaths.h @@ -31,6 +31,7 @@ std::string GetTitlePath(u64 title_id, std::optional from = {}); std::string GetTitleDataPath(u64 title_id, std::optional from = {}); std::string GetTitleContentPath(u64 title_id, std::optional from = {}); std::string GetTMDFileName(u64 title_id, std::optional from = {}); +std::string GetMiiDatabasePath(std::optional from = {}); // Returns whether a path is within an installed title's directory. bool IsTitlePath(const std::string& path, std::optional from = {}, @@ -42,4 +43,4 @@ std::string EscapeFileName(const std::string& filename); std::string EscapePath(const std::string& path); // Reverses escaping done by EscapeFileName std::string UnescapeFileName(const std::string& filename); -} +} // namespace Common diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index a2e6dcc562..7a7759c737 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -866,6 +866,31 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) auto temp_fs = std::make_unique(path); std::vector titles; + const IOS::HLE::FS::Modes fs_modes = {IOS::HLE::FS::Mode::ReadWrite, + IOS::HLE::FS::Mode::ReadWrite, + IOS::HLE::FS::Mode::ReadWrite}; + + // Read the Mii data + bool mii_data; + packet >> mii_data; + if (mii_data) + { + auto buffer = DecompressPacketIntoBuffer(packet); + + temp_fs->CreateDirectory(IOS::PID_KERNEL, IOS::PID_KERNEL, "/shared2/menu/FaceLib", 0, + fs_modes); + auto file = temp_fs->CreateAndOpenFile(IOS::PID_KERNEL, IOS::PID_KERNEL, + Common::GetMiiDatabasePath(), fs_modes); + + if (!buffer || !file || !file->Write(buffer->data(), buffer->size())) + { + PanicAlertT("Failed to write Mii data."); + SyncSaveDataResponse(false); + return 0; + } + } + + // Read the saves u32 save_count; packet >> save_count; for (u32 n = 0; n < save_count; n++) @@ -873,9 +898,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) u64 title_id = Common::PacketReadU64(packet); titles.push_back(title_id); temp_fs->CreateDirectory(IOS::PID_KERNEL, IOS::PID_KERNEL, - Common::GetTitleDataPath(title_id), 0, - {IOS::HLE::FS::Mode::ReadWrite, IOS::HLE::FS::Mode::ReadWrite, - IOS::HLE::FS::Mode::ReadWrite}); + Common::GetTitleDataPath(title_id), 0, fs_modes); auto save = WiiSave::MakeNandStorage(temp_fs.get(), title_id); bool exists; diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index abaf5446ba..c4507aa243 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -48,6 +48,7 @@ #include "Core/IOS/ES/ES.h" #include "Core/IOS/FS/FileSystem.h" #include "Core/IOS/IOS.h" +#include "Core/IOS/Uids.h" #include "Core/NetPlayClient.h" //for NetPlayUI #include "DiscIO/Enums.h" #include "InputCommon/ControllerEmu/ControlGroup/Attachments.h" @@ -1490,6 +1491,28 @@ bool NetPlayServer::SyncSaveData() sf::Packet pac; pac << static_cast(NP_MSG_SYNC_SAVE_DATA); pac << static_cast(SYNC_SAVE_DATA_WII); + + // Shove the Mii data into the start the packet + { + auto file = configured_fs->OpenFile(IOS::PID_KERNEL, IOS::PID_KERNEL, + Common::GetMiiDatabasePath(), IOS::HLE::FS::Mode::Read); + if (file) + { + pac << true; + + std::vector file_data(file->GetStatus()->size); + if (!file->Read(file_data.data(), file_data.size())) + return false; + if (!CompressBufferIntoPacket(file_data, pac)) + return false; + } + else + { + pac << false; // no mii data + } + } + + // Carry on with the save files pac << static_cast(saves.size()); for (const auto& pair : saves) diff --git a/Source/Core/Core/WiiRoot.cpp b/Source/Core/Core/WiiRoot.cpp index 1e846eca55..c849b5530d 100644 --- a/Source/Core/Core/WiiRoot.cpp +++ b/Source/Core/Core/WiiRoot.cpp @@ -41,6 +41,36 @@ static void CopySave(FS::FileSystem* source, FS::FileSystem* dest, const u64 tit WiiSave::Copy(source_save.get(), dest_save.get()); } +static bool CopyNandFile(FS::FileSystem* source_fs, const std::string& source_file, + FS::FileSystem* dest_fs, const std::string& dest_file) +{ + const auto last_slash = dest_file.find_last_of('/'); + if (last_slash != std::string::npos && last_slash > 0) + { + const std::string dir = dest_file.substr(0, last_slash); + dest_fs->CreateDirectory(IOS::PID_KERNEL, IOS::PID_KERNEL, dir, 0, + {IOS::HLE::FS::Mode::ReadWrite, IOS::HLE::FS::Mode::ReadWrite, + IOS::HLE::FS::Mode::ReadWrite}); + } + + auto source_handle = + source_fs->OpenFile(IOS::PID_KERNEL, IOS::PID_KERNEL, source_file, IOS::HLE::FS::Mode::Read); + auto dest_handle = + dest_fs->CreateAndOpenFile(IOS::PID_KERNEL, IOS::PID_KERNEL, source_file, + {IOS::HLE::FS::Mode::ReadWrite, IOS::HLE::FS::Mode::ReadWrite, + IOS::HLE::FS::Mode::ReadWrite}); + if (!source_handle || !dest_handle) + return false; + + std::vector buffer(source_handle->GetStatus()->size); + if (!source_handle->Read(buffer.data(), buffer.size())) + return false; + if (!dest_handle->Write(buffer.data(), buffer.size())) + return false; + + return true; +} + static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs) { const u64 title_id = SConfig::GetInstance().GetTitleID(); @@ -71,6 +101,13 @@ static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs) { CopySave(sync_fs, session_fs, title); } + + // Copy Mii data + if (!CopyNandFile(sync_fs, Common::GetMiiDatabasePath(), session_fs, + Common::GetMiiDatabasePath())) + { + WARN_LOG(CORE, "Failed to copy Mii database to the NAND"); + } } else { @@ -85,6 +122,13 @@ static void InitializeDeterministicWiiSaves(FS::FileSystem* session_fs) { CopySave(configured_fs.get(), session_fs, title_id); } + + // Copy Mii data + if (!CopyNandFile(configured_fs.get(), Common::GetMiiDatabasePath(), session_fs, + Common::GetMiiDatabasePath())) + { + WARN_LOG(CORE, "Failed to copy Mii database to the NAND"); + } } } } @@ -198,13 +242,20 @@ void CleanUpWiiFileSystemContents() return; } + IOS::HLE::EmulationKernel* ios = IOS::HLE::GetIOS(); + const auto configured_fs = FS::MakeFileSystem(FS::Location::Configured); + + // Copy back Mii data + if (!CopyNandFile(ios->GetFS().get(), Common::GetMiiDatabasePath(), configured_fs.get(), + Common::GetMiiDatabasePath())) + { + WARN_LOG(CORE, "Failed to copy Mii database to the NAND"); + } + const u64 title_id = SConfig::GetInstance().GetTitleID(); - IOS::HLE::EmulationKernel* ios = IOS::HLE::GetIOS(); const auto session_save = WiiSave::MakeNandStorage(ios->GetFS().get(), title_id); - const auto configured_fs = FS::MakeFileSystem(FS::Location::Configured); - // FS won't write the save if the directory doesn't exist const std::string title_path = Common::GetTitleDataPath(title_id); if (!configured_fs->GetMetadata(IOS::PID_KERNEL, IOS::PID_KERNEL, title_path))