Some updates to netplay, now using UDP to transmit pad data, it shouldn't be slow as molasses anymore, but may be unrealiable. Netplay now saves settings to ini, also fixed possible desync.

+cookie update : Updated Dolphin's icon to be Win7 ready by making it 32x32, so it now shows fine when alt-tabbing :p

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3290 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
sl1nk3.s
2009-05-27 21:24:29 +00:00
parent 9fd0802b4f
commit 0259cc388e
7 changed files with 1011 additions and 461 deletions

View File

@ -23,13 +23,11 @@ NetPlay *NetClass_ptr = NULL;
void NetPlay::IsGameFound(unsigned char * ptr, std::string m_selected)
{
m_critical.Enter();
m_selectedGame = m_selected;
if (m_games.find(m_selected) != std::string::npos)
{
*ptr = 0x1F;
}
else
*ptr = 0x1A;
@ -68,6 +66,7 @@ void NetPlay::OnNetEvent(wxCommandEvent& event)
// has been killed and so we tell the GUI thread.
AppendText(_("*Connection to Host lost.\n*You have been Disconnected.\n\n"));
m_isHosting = 2;
m_numClients--;
}
break;
case HOST_PLAYERLEFT:
@ -84,7 +83,9 @@ void NetPlay::OnNetEvent(wxCommandEvent& event)
case CLIENTS_READY:
{
m_clients_ready = true;
if (m_ready || event.GetInt())
// Tell clients everyone is ready...
if (m_ready)
LoadGame();
}
break;
@ -135,25 +136,38 @@ void NetPlay::LoadGame()
// and always sends to the server which then send it back to all the clients
// -> P2P model is faster, but is limited to 2 players
// -> Server model is slower, but supports up to 4 players
m_Logging->AppendText(_("** Everyone is ready... Loading Game ! **\n"));
// Tell clients everyone is ready...
if (m_isHosting == 1)
{
long ping[3] = {0};
unsigned char value = 0x50;
// Get ping
m_sock_server->Write(0, 0, 0, ping);
float fping = (ping[0]+ping[1]+ping[2])/(float)m_numClients;
// Tell client everyone is ready
for (int i=0; i < m_numClients ; i++)
m_sock_server->Write(i, (const char*)&value, 1);
// Sleep a bit to start the game at more or less the same time than the peer
wxMilliSleep(fping/2);
m_Logging->AppendText(wxString::Format(wxT("** Everyone is ready... Loading Game ! **\n"
"** Ping to client(s) is : %f ms\n"), fping));
}
else
m_Logging->AppendText(_("** Everyone is ready... Loading Game ! **\n"));
// TODO : Throttle should be on by default, to avoid stuttering
//soundStream->GetMixer()->SetThrottle(true);
int line_p = 0;
int line_n = 0;
m_critical.Enter();
std::string tmp = m_games.substr(0, m_games.find(m_selectedGame));
for (int i=0; i < (int)tmp.size(); i++)
if (tmp.c_str()[i] == '\n')
line_n++;
@ -162,6 +176,7 @@ void NetPlay::LoadGame()
NetClass_ptr = this;
m_timer.Start();
m_data_received = false;
m_critical.Leave();
// Find corresponding game path
for (int i=0; i < (int)m_paths.size(); i++)
@ -182,6 +197,15 @@ void NetPlay::LoadGame()
bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues)
{
if (m_numClients < 1)
{
m_Logging->AppendText(_("** WARNING : "
"Ping too high (>2000ms) or connection lost ! \n"
"** WARNING : Stopping Netplay... \n"));
NetClass_ptr = NULL;
return false;
}
// Store current pad status in netValues[]
netValues[0] = (u32)((u8)PadStatus.stickY);
netValues[0] |= (u32)((u8)PadStatus.stickX << 8);
@ -192,34 +216,37 @@ bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues)
netValues[1] |= (u32)((u8)PadStatus.substickY << 16);
netValues[1] |= (u32)((u8)PadStatus.substickX << 24);
if (m_frame == 0)
{
// We make sure everyone's pad is enabled
for (int i = 0; i < m_numClients+1; i++)
SerialInterface::ChangeDevice(SI_GC_CONTROLLER, i);
// Better disable unused ports
for (int i = m_numClients+1; i < 4; i++)
SerialInterface::ChangeDevice(SI_DUMMY, i);
}
if (m_NetModel == 0 && m_numClients == 1) // Use P2P Model
if (m_NetModel == 0) // Use 2 players Model
{
if (padnb == 0)
{
// TODO : actually show this on the GUI :p
// Update the timer and increment total frame number
m_frame++;
m_timer.Update();
if (m_frame == 1)
{
// We make sure everyone's pad is enabled
for (int i = 0; i < m_numClients+1; i++)
SerialInterface::ChangeDevice(SI_GC_CONTROLLER, i);
// Better disable unused ports
for (int i = m_numClients+1; i < 4; i++)
SerialInterface::ChangeDevice(SI_DUMMY, i);
}
if (m_timer.GetTimeDifference() > 1000)
m_timer.Update();
#ifdef NET_DEBUG
char sent[64];
sprintf(sent, "Sent Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]);
m_Logging->AppendText(wxString::FromAscii(sent));
#endif
unsigned char init_value = 0xA1;
unsigned char player = 0;
#ifdef USE_TCP
unsigned char init_value = 0xA1;
if (m_isHosting == 1) {
// Send pads values
m_sock_server->Write(0, (const char*)&init_value, 1);
@ -231,6 +258,23 @@ bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues)
m_sock_client->Write((const char*)netValues, 8);
player = 1;
}
#else // UDP
u32 padsValues[3];
padsValues[0] = m_frame;
padsValues[1] = netValues[0];
padsValues[2] = netValues[1];
if (m_isHosting == 1) {
// Send pads values
m_sock_server->WriteUDP(0, (const char*)padsValues, 12);
}
else {
// Send pads values
m_sock_client->WriteUDP((const char*)padsValues, 12);
player = 1;
}
#endif
if (!m_data_received)
{
@ -257,9 +301,10 @@ bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues)
else {
if (m_loopframe > 126)
{
m_Logging->AppendText(_("** Ping too high (>2000ms) or connection lost ! \n"));
m_Logging->AppendText(_("** Stopping game... \n"));
BootManager::Stop();
m_Logging->AppendText(_("** WARNING : "
"Ping too high (>2000ms) or connection lost ! \n"
"** WARNING : Stopping Netplay... \n"));
NetClass_ptr = NULL;
}
m_loopframe++;
@ -367,7 +412,6 @@ void NetPlay::ChangeSelectedGame(std::string game)
m_sock_server->Write(i, (const char*)&value, 1); // 0x35 -> Change game
m_sock_server->Write(i, (const char*)&game_size, 4);
//m_sock_server->Write(i, m_selectedGame.c_str(), game_size + 1);
m_sock_server->Write(i, game.c_str(), game_size + 1);
}
@ -379,20 +423,19 @@ void NetPlay::ChangeSelectedGame(std::string game)
void NetPlay::OnQuit(wxCloseEvent& WXUNUSED(event))
{
// Disable netplay
NetClass_ptr = NULL;
// We Kill the threads
// Destroy the Window
Destroy();
// Then Kill the threads
if (m_isHosting == 0)
m_sock_client->Delete();
else if (m_isHosting == 1) {
m_sock_server->Delete();
// Stop listening, we're doing it here cause Doing it in the thread
// Cause SFML to crash when built in release build, odd ? :(
m_listensocket.Close();
}
// Destroy the Frame
Destroy();
}
void NetPlay::OnDisconnect(wxCommandEvent& WXUNUSED(event))
@ -403,7 +446,7 @@ void NetPlay::OnDisconnect(wxCommandEvent& WXUNUSED(event))
bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus)
{
// TODO : adapt it to more than 2 players
#ifdef USE_TCP
if (current)
{
while (1)
@ -419,6 +462,9 @@ bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus)
break;
}
m_CriticalSection.Leave();
if (TestDestroy())
break;
}
return true;
@ -427,10 +473,54 @@ bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus)
wxCriticalSectionLocker lock(m_CriticalSection);
return m_data_received;
#else
size_t recv_size;
if (current)
{
m_CriticalSection.Enter();
if (isVersus)
{
if (m_netvalues[0][1] != 0)
{
netValues[0] = m_netvalues[0][1];
netValues[1] = m_netvalues[0][2];
}
else
{
while (true)
{
u32 frame_saved = m_netvalues[0][0];
bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 5);
if (m_netvalues[0][0] < frame_saved+1)
continue;
if (m_netvalues[0][0] > frame_saved+1 || !pass)
PanicAlert("Network ERROR !");
netValues[0] = m_netvalues[0][1];
netValues[1] = m_netvalues[0][2];
break;
}
}
}
m_netvalues[0][1] = 0;
m_CriticalSection.Leave();
return true;
}
else
return RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 1/1000);
#endif
}
bool ServerSide::isNewPadData(u32 *netValues, bool current, char client)
{
#ifdef USE_TCP
if (current)
{
while (1)
@ -446,6 +536,9 @@ bool ServerSide::isNewPadData(u32 *netValues, bool current, char client)
break;
}
m_CriticalSection.Leave();
if (TestDestroy())
break;
}
return true;
@ -454,5 +547,44 @@ bool ServerSide::isNewPadData(u32 *netValues, bool current, char client)
wxCriticalSectionLocker lock(m_CriticalSection);
return m_data_received;
#else
size_t recv_size;
if (current)
{
m_CriticalSection.Enter();
if (m_netvalues[0][1] != 0)
{
netValues[0] = m_netvalues[client][1];
netValues[1] = m_netvalues[client][2];
}
else
{
while (true)
{
u32 frame_saved = m_netvalues[client][0];
bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 5);
if (m_netvalues[client][0] < frame_saved+1)
continue;
if (m_netvalues[client][0] > frame_saved+1 || !pass)
PanicAlert("Network ERROR !");
netValues[0] = m_netvalues[client][1];
netValues[1] = m_netvalues[client][2];
break;
}
}
m_netvalues[client][1] = 0;
m_CriticalSection.Leave();
return true;
}
else
return RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 1/1000);
#endif
}