Skip to content
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

Closed
wants to merge 1 commit into from

Conversation

RachelBryk
Copy link
Member

No description provided.

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.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

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.

@delroth
Copy link
Member

delroth commented Mar 8, 2015

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.

@ghost
Copy link

ghost commented Mar 9, 2015

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?

@RachelBryk
Copy link
Member Author

Nope, tried that before, it is useless.

@ghost
Copy link

ghost commented Mar 9, 2015

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.

@RachelBryk
Copy link
Member Author

idk, but i've tested it, it is not reliable.

@ghost
Copy link

ghost commented Mar 9, 2015

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.

@RachelBryk
Copy link
Member Author

Oh, okay, that seems to work.

@RachelBryk RachelBryk changed the title Hash ram and compare to check for desyncs in netplay. Compare timebase of netplay users to detect desyncs. Mar 10, 2015
@comex
Copy link
Contributor

comex commented Mar 10, 2015

@tueidj But GetFakeTimeBase is just a wrapper around GetTicks..?

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.

@ghost
Copy link

ghost commented Mar 10, 2015

@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.

@phire
Copy link
Member

phire commented Mar 11, 2015

I'm not sure checking the timebase once a frame is the best way to catch desyncs.
Certainly faster than hashing RAM, but I worry that if the de-sync is exactly a multiple of the idle loop execution cycles then you could have a false negative, with one client executing a few extra idle loops.

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.

@ghost
Copy link

ghost commented Mar 11, 2015

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.

@phire
Copy link
Member

phire commented Mar 11, 2015

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.

@RachelBryk
Copy link
Member Author

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.

@RachelBryk RachelBryk force-pushed the netplay-hash branch 2 times, most recently from 7887a5a to f91f333 Compare March 11, 2015 06:50
@RachelBryk
Copy link
Member Author

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.

@RachelBryk
Copy link
Member Author

Rebased due to conflicts.

@RachelBryk
Copy link
Member Author

Anything stopping this from being merged?

@JMC47
Copy link
Contributor

JMC47 commented Mar 29, 2015

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.

@JMC47
Copy link
Contributor

JMC47 commented Apr 22, 2015

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.

@RachelBryk
Copy link
Member Author

As far as I know?

On 2015/04/21, at 23:10, JMC47 notifications@github.com wrote:

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.


Reply to this email directly or view it on GitHub.

@JMC47
Copy link
Contributor

JMC47 commented Apr 22, 2015

I can't get desyncs to trigger yet no matter what I do. I made sure the setting was enabled in my INI.

@RachelBryk
Copy link
Member Author

What settings? Is net play overriding it?

On 2015/04/21, at 23:25, JMC47 notifications@github.com wrote:

I can't get desyncs to trigger yet no matter what I do. I made sure the setting was enabled in my INI.


Reply to this email directly or view it on GitHub.

@JMC47
Copy link
Contributor

JMC47 commented Apr 22, 2015

I used different INIs with different cheats, I manually overrode the CPU clock, I used different save files and nothing produced a message.

@RachelBryk
Copy link
Member Author

Okay I'll look at it when I get home tomorrow

On 2015/04/21, at 23:51, JMC47 notifications@github.com wrote:

I used different INIs with different cheats, I manually overrode the CPU clock, I used different save files and nothing produced a message.


Reply to this email directly or view it on GitHub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
9 participants