Made new Wiimote plugin not deinit SDL on shutdown. (Hacks, same thing old wiimote does, fixes the crash on emulation stop, refresh button still causes crash (damn SDL)) Minor new input plugin GUI changes. (left-click on rumble button opens control config dialog) Made NetPlay save/load settings to Dolphin.ini. Allow NetPlay host to adjust which/how many pads will be used in game. (more than one gamepad per Dolphin instance can be used on NetPlay) Worked on wiimote NetPlay a bit. (still nonfunctional) Improved SDL device numbering. Added some major hacks to ControllerInterface/SDL so XInput(360 controller) devices do not have their SDL interface shown in the device list on windows. (caused confusion for users)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5625 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
1aac546185
commit
5341bbad3a
|
@ -59,6 +59,8 @@ namespace Core
|
|||
// Get core parameters kill use SConfig instead
|
||||
extern SCoreStartupParameter g_CoreStartupParameter;
|
||||
|
||||
void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size);
|
||||
|
||||
void* GetWindowHandle();
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
void* GetXWindow();
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "HW/EXI_DeviceIPL.h"
|
||||
// to start/stop game
|
||||
#include "Frame.h"
|
||||
// for OSD msgs
|
||||
// for wiimote/ OSD messages
|
||||
#include "Core.h"
|
||||
|
||||
Common::CriticalSection crit_netplay_ptr;
|
||||
|
@ -44,17 +44,6 @@ 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)
|
||||
|
@ -80,6 +69,10 @@ NetPlay::~NetPlay()
|
|||
{
|
||||
CritLocker crit(crit_netplay_ptr);
|
||||
::netplay_ptr = NULL;
|
||||
|
||||
// not perfect
|
||||
if (m_is_running)
|
||||
StopGame();
|
||||
}
|
||||
|
||||
NetPlay::Player::Player()
|
||||
|
@ -145,6 +138,9 @@ void NetPlay::ClearBuffers()
|
|||
{
|
||||
while (m_pad_buffer[i].size())
|
||||
m_pad_buffer[i].pop();
|
||||
while (m_wiimote_buffer[i].size())
|
||||
m_wiimote_buffer[i].pop();
|
||||
m_wiimote_input[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,46 +208,63 @@ bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, Ne
|
|||
// called from ---CPU--- thread
|
||||
void NetPlay::WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
//m_crit.players.Enter(); // lock 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->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);
|
||||
// does this local pad map in game?
|
||||
if (in_game_num < 4)
|
||||
{
|
||||
m_crit.buffer.Enter();
|
||||
|
||||
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;
|
||||
|
||||
// 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);
|
||||
m_crit.buffer.Leave();
|
||||
}
|
||||
|
||||
m_crit.players.Leave();
|
||||
}
|
||||
|
||||
// called from ---CPU--- thread
|
||||
void NetPlay::WiimoteUpdate(int _number)
|
||||
{
|
||||
// temporary
|
||||
if (_number)
|
||||
m_crit.players.Enter(); // lock 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
|
||||
|
||||
// does this local pad map in game?
|
||||
if (in_game_num < 4)
|
||||
{
|
||||
m_crit.buffer.Enter();
|
||||
m_wiimote_buffer[in_game_num].push(m_wiimote_input[_number]);
|
||||
|
||||
// TODO: send it
|
||||
|
||||
m_wiimote_input[_number].clear();
|
||||
m_crit.buffer.Leave();
|
||||
}
|
||||
|
||||
m_crit.players.Leave();
|
||||
|
||||
m_crit.buffer.Enter();
|
||||
|
||||
if (0 == m_wiimote_buffer[_number].size())
|
||||
{
|
||||
//PanicAlert("PANIC");
|
||||
return;
|
||||
}
|
||||
|
||||
m_crit.buffer.Enter(); // lock buffer
|
||||
++m_wiimote_update_frame;
|
||||
NetWiimote& nw = m_wiimote_buffer[_number].front();
|
||||
|
||||
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);
|
||||
|
||||
m_wiimote_buffer[_number].pop();
|
||||
m_crit.buffer.Leave();
|
||||
|
||||
// TODO: prolly do some wiimote input here
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
|
@ -274,6 +287,14 @@ bool NetPlay::StartGame(const std::string &path)
|
|||
::main_frame->BootGame(path);
|
||||
//BootManager::BootCore(path);
|
||||
|
||||
// TODO: i dont know if i like this here
|
||||
ClearBuffers();
|
||||
// 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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -353,20 +374,21 @@ u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD)
|
|||
// wiimote update / used for frame counting
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::NetPlay_WiimoteUpdate(int _number)
|
||||
{
|
||||
CritLocker crit(::crit_netplay_ptr);
|
||||
//CritLocker crit(::crit_netplay_ptr);
|
||||
|
||||
return;
|
||||
//if (::netplay_ptr)
|
||||
// ::netplay_ptr->WiimoteUpdate(_number);
|
||||
}
|
||||
|
||||
// called from ---CPU--- thread
|
||||
//
|
||||
int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number)
|
||||
{
|
||||
CritLocker crit(::crit_netplay_ptr);
|
||||
//CritLocker crit(::crit_netplay_ptr);
|
||||
|
||||
if (::netplay_ptr)
|
||||
return ::netplay_ptr->GetPadNum(_number); // just using gcpad mapping for now
|
||||
else
|
||||
//if (::netplay_ptr)
|
||||
// return ::netplay_ptr->GetPadNum(_number); // just using gcpad mapping for now
|
||||
//else
|
||||
return _number;
|
||||
}
|
||||
|
||||
|
@ -377,18 +399,19 @@ bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int _number, u16 _channelID, con
|
|||
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);
|
||||
//{
|
||||
// if (_Size >= RPT_SIZE_HACK)
|
||||
// {
|
||||
// _Size -= RPT_SIZE_HACK;
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ::netplay_ptr->WiimoteInput(_number, _channelID, _pData, _Size);
|
||||
// // don't use this packet
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// }
|
||||
//}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -32,16 +32,13 @@ public:
|
|||
u32 nLo;
|
||||
};
|
||||
|
||||
class NetWiimote
|
||||
struct Rpt : public std::vector<u8>
|
||||
{
|
||||
public:
|
||||
NetWiimote& operator=(const NetWiimote&);
|
||||
NetWiimote(const u32 _size) : size(_size), data(new u8[size]) {}
|
||||
|
||||
const u32 size;
|
||||
u8* const data;
|
||||
u16 channel;
|
||||
};
|
||||
|
||||
typedef std::vector<Rpt> NetWiimote;
|
||||
|
||||
#define NETPLAY_VERSION "Dolphin NetPlay 2.2"
|
||||
|
||||
#ifdef _M_X64
|
||||
|
@ -124,7 +121,7 @@ public:
|
|||
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 GetPlayerList(std::string& list, std::vector<int>& pid_list) = 0;
|
||||
virtual void SendChatMessage(const std::string& msg) = 0;
|
||||
|
||||
virtual bool StartGame(const std::string &path);
|
||||
|
@ -161,11 +158,10 @@ protected:
|
|||
std::string revision;
|
||||
};
|
||||
|
||||
//LockingQueue<NetPad> m_pad_buffer[4];
|
||||
std::queue<NetPad> m_pad_buffer[4];
|
||||
std::map<FrameNum, NetWiimote> m_wiimote_buffer[4];
|
||||
std::queue<NetPad> m_pad_buffer[4];
|
||||
std::queue<NetWiimote> m_wiimote_buffer[4];
|
||||
|
||||
FrameNum m_wiimote_update_frame;
|
||||
NetWiimote m_wiimote_input[4];
|
||||
|
||||
NetPlayDiag* m_dialog;
|
||||
sf::SocketTCP m_socket;
|
||||
|
@ -197,7 +193,7 @@ public:
|
|||
NetPlayServer(const u16 port, const std::string& name, NetPlayDiag* const npd = NULL, const std::string& game = "");
|
||||
~NetPlayServer();
|
||||
|
||||
void GetPlayerList(std::string& list);
|
||||
void GetPlayerList(std::string& list, std::vector<int>& pid_list);
|
||||
|
||||
// Send and receive pads values
|
||||
//bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues);
|
||||
|
@ -207,6 +203,9 @@ public:
|
|||
bool StartGame(const std::string &path);
|
||||
bool StopGame();
|
||||
|
||||
bool GetPadMapping(const int pid, int map[]);
|
||||
bool SetPadMapping(const int pid, const int map[]);
|
||||
|
||||
u64 CalculateMinimumBufferTime();
|
||||
void AdjustPadBufferSize(unsigned int size);
|
||||
|
||||
|
@ -226,6 +225,7 @@ private:
|
|||
unsigned int OnConnect(sf::SocketTCP& socket);
|
||||
unsigned int OnDisconnect(sf::SocketTCP& socket);
|
||||
unsigned int OnData(sf::Packet& packet, sf::SocketTCP& socket);
|
||||
void UpdatePadMapping();
|
||||
|
||||
std::map<sf::SocketTCP, Client> m_players;
|
||||
|
||||
|
@ -242,7 +242,7 @@ public:
|
|||
NetPlayClient(const std::string& address, const u16 port, const std::string& name, NetPlayDiag* const npd = NULL);
|
||||
~NetPlayClient();
|
||||
|
||||
void GetPlayerList(std::string& list);
|
||||
void GetPlayerList(std::string& list, std::vector<int>& pid_list);
|
||||
|
||||
// Send and receive pads values
|
||||
//bool GetNetPads(const u8 pad_nb, const SPADStatus* const, NetPad* const netvalues);
|
||||
|
|
|
@ -19,7 +19,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, const s
|
|||
is_connected = false;
|
||||
|
||||
// why is false successful? documentation says true is
|
||||
if (0 == m_socket.Connect(port, address))
|
||||
if (0 == m_socket.Connect(port, address, 5))
|
||||
{
|
||||
// send connect message
|
||||
sf::Packet spac;
|
||||
|
@ -193,7 +193,9 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||
|
||||
case NP_MSG_START_GAME :
|
||||
{
|
||||
m_crit.buffer.Enter(); // lock buffer
|
||||
packet >> m_on_game;
|
||||
m_crit.buffer.Leave();
|
||||
|
||||
wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_START_GAME);
|
||||
m_dialog->GetEventHandler()->AddPendingEvent(evt);
|
||||
|
@ -209,7 +211,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
|||
|
||||
case NP_MSG_DISABLE_GAME :
|
||||
{
|
||||
PanicAlert("Other client disconnected while game is running!! NetPlay is disabled. You must manually stop the game.");
|
||||
PanicAlert("Other client disconnected while game is running!! NetPlay is disabled. You manually stop the game.");
|
||||
CritLocker game_lock(m_crit.game); // lock game state
|
||||
m_is_running = false;
|
||||
NetPlay_Disable();
|
||||
|
@ -257,7 +259,7 @@ void NetPlayClient::Entry()
|
|||
default :
|
||||
m_is_running = false;
|
||||
NetPlay_Disable();
|
||||
AppendChatGUI("< LOST CONNECION TO SERVER >");
|
||||
AppendChatGUI("< LOST CONNECTION TO SERVER >");
|
||||
PanicAlert("Lost connection to server!");
|
||||
m_do_loop = false;
|
||||
break;
|
||||
|
@ -271,7 +273,7 @@ void NetPlayClient::Entry()
|
|||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
void NetPlayClient::GetPlayerList(std::string &list)
|
||||
void NetPlayClient::GetPlayerList(std::string& list, std::vector<int>& pid_list)
|
||||
{
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
|
||||
|
@ -281,7 +283,10 @@ void NetPlayClient::GetPlayerList(std::string &list)
|
|||
i = m_players.begin(),
|
||||
e = m_players.end();
|
||||
for ( ; i!=e; ++i)
|
||||
{
|
||||
ss << i->second.ToString() << '\n';
|
||||
pid_list.push_back(i->second.pid);
|
||||
}
|
||||
|
||||
list = ss.str();
|
||||
}
|
||||
|
@ -294,9 +299,9 @@ void NetPlayClient::SendChatMessage(const std::string& msg)
|
|||
spac << (MessageId)NP_MSG_CHAT_MESSAGE;
|
||||
spac << msg;
|
||||
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
m_socket.Send(spac);
|
||||
m_crit.send.Leave();
|
||||
}
|
||||
|
||||
// called from ---CPU--- thread
|
||||
|
@ -308,9 +313,8 @@ void NetPlayClient::SendPadState(const PadMapping local_nb, const NetPad& np)
|
|||
spac << local_nb; // local pad num
|
||||
spac << np.nHi << np.nLo;
|
||||
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
m_socket.Send(spac);
|
||||
m_crit.send.Leave();
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
|
@ -321,18 +325,15 @@ bool NetPlayClient::StartGame(const std::string &path)
|
|||
if (false == NetPlay::StartGame(path))
|
||||
return false;
|
||||
|
||||
// TODO: i dont like this here
|
||||
ClearBuffers();
|
||||
m_crit.buffer.Leave();
|
||||
|
||||
// tell server i started the game
|
||||
sf::Packet spac;
|
||||
spac << (MessageId)NP_MSG_START_GAME;
|
||||
spac << m_on_game;
|
||||
|
||||
m_crit.send.Enter(); // lock send
|
||||
m_crit.buffer.Leave();
|
||||
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
m_socket.Send(spac);
|
||||
m_crit.send.Leave();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ void NetPlayServer::Entry()
|
|||
spac << (MessageId)NP_MSG_PING;
|
||||
spac << m_ping_key;
|
||||
|
||||
CritLocker player_lock(m_crit.players);
|
||||
//CritLocker player_lock(m_crit.players);
|
||||
CritLocker send_lock(m_crit.send);
|
||||
m_ping_timer.Start();
|
||||
SendToClients(spac);
|
||||
|
@ -218,14 +218,6 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
|
|||
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;
|
||||
|
@ -239,13 +231,6 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
|
|||
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
|
||||
|
@ -254,6 +239,9 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
|
|||
// add client to the player list
|
||||
m_crit.players.Enter(); // lock players
|
||||
m_players[socket] = player;
|
||||
m_crit.send.Enter(); // lock send
|
||||
UpdatePadMapping(); // sync pad mappings with everyone
|
||||
m_crit.send.Leave();
|
||||
m_crit.players.Leave();
|
||||
|
||||
// add client to selector/ used for receiving
|
||||
|
@ -277,9 +265,8 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
|
|||
sf::Packet spac;
|
||||
spac << (MessageId)NP_MSG_DISABLE_GAME;
|
||||
// this thread doesnt need players lock
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.send.Leave();
|
||||
}
|
||||
|
||||
sf::Packet spac;
|
||||
|
@ -288,20 +275,100 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
|
|||
|
||||
m_selector.Remove(socket);
|
||||
|
||||
m_crit.players.Enter(); // lock players
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
m_players.erase(m_players.find(socket));
|
||||
m_crit.players.Leave();
|
||||
|
||||
// alert other players of disconnect
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.send.Leave();
|
||||
|
||||
UpdateGUI();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
bool NetPlayServer::GetPadMapping(const int pid, int map[])
|
||||
{
|
||||
CritLocker player_lock(m_crit.players); // lock 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.pad_map[m];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
bool NetPlayServer::SetPadMapping(const int pid, const int map[])
|
||||
{
|
||||
CritLocker game_lock(m_crit.game); // lock game
|
||||
if (m_is_running)
|
||||
return false;
|
||||
|
||||
CritLocker player_lock(m_crit.players); // lock 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.pad_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.pad_map[m] == i->second.pad_map[p])
|
||||
i->second.pad_map[p] = -1;
|
||||
}
|
||||
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
UpdatePadMapping(); // sync pad mappings with everyone
|
||||
|
||||
UpdateGUI();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---NETPLAY--- thread
|
||||
void NetPlayServer::UpdatePadMapping()
|
||||
{
|
||||
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_PAD_MAPPING;
|
||||
spac << i->second.pid;
|
||||
for (unsigned int pm = 0; pm<4; ++pm)
|
||||
spac << i->second.pad_map[pm];
|
||||
SendToClients(spac);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread and ---NETPLAY--- thread
|
||||
u64 NetPlayServer::CalculateMinimumBufferTime()
|
||||
{
|
||||
|
@ -312,7 +379,7 @@ u64 NetPlayServer::CalculateMinimumBufferTime()
|
|||
e = m_players.end();
|
||||
std::priority_queue<unsigned int> pings;
|
||||
for ( ;i!=e; ++i)
|
||||
pings.push(i->second.ping);
|
||||
pings.push(i->second.ping/2);
|
||||
|
||||
unsigned int required_ms = pings.top();
|
||||
// if there is more than 1 client, buffersize must be >= (2 highest ping times combined)
|
||||
|
@ -339,11 +406,9 @@ void NetPlayServer::AdjustPadBufferSize(unsigned int size)
|
|||
spac << (MessageId)NP_MSG_PAD_BUFFER;
|
||||
spac << (u32)m_target_buffer_size;
|
||||
|
||||
m_crit.players.Enter(); // lock players
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.send.Leave();
|
||||
m_crit.players.Leave();
|
||||
}
|
||||
|
||||
// called from ---NETPLAY--- thread
|
||||
|
@ -414,9 +479,8 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
|
|||
spac << map; // in game mapping
|
||||
spac << np.nHi << np.nLo;
|
||||
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac, player.pid);
|
||||
m_crit.send.Leave();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -452,9 +516,9 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
|
|||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
void NetPlayServer::GetPlayerList(std::string &list)
|
||||
void NetPlayServer::GetPlayerList(std::string& list, std::vector<int>& pid_list)
|
||||
{
|
||||
CritLocker player_lock(m_crit.players);
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
|
||||
std::ostringstream ss;
|
||||
|
||||
|
@ -462,7 +526,10 @@ void NetPlayServer::GetPlayerList(std::string &list)
|
|||
i = m_players.begin(),
|
||||
e = m_players.end();
|
||||
for ( ; i!=e; ++i)
|
||||
{
|
||||
ss << i->second.ToString() << " " << i->second.ping << "ms\n";
|
||||
pid_list.push_back(i->second.pid);
|
||||
}
|
||||
|
||||
list = ss.str();
|
||||
}
|
||||
|
@ -475,9 +542,8 @@ void NetPlayServer::SendChatMessage(const std::string& msg)
|
|||
spac << (PlayerId)0; // server id always 0
|
||||
spac << msg;
|
||||
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.send.Leave();
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
|
@ -492,11 +558,9 @@ bool NetPlayServer::ChangeGame(const std::string &game)
|
|||
spac << (MessageId)NP_MSG_CHANGE_GAME;
|
||||
spac << game;
|
||||
|
||||
m_crit.players.Enter(); // lock players
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.send.Leave();
|
||||
m_crit.players.Leave();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -510,9 +574,8 @@ void NetPlayServer::SendPadState(const PadMapping local_nb, const NetPad& np)
|
|||
spac << m_local_player->pad_map[local_nb]; // in-game pad num
|
||||
spac << np.nHi << np.nLo;
|
||||
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.send.Leave();
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread
|
||||
|
@ -525,7 +588,6 @@ bool NetPlayServer::StartGame(const std::string &path)
|
|||
|
||||
// TODO: i dont like this here
|
||||
m_on_game = Common::Timer::GetTimeMs();
|
||||
ClearBuffers();
|
||||
m_crit.buffer.Leave();
|
||||
|
||||
// no change, just update with clients
|
||||
|
@ -536,11 +598,9 @@ bool NetPlayServer::StartGame(const std::string &path)
|
|||
spac << (MessageId)NP_MSG_START_GAME;
|
||||
spac << m_on_game;
|
||||
|
||||
m_crit.players.Enter(); // lock players
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.send.Leave();
|
||||
m_crit.players.Leave();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -556,11 +616,9 @@ bool NetPlayServer::StopGame()
|
|||
sf::Packet spac;
|
||||
spac << (MessageId)NP_MSG_STOP_GAME;
|
||||
|
||||
m_crit.players.Enter(); // lock players
|
||||
m_crit.send.Enter(); // lock send
|
||||
CritLocker player_lock(m_crit.players); // lock players
|
||||
CritLocker send_lock(m_crit.send); // lock send
|
||||
SendToClients(spac);
|
||||
m_crit.players.Leave();
|
||||
m_crit.send.Leave();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <FileUtil.h>
|
||||
#include <IniFile.h>
|
||||
|
||||
#include "NetPlay.h"
|
||||
#include "NetWindow.h"
|
||||
|
||||
|
@ -34,13 +37,18 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
|
|||
: wxFrame(parent, wxID_ANY, wxT(NETPLAY_TITLEBAR), wxDefaultPosition, wxDefaultSize)
|
||||
, m_game_list(game_list)
|
||||
{
|
||||
//PanicAlert("ALERT: NetPlay is not 100%% functional !!!!");
|
||||
IniFile inifile;
|
||||
inifile.Load(std::string(File::GetUserPath(D_CONFIG_IDX)) + "Dolphin.ini");
|
||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||
|
||||
wxPanel* const panel = new wxPanel(this);
|
||||
|
||||
// top row
|
||||
wxStaticText* const nick_lbl = new wxStaticText(panel, wxID_ANY, wxT("Nickname :"), wxDefaultPosition, wxDefaultSize);
|
||||
m_nickname_text = new wxTextCtrl(panel, wxID_ANY, wxT("Player"));
|
||||
|
||||
std::string nickname;
|
||||
netplay_section.Get("Nickname", &nickname, "Player");
|
||||
m_nickname_text = new wxTextCtrl(panel, wxID_ANY, wxString::FromAscii(nickname.c_str()));
|
||||
|
||||
wxBoxSizer* const nick_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
nick_szr->Add(nick_lbl, 0, wxCENTER);
|
||||
|
@ -58,9 +66,17 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
|
|||
// connect tab
|
||||
{
|
||||
wxStaticText* const ip_lbl = new wxStaticText(connect_tab, wxID_ANY, wxT("Address :"), wxDefaultPosition, wxDefaultSize);
|
||||
m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, wxT("localhost"));
|
||||
|
||||
std::string address;
|
||||
netplay_section.Get("Address", &address, "localhost");
|
||||
m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(address.c_str()));
|
||||
|
||||
wxStaticText* const port_lbl = new wxStaticText(connect_tab, wxID_ANY, wxT("Port :"), wxDefaultPosition, wxDefaultSize);
|
||||
m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, wxT("2626"));
|
||||
|
||||
// string? w/e
|
||||
std::string port;
|
||||
netplay_section.Get("ConnectPort", &port, "2626");
|
||||
m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(port.c_str()));
|
||||
|
||||
wxButton* const connect_btn = new wxButton(connect_tab, wxID_ANY, wxT("Connect"));
|
||||
_connect_macro_(connect_btn, NetPlaySetupDiag::OnJoin, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
|
@ -96,7 +112,11 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
|
|||
// host tab
|
||||
{
|
||||
wxStaticText* const port_lbl = new wxStaticText(host_tab, wxID_ANY, wxT("Port :"), wxDefaultPosition, wxDefaultSize);
|
||||
m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, wxT("2626"));
|
||||
|
||||
// string? w/e
|
||||
std::string port;
|
||||
netplay_section.Get("HostPort", &port, "2626");
|
||||
m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, wxString::FromAscii(port.c_str()));
|
||||
|
||||
wxButton* const host_btn = new wxButton(host_tab, wxID_ANY, wxT("Host"));
|
||||
_connect_macro_(host_btn, NetPlaySetupDiag::OnHost, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
|
@ -143,6 +163,21 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
|
|||
Show();
|
||||
}
|
||||
|
||||
NetPlaySetupDiag::~NetPlaySetupDiag()
|
||||
{
|
||||
IniFile inifile;
|
||||
const std::string dolphin_ini = std::string(File::GetUserPath(D_CONFIG_IDX)) + "Dolphin.ini";
|
||||
inifile.Load(dolphin_ini);
|
||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||
|
||||
netplay_section.Set("Nickname", m_nickname_text->GetValue().mb_str());
|
||||
netplay_section.Set("Address", m_connect_ip_text->GetValue().mb_str());
|
||||
netplay_section.Set("ConnectPort", m_connect_port_text->GetValue().mb_str());
|
||||
netplay_section.Set("HostPort", m_host_port_text->GetValue().mb_str());
|
||||
|
||||
inifile.Save(dolphin_ini);
|
||||
}
|
||||
|
||||
void NetPlaySetupDiag::OnHost(wxCommandEvent& event)
|
||||
{
|
||||
// warning removal
|
||||
|
@ -266,8 +301,8 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game
|
|||
// player list
|
||||
if (is_hosting)
|
||||
{
|
||||
wxButton* const player_config_btn = new wxButton(panel, wxID_ANY, wxT("Configure Pads [not implemented]"));
|
||||
player_config_btn->Disable();
|
||||
wxButton* const player_config_btn = new wxButton(panel, wxID_ANY, wxT("Configure Pads"));
|
||||
_connect_macro_(player_config_btn, NetPlayDiag::OnConfigPads, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
player_szr->Add(player_config_btn, 0, wxEXPAND | wxTOP, 5);
|
||||
}
|
||||
|
||||
|
@ -380,8 +415,8 @@ void NetPlayDiag::OnPadBuffHelp(wxCommandEvent& event)
|
|||
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";
|
||||
<< time * (60.0f/1000) << "(60fps) / "
|
||||
<< time * (50.0f/1000) << "(50fps) >\n";
|
||||
|
||||
m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent));
|
||||
}
|
||||
|
@ -412,14 +447,19 @@ void NetPlayDiag::OnThread(wxCommandEvent& event)
|
|||
event.GetId();
|
||||
|
||||
// player list
|
||||
m_playerids.clear();
|
||||
std::string tmps;
|
||||
::netplay_ptr->GetPlayerList(tmps);
|
||||
::netplay_ptr->GetPlayerList(tmps, m_playerids);
|
||||
|
||||
const int selection = m_player_lbox->GetSelection();
|
||||
|
||||
m_player_lbox->Clear();
|
||||
std::istringstream ss(tmps);
|
||||
while (std::getline(ss, tmps))
|
||||
m_player_lbox->Append(wxString(tmps.c_str(), *wxConvCurrent));
|
||||
|
||||
m_player_lbox->SetSelection(selection);
|
||||
|
||||
switch (event.GetId())
|
||||
{
|
||||
case NP_GUI_EVT_CHANGE_GAME :
|
||||
|
@ -472,6 +512,30 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
void NetPlayDiag::OnConfigPads(wxCommandEvent& event)
|
||||
{
|
||||
// warning removal
|
||||
event.GetId();
|
||||
|
||||
int mapping[4];
|
||||
|
||||
// get selected player id
|
||||
int pid = m_player_lbox->GetSelection();
|
||||
if (pid < 0)
|
||||
return;
|
||||
pid = m_playerids.at(pid);
|
||||
|
||||
if (false == ((NetPlayServer*)::netplay_ptr)->GetPadMapping(pid, mapping))
|
||||
return;
|
||||
|
||||
PadMapDiag* const pmd = new PadMapDiag(this, mapping);
|
||||
pmd->ShowModal();
|
||||
pmd->Destroy();
|
||||
|
||||
if (false == ((NetPlayServer*)::netplay_ptr)->SetPadMapping(pid, mapping))
|
||||
PanicAlert("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)");
|
||||
}
|
||||
|
||||
ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* const game_list, wxString& game_name)
|
||||
: wxDialog(parent, wxID_ANY, wxT("Change Game"), wxDefaultPosition, wxDefaultSize)
|
||||
, m_game_name(game_name)
|
||||
|
@ -510,3 +574,58 @@ void ChangeGameDiag::OnPick(wxCommandEvent& event)
|
|||
m_game_name = m_game_lbox->GetStringSelection();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
PadMapDiag::PadMapDiag(wxWindow* const parent, int map[])
|
||||
: wxDialog(parent, wxID_ANY, wxT("Configure Pads"), wxDefaultPosition, wxDefaultSize)
|
||||
, m_mapping(map)
|
||||
{
|
||||
wxPanel* const panel = new wxPanel(this);
|
||||
|
||||
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
h_szr->AddSpacer(20);
|
||||
|
||||
// labels
|
||||
wxBoxSizer* const label_szr = new wxBoxSizer(wxVERTICAL);
|
||||
label_szr->Add(new wxStaticText(panel,wxID_ANY, wxT("Local")), 0, wxALIGN_TOP);
|
||||
label_szr->AddStretchSpacer(1);
|
||||
label_szr->Add(new wxStaticText(panel,wxID_ANY, wxT("In-Game")), 0, wxALIGN_BOTTOM);
|
||||
|
||||
h_szr->Add(label_szr, 1, wxTOP | wxBOTTOM | wxEXPAND, 20);
|
||||
|
||||
// set up choices
|
||||
wxString pad_names[5];
|
||||
pad_names[0] = wxT("None");
|
||||
for (unsigned int i=1; i<5; ++i)
|
||||
pad_names[i] = wxString(wxT("Pad ")) + (wxChar)(wxT('0')+i);
|
||||
|
||||
for (unsigned int i=0; i<4; ++i)
|
||||
{
|
||||
wxChoice* const pad_cbox = m_map_cbox[i]
|
||||
= new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 5, pad_names);
|
||||
pad_cbox->Select(m_mapping[i] + 1);
|
||||
|
||||
_connect_macro_(pad_cbox, PadMapDiag::OnAdjust, wxEVT_COMMAND_CHOICE_SELECTED, this);
|
||||
|
||||
wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL);
|
||||
v_szr->Add(new wxStaticText(panel,wxID_ANY, pad_names[i + 1]), 1, wxALIGN_CENTER_HORIZONTAL);
|
||||
v_szr->Add(pad_cbox, 1);
|
||||
|
||||
h_szr->Add(v_szr, 1, wxTOP | wxBOTTOM | wxEXPAND, 20);
|
||||
}
|
||||
|
||||
h_szr->AddSpacer(20);
|
||||
|
||||
panel->SetSizerAndFit(h_szr);
|
||||
|
||||
wxBoxSizer* const dlg_szr = new wxBoxSizer(wxVERTICAL);
|
||||
dlg_szr->Add(panel, 1, wxEXPAND);
|
||||
SetSizerAndFit(dlg_szr);
|
||||
}
|
||||
|
||||
void PadMapDiag::OnAdjust(wxCommandEvent& event)
|
||||
{
|
||||
(void)event;
|
||||
for (unsigned int i=0; i<4; ++i)
|
||||
m_mapping[i] = m_map_cbox[i]->GetSelection() - 1;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class NetPlaySetupDiag : public wxFrame
|
|||
{
|
||||
public:
|
||||
NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* const game_list);
|
||||
|
||||
~NetPlaySetupDiag();
|
||||
private:
|
||||
void OnJoin(wxCommandEvent& event);
|
||||
void OnHost(wxCommandEvent& event);
|
||||
|
@ -98,6 +98,7 @@ private:
|
|||
void OnThread(wxCommandEvent& event);
|
||||
void OnChangeGame(wxCommandEvent& event);
|
||||
void OnAdjustBuffer(wxCommandEvent& event);
|
||||
void OnConfigPads(wxCommandEvent& event);
|
||||
|
||||
wxListBox* m_player_lbox;
|
||||
wxTextCtrl* m_chat_text;
|
||||
|
@ -106,6 +107,8 @@ private:
|
|||
std::string m_selected_game;
|
||||
wxButton* m_game_btn;
|
||||
|
||||
std::vector<int> m_playerids;
|
||||
|
||||
const CGameListCtrl* const m_game_list;
|
||||
//NetPlay* const m_netplay;
|
||||
};
|
||||
|
@ -124,5 +127,17 @@ private:
|
|||
wxString& m_game_name;
|
||||
};
|
||||
|
||||
class PadMapDiag : public wxDialog
|
||||
{
|
||||
public:
|
||||
PadMapDiag(wxWindow* const parent, int map[]);
|
||||
|
||||
private:
|
||||
void OnAdjust(wxCommandEvent& event);
|
||||
|
||||
wxChoice* m_map_cbox[4];
|
||||
int* const m_mapping;
|
||||
};
|
||||
|
||||
#endif // _NETWINDOW_H_
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ void ControllerInterface::Init()
|
|||
//
|
||||
// remove all devices/ call library cleanup functions
|
||||
//
|
||||
void ControllerInterface::DeInit()
|
||||
void ControllerInterface::DeInit(const bool hacks_no_sdl_quit)
|
||||
{
|
||||
if ( false == m_is_init )
|
||||
return;
|
||||
|
@ -73,6 +73,13 @@ void ControllerInterface::DeInit()
|
|||
(*d)->SetOutputState( *o, 0 );
|
||||
// update output
|
||||
(*d)->UpdateOutput();
|
||||
|
||||
// TODO: remove this
|
||||
// major hacks to prevent gcpad/wiimote new from crashing eachother
|
||||
if (hacks_no_sdl_quit)
|
||||
if ((*d)->GetSource() == "SDL")
|
||||
continue;
|
||||
|
||||
//delete device
|
||||
delete *d;
|
||||
}
|
||||
|
@ -92,8 +99,9 @@ void ControllerInterface::DeInit()
|
|||
ciface::OSX::DeInit();
|
||||
#endif
|
||||
#ifdef CIFACE_USE_SDL
|
||||
// there seems to be some sort of memory leak with SDL, quit isn't freeing everything up
|
||||
SDL_Quit();
|
||||
// TODO: there seems to be some sort of memory leak with SDL, quit isn't freeing everything up
|
||||
if (false == hacks_no_sdl_quit)
|
||||
SDL_Quit();
|
||||
#endif
|
||||
|
||||
m_is_init = false;
|
||||
|
|
|
@ -240,7 +240,8 @@ public:
|
|||
|
||||
void SetHwnd( void* const hwnd );
|
||||
void Init();
|
||||
void DeInit();
|
||||
// TODO: remove this hack param
|
||||
void DeInit(const bool hacks_no_sdl_quit = false);
|
||||
bool IsInit();
|
||||
|
||||
void UpdateReference( ControlReference* control );
|
||||
|
|
|
@ -20,15 +20,21 @@ namespace SDL
|
|||
|
||||
void Init( std::vector<ControllerInterface::Device*>& devices )
|
||||
{
|
||||
if ( SDL_Init( SDL_INIT_FLAGS ) >= 0 )
|
||||
// just a struct with an int that is set to ZERO by default
|
||||
struct ZeroedInt{ZeroedInt():value(0){}unsigned int value;};
|
||||
// this is used to number the joysticks
|
||||
// multiple joysticks with the same name shall get unique ids starting at 0
|
||||
std::map<std::string, ZeroedInt> name_counts;
|
||||
|
||||
if (SDL_Init( SDL_INIT_FLAGS ) >= 0)
|
||||
{
|
||||
// joysticks
|
||||
for( int i = 0; i < SDL_NumJoysticks(); ++i )
|
||||
for(int i = 0; i < SDL_NumJoysticks(); ++i)
|
||||
{
|
||||
SDL_Joystick* dev = SDL_JoystickOpen( i );
|
||||
SDL_Joystick* dev = SDL_JoystickOpen(i);
|
||||
if ( dev )
|
||||
{
|
||||
Joystick* js = new Joystick( dev, i );
|
||||
Joystick* js = new Joystick(dev, i, name_counts[SDL_JoystickName(i)].value++);
|
||||
// only add if it has some inputs/outputs
|
||||
if ( js->Inputs().size() || js->Outputs().size() )
|
||||
devices.push_back( js );
|
||||
|
@ -39,8 +45,32 @@ void Init( std::vector<ControllerInterface::Device*>& devices )
|
|||
}
|
||||
}
|
||||
|
||||
Joystick::Joystick( SDL_Joystick* const joystick, const unsigned int index ) : m_joystick(joystick), m_index(index)
|
||||
Joystick::Joystick(SDL_Joystick* const joystick, const int sdl_index, const unsigned int index)
|
||||
: m_joystick(joystick)
|
||||
, m_sdl_index(sdl_index)
|
||||
, m_index(index)
|
||||
{
|
||||
// really bad HACKS:
|
||||
// to not use SDL for an XInput device
|
||||
// too many people on the forums pick the SDL device and ask:
|
||||
// "why don't my 360 gamepad triggers/rumble work correctly"
|
||||
#ifdef _WIN32
|
||||
// checking the name is probably good (and hacky) enough
|
||||
// but i'll double check with the num of buttons/axes
|
||||
if (
|
||||
("Controller (Xbox 360 Wireless Receiver for Windows)" == GetName())
|
||||
&& (10 == SDL_JoystickNumButtons(joystick))
|
||||
&& (5 == SDL_JoystickNumAxes(joystick))
|
||||
&& (1 == SDL_JoystickNumHats(joystick))
|
||||
&& (0 == SDL_JoystickNumBalls(joystick))
|
||||
)
|
||||
{
|
||||
// this device won't be used
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// get buttons
|
||||
for ( int i = 0; i < SDL_JoystickNumButtons( m_joystick ); ++i )
|
||||
{
|
||||
|
@ -210,7 +240,7 @@ bool Joystick::UpdateOutput()
|
|||
|
||||
std::string Joystick::GetName() const
|
||||
{
|
||||
return StripSpaces(SDL_JoystickName(m_index));
|
||||
return StripSpaces(SDL_JoystickName(m_sdl_index));
|
||||
}
|
||||
|
||||
std::string Joystick::GetSource() const
|
||||
|
|
|
@ -135,7 +135,7 @@ protected:
|
|||
void SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state );
|
||||
|
||||
public:
|
||||
Joystick( SDL_Joystick* const joystick, const unsigned int index );
|
||||
Joystick(SDL_Joystick* const joystick, const int sdl_index, const unsigned int index);
|
||||
~Joystick();
|
||||
|
||||
std::string GetName() const;
|
||||
|
@ -144,6 +144,7 @@ public:
|
|||
|
||||
private:
|
||||
SDL_Joystick* const m_joystick;
|
||||
const int m_sdl_index;
|
||||
const unsigned int m_index;
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
|
|
|
@ -373,6 +373,8 @@ void GamepadPage::ClearControl( wxCommandEvent& event )
|
|||
btn->control_reference->device_qualifier = controller->default_device;
|
||||
|
||||
g_plugin->controls_crit.Enter();
|
||||
if (btn->control_reference->is_input)
|
||||
((ControllerInterface::InputReference*)btn->control_reference)->mode = 0;
|
||||
controller->UpdateReferences( g_plugin->controller_interface );
|
||||
g_plugin->controls_crit.Leave();
|
||||
|
||||
|
@ -618,22 +620,33 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi
|
|||
static_bitmap = NULL;
|
||||
|
||||
wxFont m_SmallFont(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
for ( unsigned int c = 0; c < group->controls.size(); ++c )
|
||||
std::vector<ControllerEmu::ControlGroup::Control*>::iterator
|
||||
ci = group->controls.begin(),
|
||||
ce = group->controls.end();
|
||||
for ( ; ci != ce; ++ci)
|
||||
{
|
||||
|
||||
wxStaticText* const label = new wxStaticText( parent, -1, wxString::FromAscii( group->controls[c]->name )/*.append(wxT(" :"))*/ );
|
||||
wxStaticText* const label = new wxStaticText(parent, -1, wxString::FromAscii((*ci)->name)/*.append(wxT(" :"))*/ );
|
||||
|
||||
ControlButton* const control_button = new ControlButton( parent, group->controls[c]->control_ref, 80 );
|
||||
ControlButton* const control_button = new ControlButton(parent, (*ci)->control_ref, 80);
|
||||
control_button->SetFont(m_SmallFont);
|
||||
|
||||
controls.push_back( control_button );
|
||||
control_buttons.push_back( control_button );
|
||||
controls.push_back(control_button);
|
||||
control_buttons.push_back(control_button);
|
||||
|
||||
control_button->SetToolTip(wxT("Right-click for more options.\nMiddle-click to clear."));
|
||||
if ((*ci)->control_ref->is_input)
|
||||
{
|
||||
control_button->SetToolTip(wxT("Left-click to detect input.\nMiddle-click to clear.\nRight-click for more options."));
|
||||
_connect_macro_( control_button, GamepadPage::DetectControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink );
|
||||
}
|
||||
else
|
||||
{
|
||||
control_button->SetToolTip(wxT("Left/Right-click for more options.\nMiddle-click to clear."));
|
||||
_connect_macro_( control_button, GamepadPage::ConfigControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink );
|
||||
}
|
||||
|
||||
_connect_macro_( control_button, GamepadPage::DetectControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink );
|
||||
_connect_macro_( control_button, GamepadPage::ConfigControl, wxEVT_RIGHT_UP, eventsink );
|
||||
_connect_macro_( control_button, GamepadPage::ClearControl, wxEVT_MIDDLE_DOWN, eventsink );
|
||||
_connect_macro_( control_button, GamepadPage::ConfigControl, wxEVT_RIGHT_UP, eventsink );
|
||||
|
||||
wxBoxSizer* const control_sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
control_sizer->AddStretchSpacer( 1 );
|
||||
|
|
|
@ -99,7 +99,9 @@ void DeInitPlugin()
|
|||
delete *i;
|
||||
g_plugin.controllers.clear();
|
||||
|
||||
g_plugin.controller_interface.DeInit();
|
||||
// true parameter to make SDL not quit in the wiimote plugin,
|
||||
// the old wiimote plugin uses this hack as well, to prevent crash on stop
|
||||
g_plugin.controller_interface.DeInit(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +278,7 @@ void DllConfig(HWND _hParent)
|
|||
frame->Destroy();
|
||||
// /
|
||||
|
||||
if ( false == was_init ) // hack for showing dialog when game isnt running
|
||||
if ( false == was_init )
|
||||
DeInitPlugin();
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue