GCPad/New Wiimote: Fixed issue 2848 (profiles not saving). Renamed DInput mouse axes...
[dolphin.git] / Source / Core / DolphinWX / Src / NetPlay.cpp
blobffdaf841aad17f2ffa900d262930943032e13e8d
1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
18 #include "NetPlay.h"
19 #include "NetWindow.h"
21 // for wiimote
22 #include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
23 #include "IPC_HLE/WII_IPC_HLE_WiiMote.h"
24 // for gcpad
25 #include "HW/SI_DeviceGCController.h"
26 // for gctime
27 #include "HW/EXI_DeviceIPL.h"
28 // to start/stop game
29 #include "Frame.h"
30 // for wiimote/ OSD messages
31 #include "Core.h"
33 Common::CriticalSection crit_netplay_ptr;
34 static NetPlay* netplay_ptr = NULL;
35 extern CFrame* main_frame;
37 #define RPT_SIZE_HACK (1 << 16)
39 DEFINE_EVENT_TYPE(wxEVT_THREAD)
41 THREAD_RETURN NetPlayThreadFunc(void* arg)
43 ((NetPlay*)arg)->Entry();
44 return 0;
47 // called from ---GUI--- thread
48 NetPlay::NetPlay()
49 : m_is_running(false), m_do_loop(true)
51 m_target_buffer_size = 20;
52 ClearBuffers();
55 void NetPlay_Enable(NetPlay* const np)
57 CritLocker crit(::crit_netplay_ptr); // probably safe without a lock
58 ::netplay_ptr = np;
61 void NetPlay_Disable()
63 CritLocker crit(::crit_netplay_ptr);
64 ::netplay_ptr = NULL;
67 // called from ---GUI--- thread
68 NetPlay::~NetPlay()
70 CritLocker crit(crit_netplay_ptr);
71 ::netplay_ptr = NULL;
73 // not perfect
74 if (m_is_running)
75 StopGame();
78 NetPlay::Player::Player()
80 memset(pad_map, -1, sizeof(pad_map));
83 // called from ---NETPLAY--- thread
84 void NetPlay::UpdateGUI()
86 if (m_dialog)
88 wxCommandEvent evt(wxEVT_THREAD, 1);
89 m_dialog->GetEventHandler()->AddPendingEvent(evt);
93 // called from ---NETPLAY--- thread
94 void NetPlay::AppendChatGUI(const std::string& msg)
96 if (m_dialog)
98 m_dialog->chat_msgs.Push(msg);
99 // silly
100 UpdateGUI();
104 // called from ---GUI--- thread
105 std::string NetPlay::Player::ToString() const
107 std::ostringstream ss;
108 ss << name << '[' << (char)(pid+'0') << "] : " << revision << " |";
109 for (unsigned int i=0; i<4; ++i)
110 ss << (pad_map[i]>=0 ? (char)(pad_map[i]+'1') : '-');
111 ss << '|';
112 return ss.str();
115 NetPad::NetPad()
117 nHi = 0x00808080;
118 nLo = 0x80800000;
121 NetPad::NetPad(const SPADStatus* const pad_status)
123 nHi = (u32)((u8)pad_status->stickY);
124 nHi |= (u32)((u8)pad_status->stickX << 8);
125 nHi |= (u32)((u16)pad_status->button << 16);
126 nHi |= 0x00800000;
127 nLo = (u8)pad_status->triggerRight;
128 nLo |= (u32)((u8)pad_status->triggerLeft << 8);
129 nLo |= (u32)((u8)pad_status->substickY << 16);
130 nLo |= (u32)((u8)pad_status->substickX << 24);
133 // called from ---NETPLAY--- thread
134 void NetPlay::ClearBuffers()
136 // clear pad buffers, no clear method ?
137 for (unsigned int i=0; i<4; ++i)
139 while (m_pad_buffer[i].size())
140 m_pad_buffer[i].pop();
141 while (m_wiimote_buffer[i].size())
142 m_wiimote_buffer[i].pop();
143 m_wiimote_input[i].clear();
147 // called from ---CPU--- thread
148 bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues)
150 m_crit.players.Enter(); // lock players
152 // in game mapping for this local pad
153 unsigned int in_game_num = m_local_player->pad_map[pad_nb];
155 // does this local pad map in game?
156 if (in_game_num < 4)
158 NetPad np(pad_status);
160 m_crit.buffer.Enter(); // lock buffer
161 // adjust the buffer either up or down
162 while (m_pad_buffer[in_game_num].size() <= m_target_buffer_size)
164 // add to buffer
165 m_pad_buffer[in_game_num].push(np);
167 // send
168 SendPadState(pad_nb, np);
170 m_crit.buffer.Leave();
173 m_crit.players.Leave();
175 //Common::Timer bufftimer;
176 //bufftimer.Start();
178 // get padstate from buffer and send to game
179 m_crit.buffer.Enter(); // lock buffer
180 while (0 == m_pad_buffer[pad_nb].size())
182 m_crit.buffer.Leave();
183 // wait for receiving thread to push some data
184 Common::SleepCurrentThread(1);
185 if (false == m_is_running)
186 return false;
187 m_crit.buffer.Enter();
189 // TODO: check the time of bufftimer here,
190 // if it gets pretty high, ask the user if they want to disconnect
193 *netvalues = m_pad_buffer[pad_nb].front();
194 m_pad_buffer[pad_nb].pop();
195 m_crit.buffer.Leave();
197 //u64 hangtime = bufftimer.GetTimeElapsed();
198 //if (hangtime > 10)
200 // std::ostringstream ss;
201 // ss << "Pad " << (int)pad_nb << ": Had to wait " << hangtime << "ms for pad data. (increase pad Buffer maybe)";
202 // Core::DisplayMessage(ss.str(), 1000);
205 return true;
208 // called from ---CPU--- thread
209 void NetPlay::WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 _Size)
211 //// in game mapping for this local wiimote
212 unsigned int in_game_num = m_local_player->pad_map[_number]; // just using gc pad_map for now
214 // does this local pad map in game?
215 if (in_game_num < 4)
217 m_crit.buffer.Enter();
219 m_wiimote_input[_number].resize(m_wiimote_input[_number].size() + 1);
220 m_wiimote_input[_number].back().assign((char*)_pData, (char*)_pData + _Size);
221 m_wiimote_input[_number].back().channel = _channelID;
223 m_crit.buffer.Leave();
226 m_crit.players.Leave();
229 // called from ---CPU--- thread
230 void NetPlay::WiimoteUpdate(int _number)
232 m_crit.players.Enter(); // lock players
234 // in game mapping for this local wiimote
235 unsigned int in_game_num = m_local_player->pad_map[_number]; // just using gc pad_map for now
237 // does this local pad map in game?
238 if (in_game_num < 4)
240 m_crit.buffer.Enter();
241 m_wiimote_buffer[in_game_num].push(m_wiimote_input[_number]);
243 // TODO: send it
245 m_wiimote_input[_number].clear();
246 m_crit.buffer.Leave();
249 m_crit.players.Leave();
251 m_crit.buffer.Enter();
253 if (0 == m_wiimote_buffer[_number].size())
255 //PanicAlert("PANIC");
256 return;
259 NetWiimote& nw = m_wiimote_buffer[_number].front();
261 NetWiimote::const_iterator
262 i = nw.begin(), e = nw.end();
263 for ( ; i!=e; ++i)
264 Core::Callback_WiimoteInterruptChannel(_number, i->channel, &(*i)[0], (u32)i->size() + RPT_SIZE_HACK);
266 m_wiimote_buffer[_number].pop();
267 m_crit.buffer.Leave();
270 // called from ---GUI--- thread
271 bool NetPlay::StartGame(const std::string &path)
273 CritLocker game_lock(m_crit.game); // lock game state
275 if (m_is_running)
277 PanicAlert("Game is already running!");
278 return false;
281 AppendChatGUI(" -- STARTING GAME -- ");
283 m_is_running = true;
284 NetPlay_Enable(this);
286 // boot game
287 ::main_frame->BootGame(path);
288 //BootManager::BootCore(path);
290 // TODO: i dont know if i like this here
291 ClearBuffers();
292 // temporary
293 NetWiimote nw;
294 for (unsigned int i = 0; i<4; ++i)
295 for (unsigned int f = 0; f<2; ++f)
296 m_wiimote_buffer[i].push(nw);
298 return true;
301 // called from ---GUI--- thread and ---NETPLAY--- thread (client side)
302 bool NetPlay::StopGame()
304 CritLocker game_lock(m_crit.game); // lock game state
306 if (false == m_is_running)
308 PanicAlert("Game isn't running!");
309 return false;
312 AppendChatGUI(" -- STOPPING GAME -- ");
314 m_is_running = false;
315 NetPlay_Disable();
317 // stop game
318 ::main_frame->DoStop();
320 return true;
323 // called from ---CPU--- thread
324 u8 NetPlay::GetPadNum(u8 numPAD)
326 // TODO: i don't like that this loop is running everytime there is rumble
327 unsigned int i = 0;
328 for (; i<4; ++i)
329 if (numPAD == m_local_player->pad_map[i])
330 break;
332 return i;
335 // stuff hacked into dolphin
337 // called from ---CPU--- thread
338 // Actual Core function which is called on every frame
339 int CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
341 CritLocker crit(::crit_netplay_ptr);
343 if (::netplay_ptr)
344 return netplay_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus) ? 1 : 0;
345 else
346 return 2;
349 // called from ---CPU--- thread
350 // so all players' games get the same time
351 u32 CEXIIPL::NetPlay_GetGCTime()
353 CritLocker crit(::crit_netplay_ptr);
355 if (::netplay_ptr)
356 return 1272737767; // watev
357 else
358 return 0;
361 // called from ---CPU--- thread
362 // return the local pad num that should rumble given a ingame pad num
363 u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD)
365 CritLocker crit(::crit_netplay_ptr);
367 if (::netplay_ptr)
368 return ::netplay_ptr->GetPadNum(numPAD);
369 else
370 return numPAD;
373 // called from ---CPU--- thread
374 // wiimote update / used for frame counting
375 //void CWII_IPC_HLE_Device_usb_oh1_57e_305::NetPlay_WiimoteUpdate(int _number)
376 void CWII_IPC_HLE_Device_usb_oh1_57e_305::NetPlay_WiimoteUpdate(int)
378 //CritLocker crit(::crit_netplay_ptr);
380 //if (::netplay_ptr)
381 // ::netplay_ptr->WiimoteUpdate(_number);
384 // called from ---CPU--- thread
386 int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number)
388 //CritLocker crit(::crit_netplay_ptr);
390 //if (::netplay_ptr)
391 // return ::netplay_ptr->GetPadNum(_number); // just using gcpad mapping for now
392 //else
393 return _number;
396 // called from ---CPU--- thread
397 // intercept wiimote input callback
398 //bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int _number, u16 _channelID, const void* _pData, u32& _Size)
399 bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&)
401 CritLocker crit(::crit_netplay_ptr);
403 if (::netplay_ptr)
405 // if (_Size >= RPT_SIZE_HACK)
406 // {
407 // _Size -= RPT_SIZE_HACK;
408 // return false;
409 // }
410 // else
411 // {
412 // ::netplay_ptr->WiimoteInput(_number, _channelID, _pData, _Size);
413 // // don't use this packet
414 return true;
415 // }
417 else
418 return false;