From f62325fa4161acaf08438c6ec4cee400e4ec8d7a Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 23 Feb 2025 02:32:36 -0600 Subject: [PATCH] WiimoteEmu: Make SerializedWiimoteState efficiently handle the static balance board accel data. --- .../HW/WiimoteEmu/DesiredWiimoteState.cpp | 18 ++++++++------- .../Core/HW/WiimoteEmu/DesiredWiimoteState.h | 6 +---- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 23 +++++++++++++++---- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h | 3 +++ Source/Core/Core/Movie.cpp | 4 ++-- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp index 6155b55384..510b0f396e 100644 --- a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp @@ -20,7 +20,7 @@ namespace WiimoteEmu SerializedWiimoteState SerializeDesiredState(const DesiredWiimoteState& state) { const u8 has_buttons = (state.buttons.hex & WiimoteCommon::ButtonData::BUTTON_MASK) != 0 ? 1 : 0; - const u8 has_accel = state.acceleration != DesiredWiimoteState::DEFAULT_ACCELERATION ? 1 : 0; + const u8 has_accel = state.acceleration.has_value() ? 1 : 0; const u8 has_camera = state.camera_points != DesiredWiimoteState::DEFAULT_CAMERA ? 1 : 0; const u8 has_motion_plus = state.motion_plus.has_value() ? 1 : 0; @@ -50,9 +50,9 @@ SerializedWiimoteState SerializeDesiredState(const DesiredWiimoteState& state) if (has_accel) { - const u16 accel_x = state.acceleration.value.x; // 10 bits - const u16 accel_y = state.acceleration.value.y; // 9 bits (ignore lowest bit) - const u16 accel_z = state.acceleration.value.z; // 9 bits (ignore lowest bit) + const u16 accel_x = state.acceleration->value.x; // 10 bits + const u16 accel_y = state.acceleration->value.y; // 9 bits (ignore lowest bit) + const u16 accel_z = state.acceleration->value.z; // 9 bits (ignore lowest bit) const u8 accel_x_high = u8(accel_x >> 2); const u8 accel_y_high = u8(accel_y >> 2); const u8 accel_z_high = u8(accel_z >> 2); @@ -120,7 +120,7 @@ bool DeserializeDesiredState(DesiredWiimoteState* state, const SerializedWiimote { // clear state state->buttons.hex = 0; - state->acceleration = DesiredWiimoteState::DEFAULT_ACCELERATION; + state->acceleration = std::nullopt; state->camera_points = DesiredWiimoteState::DEFAULT_CAMERA; state->motion_plus = std::nullopt; state->extension.data = std::monostate(); @@ -200,11 +200,13 @@ bool DeserializeDesiredState(DesiredWiimoteState* state, const SerializedWiimote const u8 accel_x_high = d[pos + 1]; const u8 accel_y_high = d[pos + 2]; const u8 accel_z_high = d[pos + 3]; - state->acceleration.value.x = (accel_x_high << 2) | (accel_low & 0b11); - state->acceleration.value.y = + WiimoteCommon::AccelData accel; + accel.value.x = (accel_x_high << 2) | (accel_low & 0b11); + accel.value.y = Common::ExpandValue((accel_y_high << 1) | Common::ExtractBit<2>(accel_low), 1); - state->acceleration.value.z = + accel.value.z = Common::ExpandValue((accel_z_high << 1) | Common::ExtractBit<3>(accel_low), 1); + state->acceleration = accel; pos += 4; } diff --git a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h index d9d3bcb968..d6d446d55e 100644 --- a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h +++ b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h @@ -16,16 +16,12 @@ namespace WiimoteEmu { struct DesiredWiimoteState { - // 1g in Z direction, which is the default returned by an unmoving emulated Wiimote. - static constexpr WiimoteCommon::AccelData DEFAULT_ACCELERATION = WiimoteCommon::AccelData( - {Wiimote::ACCEL_ZERO_G << 2, Wiimote::ACCEL_ZERO_G << 2, Wiimote::ACCEL_ONE_G << 2}); - // No light detected by the IR camera. static constexpr std::array DEFAULT_CAMERA = {CameraPoint(), CameraPoint(), CameraPoint(), CameraPoint()}; WiimoteCommon::ButtonData buttons{}; // non-button state in this is ignored - WiimoteCommon::AccelData acceleration = DEFAULT_ACCELERATION; + std::optional acceleration = std::nullopt; std::array camera_points = DEFAULT_CAMERA; std::optional motion_plus = std::nullopt; DesiredExtensionState extension; diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index 8bb32bcf17..a959614f4b 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -545,8 +545,10 @@ void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state, // Calculate accelerometer state. // Calibration values are 8-bit but we want 10-bit precision, so << 2. - target_state->acceleration = + const auto accel_data = ConvertAccelData(GetTotalAcceleration(), ACCEL_ZERO_G << 2, ACCEL_ONE_G << 2); + if (accel_data != GetDefaultAccelData()) + target_state->acceleration = accel_data; // Calculate IR camera state. if (m_ir_passthrough->enabled.GetValue()) @@ -580,6 +582,13 @@ void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state, ->BuildDesiredExtensionState(&target_state->extension); } +WiimoteCommon::AccelData Wiimote::GetDefaultAccelData() const +{ + // 1g in Z direction, which is the default returned by an unmoving emulated Wiimote. + return WiimoteCommon::AccelData( + {Wiimote::ACCEL_ZERO_G << 2, Wiimote::ACCEL_ZERO_G << 2, Wiimote::ACCEL_ONE_G << 2}); +} + // This is called every ::Wiimote::UPDATE_FREQ (200hz) void WiimoteBase::PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state, SensorBarState sensor_bar_state) @@ -684,7 +693,7 @@ void WiimoteBase::SendDataReport(const DesiredWiimoteState& target_state) // Acceleration: if (rpt_builder.HasAccel()) { - rpt_builder.SetAccelData(target_state.acceleration); + rpt_builder.SetAccelData(target_state.acceleration.value_or(GetDefaultAccelData())); } // IR Camera: @@ -1183,9 +1192,7 @@ void BalanceBoard::BuildDesiredWiimoteState(DesiredWiimoteState* target_state, { m_buttons->GetState(&target_state->buttons.hex, bboard_bitmasks, m_input_override_function); - // Real balance board observed with 0x2a-filled accel data. LSbs in button data were zero. - // TODO: This will result in SerializeDesiredState wasting 3 bytes on never-changing accel data. - target_state->acceleration.value.data.fill(0x2a << 2); + // Accel data is static. // Default, 0xff-filled, camera data is accurate. @@ -1193,4 +1200,10 @@ void BalanceBoard::BuildDesiredWiimoteState(DesiredWiimoteState* target_state, m_ext.BuildDesiredExtensionState(&target_state->extension); } +WiimoteCommon::AccelData BalanceBoard::GetDefaultAccelData() const +{ + // Real balance board observed with 0x2a-filled accel data. LSbs in button data were zero. + return WiimoteCommon::AccelData({0x2a << 2, 0x2a << 2, 0x2a << 2}); +} + } // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index 39b37be7a0..e21344499a 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -136,6 +136,7 @@ protected: virtual void UpdateBatteryStatus(double charge) = 0; virtual void BuildDesiredWiimoteState(DesiredWiimoteState* target_state, SensorBarState sensor_bar_state) = 0; + virtual WiimoteCommon::AccelData GetDefaultAccelData() const = 0; void PrepareInput(WiimoteEmu::DesiredWiimoteState* target_state, SensorBarState sensor_bar_state) override; @@ -315,6 +316,7 @@ protected: void UpdateBatteryStatus(double charge) override; void BuildDesiredWiimoteState(DesiredWiimoteState* target_state, SensorBarState sensor_bar_state) override; + WiimoteCommon::AccelData GetDefaultAccelData() const override; std::optional OverrideVec3(const ControllerEmu::ControlGroup* control_group, std::optional optional_vec) const; @@ -427,6 +429,7 @@ protected: void UpdateBatteryStatus(double charge) override; void BuildDesiredWiimoteState(DesiredWiimoteState* target_state, SensorBarState sensor_bar_state) override; + WiimoteCommon::AccelData GetDefaultAccelData() const override; void HandleReportRumble(const WiimoteCommon::OutputReportRumble&) override; void HandleSpeakerMute(const WiimoteCommon::OutputReportEnableFeature&) override; diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index a64de9aa00..b4b21b6829 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -698,9 +698,9 @@ static std::string GenerateWiiInputDisplayString(int index, const DesiredWiimote display_str += " HOME"; } - if (state.acceleration != state.DEFAULT_ACCELERATION) + if (state.acceleration.has_value()) { - const AccelData& accel_data = state.acceleration; + const AccelData& accel_data = *state.acceleration; display_str += fmt::format(" ACC:{},{},{}", accel_data.value.x, accel_data.value.y, accel_data.value.z); }