Merge branch 'master' into wii-network

This commit is contained in:
Matthew Parlane
2013-08-24 23:56:31 +12:00
70 changed files with 1109 additions and 815 deletions

View File

@ -402,7 +402,7 @@ void SConfig::LoadSettings()
ini.Get("Core", "EnableCheats", &m_LocalCoreStartupParameter.bEnableCheats, false);
ini.Get("Core", "SelectedLanguage", &m_LocalCoreStartupParameter.SelectedLanguage, 0);
ini.Get("Core", "DPL2Decoder", &m_LocalCoreStartupParameter.bDPL2Decoder, false);
ini.Get("Core", "Latency", &m_LocalCoreStartupParameter.iLatency, 14);
ini.Get("Core", "Latency", &m_LocalCoreStartupParameter.iLatency, 2);
ini.Get("Core", "MemcardA", &m_strMemoryCardA);
ini.Get("Core", "MemcardB", &m_strMemoryCardB);
ini.Get("Core", "SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD);

View File

@ -388,7 +388,7 @@ void EmuThread()
return;
}
OSD::AddMessage(("Dolphin " + g_video_backend->GetName() + " Video Backend.").c_str(), 5000);
OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000);
if (!DSP::GetDSPEmulator()->Initialize(g_pWindowHandle,
_CoreParameter.bWii, _CoreParameter.bDSPThread))

View File

@ -23,22 +23,6 @@ NetSettings g_NetPlaySettings;
#define RPT_SIZE_HACK (1 << 16)
NetPlayClient::Player::Player()
{
memset(pad_map, -1, sizeof(pad_map));
}
// called from ---GUI--- thread
std::string NetPlayClient::Player::ToString() const
{
std::ostringstream ss;
ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |";
for (unsigned int i=0; i<4; ++i)
ss << (pad_map[i]>=0 ? (char)(pad_map[i]+'1') : '-');
ss << " | " << ping << "ms";
return ss.str();
}
NetPad::NetPad()
{
nHi = 0x00808080;
@ -200,16 +184,8 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_PAD_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.pad_map[i];
}
for (PadMapping i = 0; i < 4; i++)
packet >> m_pad_map[i];
m_dialog->Update();
}
@ -223,7 +199,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
// trusting server for good map value (>=0 && <4)
// add to pad buffer
m_pad_buffer[(unsigned)map].Push(np);
m_pad_buffer[map].Push(np);
}
break;
@ -361,13 +337,36 @@ void NetPlayClient::GetPlayerList(std::string& list, std::vector<int>& pid_list)
e = m_players.end();
for ( ; i!=e; ++i)
{
ss << i->second.ToString() << '\n';
pid_list.push_back(i->second.pid);
const Player *player = &(i->second);
ss << player->name << "[" << (int)player->pid << "] : " << player->revision << " | ";
for (unsigned int j = 0; j < 4; j++)
{
if (m_pad_map[j] == player->pid)
ss << j + 1;
else
ss << '-';
}
ss << " | " << player->ping << "ms\n";
pid_list.push_back(player->pid);
}
list = ss.str();
}
// called from ---GUI--- thread
void NetPlayClient::GetPlayers(std::vector<const Player *> &player_list)
{
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<PlayerId, Player>::const_iterator
i = m_players.begin(),
e = m_players.end();
for ( ; i!=e; ++i)
{
const Player *player = &(i->second);
player_list.push_back(player);
}
}
// called from ---GUI--- thread
void NetPlayClient::SendChatMessage(const std::string& msg)
@ -381,12 +380,12 @@ void NetPlayClient::SendChatMessage(const std::string& msg)
}
// called from ---CPU--- thread
void NetPlayClient::SendPadState(const PadMapping local_nb, const NetPad& np)
void NetPlayClient::SendPadState(const PadMapping in_game_pad, const NetPad& np)
{
// send to server
sf::Packet spac;
spac << (MessageId)NP_MSG_PAD_DATA;
spac << local_nb; // local pad num
spac << in_game_pad;
spac << np.nHi << np.nLo;
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
@ -457,13 +456,35 @@ void NetPlayClient::ClearBuffers()
// called from ---CPU--- thread
bool NetPlayClient::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues)
{
{
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
// The interface for this is extremely silly.
//
// Imagine a physical device that links three Gamecubes together
// and emulates NetPlay that way. Which Gamecube controls which
// in-game controllers can be configured on the device (m_pad_map)
// but which sockets on each individual Gamecube should be used
// to control which players? The solution that Dolphin uses is
// that we hardcode the knowledge that they go in order, so if
// you have a 3P game with three gamecubes, then every single
// controller should be plugged into slot 1.
//
// If you have a 4P game, then one of the Gamecubes will have
// a controller plugged into slot 1, and another in slot 2.
//
// The slot number is the "local" pad number, and what player
// it actually means is the "in-game" pad number.
//
// The interface here gives us the status of local pads, and
// expects to get back "in-game" pad numbers back in response.
// e.g. it asks "here's the input that slot 1 has, and by the
// way, what's the state of P1?"
//
// We should add this split between "in-game" pads and "local"
// pads higher up.
// in game mapping for this local pad
unsigned int in_game_num = m_local_player->pad_map[pad_nb];
int in_game_num = GetPadNum(pad_nb);
// does this local pad map in game?
// If this in-game pad is one of ours, then update from the
// information given.
if (in_game_num < 4)
{
NetPad np(pad_status);
@ -476,89 +497,36 @@ bool NetPlayClient::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_stat
m_pad_buffer[in_game_num].Push(np);
// send
SendPadState(pad_nb, np);
SendPadState(in_game_num, np);
}
}
} // unlock players
//Common::Timer bufftimer;
//bufftimer.Start();
// get padstate from buffer and send to game
// Now, we need to swap out the local value with the values
// retrieved from NetPlay. This could be the value we pushed
// above if we're configured as P1 and the code is trying
// to retrieve data for slot 1.
while (!m_pad_buffer[pad_nb].Pop(*netvalues))
{
// wait for receiving thread to push some data
Common::SleepCurrentThread(1);
if (false == m_is_running)
if (!m_is_running)
return false;
// TODO: check the time of bufftimer here,
// if it gets pretty high, ask the user if they want to disconnect
// TODO: use a condition instead of sleeping
Common::SleepCurrentThread(1);
}
//u64 hangtime = bufftimer.GetTimeElapsed();
//if (hangtime > 10)
//{
// std::ostringstream ss;
// ss << "Pad " << (int)pad_nb << ": Had to wait " << hangtime << "ms for pad data. (increase pad Buffer maybe)";
// Core::DisplayMessage(ss.str(), 1000);
//}
return true;
}
// 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;
}
// XXX
}
// called from ---CPU--- thread
void NetPlayClient::WiimoteUpdate(int _number)
{
{
std::lock_guard<std::recursive_mutex> 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
// does this local pad map in game?
if (in_game_num < 4)
{
m_wiimote_buffer[in_game_num].Push(m_wiimote_input[_number]);
// TODO: send it
m_wiimote_input[_number].clear();
}
} // unlock players
if (0 == m_wiimote_buffer[_number].Size())
{
//PanicAlert("PANIC");
return;
}
NetWiimote nw;
m_wiimote_buffer[_number].Pop(nw);
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);
// XXX
}
// called from ---GUI--- thread and ---NETPLAY--- thread (client side)
@ -586,13 +554,21 @@ bool NetPlayClient::StopGame()
// called from ---CPU--- thread
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)
if (numPAD == m_local_player->pad_map[i])
break;
// 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_pad_map[ingame_pad] == m_local_player->pid)
local_pad_count++;
return i;
if (local_pad_count == numPAD)
break;
}
return ingame_pad;
}
// stuff hacked into dolphin
@ -658,22 +634,13 @@ u8 CSIDevice_DanceMat::NetPlay_GetPadNum(u8 numPAD)
//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);
//if (netplay_client)
// return netplay_client->GetPadNum(_number); // just using gcpad mapping for now
//else
return _number;
return _number;
}
// called from ---CPU--- thread
@ -684,19 +651,7 @@ bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&)
std::lock_guard<std::mutex> lk(crit_netplay_client);
if (netplay_client)
//{
// if (_Size >= RPT_SIZE_HACK)
// {
// _Size -= RPT_SIZE_HACK;
// return false;
// }
// else
// {
// netplay_client->WiimoteInput(_number, _channelID, _pData, _Size);
// // don't use this packet
return true;
// }
//}
return true;
else
return false;
}

View File

@ -50,6 +50,15 @@ public:
extern NetSettings g_NetPlaySettings;
class Player
{
public:
PlayerId pid;
std::string name;
std::string revision;
u32 ping;
};
class NetPlayClient
{
public:
@ -59,6 +68,7 @@ public:
~NetPlayClient();
void GetPlayerList(std::string& list, std::vector<int>& pid_list);
void GetPlayers(std::vector<const Player *>& player_list);
bool is_connected;
@ -84,19 +94,6 @@ protected:
std::recursive_mutex players, send;
} m_crit;
class Player
{
public:
Player();
std::string ToString() const;
PlayerId pid;
std::string name;
PadMapping pad_map[4];
std::string revision;
u32 ping;
};
Common::FifoQueue<NetPad> m_pad_buffer[4];
Common::FifoQueue<NetWiimote> m_wiimote_buffer[4];
@ -117,8 +114,10 @@ protected:
u32 m_current_game;
PadMapping m_pad_map[4];
private:
void SendPadState(const PadMapping local_nb, const NetPad& np);
void SendPadState(const PadMapping in_game_pad, const NetPad& np);
unsigned int OnData(sf::Packet& packet);
PlayerId m_pid;

View File

@ -24,7 +24,7 @@ struct Rpt : public std::vector<u8>
typedef std::vector<Rpt> NetWiimote;
#define NETPLAY_VERSION "Dolphin NetPlay 2013-08-18"
#define NETPLAY_VERSION "Dolphin NetPlay 2013-08-23"
// messages
enum

View File

@ -4,11 +4,6 @@
#include "NetPlayServer.h"
NetPlayServer::Client::Client()
{
memset(pad_map, -1, sizeof(pad_map));
}
NetPlayServer::~NetPlayServer()
{
if (is_connected)
@ -29,6 +24,7 @@ NetPlayServer::~NetPlayServer()
// called from ---GUI--- thread
NetPlayServer::NetPlayServer(const u16 port) : is_connected(false), m_is_running(false)
{
memset(m_pad_map, -1, sizeof(m_pad_map));
if (m_socket.Listen(port))
{
is_connected = true;
@ -155,45 +151,16 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
rpac >> player.name;
// give new client first available id
player.pid = 0;
std::map<sf::SocketTCP, Client>::const_iterator
i,
e = m_players.end();
for (PlayerId p = 1; 0 == player.pid; ++p)
{
for (i = m_players.begin(); ; ++i)
{
if (e == i)
{
player.pid = p;
break;
}
if (p == i->second.pid)
break;
}
}
player.pid = m_players.size() + 1;
// TODO: this is crappy
// try to automatically assign new user a pad
for (unsigned int m = 0; m < 4; ++m)
{
bool is_mapped[4] = {false,false,false,false};
for ( unsigned int m = 0; m<4; ++m)
{
for (i = m_players.begin(); i!=e; ++i)
if (m_pad_map[m] == -1)
{
if (i->second.pad_map[m] >= 0)
is_mapped[(unsigned)i->second.pad_map[m]] = true;
}
}
for ( unsigned int m = 0; m<4; ++m)
if (false == is_mapped[m])
{
player.pad_map[0] = m;
m_pad_map[m] = player.pid;
break;
}
}
{
@ -221,6 +188,9 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
}
// sync values with new client
std::map<sf::SocketTCP, Client>::const_iterator
i,
e = m_players.end();
for (i = m_players.begin(); i!=e; ++i)
{
spac.Clear();
@ -279,83 +249,28 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
}
// called from ---GUI--- thread
bool NetPlayServer::GetPadMapping(const int pid, int map[])
void NetPlayServer::GetPadMapping(PadMapping map[4])
{
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.pad_map[m];
return true;
for (int i = 0; i < 4; i++)
map[i] = m_pad_map[i];
}
// called from ---GUI--- thread
bool NetPlayServer::SetPadMapping(const int pid, const int map[])
void NetPlayServer::SetPadMapping(const PadMapping map[4])
{
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.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;
}
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
UpdatePadMapping(); // sync pad mappings with everyone
return true;
for (int i = 0; i < 4; i++)
m_pad_map[i] = map[i];
UpdatePadMapping();
}
// called from ---NETPLAY--- thread
// called from ---GUI--- thread and ---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);
}
sf::Packet spac;
spac << (MessageId)NP_MSG_PAD_MAPPING;
for (int i = 0; i < 4; i++)
spac << m_pad_map[i];
SendToClients(spac);
}
// called from ---GUI--- thread and ---NETPLAY--- thread
@ -415,23 +330,15 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
int hi, lo;
packet >> map >> hi >> lo;
// check if client's pad indeed maps in game
if (map >= 0 && map < 4)
map = player.pad_map[(unsigned)map];
else
map = -1;
// if not, they are hacking, so disconnect them
// this could happen right after a pad map change, but that isn't implemented yet
if (map < 0)
// If the data is not from the correct player,
// then disconnect them.
if (m_pad_map[map] != player.pid)
return 1;
// relay to clients
// Relay to clients
sf::Packet spac;
spac << (MessageId)NP_MSG_PAD_DATA;
spac << map; // in game mapping
spac << hi << lo;
spac << map << hi << lo;
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid);

View File

@ -35,8 +35,8 @@ public:
bool StartGame(const std::string &path);
bool StopGame();
bool GetPadMapping(const int pid, int map[]);
bool SetPadMapping(const int pid, const int map[]);
void GetPadMapping(PadMapping map[]);
void SetPadMapping(const PadMapping map[]);
void AdjustPadBufferSize(unsigned int size);
@ -50,11 +50,8 @@ private:
class Client
{
public:
Client();
PlayerId pid;
std::string name;
PadMapping pad_map[4];
std::string revision;
sf::SocketTCP socket;
@ -77,6 +74,7 @@ private:
bool m_update_pings;
u32 m_current_game;
unsigned int m_target_buffer_size;
PadMapping m_pad_map[4];
std::map<sf::SocketTCP, Client> m_players;

View File

@ -513,10 +513,8 @@ void CConfigMain::InitializeGUITooltips()
#if defined(__APPLE__)
DPL2Decoder->SetToolTip(_("Enables Dolby Pro Logic II emulation using 5.1 surround. Not available on OSX."));
#elif defined(__linux__)
#else
DPL2Decoder->SetToolTip(_("Enables Dolby Pro Logic II emulation using 5.1 surround. OpenAL backend only."));
#elif defined(_WIN32)
DPL2Decoder->SetToolTip(_("Enables Dolby Pro Logic II emulation using 5.1 surround. OpenAL backend only. May need to rename soft_oal.dll to OpenAL32.dll to make it work."));
#endif
Latency->SetToolTip(_("Sets the latency (in ms). Higher values may reduce audio crackling. OpenAL backend only."));

View File

@ -132,25 +132,6 @@ void Host_SysMessage(const char *fmt, ...)
void Host_SetWiiMoteConnectionState(int _State) {}
void OSDCallbacks(u32 UserData)
{
switch(UserData)
{
case 0: // Init
ButtonManager::Init();
break;
case 1: // Draw
ButtonManager::DrawButtons();
break;
case 2: // Shutdown
ButtonManager::Shutdown();
break;
default:
WARN_LOG(COMMON, "Error, wrong OSD type");
break;
}
}
#define DVD_BANNER_WIDTH 96
#define DVD_BANNER_HEIGHT 32
std::vector<std::string> m_volume_names;
@ -321,8 +302,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *
{
surf = ANativeWindow_fromSurface(env, _surf);
// Install our callbacks
OSD::AddCallback(OSD::OSD_INIT, OSDCallbacks, 0);
OSD::AddCallback(OSD::OSD_SHUTDOWN, OSDCallbacks, 2);
OSD::AddCallback(OSD::OSD_INIT, ButtonManager::Init);
OSD::AddCallback(OSD::OSD_SHUTDOWN, ButtonManager::Shutdown);
LogManager::Init();
SConfig::Init();
@ -337,7 +318,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *
ini.Get("Android", "ScreenControls", &onscreencontrols, true);
if (onscreencontrols)
OSD::AddCallback(OSD::OSD_ONFRAME, OSDCallbacks, 1);
OSD::AddCallback(OSD::OSD_ONFRAME, ButtonManager::DrawButtons);
// No use running the loop when booting fails
if ( BootManager::BootCore( g_filename.c_str() ) )

View File

@ -559,23 +559,13 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&)
void NetPlayDiag::OnConfigPads(wxCommandEvent&)
{
int mapping[4];
// get selected player id
int pid = m_player_lbox->GetSelection();
if (pid < 0)
return;
pid = m_playerids.at(pid);
if (false == netplay_server->GetPadMapping(pid, mapping))
return;
PadMapDiag pmd(this, mapping);
PadMapping mapping[4];
std::vector<const Player *> player_list;
netplay_server->GetPadMapping(mapping);
netplay_client->GetPlayers(player_list);
PadMapDiag pmd(this, mapping, player_list);
pmd.ShowModal();
if (false == netplay_server->SetPadMapping(pid, mapping))
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)");
netplay_server->SetPadMapping(mapping);
}
ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* const game_list, wxString& game_name)
@ -605,45 +595,40 @@ void ChangeGameDiag::OnPick(wxCommandEvent& event)
EndModal(wxID_OK);
}
PadMapDiag::PadMapDiag(wxWindow* const parent, int map[])
PadMapDiag::PadMapDiag(wxWindow* const parent, PadMapping map[], std::vector<const Player *>& player_list)
: wxDialog(parent, wxID_ANY, _("Configure Pads"), wxDefaultPosition, wxDefaultSize)
, m_mapping(map)
, m_player_list(player_list)
{
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL);
h_szr->AddSpacer(10);
h_szr->AddSpacer(20);
// labels
wxBoxSizer* const label_szr = new wxBoxSizer(wxVERTICAL);
label_szr->Add(new wxStaticText(this, wxID_ANY, _("Local")), 0, wxALIGN_TOP);
label_szr->AddStretchSpacer(1);
label_szr->Add(new wxStaticText(this, wxID_ANY, _("In-Game")), 0, wxALIGN_BOTTOM);
h_szr->Add(label_szr, 1, wxTOP | wxEXPAND, 20);
// set up choices
wxString pad_names[5];
pad_names[0] = _("None");
for (unsigned int i=1; i<5; ++i)
pad_names[i] = wxString(_("Pad ")) + (wxChar)(wxT('0')+i);
wxArrayString player_names;
player_names.Add(_("None"));
for (unsigned int i = 0; i < m_player_list.size(); i++)
player_names.Add(m_player_list[i]->name);
for (unsigned int i=0; i<4; ++i)
{
wxChoice* const pad_cbox = m_map_cbox[i]
= new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 5, pad_names);
pad_cbox->Select(m_mapping[i] + 1);
pad_cbox->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &PadMapDiag::OnAdjust, this);
wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL);
v_szr->Add(new wxStaticText(this,wxID_ANY, pad_names[i + 1]), 1, wxALIGN_CENTER_HORIZONTAL);
v_szr->Add(pad_cbox, 1);
v_szr->Add(new wxStaticText(this, wxID_ANY, (wxString(_("Pad ")) + (wxChar)(wxT('0')+i))),
1, wxALIGN_CENTER_HORIZONTAL);
m_map_cbox[i] = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, player_names);
m_map_cbox[i]->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &PadMapDiag::OnAdjust, this);
if (m_mapping[i] == -1)
m_map_cbox[i]->Select(0);
else
for (unsigned int j = 0; j < m_player_list.size(); j++)
if (m_mapping[i] == m_player_list[j]->pid)
m_map_cbox[i]->Select(j + 1);
v_szr->Add(m_map_cbox[i], 1);
h_szr->Add(v_szr, 1, wxTOP | wxEXPAND, 20);
h_szr->AddSpacer(10);
}
h_szr->AddSpacer(20);
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
main_szr->Add(h_szr);
main_szr->AddSpacer(5);
@ -656,8 +641,14 @@ PadMapDiag::PadMapDiag(wxWindow* const parent, int map[])
void PadMapDiag::OnAdjust(wxCommandEvent& event)
{
(void)event;
for (unsigned int i=0; i<4; ++i)
m_mapping[i] = m_map_cbox[i]->GetSelection() - 1;
for (unsigned int i = 0; i < 4; i++)
{
int player_idx = m_map_cbox[i]->GetSelection();
if (player_idx > 0)
m_mapping[i] = m_player_list[player_idx - 1]->pid;
else
m_mapping[i] = -1;
}
}
void NetPlay::StopGame()

View File

@ -124,13 +124,14 @@ private:
class PadMapDiag : public wxDialog
{
public:
PadMapDiag(wxWindow* const parent, int map[]);
PadMapDiag(wxWindow* const parent, PadMapping map[], std::vector<const Player *>& player_list);
private:
void OnAdjust(wxCommandEvent& event);
wxChoice* m_map_cbox[4];
int* const m_mapping;
PadMapping* const m_mapping;
std::vector<const Player *>& m_player_list;
};
namespace NetPlay

View File

@ -11,8 +11,9 @@ namespace DriverDetails
{
struct BugInfo
{
Vendor m_vendor; // which vendor has the error
Driver m_driver; // which driver has the error
Bug m_bug; // Which bug it is
u32 m_devfamily; // Which device(family) has the error
double m_versionstart; // When it started
double m_versionend; // When it ended
bool m_hasbug; // Does it have it?
@ -21,40 +22,27 @@ namespace DriverDetails
// Local members
Vendor m_vendor = VENDOR_UNKNOWN;
Driver m_driver = DRIVER_UNKNOWN;
u32 m_devfamily = 0;
double m_version = 0.0;
// This is a list of all known bugs for each vendor
// We use this to check if the device and driver has a issue
BugInfo m_qualcommbugs[] = {
{BUG_NODYNUBOACCESS, 300, 14.0, -1.0},
{BUG_BROKENCENTROID, 300, 14.0, -1.0},
{BUG_BROKENINFOLOG, 300, -1.0, -1.0},
BugInfo m_known_bugs[] = {
{VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true},
{VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true},
{VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true},
{VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENUBO, 900, 916, true},
{VENDOR_MESA, DRIVER_R600, BUG_BROKENUBO, 900, 913, true},
{VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true},
};
std::map<std::pair<Vendor, Bug>, BugInfo> m_bugs;
// Private function
void InitBugMap()
{
switch(m_driver)
{
case DRIVER_QUALCOMM:
for (unsigned int a = 0; a < (sizeof(m_qualcommbugs) / sizeof(BugInfo)); ++a)
m_bugs[std::make_pair(m_vendor, m_qualcommbugs[a].m_bug)] = m_qualcommbugs[a];
break;
default:
break;
}
}
std::map<Bug, BugInfo> m_bugs;
void Init(Vendor vendor, Driver driver, const u32 devfamily, const double version)
void Init(Vendor vendor, Driver driver, const double version)
{
m_vendor = vendor;
m_driver = driver;
m_devfamily = devfamily;
m_version = version;
InitBugMap();
if (driver == DRIVER_UNKNOWN)
switch(vendor)
{
@ -68,12 +56,6 @@ namespace DriverDetails
case VENDOR_INTEL:
m_driver = DRIVER_INTEL;
break;
case VENDOR_ARM:
m_driver = DRIVER_ARM;
break;
case VENDOR_QUALCOMM:
m_driver = DRIVER_QUALCOMM;
break;
case VENDOR_IMGTEC:
m_driver = DRIVER_IMGTEC;
break;
@ -83,16 +65,22 @@ namespace DriverDetails
default:
break;
}
for (auto it = m_bugs.begin(); it != m_bugs.end(); ++it)
if (it->second.m_devfamily == m_devfamily)
if (it->second.m_versionend == -1.0 || (it->second.m_versionstart <= m_version && it->second.m_versionend > m_version))
it->second.m_hasbug = true;
for(unsigned int a = 0; a < (sizeof(m_known_bugs) / sizeof(BugInfo)); ++a)
{
if(
( m_known_bugs[a].m_vendor == m_vendor || m_known_bugs[a].m_vendor == VENDOR_ALL ) &&
( m_known_bugs[a].m_driver == m_driver || m_known_bugs[a].m_driver == DRIVER_ALL ) &&
( m_known_bugs[a].m_versionstart <= m_version || m_known_bugs[a].m_versionstart == -1 ) &&
( m_known_bugs[a].m_versionend > m_version || m_known_bugs[a].m_versionend == -1 )
)
m_bugs.insert(std::make_pair(m_known_bugs[a].m_bug, m_known_bugs[a]));
}
}
bool HasBug(Bug bug)
{
auto it = m_bugs.find(std::make_pair(m_vendor, bug));
auto it = m_bugs.find(bug);
if (it == m_bugs.end())
return false;
return it->second.m_hasbug;

View File

@ -10,7 +10,8 @@ namespace DriverDetails
// Tegra and Nvidia are separated out due to such substantial differences
enum Vendor
{
VENDOR_NVIDIA = 0,
VENDOR_ALL = 0,
VENDOR_NVIDIA,
VENDOR_ATI,
VENDOR_INTEL,
VENDOR_ARM,
@ -18,20 +19,25 @@ namespace DriverDetails
VENDOR_IMGTEC,
VENDOR_TEGRA,
VENDOR_VIVANTE,
VENDOR_MESA,
VENDOR_UNKNOWN
};
// Enum of known drivers
enum Driver
{
DRIVER_NVIDIA = 0, // Official Nvidia, including mobile GPU
DRIVER_ALL = 0,
DRIVER_NVIDIA, // Official Nvidia, including mobile GPU
DRIVER_NOUVEAU, // OSS nouveau
DRIVER_ATI, // Official ATI
DRIVER_RADEONHD, // OSS Radeon
DRIVER_R600, // OSS Radeon
DRIVER_INTEL, // Official Intel
DRIVER_ARM, // Official Mali driver
DRIVER_I965, // OSS Intel
DRIVER_ARM_4XX, // Official Mali driver
DRIVER_ARM_T6XX, // Official Mali driver
DRIVER_LIMA, // OSS Mali driver
DRIVER_QUALCOMM, // Official Adreno driver
DRIVER_QUALCOMM_3XX, // Official Adreno driver 3xx
DRIVER_QUALCOMM_2XX, // Official Adreno driver 2xx
DRIVER_FREEDRENO, // OSS Adreno driver
DRIVER_IMGTEC, // OSS PowerVR driver
DRIVER_VIVANTE, // Official vivante driver
@ -69,10 +75,18 @@ namespace DriverDetails
// Adreno devices /always/ return 0 when querying GL_INFO_LOG_LENGTH
// They also max out at 1024 bytes(1023 characters + null terminator) for the log
BUG_BROKENINFOLOG,
// Bug: UBO buffer offset broken
// Affected devices: all mesa drivers
// Started Version: 9.0 (mesa doesn't support ubo before)
// Ended Version: up to 9.2
// The offset of glBindBufferRange was ignored on all Mesa Gallium3D drivers until 9.1.3
// Nouveau stored the offset as u16 which isn't enough for all cases with range until 9.1.6
// I965 has broken data fetches from uniform buffers which results in a dithering until 9.2.0
BUG_BROKENUBO,
};
// Initializes our internal vendor, device family, and driver version
void Init(Vendor vendor, Driver driver, const u32 devfamily, const double version);
void Init(Vendor vendor, Driver driver, const double version);
// Once Vendor and driver version is set, this will return if it has the applicable bug passed to it.
bool HasBug(Bug bug);

View File

@ -11,51 +11,27 @@
#include "RenderBase.h"
#include "Timer.h"
#include <vector>
#include <map>
#include <string>
namespace OSD
{
struct MESSAGE
struct Message
{
MESSAGE() {}
MESSAGE(const char* p, u32 dw)
{
strncpy(str, p, 255);
str[255] = '\0';
dwTimeStamp = dw;
}
char str[256];
u32 dwTimeStamp;
Message() {}
Message(const std::string& s, u32 ts) : str(s), timestamp(ts) {}
std::string str;
u32 timestamp;
};
class OSDCALLBACK
static std::multimap<CallbackType, Callback> s_callbacks;
static std::list<Message> s_msgList;
void AddMessage(const std::string& str, u32 ms)
{
private:
CallbackPtr m_functionptr;
CallbackType m_type;
u32 m_data;
public:
OSDCALLBACK(CallbackType OnType, CallbackPtr FuncPtr, u32 UserData)
{
m_type = OnType;
m_functionptr = FuncPtr;
m_data = UserData;
}
void Call()
{
m_functionptr(m_data);
}
CallbackType Type() { return m_type; }
};
std::vector<OSDCALLBACK> m_callbacks;
static std::list<MESSAGE> s_listMsgs;
void AddMessage(const char* pstr, u32 ms)
{
s_listMsgs.push_back(MESSAGE(pstr, Common::Timer::GetTimeMs() + ms));
s_msgList.push_back(Message(str, Common::Timer::GetTimeMs() + ms));
}
void DrawMessages()
@ -63,58 +39,50 @@ void DrawMessages()
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bOnScreenDisplayMessages)
return;
if (s_listMsgs.size() > 0)
int left = 25, top = 15;
auto it = s_msgList.begin();
while (it != s_msgList.end())
{
int left = 25, top = 15;
std::list<MESSAGE>::iterator it = s_listMsgs.begin();
while (it != s_listMsgs.end())
int time_left = (int)(it->timestamp - Common::Timer::GetTimeMs());
u32 alpha = 255;
if (time_left < 1024)
{
int time_left = (int)(it->dwTimeStamp - Common::Timer::GetTimeMs());
int alpha = 255;
if (time_left < 1024)
{
alpha = time_left >> 2;
if (time_left < 0)
alpha = 0;
}
alpha <<= 24;
g_renderer->RenderText(it->str, left+1, top+1, 0x000000|alpha);
g_renderer->RenderText(it->str, left, top, 0xffff30|alpha);
top += 15;
if (time_left <= 0)
it = s_listMsgs.erase(it);
else
++it;
alpha = time_left >> 2;
if (time_left < 0)
alpha = 0;
}
alpha <<= 24;
g_renderer->RenderText(it->str.c_str(), left + 1, top + 1, 0x000000 | alpha);
g_renderer->RenderText(it->str.c_str(), left, top, 0xffff30 | alpha);
top += 15;
if (time_left <= 0)
it = s_msgList.erase(it);
else
++it;
}
}
void ClearMessages()
{
std::list<MESSAGE>::iterator it = s_listMsgs.begin();
while (it != s_listMsgs.end())
{
it = s_listMsgs.erase(it);
}
s_msgList.clear();
}
// On-Screen Display Callbacks
void AddCallback(CallbackType OnType, CallbackPtr FuncPtr, u32 UserData)
void AddCallback(CallbackType type, Callback cb)
{
m_callbacks.push_back(OSDCALLBACK(OnType, FuncPtr, UserData));
s_callbacks.insert(std::pair<CallbackType, Callback>(type, cb));
}
void DoCallbacks(CallbackType OnType)
void DoCallbacks(CallbackType type)
{
for (auto it = m_callbacks.begin(); it != m_callbacks.end(); ++it)
auto it_bounds = s_callbacks.equal_range(type);
for (auto it = it_bounds.first; it != it_bounds.second; ++it)
{
if (it->Type() == OnType)
it->Call();
it->second();
}
}

View File

@ -5,11 +5,13 @@
#ifndef _OSD_H_
#define _OSD_H_
namespace OSD
{
#include <functional>
#include <string>
namespace OSD
{
// On-screen message display
void AddMessage(const char* str, u32 ms = 2000);
void AddMessage(const std::string& str, u32 ms = 2000);
void DrawMessages(); // draw the current messages on the screen. Only call once per frame.
void ClearMessages();
@ -20,12 +22,10 @@ enum CallbackType
OSD_ONFRAME,
OSD_SHUTDOWN
};
typedef void(*CallbackPtr)(u32);
typedef std::function<void()> Callback;
void AddCallback(CallbackType OnType, CallbackPtr FuncPtr, u32 UserData);
void DoCallbacks(CallbackType OnType);
} // namespace
void AddCallback(CallbackType type, Callback cb);
void DoCallbacks(CallbackType type);
} // namespace OSD
#endif // _OSD_H_

View File

@ -97,6 +97,7 @@ void VideoConfig::Load(const char *ini_file)
iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true);
iniFile.Get("Hacks", "EFBCopyCacheEnable", &bEFBCopyCacheEnable, false);
iniFile.Get("Hacks", "EFBEmulateFormatChanges", &bEFBEmulateFormatChanges, false);
iniFile.Get("Hacks", "ForceDualSourceBlend", &bForceDualSourceBlend, false);
iniFile.Get("Hardware", "Adapter", &iAdapter, 0);
@ -265,6 +266,7 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled);
iniFile.Set("Hacks", "EFBCopyCacheEnable", bEFBCopyCacheEnable);
iniFile.Set("Hacks", "EFBEmulateFormatChanges", bEFBEmulateFormatChanges);
iniFile.Set("Hacks", "ForceDualSourceBlend", bForceDualSourceBlend);
iniFile.Set("Hardware", "Adapter", iAdapter);

View File

@ -124,7 +124,8 @@ struct VideoConfig
bool bEnablePixelLighting;
bool bHackedBufferUpload;
bool bFastDepthCalc;
//for dx9-backend
bool bForceDualSourceBlend;
int iLog; // CONF_ bits
int iSaveTargetId; // TODO: Should be dropped