mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-10 06:29:00 +01:00
Wiimote: Separate the Input system state update from the emulated state update.
This commit is contained in:
parent
bb5943ae77
commit
a2dadbb2f0
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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}};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user