summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRachel Bryk <RachelBryk@gmail.com>2015-03-08 06:50:47 -0400
committercomex <comexk@gmail.com>2015-06-06 00:52:02 -0400
commit04ca54623cb896c06776668f2cb6abb5bd25d7f8 (patch)
tree1ae9e104f57f8b3b07dd93d33fd384e695963392 /Source/Core
parent3d9fdf57e8f199bf923c71533c598cfa746ccf26 (diff)
Compare timebase of netplay users to detect desyncs.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/ConfigManager.h2
-rw-r--r--Source/Core/Core/Movie.cpp4
-rw-r--r--Source/Core/Core/NetPlayClient.cpp33
-rw-r--r--Source/Core/Core/NetPlayClient.h2
-rw-r--r--Source/Core/Core/NetPlayProto.h5
-rw-r--r--Source/Core/Core/NetPlayServer.cpp51
6 files changed, 94 insertions, 3 deletions
diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h
index 42cd8d5d2b..ee60a059ae 100644
--- a/Source/Core/Core/ConfigManager.h
+++ b/Source/Core/Core/ConfigManager.h
@@ -118,6 +118,8 @@ struct SConfig : NonCopyable
bool m_GameCubeAdapter;
bool m_AdapterRumble;
+ bool m_NetplayDesyncCheck;
+
SysConf* m_SYSCONF;
// Save settings
diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp
index b59ff1d78a..2df26d93e8 100644
--- a/Source/Core/Core/Movie.cpp
+++ b/Source/Core/Core/Movie.cpp
@@ -17,6 +17,7 @@
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/Movie.h"
+#include "Core/NetPlayClient.h"
#include "Core/NetPlayProto.h"
#include "Core/State.h"
#include "Core/DSP/DSPCore.h"
@@ -163,6 +164,9 @@ void FrameUpdate()
FrameSkipping();
s_bPolled = false;
+
+ if (NetPlay::IsNetPlayRunning() && SConfig::GetInstance().m_NetplayDesyncCheck)
+ NetPlayClient::SendTimeBase();
}
// called when game is booting up, even if no movie is active,
diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp
index 3f53d58a32..6670acb202 100644
--- a/Source/Core/Core/NetPlayClient.cpp
+++ b/Source/Core/Core/NetPlayClient.cpp
@@ -374,6 +374,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_START_GAME:
{
{
+ SConfig::GetInstance().m_NetplayDesyncCheck = true;
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
packet >> m_current_game;
packet >> g_NetPlaySettings.m_CPUthread;
@@ -442,6 +443,24 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
}
break;
+ case NP_MSG_DESYNC_DETECTED:
+ {
+ if (!SConfig::GetInstance().m_NetplayDesyncCheck)
+ break;
+
+ int id;
+ u32 frame;
+ packet >> id;
+ packet >> frame;
+ std::string sID = "";
+ if (id != -1)
+ sID = StringFromFormat(" from player ID %d", id);
+
+ m_dialog->AppendChat("Possible desync detected" + sID + StringFromFormat(" on frame: %u", frame));
+ SConfig::GetInstance().m_NetplayDesyncCheck = false;
+ }
+ break;
+
default:
PanicAlertT("Unknown message received with id : %d", mid);
break;
@@ -1044,6 +1063,20 @@ u8 NetPlayClient::LocalWiimoteToInGameWiimote(u8 local_pad)
return ingame_pad;
}
+void NetPlayClient::SendTimeBase()
+{
+ std::lock_guard<std::mutex> lk(crit_netplay_client);
+
+ u64 timebase = SystemTimers::GetFakeTimeBase();
+
+ sf::Packet* spac = new sf::Packet;
+ *spac << (MessageId)NP_MSG_TIMEBASE;
+ *spac << (u32)timebase;
+ *spac << (u32)(timebase << 32);
+ *spac << (u32)Movie::g_currentFrame;
+ netplay_client->SendAsync(spac);
+}
+
// stuff hacked into dolphin
// called from ---CPU--- thread
diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h
index ce5d0ee63b..f12b489b7d 100644
--- a/Source/Core/Core/NetPlayClient.h
+++ b/Source/Core/Core/NetPlayClient.h
@@ -77,6 +77,8 @@ public:
u8 LocalWiimoteToInGameWiimote(u8 local_pad);
+ static void SendTimeBase();
+
enum State
{
WaitingForTraversalClientConnection,
diff --git a/Source/Core/Core/NetPlayProto.h b/Source/Core/Core/NetPlayProto.h
index 7f17e0aa60..e473c660fa 100644
--- a/Source/Core/Core/NetPlayProto.h
+++ b/Source/Core/Core/NetPlayProto.h
@@ -29,7 +29,7 @@ struct Rpt : public std::vector<u8>
typedef std::vector<u8> NetWiimote;
-#define NETPLAY_VERSION "Dolphin NetPlay 2014-01-08"
+#define NETPLAY_VERSION "Dolphin NetPlay 2015-03-10"
extern u64 g_netplay_initial_gctime;
@@ -53,6 +53,9 @@ enum
NP_MSG_STOP_GAME = 0xA2,
NP_MSG_DISABLE_GAME = 0xA3,
+ NP_MSG_TIMEBASE = 0xB0,
+ NP_MSG_DESYNC_DETECTED = 0xB1,
+
NP_MSG_READY = 0xD0,
NP_MSG_NOT_READY = 0xD1,
diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp
index f53793f3be..d47857e723 100644
--- a/Source/Core/Core/NetPlayServer.cpp
+++ b/Source/Core/Core/NetPlayServer.cpp
@@ -23,6 +23,8 @@
u64 g_netplay_initial_gctime = 1272737767;
+static std::map<u32, std::vector<std::pair<u64, u8>>> s_timebase;
+
NetPlayServer::~NetPlayServer()
{
if (is_connected)
@@ -110,8 +112,7 @@ void NetPlayServer::ThreadFunc()
while (m_do_loop)
{
// update pings every so many seconds
-
- if ((m_ping_timer.GetTimeElapsed() > 1000) || m_update_pings)
+ if (m_update_pings || (m_ping_timer.GetTimeElapsed() > 1000))
{
m_ping_key = Common::Timer::GetTimeMs();
@@ -208,6 +209,7 @@ void NetPlayServer::ThreadFunc()
break;
}
}
+ Common::SleepCurrentThread(1);
}
// close listening socket and client sockets
@@ -581,6 +583,50 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
}
break;
+ case NP_MSG_TIMEBASE:
+ {
+ u32 x, y, frame;
+ packet >> x;
+ packet >> y;
+ packet >> frame;
+ s_timebase[frame].emplace_back(x | ((u64)y >> 32), player.pid);
+
+ if (!std::all_of(s_timebase[frame].begin(), s_timebase[frame].end(), [&frame](std::pair<u64, u8> i){ return i.first == s_timebase[frame][0].first; }))
+ {
+ sf::Packet spac;
+ spac << (MessageId) NP_MSG_DESYNC_DETECTED;
+
+ int pid = -1;
+ if (s_timebase[frame].size() > 2)
+ {
+ for (auto time : s_timebase[frame])
+ {
+ int count = 0;
+ for (auto _time : s_timebase[frame])
+ {
+ if (_time.first == time.first)
+ count++;
+ }
+ if ((size_t)count != s_timebase[frame].size() - 1)
+ {
+ if (pid == -1)
+ {
+ pid = time.second;
+ }
+ else
+ {
+ pid = -1;
+ break;
+ }
+ }
+ }
+ }
+ spac << pid;
+ spac << frame;
+ SendToClients(spac);
+ }
+ }
+ break;
default:
PanicAlertT("Unknown message with id:%d received from player:%d Kicking player!", mid, player.pid);
// unknown message, kick the client
@@ -635,6 +681,7 @@ void NetPlayServer::SetNetSettings(const NetSettings &settings)
// called from ---GUI--- thread
bool NetPlayServer::StartGame()
{
+ s_timebase.clear();
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_current_game = Common::Timer::GetTimeMs();