Add wiimote support to netplay.

This commit is contained in:
Rachel Bryk 2013-08-06 23:48:52 -04:00
parent 88212fba67
commit d0f05291e7
11 changed files with 317 additions and 76 deletions

View File

@ -27,6 +27,7 @@ inline double round(double x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
#include "MatrixMath.h" #include "MatrixMath.h"
#include "../../Movie.h" #include "../../Movie.h"
#include "NetPlayClient.h"
namespace namespace
{ {
@ -339,7 +340,7 @@ bool Wiimote::Step()
m_rumble->controls[0]->control_ref->State(m_rumble_on); 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. // 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); UpdateButtonsStatus(has_focus);
} }
@ -397,7 +398,7 @@ void Wiimote::UpdateButtonsStatus(bool has_focus)
void Wiimote::GetCoreData(u8* const data) 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. // 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); 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()) if (!Movie::IsPlayingInput())
{ {
Movie::CheckWiimoteStatus(m_index, data, rptf, m_reg_ir.mode); Movie::CheckWiimoteStatus(m_index, data, rptf, m_reg_ir.mode);

View File

@ -158,6 +158,7 @@ private:
void WriteData(const wm_write_data* const wd); void WriteData(const wm_write_data* const wd);
void SendReadDataReply(ReadRequest& _request); void SendReadDataReply(ReadRequest& _request);
void SpeakerData(wm_speaker_data* sd); void SpeakerData(wm_speaker_data* sd);
bool NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size);
// control groups // control groups
Buttons *m_buttons, *m_dpad, *m_shake; Buttons *m_buttons, *m_dpad, *m_shake;

View File

@ -494,7 +494,6 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
for (unsigned int i = 0; i < m_WiiMotes.size(); i++) for (unsigned int i = 0; i < m_WiiMotes.size(); i++)
if (m_WiiMotes[i].IsConnected()) if (m_WiiMotes[i].IsConnected())
{ {
NetPlay_WiimoteUpdate(i);
Wiimote::Update(i); Wiimote::Update(i);
} }
m_last_ticks = now; m_last_ticks = now;

View File

@ -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) 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 // Allocate DataFrame
u8 DataFrame[1024]; u8 DataFrame[1024];

View File

@ -16,6 +16,7 @@
// for wiimote/ OSD messages // for wiimote/ OSD messages
#include "Core.h" #include "Core.h"
#include "ConfigManager.h" #include "ConfigManager.h"
#include "HW/WiimoteEmu/WiimoteEmu.h"
std::mutex crit_netplay_client; std::mutex crit_netplay_client;
static NetPlayClient * netplay_client = NULL; static NetPlayClient * netplay_client = NULL;
@ -26,6 +27,7 @@ NetSettings g_NetPlaySettings;
NetPlayClient::Player::Player() NetPlayClient::Player::Player()
{ {
memset(pad_map, -1, sizeof(pad_map)); memset(pad_map, -1, sizeof(pad_map));
memset(wiimote_map, -1, sizeof(wiimote_map));
} }
// called from ---GUI--- thread // called from ---GUI--- thread
@ -35,6 +37,8 @@ std::string NetPlayClient::Player::ToString() const
ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |"; ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |";
for (unsigned int i=0; i<4; ++i) for (unsigned int i=0; i<4; ++i)
ss << (pad_map[i]>=0 ? (char)(pad_map[i]+'1') : '-'); 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"; ss << " | " << ping << "ms";
return ss.str(); return ss.str();
} }
@ -215,6 +219,23 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
} }
break; break;
case NP_MSG_WIIMOTE_MAPPING :
{
PlayerId pid;
packet >> pid;
{
std::lock_guard<std::recursive_mutex> 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 : case NP_MSG_PAD_DATA :
{ {
PadMapping map = 0; PadMapping map = 0;
@ -227,6 +248,27 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
} }
break; 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 : case NP_MSG_PAD_BUFFER :
{ {
u32 size = 0; u32 size = 0;
@ -392,11 +434,34 @@ void NetPlayClient::SendPadState(const PadMapping local_nb, const NetPad& np)
m_socket.Send(spac); 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<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac);
}
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayClient::StartGame(const std::string &path) bool NetPlayClient::StartGame(const std::string &path)
{ {
std::lock_guard<std::recursive_mutex> lkg(m_crit.game); std::lock_guard<std::recursive_mutex> 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 // tell server i started the game
sf::Packet spac; sf::Packet spac;
spac << (MessageId)NP_MSG_START_GAME; spac << (MessageId)NP_MSG_START_GAME;
@ -423,10 +488,10 @@ bool NetPlayClient::StartGame(const std::string &path)
m_dialog->BootGame(path); m_dialog->BootGame(path);
// temporary // temporary
NetWiimote nw; //NetWiimote nw;
for (unsigned int i = 0; i<4; ++i) //for (unsigned int i = 0; i<4; ++i)
for (unsigned int f = 0; f<2; ++f) //for (unsigned int f = 0; f<2; ++f)
m_wiimote_buffer[i].Push(nw); //m_wiimote_buffer[i].Push(nw);
return true; return true;
} }
@ -449,7 +514,7 @@ void NetPlayClient::ClearBuffers()
while (m_wiimote_buffer[i].Size()) while (m_wiimote_buffer[i].Size())
m_wiimote_buffer[i].Pop(); 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; 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 // called from ---CPU--- thread
void NetPlayClient::WiimoteUpdate(int _number) bool NetPlayClient::WiimoteUpdate(int _number, u8* data, u8 size)
{ {
{ {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players); std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
// in game mapping for this local wiimote // 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? // does this local pad map in game?
if (in_game_num < 4) 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 } // unlock players
if (0 == m_wiimote_buffer[_number].Size()) NetWiimote nw;
while (!m_wiimote_buffer[_number].Pop(nw))
{ {
//PanicAlert("PANIC"); // wait for receiving thread to push some data
return; Common::SleepCurrentThread(1);
if (false == m_is_running)
return false;
} }
NetWiimote nw; // This is either a desync, or the reporting mode changed. No way to really be sure...
m_wiimote_buffer[_number].Pop(nw); 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 // TODO: break if this runs too long; it probably desynced if it runs for longer than the buffer size
i = nw.begin(), e = nw.end(); } while (nw.size != size);
for ( ; i!=e; ++i)
Core::Callback_WiimoteInterruptChannel(_number, i->channel, &(*i)[0], (u32)i->size() + RPT_SIZE_HACK); // 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) // called from ---GUI--- thread and ---NETPLAY--- thread (client side)
@ -586,12 +673,9 @@ bool NetPlayClient::StopGame()
u8 NetPlayClient::GetPadNum(u8 numPAD) u8 NetPlayClient::GetPadNum(u8 numPAD)
{ {
// TODO: i don't like that this loop is running everytime there is rumble // TODO: i don't like that this loop is running everytime there is rumble
unsigned int i = 0; for (unsigned int i = 0; i<4; ++i)
for (; i<4; ++i)
if (numPAD == m_local_player->pad_map[i]) if (numPAD == m_local_player->pad_map[i])
break; return i;
return i;
} }
// stuff hacked into dolphin // stuff hacked into dolphin
@ -608,6 +692,16 @@ bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u
return false; return false;
} }
bool WiimoteEmu::Wiimote::NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size)
{
std::lock_guard<std::mutex> 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) bool CSIDevice_GCSteeringWheel::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
{ {
return CSIDevice_GCController::NetPlay_GetInput(numPAD, PadStatus, 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); 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 // called from ---CPU--- thread
// //
int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number) int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number)
{ {
//CritLocker crit(crit_netplay_client); // std::lock_guard<std::mutex> lk(crit_netplay_client);
//if (netplay_client) // if (netplay_client)
// return netplay_client->GetPadNum(_number); // just using gcpad mapping for now // return netplay_client->GetPadNum(_number+4);
//else // else
return _number; return _number;
} }

View File

@ -68,8 +68,7 @@ public:
void SendChatMessage(const std::string& msg); void SendChatMessage(const std::string& msg);
// Send and receive pads values // Send and receive pads values
void WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 _Size); bool WiimoteUpdate(int _number, u8* data, u8 size);
void WiimoteUpdate(int _number);
bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues); bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues);
u8 GetPadNum(u8 numPAD); u8 GetPadNum(u8 numPAD);
@ -93,6 +92,7 @@ protected:
PlayerId pid; PlayerId pid;
std::string name; std::string name;
PadMapping pad_map[4]; PadMapping pad_map[4];
PadMapping wiimote_map[4];
std::string revision; std::string revision;
u32 ping; u32 ping;
}; };
@ -119,6 +119,7 @@ protected:
private: private:
void SendPadState(const PadMapping local_nb, const NetPad& np); void SendPadState(const PadMapping local_nb, const NetPad& np);
void SendWiimoteState(const PadMapping local_nb, const NetWiimote& nw);
unsigned int OnData(sf::Packet& packet); unsigned int OnData(sf::Packet& packet);
PlayerId m_pid; PlayerId m_pid;

View File

@ -16,14 +16,13 @@ struct NetSettings
u8 m_Controllers[4]; u8 m_Controllers[4];
}; };
struct Rpt : public std::vector<u8> struct NetWiimote
{ {
u16 channel; u8 size;
std::vector<u8> data;
}; };
typedef std::vector<Rpt> NetWiimote; #define NETPLAY_VERSION "Dolphin NetPlay 2013-08-06 now with wiimote(TM)"
#define NETPLAY_VERSION "Dolphin NetPlay 2013-08-05"
// messages // messages
enum enum
@ -38,7 +37,7 @@ enum
NP_MSG_PAD_BUFFER = 0x62, NP_MSG_PAD_BUFFER = 0x62,
NP_MSG_WIIMOTE_DATA = 0x70, 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_START_GAME = 0xA0,
NP_MSG_CHANGE_GAME = 0xA1, NP_MSG_CHANGE_GAME = 0xA1,

View File

@ -7,6 +7,7 @@
NetPlayServer::Client::Client() NetPlayServer::Client::Client()
{ {
memset(pad_map, -1, sizeof(pad_map)); memset(pad_map, -1, sizeof(pad_map));
memset(wiimote_map, -1, sizeof(wiimote_map));
} }
// called from ---GUI--- thread // called from ---GUI--- thread
@ -16,6 +17,8 @@ std::string NetPlayServer::Client::ToString() const
ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |"; ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |";
for (unsigned int i=0; i<4; ++i) for (unsigned int i=0; i<4; ++i)
ss << (pad_map[i]>=0 ? (char)(pad_map[i]+'1') : '-'); 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 << '|'; ss << '|';
return ss.str(); return ss.str();
} }
@ -311,6 +314,27 @@ bool NetPlayServer::GetPadMapping(const int pid, int map[])
return true; return true;
} }
bool NetPlayServer::GetWiimoteMapping(const int pid, int map[])
{
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::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 // called from ---GUI--- thread
bool NetPlayServer::SetPadMapping(const int pid, const int map[]) bool NetPlayServer::SetPadMapping(const int pid, const int map[])
{ {
@ -351,6 +375,46 @@ bool NetPlayServer::SetPadMapping(const int pid, const int map[])
return true; return true;
} }
// called from ---GUI--- thread
bool NetPlayServer::SetWiimoteMapping(const int pid, const int map[])
{
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (m_is_running)
return false;
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::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<std::recursive_mutex> lks(m_crit.send);
UpdateWiimoteMapping(); // sync pad mappings with everyone
return true;
}
// called from ---NETPLAY--- thread // called from ---NETPLAY--- thread
void NetPlayServer::UpdatePadMapping() void NetPlayServer::UpdatePadMapping()
{ {
@ -369,6 +433,24 @@ void NetPlayServer::UpdatePadMapping()
} }
// called from ---NETPLAY--- thread
void NetPlayServer::UpdateWiimoteMapping()
{
std::map<sf::SocketTCP, Client>::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 // called from ---GUI--- thread and ---NETPLAY--- thread
void NetPlayServer::AdjustPadBufferSize(unsigned int size) 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]; map = player.pad_map[(unsigned)map];
else else
map = -1; map = -1;
// if not, they are hacking, so disconnect them // if not, they are hacking, so disconnect them
// this could happen right after a pad map change, but that isn't implemented yet // this could happen right after a pad map change, but that isn't implemented yet
if (map < 0) if (map < 0)
return 1; return 1;
// relay to clients // relay to clients
sf::Packet spac; sf::Packet spac;
@ -449,6 +531,45 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
} }
break; 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<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid);
}
break;
case NP_MSG_PONG : case NP_MSG_PONG :
{ {
const u32 ping = m_ping_timer.GetTimeElapsed(); const u32 ping = m_ping_timer.GetTimeElapsed();

View File

@ -40,6 +40,9 @@ public:
bool GetPadMapping(const int pid, int map[]); bool GetPadMapping(const int pid, int map[]);
bool SetPadMapping(const int pid, const 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); void AdjustPadBufferSize(unsigned int size);
bool is_connected; bool is_connected;
@ -58,6 +61,7 @@ private:
PlayerId pid; PlayerId pid;
std::string name; std::string name;
PadMapping pad_map[4]; PadMapping pad_map[4];
PadMapping wiimote_map[4];
std::string revision; std::string revision;
sf::SocketTCP socket; sf::SocketTCP socket;
@ -70,6 +74,7 @@ private:
unsigned int OnDisconnect(sf::SocketTCP& socket); unsigned int OnDisconnect(sf::SocketTCP& socket);
unsigned int OnData(sf::Packet& packet, sf::SocketTCP& socket); unsigned int OnData(sf::Packet& packet, sf::SocketTCP& socket);
void UpdatePadMapping(); void UpdatePadMapping();
void UpdateWiimoteMapping();
NetSettings m_settings; NetSettings m_settings;

View File

@ -106,11 +106,11 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
" - DSP Emulator Engine Must be the same on all computers!\n" " - DSP Emulator Engine Must be the same on all computers!\n"
" - DSP on Dedicated Thread [OFF]\n" " - DSP on Dedicated Thread [OFF]\n"
" - Framelimit NOT set to [Audio]\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" "\n"
"All players should use the same Dolphin version and settings.\n" "All players should use the same Dolphin version and settings.\n"
"All memory cards must be identical between players or disabled.\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" "\n"
"The host must have the chosen TCP port open/forwarded!\n"), "The host must have the chosen TCP port open/forwarded!\n"),
wxDefaultPosition, wxDefaultSize); wxDefaultPosition, wxDefaultSize);
@ -560,6 +560,7 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&)
void NetPlayDiag::OnConfigPads(wxCommandEvent&) void NetPlayDiag::OnConfigPads(wxCommandEvent&)
{ {
int mapping[4]; int mapping[4];
int wiimotemapping[4];
// get selected player id // get selected player id
int pid = m_player_lbox->GetSelection(); int pid = m_player_lbox->GetSelection();
@ -569,11 +570,13 @@ void NetPlayDiag::OnConfigPads(wxCommandEvent&)
if (false == netplay_server->GetPadMapping(pid, mapping)) if (false == netplay_server->GetPadMapping(pid, mapping))
return; return;
if (false == netplay_server->GetWiimoteMapping(pid, wiimotemapping))
return;
PadMapDiag pmd(this, mapping); PadMapDiag pmd(this, mapping, wiimotemapping);
pmd.ShowModal(); 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" 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)"); "(setting pads while the game is running is not yet supported)");
} }
@ -605,9 +608,9 @@ void ChangeGameDiag::OnPick(wxCommandEvent& event)
EndModal(wxID_OK); 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) : wxDialog(parent, wxID_ANY, _("Configure Pads"), wxDefaultPosition, wxDefaultSize)
, m_mapping(map) , m_mapping(map), m_wiimapping(wiimotemap)
{ {
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL); 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) for (unsigned int i=1; i<5; ++i)
pad_names[i] = wxString(_("Pad ")) + (wxChar)(wxT('0')+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) for (unsigned int i=0; i<4; ++i)
{ {
wxChoice* const pad_cbox = m_map_cbox[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); 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); h_szr->AddSpacer(20);
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL); wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
@ -657,5 +680,8 @@ void PadMapDiag::OnAdjust(wxCommandEvent& event)
{ {
(void)event; (void)event;
for (unsigned int i=0; i<4; ++i) for (unsigned int i=0; i<4; ++i)
{
m_mapping[i] = m_map_cbox[i]->GetSelection() - 1; m_mapping[i] = m_map_cbox[i]->GetSelection() - 1;
m_wiimapping[i] = m_map_cbox[i+4]->GetSelection() - 1;
}
} }

View File

@ -124,13 +124,14 @@ private:
class PadMapDiag : public wxDialog class PadMapDiag : public wxDialog
{ {
public: public:
PadMapDiag(wxWindow* const parent, int map[]); PadMapDiag(wxWindow* const parent, int map[], int wiimotemap[]);
private: private:
void OnAdjust(wxCommandEvent& event); void OnAdjust(wxCommandEvent& event);
wxChoice* m_map_cbox[4]; wxChoice* m_map_cbox[8];
int* const m_mapping; int* const m_mapping;
int* const m_wiimapping;
}; };
#endif // _NETWINDOW_H_ #endif // _NETWINDOW_H_