mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
Merge pull request #7871 from jordan-woyak/wm-real-cleanup
WiimoteReal: Improve state changes and code cleanups.
This commit is contained in:
commit
e636b3e712
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
@ -137,21 +138,29 @@ void Pause()
|
|||||||
// An L2CAP packet is passed from the Core to the Wiimote on the HID CONTROL channel.
|
// An L2CAP packet is passed from the Core to the Wiimote on the HID CONTROL channel.
|
||||||
void ControlChannel(int number, u16 channel_id, const void* data, u32 size)
|
void ControlChannel(int number, u16 channel_id, const void* data, u32 size)
|
||||||
{
|
{
|
||||||
if (g_wiimote_sources[number])
|
if (WIIMOTE_SRC_EMU == g_wiimote_sources[number])
|
||||||
{
|
{
|
||||||
static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
||||||
->ControlChannel(channel_id, data, size);
|
->ControlChannel(channel_id, data, size);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WiimoteReal::ControlChannel(number, channel_id, data, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// An L2CAP packet is passed from the Core to the Wiimote on the HID INTERRUPT channel.
|
// An L2CAP packet is passed from the Core to the Wiimote on the HID INTERRUPT channel.
|
||||||
void InterruptChannel(int number, u16 channel_id, const void* data, u32 size)
|
void InterruptChannel(int number, u16 channel_id, const void* data, u32 size)
|
||||||
{
|
{
|
||||||
if (g_wiimote_sources[number])
|
if (WIIMOTE_SRC_EMU == g_wiimote_sources[number])
|
||||||
{
|
{
|
||||||
static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
||||||
->InterruptChannel(channel_id, data, size);
|
->InterruptChannel(channel_id, data, size);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WiimoteReal::InterruptChannel(number, channel_id, data, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ButtonPressed(int number)
|
bool ButtonPressed(int number)
|
||||||
@ -215,6 +224,26 @@ unsigned int GetAttached()
|
|||||||
void DoState(PointerWrap& p)
|
void DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_BBMOTES; ++i)
|
for (int i = 0; i < MAX_BBMOTES; ++i)
|
||||||
|
{
|
||||||
|
auto state_wiimote_source = u8(g_wiimote_sources[i]);
|
||||||
|
p.Do(state_wiimote_source);
|
||||||
|
|
||||||
|
if (WIIMOTE_SRC_EMU == state_wiimote_source)
|
||||||
|
{
|
||||||
|
// Sync complete state of emulated wiimotes.
|
||||||
static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(i))->DoState(p);
|
static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(i))->DoState(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||||
|
{
|
||||||
|
// If using a real wiimote or the save-state source does not match the current source,
|
||||||
|
// then force a reconnection on load.
|
||||||
|
if (WIIMOTE_SRC_REAL == g_wiimote_sources[i] || state_wiimote_source != g_wiimote_sources[i])
|
||||||
|
{
|
||||||
|
Connect(i, false);
|
||||||
|
Connect(i, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace Wiimote
|
} // namespace Wiimote
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
@ -45,7 +48,7 @@ enum
|
|||||||
WIIMOTE_SRC_REAL = 2,
|
WIIMOTE_SRC_REAL = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern unsigned int g_wiimote_sources[MAX_BBMOTES];
|
extern std::array<std::atomic<u32>, MAX_BBMOTES> g_wiimote_sources;
|
||||||
|
|
||||||
namespace Wiimote
|
namespace Wiimote
|
||||||
{
|
{
|
||||||
|
@ -590,9 +590,6 @@ void Wiimote::DoState(PointerWrap& p)
|
|||||||
p.Do(m_shake_step);
|
p.Do(m_shake_step);
|
||||||
|
|
||||||
p.DoMarker("Wiimote");
|
p.DoMarker("Wiimote");
|
||||||
|
|
||||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
|
||||||
RealState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtensionNumber Wiimote::GetActiveExtensionNumber() const
|
ExtensionNumber Wiimote::GetActiveExtensionNumber() const
|
||||||
@ -600,14 +597,4 @@ ExtensionNumber Wiimote::GetActiveExtensionNumber() const
|
|||||||
return m_active_extension;
|
return m_active_extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::RealState()
|
|
||||||
{
|
|
||||||
using namespace WiimoteReal;
|
|
||||||
|
|
||||||
if (g_wiimotes[m_index])
|
|
||||||
{
|
|
||||||
g_wiimotes[m_index]->SetChannel(m_reporting_channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace WiimoteEmu
|
} // namespace WiimoteEmu
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "Core/Config/WiimoteInputSettings.h"
|
#include "Core/Config/WiimoteInputSettings.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
|
#include "Core/HW/Wiimote.h"
|
||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
#include "Core/NetPlayClient.h"
|
#include "Core/NetPlayClient.h"
|
||||||
|
|
||||||
@ -30,7 +31,6 @@
|
|||||||
#include "Core/HW/WiimoteEmu/Extension/Guitar.h"
|
#include "Core/HW/WiimoteEmu/Extension/Guitar.h"
|
||||||
#include "Core/HW/WiimoteEmu/Extension/Nunchuk.h"
|
#include "Core/HW/WiimoteEmu/Extension/Nunchuk.h"
|
||||||
#include "Core/HW/WiimoteEmu/Extension/Turntable.h"
|
#include "Core/HW/WiimoteEmu/Extension/Turntable.h"
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
|
||||||
|
|
||||||
#include "InputCommon/ControllerEmu/Control/Input.h"
|
#include "InputCommon/ControllerEmu/Control/Input.h"
|
||||||
#include "InputCommon/ControllerEmu/Control/Output.h"
|
#include "InputCommon/ControllerEmu/Control/Output.h"
|
||||||
@ -503,14 +503,6 @@ void Wiimote::ControlChannel(const u16 channel_id, const void* data, u32 size)
|
|||||||
|
|
||||||
m_reporting_channel = channel_id;
|
m_reporting_channel = channel_id;
|
||||||
|
|
||||||
// FYI: ControlChannel is piped through WiimoteEmu before WiimoteReal just so we can sync the
|
|
||||||
// channel on state load. This is ugly.
|
|
||||||
if (WIIMOTE_SRC_REAL == g_wiimote_sources[m_index])
|
|
||||||
{
|
|
||||||
WiimoteReal::ControlChannel(m_index, channel_id, data, size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& hidp = *reinterpret_cast<const HIDPacket*>(data);
|
const auto& hidp = *reinterpret_cast<const HIDPacket*>(data);
|
||||||
|
|
||||||
DEBUG_LOG(WIIMOTE, "Emu ControlChannel (page: %i, type: 0x%02x, param: 0x%02x)", m_index,
|
DEBUG_LOG(WIIMOTE, "Emu ControlChannel (page: %i, type: 0x%02x, param: 0x%02x)", m_index,
|
||||||
@ -559,14 +551,6 @@ void Wiimote::InterruptChannel(const u16 channel_id, const void* data, u32 size)
|
|||||||
|
|
||||||
m_reporting_channel = channel_id;
|
m_reporting_channel = channel_id;
|
||||||
|
|
||||||
// FYI: InterruptChannel is piped through WiimoteEmu before WiimoteReal just so we can sync the
|
|
||||||
// channel on state load. This is ugly.
|
|
||||||
if (WIIMOTE_SRC_REAL == g_wiimote_sources[m_index])
|
|
||||||
{
|
|
||||||
WiimoteReal::InterruptChannel(m_index, channel_id, data, size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& hidp = *reinterpret_cast<const HIDPacket*>(data);
|
const auto& hidp = *reinterpret_cast<const HIDPacket*>(data);
|
||||||
|
|
||||||
switch (hidp.type)
|
switch (hidp.type)
|
||||||
|
@ -35,12 +35,6 @@ class Output;
|
|||||||
class Tilt;
|
class Tilt;
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
|
||||||
// Needed for friendship:
|
|
||||||
namespace WiimoteReal
|
|
||||||
{
|
|
||||||
class Wiimote;
|
|
||||||
} // namespace WiimoteReal
|
|
||||||
|
|
||||||
namespace WiimoteEmu
|
namespace WiimoteEmu
|
||||||
{
|
{
|
||||||
enum class WiimoteGroup
|
enum class WiimoteGroup
|
||||||
@ -87,8 +81,6 @@ void UpdateCalibrationDataChecksum(T& data, int cksum_bytes)
|
|||||||
|
|
||||||
class Wiimote : public ControllerEmu::EmulatedController
|
class Wiimote : public ControllerEmu::EmulatedController
|
||||||
{
|
{
|
||||||
friend class WiimoteReal::Wiimote;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum : u8
|
enum : u8
|
||||||
{
|
{
|
||||||
@ -173,8 +165,6 @@ private:
|
|||||||
void SendDataReport();
|
void SendDataReport();
|
||||||
bool ProcessReadDataRequest();
|
bool ProcessReadDataRequest();
|
||||||
|
|
||||||
void RealState();
|
|
||||||
|
|
||||||
void SetRumble(bool on);
|
void SetRumble(bool on);
|
||||||
|
|
||||||
void CallbackInterruptChannel(const u8* data, u32 size);
|
void CallbackInterruptChannel(const u8* data, u32 size);
|
||||||
|
@ -284,7 +284,7 @@ void WiimoteDarwin::DisablePowerAssertionInternal()
|
|||||||
|
|
||||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||||
{
|
{
|
||||||
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i]);
|
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i].get());
|
||||||
if (!wm)
|
if (!wm)
|
||||||
continue;
|
continue;
|
||||||
if ([device isEqual:wm->m_btd])
|
if ([device isEqual:wm->m_btd])
|
||||||
@ -325,7 +325,7 @@ void WiimoteDarwin::DisablePowerAssertionInternal()
|
|||||||
|
|
||||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||||
{
|
{
|
||||||
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i]);
|
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i].get());
|
||||||
if (!wm)
|
if (!wm)
|
||||||
continue;
|
continue;
|
||||||
if ([device isEqual:wm->m_btd])
|
if ([device isEqual:wm->m_btd])
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/HW/Wiimote.h"
|
#include "Core/HW/Wiimote.h"
|
||||||
|
#include "Core/HW/WiimoteCommon/DataReport.h"
|
||||||
#include "Core/HW/WiimoteCommon/WiimoteHid.h"
|
#include "Core/HW/WiimoteCommon/WiimoteHid.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
|
||||||
#include "Core/HW/WiimoteReal/IOAndroid.h"
|
#include "Core/HW/WiimoteReal/IOAndroid.h"
|
||||||
#include "Core/HW/WiimoteReal/IOLinux.h"
|
#include "Core/HW/WiimoteReal/IOLinux.h"
|
||||||
#include "Core/HW/WiimoteReal/IOWin.h"
|
#include "Core/HW/WiimoteReal/IOWin.h"
|
||||||
@ -30,14 +30,14 @@
|
|||||||
|
|
||||||
#include "SFML/Network.hpp"
|
#include "SFML/Network.hpp"
|
||||||
|
|
||||||
unsigned int g_wiimote_sources[MAX_BBMOTES];
|
std::array<std::atomic<u32>, MAX_BBMOTES> g_wiimote_sources;
|
||||||
|
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
{
|
{
|
||||||
using namespace WiimoteCommon;
|
using namespace WiimoteCommon;
|
||||||
|
|
||||||
static void TryToConnectBalanceBoard(Wiimote*);
|
static void TryToConnectBalanceBoard(std::unique_ptr<Wiimote>);
|
||||||
static void TryToConnectWiimote(Wiimote*);
|
static void TryToConnectWiimote(std::unique_ptr<Wiimote>);
|
||||||
static void HandleWiimoteDisconnect(int index);
|
static void HandleWiimoteDisconnect(int index);
|
||||||
|
|
||||||
static bool g_real_wiimotes_initialized = false;
|
static bool g_real_wiimotes_initialized = false;
|
||||||
@ -49,18 +49,19 @@ static std::mutex s_known_ids_mutex;
|
|||||||
|
|
||||||
std::mutex g_wiimotes_mutex;
|
std::mutex g_wiimotes_mutex;
|
||||||
|
|
||||||
Wiimote* g_wiimotes[MAX_BBMOTES];
|
std::unique_ptr<Wiimote> g_wiimotes[MAX_BBMOTES];
|
||||||
WiimoteScanner g_wiimote_scanner;
|
WiimoteScanner g_wiimote_scanner;
|
||||||
|
|
||||||
Wiimote::Wiimote() : m_index(), m_last_input_report(), m_channel(0), m_rumble_state()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wiimote::Shutdown()
|
void Wiimote::Shutdown()
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(s_known_ids_mutex);
|
||||||
|
s_known_ids.erase(GetId());
|
||||||
|
|
||||||
StopThread();
|
StopThread();
|
||||||
ClearReadQueue();
|
ClearReadQueue();
|
||||||
m_write_reports.Clear();
|
m_write_reports.Clear();
|
||||||
|
|
||||||
|
NOTICE_LOG(WIIMOTE, "Disconnected real wiimote.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be called from CPU thread
|
// to be called from CPU thread
|
||||||
@ -70,9 +71,31 @@ void Wiimote::WriteReport(Report rpt)
|
|||||||
{
|
{
|
||||||
bool const new_rumble_state = (rpt[2] & 0x1) != 0;
|
bool const new_rumble_state = (rpt[2] & 0x1) != 0;
|
||||||
|
|
||||||
// If this is a rumble report and the rumble state didn't change, ignore.
|
switch (WiimoteCommon::OutputReportID(rpt[1]))
|
||||||
if (rpt[1] == u8(OutputReportID::Rumble) && new_rumble_state == m_rumble_state)
|
{
|
||||||
|
case OutputReportID::Rumble:
|
||||||
|
// If this is a rumble report and the rumble state didn't change, we can drop this report.
|
||||||
|
if (new_rumble_state == m_rumble_state)
|
||||||
return;
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OutputReportID::SpeakerEnable:
|
||||||
|
m_speaker_enable = (rpt[2] & 0x4) != 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OutputReportID::SpeakerMute:
|
||||||
|
m_speaker_mute = (rpt[2] & 0x4) != 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OutputReportID::ReportMode:
|
||||||
|
// Force non-continuous reporting for less BT traffic.
|
||||||
|
// We duplicate reports to maintain 200hz anyways.
|
||||||
|
rpt[2] &= ~0x4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m_rumble_state = new_rumble_state;
|
m_rumble_state = new_rumble_state;
|
||||||
}
|
}
|
||||||
@ -82,42 +105,27 @@ void Wiimote::WriteReport(Report rpt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// to be called from CPU thread
|
// to be called from CPU thread
|
||||||
void Wiimote::QueueReport(u8 rpt_id, const void* data, unsigned int size)
|
void Wiimote::QueueReport(WiimoteCommon::OutputReportID rpt_id, const void* data, unsigned int size)
|
||||||
{
|
{
|
||||||
auto const queue_data = static_cast<const u8*>(data);
|
auto const queue_data = static_cast<const u8*>(data);
|
||||||
|
|
||||||
Report rpt(size + 2);
|
Report rpt(size + 2);
|
||||||
rpt[0] = WR_SET_REPORT | BT_OUTPUT;
|
rpt[0] = WR_SET_REPORT | BT_OUTPUT;
|
||||||
rpt[1] = rpt_id;
|
rpt[1] = u8(rpt_id);
|
||||||
std::copy_n(queue_data, size, rpt.begin() + 2);
|
std::copy_n(queue_data, size, rpt.begin() + 2);
|
||||||
WriteReport(std::move(rpt));
|
WriteReport(std::move(rpt));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::DisableDataReporting()
|
void Wiimote::ResetDataReporting()
|
||||||
{
|
{
|
||||||
m_last_input_report.clear();
|
m_last_input_report.clear();
|
||||||
|
|
||||||
// This accomplishes very little:
|
// "core" reporting in non-continuous mode is a wiimote's initial state.
|
||||||
|
// FYI: This also disables rumble.
|
||||||
OutputReportMode rpt = {};
|
OutputReportMode rpt = {};
|
||||||
rpt.mode = InputReportID::ReportCore;
|
rpt.mode = InputReportID::ReportCore;
|
||||||
rpt.continuous = 0;
|
rpt.continuous = 0;
|
||||||
rpt.rumble = 0;
|
QueueReport(OutputReportID::ReportMode, &rpt, sizeof(rpt));
|
||||||
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wiimote::EnableDataReporting(u8 mode)
|
|
||||||
{
|
|
||||||
m_last_input_report.clear();
|
|
||||||
|
|
||||||
OutputReportMode rpt = {};
|
|
||||||
rpt.mode = InputReportID(mode);
|
|
||||||
rpt.continuous = 1;
|
|
||||||
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wiimote::SetChannel(u16 channel)
|
|
||||||
{
|
|
||||||
m_channel = channel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::ClearReadQueue()
|
void Wiimote::ClearReadQueue()
|
||||||
@ -136,9 +144,15 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3
|
|||||||
if (channel == 99)
|
if (channel == 99)
|
||||||
{
|
{
|
||||||
if (m_really_disconnect)
|
if (m_really_disconnect)
|
||||||
|
{
|
||||||
DisconnectInternal();
|
DisconnectInternal();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
EmuStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
InterruptChannel(channel, data, size);
|
InterruptChannel(channel, data, size);
|
||||||
const auto& hidp = *static_cast<const HIDPacket*>(data);
|
const auto& hidp = *static_cast<const HIDPacket*>(data);
|
||||||
@ -164,8 +178,6 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const
|
|||||||
|
|
||||||
auto const report_data = static_cast<const u8*>(data);
|
auto const report_data = static_cast<const u8*>(data);
|
||||||
Report rpt(report_data, report_data + size);
|
Report rpt(report_data, report_data + size);
|
||||||
WiimoteEmu::Wiimote* const wm =
|
|
||||||
static_cast<WiimoteEmu::Wiimote*>(::Wiimote::GetConfig()->GetController(m_index));
|
|
||||||
|
|
||||||
// Convert output DATA packets to SET_REPORT packets.
|
// Convert output DATA packets to SET_REPORT packets.
|
||||||
// Nintendo Wiimotes work without this translation, but 3rd
|
// Nintendo Wiimotes work without this translation, but 3rd
|
||||||
@ -187,10 +199,9 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rpt[1] == u8(OutputReportID::SpeakerData) &&
|
else if (rpt[1] == u8(OutputReportID::SpeakerData) &&
|
||||||
(!SConfig::GetInstance().m_WiimoteEnableSpeaker ||
|
(!SConfig::GetInstance().m_WiimoteEnableSpeaker || !m_speaker_enable || m_speaker_mute))
|
||||||
(!wm->m_status.speaker || wm->m_speaker_mute)))
|
|
||||||
{
|
{
|
||||||
// Translate speaker data reports into rumble reports.
|
// Translate undesired speaker data reports into rumble reports.
|
||||||
rpt[1] = u8(OutputReportID::Rumble);
|
rpt[1] = u8(OutputReportID::Rumble);
|
||||||
// Keep only the rumble bit.
|
// Keep only the rumble bit.
|
||||||
rpt[2] &= 0x1;
|
rpt[2] &= 0x1;
|
||||||
@ -379,6 +390,8 @@ bool Wiimote::CheckForButtonPress()
|
|||||||
if (rpt.size() >= 4)
|
if (rpt.size() >= 4)
|
||||||
{
|
{
|
||||||
const auto mode = InputReportID(rpt[1]);
|
const auto mode = InputReportID(rpt[1]);
|
||||||
|
|
||||||
|
// TODO: Button data could also be pulled out of non-data reports if really wanted.
|
||||||
if (DataReportBuilder::IsValidMode(mode))
|
if (DataReportBuilder::IsValidMode(mode))
|
||||||
{
|
{
|
||||||
auto builder = MakeDataReportManipulator(mode, rpt.data() + 2);
|
auto builder = MakeDataReportManipulator(mode, rpt.data() + 2);
|
||||||
@ -423,49 +436,26 @@ bool Wiimote::PrepareOnThread()
|
|||||||
|
|
||||||
void Wiimote::EmuStart()
|
void Wiimote::EmuStart()
|
||||||
{
|
{
|
||||||
DisableDataReporting();
|
ResetDataReporting();
|
||||||
EnablePowerAssertionInternal();
|
EnablePowerAssertionInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::EmuStop()
|
void Wiimote::EmuStop()
|
||||||
{
|
{
|
||||||
m_channel = 0;
|
m_channel = 0;
|
||||||
|
ResetDataReporting();
|
||||||
DisableDataReporting();
|
|
||||||
|
|
||||||
NOTICE_LOG(WIIMOTE, "Stopping Wiimote data reporting.");
|
|
||||||
|
|
||||||
DisablePowerAssertionInternal();
|
DisablePowerAssertionInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::EmuResume()
|
void Wiimote::EmuResume()
|
||||||
{
|
{
|
||||||
WiimoteEmu::Wiimote* const wm =
|
|
||||||
static_cast<WiimoteEmu::Wiimote*>(::Wiimote::GetConfig()->GetController(m_index));
|
|
||||||
|
|
||||||
m_last_input_report.clear();
|
m_last_input_report.clear();
|
||||||
|
|
||||||
OutputReportMode rpt = {};
|
|
||||||
rpt.mode = wm->m_reporting_mode;
|
|
||||||
rpt.continuous = 1;
|
|
||||||
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
|
|
||||||
|
|
||||||
NOTICE_LOG(WIIMOTE, "Resuming Wiimote data reporting.");
|
|
||||||
|
|
||||||
EnablePowerAssertionInternal();
|
EnablePowerAssertionInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::EmuPause()
|
void Wiimote::EmuPause()
|
||||||
{
|
{
|
||||||
m_last_input_report.clear();
|
|
||||||
|
|
||||||
OutputReportMode rpt = {};
|
|
||||||
rpt.mode = InputReportID::ReportCore;
|
|
||||||
rpt.continuous = 0;
|
|
||||||
QueueReport(u8(OutputReportID::ReportMode), &rpt, sizeof(rpt));
|
|
||||||
|
|
||||||
NOTICE_LOG(WIIMOTE, "Pausing Wiimote data reporting.");
|
|
||||||
|
|
||||||
DisablePowerAssertionInternal();
|
DisablePowerAssertionInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,25 +559,43 @@ void WiimoteScanner::ThreadFunc()
|
|||||||
if (m_scan_mode.load() == WiimoteScanMode::DO_NOT_SCAN)
|
if (m_scan_mode.load() == WiimoteScanMode::DO_NOT_SCAN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!g_real_wiimotes_initialized)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Does stuff needed to detect disconnects on Windows
|
||||||
|
for (const auto& backend : m_backends)
|
||||||
|
backend->Update();
|
||||||
|
|
||||||
|
if (0 == CalculateWantedWiimotes() && 0 == CalculateWantedBB())
|
||||||
|
continue;
|
||||||
|
|
||||||
for (const auto& backend : m_backends)
|
for (const auto& backend : m_backends)
|
||||||
{
|
|
||||||
if (CalculateWantedWiimotes() != 0 || CalculateWantedBB() != 0)
|
|
||||||
{
|
{
|
||||||
std::vector<Wiimote*> found_wiimotes;
|
std::vector<Wiimote*> found_wiimotes;
|
||||||
Wiimote* found_board = nullptr;
|
Wiimote* found_board = nullptr;
|
||||||
backend->FindWiimotes(found_wiimotes, found_board);
|
backend->FindWiimotes(found_wiimotes, found_board);
|
||||||
{
|
{
|
||||||
if (!g_real_wiimotes_initialized)
|
std::lock_guard<std::mutex> wm_lk(g_wiimotes_mutex);
|
||||||
continue;
|
|
||||||
std::lock_guard<std::mutex> lk(g_wiimotes_mutex);
|
for (auto* wiimote : found_wiimotes)
|
||||||
std::for_each(found_wiimotes.begin(), found_wiimotes.end(), TryToConnectWiimote);
|
|
||||||
if (found_board)
|
|
||||||
TryToConnectBalanceBoard(found_board);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
backend->Update(); // Does stuff needed to detect disconnects on Windows
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(s_known_ids_mutex);
|
||||||
|
s_known_ids.insert(wiimote->GetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
TryToConnectWiimote(std::unique_ptr<Wiimote>(wiimote));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_board)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(s_known_ids_mutex);
|
||||||
|
s_known_ids.insert(found_board->GetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
TryToConnectBalanceBoard(std::unique_ptr<Wiimote>(found_board));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,12 +695,17 @@ void LoadSettings()
|
|||||||
secname += static_cast<char>('1' + i);
|
secname += static_cast<char>('1' + i);
|
||||||
IniFile::Section& sec = *inifile.GetOrCreateSection(secname);
|
IniFile::Section& sec = *inifile.GetOrCreateSection(secname);
|
||||||
|
|
||||||
sec.Get("Source", &g_wiimote_sources[i], i ? WIIMOTE_SRC_NONE : WIIMOTE_SRC_EMU);
|
unsigned int source = 0;
|
||||||
|
sec.Get("Source", &source, i ? WIIMOTE_SRC_NONE : WIIMOTE_SRC_EMU);
|
||||||
|
g_wiimote_sources[i] = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string secname("BalanceBoard");
|
std::string secname("BalanceBoard");
|
||||||
IniFile::Section& sec = *inifile.GetOrCreateSection(secname);
|
IniFile::Section& sec = *inifile.GetOrCreateSection(secname);
|
||||||
sec.Get("Source", &g_wiimote_sources[WIIMOTE_BALANCE_BOARD], WIIMOTE_SRC_NONE);
|
|
||||||
|
unsigned int bb_source = 0;
|
||||||
|
sec.Get("Source", &bb_source, WIIMOTE_SRC_NONE);
|
||||||
|
g_wiimote_sources[WIIMOTE_BALANCE_BOARD] = bb_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
// config dialog calls this when some settings change
|
// config dialog calls this when some settings change
|
||||||
@ -700,7 +713,6 @@ void Initialize(::Wiimote::InitializeMode init_mode)
|
|||||||
{
|
{
|
||||||
if (!g_real_wiimotes_initialized)
|
if (!g_real_wiimotes_initialized)
|
||||||
{
|
{
|
||||||
s_known_ids.clear();
|
|
||||||
g_wiimote_scanner.StartThread();
|
g_wiimote_scanner.StartThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,83 +788,70 @@ void ChangeWiimoteSource(unsigned int index, int source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_wiimote_sources[index] = source;
|
g_wiimote_sources[index] = source;
|
||||||
|
|
||||||
{
|
{
|
||||||
// kill real connection (or swap to different slot)
|
// Kill real wiimote connection (if any) (or swap to different slot)
|
||||||
std::lock_guard<std::mutex> lk(g_wiimotes_mutex);
|
std::lock_guard<std::mutex> lk(g_wiimotes_mutex);
|
||||||
|
if (auto removed_wiimote = std::move(g_wiimotes[index]))
|
||||||
Wiimote* wm = g_wiimotes[index];
|
|
||||||
|
|
||||||
if (wm)
|
|
||||||
{
|
{
|
||||||
g_wiimotes[index] = nullptr;
|
// See if we can use this real Wiimote in another slot.
|
||||||
// First see if we can use this real Wiimote in another slot.
|
// Otherwise it will be disconnected.
|
||||||
TryToConnectWiimote(wm);
|
TryToConnectWiimote(std::move(removed_wiimote));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// else, just disconnect the Wiimote
|
// Reconnect to the emulator.
|
||||||
HandleWiimoteDisconnect(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reconnect to the emulator
|
|
||||||
Core::RunAsCPUThread([index, previous_source, source] {
|
Core::RunAsCPUThread([index, previous_source, source] {
|
||||||
if (previous_source != WIIMOTE_SRC_NONE)
|
if (previous_source != WIIMOTE_SRC_NONE)
|
||||||
::Wiimote::Connect(index, false);
|
::Wiimote::Connect(index, false);
|
||||||
if (source & WIIMOTE_SRC_EMU)
|
|
||||||
|
if (source == WIIMOTE_SRC_EMU)
|
||||||
::Wiimote::Connect(index, true);
|
::Wiimote::Connect(index, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from the Wiimote scanner thread
|
// Called from the Wiimote scanner thread (or UI thread on source change)
|
||||||
static bool TryToConnectWiimoteToSlot(Wiimote* wm, unsigned int i)
|
static bool TryToConnectWiimoteToSlot(std::unique_ptr<Wiimote>& wm, unsigned int i)
|
||||||
{
|
{
|
||||||
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i])
|
if (WIIMOTE_SRC_REAL != g_wiimote_sources[i] || g_wiimotes[i])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!wm->Connect(i))
|
||||||
{
|
{
|
||||||
if (wm->Connect(i))
|
ERROR_LOG(WIIMOTE, "Failed to connect real wiimote.");
|
||||||
{
|
|
||||||
NOTICE_LOG(WIIMOTE, "Connected to Wiimote %i.", i + 1);
|
|
||||||
g_wiimotes[i] = wm;
|
|
||||||
Core::RunAsCPUThread([i] { ::Wiimote::Connect(i, true); });
|
|
||||||
std::lock_guard<std::mutex> lk(s_known_ids_mutex);
|
|
||||||
s_known_ids.insert(wm->GetId());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TryToConnectWiimote(Wiimote* wm)
|
g_wiimotes[i] = std::move(wm);
|
||||||
|
Core::RunAsCPUThread([i] { ::Wiimote::Connect(i, true); });
|
||||||
|
|
||||||
|
NOTICE_LOG(WIIMOTE, "Connected real wiimote to slot %i.", i + 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TryToConnectWiimote(std::unique_ptr<Wiimote> wm)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
|
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
|
||||||
{
|
{
|
||||||
if (TryToConnectWiimoteToSlot(wm, i))
|
if (TryToConnectWiimoteToSlot(wm, i))
|
||||||
{
|
return;
|
||||||
wm = nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete wm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TryToConnectBalanceBoard(Wiimote* wm)
|
NOTICE_LOG(WIIMOTE, "No open slot for real wiimote.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TryToConnectBalanceBoard(std::unique_ptr<Wiimote> wm)
|
||||||
{
|
{
|
||||||
if (TryToConnectWiimoteToSlot(wm, WIIMOTE_BALANCE_BOARD))
|
if (TryToConnectWiimoteToSlot(wm, WIIMOTE_BALANCE_BOARD))
|
||||||
{
|
return;
|
||||||
wm = nullptr;
|
|
||||||
}
|
NOTICE_LOG(WIIMOTE, "No open slot for real balance board.");
|
||||||
delete wm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleWiimoteDisconnect(int index)
|
static void HandleWiimoteDisconnect(int index)
|
||||||
{
|
{
|
||||||
Wiimote* wm = nullptr;
|
g_wiimotes[index] = nullptr;
|
||||||
std::swap(wm, g_wiimotes[index]);
|
|
||||||
if (wm)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lk(s_known_ids_mutex);
|
|
||||||
s_known_ids.erase(wm->GetId());
|
|
||||||
delete wm;
|
|
||||||
NOTICE_LOG(WIIMOTE, "Disconnected Wiimote %i.", index + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called from the GUI thread
|
// This is called from the GUI thread
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -105,19 +106,19 @@ public:
|
|||||||
void Prepare();
|
void Prepare();
|
||||||
bool PrepareOnThread();
|
bool PrepareOnThread();
|
||||||
|
|
||||||
void DisableDataReporting();
|
void ResetDataReporting();
|
||||||
void EnableDataReporting(u8 mode);
|
|
||||||
void SetChannel(u16 channel);
|
|
||||||
|
|
||||||
void QueueReport(u8 rpt_id, const void* data, unsigned int size);
|
void QueueReport(WiimoteCommon::OutputReportID rpt_id, const void* data, unsigned int size);
|
||||||
|
|
||||||
int GetIndex() const;
|
int GetIndex() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Wiimote();
|
Wiimote() = default;
|
||||||
int m_index;
|
|
||||||
Report m_last_input_report;
|
int m_index = 0;
|
||||||
u16 m_channel;
|
Report m_last_input_report = {};
|
||||||
|
u16 m_channel = 0;
|
||||||
|
|
||||||
// If true, the Wiimote will be really disconnected when it is disconnected by Dolphin.
|
// If true, the Wiimote will be really disconnected when it is disconnected by Dolphin.
|
||||||
// In any other case, data reporting is not paused to allow reconnecting on any button press.
|
// In any other case, data reporting is not paused to allow reconnecting on any button press.
|
||||||
// This is not enabled on all platforms as connecting a Wiimote can be a pain on some platforms.
|
// This is not enabled on all platforms as connecting a Wiimote can be a pain on some platforms.
|
||||||
@ -133,7 +134,12 @@ private:
|
|||||||
|
|
||||||
void ThreadFunc();
|
void ThreadFunc();
|
||||||
|
|
||||||
bool m_rumble_state;
|
// We track the speaker state to convert unnecessary speaker data into rumble reports.
|
||||||
|
bool m_speaker_enable = false;
|
||||||
|
bool m_speaker_mute = false;
|
||||||
|
|
||||||
|
// And we track the rumble state to drop unnecessary rumble reports.
|
||||||
|
bool m_rumble_state = false;
|
||||||
|
|
||||||
std::thread m_wiimote_thread;
|
std::thread m_wiimote_thread;
|
||||||
// Whether to keep running the thread.
|
// Whether to keep running the thread.
|
||||||
@ -188,7 +194,7 @@ private:
|
|||||||
|
|
||||||
extern std::mutex g_wiimotes_mutex;
|
extern std::mutex g_wiimotes_mutex;
|
||||||
extern WiimoteScanner g_wiimote_scanner;
|
extern WiimoteScanner g_wiimote_scanner;
|
||||||
extern Wiimote* g_wiimotes[MAX_BBMOTES];
|
extern std::unique_ptr<Wiimote> g_wiimotes[MAX_BBMOTES];
|
||||||
|
|
||||||
void InterruptChannel(int wiimote_number, u16 channel_id, const void* data, u32 size);
|
void InterruptChannel(int wiimote_number, u16 channel_id, const void* data, u32 size);
|
||||||
void ControlChannel(int wiimote_number, u16 channel_id, const void* data, u32 size);
|
void ControlChannel(int wiimote_number, u16 channel_id, const void* data, u32 size);
|
||||||
|
@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
|||||||
static std::thread g_save_thread;
|
static std::thread g_save_thread;
|
||||||
|
|
||||||
// Don't forget to increase this after doing changes on the savestate system
|
// Don't forget to increase this after doing changes on the savestate system
|
||||||
static const u32 STATE_VERSION = 104; // Last changed in PR 7806
|
static const u32 STATE_VERSION = 105; // Last changed in PR 7871
|
||||||
|
|
||||||
// Maps savestate versions to Dolphin versions.
|
// Maps savestate versions to Dolphin versions.
|
||||||
// Versions after 42 don't need to be added to this list,
|
// Versions after 42 don't need to be added to this list,
|
||||||
@ -177,10 +177,6 @@ static void DoState(PointerWrap& p)
|
|||||||
g_video_backend->DoState(p);
|
g_video_backend->DoState(p);
|
||||||
p.DoMarker("video_backend");
|
p.DoMarker("video_backend");
|
||||||
|
|
||||||
if (SConfig::GetInstance().bWii)
|
|
||||||
Wiimote::DoState(p);
|
|
||||||
p.DoMarker("Wiimote");
|
|
||||||
|
|
||||||
PowerPC::DoState(p);
|
PowerPC::DoState(p);
|
||||||
p.DoMarker("PowerPC");
|
p.DoMarker("PowerPC");
|
||||||
// CoreTiming needs to be restored before restoring Hardware because
|
// CoreTiming needs to be restored before restoring Hardware because
|
||||||
@ -189,6 +185,9 @@ static void DoState(PointerWrap& p)
|
|||||||
p.DoMarker("CoreTiming");
|
p.DoMarker("CoreTiming");
|
||||||
HW::DoState(p);
|
HW::DoState(p);
|
||||||
p.DoMarker("HW");
|
p.DoMarker("HW");
|
||||||
|
if (SConfig::GetInstance().bWii)
|
||||||
|
Wiimote::DoState(p);
|
||||||
|
p.DoMarker("Wiimote");
|
||||||
Movie::DoState(p);
|
Movie::DoState(p);
|
||||||
p.DoMarker("Movie");
|
p.DoMarker("Movie");
|
||||||
Gecko::DoState(p);
|
Gecko::DoState(p);
|
||||||
|
@ -496,10 +496,7 @@ void ControllersWindow::SaveSettings()
|
|||||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||||
{
|
{
|
||||||
const int index = m_wiimote_boxes[i]->currentIndex();
|
const int index = m_wiimote_boxes[i]->currentIndex();
|
||||||
g_wiimote_sources[i] = index;
|
|
||||||
m_wiimote_buttons[i]->setEnabled(index != 0 && index != 2);
|
m_wiimote_buttons[i]->setEnabled(index != 0 && index != 2);
|
||||||
|
|
||||||
if (Core::IsRunning())
|
|
||||||
WiimoteReal::ChangeWiimoteSource(static_cast<u32>(i), index);
|
WiimoteReal::ChangeWiimoteSource(static_cast<u32>(i), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user