From d0f05291e7eee2c58f9beaa85e4f8933965773f2 Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Tue, 6 Aug 2013 23:48:52 -0400 Subject: [PATCH] Add wiimote support to netplay. --- .../Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp | 11 +- .../Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h | 1 + .../Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 1 - .../Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp | 2 - Source/Core/Core/Src/NetPlayClient.cpp | 189 +++++++++++++----- Source/Core/Core/Src/NetPlayClient.h | 5 +- Source/Core/Core/Src/NetPlayProto.h | 11 +- Source/Core/Core/Src/NetPlayServer.cpp | 125 +++++++++++- Source/Core/Core/Src/NetPlayServer.h | 5 + Source/Core/DolphinWX/Src/NetWindow.cpp | 38 +++- Source/Core/DolphinWX/Src/NetWindow.h | 5 +- 11 files changed, 317 insertions(+), 76 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index eb5ebc2be5..94e7d88cd6 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -27,6 +27,7 @@ inline double round(double x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); } #include "MatrixMath.h" #include "../../Movie.h" +#include "NetPlayClient.h" namespace { @@ -339,7 +340,7 @@ bool Wiimote::Step() m_rumble->controls[0]->control_ref->State(m_rumble_on); // when a movie is active, this button status update is disabled (moved), because movies only record data reports. - if(!(Movie::IsPlayingInput() || Movie::IsRecordingInput())) + if(!(Movie::IsPlayingInput() || Movie::IsRecordingInput()) || NetPlay::IsNetPlayRunning()) { UpdateButtonsStatus(has_focus); } @@ -397,7 +398,7 @@ void Wiimote::UpdateButtonsStatus(bool has_focus) void Wiimote::GetCoreData(u8* const data) { // when a movie is active, the button update happens here instead of Wiimote::Step, to avoid potential desync issues. - if(Movie::IsPlayingInput() || Movie::IsRecordingInput()) + if(Movie::IsPlayingInput() || Movie::IsRecordingInput() || NetPlay::IsNetPlayRunning()) { UpdateButtonsStatus(HAS_FOCUS); } @@ -770,6 +771,12 @@ void Wiimote::Update() } } } + if (NetPlay::IsNetPlayRunning()) + { + NetPlay_GetWiimoteData(m_index, data, rptf.size); + if (rptf.core) + m_status.buttons = *(wm_core*)(data + rptf.core); + } if (!Movie::IsPlayingInput()) { Movie::CheckWiimoteStatus(m_index, data, rptf, m_reg_ir.mode); diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h index 2fd471978e..9ed58f8b48 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h @@ -158,6 +158,7 @@ private: void WriteData(const wm_write_data* const wd); void SendReadDataReply(ReadRequest& _request); void SpeakerData(wm_speaker_data* sd); + bool NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size); // control groups Buttons *m_buttons, *m_dpad, *m_shake; 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 9bef545257..a2d5768039 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,7 +494,6 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() for (unsigned int i = 0; i < m_WiiMotes.size(); i++) if (m_WiiMotes[i].IsConnected()) { - NetPlay_WiimoteUpdate(i); Wiimote::Update(i); } m_last_ticks = now; 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 9386682106..4adec84469 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 @@ -862,8 +862,6 @@ 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]; diff --git a/Source/Core/Core/Src/NetPlayClient.cpp b/Source/Core/Core/Src/NetPlayClient.cpp index e10cc25186..cefb0ebe16 100644 --- a/Source/Core/Core/Src/NetPlayClient.cpp +++ b/Source/Core/Core/Src/NetPlayClient.cpp @@ -16,6 +16,7 @@ // for wiimote/ OSD messages #include "Core.h" #include "ConfigManager.h" +#include "HW/WiimoteEmu/WiimoteEmu.h" std::mutex crit_netplay_client; static NetPlayClient * netplay_client = NULL; @@ -26,6 +27,7 @@ NetSettings g_NetPlaySettings; NetPlayClient::Player::Player() { memset(pad_map, -1, sizeof(pad_map)); + memset(wiimote_map, -1, sizeof(wiimote_map)); } // called from ---GUI--- thread @@ -35,6 +37,8 @@ std::string NetPlayClient::Player::ToString() const ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |"; for (unsigned int i=0; i<4; ++i) ss << (pad_map[i]>=0 ? (char)(pad_map[i]+'1') : '-'); + for (unsigned int i=0; i<4; ++i) + ss << (wiimote_map[i]>=0 ? (char)(wiimote_map[i]+'1') : '-'); ss << " | " << ping << "ms"; return ss.str(); } @@ -215,6 +219,23 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) } break; + case NP_MSG_WIIMOTE_MAPPING : + { + PlayerId pid; + packet >> pid; + + { + std::lock_guard lkp(m_crit.players); + Player& player = m_players[pid]; + + for (unsigned int i=0; i<4; ++i) + packet >> player.wiimote_map[i]; + } + + m_dialog->Update(); + } + break; + case NP_MSG_PAD_DATA : { PadMapping map = 0; @@ -227,6 +248,27 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) } break; + case NP_MSG_WIIMOTE_DATA : + { + PadMapping map = 0; + NetWiimote nw; + u8 size; + packet >> map >> size; + + nw.size = size; + u8* data = new u8[size]; + for (unsigned int i = 0; i < size; ++i) + packet >> data[i]; + nw.data.assign(data,data+size); + delete[] data; + + // trusting server for good map value (>=0 && <4) + // add to pad buffer + m_wiimote_buffer[(unsigned)map].Push(nw); + } + break; + + case NP_MSG_PAD_BUFFER : { u32 size = 0; @@ -392,11 +434,34 @@ void NetPlayClient::SendPadState(const PadMapping local_nb, const NetPad& np) m_socket.Send(spac); } +// called from ---CPU--- thread +void NetPlayClient::SendWiimoteState(const PadMapping local_nb, const NetWiimote& nw) +{ + // send to server + sf::Packet spac; + spac << (MessageId)NP_MSG_WIIMOTE_DATA; + spac << local_nb; // local pad num + u8 size = nw.size; + spac << size; + for (unsigned int i = 0; i < size; ++i) + spac << nw.data.data()[i]; + + std::lock_guard lks(m_crit.send); + m_socket.Send(spac); +} + // called from ---GUI--- thread bool NetPlayClient::StartGame(const std::string &path) { std::lock_guard lkg(m_crit.game); + //wtf? + if (m_target_buffer_size > 100) + { + m_target_buffer_size = 20; + NOTICE_LOG(NETPLAY,"WHYYYYYYYYYYYY"); + } + // tell server i started the game sf::Packet spac; spac << (MessageId)NP_MSG_START_GAME; @@ -423,10 +488,10 @@ bool NetPlayClient::StartGame(const std::string &path) m_dialog->BootGame(path); // temporary - NetWiimote nw; - for (unsigned int i = 0; i<4; ++i) - for (unsigned int f = 0; f<2; ++f) - m_wiimote_buffer[i].Push(nw); + //NetWiimote nw; + //for (unsigned int i = 0; i<4; ++i) + //for (unsigned int f = 0; f<2; ++f) + //m_wiimote_buffer[i].Push(nw); return true; } @@ -449,7 +514,7 @@ void NetPlayClient::ClearBuffers() while (m_wiimote_buffer[i].Size()) m_wiimote_buffer[i].Pop(); - m_wiimote_input[i].clear(); + m_wiimote_input[i].data.clear(); } } @@ -509,55 +574,77 @@ bool NetPlayClient::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_stat return true; } -// called from ---CPU--- thread -void NetPlayClient::WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 _Size) -{ - //// 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) - { - m_wiimote_input[_number].resize(m_wiimote_input[_number].size() + 1); - m_wiimote_input[_number].back().assign((char*)_pData, (char*)_pData + _Size); - m_wiimote_input[_number].back().channel = _channelID; - } -} // called from ---CPU--- thread -void NetPlayClient::WiimoteUpdate(int _number) +bool NetPlayClient::WiimoteUpdate(int _number, u8* data, u8 size) { { std::lock_guard lkp(m_crit.players); // 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 + unsigned int in_game_num = m_local_player->wiimote_map[_number]; // does this local pad map in game? if (in_game_num < 4) { - m_wiimote_buffer[in_game_num].Push(m_wiimote_input[_number]); + static u8 previousSize = 0; - // TODO: send it + if (previousSize != size && m_wiimote_buffer[in_game_num].Size() > 0) + { + // Reporting mode changed, so previous buffer is no good. + m_wiimote_buffer[_number].Clear(); + } + + //m_wiimote_input[in_game_num].data.resize(m_wiimote_input[_number].size + 1); + m_wiimote_input[in_game_num].data.assign(data, data + size); + m_wiimote_input[in_game_num].size = size; + while (m_wiimote_buffer[in_game_num].Size() <= m_target_buffer_size) + { + // add to buffer + m_wiimote_buffer[in_game_num].Push(m_wiimote_input[in_game_num]); - m_wiimote_input[_number].clear(); + // send + SendWiimoteState(_number, m_wiimote_input[_number]); + } + previousSize = size; } } // unlock players - if (0 == m_wiimote_buffer[_number].Size()) + NetWiimote nw; + while (!m_wiimote_buffer[_number].Pop(nw)) { - //PanicAlert("PANIC"); - return; + // wait for receiving thread to push some data + Common::SleepCurrentThread(1); + if (false == m_is_running) + return false; } - NetWiimote nw; - m_wiimote_buffer[_number].Pop(nw); + // This is either a desync, or the reporting mode changed. No way to really be sure... + if (size != nw.size) + { + // Clear the buffer and wait for new input, in case it was just the reporting mode changing as expected. + do + { + m_wiimote_buffer[_number].Pop(nw); + Common::SleepCurrentThread(1); + if (false == m_is_running) + return false; - NetWiimote::const_iterator - i = nw.begin(), e = nw.end(); - for ( ; i!=e; ++i) - Core::Callback_WiimoteInterruptChannel(_number, i->channel, &(*i)[0], (u32)i->size() + RPT_SIZE_HACK); + // TODO: break if this runs too long; it probably desynced if it runs for longer than the buffer size + } while (nw.size != size); + + // If it still mismatches, it surely desynced + if (size != nw.size) + { + PanicAlert("Netplay has desynced. There is no way to handle this. Self destructing in 3...2...1..."); + StopGame(); + return false; + } + } + + memcpy(data, nw.data.data(), size); + return true; } // called from ---GUI--- thread and ---NETPLAY--- thread (client side) @@ -586,12 +673,9 @@ bool NetPlayClient::StopGame() u8 NetPlayClient::GetPadNum(u8 numPAD) { // TODO: i don't like that this loop is running everytime there is rumble - unsigned int i = 0; - for (; i<4; ++i) + for (unsigned int i = 0; i<4; ++i) if (numPAD == m_local_player->pad_map[i]) - break; - - return i; + return i; } // stuff hacked into dolphin @@ -608,6 +692,16 @@ bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u return false; } +bool WiimoteEmu::Wiimote::NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size) +{ + std::lock_guard lk(crit_netplay_client); + + if (netplay_client) + return netplay_client->WiimoteUpdate(wiimote, data, size); + else + return false; +} + bool CSIDevice_GCSteeringWheel::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) { return CSIDevice_GCController::NetPlay_GetInput(numPAD, PadStatus, PADStatus); @@ -652,26 +746,15 @@ u8 CSIDevice_DanceMat::NetPlay_GetPadNum(u8 numPAD) return CSIDevice_GCController::NetPlay_GetPadNum(numPAD); } -// called from ---CPU--- thread -// wiimote update / used for frame counting -//void CWII_IPC_HLE_Device_usb_oh1_57e_305::NetPlay_WiimoteUpdate(int _number) -void CWII_IPC_HLE_Device_usb_oh1_57e_305::NetPlay_WiimoteUpdate(int) -{ - //CritLocker crit(crit_netplay_client); - - //if (netplay_client) - // netplay_client->WiimoteUpdate(_number); -} - // called from ---CPU--- thread // int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number) { - //CritLocker crit(crit_netplay_client); +// std::lock_guard lk(crit_netplay_client); - //if (netplay_client) - // return netplay_client->GetPadNum(_number); // just using gcpad mapping for now - //else +// if (netplay_client) +// return netplay_client->GetPadNum(_number+4); +// else return _number; } diff --git a/Source/Core/Core/Src/NetPlayClient.h b/Source/Core/Core/Src/NetPlayClient.h index d44a4c84b8..625c20b951 100644 --- a/Source/Core/Core/Src/NetPlayClient.h +++ b/Source/Core/Core/Src/NetPlayClient.h @@ -68,8 +68,7 @@ public: void SendChatMessage(const std::string& msg); // Send and receive pads values - void WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 _Size); - void WiimoteUpdate(int _number); + bool WiimoteUpdate(int _number, u8* data, u8 size); bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); u8 GetPadNum(u8 numPAD); @@ -93,6 +92,7 @@ protected: PlayerId pid; std::string name; PadMapping pad_map[4]; + PadMapping wiimote_map[4]; std::string revision; u32 ping; }; @@ -119,6 +119,7 @@ protected: private: void SendPadState(const PadMapping local_nb, const NetPad& np); + void SendWiimoteState(const PadMapping local_nb, const NetWiimote& nw); unsigned int OnData(sf::Packet& packet); PlayerId m_pid; diff --git a/Source/Core/Core/Src/NetPlayProto.h b/Source/Core/Core/Src/NetPlayProto.h index 84e2b420fd..b1c4c481d9 100644 --- a/Source/Core/Core/Src/NetPlayProto.h +++ b/Source/Core/Core/Src/NetPlayProto.h @@ -16,14 +16,13 @@ struct NetSettings u8 m_Controllers[4]; }; -struct Rpt : public std::vector +struct NetWiimote { - u16 channel; + u8 size; + std::vector data; }; -typedef std::vector NetWiimote; - -#define NETPLAY_VERSION "Dolphin NetPlay 2013-08-05" +#define NETPLAY_VERSION "Dolphin NetPlay 2013-08-06 now with wiimote(TM)" // messages enum @@ -38,7 +37,7 @@ enum NP_MSG_PAD_BUFFER = 0x62, NP_MSG_WIIMOTE_DATA = 0x70, - NP_MSG_WIIMOTE_MAPPING = 0x71, // just using pad mapping for now + NP_MSG_WIIMOTE_MAPPING = 0x71, NP_MSG_START_GAME = 0xA0, NP_MSG_CHANGE_GAME = 0xA1, diff --git a/Source/Core/Core/Src/NetPlayServer.cpp b/Source/Core/Core/Src/NetPlayServer.cpp index 505e6a8f76..5eb5288c15 100644 --- a/Source/Core/Core/Src/NetPlayServer.cpp +++ b/Source/Core/Core/Src/NetPlayServer.cpp @@ -7,6 +7,7 @@ NetPlayServer::Client::Client() { memset(pad_map, -1, sizeof(pad_map)); + memset(wiimote_map, -1, sizeof(wiimote_map)); } // called from ---GUI--- thread @@ -16,6 +17,8 @@ std::string NetPlayServer::Client::ToString() const ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |"; for (unsigned int i=0; i<4; ++i) ss << (pad_map[i]>=0 ? (char)(pad_map[i]+'1') : '-'); + for (unsigned int i=0; i<4; ++i) + ss << (wiimote_map[i]>=0 ? (char)(wiimote_map[i]+'1') : '-'); ss << '|'; return ss.str(); } @@ -311,6 +314,27 @@ bool NetPlayServer::GetPadMapping(const int pid, int map[]) return true; } +bool NetPlayServer::GetWiimoteMapping(const int pid, int map[]) +{ + std::lock_guard lkp(m_crit.players); + std::map::const_iterator + i = m_players.begin(), + e = m_players.end(); + for (; i!=e; ++i) + if (pid == i->second.pid) + break; + + // player not found + if (i == e) + return false; + + // get pad mapping + for (unsigned int m = 0; m<4; ++m) + map[m] = i->second.wiimote_map[m]; + + return true; +} + // called from ---GUI--- thread bool NetPlayServer::SetPadMapping(const int pid, const int map[]) { @@ -351,6 +375,46 @@ bool NetPlayServer::SetPadMapping(const int pid, const int map[]) return true; } +// called from ---GUI--- thread +bool NetPlayServer::SetWiimoteMapping(const int pid, const int map[]) +{ + std::lock_guard lkg(m_crit.game); + if (m_is_running) + return false; + + std::lock_guard lkp(m_crit.players); + std::map::iterator + i = m_players.begin(), + e = m_players.end(); + for (; i!=e; ++i) + if (pid == i->second.pid) + break; + + // player not found + if (i == e) + return false; + + Client& player = i->second; + + // set pad mapping + for (unsigned int m = 0; m<4; ++m) + { + player.wiimote_map[m] = (PadMapping)map[m]; + + // remove duplicate mappings + for (i = m_players.begin(); i!=e; ++i) + for (unsigned int p = 0; p<4; ++p) + if (p != m || i->second.pid != pid) + if (player.wiimote_map[m] == i->second.wiimote_map[p]) + i->second.wiimote_map[p] = -1; + } + + std::lock_guard lks(m_crit.send); + UpdateWiimoteMapping(); // sync pad mappings with everyone + + return true; +} + // called from ---NETPLAY--- thread void NetPlayServer::UpdatePadMapping() { @@ -369,6 +433,24 @@ void NetPlayServer::UpdatePadMapping() } +// called from ---NETPLAY--- thread +void NetPlayServer::UpdateWiimoteMapping() +{ + std::map::const_iterator + i = m_players.begin(), + e = m_players.end(); + for (; i!=e; ++i) + { + sf::Packet spac; + spac << (MessageId)NP_MSG_WIIMOTE_MAPPING; + spac << i->second.pid; + for (unsigned int pm = 0; pm<4; ++pm) + spac << i->second.wiimote_map[pm]; + SendToClients(spac); + } + +} + // called from ---GUI--- thread and ---NETPLAY--- thread void NetPlayServer::AdjustPadBufferSize(unsigned int size) { @@ -431,12 +513,12 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) 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 implemented yet if (map < 0) return 1; - + // relay to clients sf::Packet spac; @@ -449,6 +531,45 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) } break; + case NP_MSG_WIIMOTE_DATA : + { + // if this is pad data from the last game still being received, ignore it + if (player.current_game != m_current_game) + break; + + PadMapping map = 0; + u8 size; + packet >> map >> size; + u8* data = new u8[size]; + for (unsigned int i = 0; i < size; ++i) + packet >> data[i]; + + // check if client's pad indeed maps in game + if (map >= 0 && map < 4) + map = player.wiimote_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 implemented yet + if (map < 0) + return 1; + + // relay to clients + sf::Packet spac; + spac << (MessageId)NP_MSG_WIIMOTE_DATA; + spac << map; // in game mapping + spac << size; + for (unsigned int i = 0; i < size; ++i) + spac << data[i]; + + delete[] data; + + std::lock_guard lks(m_crit.send); + SendToClients(spac, player.pid); + } + break; + case NP_MSG_PONG : { const u32 ping = m_ping_timer.GetTimeElapsed(); diff --git a/Source/Core/Core/Src/NetPlayServer.h b/Source/Core/Core/Src/NetPlayServer.h index 95f98e2a73..1d3735277d 100644 --- a/Source/Core/Core/Src/NetPlayServer.h +++ b/Source/Core/Core/Src/NetPlayServer.h @@ -40,6 +40,9 @@ public: bool GetPadMapping(const int pid, int map[]); bool SetPadMapping(const int pid, const int map[]); + bool GetWiimoteMapping(const int pid, int map[]); + bool SetWiimoteMapping(const int pid, const int map[]); + void AdjustPadBufferSize(unsigned int size); bool is_connected; @@ -58,6 +61,7 @@ private: PlayerId pid; std::string name; PadMapping pad_map[4]; + PadMapping wiimote_map[4]; std::string revision; sf::SocketTCP socket; @@ -70,6 +74,7 @@ private: unsigned int OnDisconnect(sf::SocketTCP& socket); unsigned int OnData(sf::Packet& packet, sf::SocketTCP& socket); void UpdatePadMapping(); + void UpdateWiimoteMapping(); NetSettings m_settings; diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 1c8f0549b9..86650b3588 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -106,11 +106,11 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* " - DSP Emulator Engine Must be the same on all computers!\n" " - DSP on Dedicated Thread [OFF]\n" " - Framelimit NOT set to [Audio]\n" - " - Manually set the exact number of controllers to be used to [Standard Controller]\n" + " - Manually set the exact number of wiimotes to be used to [Emulated Wiimote]\n" "\n" "All players should use the same Dolphin version and settings.\n" "All memory cards must be identical between players or disabled.\n" - "Wiimote support has not been implemented!\n" + "Wiimote support is probably terrible. Don't use it.\n" "\n" "The host must have the chosen TCP port open/forwarded!\n"), wxDefaultPosition, wxDefaultSize); @@ -560,6 +560,7 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&) void NetPlayDiag::OnConfigPads(wxCommandEvent&) { int mapping[4]; + int wiimotemapping[4]; // get selected player id int pid = m_player_lbox->GetSelection(); @@ -569,11 +570,13 @@ void NetPlayDiag::OnConfigPads(wxCommandEvent&) if (false == netplay_server->GetPadMapping(pid, mapping)) return; + if (false == netplay_server->GetWiimoteMapping(pid, wiimotemapping)) + return; - PadMapDiag pmd(this, mapping); + PadMapDiag pmd(this, mapping, wiimotemapping); pmd.ShowModal(); - if (false == netplay_server->SetPadMapping(pid, mapping)) + if (false == netplay_server->SetPadMapping(pid, mapping) || false == netplay_server->SetWiimoteMapping(pid, wiimotemapping)) PanicAlertT("Could not set pads. The player left or the game is currently running!\n" "(setting pads while the game is running is not yet supported)"); } @@ -605,9 +608,9 @@ void ChangeGameDiag::OnPick(wxCommandEvent& event) EndModal(wxID_OK); } -PadMapDiag::PadMapDiag(wxWindow* const parent, int map[]) +PadMapDiag::PadMapDiag(wxWindow* const parent, int map[], int wiimotemap[]) : wxDialog(parent, wxID_ANY, _("Configure Pads"), wxDefaultPosition, wxDefaultSize) - , m_mapping(map) + , m_mapping(map), m_wiimapping(wiimotemap) { wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL); @@ -627,6 +630,11 @@ PadMapDiag::PadMapDiag(wxWindow* const parent, int map[]) for (unsigned int i=1; i<5; ++i) pad_names[i] = wxString(_("Pad ")) + (wxChar)(wxT('0')+i); + wxString wiimote_names[5]; + wiimote_names[0] = _("None"); + for (unsigned int i=1; i < 5; ++i) + wiimote_names[i] = wxString(_("Wiimote ")) + (wxChar)(wxT('0')+i); + for (unsigned int i=0; i<4; ++i) { wxChoice* const pad_cbox = m_map_cbox[i] @@ -642,6 +650,21 @@ PadMapDiag::PadMapDiag(wxWindow* const parent, int map[]) h_szr->Add(v_szr, 1, wxTOP | wxEXPAND, 20); } + for (unsigned int i=0; i<4; ++i) + { + wxChoice* const wiimote_cbox = m_map_cbox[i+4] + = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 5, wiimote_names); + wiimote_cbox->Select(m_wiimapping[i] + 1); + + wiimote_cbox->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &PadMapDiag::OnAdjust, this); + + wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL); + v_szr->Add(new wxStaticText(this,wxID_ANY, wiimote_names[i + 1]), 1, wxALIGN_CENTER_HORIZONTAL); + v_szr->Add(wiimote_cbox, 1); + + h_szr->Add(v_szr, 1, wxTOP | wxEXPAND, 20); + } + h_szr->AddSpacer(20); wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL); @@ -657,5 +680,8 @@ void PadMapDiag::OnAdjust(wxCommandEvent& event) { (void)event; for (unsigned int i=0; i<4; ++i) + { m_mapping[i] = m_map_cbox[i]->GetSelection() - 1; + m_wiimapping[i] = m_map_cbox[i+4]->GetSelection() - 1; + } } diff --git a/Source/Core/DolphinWX/Src/NetWindow.h b/Source/Core/DolphinWX/Src/NetWindow.h index 543c164994..89bf66fee2 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.h +++ b/Source/Core/DolphinWX/Src/NetWindow.h @@ -124,13 +124,14 @@ private: class PadMapDiag : public wxDialog { public: - PadMapDiag(wxWindow* const parent, int map[]); + PadMapDiag(wxWindow* const parent, int map[], int wiimotemap[]); private: void OnAdjust(wxCommandEvent& event); - wxChoice* m_map_cbox[4]; + wxChoice* m_map_cbox[8]; int* const m_mapping; + int* const m_wiimapping; }; #endif // _NETWINDOW_H_