diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 33a97d05e7..701e905869 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -304,6 +304,8 @@ add_library(core HW/WiimoteEmu/EmuSubroutines.cpp HW/WiimoteEmu/Encryption.cpp HW/WiimoteEmu/Encryption.h + HW/WiimoteEmu/Extension/BalanceBoard.cpp + HW/WiimoteEmu/Extension/BalanceBoard.h HW/WiimoteEmu/Extension/Classic.cpp HW/WiimoteEmu/Extension/Classic.h HW/WiimoteEmu/Extension/DesiredExtensionState.h diff --git a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp index 0293ae41e4..630fa88c6f 100644 --- a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp @@ -117,7 +117,7 @@ SerializedWiimoteState SerializeDesiredState(const DesiredWiimoteState& state) using T = std::decay_t; if constexpr (!std::is_same_v) { - static_assert(sizeof(arg) <= 6); + static_assert(sizeof(arg) <= 12); static_assert(std::is_trivially_copyable_v); std::memcpy(&s.data[s.length], &arg, sizeof(arg)); s.length += sizeof(arg); @@ -213,6 +213,9 @@ bool DeserializeDesiredState(DesiredWiimoteState* state, const SerializedWiimote case ExtensionNumber::SHINKANSEN: s += sizeof(Shinkansen::DesiredState); break; + case ExtensionNumber::BALANCE_BOARD: + s += sizeof(BalanceBoardExt::DataFormat); + break; default: break; } @@ -319,6 +322,8 @@ bool DeserializeDesiredState(DesiredWiimoteState* state, const SerializedWiimote return DeserializeExtensionState(state, serialized, pos); case ExtensionNumber::SHINKANSEN: return DeserializeExtensionState(state, serialized, pos); + case ExtensionNumber::BALANCE_BOARD: + return DeserializeExtensionState(state, serialized, pos); default: break; } diff --git a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h index 6ef25675f3..5a7f3c99c3 100644 --- a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h +++ b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.h @@ -35,7 +35,7 @@ struct DesiredWiimoteState struct SerializedWiimoteState { u8 length; - std::array data; // 18 bytes Wiimote, 6 bytes MotionPlus, 6 bytes Extension + std::array data; // 18 bytes Wiimote, 6 bytes MotionPlus, 12 bytes Extension }; SerializedWiimoteState SerializeDesiredState(const DesiredWiimoteState& state); diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index 9d354a4b8e..c77622e534 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -149,7 +149,18 @@ void Wiimote::HandleExtensionSwap(ExtensionNumber desired_extension_number, if (WIIMOTE_BALANCE_BOARD == m_index) { // Prevent M+ or anything else silly from being attached to a balance board. - // In the future if we support an emulated balance board we can force the BB "extension" here. + if (m_is_motion_plus_attached) + { + m_is_motion_plus_attached = false; + m_motion_plus.GetExtPort().AttachExtension(GetNoneExtension()); + } + // Also force the BB "extension". + if (m_active_extension != ExtensionNumber::BALANCE_BOARD) + { + m_active_extension = ExtensionNumber::BALANCE_BOARD; + m_extension_port.AttachExtension(GetActiveExtension()); + GetActiveExtension()->Reset(); + } return; } diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/BalanceBoard.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/BalanceBoard.cpp new file mode 100644 index 0000000000..38a782f785 --- /dev/null +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/BalanceBoard.cpp @@ -0,0 +1,109 @@ +// Copyright 2022 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "Core/HW/WiimoteEmu/Extension/BalanceBoard.h" + +#include +#include +#include +#include + +#include "Common/BitUtils.h" +#include "Common/Common.h" +#include "Common/CommonTypes.h" +#include "Common/MathUtil.h" +#include "Common/Swap.h" + +#include "Core/HW/Wiimote.h" +#include "Core/HW/WiimoteEmu/Extension/DesiredExtensionState.h" +#include "Core/HW/WiimoteEmu/WiimoteEmu.h" + +#include "InputCommon/ControllerEmu/Control/Input.h" +#include "InputCommon/ControllerEmu/ControlGroup/AnalogStick.h" +#include "InputCommon/ControllerEmu/ControlGroup/Buttons.h" +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" +#include "InputCommon/ControllerEmu/ControlGroup/Force.h" +#include "InputCommon/ControllerEmu/ControlGroup/Tilt.h" + +namespace WiimoteEmu +{ +constexpr std::array balance_board_id{{0x00, 0x00, 0xa4, 0x20, 0x04, 0x02}}; + +BalanceBoardExt::BalanceBoardExt() : Extension1stParty("BalanceBoard", _trans("Balance Board")) +{ +} + +void BalanceBoardExt::BuildDesiredExtensionState(DesiredExtensionState* target_state) +{ + DataFormat bb_data = {}; + + bb_data.top_right = Common::swap16(0x0743); + bb_data.bottom_right = Common::swap16(0x11a2); + bb_data.top_left = Common::swap16(0x06a8); + bb_data.bottom_left = Common::swap16(0x4694); + bb_data.temperature = 0x19; + bb_data.battery = 0x83; + + target_state->data = bb_data; +} + +void BalanceBoardExt::Update(const DesiredExtensionState& target_state) +{ + DefaultExtensionUpdate(&m_reg, target_state); +} + +void BalanceBoardExt::Reset() +{ + EncryptedExtension::Reset(); + + m_reg.identifier = balance_board_id; + + // Build calibration data: + m_reg.calibration = {{// Unused battery calibration + 0x01, 0x69, 0x00, 0x00, + // Top right 0kg + 0x07, 0xbc, + // Bottom right 0kg + 0x11, 0x8b, + // Top left 0kg + 0x06, 0xba, + // Bottom left 0kg + 0x46, 0x52, + // Top right 17kg + 0x0e, 0x6e, + // Bottom right 17kg + 0x18, 0x79}}; + m_reg.calibration2 = {{// Top left 17kg + 0x0d, 0x5d, + // Bottom left 17kg + 0x4d, 0x4c, + // Top right 34kg + 0x15, 0x2e, + // Bottom right 34kg + 0x1f, 0x71, + // Top left 34kg + 0x14, 0x07, + // Bottom left 34kg + 0x54, 0x51, + // Checksum + 0xa9, 0x06, 0xb4, 0xf0}}; + m_reg.calibration3 = {{0x19, 0x01}}; + + // UpdateCalibrationDataChecksum(m_reg.calibration, CALIBRATION_CHECKSUM_BYTES); +} + +ControllerEmu::ControlGroup* BalanceBoardExt::GetGroup(BalanceBoardGroup group) +{ + return nullptr; +} + +void BalanceBoardExt::DoState(PointerWrap& p) +{ + EncryptedExtension::DoState(p); +} + +void BalanceBoardExt::LoadDefaults(const ControllerInterface& ciface) +{ +} + +} // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/BalanceBoard.h b/Source/Core/Core/HW/WiimoteEmu/Extension/BalanceBoard.h new file mode 100644 index 0000000000..db8e5a8bdb --- /dev/null +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/BalanceBoard.h @@ -0,0 +1,51 @@ +// Copyright 2022 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "Core/HW/WiimoteCommon/WiimoteReport.h" +#include "Core/HW/WiimoteEmu/Dynamics.h" +#include "Core/HW/WiimoteEmu/Extension/Extension.h" + +namespace ControllerEmu +{ +class ControlGroup; +} // namespace ControllerEmu + +namespace WiimoteEmu +{ +enum class BalanceBoardGroup +{ +}; + +class BalanceBoardExt : public Extension1stParty +{ +public: + struct DataFormat + { + u16 top_right; + u16 bottom_right; + u16 top_left; + u16 bottom_left; + u8 temperature; + u8 padding; + u8 battery; + }; + static_assert(sizeof(DataFormat) == 12, "Wrong size"); + + BalanceBoardExt(); + + void BuildDesiredExtensionState(DesiredExtensionState* target_state) override; + void Update(const DesiredExtensionState& target_state) override; + void Reset() override; + void DoState(PointerWrap& p) override; + + ControllerEmu::ControlGroup* GetGroup(BalanceBoardGroup group); + + void LoadDefaults(const ControllerInterface& ciface) override; + +private: +}; +} // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/DesiredExtensionState.h b/Source/Core/Core/HW/WiimoteEmu/Extension/DesiredExtensionState.h index 4929c91cd1..4f52de1c9a 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/DesiredExtensionState.h +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/DesiredExtensionState.h @@ -8,6 +8,7 @@ #include "Common/BitUtils.h" +#include "Core/HW/WiimoteEmu/Extension/BalanceBoard.h" #include "Core/HW/WiimoteEmu/Extension/Classic.h" #include "Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h" #include "Core/HW/WiimoteEmu/Extension/Drums.h" @@ -27,7 +28,8 @@ struct DesiredExtensionState using ExtensionData = std::variant; + DrawsomeTablet::DataFormat, TaTaCon::DataFormat, Shinkansen::DesiredState, + BalanceBoardExt::DataFormat>; ExtensionData data = std::monostate(); static_assert(std::is_same_v>); + static_assert( + std::is_same_v>); static_assert(std::variant_size_v == ExtensionNumber::MAX); }; diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h b/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h index 4a055c597d..0431923384 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Extension.h @@ -85,11 +85,14 @@ public: // address 0x20 std::array calibration; - u8 unknown3[0x10]; + std::array calibration2; // address 0x40 std::array encryption_key_data; - u8 unknown4[0xA0]; + u8 unknown3[0x10]; + // Address 0x60 + std::array calibration3; + u8 unknown4[0x8e]; // address 0xF0 u8 encryption; diff --git a/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h b/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h index 86b1fd31f9..43b4aca6d1 100644 --- a/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h +++ b/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h @@ -23,6 +23,8 @@ enum ExtensionNumber : u8 TATACON, SHINKANSEN, + BALANCE_BOARD, + MAX }; diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index a93ad379e8..501b5a5972 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -28,6 +28,7 @@ #include "Core/HW/WiimoteCommon/WiimoteConstants.h" #include "Core/HW/WiimoteCommon/WiimoteHid.h" #include "Core/HW/WiimoteEmu/DesiredWiimoteState.h" +#include "Core/HW/WiimoteEmu/Extension/BalanceBoard.h" #include "Core/HW/WiimoteEmu/Extension/Classic.h" #include "Core/HW/WiimoteEmu/Extension/DesiredExtensionState.h" #include "Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h" @@ -182,6 +183,7 @@ void Wiimote::Reset() { // Switch to desired M+ status and extension (if any). // M+ and EXT are reset on attachment. + // This also ensures that the balance board extension is attached if needed. HandleExtensionSwap(static_cast(m_attachments->GetSelectedAttachment()), m_motion_plus_setting.GetValue()); } @@ -280,6 +282,7 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), m_bt_device_index(i m_attachments->AddAttachment(std::make_unique()); m_attachments->AddAttachment(std::make_unique()); m_attachments->AddAttachment(std::make_unique()); + m_attachments->AddAttachment(std::make_unique()); m_attachments->AddSetting(&m_motion_plus_setting, {_trans("Attach MotionPlus")}, true); diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index e41e9fc26a..f55b6aa43d 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -337,6 +337,7 @@ + @@ -1001,6 +1002,7 @@ +