// called from ---CPU--- thread bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size) { NetWiimote nw; static u8 previousSize[4] = { 4, 4, 4, 4 }; { std::lock_guard<std::recursive_mutex> lkp(m_crit.players); // in game mapping for this local Wiimote unsigned int in_game_num = LocalWiimoteToInGameWiimote(_number); // does this local Wiimote map in game? if (in_game_num < 4) { if (previousSize[in_game_num] == size) { nw.assign(data, data + size); do { // add to buffer m_wiimote_buffer[in_game_num].Push(nw); SendWiimoteState(in_game_num, nw); } while (m_wiimote_buffer[in_game_num].Size() <= m_target_buffer_size * 200 / 120); // TODO: add a seperate setting for wiimote buffer? } else { while (m_wiimote_buffer[in_game_num].Size() > 0) { // Reporting mode changed, so previous buffer is no good. m_wiimote_buffer[in_game_num].Pop(); } nw.resize(size, 0); m_wiimote_buffer[in_game_num].Push(nw); m_wiimote_buffer[in_game_num].Push(nw); m_wiimote_buffer[in_game_num].Push(nw); m_wiimote_buffer[in_game_num].Push(nw); m_wiimote_buffer[in_game_num].Push(nw); m_wiimote_buffer[in_game_num].Push(nw); previousSize[in_game_num] = size; } } } // unlock players while (previousSize[_number] == size && !m_wiimote_buffer[_number].Pop(nw)) { // wait for receiving thread to push some data Common::SleepCurrentThread(1); if (!m_is_running.load()) return false; } // Use a blank input, since we may not have any valid input. if (previousSize[_number] != size) { nw.resize(size, 0); m_wiimote_buffer[_number].Push(nw); m_wiimote_buffer[_number].Push(nw); m_wiimote_buffer[_number].Push(nw); m_wiimote_buffer[_number].Push(nw); m_wiimote_buffer[_number].Push(nw); } // We should have used a blank input last time, so now we just need to pop through the old buffer, until we reach a good input if (nw.size() != size) { u8 tries = 0; // Clear the buffer and wait for new input, since we probably just changed reporting mode. while (nw.size() != size) { while (!m_wiimote_buffer[_number].Pop(nw)) { Common::SleepCurrentThread(1); if (!m_is_running.load()) return false; } ++tries; if (tries > m_target_buffer_size * 200 / 120) break; } // If it still mismatches, it surely desynced if (size != nw.size()) { PanicAlertT("Netplay has desynced. There is no way to recover from this."); return false; } } previousSize[_number] = size; memcpy(data, nw.data(), size); return true; }
// called from ---CPU--- thread bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size, u8 reporting_mode) { NetWiimote nw; { std::lock_guard<std::recursive_mutex> lkp(m_crit.players); // Only send data, if this Wiimote is mapped to this player if (m_wiimote_map[_number] == m_local_player->pid) { nw.assign(data, data + size); do { // add to buffer m_wiimote_buffer[_number].Push(nw); SendWiimoteState(_number, nw); } while (m_wiimote_buffer[_number].Size() <= m_target_buffer_size * 200 / 120); // TODO: add a seperate setting for wiimote buffer? } } // unlock players while (m_wiimote_buffer[_number].Size() == 0) { if (!m_is_running.IsSet()) { return false; } // wait for receiving thread to push some data m_wii_pad_event.Wait(); } m_wiimote_buffer[_number].Pop(nw); // If the reporting mode has changed, we just need to pop through the buffer, // until we reach a good input if (nw[1] != reporting_mode) { u32 tries = 0; while (nw[1] != reporting_mode) { while (m_wiimote_buffer[_number].Size() == 0) { if (!m_is_running.IsSet()) { return false; } // wait for receiving thread to push some data m_wii_pad_event.Wait(); } m_wiimote_buffer[_number].Pop(nw); ++tries; if (tries > m_target_buffer_size * 200 / 120) break; } // If it still mismatches, it surely desynced if (nw[1] != reporting_mode) { PanicAlertT("Netplay has desynced. There is no way to recover from this."); return false; } } memcpy(data, nw.data(), size); return true; }