diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 37a1991cdb..a3f3f4dc93 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -37,6 +37,7 @@ add_library(core
PatchEngine.h
State.cpp
State.h
+ SyncIdentifier.h
SysConf.cpp
SysConf.h
TitleDatabase.cpp
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index ceefd749c9..dfe82922d6 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -709,6 +709,7 @@
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index cb729a6f4a..91553ac3af 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -1757,7 +1757,8 @@
HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA
-
+
+
diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp
index e6efce1799..4b1c730a7d 100644
--- a/Source/Core/Core/NetPlayClient.cpp
+++ b/Source/Core/Core/NetPlayClient.cpp
@@ -53,9 +53,11 @@
#include "Core/IOS/Uids.h"
#include "Core/Movie.h"
#include "Core/PowerPC/PowerPC.h"
+#include "Core/SyncIdentifier.h"
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
#include "InputCommon/GCAdapter.h"
#include "InputCommon/InputConfig.h"
+#include "UICommon/GameFile.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/VideoConfig.h"
@@ -284,6 +286,22 @@ bool NetPlayClient::Connect()
}
}
+static void ReceiveSyncIdentifier(sf::Packet& spac, SyncIdentifier& sync_identifier)
+{
+ // We use a temporary variable here due to a potential long vs long long mismatch
+ sf::Uint64 dol_elf_size;
+ spac >> dol_elf_size;
+ sync_identifier.dol_elf_size = dol_elf_size;
+
+ spac >> sync_identifier.game_id;
+ spac >> sync_identifier.revision;
+ spac >> sync_identifier.disc_number;
+ spac >> sync_identifier.is_datel;
+
+ for (u8& x : sync_identifier.sync_hash)
+ spac >> x;
+}
+
// called from ---NETPLAY--- thread
unsigned int NetPlayClient::OnData(sf::Packet& packet)
{
@@ -572,24 +590,25 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_CHANGE_GAME:
{
+ std::string netplay_name;
{
std::lock_guard lkg(m_crit.game);
- packet >> m_selected_game;
+ ReceiveSyncIdentifier(packet, m_selected_game);
+ packet >> netplay_name;
}
- INFO_LOG(NETPLAY, "Game changed to %s", m_selected_game.c_str());
+ INFO_LOG(NETPLAY, "Game changed to %s", netplay_name.c_str());
// update gui
- m_dialog->OnMsgChangeGame(m_selected_game);
+ m_dialog->OnMsgChangeGame(m_selected_game, netplay_name);
sf::Packet game_status_packet;
game_status_packet << static_cast(NP_MSG_GAME_STATUS);
- PlayerGameStatus status = m_dialog->FindGame(m_selected_game).empty() ?
- PlayerGameStatus::NotFound :
- PlayerGameStatus::Ok;
+ SyncIdentifierComparison result;
+ m_dialog->FindGameFile(m_selected_game, &result);
- game_status_packet << static_cast(status);
+ game_status_packet << static_cast(result);
Send(game_status_packet);
sf::Packet ipl_status_packet;
@@ -609,7 +628,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
Player& player = m_players[pid];
u32 status;
packet >> status;
- player.game_status = static_cast(status);
+ player.game_status = static_cast(status);
}
m_dialog->Update();
@@ -623,7 +642,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> m_current_game;
packet >> m_net_settings.m_CPUthread;
- INFO_LOG(NETPLAY, "Start of game %s", m_selected_game.c_str());
+ INFO_LOG(NETPLAY, "Start of game %s", m_selected_game.game_id.c_str());
{
std::underlying_type_t core;
@@ -1172,10 +1191,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_COMPUTE_MD5:
{
- std::string file_identifier;
- packet >> file_identifier;
+ SyncIdentifier sync_identifier;
+ ReceiveSyncIdentifier(packet, sync_identifier);
- ComputeMD5(file_identifier);
+ ComputeMD5(sync_identifier);
}
break;
@@ -1382,11 +1401,15 @@ void NetPlayClient::GetPlayerList(std::string& list, std::vector& pid_list)
switch (player.game_status)
{
- case PlayerGameStatus::Ok:
+ case SyncIdentifierComparison::SameGame:
ss << "ready";
break;
- case PlayerGameStatus::NotFound:
+ case SyncIdentifierComparison::DifferentVersion:
+ ss << "wrong game version";
+ break;
+
+ case SyncIdentifierComparison::DifferentGame:
ss << "game missing";
break;
@@ -2286,23 +2309,24 @@ bool NetPlayClient::DoAllPlayersHaveGame()
{
std::lock_guard lkp(m_crit.players);
- return std::all_of(std::begin(m_players), std::end(m_players),
- [](auto entry) { return entry.second.game_status == PlayerGameStatus::Ok; });
+ return std::all_of(std::begin(m_players), std::end(m_players), [](auto entry) {
+ return entry.second.game_status == SyncIdentifierComparison::SameGame;
+ });
}
-void NetPlayClient::ComputeMD5(const std::string& file_identifier)
+void NetPlayClient::ComputeMD5(const SyncIdentifier& sync_identifier)
{
if (m_should_compute_MD5)
return;
- m_dialog->ShowMD5Dialog(file_identifier);
+ m_dialog->ShowMD5Dialog(sync_identifier.game_id);
m_should_compute_MD5 = true;
std::string file;
- if (file_identifier == WII_SDCARD)
+ if (sync_identifier == GetSDCardIdentifier())
file = File::GetUserPath(F_WIISDCARD_IDX);
- else
- file = m_dialog->FindGame(file_identifier);
+ else if (auto game = m_dialog->FindGameFile(sync_identifier))
+ file = game->GetFilePath();
if (file.empty() || !File::Exists(file))
{
@@ -2348,6 +2372,11 @@ void NetPlayClient::AdjustPadBufferSize(const unsigned int size)
m_dialog->OnPadBufferChanged(size);
}
+SyncIdentifier NetPlayClient::GetSDCardIdentifier()
+{
+ return SyncIdentifier{{}, "sd", {}, {}, {}, {}};
+}
+
bool IsNetPlayRunning()
{
return netplay_client != nullptr;
diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h
index 2e6acf4518..6af81e8d60 100644
--- a/Source/Core/Core/NetPlayClient.h
+++ b/Source/Core/Core/NetPlayClient.h
@@ -22,6 +22,7 @@
#include "Common/SPSCQueue.h"
#include "Common/TraversalClient.h"
#include "Core/NetPlayProto.h"
+#include "Core/SyncIdentifier.h"
#include "InputCommon/GCPadStatus.h"
namespace UICommon
@@ -42,7 +43,8 @@ public:
virtual void Update() = 0;
virtual void AppendChat(const std::string& msg) = 0;
- virtual void OnMsgChangeGame(const std::string& filename) = 0;
+ virtual void OnMsgChangeGame(const SyncIdentifier& sync_identifier,
+ const std::string& netplay_name) = 0;
virtual void OnMsgStartGame() = 0;
virtual void OnMsgStopGame() = 0;
virtual void OnMsgPowerButton() = 0;
@@ -59,9 +61,10 @@ public:
virtual void OnGolferChanged(bool is_golfer, const std::string& golfer_name) = 0;
virtual bool IsRecording() = 0;
- virtual std::string FindGame(const std::string& game) = 0;
- virtual std::shared_ptr FindGameFile(const std::string& game) = 0;
- virtual void ShowMD5Dialog(const std::string& file_identifier) = 0;
+ virtual std::shared_ptr
+ FindGameFile(const SyncIdentifier& sync_identifier,
+ SyncIdentifierComparison* found = nullptr) = 0;
+ virtual void ShowMD5Dialog(const std::string& title) = 0;
virtual void SetMD5Progress(int pid, int progress) = 0;
virtual void SetMD5Result(int pid, const std::string& result) = 0;
virtual void AbortMD5() = 0;
@@ -75,13 +78,6 @@ public:
virtual void SetChunkedProgress(int pid, u64 progress) = 0;
};
-enum class PlayerGameStatus
-{
- Unknown,
- Ok,
- NotFound
-};
-
class Player
{
public:
@@ -89,7 +85,7 @@ public:
std::string name;
std::string revision;
u32 ping;
- PlayerGameStatus game_status;
+ SyncIdentifierComparison game_status;
bool IsHost() const { return pid == 1; }
};
@@ -149,6 +145,8 @@ public:
void AdjustPadBufferSize(unsigned int size);
+ static SyncIdentifier GetSDCardIdentifier();
+
protected:
struct AsyncQueueEntry
{
@@ -182,7 +180,7 @@ protected:
ENetPeer* m_server = nullptr;
std::thread m_thread;
- std::string m_selected_game;
+ SyncIdentifier m_selected_game;
Common::Flag m_is_running{false};
Common::Flag m_do_loop{true};
@@ -237,7 +235,7 @@ private:
void Send(const sf::Packet& packet, u8 channel_id = DEFAULT_CHANNEL);
void Disconnect();
bool Connect();
- void ComputeMD5(const std::string& file_identifier);
+ void ComputeMD5(const SyncIdentifier& sync_identifier);
void DisplayPlayersPing();
u32 GetPlayersMaxPing() const;
diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp
index e76d362285..aac046ed44 100644
--- a/Source/Core/Core/NetPlayServer.cpp
+++ b/Source/Core/Core/NetPlayServer.cpp
@@ -51,6 +51,7 @@
#include "Core/IOS/IOS.h"
#include "Core/IOS/Uids.h"
#include "Core/NetPlayClient.h" //for NetPlayUI
+#include "Core/SyncIdentifier.h"
#include "DiscIO/Enums.h"
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
#include "InputCommon/GCPadStatus.h"
@@ -182,7 +183,7 @@ void NetPlayServer::SetupIndex()
session.region = Config::Get(Config::NETPLAY_INDEX_REGION);
session.has_password = !Config::Get(Config::NETPLAY_INDEX_PASSWORD).empty();
session.method = m_traversal_client ? "traversal" : "direct";
- session.game_id = m_selected_game.empty() ? "UNKNOWN" : m_selected_game;
+ session.game_id = m_selected_game_name.empty() ? "UNKNOWN" : m_selected_game_name;
session.player_count = static_cast(m_players.size());
session.in_game = m_is_running;
session.port = GetPort();
@@ -238,7 +239,7 @@ void NetPlayServer::ThreadFunc()
SendToClients(spac);
m_index.SetPlayerCount(static_cast(m_players.size()));
- m_index.SetGame(m_selected_game);
+ m_index.SetGame(m_selected_game_name);
m_index.SetInGame(m_is_running);
m_update_pings = false;
@@ -348,6 +349,20 @@ void NetPlayServer::ThreadFunc()
}
} // namespace NetPlay
+static void SendSyncIdentifier(sf::Packet& spac, const SyncIdentifier& sync_identifier)
+{
+ // We cast here due to a potential long vs long long mismatch
+ spac << static_cast(sync_identifier.dol_elf_size);
+
+ spac << sync_identifier.game_id;
+ spac << sync_identifier.revision;
+ spac << sync_identifier.disc_number;
+ spac << sync_identifier.is_datel;
+
+ for (const u8& x : sync_identifier.sync_hash)
+ spac << x;
+}
+
// called from ---NETPLAY--- thread
unsigned int NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac)
{
@@ -413,11 +428,12 @@ unsigned int NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac)
Send(player.socket, spac);
// send new client the selected game
- if (!m_selected_game.empty())
+ if (!m_selected_game_name.empty())
{
spac.clear();
spac << static_cast(NP_MSG_CHANGE_GAME);
- spac << m_selected_game;
+ SendSyncIdentifier(spac, m_selected_game_identifier);
+ spac << m_selected_game_name;
Send(player.socket, spac);
}
@@ -913,7 +929,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
u32 status;
packet >> status;
- m_players[player.pid].game_status = static_cast(status);
+ m_players[player.pid].game_status = static_cast(status);
// send msg to other clients
sf::Packet spac;
@@ -1153,16 +1169,19 @@ void NetPlayServer::SendChatMessage(const std::string& msg)
}
// called from ---GUI--- thread
-bool NetPlayServer::ChangeGame(const std::string& game)
+bool NetPlayServer::ChangeGame(const SyncIdentifier& sync_identifier,
+ const std::string& netplay_name)
{
std::lock_guard lkg(m_crit.game);
- m_selected_game = game;
+ m_selected_game_identifier = sync_identifier;
+ m_selected_game_name = netplay_name;
// send changed game to clients
sf::Packet spac;
spac << static_cast(NP_MSG_CHANGE_GAME);
- spac << game;
+ SendSyncIdentifier(spac, m_selected_game_identifier);
+ spac << m_selected_game_name;
SendAsyncToClients(std::move(spac));
@@ -1170,11 +1189,11 @@ bool NetPlayServer::ChangeGame(const std::string& game)
}
// called from ---GUI--- thread
-bool NetPlayServer::ComputeMD5(const std::string& file_identifier)
+bool NetPlayServer::ComputeMD5(const SyncIdentifier& sync_identifier)
{
sf::Packet spac;
spac << static_cast(NP_MSG_COMPUTE_MD5);
- spac << file_identifier;
+ SendSyncIdentifier(spac, sync_identifier);
SendAsyncToClients(std::move(spac));
@@ -1260,7 +1279,7 @@ bool NetPlayServer::StartGame()
const sf::Uint64 initial_rtc = GetInitialNetPlayRTC();
const std::string region = SConfig::GetDirectoryForRegion(
- SConfig::ToGameCubeRegion(m_dialog->FindGameFile(m_selected_game)->GetRegion()));
+ SConfig::ToGameCubeRegion(m_dialog->FindGameFile(m_selected_game_identifier)->GetRegion()));
// sync GC SRAM with clients
if (!g_SRAM_netplay_initialized)
@@ -1395,7 +1414,7 @@ bool NetPlayServer::SyncSaveData()
}
}
- const auto game = m_dialog->FindGameFile(m_selected_game);
+ const auto game = m_dialog->FindGameFile(m_selected_game_identifier);
if (game == nullptr)
{
PanicAlertT("Selected game doesn't exist in game list!");
@@ -1618,7 +1637,7 @@ bool NetPlayServer::SyncCodes()
m_codes_synced = false;
// Get Game Path
- const auto game = m_dialog->FindGameFile(m_selected_game);
+ const auto game = m_dialog->FindGameFile(m_selected_game_identifier);
if (game == nullptr)
{
PanicAlertT("Selected game doesn't exist in game list!");
diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h
index 62b20f7744..16034074af 100644
--- a/Source/Core/Core/NetPlayServer.h
+++ b/Source/Core/Core/NetPlayServer.h
@@ -5,6 +5,7 @@
#pragma once
#include
+
#include