mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-04 20:32:51 +02:00
a4dd8c41a8
Add Hungarian translations by Delirious. Update Italian translations by RebuMan. Update German translations by JackyCola and LucasX. Update Greek translations by Gpower2. Update Frensh translations by Pascal. Make sure the game list is refreshed when the GC language is changed. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6826 8ced0084-cf51-0410-be5f-012b33b47a6e
403 lines
9.0 KiB
C++
403 lines
9.0 KiB
C++
// Copyright (C) 2003 Dolphin Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official SVN repository and contact information can be found at
|
|
// http://code.google.com/p/dolphin-emu/
|
|
|
|
#include "NetPlay.h"
|
|
#include "NetWindow.h"
|
|
|
|
// for wiimote
|
|
#include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
|
|
#include "IPC_HLE/WII_IPC_HLE_WiiMote.h"
|
|
// for gcpad
|
|
#include "HW/SI_DeviceGCController.h"
|
|
// for gctime
|
|
#include "HW/EXI_DeviceIPL.h"
|
|
// to start/stop game
|
|
#include "Frame.h"
|
|
// for wiimote/ OSD messages
|
|
#include "Core.h"
|
|
|
|
Common::CriticalSection crit_netplay_ptr;
|
|
static NetPlay* netplay_ptr = NULL;
|
|
extern CFrame* main_frame;
|
|
|
|
#define RPT_SIZE_HACK (1 << 16)
|
|
|
|
DEFINE_EVENT_TYPE(wxEVT_THREAD)
|
|
|
|
THREAD_RETURN NetPlayThreadFunc(void* arg)
|
|
{
|
|
((NetPlay*)arg)->Entry();
|
|
return 0;
|
|
}
|
|
|
|
// called from ---GUI--- thread
|
|
NetPlay::NetPlay()
|
|
: m_is_running(false), m_do_loop(true)
|
|
{
|
|
m_target_buffer_size = 20;
|
|
ClearBuffers();
|
|
}
|
|
|
|
void NetPlay_Enable(NetPlay* const np)
|
|
{
|
|
CritLocker crit(::crit_netplay_ptr); // probably safe without a lock
|
|
::netplay_ptr = np;
|
|
}
|
|
|
|
void NetPlay_Disable()
|
|
{
|
|
CritLocker crit(::crit_netplay_ptr);
|
|
::netplay_ptr = NULL;
|
|
}
|
|
|
|
// called from ---GUI--- thread
|
|
NetPlay::~NetPlay()
|
|
{
|
|
CritLocker crit(crit_netplay_ptr);
|
|
::netplay_ptr = NULL;
|
|
|
|
// not perfect
|
|
if (m_is_running)
|
|
StopGame();
|
|
}
|
|
|
|
NetPlay::Player::Player()
|
|
{
|
|
memset(pad_map, -1, sizeof(pad_map));
|
|
}
|
|
|
|
// called from ---NETPLAY--- thread
|
|
void NetPlay::UpdateGUI()
|
|
{
|
|
if (m_dialog)
|
|
{
|
|
wxCommandEvent evt(wxEVT_THREAD, 1);
|
|
m_dialog->GetEventHandler()->AddPendingEvent(evt);
|
|
}
|
|
}
|
|
|
|
// called from ---NETPLAY--- thread
|
|
void NetPlay::AppendChatGUI(const std::string& msg)
|
|
{
|
|
if (m_dialog)
|
|
{
|
|
m_dialog->chat_msgs.Push(msg);
|
|
// silly
|
|
UpdateGUI();
|
|
}
|
|
}
|
|
|
|
// called from ---GUI--- thread
|
|
std::string NetPlay::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 << '|';
|
|
return ss.str();
|
|
}
|
|
|
|
NetPad::NetPad()
|
|
{
|
|
nHi = 0x00808080;
|
|
nLo = 0x80800000;
|
|
}
|
|
|
|
NetPad::NetPad(const SPADStatus* const pad_status)
|
|
{
|
|
nHi = (u32)((u8)pad_status->stickY);
|
|
nHi |= (u32)((u8)pad_status->stickX << 8);
|
|
nHi |= (u32)((u16)pad_status->button << 16);
|
|
nHi |= 0x00800000;
|
|
nLo = (u8)pad_status->triggerRight;
|
|
nLo |= (u32)((u8)pad_status->triggerLeft << 8);
|
|
nLo |= (u32)((u8)pad_status->substickY << 16);
|
|
nLo |= (u32)((u8)pad_status->substickX << 24);
|
|
}
|
|
|
|
// called from ---NETPLAY--- thread
|
|
void NetPlay::ClearBuffers()
|
|
{
|
|
// clear pad buffers, Clear method isn't thread safe
|
|
for (unsigned int i=0; i<4; ++i)
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
|
|
// called from ---CPU--- thread
|
|
bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues)
|
|
{
|
|
m_crit.players.Enter(); // lock players
|
|
|
|
// in game mapping for this local pad
|
|
unsigned int in_game_num = m_local_player->pad_map[pad_nb];
|
|
|
|
// does this local pad map in game?
|
|
if (in_game_num < 4)
|
|
{
|
|
NetPad np(pad_status);
|
|
|
|
// adjust the buffer either up or down
|
|
// inserting multiple padstates or dropping states
|
|
while (m_pad_buffer[in_game_num].Size() <= m_target_buffer_size)
|
|
{
|
|
// add to buffer
|
|
m_pad_buffer[in_game_num].Push(np);
|
|
|
|
// send
|
|
SendPadState(pad_nb, np);
|
|
}
|
|
}
|
|
|
|
m_crit.players.Leave();
|
|
|
|
//Common::Timer bufftimer;
|
|
//bufftimer.Start();
|
|
|
|
// get padstate from buffer and send to game
|
|
while (!m_pad_buffer[pad_nb].Pop(*netvalues))
|
|
{
|
|
// wait for receiving thread to push some data
|
|
Common::SleepCurrentThread(1);
|
|
|
|
if (false == 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
|
|
|
|
}
|
|
|
|
//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 NetPlay::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;
|
|
}
|
|
|
|
m_crit.players.Leave();
|
|
}
|
|
|
|
// called from ---CPU--- thread
|
|
void NetPlay::WiimoteUpdate(int _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_wiimote_buffer[in_game_num].Push(m_wiimote_input[_number]);
|
|
|
|
// TODO: send it
|
|
|
|
m_wiimote_input[_number].clear();
|
|
}
|
|
|
|
m_crit.players.Leave();
|
|
|
|
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);
|
|
}
|
|
|
|
// called from ---GUI--- thread
|
|
bool NetPlay::StartGame(const std::string &path)
|
|
{
|
|
if (m_is_running)
|
|
{
|
|
PanicAlert("%s", _wxt("Game is already running!"));
|
|
return false;
|
|
}
|
|
|
|
AppendChatGUI(" -- STARTING GAME -- ");
|
|
|
|
m_is_running = true;
|
|
NetPlay_Enable(this);
|
|
|
|
ClearBuffers();
|
|
|
|
// boot game
|
|
::main_frame->BootGame(path);
|
|
|
|
// temporary
|
|
NetWiimote nw;
|
|
for (unsigned int i = 0; i<4; ++i)
|
|
for (unsigned int f = 0; f<2; ++f)
|
|
m_wiimote_buffer[i].Push(nw);
|
|
|
|
return true;
|
|
}
|
|
|
|
// called from ---GUI--- thread and ---NETPLAY--- thread (client side)
|
|
bool NetPlay::StopGame()
|
|
{
|
|
CritLocker game_lock(m_crit.game); // lock game state
|
|
|
|
if (false == m_is_running)
|
|
{
|
|
PanicAlert("%s", _wxt("Game isn't running!"));
|
|
return false;
|
|
}
|
|
|
|
AppendChatGUI(" -- STOPPING GAME -- ");
|
|
|
|
m_is_running = false;
|
|
NetPlay_Disable();
|
|
|
|
// stop game
|
|
::main_frame->DoStop();
|
|
|
|
return true;
|
|
}
|
|
|
|
// called from ---CPU--- thread
|
|
u8 NetPlay::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;
|
|
|
|
return i;
|
|
}
|
|
|
|
// stuff hacked into dolphin
|
|
|
|
// called from ---CPU--- thread
|
|
// Actual Core function which is called on every frame
|
|
bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
|
|
{
|
|
CritLocker crit(::crit_netplay_ptr);
|
|
|
|
if (::netplay_ptr)
|
|
return netplay_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus);
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// called from ---CPU--- thread
|
|
// so all players' games get the same time
|
|
u32 CEXIIPL::NetPlay_GetGCTime()
|
|
{
|
|
CritLocker crit(::crit_netplay_ptr);
|
|
|
|
if (::netplay_ptr)
|
|
return 1272737767; // watev
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
// called from ---CPU--- thread
|
|
// return the local pad num that should rumble given a ingame pad num
|
|
u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD)
|
|
{
|
|
CritLocker crit(::crit_netplay_ptr);
|
|
|
|
if (::netplay_ptr)
|
|
return ::netplay_ptr->GetPadNum(numPAD);
|
|
else
|
|
return 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_ptr);
|
|
|
|
//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);
|
|
|
|
//if (::netplay_ptr)
|
|
// return ::netplay_ptr->GetPadNum(_number); // just using gcpad mapping for now
|
|
//else
|
|
return _number;
|
|
}
|
|
|
|
// called from ---CPU--- thread
|
|
// intercept wiimote input callback
|
|
//bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int _number, u16 _channelID, const void* _pData, u32& _Size)
|
|
bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&)
|
|
{
|
|
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);
|
|
// // don't use this packet
|
|
return true;
|
|
// }
|
|
//}
|
|
else
|
|
return false;
|
|
}
|