Netplay: Ok After more testing it doesnt seem to be the CDROM. so im reveting this change. its weird tho its seems to be fine in the first session created but after when a new session is created it is prone to desync. this doesnt happen when starting the session with an identical savestate for both players tho.
GGPO: Changed the size of the checksums from u16 to u32.
This commit is contained in:
parent
f544a250d3
commit
ffe70067c2
|
@ -196,8 +196,8 @@ typedef struct {
|
||||||
} chat;
|
} chat;
|
||||||
struct {
|
struct {
|
||||||
int nFrameOfDesync;
|
int nFrameOfDesync;
|
||||||
uint16_t ourCheckSum;
|
uint32_t ourCheckSum;
|
||||||
uint16_t remoteChecksum;
|
uint32_t remoteChecksum;
|
||||||
} desync;
|
} desync;
|
||||||
} u;
|
} u;
|
||||||
} GGPOEvent;
|
} GGPOEvent;
|
||||||
|
|
|
@ -431,9 +431,8 @@ Peer2PeerBackend::IncrementFrame(uint16_t checksum1)
|
||||||
{
|
{
|
||||||
auto currentFrame = _sync.GetFrameCount();
|
auto currentFrame = _sync.GetFrameCount();
|
||||||
_sync.IncrementFrame();
|
_sync.IncrementFrame();
|
||||||
checksum1 = _sync.GetLastSavedFrame().checksum;
|
uint32 cSum = _sync.GetLastSavedFrame().checksum;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
uint16_t cSum = checksum1;
|
|
||||||
Log("End of frame (%d)...\n", currentFrame);
|
Log("End of frame (%d)...\n", currentFrame);
|
||||||
static int maxDif = 0;
|
static int maxDif = 0;
|
||||||
if (_pendingCheckSums.count(currentFrame))
|
if (_pendingCheckSums.count(currentFrame))
|
||||||
|
@ -510,7 +509,7 @@ Peer2PeerBackend::PollUdpProtocolEvents(void)
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16 cs)
|
void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint32 cs)
|
||||||
{
|
{
|
||||||
if (framenumber <= _sync.MaxPredictionFrames())
|
if (framenumber <= _sync.MaxPredictionFrames())
|
||||||
return;
|
return;
|
||||||
|
@ -521,7 +520,7 @@ void Peer2PeerBackend::CheckRemoteChecksum(int framenumber, uint16 cs)
|
||||||
|
|
||||||
int Peer2PeerBackend::HowFarBackForChecksums()const
|
int Peer2PeerBackend::HowFarBackForChecksums()const
|
||||||
{
|
{
|
||||||
return 16;
|
return 32;
|
||||||
}/*
|
}/*
|
||||||
uint16 Peer2PeerBackend::GetChecksumForConfirmedFrame(int frameNumber) const
|
uint16 Peer2PeerBackend::GetChecksumForConfirmedFrame(int frameNumber) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,11 +82,11 @@ protected:
|
||||||
int nFrame;
|
int nFrame;
|
||||||
int checkSum;;
|
int checkSum;;
|
||||||
};
|
};
|
||||||
std::map<int, uint16> _pendingCheckSums;
|
std::map<int, uint32> _pendingCheckSums;
|
||||||
std::map<int, uint16> _confirmedCheckSums;
|
std::map<int, uint32> _confirmedCheckSums;
|
||||||
|
|
||||||
// uint16 GetChecksumForConfirmedFrame(int frameNumber) const;
|
// uint16 GetChecksumForConfirmedFrame(int frameNumber) const;
|
||||||
void CheckRemoteChecksum(int framenumber, uint16 cs);
|
void CheckRemoteChecksum(int framenumber, uint32 cs);
|
||||||
int HowFarBackForChecksums()const;
|
int HowFarBackForChecksums()const;
|
||||||
int _confirmedCheckSumFrame = -500;
|
int _confirmedCheckSumFrame = -500;
|
||||||
void CheckDesync();
|
void CheckDesync();
|
||||||
|
|
|
@ -24,7 +24,7 @@ struct GameInput {
|
||||||
int frame;
|
int frame;
|
||||||
int size; /* size in bytes of the entire input for all players */
|
int size; /* size in bytes of the entire input for all players */
|
||||||
char bits[GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS];
|
char bits[GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS];
|
||||||
uint16 checksum;
|
uint32 checksum;
|
||||||
bool is_null() { return frame == NullFrame; }
|
bool is_null() { return frame == NullFrame; }
|
||||||
void init(int frame, char *bits, int size, int offset);
|
void init(int frame, char *bits, int size, int offset);
|
||||||
void init(int frame, char *bits, int size);
|
void init(int frame, char *bits, int size);
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct UdpMsg
|
||||||
int ack_frame:31;
|
int ack_frame:31;
|
||||||
|
|
||||||
uint16 num_bits;
|
uint16 num_bits;
|
||||||
uint16 checksum16;
|
uint32 checksum32;
|
||||||
uint8 input_size; // XXX: shouldn't be in every single packet!
|
uint8 input_size; // XXX: shouldn't be in every single packet!
|
||||||
uint8 bits[MAX_COMPRESSED_BITS]; /* must be last */
|
uint8 bits[MAX_COMPRESSED_BITS]; /* must be last */
|
||||||
} input;
|
} input;
|
||||||
|
|
|
@ -134,7 +134,7 @@ UdpProtocol::SendPendingOutput()
|
||||||
ASSERT(last.frame == -1 || last.frame + 1 == msg->u.input.start_frame);
|
ASSERT(last.frame == -1 || last.frame + 1 == msg->u.input.start_frame);
|
||||||
for (j = 0; j < _pending_output.size(); j++) {
|
for (j = 0; j < _pending_output.size(); j++) {
|
||||||
GameInput ¤t = _pending_output.item(j);
|
GameInput ¤t = _pending_output.item(j);
|
||||||
msg->u.input.checksum16 = current.checksum;
|
msg->u.input.checksum32 = current.checksum;
|
||||||
if (memcmp(current.bits, last.bits, current.size) != 0) {
|
if (memcmp(current.bits, last.bits, current.size) != 0) {
|
||||||
ASSERT((GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS * 8) < (1 << BITVECTOR_NIBBLE_SIZE));
|
ASSERT((GAMEINPUT_MAX_BYTES * GAMEINPUT_MAX_PLAYERS * 8) < (1 << BITVECTOR_NIBBLE_SIZE));
|
||||||
for (i = 0; i < current.size * 8; i++) {
|
for (i = 0; i < current.size * 8; i++) {
|
||||||
|
@ -627,7 +627,7 @@ UdpProtocol::OnInput(UdpMsg *msg, int len)
|
||||||
char desc[1024];
|
char desc[1024];
|
||||||
ASSERT(currentFrame == _last_received_input.frame + 1);
|
ASSERT(currentFrame == _last_received_input.frame + 1);
|
||||||
_last_received_input.frame = currentFrame;
|
_last_received_input.frame = currentFrame;
|
||||||
_last_received_input.checksum = msg->u.input.checksum16;
|
_last_received_input.checksum = msg->u.input.checksum32;
|
||||||
/*
|
/*
|
||||||
* Send the event to the emualtor
|
* Send the event to the emualtor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -94,8 +94,8 @@ public:
|
||||||
void ApplyToEvents(std::function<void(UdpProtocol::Event&)> cb);
|
void ApplyToEvents(std::function<void(UdpProtocol::Event&)> cb);
|
||||||
void StartPollLoop();
|
void StartPollLoop();
|
||||||
void EndPollLoop();
|
void EndPollLoop();
|
||||||
std::map<int, uint16> _remoteCheckSums;
|
std::map<int, uint32> _remoteCheckSums;
|
||||||
std::map<int, uint16> _remoteCheckSumsThisFrame;
|
std::map<int, uint32> _remoteCheckSumsThisFrame;
|
||||||
protected:
|
protected:
|
||||||
enum State {
|
enum State {
|
||||||
Syncing,
|
Syncing,
|
||||||
|
|
|
@ -112,7 +112,7 @@ s32 Netplay::Start(s32 lhandle, u16 lport, std::string& raddr, u16 rport, s32 ld
|
||||||
ggpo_start_session(&s_ggpo, &cb, "Duckstation-Netplay", 2, sizeof(Netplay::Input), lport, MAX_ROLLBACK_FRAMES);
|
ggpo_start_session(&s_ggpo, &cb, "Duckstation-Netplay", 2, sizeof(Netplay::Input), lport, MAX_ROLLBACK_FRAMES);
|
||||||
// result = ggpo_start_synctest(&s_ggpo, &cb, (char*)"asdf", 2, sizeof(Netplay::Input), 1);
|
// result = ggpo_start_synctest(&s_ggpo, &cb, (char*)"asdf", 2, sizeof(Netplay::Input), 1);
|
||||||
|
|
||||||
ggpo_set_disconnect_timeout(s_ggpo, 3000);
|
ggpo_set_disconnect_timeout(s_ggpo, 2000);
|
||||||
ggpo_set_disconnect_notify_start(s_ggpo, 1000);
|
ggpo_set_disconnect_notify_start(s_ggpo, 1000);
|
||||||
|
|
||||||
for (int i = 1; i <= 2; i++)
|
for (int i = 1; i <= 2; i++)
|
||||||
|
@ -184,10 +184,6 @@ void Netplay::SetSettings()
|
||||||
// no block linking, it degrades savestate loading performance
|
// no block linking, it degrades savestate loading performance
|
||||||
si.SetBoolValue("CPU", "RecompilerBlockLinking", false);
|
si.SetBoolValue("CPU", "RecompilerBlockLinking", false);
|
||||||
|
|
||||||
// for some games CDROM async readahead seems to cause desyncs (most notable during testing were the tekken games)
|
|
||||||
// so for now disabling it seems like the only option
|
|
||||||
si.SetIntValue("CDROM", "ReadaheadSectors", 0);
|
|
||||||
|
|
||||||
Host::Internal::SetNetplaySettingsLayer(&si);
|
Host::Internal::SetNetplaySettingsLayer(&si);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +211,7 @@ void Netplay::HandleTimeSyncEvent(float frame_delta, int update_interval)
|
||||||
// Distribute the frame difference over the next N * 0.75 frames.
|
// Distribute the frame difference over the next N * 0.75 frames.
|
||||||
// only part of the interval time is used since we want to come back to normal speed.
|
// only part of the interval time is used since we want to come back to normal speed.
|
||||||
// otherwise we will keep spiraling into unplayable gameplay.
|
// otherwise we will keep spiraling into unplayable gameplay.
|
||||||
float total_time = (frame_delta * s_frame_period) / 8;
|
float total_time = (frame_delta * s_frame_period) / 4;
|
||||||
float mun_timesync_frames = update_interval * 0.75f;
|
float mun_timesync_frames = update_interval * 0.75f;
|
||||||
float added_time_per_frame = -(total_time / mun_timesync_frames);
|
float added_time_per_frame = -(total_time / mun_timesync_frames);
|
||||||
float iterations_per_frame = 1.0f / s_frame_period;
|
float iterations_per_frame = 1.0f / s_frame_period;
|
||||||
|
@ -279,7 +275,7 @@ void Netplay::GenerateChecksumForFrame(int* checksum, int frame, unsigned char*
|
||||||
const u32 num_group_of_pages = buffer_size / sliding_window_size;
|
const u32 num_group_of_pages = buffer_size / sliding_window_size;
|
||||||
const u32 start_position = (frame % num_group_of_pages) * sliding_window_size;
|
const u32 start_position = (frame % num_group_of_pages) * sliding_window_size;
|
||||||
*checksum = XXH32(buffer + start_position, sliding_window_size, frame);
|
*checksum = XXH32(buffer + start_position, sliding_window_size, frame);
|
||||||
// Log_InfoPrintf("check: f:%d c:%u", frame, *checksum);
|
Log_VerbosePrintf("Netplay Checksum: f:%d wf:%d c:%u", frame, frame % num_group_of_pages, *checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Netplay::AdvanceFrame(u16 checksum)
|
void Netplay::AdvanceFrame(u16 checksum)
|
||||||
|
@ -332,7 +328,7 @@ Netplay::Input Netplay::ReadLocalInput()
|
||||||
Netplay::Input inp{0};
|
Netplay::Input inp{0};
|
||||||
for (u32 i = 0; i < (u32)DigitalController::Button::Count; i++)
|
for (u32 i = 0; i < (u32)DigitalController::Button::Count; i++)
|
||||||
{
|
{
|
||||||
if (s_net_input[0][i] >= 0.4f)
|
if (s_net_input[0][i] >= 0.25f)
|
||||||
inp.button_data |= 1 << i;
|
inp.button_data |= 1 << i;
|
||||||
}
|
}
|
||||||
return inp;
|
return inp;
|
||||||
|
@ -432,7 +428,7 @@ bool Netplay::NpBeginGameCb(void* ctx, const char* game_name)
|
||||||
System::ShutdownSystem(false);
|
System::ShutdownSystem(false);
|
||||||
// fast boot the selected game and wait for the other player
|
// fast boot the selected game and wait for the other player
|
||||||
auto param = SystemBootParameters(s_game_path);
|
auto param = SystemBootParameters(s_game_path);
|
||||||
param.override_fast_boot = true;
|
// param.save_state = EmuFolders::SaveStates + "/SLUS-00402_2.sav";
|
||||||
if (!System::BootSystem(param))
|
if (!System::BootSystem(param))
|
||||||
{
|
{
|
||||||
StopNetplaySession();
|
StopNetplaySession();
|
||||||
|
|
Loading…
Reference in New Issue