summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2022-09-25 02:29:35 +0200
committerAdmiral H. Curtiss <pikachu025@gmail.com>2022-10-02 23:14:36 +0200
commita2dadbb2f0c150a5e82088e0a04dfcdc36d709a7 (patch)
treebbf50b011225b5cfabeb1eb3c19650bee1750ad0
parentbb5943ae777b7f16441373fca4607451a55473a5 (diff)
Wiimote: Separate the Input system state update from the emulated state update.
-rw-r--r--Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h14
-rw-r--r--Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp41
-rw-r--r--Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h7
-rw-r--r--Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp13
-rw-r--r--Source/Core/Core/HW/WiimoteReal/WiimoteReal.h5
-rw-r--r--Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp15
-rw-r--r--Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h2
-rw-r--r--Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp41
-rw-r--r--Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h15
9 files changed, 109 insertions, 44 deletions
diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h
index 5ab296a9cc..0b3b5d37d6 100644
--- a/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h
+++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteHid.h
@@ -7,6 +7,11 @@
#include "Core/HW/WiimoteCommon/WiimoteConstants.h"
#include "Core/HW/WiimoteCommon/WiimoteReport.h"
+namespace WiimoteEmu
+{
+struct DesiredWiimoteState;
+}
+
namespace WiimoteCommon
{
// Source: HID_010_SPC_PFL/1.0 (official HID specification)
@@ -34,7 +39,8 @@ public:
virtual void SetWiimoteDeviceIndex(u8 index) = 0;
// Called every ~200hz after HID channels are established.
- virtual void Update() = 0;
+ virtual void PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state) = 0;
+ virtual void Update(const WiimoteEmu::DesiredWiimoteState& target_state) = 0;
void SetInterruptCallback(InterruptCallbackType callback) { m_callback = std::move(callback); }
@@ -42,8 +48,10 @@ public:
// Does not include HID-type header.
virtual void InterruptDataOutput(const u8* data, u32 size) = 0;
- // Used to connect a disconnected wii remote on button press.
- virtual bool IsButtonPressed() = 0;
+ // Get a snapshot of the current state of the Wiimote's buttons.
+ // Note that only the button bits of the return value are meaningful, the rest should be ignored.
+ // This is used to query a disconnected Wiimote whether it wants to reconnect.
+ virtual ButtonData GetCurrentlyPressedButtons() = 0;
protected:
void InterruptDataInputCallback(const u8* data, u32 size)
diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
index deac5a98ef..de676f8f4a 100644
--- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
+++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
@@ -448,7 +448,7 @@ void Wiimote::UpdateButtonsStatus(const DesiredWiimoteState& target_state)
m_status.buttons.hex = target_state.buttons.hex & ButtonData::BUTTON_MASK;
}
-DesiredWiimoteState Wiimote::BuildDesiredWiimoteState()
+void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state)
{
// Hotkey / settings modifier
// Data is later accessed in IsSideways and IsUpright
@@ -457,36 +457,35 @@ DesiredWiimoteState Wiimote::BuildDesiredWiimoteState()
// Update our motion simulations.
StepDynamics();
- DesiredWiimoteState wiimote_state;
-
// Fetch pressed buttons from user input.
- m_buttons->GetState(&wiimote_state.buttons.hex, button_bitmasks);
- m_dpad->GetState(&wiimote_state.buttons.hex,
+ target_state->buttons.hex = 0;
+ m_buttons->GetState(&target_state->buttons.hex, button_bitmasks);
+ m_dpad->GetState(&target_state->buttons.hex,
IsSideways() ? dpad_sideways_bitmasks : dpad_bitmasks);
// Calculate accelerometer state.
// Calibration values are 8-bit but we want 10-bit precision, so << 2.
- wiimote_state.acceleration =
+ target_state->acceleration =
ConvertAccelData(GetTotalAcceleration(), ACCEL_ZERO_G << 2, ACCEL_ONE_G << 2);
// Calculate IR camera state.
- wiimote_state.camera_points = CameraLogic::GetCameraPoints(
+ target_state->camera_points = CameraLogic::GetCameraPoints(
GetTotalTransformation(),
Common::Vec2(m_fov_x_setting.GetValue(), m_fov_y_setting.GetValue()) / 360 *
float(MathUtil::TAU));
// Calculate MotionPlus state.
if (m_motion_plus_setting.GetValue())
- wiimote_state.motion_plus = MotionPlus::GetGyroscopeData(GetTotalAngularVelocity());
+ target_state->motion_plus = MotionPlus::GetGyroscopeData(GetTotalAngularVelocity());
+ else
+ target_state->motion_plus = std::nullopt;
// Build Extension state.
// This also allows the extension to perform any regular duties it may need.
// (e.g. Nunchuk motion simulation step)
static_cast<Extension*>(
m_attachments->GetAttachmentList()[m_attachments->GetSelectedAttachment()].get())
- ->BuildDesiredExtensionState(&wiimote_state.extension);
-
- return wiimote_state;
+ ->BuildDesiredExtensionState(&target_state->extension);
}
u8 Wiimote::GetWiimoteDeviceIndex() const
@@ -500,13 +499,14 @@ void Wiimote::SetWiimoteDeviceIndex(u8 index)
}
// This is called every ::Wiimote::UPDATE_FREQ (200hz)
-void Wiimote::Update()
+void Wiimote::PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state)
{
const auto lock = GetStateLock();
+ BuildDesiredWiimoteState(target_state);
+}
- // Build target state.
- auto target_state = BuildDesiredWiimoteState();
-
+void Wiimote::Update(const WiimoteEmu::DesiredWiimoteState& target_state)
+{
// Update buttons in the status struct which is sent in 99% of input reports.
UpdateButtonsStatus(target_state);
@@ -656,14 +656,15 @@ void Wiimote::SendDataReport(const DesiredWiimoteState& target_state)
m_reporting_mode = InputReportID::ReportInterleave1;
}
-bool Wiimote::IsButtonPressed()
+ButtonData Wiimote::GetCurrentlyPressedButtons()
{
- u16 buttons = 0;
const auto lock = GetStateLock();
- m_buttons->GetState(&buttons, button_bitmasks);
- m_dpad->GetState(&buttons, dpad_bitmasks);
- return buttons != 0;
+ ButtonData buttons{};
+ m_buttons->GetState(&buttons.hex, button_bitmasks);
+ m_dpad->GetState(&buttons.hex, IsSideways() ? dpad_sideways_bitmasks : dpad_bitmasks);
+
+ return buttons;
}
void Wiimote::LoadDefaults(const ControllerInterface& ciface)
diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h
index 2dd3f79800..9b07085cef 100644
--- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h
+++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h
@@ -132,11 +132,12 @@ public:
u8 GetWiimoteDeviceIndex() const override;
void SetWiimoteDeviceIndex(u8 index) override;
- void Update() override;
+ void PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state) override;
+ void Update(const WiimoteEmu::DesiredWiimoteState& target_state) override;
void EventLinked() override;
void EventUnlinked() override;
void InterruptDataOutput(const u8* data, u32 size) override;
- bool IsButtonPressed() override;
+ WiimoteCommon::ButtonData GetCurrentlyPressedButtons() override;
void Reset();
@@ -157,7 +158,7 @@ private:
void StepDynamics();
void UpdateButtonsStatus(const DesiredWiimoteState& target_state);
- DesiredWiimoteState BuildDesiredWiimoteState();
+ void BuildDesiredWiimoteState(DesiredWiimoteState* target_state);
// Returns simulated accelerometer data in m/s^2.
Common::Vec3 GetAcceleration(
diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp
index 6ef990744a..10fa8f2686 100644
--- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp
+++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp
@@ -460,7 +460,12 @@ void Wiimote::SetWiimoteDeviceIndex(u8 index)
m_bt_device_index = index;
}
-void Wiimote::Update()
+void Wiimote::PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state)
+{
+ // Nothing to do here on real Wiimotes.
+}
+
+void Wiimote::Update(const WiimoteEmu::DesiredWiimoteState& target_state)
{
// Wii remotes send input at 200hz once a Wii enables "sniff mode" on the connection.
// PC bluetooth stacks do not enable sniff mode causing remotes to send input at only 100hz.
@@ -485,7 +490,7 @@ void Wiimote::Update()
u32(rpt.size() - REPORT_HID_HEADER_SIZE));
}
-bool Wiimote::IsButtonPressed()
+ButtonData Wiimote::GetCurrentlyPressedButtons()
{
Report& rpt = m_last_input_report;
if (rpt.size() >= 4)
@@ -499,10 +504,10 @@ bool Wiimote::IsButtonPressed()
ButtonData buttons = {};
builder->GetCoreData(&buttons);
- return buttons.hex != 0;
+ return buttons;
}
}
- return false;
+ return ButtonData{};
}
void Wiimote::Prepare()
diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h
index 859aadad45..e597d774bc 100644
--- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h
+++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h
@@ -66,10 +66,11 @@ public:
u8 GetWiimoteDeviceIndex() const override;
void SetWiimoteDeviceIndex(u8 index) override;
- void Update() override;
+ void PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state) override;
+ void Update(const WiimoteEmu::DesiredWiimoteState& target_state) override;
void EventLinked() override;
void EventUnlinked() override;
- bool IsButtonPressed() override;
+ WiimoteCommon::ButtonData GetCurrentlyPressedButtons() override;
void EmuStop();
diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp
index fae22f35de..94abbb0b14 100644
--- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp
+++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp
@@ -19,6 +19,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/HW/Wiimote.h"
+#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h"
#include "Core/SysConf.h"
@@ -58,7 +59,7 @@ 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],
tmp_bd[1], tmp_bd[2], tmp_bd[3], tmp_bd[4], tmp_bd[5]);
- m_wiimotes.emplace_back(std::make_unique<WiimoteDevice>(this, tmp_bd, i));
+ m_wiimotes[i] = std::make_unique<WiimoteDevice>(this, tmp_bd, i);
}
bt_dinf.num_registered = MAX_BBMOTES;
@@ -340,8 +341,16 @@ void BluetoothEmuDevice::Update()
{
g_controller_interface.SetCurrentInputChannel(ciface::InputChannel::Bluetooth);
g_controller_interface.UpdateInput();
- for (auto& wiimote : m_wiimotes)
- wiimote->UpdateInput();
+
+ std::array<WiimoteEmu::DesiredWiimoteState, MAX_BBMOTES> wiimote_states;
+ std::array<WiimoteDevice::NextUpdateInputCall, MAX_BBMOTES> next_call;
+
+ for (size_t i = 0; i < m_wiimotes.size(); ++i)
+ next_call[i] = m_wiimotes[i]->PrepareInput(&wiimote_states[i]);
+
+ for (size_t i = 0; i < m_wiimotes.size(); ++i)
+ m_wiimotes[i]->UpdateInput(next_call[i], wiimote_states[i]);
+
m_last_ticks = now;
}
diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h
index e3b649d252..038ed2f5e2 100644
--- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h
+++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h
@@ -60,7 +60,7 @@ public:
void DoState(PointerWrap& p) override;
private:
- std::vector<std::unique_ptr<WiimoteDevice>> m_wiimotes;
+ std::array<std::unique_ptr<WiimoteDevice>, MAX_BBMOTES> m_wiimotes;
bdaddr_t m_controller_bd{{0x11, 0x02, 0x19, 0x79, 0x00, 0xff}};
diff --git a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp
index 37d63f8455..5a59315606 100644
--- a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp
+++ b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp
@@ -21,6 +21,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteCommon/WiimoteConstants.h"
#include "Core/HW/WiimoteCommon/WiimoteHid.h"
+#include "Core/HW/WiimoteEmu/DesiredWiimoteState.h"
#include "Core/Host.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteHIDAttr.h"
@@ -341,25 +342,51 @@ void WiimoteDevice::Update()
}
}
-void WiimoteDevice::UpdateInput()
+WiimoteDevice::NextUpdateInputCall
+WiimoteDevice::PrepareInput(WiimoteEmu::DesiredWiimoteState* wiimote_state)
{
if (m_connection_request_counter)
--m_connection_request_counter;
if (!IsSourceValid())
- return;
+ return NextUpdateInputCall::None;
- // Allow button press to trigger activation after a second of no connection activity.
- if (!m_connection_request_counter && m_baseband_state == BasebandState::Inactive)
+ if (m_baseband_state == BasebandState::Inactive)
{
- if (Wiimote::NetPlay_GetButtonPress(GetNumber(), m_hid_source->IsButtonPressed()))
- Activate(true);
+ // Allow button press to trigger activation after a second of no connection activity.
+ if (!m_connection_request_counter)
+ {
+ wiimote_state->buttons = m_hid_source->GetCurrentlyPressedButtons();
+ return NextUpdateInputCall::Activate;
+ }
+ return NextUpdateInputCall::None;
}
// Verify interrupt channel is connected and configured.
const auto* channel = FindChannelWithPSM(L2CAP_PSM_HID_INTR);
if (channel && channel->IsComplete())
- m_hid_source->Update();
+ {
+ m_hid_source->PrepareInput(wiimote_state);
+ return NextUpdateInputCall::Update;
+ }
+ return NextUpdateInputCall::None;
+}
+
+void WiimoteDevice::UpdateInput(NextUpdateInputCall next_call,
+ const WiimoteEmu::DesiredWiimoteState& wiimote_state)
+{
+ switch (next_call)
+ {
+ case NextUpdateInputCall::Activate:
+ if (wiimote_state.buttons.hex & WiimoteCommon::ButtonData::BUTTON_MASK)
+ Activate(true);
+ break;
+ case NextUpdateInputCall::Update:
+ m_hid_source->Update(wiimote_state);
+ break;
+ default:
+ break;
+ }
}
// This function receives L2CAP commands from the CPU
diff --git a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h
index d0dbb4dc5e..99ac995f78 100644
--- a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h
+++ b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h
@@ -13,6 +13,11 @@
class PointerWrap;
+namespace WiimoteEmu
+{
+struct DesiredWiimoteState;
+}
+
namespace IOS::HLE
{
class BluetoothEmuDevice;
@@ -38,7 +43,15 @@ public:
void Update();
// Called every ~200hz.
- void UpdateInput();
+ enum class NextUpdateInputCall
+ {
+ None,
+ Activate,
+ Update
+ };
+ NextUpdateInputCall PrepareInput(WiimoteEmu::DesiredWiimoteState* wiimote_state);
+ void UpdateInput(NextUpdateInputCall next_call,
+ const WiimoteEmu::DesiredWiimoteState& wiimote_state);
void DoState(PointerWrap& p);