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/
19 #include "NetWindow.h"
22 #include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
23 #include "IPC_HLE/WII_IPC_HLE_WiiMote.h"
25 #include "HW/SI_DeviceGCController.h"
27 #include "HW/EXI_DeviceIPL.h"
30 // for wiimote/ OSD messages
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();
47 // called from ---GUI--- thread
49 : m_is_running(false), m_do_loop(true)
51 m_target_buffer_size
= 20;
55 void NetPlay_Enable(NetPlay
* const np
)
57 CritLocker
crit(::crit_netplay_ptr
); // probably safe without a lock
61 void NetPlay_Disable()
63 CritLocker
crit(::crit_netplay_ptr
);
67 // called from ---GUI--- thread
70 CritLocker
crit(crit_netplay_ptr
);
78 NetPlay::Player::Player()
80 memset(pad_map
, -1, sizeof(pad_map
));
83 // called from ---NETPLAY--- thread
84 void NetPlay::UpdateGUI()
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
)
98 m_dialog
->chat_msgs
.Push(msg
);
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') : '-');
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);
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?
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
)
165 m_pad_buffer
[in_game_num
].push(np
);
168 SendPadState(pad_nb
, np
);
170 m_crit
.buffer
.Leave();
173 m_crit
.players
.Leave();
175 //Common::Timer bufftimer;
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
)
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();
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);
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?
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?
240 m_crit
.buffer
.Enter();
241 m_wiimote_buffer
[in_game_num
].push(m_wiimote_input
[_number
]);
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");
259 NetWiimote
& nw
= m_wiimote_buffer
[_number
].front();
261 NetWiimote::const_iterator
262 i
= nw
.begin(), e
= nw
.end();
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
277 PanicAlert("Game is already running!");
281 AppendChatGUI(" -- STARTING GAME -- ");
284 NetPlay_Enable(this);
287 ::main_frame
->BootGame(path
);
288 //BootManager::BootCore(path);
290 // TODO: i dont know if i like this here
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
);
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!");
312 AppendChatGUI(" -- STOPPING GAME -- ");
314 m_is_running
= false;
318 ::main_frame
->DoStop();
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
329 if (numPAD
== m_local_player
->pad_map
[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
);
344 return netplay_ptr
->GetNetPads(numPAD
, &PadStatus
, (NetPad
*)PADStatus
) ? 1 : 0;
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
);
356 return 1272737767; // watev
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
);
368 return ::netplay_ptr
->GetPadNum(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);
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);
391 // return ::netplay_ptr->GetPadNum(_number); // just using gcpad mapping for now
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
);
405 // if (_Size >= RPT_SIZE_HACK)
407 // _Size -= RPT_SIZE_HACK;
412 // ::netplay_ptr->WiimoteInput(_number, _channelID, _pData, _Size);
413 // // don't use this packet