From ec11685a664dd3f34720f0c0ad589e92a652cc5f Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 5 May 2010 04:31:21 +0000 Subject: [PATCH] NetPlay: Allow manual adjustments to the pad buffer size. Hacked in all the functions that will be needed for wiimote support (not functional yet). Rumble is sent to the correct gamepad during netplay. Stop button works better. Games no longer hang on disconnect. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5434 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp | 2 +- Source/Core/Core/Src/HW/EXI_DeviceIPL.h | 2 +- .../Core/Src/HW/SI_DeviceGCController.cpp | 11 +- .../Core/Core/Src/HW/SI_DeviceGCController.h | 3 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 1 + .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h | 2 + .../Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp | 11 +- .../Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h | 3 + Source/Core/DolphinWX/DolphinWX.vcproj | 8 + Source/Core/DolphinWX/Src/NetPlay.cpp | 1011 ++++------------- Source/Core/DolphinWX/Src/NetPlay.h | 101 +- Source/Core/DolphinWX/Src/NetWindow.cpp | 45 +- Source/Core/DolphinWX/Src/NetWindow.h | 3 + Source/Core/DolphinWX/Src/SConscript | 2 + Source/UnitTests/UnitTests.cpp | 5 - 15 files changed, 380 insertions(+), 830 deletions(-) diff --git a/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp b/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp index 7ba24d00ce..c996b60b20 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceIPL.cpp @@ -417,7 +417,7 @@ u32 CEXIIPL::GetGCTime() #else // hack in some netplay stuff - u64 ltime = GetNetGCTime(); + u64 ltime = NetPlay_GetGCTime(); if (0 == ltime) ltime = Common::Timer::GetLocalTimeSinceJan1970(); diff --git a/Source/Core/Core/Src/HW/EXI_DeviceIPL.h b/Source/Core/Core/Src/HW/EXI_DeviceIPL.h index b2e3dcc54f..77b26cade0 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceIPL.h +++ b/Source/Core/Core/Src/HW/EXI_DeviceIPL.h @@ -32,7 +32,7 @@ public: void DoState(PointerWrap &p); static u32 GetGCTime(); - static u32 GetNetGCTime(); + static u32 NetPlay_GetGCTime(); static void Descrambler(u8* data, u32 size); diff --git a/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp index 9020943953..a0df5813d0 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp +++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp @@ -134,7 +134,7 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) u32 netValues[2] = {0}; int NetPlay = 2; #if defined(HAVE_WX) && HAVE_WX - NetPlay = GetNetInput(ISIDevice::m_iDeviceNumber, PadStatus, netValues); + NetPlay = NetPlay_GetInput(ISIDevice::m_iDeviceNumber, PadStatus, netValues); #endif if (NetPlay != 2) @@ -271,8 +271,13 @@ void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll) { unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard unsigned int uStrength = command.Parameter2; - if (pad->PAD_Rumble) - pad->PAD_Rumble(ISIDevice::m_iDeviceNumber, uType, uStrength); + + // get the correct pad number that should rumble locally when using netplay + const u8 numPAD = NetPlay_GetPadNum(ISIDevice::m_iDeviceNumber); + + if (numPAD < 4) + if (pad->PAD_Rumble) + pad->PAD_Rumble(numPAD, uType, uStrength); if (!_Poll) { diff --git a/Source/Core/Core/Src/HW/SI_DeviceGCController.h b/Source/Core/Core/Src/HW/SI_DeviceGCController.h index 61c40fec44..8a8dd0efb7 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGCController.h +++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.h @@ -102,7 +102,8 @@ public: virtual int RunBuffer(u8* _pBuffer, int _iLength); // Send and Receive pad input from network - static int GetNetInput(u8 numPAD, SPADStatus, u32 *PADStatus); + static int NetPlay_GetInput(u8 numPAD, SPADStatus, u32 *PADStatus); + static u8 NetPlay_GetPadNum(u8 numPAD); // Return true on new data virtual bool GetData(u32& _Hi, u32& _Low); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index fada6ed971..5f29557ce1 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -494,6 +494,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() { if (m_WiiMotes[i].IsConnected() == 3 && m_FreqDividerMote == 150 / (i + 1)) { + NetPlay_WiimoteUpdate(i); CPluginManager::GetInstance().GetWiimote(0)->Wiimote_Update(i); return true; } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h index eb7f51e718..1cc46217c4 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h @@ -95,6 +95,8 @@ public: void DoState(PointerWrap &p); + void NetPlay_WiimoteUpdate(int _number); + private: enum diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp index 39aef08d98..01d641c96b 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp @@ -258,6 +258,8 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size) _dbg_assert_msg_(WII_IPC_WIIMOTE, DoesChannelExist(pHeader->CID), "L2CAP: SendACLPacket to unknown channel %i", pHeader->CID); CChannelMap::iterator itr= m_Channel.find(pHeader->CID); + const int number = NetPlay_GetWiimoteNum(m_ConnectionHandle & 0xFF); + Common::PluginWiimote* mote = CPluginManager::GetInstance().GetWiimote(0); if (itr != m_Channel.end()) { @@ -269,11 +271,13 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size) break; case HID_CONTROL_CHANNEL: - mote->Wiimote_ControlChannel(m_ConnectionHandle & 0xFF, pHeader->CID, pData, DataSize); + if (number < 4) + mote->Wiimote_ControlChannel(number, pHeader->CID, pData, DataSize); break; case HID_INTERRUPT_CHANNEL: - mote->Wiimote_InterruptChannel(m_ConnectionHandle & 0xFF, pHeader->CID, pData, DataSize); + if (number < 4) + mote->Wiimote_InterruptChannel(number, pHeader->CID, pData, DataSize); break; default: @@ -854,6 +858,9 @@ void CWII_IPC_HLE_WiiMote::SendCommandToACL(u8 _Ident, u8 _Code, u8 _CommandLeng // --------------------------------------------------- void CWII_IPC_HLE_WiiMote::ReceiveL2capData(u16 scid, const void* _pData, u32 _Size) { + if (NetPlay_WiimoteInput(m_ConnectionHandle & 0xFF, scid, _pData, _Size)) + return; + // Allocate DataFrame u8 DataFrame[1024]; u32 Offset = 0; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h index 7edba78858..fef983a961 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h @@ -170,6 +170,9 @@ public: void ExecuteL2capCmd(u8* _pData, u32 _Size); // From CPU void ReceiveL2capData(u16 scid, const void* _pData, u32 _Size); // From wiimote + int NetPlay_GetWiimoteNum(int _number); + bool NetPlay_WiimoteInput(int _number, u16 _channelID, const void* _pData, u32& _Size); + void EventConnectionAccepted(); void EventDisconnect(); bool EventPagingChanged(u8 _pageMode); diff --git a/Source/Core/DolphinWX/DolphinWX.vcproj b/Source/Core/DolphinWX/DolphinWX.vcproj index a8568318aa..d8ebfe24d5 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcproj +++ b/Source/Core/DolphinWX/DolphinWX.vcproj @@ -934,6 +934,14 @@ RelativePath=".\Src\NetPlay.h" > + + + + diff --git a/Source/Core/DolphinWX/Src/NetPlay.cpp b/Source/Core/DolphinWX/Src/NetPlay.cpp index 74ba25b267..e6700e2e4a 100644 --- a/Source/Core/DolphinWX/Src/NetPlay.cpp +++ b/Source/Core/DolphinWX/Src/NetPlay.cpp @@ -15,29 +15,27 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "HW/SI_DeviceGCController.h" -#include "HW/EXI_DeviceIPL.h" - #include "NetPlay.h" #include "NetWindow.h" +// for wiimote +#include "IPC_HLE/WII_IPC_HLE_Device_usb.h" +#include "IPC_HLE/WII_IPC_HLE_WiiMote.h" +// for gcpad +#include "HW/SI_DeviceGCController.h" +// for gctime +#include "HW/EXI_DeviceIPL.h" +// to start/stop game #include "Frame.h" +// for OSD msgs +#include "Core.h" -#include - -// this will be removed soon -#define TEMP_FIXED_BUFFER 20 - -enum -{ - CON_ERR_SERVER_FULL = 1, - CON_ERR_GAME_RUNNING, - CON_ERR_VERSION_MISMATCH -}; - -NetPlay* NetClass_ptr = NULL; +Common::CriticalSection crit_netplay_ptr; +static NetPlay* netplay_ptr = NULL; extern CFrame* main_frame; +#define RPT_SIZE_HACK (1 << 16) + DEFINE_EVENT_TYPE(wxEVT_THREAD) THREAD_RETURN NetPlayThreadFunc(void* arg) @@ -46,29 +44,42 @@ THREAD_RETURN NetPlayThreadFunc(void* arg) return 0; } +//CritLocker::CritLocker(Common::CriticalSection& crit) +// : m_crit(crit) +//{ +// m_crit.Enter(); +//} +// +//CritLocker::~CritLocker() +//{ +// m_crit.Leave(); +//} + +// called from ---GUI--- thread +NetPlay::NetPlay() + : m_is_running(false), m_do_loop(true) +{ + m_target_buffer_size = 20; + ClearBuffers(); +} + +void NetPlay_Enable(NetPlay* const np) +{ + CritLocker crit(::crit_netplay_ptr); // probably safe without a lock + ::netplay_ptr = np; +} + +void NetPlay_Disable() +{ + CritLocker crit(::crit_netplay_ptr); + ::netplay_ptr = NULL; +} + +// called from ---GUI--- thread NetPlay::~NetPlay() { - ::NetClass_ptr = NULL; -} - -NetPlayServer::~NetPlayServer() -{ - if (is_connected) - { - m_do_loop = false; - m_thread->WaitForDeath(); - delete m_thread; - } -} - -NetPlayClient::~NetPlayClient() -{ - if (is_connected) - { - m_do_loop = false; - m_thread->WaitForDeath(); - delete m_thread; - } + CritLocker crit(crit_netplay_ptr); + ::netplay_ptr = NULL; } NetPlay::Player::Player() @@ -76,322 +87,7 @@ NetPlay::Player::Player() memset(pad_map, -1, sizeof(pad_map)); } -NetPlayServer::NetPlayServer(const u16 port, const std::string& name, NetPlayDiag* const npd, const std::string& game) -{ - m_dialog = npd; - m_selected_game = game; - - if (m_socket.Listen(port)) - { - Client player; - player.pid = 0; - player.revision = NETPLAY_DOLPHIN_VER; - player.socket = m_socket; - player.name = name; - - // map local pad 1 to game pad 1 - player.pad_map[0] = 0; - - // add self to player list - m_players[m_socket] = player; - //PanicAlert("Listening"); - - UpdateGUI(); - - is_connected = true; - - m_selector.Add(m_socket); - m_thread = new Common::Thread(NetPlayThreadFunc, this); - } - else - is_connected = false; -} - -NetPlayClient::NetPlayClient(const std::string& address, const u16 port, const std::string& name, NetPlayDiag* const npd) -{ - m_dialog = npd; - is_connected = false; - - // why is false successful? documentation says true is - if (0 == m_socket.Connect(port, address)) - { - // send connect message - sf::Packet spac; - spac << NETPLAY_VERSION; - spac << NETPLAY_DOLPHIN_VER; - spac << name; - m_socket.Send(spac); - - sf::Packet rpac; - // TODO: make this not hang - m_socket.Receive(rpac); - MessageId error; - rpac >> error; - - // got error message - if (error) - { - switch (error) - { - case CON_ERR_SERVER_FULL : - PanicAlert("The server is full!"); - break; - case CON_ERR_VERSION_MISMATCH : - PanicAlert("The server and client's NetPlay versions are incompatible!"); - break; - case CON_ERR_GAME_RUNNING : - PanicAlert("The server responded: the game is currently running!"); - break; - default : - PanicAlert("The server sent an unknown error message!"); - break; - } - m_socket.Close(); - } - else - { - rpac >> m_pid; - - Player player; - player.name = name; - player.pid = m_pid; - player.revision = NETPLAY_DOLPHIN_VER; - - // add self to player list - m_players[m_pid] = player; - - UpdateGUI(); - - //PanicAlert("Connection successful: assigned player id: %d", m_pid); - is_connected = true; - - m_selector.Add(m_socket); - m_thread = new Common::Thread(NetPlayThreadFunc, this); - } - } - else - PanicAlert("Failed to Connect!"); - -} - -void NetPlayServer::Entry() -{ - while (m_do_loop) - { - const unsigned int num = m_selector.Wait(0.01f); - - for (unsigned int i=0; i::reverse_iterator - i = m_players.rbegin(), - e = m_players.rend(); - for ( ; i!=e; ++i) - i->second.socket.Close(); - } - - return; -} - -unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) -{ - sf::Packet rpac; - // TODO: make this not hang / check if good packet - socket.Receive(rpac); - - std::string npver; - rpac >> npver; - // dolphin netplay version - if (npver != NETPLAY_VERSION) - return CON_ERR_VERSION_MISMATCH; - - // game is currently running - if (m_is_running) - return CON_ERR_GAME_RUNNING; - - // too many players - if (m_players.size() >= 255) - return CON_ERR_SERVER_FULL; - - Client player; - player.socket = socket; - rpac >> player.revision; - rpac >> player.name; - - // give new client first available id - player.pid = 0; - std::map::const_iterator - i, - e = m_players.end(); - for (PlayerId p = 1; 0 == player.pid; ++p) - { - for (i = m_players.begin(); ; ++i) - { - if (e == i) - { - player.pid = p; - break; - } - if (p == i->second.pid) - break; - } - } - - // TODO: this is crappy - // try to automatically assign new user a pad - { - bool is_mapped[4] = {false,false,false,false}; - - for ( unsigned int m = 0; m<4; ++m) - { - for (i = m_players.begin(); i!=e; ++i) - { - if (i->second.pad_map[m] >= 0) - is_mapped[(unsigned)i->second.pad_map[m]] = true; - } - } - - for ( unsigned int m = 0; m<4; ++m) - if (false == is_mapped[m]) - { - player.pad_map[0] = m; - break; - } - - } - - // ENTER - m_crit.send.Enter(); - - // send join message to already connected clients - sf::Packet spac; - spac << (MessageId)NP_MSG_PLAYER_JOIN; - spac << player.pid << player.name << player.revision; - SendToClients(spac); - - // send new client success message with their id - spac.Clear(); - spac << (MessageId)0; - spac << player.pid; - socket.Send(spac); - - // send user their pad mapping - spac.Clear(); - spac << (MessageId)NP_MSG_PAD_MAPPING; - spac << player.pid; - for (unsigned int pm = 0; pm<4; ++pm) - spac << player.pad_map[pm]; - socket.Send(spac); - - // send new client the selected game - spac.Clear(); - spac << (MessageId)NP_MSG_CHANGE_GAME; - spac << m_selected_game; - socket.Send(spac); - - // sync values with new client - for (i = m_players.begin(); i!=e; ++i) - { - spac.Clear(); - spac << (MessageId)NP_MSG_PLAYER_JOIN; - spac << i->second.pid << i->second.name << i->second.revision; - socket.Send(spac); - - spac.Clear(); - spac << (MessageId)NP_MSG_PAD_MAPPING; - spac << i->second.pid; - for (unsigned int pm = 0; pm<4; ++pm) - spac << i->second.pad_map[pm]; - socket.Send(spac); - } - - // LEAVE - m_crit.send.Leave(); - - // add client to the player list - m_crit.players.Enter(); - m_players[socket] = player; - m_crit.players.Leave(); - - // add client to selector/ used for receiving - m_selector.Add(socket); - - UpdateGUI(); - - return 0; -} - -unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket) -{ - if (m_is_running) - PanicAlert("Disconnect while game is running. Game will likely hang!"); - - sf::Packet spac; - spac << (MessageId)NP_MSG_PLAYER_LEAVE; - spac << m_players[socket].pid; - - m_selector.Remove(socket); - - m_crit.players.Enter(); - m_players.erase(m_players.find(socket)); - m_crit.players.Leave(); - - // alert other players of disconnect - m_crit.send.Enter(); - SendToClients(spac); - m_crit.send.Leave(); - - UpdateGUI(); - - return 0; -} - +// called from ---NETPLAY--- thread void NetPlay::UpdateGUI() { if (m_dialog) @@ -401,6 +97,7 @@ void NetPlay::UpdateGUI() } } +// called from ---NETPLAY--- thread void NetPlay::AppendChatGUI(const std::string& msg) { if (m_dialog) @@ -411,241 +108,7 @@ void NetPlay::AppendChatGUI(const std::string& msg) } } -void NetPlayServer::SendToClients(sf::Packet& packet, const PlayerId skip_pid) -{ - std::map::iterator - i = m_players.begin(), - e = m_players.end(); - for ( ; i!=e; ++i) - if (i->second.pid && (i->second.pid != skip_pid)) - i->second.socket.Send(packet); -} - -unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) -{ - MessageId mid; - packet >> mid; - - // don't need lock because this is the only thread that modifies the players - // only need locks for writes to m_players in this thread - Player& player = m_players[socket]; - - switch (mid) - { - case NP_MSG_CHAT_MESSAGE : - { - std::string msg; - packet >> msg; - - // send msg to other clients - sf::Packet spac; - spac << (MessageId)NP_MSG_CHAT_MESSAGE; - spac << player.pid; - spac << msg; - - m_crit.send.Enter(); - SendToClients(spac, player.pid); - m_crit.send.Leave(); - - // add to gui - std::ostringstream ss; - ss << player.name << '[' << (char)(player.pid+'0') << "]: " << msg; - - AppendChatGUI(ss.str()); - } - break; - - case NP_MSG_PAD_DATA : - { - PadMapping map = 0; - NetPad np; - packet >> map >> np.nHi >> np.nLo; - - // check if client's pad indeed maps in game - if (map >= 0 && map < 4) - map = player.pad_map[(unsigned)map]; - else - map = -1; - - // if not, they are hacking, so disconnect them - // this could happen right after a pad map change, but that isn't implimented yet - if (map < 0) - return 1; - - // add to pad buffer - m_crit.buffer.Enter(); - m_pad_buffer[(unsigned)map].push(np); - m_crit.buffer.Leave(); - - // relay to clients - sf::Packet spac; - spac << (MessageId)NP_MSG_PAD_DATA; - spac << map; // in game mapping - spac << np.nHi << np.nLo; - - m_crit.send.Enter(); - SendToClients(spac, player.pid); - m_crit.send.Leave(); - } - break; - - default : - PanicAlert("Unknown message with id:%d received from player:%d Kicking player!", mid, player.pid); - // unknown message, kick the client - return 1; - break; - } - - return 0; -} - -unsigned int NetPlayClient::OnData(sf::Packet& packet) -{ - MessageId mid; - packet >> mid; - - switch (mid) - { - case NP_MSG_PLAYER_JOIN : - { - Player player; - packet >> player.pid; - packet >> player.name; - packet >> player.revision; - - m_crit.players.Enter(); - m_players[player.pid] = player; - m_crit.players.Leave(); - - UpdateGUI(); - } - break; - - case NP_MSG_PLAYER_LEAVE : - { - PlayerId pid; - packet >> pid; - - m_crit.players.Enter(); - m_players.erase(m_players.find(pid)); - m_crit.players.Leave(); - - UpdateGUI(); - } - break; - - case NP_MSG_CHAT_MESSAGE : - { - PlayerId pid; - packet >> pid; - std::string msg; - packet >> msg; - - // don't need lock to read in this thread - const Player& player = m_players[pid]; - - // add to gui - std::ostringstream ss; - ss << player.name << '[' << (char)(pid+'0') << "]: " << msg; - - AppendChatGUI(ss.str()); - } - break; - - case NP_MSG_PAD_MAPPING : - { - PlayerId pid; - packet >> pid; - - m_crit.players.Enter(); - Player& player = m_players[pid]; - - for (unsigned int i=0; i<4; ++i) - packet >> player.pad_map[i]; - m_crit.players.Leave(); - - UpdateGUI(); - } - break; - - case NP_MSG_PAD_DATA : - { - PadMapping map = 0; - NetPad np; - packet >> map >> np.nHi >> np.nLo; - - // trusting server for good map value (>=0 && <4) - // add to pad buffer - m_crit.buffer.Enter(); - m_pad_buffer[(unsigned)map].push(np); - m_crit.buffer.Leave(); - } - break; - - case NP_MSG_CHANGE_GAME : - { - m_crit.other.Enter(); - packet >> m_selected_game; - m_crit.other.Leave(); - - // update gui - wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_CHANGE_GAME); - // TODO: using a wxString in AddPendingEvent from another thread is unsafe i guess? - evt.SetString(wxString(m_selected_game.c_str(), *wxConvCurrent)); - m_dialog->GetEventHandler()->AddPendingEvent(evt); - } - break; - - case NP_MSG_START_GAME : - { - wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_START_GAME); - m_dialog->GetEventHandler()->AddPendingEvent(evt); - } - break; - - case NP_MSG_STOP_GAME : - { - wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_STOP_GAME); - m_dialog->GetEventHandler()->AddPendingEvent(evt); - } - break; - - default : - PanicAlert("Unknown message received with id : %d", mid); - break; - - } - - return 0; -} - -void NetPlayClient::Entry() -{ - while (m_do_loop) - { - if (m_selector.Wait(0.01f)) - { - sf::Packet rpac; - switch (m_socket.Receive(rpac)) - { - case sf::Socket::Done : - OnData(rpac); - break; - - //case sf::Socket::Disconnected : - default : - PanicAlert("Lost connection to server! If the game is running, it will likely hang!"); - m_do_loop = false; - break; - } - } - } - - m_socket.Close(); - - return; -} - +// called from ---GUI--- thread std::string NetPlay::Player::ToString() const { std::ostringstream ss; @@ -656,71 +119,8 @@ std::string NetPlay::Player::ToString() const return ss.str(); } -void NetPlayClient::GetPlayerList(std::string &list) -{ - m_crit.players.Enter(); - - std::ostringstream ss; - - std::map::const_iterator - i = m_players.begin(), - e = m_players.end(); - for ( ; i!=e; ++i) - ss << i->second.ToString() << '\n'; - - list = ss.str(); - - m_crit.players.Leave(); -} - -void NetPlayServer::GetPlayerList(std::string &list) -{ - m_crit.players.Enter(); - - std::ostringstream ss; - - std::map::const_iterator - i = m_players.begin(), - e = m_players.end(); - for ( ; i!=e; ++i) - ss << i->second.ToString() << '\n'; - - list = ss.str(); - - m_crit.players.Leave(); -} - -void NetPlayServer::SendChatMessage(const std::string& msg) -{ - sf::Packet spac; - spac << (MessageId)NP_MSG_CHAT_MESSAGE; - spac << (PlayerId)0; // server id always 0 - spac << msg; - - m_crit.send.Enter(); - SendToClients(spac); - m_crit.send.Leave(); -} - -void NetPlayClient::SendChatMessage(const std::string& msg) -{ - sf::Packet spac; - spac << (MessageId)NP_MSG_CHAT_MESSAGE; - spac << msg; - - m_crit.send.Enter(); - m_socket.Send(spac); - m_crit.send.Leave(); -} - NetPad::NetPad() { - //SPADStatus sp; - //memset(&sp, 0, sizeof(sp)); - //memset(&sp.stickX, 0x80, 4); - //*this = NetPad(&sp); - - // i'd rather do something like this nHi = 0x00808080; nLo = 0x80800000; } @@ -737,146 +137,127 @@ NetPad::NetPad(const SPADStatus* const pad_status) nLo |= (u32)((u8)pad_status->substickX << 24); } -bool NetPlayServer::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues) +// called from ---NETPLAY--- thread +void NetPlay::ClearBuffers() { - m_crit.players.Enter(); + // clear pad buffers, no clear method ? + for (unsigned int i=0; i<4; ++i) + { + while (m_pad_buffer[i].size()) + m_pad_buffer[i].pop(); + } +} - // in game mapping for this local pad, kinda silly method - PadMapping in_game_num = m_players[m_socket].pad_map[pad_nb]; +// called from ---CPU--- thread +bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues) +{ + m_crit.players.Enter(); // lock players - // check if this local pad maps in game - if (in_game_num >= 0) + // in game mapping for this local pad + unsigned int in_game_num = m_local_player->pad_map[pad_nb]; + + // does this local pad map in game? + if (in_game_num < 4) { NetPad np(pad_status); - // add to buffer - m_crit.buffer.Enter(); - m_pad_buffer[(unsigned)in_game_num].push(np); + m_crit.buffer.Enter(); // lock buffer + // adjust the buffer either up or down + while (m_pad_buffer[in_game_num].size() <= m_target_buffer_size) + { + // add to buffer + m_pad_buffer[in_game_num].push(np); + + // send + SendPadState(pad_nb, np); + } m_crit.buffer.Leave(); - - // send to clients - sf::Packet spac; - spac << (MessageId)NP_MSG_PAD_DATA; - spac << in_game_num; // in game pad num - spac << np.nHi << np.nLo; - - m_crit.send.Enter(); - SendToClients(spac); - m_crit.send.Leave(); } m_crit.players.Leave(); - // get pad from pad buffer and send to game - GetBufferedPad(pad_nb, netvalues); + //Common::Timer bufftimer; + //bufftimer.Start(); - return true; -} - -bool NetPlayServer::ChangeGame(const std::string &game) -{ - m_crit.other.Enter(); - m_selected_game = game; - - // send changed game to clients - sf::Packet spac; - spac << (MessageId)NP_MSG_CHANGE_GAME; - spac << game; - - m_crit.players.Enter(); - m_crit.send.Enter(); - SendToClients(spac); - m_crit.send.Leave(); - m_crit.players.Leave(); - - m_crit.other.Leave(); - - return true; -} - -void NetPlay::GetBufferedPad(const u8 pad_nb, NetPad* const netvalues) -{ // get padstate from buffer and send to game - m_crit.buffer.Enter(); + m_crit.buffer.Enter(); // lock buffer while (0 == m_pad_buffer[pad_nb].size()) { m_crit.buffer.Leave(); // wait for receiving thread to push some data Common::SleepCurrentThread(1); + if (false == m_is_running) + return false; m_crit.buffer.Enter(); + + // TODO: check the time of bufftimer here, + // if it gets pretty high, ask the user if they want to disconnect + } *netvalues = m_pad_buffer[pad_nb].front(); m_pad_buffer[pad_nb].pop(); m_crit.buffer.Leave(); -} -bool NetPlayClient::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues) -{ - m_crit.players.Enter(); - - // in game mapping for this local pad - PadMapping in_game_num = m_players[m_pid].pad_map[pad_nb]; - - // does this local pad map in game? - if (in_game_num >= 0) - { - NetPad np(pad_status); - - // add to buffer - m_crit.buffer.Enter(); - m_pad_buffer[(unsigned)in_game_num].push(np); - m_crit.buffer.Leave(); - - // send to server - sf::Packet spac; - spac << (MessageId)NP_MSG_PAD_DATA; - spac << (PadMapping)pad_nb; // local pad num - spac << np.nHi << np.nLo; - - m_crit.send.Enter(); - m_socket.Send(spac); - m_crit.send.Leave(); - } - - m_crit.players.Leave(); - - // get pad from pad buffer and send to game - GetBufferedPad(pad_nb, netvalues); + //u64 hangtime = bufftimer.GetTimeElapsed(); + //if (hangtime > 10) + //{ + // std::ostringstream ss; + // ss << "Pad " << (int)pad_nb << ": Had to wait " << hangtime << "ms for pad data. (increase pad Buffer maybe)"; + // Core::DisplayMessage(ss.str(), 1000); + //} return true; } -bool NetPlayClient::ChangeGame(const std::string &game) +// called from ---CPU--- thread +void NetPlay::WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 _Size) { - // warning removal - game.size(); + //m_crit.players.Enter(); // lock players - // idk, nothing is needed here + //// in game mapping for this local wiimote + //unsigned int in_game_num = m_local_player->pad_map[_number]; // just using gc pad_map for now + + //// does this local pad map in game? + //if (in_game_num < 4) + //{ + // //NetPad np(pad_status); + + // m_crit.buffer.Enter(); // lock buffer + // // adjust the buffer either up or down + // //while (m_pad_buffer[in_game_num].size() <= m_target_buffer_size) + // { + // // add to buffer + // //m_wiimote_buffer[in_game_num].push(np); + + // // send + // //SendPadState(pad_nb, np); + // } + // m_crit.buffer.Leave(); + //} + + //// get pad from pad buffer and send to game + //GetBufferedPad(pad_nb, netvalues); - return true; } -bool NetPlayServer::StartGame(const std::string &path) +// called from ---CPU--- thread +void NetPlay::WiimoteUpdate(int _number) { - if (false == NetPlay::StartGame(path)) - return false; + // temporary + if (_number) + return; - // tell clients to start game - sf::Packet spac; - spac << (MessageId)NP_MSG_START_GAME; + m_crit.buffer.Enter(); // lock buffer + ++m_wiimote_update_frame; + m_crit.buffer.Leave(); - m_crit.players.Enter(); - m_crit.send.Enter(); - SendToClients(spac); - m_crit.send.Leave(); - m_crit.players.Leave(); - - return true; + // TODO: prolly do some wiimote input here } +// called from ---GUI--- thread bool NetPlay::StartGame(const std::string &path) { - m_crit.other.Enter(); + CritLocker game_lock(m_crit.game); // lock game state if (m_is_running) { @@ -887,35 +268,19 @@ bool NetPlay::StartGame(const std::string &path) AppendChatGUI(" -- STARTING GAME -- "); m_is_running = true; - ::NetClass_ptr = this; - - // temporary / testing - m_crit.buffer.Enter(); - NetPad np; - for (unsigned int p=0; p<4; ++p) - { - // no clear method ? - while (m_pad_buffer[p].size()) - m_pad_buffer[p].pop(); - - // temporary - for (unsigned int i=0; iBootGame(path); //BootManager::BootCore(path); - m_crit.other.Leave(); - return true; } +// called from ---GUI--- thread and ---NETPLAY--- thread (client side) bool NetPlay::StopGame() { - m_crit.other.Enter(); + CritLocker game_lock(m_crit.game); // lock game state if (false == m_is_running) { @@ -925,51 +290,105 @@ bool NetPlay::StopGame() AppendChatGUI(" -- STOPPING GAME -- "); + m_is_running = false; + NetPlay_Disable(); + // stop game ::main_frame->DoStop(); - m_is_running = false; - ::NetClass_ptr = false; - - m_crit.other.Leave(); - return true; } -bool NetPlayServer::StopGame() +// called from ---CPU--- thread +u8 NetPlay::GetPadNum(u8 numPAD) { - if (false == NetPlay::StopGame()) - return false; + // TODO: i don't like that this loop is running everytime there is rumble + unsigned int i = 0; + for (; i<4; ++i) + if (numPAD == m_local_player->pad_map[i]) + break; - // tell clients to stop game - sf::Packet spac; - spac << (MessageId)NP_MSG_STOP_GAME; - - m_crit.players.Enter(); - m_crit.send.Enter(); - SendToClients(spac); - m_crit.send.Leave(); - m_crit.players.Leave(); - - return true; + return i; } +// stuff hacked into dolphin + +// called from ---CPU--- thread // Actual Core function which is called on every frame -int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) +int CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) { - if (NetClass_ptr) - // TODO: NetClass_ptr could go null here, need a lock - return NetClass_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus) ? 1 : 0; + CritLocker crit(::crit_netplay_ptr); + + if (::netplay_ptr) + return netplay_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus) ? 1 : 0; else return 2; } +// called from ---CPU--- thread // so all players' games get the same time -u32 CEXIIPL::GetNetGCTime() +u32 CEXIIPL::NetPlay_GetGCTime() { - if (NetClass_ptr) - // TODO: NetClass_ptr could go null here, need a lock + CritLocker crit(::crit_netplay_ptr); + + if (::netplay_ptr) return 1272737767; // watev else return 0; } + +// called from ---CPU--- thread +// return the local pad num that should rumble given a ingame pad num +u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD) +{ + CritLocker crit(::crit_netplay_ptr); + + if (::netplay_ptr) + return ::netplay_ptr->GetPadNum(numPAD); + else + return numPAD; +} + +// called from ---CPU--- thread +// wiimote update / used for frame counting +void CWII_IPC_HLE_Device_usb_oh1_57e_305::NetPlay_WiimoteUpdate(int _number) +{ + CritLocker crit(::crit_netplay_ptr); + + return; +} + +// called from ---CPU--- thread +// +int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number) +{ + CritLocker crit(::crit_netplay_ptr); + + if (::netplay_ptr) + return ::netplay_ptr->GetPadNum(_number); // just using gcpad mapping for now + else + return _number; +} + +// called from ---CPU--- thread +// intercept wiimote input callback +bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int _number, u16 _channelID, const void* _pData, u32& _Size) +{ + CritLocker crit(::crit_netplay_ptr); + + if (::netplay_ptr) + { + if (_Size >= RPT_SIZE_HACK) + { + _Size -= RPT_SIZE_HACK; + return false; + } + else + { + ::netplay_ptr->WiimoteInput(_number, _channelID, _pData, _Size); + return true; + } + } + else + return false; +} diff --git a/Source/Core/DolphinWX/Src/NetPlay.h b/Source/Core/DolphinWX/Src/NetPlay.h index eb826510fa..1e7ac3f501 100644 --- a/Source/Core/DolphinWX/Src/NetPlay.h +++ b/Source/Core/DolphinWX/Src/NetPlay.h @@ -5,6 +5,7 @@ #include "CommonTypes.h" //#define WIN32_LEAN_AND_MEAN #include "Thread.h" +#include "Timer.h" // hax, i hope something like this isn't needed on non-windows #define _WINSOCK2API_ @@ -17,6 +18,7 @@ #include #include +#include class NetPlayDiag; @@ -30,7 +32,17 @@ public: u32 nLo; }; -#define NETPLAY_VERSION "Dolphin NetPlay 2.1" +class NetWiimote +{ +public: + NetWiimote& operator=(const NetWiimote&); + NetWiimote(const u32 _size) : size(_size), data(new u8[size]) {} + + const u32 size; + u8* const data; +}; + +#define NETPLAY_VERSION "Dolphin NetPlay 2.2" #ifdef _M_X64 #define NP_ARCH "x64" @@ -39,11 +51,11 @@ public: #endif #ifdef _WIN32 - #define NETPLAY_DOLPHIN_VER SVN_REV_STR" win-"NP_ARCH + #define NETPLAY_DOLPHIN_VER SVN_REV_STR" W"NP_ARCH #elif __APPLE__ - #define NETPLAY_DOLPHIN_VER SVN_REV_STR" osx-"NP_ARCH + #define NETPLAY_DOLPHIN_VER SVN_REV_STR" M"NP_ARCH #else - #define NETPLAY_DOLPHIN_VER SVN_REV_STR" nix-"NP_ARCH + #define NETPLAY_DOLPHIN_VER SVN_REV_STR" L"NP_ARCH #endif // messages @@ -56,9 +68,13 @@ public: #define NP_MSG_PAD_MAPPING 0x61 #define NP_MSG_PAD_BUFFER 0x62 +#define NP_MSG_WIIMOTE_DATA 0x70 +#define NP_MSG_WIIMOTE_MAPPING 0x71 // just using pad mapping for now + #define NP_MSG_START_GAME 0xA0 #define NP_MSG_CHANGE_GAME 0xA1 #define NP_MSG_STOP_GAME 0xA2 +#define NP_MSG_DISABLE_GAME 0xA3 #define NP_MSG_READY 0xD0 #define NP_MSG_NOT_READY 0xD1 @@ -67,25 +83,46 @@ public: #define NP_MSG_PONG 0xE1 // end messages -// gui messages -#define NP_GUI_UPDATE 0x10 -// end messages - typedef u8 MessageId; typedef u8 PlayerId; typedef s8 PadMapping; +typedef u32 FrameNum; + +enum +{ + CON_ERR_SERVER_FULL = 1, + CON_ERR_GAME_RUNNING, + CON_ERR_VERSION_MISMATCH +}; + +THREAD_RETURN NetPlayThreadFunc(void* arg); + +// something like this should be in Common stuff +class CritLocker +{ +public: + //CritLocker(const CritLocker&); + CritLocker& operator=(const CritLocker&); + CritLocker(Common::CriticalSection& crit) : m_crit(crit) { m_crit.Enter(); } + ~CritLocker() { m_crit.Leave(); } + +private: + Common::CriticalSection& m_crit; +}; class NetPlay { public: - NetPlay() : m_is_running(false), m_do_loop(true) {} + NetPlay(); virtual ~NetPlay(); virtual void Entry() = 0; bool is_connected; // Send and receive pads values - virtual bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues) = 0; + void WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 _Size); + void WiimoteUpdate(int _number); + bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); virtual bool ChangeGame(const std::string& game) = 0; virtual void GetPlayerList(std::string& list) = 0; virtual void SendChatMessage(const std::string& msg) = 0; @@ -93,15 +130,23 @@ public: virtual bool StartGame(const std::string &path); virtual bool StopGame(); + //void PushPadStates(unsigned int count); + + u8 GetPadNum(u8 numPAD); + protected: //NetPlay(Common::ThreadFunc entry, void* arg) : m_thread(entry, arg) {} - void GetBufferedPad(const u8 pad_nb, NetPad* const netvalues); + //void GetBufferedPad(const u8 pad_nb, NetPad* const netvalues); + void ClearBuffers(); void UpdateGUI(); void AppendChatGUI(const std::string& msg); + virtual void SendPadState(const PadMapping local_nb, const NetPad& np) = 0; struct { - Common::CriticalSection send, players, buffer, other; + Common::CriticalSection game; + // lock order + Common::CriticalSection players, buffer, send; } m_crit; class Player @@ -118,6 +163,9 @@ protected: //LockingQueue m_pad_buffer[4]; std::queue m_pad_buffer[4]; + std::map m_wiimote_buffer[4]; + + FrameNum m_wiimote_update_frame; NetPlayDiag* m_dialog; sf::SocketTCP m_socket; @@ -125,13 +173,22 @@ protected: sf::Selector m_selector; std::string m_selected_game; - bool m_is_running; + volatile bool m_is_running; volatile bool m_do_loop; + unsigned int m_target_buffer_size; + + Player* m_local_player; + + u32 m_on_game; + private: }; +void NetPlay_Enable(NetPlay* const np); +void NetPlay_Disable(); + class NetPlayServer : public NetPlay { public: @@ -143,26 +200,38 @@ public: void GetPlayerList(std::string& list); // Send and receive pads values - bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); + //bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); bool ChangeGame(const std::string& game); void SendChatMessage(const std::string& msg); bool StartGame(const std::string &path); bool StopGame(); + u64 CalculateMinimumBufferTime(); + void AdjustPadBufferSize(unsigned int size); + private: class Client : public Player { public: + Client() : ping(0), on_game(0) {} + sf::SocketTCP socket; + u64 ping; + u32 on_game; }; + void SendPadState(const PadMapping local_nb, const NetPad& np); void SendToClients(sf::Packet& packet, const PlayerId skip_pid = 0); unsigned int OnConnect(sf::SocketTCP& socket); unsigned int OnDisconnect(sf::SocketTCP& socket); unsigned int OnData(sf::Packet& packet, sf::SocketTCP& socket); std::map m_players; + + Common::Timer m_ping_timer; + u32 m_ping_key; + bool m_update_pings; }; class NetPlayClient : public NetPlay @@ -176,11 +245,13 @@ public: void GetPlayerList(std::string& list); // Send and receive pads values - bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); + //bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); + bool StartGame(const std::string &path); bool ChangeGame(const std::string& game); void SendChatMessage(const std::string& msg); private: + void SendPadState(const PadMapping local_nb, const NetPad& np); unsigned int OnData(sf::Packet& packet); PlayerId m_pid; diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index ff44f54960..687c92eaee 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -28,7 +28,7 @@ BEGIN_EVENT_TABLE(NetPlayDiag, wxFrame) EVT_COMMAND(wxID_ANY, wxEVT_THREAD, NetPlayDiag::OnThread) END_EVENT_TABLE() -NetPlay* netplay_ptr = NULL; +static NetPlay* netplay_ptr = NULL; NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* const game_list) : wxFrame(parent, wxID_ANY, wxT(NETPLAY_TITLEBAR), wxDefaultPosition, wxDefaultSize) @@ -68,12 +68,12 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* wxStaticText* const alert_lbl = new wxStaticText(connect_tab, wxID_ANY , wxT("ALERT:\n\nNetPlay will currently only work properly when using the following settings:") wxT("\n - Dual Core [OFF]") - wxT("\n - Audio Throttle [OFF] (if using DSP HLE)") - wxT("\n - DSP LLE Plugin (may not be needed)\n - DSPLLE on thread [OFF]") - wxT("\n - Manually set the exact number of controller that will be used to [Standard Controller]") + wxT("\n - Audio Throttle [OFF/ON] (try both)") + wxT("\n - DSP LLE/HLE (try both)") + wxT("\n - Manually set the exact number of controllers that will be used to [Standard Controller]") wxT("\n\nAll players should try to use the same Dolphin version and settings.") wxT("\nDisable all memory cards or send them to all players before starting.") - wxT("\nWiimote support has not been implemented.\nWii games will likely desync for other reasons as well.") + wxT("\nWiimote support has not been implemented.") wxT("\n\nYou must forward TCP port to host!!") , wxDefaultPosition, wxDefaultSize); @@ -285,9 +285,17 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game wxButton* const start_btn = new wxButton(panel, wxID_ANY, wxT("Start")); _connect_macro_(start_btn, NetPlayDiag::OnStart, wxEVT_COMMAND_BUTTON_CLICKED, this); bottom_szr->Add(start_btn); - wxButton* const stop_btn = new wxButton(panel, wxID_ANY, wxT("Stop [buggy]")); + wxButton* const stop_btn = new wxButton(panel, wxID_ANY, wxT("Stop")); _connect_macro_(stop_btn, NetPlayDiag::OnStop, wxEVT_COMMAND_BUTTON_CLICKED, this); bottom_szr->Add(stop_btn); + bottom_szr->Add(new wxStaticText(panel, wxID_ANY, wxT("Buffer:")), 0, wxLEFT | wxCENTER, 5 ); + wxSpinCtrl* const padbuf_spin = new wxSpinCtrl(panel, wxID_ANY, wxT("20") + , wxDefaultPosition, wxSize(64, -1), wxSP_ARROW_KEYS, 0, 200, 20); + _connect_macro_(padbuf_spin, NetPlayDiag::OnAdjustBuffer, wxEVT_COMMAND_SPINCTRL_UPDATED, this); + wxButton* const padbuf_btn = new wxButton(panel, wxID_ANY, wxT("?"), wxDefaultPosition, wxSize(22, -1)); + _connect_macro_(padbuf_btn, NetPlayDiag::OnPadBuffHelp, wxEVT_COMMAND_BUTTON_CLICKED, this); + bottom_szr->Add(padbuf_spin, 0, wxCENTER); + bottom_szr->Add(padbuf_btn); } bottom_szr->AddStretchSpacer(1); @@ -364,6 +372,31 @@ void NetPlayDiag::OnStop(wxCommandEvent& event) ::netplay_ptr->StopGame(); } +void NetPlayDiag::OnPadBuffHelp(wxCommandEvent& event) +{ + // warning removal + event.GetId(); + + const u64 time = ((NetPlayServer*)::netplay_ptr)->CalculateMinimumBufferTime(); + std::ostringstream ss; + ss << "< Calculated from pings: required buffer: " + << time * (60/1000) << "(60fps) / " + << time * (50/1000) << "(50fps) >\n"; + + m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent)); +} + +void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event) +{ + const int val = ((wxSpinCtrl*)event.GetEventObject())->GetValue(); + ((NetPlayServer*)::netplay_ptr)->AdjustPadBufferSize(val); + + std::ostringstream ss; + ss << "< Pad Buffer: " << val << " >"; + ::netplay_ptr->SendChatMessage(ss.str()); + m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent).Append(wxT('\n'))); +} + void NetPlayDiag::OnQuit(wxCommandEvent& event) { // warning removal diff --git a/Source/Core/DolphinWX/Src/NetWindow.h b/Source/Core/DolphinWX/Src/NetWindow.h index 393c88f34d..0d6a9958a2 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.h +++ b/Source/Core/DolphinWX/Src/NetWindow.h @@ -29,6 +29,7 @@ #include #include #include +#include //#include #include "GameListCtrl.h" @@ -93,8 +94,10 @@ private: void OnChat(wxCommandEvent& event); void OnQuit(wxCommandEvent& event); + void OnPadBuffHelp(wxCommandEvent& event); void OnThread(wxCommandEvent& event); void OnChangeGame(wxCommandEvent& event); + void OnAdjustBuffer(wxCommandEvent& event); wxListBox* m_player_lbox; wxTextCtrl* m_chat_text; diff --git a/Source/Core/DolphinWX/Src/SConscript b/Source/Core/DolphinWX/Src/SConscript index 9bc5b03d32..873ca421f6 100644 --- a/Source/Core/DolphinWX/Src/SConscript +++ b/Source/Core/DolphinWX/Src/SConscript @@ -38,6 +38,8 @@ if wxenv['HAVE_WX']: 'WxUtils.cpp', 'MemoryCards/WiiSaveCrypted.cpp', 'NetPlay.cpp', + 'NetPlayClient.cpp', + 'NetPlayServer.cpp', 'NetWindow.cpp', ] diff --git a/Source/UnitTests/UnitTests.cpp b/Source/UnitTests/UnitTests.cpp index 4273f99b46..c732ea3d1e 100644 --- a/Source/UnitTests/UnitTests.cpp +++ b/Source/UnitTests/UnitTests.cpp @@ -138,8 +138,3 @@ void Host_UpdateLeds(int bits){} void Host_UpdateSpeakerStatus(int index, int bits){} void Host_UpdateStatus(){} void Host_Message(int){} - -int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) -{ - return 0; -}