mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-03-12 14:46:49 +01:00
Netplay: Completely rewrite Wiimote syncing logic to be similar to the GameCube controller one.
This commit is contained in:
parent
f8518b2ff6
commit
aade584180
@ -498,9 +498,6 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
|||||||
if (core_parameter.bWii && !Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED))
|
if (core_parameter.bWii && !Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED))
|
||||||
{
|
{
|
||||||
Wiimote::LoadConfig();
|
Wiimote::LoadConfig();
|
||||||
|
|
||||||
if (NetPlay::IsNetPlayRunning())
|
|
||||||
NetPlay::SetupWiimotes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeLook::LoadInputConfig();
|
FreeLook::LoadInputConfig();
|
||||||
|
@ -94,8 +94,6 @@ ControllerEmu::ControlGroup* GetDrawsomeTabletGroup(int number,
|
|||||||
WiimoteEmu::DrawsomeTabletGroup group);
|
WiimoteEmu::DrawsomeTabletGroup group);
|
||||||
ControllerEmu::ControlGroup* GetTaTaConGroup(int number, WiimoteEmu::TaTaConGroup group);
|
ControllerEmu::ControlGroup* GetTaTaConGroup(int number, WiimoteEmu::TaTaConGroup group);
|
||||||
ControllerEmu::ControlGroup* GetShinkansenGroup(int number, WiimoteEmu::ShinkansenGroup group);
|
ControllerEmu::ControlGroup* GetShinkansenGroup(int number, WiimoteEmu::ShinkansenGroup group);
|
||||||
|
|
||||||
bool NetPlay_GetButtonPress(int wiimote, bool pressed);
|
|
||||||
} // namespace Wiimote
|
} // namespace Wiimote
|
||||||
|
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
|
@ -156,6 +156,9 @@ void Wiimote::HandleExtensionSwap(ExtensionNumber desired_extension_number,
|
|||||||
|
|
||||||
if (m_is_motion_plus_attached && !desired_motion_plus)
|
if (m_is_motion_plus_attached && !desired_motion_plus)
|
||||||
{
|
{
|
||||||
|
INFO_LOG_FMT(WIIMOTE, "Detaching Motion Plus (Wiimote {} in slot {})", m_index,
|
||||||
|
m_bt_device_index);
|
||||||
|
|
||||||
// M+ is attached and it's not wanted, so remove it.
|
// M+ is attached and it's not wanted, so remove it.
|
||||||
m_extension_port.AttachExtension(GetNoneExtension());
|
m_extension_port.AttachExtension(GetNoneExtension());
|
||||||
m_is_motion_plus_attached = false;
|
m_is_motion_plus_attached = false;
|
||||||
@ -180,6 +183,9 @@ void Wiimote::HandleExtensionSwap(ExtensionNumber desired_extension_number,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
INFO_LOG_FMT(WIIMOTE, "Attaching Motion Plus (Wiimote {} in slot {})", m_index,
|
||||||
|
m_bt_device_index);
|
||||||
|
|
||||||
// No extension attached so attach M+.
|
// No extension attached so attach M+.
|
||||||
m_is_motion_plus_attached = true;
|
m_is_motion_plus_attached = true;
|
||||||
m_extension_port.AttachExtension(&m_motion_plus);
|
m_extension_port.AttachExtension(&m_motion_plus);
|
||||||
@ -194,12 +200,18 @@ void Wiimote::HandleExtensionSwap(ExtensionNumber desired_extension_number,
|
|||||||
// A different extension is wanted (either by user or by the M+ logic above)
|
// A different extension is wanted (either by user or by the M+ logic above)
|
||||||
if (GetActiveExtensionNumber() != ExtensionNumber::NONE)
|
if (GetActiveExtensionNumber() != ExtensionNumber::NONE)
|
||||||
{
|
{
|
||||||
|
INFO_LOG_FMT(WIIMOTE, "Detaching Extension (Wiimote {} in slot {})", m_index,
|
||||||
|
m_bt_device_index);
|
||||||
|
|
||||||
// First we must detach the current extension.
|
// First we must detach the current extension.
|
||||||
// The next call will change to the new extension if needed.
|
// The next call will change to the new extension if needed.
|
||||||
m_active_extension = ExtensionNumber::NONE;
|
m_active_extension = ExtensionNumber::NONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
INFO_LOG_FMT(WIIMOTE, "Switching to Extension {} (Wiimote {} in slot {})",
|
||||||
|
desired_extension_number, m_index, m_bt_device_index);
|
||||||
|
|
||||||
m_active_extension = desired_extension_number;
|
m_active_extension = desired_extension_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/HW/Wiimote.h"
|
#include "Core/HW/Wiimote.h"
|
||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
#include "Core/NetPlayClient.h"
|
|
||||||
|
|
||||||
#include "Core/HW/WiimoteCommon/WiimoteConstants.h"
|
#include "Core/HW/WiimoteCommon/WiimoteConstants.h"
|
||||||
#include "Core/HW/WiimoteCommon/WiimoteHid.h"
|
#include "Core/HW/WiimoteCommon/WiimoteHid.h"
|
||||||
@ -634,15 +633,6 @@ void Wiimote::SendDataReport(const DesiredWiimoteState& target_state)
|
|||||||
GetExtensionEncryptionKey());
|
GetExtensionEncryptionKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetPlay::IsNetPlayRunning())
|
|
||||||
{
|
|
||||||
NetPlay_GetWiimoteData(m_index, rpt_builder.GetDataPtr(), rpt_builder.GetDataSize(),
|
|
||||||
u8(m_reporting_mode));
|
|
||||||
|
|
||||||
// TODO: clean up how m_status.buttons is updated.
|
|
||||||
rpt_builder.GetCoreData(&m_status.buttons);
|
|
||||||
}
|
|
||||||
|
|
||||||
Movie::CheckWiimoteStatus(m_bt_device_index, rpt_builder, m_active_extension,
|
Movie::CheckWiimoteStatus(m_bt_device_index, rpt_builder, m_active_extension,
|
||||||
GetExtensionEncryptionKey());
|
GetExtensionEncryptionKey());
|
||||||
|
|
||||||
|
@ -210,8 +210,6 @@ private:
|
|||||||
Extension* GetActiveExtension() const;
|
Extension* GetActiveExtension() const;
|
||||||
Extension* GetNoneExtension() const;
|
Extension* GetNoneExtension() const;
|
||||||
|
|
||||||
bool NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size, u8 reporting_mode);
|
|
||||||
|
|
||||||
// TODO: Kill this nonsensical function used for TAS:
|
// TODO: Kill this nonsensical function used for TAS:
|
||||||
EncryptionKey GetExtensionEncryptionKey() const;
|
EncryptionKey GetExtensionEncryptionKey() const;
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
|
#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
|
||||||
#include "Core/IOS/Device.h"
|
#include "Core/IOS/Device.h"
|
||||||
#include "Core/IOS/IOS.h"
|
#include "Core/IOS/IOS.h"
|
||||||
|
#include "Core/NetPlayClient.h"
|
||||||
|
#include "Core/NetPlayProto.h"
|
||||||
#include "Core/SysConf.h"
|
#include "Core/SysConf.h"
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
|
|
||||||
@ -59,7 +61,9 @@ BluetoothEmuDevice::BluetoothEmuDevice(Kernel& ios, const std::string& device_na
|
|||||||
DEBUG_LOG_FMT(IOS_WIIMOTE, "Wii Remote {} BT ID {:x},{:x},{:x},{:x},{:x},{:x}", i, tmp_bd[0],
|
DEBUG_LOG_FMT(IOS_WIIMOTE, "Wii Remote {} BT ID {:x},{:x},{:x},{:x},{:x},{:x}", i, tmp_bd[0],
|
||||||
tmp_bd[1], tmp_bd[2], tmp_bd[3], tmp_bd[4], tmp_bd[5]);
|
tmp_bd[1], tmp_bd[2], tmp_bd[3], tmp_bd[4], tmp_bd[5]);
|
||||||
|
|
||||||
m_wiimotes[i] = std::make_unique<WiimoteDevice>(this, tmp_bd, i);
|
const unsigned int hid_source_number =
|
||||||
|
NetPlay::IsNetPlayRunning() ? NetPlay::NetPlay_GetLocalWiimoteForSlot(i) : i;
|
||||||
|
m_wiimotes[i] = std::make_unique<WiimoteDevice>(this, tmp_bd, hid_source_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_dinf.num_registered = MAX_BBMOTES;
|
bt_dinf.num_registered = MAX_BBMOTES;
|
||||||
@ -348,6 +352,21 @@ void BluetoothEmuDevice::Update()
|
|||||||
for (size_t i = 0; i < m_wiimotes.size(); ++i)
|
for (size_t i = 0; i < m_wiimotes.size(); ++i)
|
||||||
next_call[i] = m_wiimotes[i]->PrepareInput(&wiimote_states[i]);
|
next_call[i] = m_wiimotes[i]->PrepareInput(&wiimote_states[i]);
|
||||||
|
|
||||||
|
if (NetPlay::IsNetPlayRunning())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
if (next_call[i] != WiimoteDevice::NextUpdateInputCall::None)
|
||||||
|
{
|
||||||
|
WiimoteEmu::SerializedWiimoteState serialized_state =
|
||||||
|
WiimoteEmu::SerializeDesiredState(wiimote_states[i]);
|
||||||
|
NetPlay::NetPlay_GetWiimoteData(static_cast<int>(i), &serialized_state);
|
||||||
|
if (!WiimoteEmu::DeserializeDesiredState(&wiimote_states[i], serialized_state))
|
||||||
|
PanicAlertFmtT("Received invalid Wii Remote data from Netplay.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_wiimotes.size(); ++i)
|
for (size_t i = 0; i < m_wiimotes.size(); ++i)
|
||||||
m_wiimotes[i]->UpdateInput(next_call[i], wiimote_states[i]);
|
m_wiimotes[i]->UpdateInput(next_call[i], wiimote_states[i]);
|
||||||
|
|
||||||
|
@ -10,8 +10,10 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <span>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -54,6 +56,7 @@
|
|||||||
#include "Core/HW/Sram.h"
|
#include "Core/HW/Sram.h"
|
||||||
#include "Core/HW/WiiSave.h"
|
#include "Core/HW/WiiSave.h"
|
||||||
#include "Core/HW/WiiSaveStructs.h"
|
#include "Core/HW/WiiSaveStructs.h"
|
||||||
|
#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||||
#include "Core/IOS/FS/FileSystem.h"
|
#include "Core/IOS/FS/FileSystem.h"
|
||||||
@ -695,20 +698,29 @@ void NetPlayClient::OnPadHostData(sf::Packet& packet)
|
|||||||
|
|
||||||
void NetPlayClient::OnWiimoteData(sf::Packet& packet)
|
void NetPlayClient::OnWiimoteData(sf::Packet& packet)
|
||||||
{
|
{
|
||||||
PadIndex map;
|
while (!packet.endOfPacket())
|
||||||
WiimoteInput nw;
|
{
|
||||||
u8 size;
|
PadIndex map;
|
||||||
|
packet >> map;
|
||||||
|
|
||||||
packet >> map >> nw.report_id >> size;
|
WiimoteEmu::SerializedWiimoteState pad;
|
||||||
|
packet >> pad.length;
|
||||||
|
ASSERT(pad.length <= pad.data.size());
|
||||||
|
if (pad.length <= pad.data.size())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < pad.length; ++i)
|
||||||
|
packet >> pad.data[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pad.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
nw.data.resize(size);
|
// Trusting server for good map value (>=0 && <4)
|
||||||
for (auto& byte : nw.data)
|
// add to pad buffer
|
||||||
packet >> byte;
|
m_wiimote_buffer.at(map).Push(pad);
|
||||||
|
m_wii_pad_event.Set();
|
||||||
// Trusting server for good map value (>=0 && <4)
|
}
|
||||||
// add to Wiimote buffer
|
|
||||||
m_wiimote_buffer.at(map).Push(nw);
|
|
||||||
m_wii_pad_event.Set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetPlayClient::OnPadBuffer(sf::Packet& packet)
|
void NetPlayClient::OnPadBuffer(sf::Packet& packet)
|
||||||
@ -886,9 +898,6 @@ void NetPlayClient::OnStartGame(sf::Packet& packet)
|
|||||||
packet >> m_net_settings.save_data_region;
|
packet >> m_net_settings.save_data_region;
|
||||||
packet >> m_net_settings.sync_codes;
|
packet >> m_net_settings.sync_codes;
|
||||||
|
|
||||||
for (int& extension : m_net_settings.wiimote_extension)
|
|
||||||
packet >> extension;
|
|
||||||
|
|
||||||
packet >> m_net_settings.golf_mode;
|
packet >> m_net_settings.golf_mode;
|
||||||
packet >> m_net_settings.use_fma;
|
packet >> m_net_settings.use_fma;
|
||||||
packet >> m_net_settings.hide_remote_gbas;
|
packet >> m_net_settings.hide_remote_gbas;
|
||||||
@ -1619,15 +1628,14 @@ void NetPlayClient::AddPadStateToPacket(const int in_game_pad, const GCPadStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called from ---CPU--- thread
|
// called from ---CPU--- thread
|
||||||
void NetPlayClient::SendWiimoteState(const int in_game_pad, const WiimoteInput& nw)
|
void NetPlayClient::AddWiimoteStateToPacket(int in_game_pad,
|
||||||
|
const WiimoteEmu::SerializedWiimoteState& state,
|
||||||
|
sf::Packet& packet)
|
||||||
{
|
{
|
||||||
sf::Packet packet;
|
|
||||||
packet << MessageID::WiimoteData;
|
|
||||||
packet << static_cast<PadIndex>(in_game_pad);
|
packet << static_cast<PadIndex>(in_game_pad);
|
||||||
packet << static_cast<u8>(nw.report_id);
|
packet << state.length;
|
||||||
packet << static_cast<u8>(nw.data.size());
|
for (size_t i = 0; i < state.length; ++i)
|
||||||
packet.append(nw.data.data(), nw.data.size());
|
packet << state.data[i];
|
||||||
SendAsync(std::move(packet));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from ---GUI--- thread
|
// called from ---GUI--- thread
|
||||||
@ -2042,79 +2050,43 @@ u64 NetPlayClient::GetInitialRTCValue() const
|
|||||||
return m_initial_rtc;
|
return m_initial_rtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetPlayClient::WaitForWiimoteBuffer(int _number)
|
// called from ---CPU--- thread
|
||||||
|
bool NetPlayClient::WiimoteUpdate(int wiimote_number,
|
||||||
|
WiimoteEmu::SerializedWiimoteState* target_state)
|
||||||
{
|
{
|
||||||
while (m_wiimote_buffer[_number].Size() == 0)
|
{
|
||||||
|
const int local_wiimote = InGameWiimoteToLocalWiimote(wiimote_number);
|
||||||
|
DEBUG_LOG_FMT(
|
||||||
|
NETPLAY,
|
||||||
|
"Entering WiimoteUpdate() with wiimote_number {}, local_wiimote {}, target_state [{:02x}]",
|
||||||
|
wiimote_number, local_wiimote,
|
||||||
|
fmt::join(std::span(target_state->data.data(), target_state->length), ", "));
|
||||||
|
if (local_wiimote < 4)
|
||||||
|
{
|
||||||
|
sf::Packet packet;
|
||||||
|
packet << MessageID::WiimoteData;
|
||||||
|
if (AddLocalWiimoteToBuffer(local_wiimote, *target_state, packet))
|
||||||
|
SendAsync(std::move(packet));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, we either use the data pushed earlier, or wait for the
|
||||||
|
// other clients to send it to us
|
||||||
|
while (m_wiimote_buffer[wiimote_number].Size() == 0)
|
||||||
{
|
{
|
||||||
if (!m_is_running.IsSet())
|
if (!m_is_running.IsSet())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for receiving thread to push some data
|
|
||||||
m_wii_pad_event.Wait();
|
m_wii_pad_event.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
m_wiimote_buffer[wiimote_number].Pop(*target_state);
|
||||||
}
|
|
||||||
|
|
||||||
// called from ---CPU--- thread
|
DEBUG_LOG_FMT(NETPLAY, "Exiting WiimoteUpdate() with wiimote_number {}, target_state [{:02x}]",
|
||||||
bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const std::size_t size, u8 reporting_mode)
|
wiimote_number,
|
||||||
{
|
fmt::join(std::span(target_state->data.data(), target_state->length), ", "));
|
||||||
WiimoteInput nw;
|
|
||||||
nw.report_id = reporting_mode;
|
|
||||||
{
|
|
||||||
std::lock_guard 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.data.assign(data, data + size);
|
|
||||||
|
|
||||||
// TODO: add a seperate setting for wiimote buffer?
|
|
||||||
while (m_wiimote_buffer[_number].Size() <= m_target_buffer_size * 200 / 120)
|
|
||||||
{
|
|
||||||
// add to buffer
|
|
||||||
m_wiimote_buffer[_number].Push(nw);
|
|
||||||
|
|
||||||
SendWiimoteState(_number, nw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // unlock players
|
|
||||||
|
|
||||||
if (!WaitForWiimoteBuffer(_number))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
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.report_id != reporting_mode)
|
|
||||||
{
|
|
||||||
u32 tries = 0;
|
|
||||||
while (nw.report_id != reporting_mode)
|
|
||||||
{
|
|
||||||
if (!WaitForWiimoteBuffer(_number))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
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.report_id != reporting_mode)
|
|
||||||
{
|
|
||||||
PanicAlertFmtT("Netplay has desynced. There is no way to recover from this.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(nw.data.size() == size);
|
|
||||||
std::copy(nw.data.begin(), nw.data.end(), data);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2171,6 +2143,28 @@ bool NetPlayClient::PollLocalPad(const int local_pad, sf::Packet& packet)
|
|||||||
return data_added;
|
return data_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetPlayClient::AddLocalWiimoteToBuffer(const int local_wiimote,
|
||||||
|
const WiimoteEmu::SerializedWiimoteState& state,
|
||||||
|
sf::Packet& packet)
|
||||||
|
{
|
||||||
|
const int ingame_pad = LocalWiimoteToInGameWiimote(local_wiimote);
|
||||||
|
bool data_added = false;
|
||||||
|
|
||||||
|
// adjust the buffer either up or down
|
||||||
|
// inserting multiple padstates or dropping states
|
||||||
|
while (m_wiimote_buffer[ingame_pad].Size() <= m_target_buffer_size)
|
||||||
|
{
|
||||||
|
// add to buffer
|
||||||
|
m_wiimote_buffer[ingame_pad].Push(state);
|
||||||
|
|
||||||
|
// add to packet
|
||||||
|
AddWiimoteStateToPacket(ingame_pad, state, packet);
|
||||||
|
data_added = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data_added;
|
||||||
|
}
|
||||||
|
|
||||||
void NetPlayClient::SendPadHostPoll(const PadIndex pad_num)
|
void NetPlayClient::SendPadHostPoll(const PadIndex pad_num)
|
||||||
{
|
{
|
||||||
// Here we handle polling for the Host Input Authority and Golf modes. Pad data is "polled" from
|
// Here we handle polling for the Host Input Authority and Golf modes. Pad data is "polled" from
|
||||||
@ -2335,25 +2329,25 @@ int NetPlayClient::NumLocalPads() const
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
int NetPlayClient::InGamePadToLocalPad(int ingame_pad) const
|
static int InGameToLocal(int ingame_pad, const PadMappingArray& pad_map, PlayerId local_player_pid)
|
||||||
{
|
{
|
||||||
// not our pad
|
// not our pad
|
||||||
if (m_pad_map[ingame_pad] != m_local_player->pid)
|
if (pad_map[ingame_pad] != local_player_pid)
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
int local_pad = 0;
|
int local_pad = 0;
|
||||||
int pad = 0;
|
int pad = 0;
|
||||||
|
|
||||||
for (; pad < ingame_pad; pad++)
|
for (; pad < ingame_pad; ++pad)
|
||||||
{
|
{
|
||||||
if (m_pad_map[pad] == m_local_player->pid)
|
if (pad_map[pad] == local_player_pid)
|
||||||
local_pad++;
|
local_pad++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return local_pad;
|
return local_pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NetPlayClient::LocalPadToInGamePad(int local_pad) const
|
static int LocalToInGame(int local_pad, const PadMappingArray& pad_map, PlayerId local_player_pid)
|
||||||
{
|
{
|
||||||
// Figure out which in-game pad maps to which local pad.
|
// Figure out which in-game pad maps to which local pad.
|
||||||
// The logic we have here is that the local slots always
|
// The logic we have here is that the local slots always
|
||||||
@ -2362,7 +2356,7 @@ int NetPlayClient::LocalPadToInGamePad(int local_pad) const
|
|||||||
int ingame_pad = 0;
|
int ingame_pad = 0;
|
||||||
for (; ingame_pad < 4; ingame_pad++)
|
for (; ingame_pad < 4; ingame_pad++)
|
||||||
{
|
{
|
||||||
if (m_pad_map[ingame_pad] == m_local_player->pid)
|
if (pad_map[ingame_pad] == local_player_pid)
|
||||||
local_pad_count++;
|
local_pad_count++;
|
||||||
|
|
||||||
if (local_pad_count == local_pad)
|
if (local_pad_count == local_pad)
|
||||||
@ -2372,6 +2366,26 @@ int NetPlayClient::LocalPadToInGamePad(int local_pad) const
|
|||||||
return ingame_pad;
|
return ingame_pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int NetPlayClient::InGamePadToLocalPad(int ingame_pad) const
|
||||||
|
{
|
||||||
|
return InGameToLocal(ingame_pad, m_pad_map, m_local_player->pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NetPlayClient::LocalPadToInGamePad(int local_pad) const
|
||||||
|
{
|
||||||
|
return LocalToInGame(local_pad, m_pad_map, m_local_player->pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NetPlayClient::InGameWiimoteToLocalWiimote(int ingame_wiimote) const
|
||||||
|
{
|
||||||
|
return InGameToLocal(ingame_wiimote, m_wiimote_map, m_local_player->pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NetPlayClient::LocalWiimoteToInGameWiimote(int local_wiimote) const
|
||||||
|
{
|
||||||
|
return LocalToInGame(local_wiimote, m_wiimote_map, m_local_player->pid);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetPlayClient::PlayerHasControllerMapped(const PlayerId pid) const
|
bool NetPlayClient::PlayerHasControllerMapped(const PlayerId pid) const
|
||||||
{
|
{
|
||||||
const auto mapping_matches_player_id = [pid](const PlayerId& mapping) { return mapping == pid; };
|
const auto mapping_matches_player_id = [pid](const PlayerId& mapping) { return mapping == pid; };
|
||||||
@ -2385,6 +2399,11 @@ bool NetPlayClient::IsLocalPlayer(const PlayerId pid) const
|
|||||||
return pid == m_local_player->pid;
|
return pid == m_local_player->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PlayerId& NetPlayClient::GetLocalPlayerId() const
|
||||||
|
{
|
||||||
|
return m_local_player->pid;
|
||||||
|
}
|
||||||
|
|
||||||
void NetPlayClient::SendGameStatus()
|
void NetPlayClient::SendGameStatus()
|
||||||
{
|
{
|
||||||
sf::Packet packet;
|
sf::Packet packet;
|
||||||
@ -2580,23 +2599,6 @@ void SendPowerButtonEvent()
|
|||||||
netplay_client->SendPowerButtonEvent();
|
netplay_client->SendPowerButtonEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupWiimotes()
|
|
||||||
{
|
|
||||||
ASSERT(IsNetPlayRunning());
|
|
||||||
const NetSettings& netplay_settings = netplay_client->GetNetSettings();
|
|
||||||
const PadMappingArray& wiimote_map = netplay_client->GetWiimoteMapping();
|
|
||||||
for (size_t i = 0; i < netplay_settings.wiimote_extension.size(); i++)
|
|
||||||
{
|
|
||||||
if (wiimote_map[i] > 0)
|
|
||||||
{
|
|
||||||
static_cast<ControllerEmu::Attachments*>(
|
|
||||||
static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(int(i)))
|
|
||||||
->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments))
|
|
||||||
->SetSelectedAttachment(netplay_settings.wiimote_extension[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetGBASavePath(int pad_num)
|
std::string GetGBASavePath(int pad_num)
|
||||||
{
|
{
|
||||||
std::lock_guard lk(crit_netplay_client);
|
std::lock_guard lk(crit_netplay_client);
|
||||||
@ -2679,37 +2681,51 @@ bool SerialInterface::CSIDevice_GCController::NetPlay_GetInput(int pad_num, GCPa
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiimoteEmu::Wiimote::NetPlay_GetWiimoteData(int wiimote, u8* data, u8 size, u8 reporting_mode)
|
bool NetPlay::NetPlay_GetWiimoteData(int wiimote, WiimoteEmu::SerializedWiimoteState* target_state)
|
||||||
{
|
{
|
||||||
std::lock_guard lk(NetPlay::crit_netplay_client);
|
std::lock_guard lk(crit_netplay_client);
|
||||||
|
|
||||||
if (NetPlay::netplay_client)
|
if (netplay_client)
|
||||||
return NetPlay::netplay_client->WiimoteUpdate(wiimote, data, size, reporting_mode);
|
return netplay_client->WiimoteUpdate(wiimote, target_state);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync the info whether a button was pressed or not. Used for the reconnect on button press feature
|
unsigned int NetPlay::NetPlay_GetLocalWiimoteForSlot(unsigned int slot)
|
||||||
bool Wiimote::NetPlay_GetButtonPress(int wiimote, bool pressed)
|
|
||||||
{
|
{
|
||||||
std::lock_guard lk(NetPlay::crit_netplay_client);
|
if (slot >= std::tuple_size_v<PadMappingArray>)
|
||||||
|
return slot;
|
||||||
|
|
||||||
// Use the reporting mode 0 for the button pressed event, the real ones start at RT_REPORT_CORE
|
std::lock_guard lk(crit_netplay_client);
|
||||||
static const u8 BUTTON_PRESS_REPORTING_MODE = 0;
|
|
||||||
|
|
||||||
if (NetPlay::netplay_client)
|
if (!netplay_client)
|
||||||
|
return slot;
|
||||||
|
|
||||||
|
const auto& mapping = netplay_client->GetWiimoteMapping();
|
||||||
|
const auto& local_player_id = netplay_client->GetLocalPlayerId();
|
||||||
|
|
||||||
|
std::array<unsigned int, std::tuple_size_v<std::decay_t<decltype(mapping)>>> slot_map;
|
||||||
|
size_t player_count = 0;
|
||||||
|
for (size_t i = 0; i < mapping.size(); ++i)
|
||||||
{
|
{
|
||||||
std::array<u8, 1> data = {u8(pressed)};
|
if (mapping[i] == local_player_id)
|
||||||
if (NetPlay::netplay_client->WiimoteUpdate(wiimote, data.data(), data.size(),
|
|
||||||
BUTTON_PRESS_REPORTING_MODE))
|
|
||||||
{
|
{
|
||||||
return data[0];
|
slot_map[i] = static_cast<unsigned int>(player_count);
|
||||||
|
++player_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < mapping.size(); ++i)
|
||||||
|
{
|
||||||
|
if (mapping[i] != local_player_id)
|
||||||
|
{
|
||||||
|
slot_map[i] = static_cast<unsigned int>(player_count);
|
||||||
|
++player_count;
|
||||||
}
|
}
|
||||||
PanicAlertFmtT("Netplay has desynced in NetPlay_GetButtonPress()");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pressed;
|
INFO_LOG_FMT(NETPLAY, "Wiimote slot map: [{}]", fmt::join(slot_map, ", "));
|
||||||
|
|
||||||
|
return slot_map[slot];
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from ---CPU--- thread
|
// called from ---CPU--- thread
|
||||||
|
@ -35,6 +35,11 @@ namespace UICommon
|
|||||||
class GameFile;
|
class GameFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace WiimoteEmu
|
||||||
|
{
|
||||||
|
struct SerializedWiimoteState;
|
||||||
|
}
|
||||||
|
|
||||||
namespace NetPlay
|
namespace NetPlay
|
||||||
{
|
{
|
||||||
class NetPlayUI
|
class NetPlayUI
|
||||||
@ -129,7 +134,7 @@ public:
|
|||||||
std::string GetCurrentGolfer();
|
std::string GetCurrentGolfer();
|
||||||
|
|
||||||
// Send and receive pads values
|
// Send and receive pads values
|
||||||
bool WiimoteUpdate(int _number, u8* data, std::size_t size, u8 reporting_mode);
|
bool WiimoteUpdate(int wiimote_number, WiimoteEmu::SerializedWiimoteState* target_state);
|
||||||
bool GetNetPads(int pad_nb, bool from_vi, GCPadStatus* pad_status);
|
bool GetNetPads(int pad_nb, bool from_vi, GCPadStatus* pad_status);
|
||||||
|
|
||||||
u64 GetInitialRTCValue() const;
|
u64 GetInitialRTCValue() const;
|
||||||
@ -142,11 +147,14 @@ public:
|
|||||||
int NumLocalPads() const;
|
int NumLocalPads() const;
|
||||||
|
|
||||||
int InGamePadToLocalPad(int ingame_pad) const;
|
int InGamePadToLocalPad(int ingame_pad) const;
|
||||||
int LocalPadToInGamePad(int localPad) const;
|
int LocalPadToInGamePad(int local_pad) const;
|
||||||
|
int InGameWiimoteToLocalWiimote(int ingame_wiimote) const;
|
||||||
|
int LocalWiimoteToInGameWiimote(int local_wiimote) const;
|
||||||
|
|
||||||
bool PlayerHasControllerMapped(PlayerId pid) const;
|
bool PlayerHasControllerMapped(PlayerId pid) const;
|
||||||
bool LocalPlayerHasControllerMapped() const;
|
bool LocalPlayerHasControllerMapped() const;
|
||||||
bool IsLocalPlayer(PlayerId pid) const;
|
bool IsLocalPlayer(PlayerId pid) const;
|
||||||
|
const PlayerId& GetLocalPlayerId() const;
|
||||||
|
|
||||||
static void SendTimeBase();
|
static void SendTimeBase();
|
||||||
bool DoAllPlayersHaveGame();
|
bool DoAllPlayersHaveGame();
|
||||||
@ -182,7 +190,7 @@ protected:
|
|||||||
Common::SPSCQueue<AsyncQueueEntry, false> m_async_queue;
|
Common::SPSCQueue<AsyncQueueEntry, false> m_async_queue;
|
||||||
|
|
||||||
std::array<Common::SPSCQueue<GCPadStatus>, 4> m_pad_buffer;
|
std::array<Common::SPSCQueue<GCPadStatus>, 4> m_pad_buffer;
|
||||||
std::array<Common::SPSCQueue<WiimoteInput>, 4> m_wiimote_buffer;
|
std::array<Common::SPSCQueue<WiimoteEmu::SerializedWiimoteState>, 4> m_wiimote_buffer;
|
||||||
|
|
||||||
std::array<GCPadStatus, 4> m_last_pad_status{};
|
std::array<GCPadStatus, 4> m_last_pad_status{};
|
||||||
std::array<bool, 4> m_first_pad_status_received{};
|
std::array<bool, 4> m_first_pad_status_received{};
|
||||||
@ -242,9 +250,13 @@ private:
|
|||||||
bool PollLocalPad(int local_pad, sf::Packet& packet);
|
bool PollLocalPad(int local_pad, sf::Packet& packet);
|
||||||
void SendPadHostPoll(PadIndex pad_num);
|
void SendPadHostPoll(PadIndex pad_num);
|
||||||
|
|
||||||
|
bool AddLocalWiimoteToBuffer(int local_wiimote, const WiimoteEmu::SerializedWiimoteState& state,
|
||||||
|
sf::Packet& packet);
|
||||||
|
|
||||||
void UpdateDevices();
|
void UpdateDevices();
|
||||||
void AddPadStateToPacket(int in_game_pad, const GCPadStatus& np, sf::Packet& packet);
|
void AddPadStateToPacket(int in_game_pad, const GCPadStatus& np, sf::Packet& packet);
|
||||||
void SendWiimoteState(int in_game_pad, const WiimoteInput& nw);
|
void AddWiimoteStateToPacket(int in_game_pad, const WiimoteEmu::SerializedWiimoteState& np,
|
||||||
|
sf::Packet& packet);
|
||||||
void Send(const sf::Packet& packet, u8 channel_id = DEFAULT_CHANNEL);
|
void Send(const sf::Packet& packet, u8 channel_id = DEFAULT_CHANNEL);
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
bool Connect();
|
bool Connect();
|
||||||
@ -253,8 +265,6 @@ private:
|
|||||||
void DisplayPlayersPing();
|
void DisplayPlayersPing();
|
||||||
u32 GetPlayersMaxPing() const;
|
u32 GetPlayersMaxPing() const;
|
||||||
|
|
||||||
bool WaitForWiimoteBuffer(int _number);
|
|
||||||
|
|
||||||
void OnData(sf::Packet& packet);
|
void OnData(sf::Packet& packet);
|
||||||
void OnPlayerJoin(sf::Packet& packet);
|
void OnPlayerJoin(sf::Packet& packet);
|
||||||
void OnPlayerLeave(sf::Packet& packet);
|
void OnPlayerLeave(sf::Packet& packet);
|
||||||
@ -335,4 +345,6 @@ private:
|
|||||||
|
|
||||||
void NetPlay_Enable(NetPlayClient* const np);
|
void NetPlay_Enable(NetPlayClient* const np);
|
||||||
void NetPlay_Disable();
|
void NetPlay_Disable();
|
||||||
|
bool NetPlay_GetWiimoteData(int wiimote, WiimoteEmu::SerializedWiimoteState* target_state);
|
||||||
|
unsigned int NetPlay_GetLocalWiimoteForSlot(unsigned int slot);
|
||||||
} // namespace NetPlay
|
} // namespace NetPlay
|
||||||
|
@ -101,7 +101,6 @@ struct NetSettings
|
|||||||
bool strict_settings_sync = false;
|
bool strict_settings_sync = false;
|
||||||
bool sync_codes = false;
|
bool sync_codes = false;
|
||||||
std::string save_data_region;
|
std::string save_data_region;
|
||||||
std::array<int, 4> wiimote_extension{};
|
|
||||||
bool golf_mode = false;
|
bool golf_mode = false;
|
||||||
bool use_fma = false;
|
bool use_fma = false;
|
||||||
bool hide_remote_gbas = false;
|
bool hide_remote_gbas = false;
|
||||||
@ -228,11 +227,6 @@ enum : u8
|
|||||||
CHANNEL_COUNT
|
CHANNEL_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WiimoteInput
|
|
||||||
{
|
|
||||||
u8 report_id = 0;
|
|
||||||
std::vector<u8> data;
|
|
||||||
};
|
|
||||||
using PlayerId = u8;
|
using PlayerId = u8;
|
||||||
using FrameNum = u32;
|
using FrameNum = u32;
|
||||||
using PadIndex = s8;
|
using PadIndex = s8;
|
||||||
@ -260,7 +254,6 @@ std::string GetPlayerMappingString(PlayerId pid, const PadMappingArray& pad_map,
|
|||||||
bool IsNetPlayRunning();
|
bool IsNetPlayRunning();
|
||||||
void SetSIPollBatching(bool state);
|
void SetSIPollBatching(bool state);
|
||||||
void SendPowerButtonEvent();
|
void SendPowerButtonEvent();
|
||||||
void SetupWiimotes();
|
|
||||||
std::string GetGBASavePath(int pad_num);
|
std::string GetGBASavePath(int pad_num);
|
||||||
PadDetails GetPadDetails(int pad_num);
|
PadDetails GetPadDetails(int pad_num);
|
||||||
} // namespace NetPlay
|
} // namespace NetPlay
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#include "Core/HW/Sram.h"
|
#include "Core/HW/Sram.h"
|
||||||
#include "Core/HW/WiiSave.h"
|
#include "Core/HW/WiiSave.h"
|
||||||
#include "Core/HW/WiiSaveStructs.h"
|
#include "Core/HW/WiiSaveStructs.h"
|
||||||
|
#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||||
#include "Core/IOS/ES/ES.h"
|
#include "Core/IOS/ES/ES.h"
|
||||||
@ -827,27 +828,33 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
|
|||||||
if (player.current_game != m_current_game)
|
if (player.current_game != m_current_game)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
PadIndex map;
|
|
||||||
u8 size;
|
|
||||||
packet >> map >> size;
|
|
||||||
std::vector<u8> data(size);
|
|
||||||
for (u8& byte : data)
|
|
||||||
packet >> byte;
|
|
||||||
|
|
||||||
// If the data is not from the correct player,
|
|
||||||
// then disconnect them.
|
|
||||||
if (m_wiimote_map.at(map) != player.pid)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// relay to clients
|
|
||||||
sf::Packet spac;
|
sf::Packet spac;
|
||||||
spac << MessageID::WiimoteData;
|
spac << MessageID::WiimoteData;
|
||||||
spac << map;
|
|
||||||
spac << size;
|
while (!packet.endOfPacket())
|
||||||
for (const u8& byte : data)
|
{
|
||||||
spac << byte;
|
PadIndex map;
|
||||||
|
packet >> map;
|
||||||
|
|
||||||
|
// If the data is not from the correct player,
|
||||||
|
// then disconnect them.
|
||||||
|
if (m_wiimote_map.at(map) != player.pid)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiimoteEmu::SerializedWiimoteState pad;
|
||||||
|
packet >> pad.length;
|
||||||
|
if (pad.length > pad.data.size())
|
||||||
|
return 1;
|
||||||
|
for (size_t i = 0; i < pad.length; ++i)
|
||||||
|
packet >> pad.data[i];
|
||||||
|
|
||||||
|
spac << map;
|
||||||
|
spac << pad.length;
|
||||||
|
for (size_t i = 0; i < pad.length; ++i)
|
||||||
|
spac << pad.data[i];
|
||||||
|
}
|
||||||
|
|
||||||
SendToClients(spac, player.pid);
|
SendToClients(spac, player.pid);
|
||||||
}
|
}
|
||||||
@ -1518,16 +1525,6 @@ bool NetPlayServer::StartGame()
|
|||||||
spac << region;
|
spac << region;
|
||||||
spac << m_settings.sync_codes;
|
spac << m_settings.sync_codes;
|
||||||
|
|
||||||
for (size_t i = 0; i < m_settings.wiimote_extension.size(); i++)
|
|
||||||
{
|
|
||||||
const int extension =
|
|
||||||
static_cast<ControllerEmu::Attachments*>(
|
|
||||||
static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(int(i)))
|
|
||||||
->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments))
|
|
||||||
->GetSelectedAttachment();
|
|
||||||
spac << extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
spac << m_settings.golf_mode;
|
spac << m_settings.golf_mode;
|
||||||
spac << m_settings.use_fma;
|
spac << m_settings.use_fma;
|
||||||
spac << m_settings.hide_remote_gbas;
|
spac << m_settings.hide_remote_gbas;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user