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 13ae6bd1b2..ecf84cf31e 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 @@ -465,7 +465,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..9b57f96a2c 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 @@ -265,7 +265,7 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size) _dbg_assert_msg_(WII_IPC_WIIMOTE, DoesChannelExist(pHeader->dcid), "L2CAP: SendACLPacket to unknown channel %i", pHeader->dcid); CChannelMap::iterator itr= m_Channel.find(pHeader->dcid); - const int number = NetPlay_GetWiimoteNum(m_ConnectionHandle & 0xFF); + const int number = m_ConnectionHandle & 0xFF; if (itr != m_Channel.end()) { @@ -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/IPC_HLE/WII_IPC_HLE_WiiMote.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h index 691fc84011..397841a2f0 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 @@ -56,7 +56,6 @@ public: 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(); diff --git a/Source/Core/Core/Src/NetPlayClient.cpp b/Source/Core/Core/Src/NetPlayClient.cpp index bc6ca9d393..d20c726a17 100644 --- a/Source/Core/Core/Src/NetPlayClient.cpp +++ b/Source/Core/Core/Src/NetPlayClient.cpp @@ -18,6 +18,7 @@ #include "Core.h" #include "ConfigManager.h" #include "Movie.h" +#include "HW/WiimoteEmu/WiimoteEmu.h" std::mutex crit_netplay_client; static NetPlayClient * netplay_client = NULL; @@ -195,6 +196,15 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) } break; + case NP_MSG_WIIMOTE_MAPPING : + { + for (PadMapping i = 0; i < 4; i++) + packet >> m_wiimote_map[i]; + + m_dialog->Update(); + } + break; + case NP_MSG_PAD_DATA : { PadMapping map = 0; @@ -207,6 +217,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.resize(size); + u8* data = new u8[size]; + for (unsigned int i = 0; i < size; ++i) + packet >> data[i]; + nw.assign(data,data+size); + delete[] data; + + // trusting server for good map value (>=0 && <4) + // add to wiimote buffer + m_wiimote_buffer[(unsigned)map].Push(nw); + } + break; + + case NP_MSG_PAD_BUFFER : { u32 size = 0; @@ -353,6 +384,13 @@ void NetPlayClient::GetPlayerList(std::string& list, std::vector& pid_list) else ss << '-'; } + for (unsigned int j = 0; j < 4; j++) + { + if (m_wiimote_map[j] == player->pid) + ss << j + 1; + else + ss << '-'; + } ss << " | " << player->ping << "ms\n"; pid_list.push_back(player->pid); } @@ -399,6 +437,22 @@ void NetPlayClient::SendPadState(const PadMapping in_game_pad, const NetPad& np) m_socket.Send(spac); } +// called from ---CPU--- thread +void NetPlayClient::SendWiimoteState(const PadMapping in_game_pad, const NetWiimote& nw) +{ + // send to server + sf::Packet spac; + spac << (MessageId)NP_MSG_WIIMOTE_DATA; + spac << in_game_pad; + u8 size = nw.size(); + spac << size; + for (unsigned int i = 0; i < size; ++i) + spac << nw.data()[i]; + + std::lock_guard lks(m_crit.send); + m_socket.Send(spac); +} + // called from ---GUI--- thread bool NetPlayClient::StartGame(const std::string &path) { @@ -446,11 +500,17 @@ bool NetPlayClient::StartGame(const std::string &path) UpdateDevices(); - // temporary + // Needed to prevent locking up at boot if (when) the wiimotes connect out of order. NetWiimote nw; - for (unsigned int i = 0; i<4; ++i) - for (unsigned int f = 0; f<2; ++f) - m_wiimote_buffer[i].Push(nw); + nw.resize(4, 0); + + for (unsigned int w = 0; w < 4; ++w) + { + if (m_wiimote_map[w] != -1) + // probably overkill, but whatever + for (unsigned int i = 0; i < 7; ++i) + m_wiimote_buffer[w].Push(nw); + } return true; } @@ -482,8 +542,6 @@ void NetPlayClient::ClearBuffers() while (m_wiimote_buffer[i].Size()) m_wiimote_buffer[i].Pop(); - - m_wiimote_input[i].clear(); } } @@ -570,16 +628,95 @@ 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) -{ - // XXX -} // called from ---CPU--- thread -void NetPlayClient::WiimoteUpdate(int _number) +bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size) { - // XXX + NetWiimote nw; + static u8 previousSize[4] = {4,4,4,4}; + { + std::lock_guard lkp(m_crit.players); + + // in game mapping for this local wiimote + unsigned int in_game_num = LocalWiimoteToInGameWiimote(_number); + + // does this local wiimote map in game? + if (in_game_num < 4) + { + if (previousSize[in_game_num] == size) + { + nw.assign(data, data + size); + do + { + // add to buffer + m_wiimote_buffer[in_game_num].Push(nw); + + SendWiimoteState(in_game_num, nw); + } while (m_wiimote_buffer[in_game_num].Size() <= m_target_buffer_size * 200 / 120); // TODO: add a seperate setting for wiimote buffer? + } + else + { + while (m_wiimote_buffer[in_game_num].Size() > 0) + { + // Reporting mode changed, so previous buffer is no good. + m_wiimote_buffer[in_game_num].Pop(); + } + nw.resize(size, 0); + + m_wiimote_buffer[in_game_num].Push(nw); + m_wiimote_buffer[in_game_num].Push(nw); + m_wiimote_buffer[in_game_num].Push(nw); + previousSize[in_game_num] = size; + } + } + + } // unlock players + + while (previousSize[_number] == size && !m_wiimote_buffer[_number].Pop(nw)) + { + // wait for receiving thread to push some data + Common::SleepCurrentThread(1); + if (false == m_is_running) + return false; + } + + // Use a blank input, since we may not have any valid input. + if (previousSize[_number] != size) + { + nw.resize(size, 0); + m_wiimote_buffer[_number].Push(nw); + m_wiimote_buffer[_number].Push(nw); + } + + // We should have used a blank input last time, so now we just need to pop through the old buffer, until we reach a good input + if (nw.size() != size) + { + u8 tries = 0; + // Clear the buffer and wait for new input, since we probably just changed reporting mode. + while (nw.size() != size) + { + while (!m_wiimote_buffer[_number].Pop(nw)) + { + Common::SleepCurrentThread(1); + if (false == m_is_running) + return false; + } + ++tries; + if (tries > m_target_buffer_size * 200 / 120) + break; + } + + // If it still mismatches, it surely desynced + if (size != nw.size()) + { + PanicAlert("Netplay has desynced. There is no way to recover from this."); + return false; + } + } + + previousSize[_number] = size; + memcpy(data, nw.data(), size); + return true; } // called from ---GUI--- thread and ---NETPLAY--- thread (client side) @@ -614,6 +751,11 @@ void NetPlayClient::Stop() if (m_pad_map[i] == m_local_player->pid) isPadMapped = true; } + for (unsigned int i = 0; i < 4; ++i) + { + if (m_wiimote_map[i] == m_local_player->pid) + isPadMapped = true; + } // tell the server to stop if we have a pad mapped in game. if (isPadMapped) { @@ -660,6 +802,25 @@ u8 NetPlayClient::LocalPadToInGamePad(u8 local_pad) return ingame_pad; } +u8 NetPlayClient::LocalWiimoteToInGameWiimote(u8 local_pad) +{ + // Figure out which in-game pad maps to which local pad. + // The logic we have here is that the local slots always + // go in order. + int local_pad_count = -1; + int ingame_pad = 0; + for (; ingame_pad < 4; ingame_pad++) + { + if (m_wiimote_map[ingame_pad] == m_local_player->pid) + local_pad_count++; + + if (local_pad_count == local_pad) + break; + } + + return ingame_pad; +} + // stuff hacked into dolphin // called from ---CPU--- thread @@ -674,6 +835,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); @@ -718,33 +889,6 @@ u8 CSIDevice_DanceMat::NetPlay_InGamePadToLocalPad(u8 numPAD) return CSIDevice_GCController::NetPlay_InGamePadToLocalPad(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) -{ -} - -// called from ---CPU--- thread -// -int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number) -{ - 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) -bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&) -{ - std::lock_guard lk(crit_netplay_client); - - if (netplay_client) - return true; - else - return false; -} - bool NetPlay::IsNetPlayRunning() { return netplay_client != NULL; diff --git a/Source/Core/Core/Src/NetPlayClient.h b/Source/Core/Core/Src/NetPlayClient.h index fa53154b7e..18509cf8c0 100644 --- a/Source/Core/Core/Src/NetPlayClient.h +++ b/Source/Core/Core/Src/NetPlayClient.h @@ -78,13 +78,14 @@ 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, const u8 size); bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); u8 LocalPadToInGamePad(u8 localPad); u8 InGamePadToLocalPad(u8 localPad); + u8 LocalWiimoteToInGameWiimote(u8 local_pad); + protected: void ClearBuffers(); @@ -98,8 +99,6 @@ protected: Common::FifoQueue m_pad_buffer[4]; Common::FifoQueue m_wiimote_buffer[4]; - NetWiimote m_wiimote_input[4]; - NetPlayUI* m_dialog; sf::SocketTCP m_socket; std::thread m_thread; @@ -116,12 +115,14 @@ protected: u32 m_current_game; PadMapping m_pad_map[4]; + PadMapping m_wiimote_map[4]; bool m_is_recording; private: void UpdateDevices(); void SendPadState(const PadMapping in_game_pad, const NetPad& np); + void SendWiimoteState(const PadMapping in_game_pad, 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 2b4c49d97c..6fe6899b87 100644 --- a/Source/Core/Core/Src/NetPlayProto.h +++ b/Source/Core/Core/Src/NetPlayProto.h @@ -25,12 +25,13 @@ struct Rpt : public std::vector u16 channel; }; -typedef std::vector NetWiimote; +typedef std::vector NetWiimote; -#define NETPLAY_VERSION "Dolphin NetPlay 2013-09-03" +#define NETPLAY_VERSION "Dolphin NetPlay 2013-09-22" const int NETPLAY_INITIAL_GCTIME = 1272737767; + // messages enum { @@ -44,7 +45,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 5abf805fe5..f78bfe43ef 100644 --- a/Source/Core/Core/Src/NetPlayServer.cpp +++ b/Source/Core/Core/Src/NetPlayServer.cpp @@ -25,12 +25,14 @@ NetPlayServer::~NetPlayServer() NetPlayServer::NetPlayServer(const u16 port) : is_connected(false), m_is_running(false) { memset(m_pad_map, -1, sizeof(m_pad_map)); + memset(m_wiimote_map, -1, sizeof(m_wiimote_map)); if (m_socket.Listen(port)) { is_connected = true; m_do_loop = true; m_selector.Add(m_socket); m_thread = std::thread(std::mem_fun(&NetPlayServer::ThreadFunc), this); + m_target_buffer_size = 20; } } @@ -213,6 +215,7 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) m_players[socket] = player; std::lock_guard lks(m_crit.send); UpdatePadMapping(); // sync pad mappings with everyone + UpdateWiimoteMapping(); } @@ -258,6 +261,11 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket) m_pad_map[i] = -1; UpdatePadMapping(); + for (int i = 0; i < 4; i++) + if (m_wiimote_map[i] == pid) + m_wiimote_map[i] = -1; + UpdateWiimoteMapping(); + return 0; } @@ -268,6 +276,12 @@ void NetPlayServer::GetPadMapping(PadMapping map[4]) map[i] = m_pad_map[i]; } +void NetPlayServer::GetWiimoteMapping(PadMapping map[4]) +{ + for (int i = 0; i < 4; i++) + map[i] = m_wiimote_map[i]; +} + // called from ---GUI--- thread void NetPlayServer::SetPadMapping(const PadMapping map[4]) { @@ -276,6 +290,14 @@ void NetPlayServer::SetPadMapping(const PadMapping map[4]) UpdatePadMapping(); } +// called from ---GUI--- thread +void NetPlayServer::SetWiimoteMapping(const PadMapping map[4]) +{ + for (int i = 0; i < 4; i++) + m_wiimote_map[i] = map[i]; + UpdateWiimoteMapping(); +} + // called from ---GUI--- thread and ---NETPLAY--- thread void NetPlayServer::UpdatePadMapping() { @@ -286,6 +308,16 @@ void NetPlayServer::UpdatePadMapping() SendToClients(spac); } +// called from ---NETPLAY--- thread +void NetPlayServer::UpdateWiimoteMapping() +{ + sf::Packet spac; + spac << (MessageId)NP_MSG_WIIMOTE_MAPPING; + for (int i = 0; i < 4; i++) + spac << m_wiimote_map[i]; + SendToClients(spac); +} + // called from ---GUI--- thread and ---NETPLAY--- thread void NetPlayServer::AdjustPadBufferSize(unsigned int size) { @@ -358,6 +390,39 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) } break; + case NP_MSG_WIIMOTE_DATA : + { + // if this is wiimote 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]; + + // If the data is not from the correct player, + // then disconnect them. + if (m_wiimote_map[map] != player.pid) + return 1; + + // relay to clients + sf::Packet spac; + spac << (MessageId)NP_MSG_WIIMOTE_DATA; + spac << map; + 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 5349764790..13acbcfb2b 100644 --- a/Source/Core/Core/Src/NetPlayServer.h +++ b/Source/Core/Core/Src/NetPlayServer.h @@ -37,6 +37,9 @@ public: void GetPadMapping(PadMapping map[]); void SetPadMapping(const PadMapping map[]); + void GetWiimoteMapping(PadMapping map[]); + void SetWiimoteMapping(const PadMapping map[]); + void AdjustPadBufferSize(unsigned int size); bool is_connected; @@ -63,6 +66,7 @@ private: unsigned int OnDisconnect(sf::SocketTCP& socket); unsigned int OnData(sf::Packet& packet, sf::SocketTCP& socket); void UpdatePadMapping(); + void UpdateWiimoteMapping(); NetSettings m_settings; @@ -74,6 +78,7 @@ private: u32 m_current_game; unsigned int m_target_buffer_size; PadMapping m_pad_map[4]; + PadMapping m_wiimote_map[4]; std::map m_players; diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index c7ef839198..7f48455ef7 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -107,10 +107,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 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); @@ -562,12 +563,15 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&) void NetPlayDiag::OnConfigPads(wxCommandEvent&) { PadMapping mapping[4]; + PadMapping wiimotemapping[4]; std::vector player_list; netplay_server->GetPadMapping(mapping); + netplay_server->GetWiimoteMapping(wiimotemapping); netplay_client->GetPlayers(player_list); - PadMapDiag pmd(this, mapping, player_list); + PadMapDiag pmd(this, mapping, wiimotemapping, player_list); pmd.ShowModal(); netplay_server->SetPadMapping(mapping); + netplay_server->SetWiimoteMapping(wiimotemapping); } bool NetPlayDiag::IsRecording() @@ -602,9 +606,10 @@ void ChangeGameDiag::OnPick(wxCommandEvent& event) EndModal(wxID_OK); } -PadMapDiag::PadMapDiag(wxWindow* const parent, PadMapping map[], std::vector& player_list) +PadMapDiag::PadMapDiag(wxWindow* const parent, PadMapping map[], PadMapping wiimotemap[], std::vector& player_list) : wxDialog(parent, wxID_ANY, _("Configure Pads"), wxDefaultPosition, wxDefaultSize) , m_mapping(map) + , m_wiimapping (wiimotemap) , m_player_list(player_list) { wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL); @@ -615,6 +620,11 @@ PadMapDiag::PadMapDiag(wxWindow* const parent, PadMapping map[], std::vectorname); + 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) { wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL); @@ -636,6 +646,27 @@ PadMapDiag::PadMapDiag(wxWindow* const parent, PadMapping map[], std::vectorAddSpacer(10); } + for (unsigned int i=0; i<4; ++i) + { + wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL); + v_szr->Add(new wxStaticText(this, wxID_ANY, (wxString(_("Wiimote ")) + (wxChar)(wxT('0')+i))), + 1, wxALIGN_CENTER_HORIZONTAL); + + m_map_cbox[i+4] = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, player_names); + m_map_cbox[i+4]->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &PadMapDiag::OnAdjust, this); + if (m_wiimapping[i] == -1) + m_map_cbox[i+4]->Select(0); + else + for (unsigned int j = 0; j < m_player_list.size(); j++) + if (m_wiimapping[i] == m_player_list[j]->pid) + m_map_cbox[i+4]->Select(j + 1); + + v_szr->Add(m_map_cbox[i+4], 1); + + h_szr->Add(v_szr, 1, wxTOP | wxEXPAND, 20); + h_szr->AddSpacer(10); + } + wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL); main_szr->Add(h_szr); main_szr->AddSpacer(5); @@ -655,6 +686,12 @@ void PadMapDiag::OnAdjust(wxCommandEvent& event) m_mapping[i] = m_player_list[player_idx - 1]->pid; else m_mapping[i] = -1; + + player_idx = m_map_cbox[i+4]->GetSelection(); + if (player_idx > 0) + m_wiimapping[i] = m_player_list[player_idx - 1]->pid; + else + m_wiimapping[i] = -1; } } diff --git a/Source/Core/DolphinWX/Src/NetWindow.h b/Source/Core/DolphinWX/Src/NetWindow.h index f271f12afe..0e55862259 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.h +++ b/Source/Core/DolphinWX/Src/NetWindow.h @@ -127,13 +127,14 @@ private: class PadMapDiag : public wxDialog { public: - PadMapDiag(wxWindow* const parent, PadMapping map[], std::vector& player_list); + PadMapDiag(wxWindow* const parent, PadMapping map[], PadMapping wiimotemap[], std::vector& player_list); private: void OnAdjust(wxCommandEvent& event); - wxChoice* m_map_cbox[4]; + wxChoice* m_map_cbox[8]; PadMapping* const m_mapping; + PadMapping* const m_wiimapping; std::vector& m_player_list; };