-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compare timebase of netplay users to detect desyncs. #2178
Conversation
if (isPlayer) | ||
{ | ||
bool bWii = SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; | ||
u64 hash = XXH64(Memory::GetPointer(bWii ? 0x90000000 : 0x80000000), bWii ? 0x4000000 : 0x2000000, 0); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
int pid = -1; | ||
if (s_hashes[frame].size() > 2) | ||
{ | ||
for (int i = 0; i < s_hashes[frame].size(); ++i) |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
Aka. killing caches for sadness and negative profit. |
hash.first = x | ((u64)y >> 32); | ||
hash.second = player.pid; | ||
|
||
s_hashes[frame].push_back(hash); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This idea seems really excessive. Can't you just compare timebases of the machines when swapping input, since practically any divergence in the code being executed will change the number of instructions having been run? |
Nope, tried that before, it is useless. |
Care to explain why? It seems a bit strange that two machines executing different code paths would have the exact same instruction count at consecutive intervals. |
idk, but i've tested it, it is not reliable. |
Sounds like your testing was unreliable if you can't explain the results. The timebase I'm referring to is what SystemTimers::GetFakeTimeBase() returns, which is the same as the CPU's timebase registers. Not CoreTiming::GetTicks() and certainly not CEXIIPL::GetGCTime(). You're testing for differences in RAM (in a really slow and ugly way, see Delroth's comment): those differences can't just spontaneously happen (except for maybe differences in the ISO, but that definitely should not be solved in this way), there has to be instructions being executed on one machine and not the other that causes them. |
Oh, okay, that seems to work. |
e4e7fa2
to
7f37e72
Compare
7f37e72
to
3ff5faa
Compare
@tueidj But |
int pid = -1; | ||
if (s_timebase[frame].size() > 2) | ||
{ | ||
for (auto hash : s_timebase[frame]) |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
@comex Not just a wrapper, it's GetTicks + an offset that can be modified by emulated code. Although it's unlikely for any game to modify the timebase registers, there's no reason to pretend it couldn't happen. |
@@ -584,6 +586,51 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) | |||
} | |||
break; | |||
|
|||
case NP_MSG_TIMEBASE: | |||
{ | |||
u32 x,y, frame; |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
3ff5faa
to
2a343ce
Compare
I'm not sure checking the timebase once a frame is the best way to catch desyncs. With the standard 3 instruction idle loop (which I think dolphin executes in 3 cycles), that's a 33% chance of a false negative. Perhaps you should stop the cpu thread 10 to 100 times a frame and check if the program counters match, maybe hashing the other registers too. |
If the clients are only desynced by a couple of idle loops is it really going to be a problem if it's not detected? There would likely have to be a greater divergence in execution paths before problems started to manifest, which would cause more significant differences in the timebases. |
It's modulus. One client could be executing 3, 300, 3000 or 3 million extra cycles, as long as it's a modulus of the length of the idle loop. It might be a non-issue, probability is that you will detect the desync within 3 frames. |
Yeah, i do not think it is an issue, it should still always detect desyncs long before the players notice. Testing it by changing settings always caught it instantly. |
7887a5a
to
f91f333
Compare
If there's no more issues, i think this should be good to merge. |
@@ -514,7 +533,7 @@ void NetPlayClient::ThreadFunc() | |||
break; | |||
} | |||
} | |||
|
|||
Common::SleepCurrentThread(1); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
f91f333
to
48a5991
Compare
Rebased due to conflicts. |
Anything stopping this from being merged? |
The only thing I can think of is if it works for everything now. I know it doesn't work on Dualcore at all with this method (instant desync) but single core should work without a performance down afaict so far. |
Is this working? I tried testing the latest build of it, but even when I have obviously wrong settings, it still doesn't trigger. Ping and whatnot. |
As far as I know?
|
I can't get desyncs to trigger yet no matter what I do. I made sure the setting was enabled in my INI. |
What settings? Is net play overriding it?
|
I used different INIs with different cheats, I manually overrode the CPU clock, I used different save files and nothing produced a message. |
Okay I'll look at it when I get home tomorrow
|
No description provided.