Skip to content
Permalink
Browse files
Merge pull request #10187 from AdmiralCurtiss/json-gamelist
Support for GameModDescriptor files in Game List.
  • Loading branch information
leoetlino committed Dec 14, 2021
2 parents 45fac51 + b928900 commit 185475f
Show file tree
Hide file tree
Showing 25 changed files with 575 additions and 66 deletions.
@@ -30,7 +30,7 @@
public final class FileBrowserHelper
{
public static final HashSet<String> GAME_EXTENSIONS = new HashSet<>(Arrays.asList(
"gcm", "tgc", "iso", "ciso", "gcz", "wbfs", "wia", "rvz", "wad", "dol", "elf"));
"gcm", "tgc", "iso", "ciso", "gcz", "wbfs", "wia", "rvz", "wad", "dol", "elf", "json"));

public static final HashSet<String> GAME_LIKE_EXTENSIONS = new HashSet<>(GAME_EXTENSIONS);

@@ -155,17 +155,24 @@ const std::vector<u64>& BootSessionData::GetWiiSyncTitles() const
return m_wii_sync_titles;
}

const std::string& BootSessionData::GetWiiSyncRedirectFolder() const
{
return m_wii_sync_redirect_folder;
}

void BootSessionData::InvokeWiiSyncCleanup() const
{
if (m_wii_sync_cleanup)
m_wii_sync_cleanup();
}

void BootSessionData::SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs,
std::vector<u64> titles, WiiSyncCleanupFunction cleanup)
std::vector<u64> titles, std::string redirect_folder,
WiiSyncCleanupFunction cleanup)
{
m_wii_sync_fs = std::move(fs);
m_wii_sync_titles = std::move(titles);
m_wii_sync_redirect_folder = std::move(redirect_folder);
m_wii_sync_cleanup = std::move(cleanup);
}

@@ -66,16 +66,18 @@ class BootSessionData

IOS::HLE::FS::FileSystem* GetWiiSyncFS() const;
const std::vector<u64>& GetWiiSyncTitles() const;
const std::string& GetWiiSyncRedirectFolder() const;
void InvokeWiiSyncCleanup() const;
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, std::vector<u64> titles,
WiiSyncCleanupFunction cleanup);
std::string redirect_folder, WiiSyncCleanupFunction cleanup);

private:
std::optional<std::string> m_savestate_path;
DeleteSavestateAfterBoot m_delete_savestate = DeleteSavestateAfterBoot::No;

std::unique_ptr<IOS::HLE::FS::FileSystem> m_wii_sync_fs;
std::vector<u64> m_wii_sync_titles;
std::string m_wii_sync_redirect_folder;
WiiSyncCleanupFunction m_wii_sync_cleanup;
};

@@ -1077,13 +1077,20 @@ void NetPlayClient::OnSyncSaveDataGCI(sf::Packet& packet)
void NetPlayClient::OnSyncSaveDataWii(sf::Packet& packet)
{
const std::string path = File::GetUserPath(D_USER_IDX) + "Wii" GC_MEMCARD_NETPLAY DIR_SEP;
std::string redirect_path = File::GetUserPath(D_USER_IDX) + "Redirect" GC_MEMCARD_NETPLAY DIR_SEP;

if (File::Exists(path) && !File::DeleteDirRecursively(path))
{
PanicAlertFmtT("Failed to reset NetPlay NAND folder. Verify your write permissions.");
SyncSaveDataResponse(false);
return;
}
if (File::Exists(redirect_path) && !File::DeleteDirRecursively(redirect_path))
{
PanicAlertFmtT("Failed to reset NetPlay redirect folder. Verify your write permissions.");
SyncSaveDataResponse(false);
return;
}

auto temp_fs = std::make_unique<IOS::HLE::FS::HostFileSystem>(path);
std::vector<u64> titles;
@@ -1190,7 +1197,19 @@ void NetPlayClient::OnSyncSaveDataWii(sf::Packet& packet)
}
}

SetWiiSyncData(std::move(temp_fs), std::move(titles));
bool has_redirected_save;
packet >> has_redirected_save;
if (has_redirected_save)
{
if (!DecompressPacketIntoFolder(packet, redirect_path))
{
PanicAlertFmtT("Failed to write redirected save.");
SyncSaveDataResponse(false);
return;
}
}

SetWiiSyncData(std::move(temp_fs), std::move(titles), std::move(redirect_path));
SyncSaveDataResponse(true);
}

@@ -1721,12 +1740,18 @@ bool NetPlayClient::StartGame(const std::string& path)

// boot game
auto boot_session_data = std::make_unique<BootSessionData>();
boot_session_data->SetWiiSyncData(std::move(m_wii_sync_fs), std::move(m_wii_sync_titles), [] {
// on emulation end clean up the Wii save sync directory -- see OnSyncSaveDataWii()
const std::string path = File::GetUserPath(D_USER_IDX) + "Wii" GC_MEMCARD_NETPLAY DIR_SEP;
if (File::Exists(path))
File::DeleteDirRecursively(path);
});
boot_session_data->SetWiiSyncData(
std::move(m_wii_sync_fs), std::move(m_wii_sync_titles), std::move(m_wii_sync_redirect_folder),
[] {
// on emulation end clean up the Wii save sync directory -- see OnSyncSaveDataWii()
const std::string path = File::GetUserPath(D_USER_IDX) + "Wii" GC_MEMCARD_NETPLAY DIR_SEP;
if (File::Exists(path))
File::DeleteDirRecursively(path);
const std::string redirect_path =
File::GetUserPath(D_USER_IDX) + "Redirect" GC_MEMCARD_NETPLAY DIR_SEP;
if (File::Exists(redirect_path))
File::DeleteDirRecursively(redirect_path);
});
m_dialog->BootGame(path, std::move(boot_session_data));

UpdateDevices();
@@ -2501,10 +2526,11 @@ void NetPlayClient::AdjustPadBufferSize(const unsigned int size)
}

void NetPlayClient::SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs,
std::vector<u64> titles)
std::vector<u64> titles, std::string redirect_folder)
{
m_wii_sync_fs = std::move(fs);
m_wii_sync_titles = std::move(titles);
m_wii_sync_redirect_folder = std::move(redirect_folder);
}

SyncIdentifier NetPlayClient::GetSDCardIdentifier()
@@ -86,7 +86,7 @@ class NetPlayUI
virtual void HideChunkedProgressDialog() = 0;
virtual void SetChunkedProgress(int pid, u64 progress) = 0;

virtual void SetHostWiiSyncTitles(std::vector<u64> titles) = 0;
virtual void SetHostWiiSyncData(std::vector<u64> titles, std::string redirect_folder) = 0;
};

class Player
@@ -157,7 +157,8 @@ class NetPlayClient : public TraversalClientClient

void AdjustPadBufferSize(unsigned int size);

void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, std::vector<u64> titles);
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, std::vector<u64> titles,
std::string redirect_folder);

static SyncIdentifier GetSDCardIdentifier();

@@ -328,6 +329,7 @@ class NetPlayClient : public TraversalClientClient

std::unique_ptr<IOS::HLE::FS::FileSystem> m_wii_sync_fs;
std::vector<u64> m_wii_sync_titles;
std::string m_wii_sync_redirect_folder;
};

void NetPlay_Enable(NetPlayClient* const np);
@@ -3,6 +3,7 @@

#include "Core/NetPlayCommon.h"

#include <fmt/format.h>
#include <lzo/lzo1x.h>

#include "Common/FileUtil.h"
@@ -84,6 +85,35 @@ bool CompressFileIntoPacket(const std::string& file_path, sf::Packet& packet)
return true;
}

static bool CompressFolderIntoPacketInternal(const File::FSTEntry& folder, sf::Packet& packet)
{
const sf::Uint64 size = folder.children.size();
packet << size;
for (const auto& child : folder.children)
{
const bool is_folder = child.isDirectory;
packet << child.virtualName;
packet << is_folder;
const bool success = is_folder ? CompressFolderIntoPacketInternal(child, packet) :
CompressFileIntoPacket(child.physicalName, packet);
if (!success)
return false;
}
return true;
}

bool CompressFolderIntoPacket(const std::string& folder_path, sf::Packet& packet)
{
if (!File::IsDirectory(folder_path))
{
packet << false;
return true;
}

packet << true;
return CompressFolderIntoPacketInternal(File::ScanDirectoryTree(folder_path, true), packet);
}

bool CompressBufferIntoPacket(const std::vector<u8>& in_buffer, sf::Packet& packet)
{
const sf::Uint64 size = in_buffer.size();
@@ -187,6 +217,47 @@ bool DecompressPacketIntoFile(sf::Packet& packet, const std::string& file_path)
return true;
}

static bool DecompressPacketIntoFolderInternal(sf::Packet& packet, const std::string& folder_path)
{
if (!File::CreateFullPath(folder_path + "/"))
return false;

sf::Uint64 size;
packet >> size;
for (size_t i = 0; i < size; ++i)
{
std::string name;
packet >> name;

if (name.find('/') != std::string::npos)
return false;
#ifdef _WIN32
if (name.find('\\') != std::string::npos)
return false;
#endif
if (std::all_of(name.begin(), name.end(), [](char c) { return c == '.'; }))
return false;

bool is_folder;
packet >> is_folder;
std::string path = fmt::format("{}/{}", folder_path, name);
const bool success = is_folder ? DecompressPacketIntoFolderInternal(packet, path) :
DecompressPacketIntoFile(packet, path);
if (!success)
return false;
}
return true;
}

bool DecompressPacketIntoFolder(sf::Packet& packet, const std::string& folder_path)
{
bool folder_existed;
packet >> folder_existed;
if (!folder_existed)
return true;
return DecompressPacketIntoFolderInternal(packet, folder_path);
}

std::optional<std::vector<u8>> DecompressPacketIntoBuffer(sf::Packet& packet)
{
u64 size = Common::PacketReadU64(packet);
@@ -15,7 +15,9 @@
namespace NetPlay
{
bool CompressFileIntoPacket(const std::string& file_path, sf::Packet& packet);
bool CompressFolderIntoPacket(const std::string& folder_path, sf::Packet& packet);
bool CompressBufferIntoPacket(const std::vector<u8>& in_buffer, sf::Packet& packet);
bool DecompressPacketIntoFile(sf::Packet& packet, const std::string& file_path);
bool DecompressPacketIntoFolder(sf::Packet& packet, const std::string& folder_path);
std::optional<std::vector<u8>> DecompressPacketIntoBuffer(sf::Packet& packet);
} // namespace NetPlay
@@ -31,6 +31,7 @@
#include "Common/Version.h"

#include "Core/ActionReplay.h"
#include "Core/Boot/Boot.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/NetplaySettings.h"
@@ -60,6 +61,7 @@
#include "Core/SyncIdentifier.h"

#include "DiscIO/Enums.h"
#include "DiscIO/RiivolutionPatcher.h"

#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
#include "InputCommon/GCPadStatus.h"
@@ -1616,6 +1618,17 @@ bool NetPlayServer::SyncSaveData()
save_count++;
}

std::optional<DiscIO::Riivolution::SavegameRedirect> redirected_save;
if (wii_save && game->GetBlobType() == DiscIO::BlobType::MOD_DESCRIPTOR)
{
auto boot_params = BootParameters::GenerateFromFile(game->GetFilePath());
if (boot_params)
{
redirected_save =
DiscIO::Riivolution::ExtractSavegameRedirect(boot_params->riivolution_patches);
}
}

for (const auto& config : m_gba_config)
{
if (config.enabled && config.has_rom)
@@ -1818,8 +1831,20 @@ bool NetPlayServer::SyncSaveData()
}
}

if (redirected_save)
{
pac << true;
if (!CompressFolderIntoPacket(redirected_save->m_target_path, pac))
return false;
}
else
{
pac << false; // no redirected save
}

// Set titles for host-side loading in WiiRoot
m_dialog->SetHostWiiSyncTitles(std::move(titles));
m_dialog->SetHostWiiSyncData(std::move(titles),
redirected_save ? redirected_save->m_target_path : "");

SendChunkedToClients(std::move(pac), 1, "Wii Save Synchronization");
}

0 comments on commit 185475f

Please sign in to comment.