diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 3ca82051a7..4a9a0e7b74 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -144,6 +144,7 @@ add_library(core HW/WiimoteEmu/MotionPlus.cpp HW/WiimoteEmu/Speaker.cpp HW/WiimoteEmu/Extension/Classic.cpp + HW/WiimoteEmu/Extension/DrawsomeTablet.cpp HW/WiimoteEmu/Extension/Extension.cpp HW/WiimoteEmu/Extension/Nunchuk.cpp HW/WiimoteEmu/Extension/Drums.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index b12485dafc..82709080f4 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -178,6 +178,7 @@ + @@ -448,6 +449,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 2420db532a..62091ccacd 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -895,6 +895,9 @@ HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension + + HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension + HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension @@ -1616,6 +1619,9 @@ HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension + + HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension + HW %28Flipper/Hollywood%29\Wiimote\Emu\Extension diff --git a/Source/Core/Core/HW/Wiimote.cpp b/Source/Core/Core/HW/Wiimote.cpp index 5d6f1a2286..95fe6f122b 100644 --- a/Source/Core/Core/HW/Wiimote.cpp +++ b/Source/Core/Core/HW/Wiimote.cpp @@ -72,6 +72,13 @@ ControllerEmu::ControlGroup* GetUDrawTabletGroup(int number, WiimoteEmu::UDrawTa ->GetUDrawTabletGroup(group); } +ControllerEmu::ControlGroup* GetDrawsomeTabletGroup(int number, + WiimoteEmu::DrawsomeTabletGroup group) +{ + return static_cast(s_config.GetController(number)) + ->GetDrawsomeTabletGroup(group); +} + ControllerEmu::ControlGroup* GetTaTaConGroup(int number, WiimoteEmu::TaTaConGroup group) { return static_cast(s_config.GetController(number))->GetTaTaConGroup(group); diff --git a/Source/Core/Core/HW/Wiimote.h b/Source/Core/Core/HW/Wiimote.h index af87e0e0c7..0d23637563 100644 --- a/Source/Core/Core/HW/Wiimote.h +++ b/Source/Core/Core/HW/Wiimote.h @@ -27,6 +27,7 @@ enum class GuitarGroup; enum class DrumsGroup; enum class TurntableGroup; enum class UDrawTabletGroup; +enum class DrawsomeTabletGroup; enum class TaTaConGroup; } // namespace WiimoteEmu @@ -81,6 +82,8 @@ ControllerEmu::ControlGroup* GetGuitarGroup(int number, WiimoteEmu::GuitarGroup ControllerEmu::ControlGroup* GetDrumsGroup(int number, WiimoteEmu::DrumsGroup group); ControllerEmu::ControlGroup* GetTurntableGroup(int number, WiimoteEmu::TurntableGroup group); ControllerEmu::ControlGroup* GetUDrawTabletGroup(int number, WiimoteEmu::UDrawTabletGroup group); +ControllerEmu::ControlGroup* GetDrawsomeTabletGroup(int number, + WiimoteEmu::DrawsomeTabletGroup group); ControllerEmu::ControlGroup* GetTaTaConGroup(int number, WiimoteEmu::TaTaConGroup group); void ControlChannel(int number, u16 channel_id, const void* data, u32 size); diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/DrawsomeTablet.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/DrawsomeTablet.cpp new file mode 100644 index 0000000000..eb1eb77d56 --- /dev/null +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/DrawsomeTablet.cpp @@ -0,0 +1,116 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h" + +#include +#include + +#include "Common/BitUtils.h" +#include "Common/Common.h" +#include "Common/CommonTypes.h" +#include "Core/HW/WiimoteEmu/WiimoteEmu.h" + +#include "InputCommon/ControllerEmu/Control/Input.h" +#include "InputCommon/ControllerEmu/ControlGroup/AnalogStick.h" +#include "InputCommon/ControllerEmu/ControlGroup/Triggers.h" + +namespace WiimoteEmu +{ +constexpr std::array drawsome_tablet_id{{0xff, 0x00, 0xa4, 0x20, 0x00, 0x13}}; + +// i18n: The "Drawsome" (combination of "Draw" and "Awesome") tablet wiimote extension by Ubisoft. +DrawsomeTablet::DrawsomeTablet() : Extension3rdParty("Drawsome", _trans("Drawsome Tablet")) +{ + // Stylus + groups.emplace_back(m_stylus = new ControllerEmu::AnalogStick( + _trans("Stylus"), std::make_unique(1.0))); + + // Touch + groups.emplace_back(m_touch = new ControllerEmu::Triggers(_trans("Touch"))); + m_touch->controls.emplace_back( + new ControllerEmu::Input(ControllerEmu::Translate, _trans("Pressure"))); +} + +void DrawsomeTablet::Update() +{ + DataFormat tablet_data = {}; + + // Stylus X/Y (calibrated values): + constexpr u16 MIN_X = 0x0000; + constexpr u16 MAX_X = 0x27ff; + // Note: While 0x15ff seems to be the ideal calibrated value, + // the "Drawsome" game expects you to go "off screen" a bit to access some menu items. + constexpr u16 MIN_Y = 0x15ff + 0x100; + constexpr u16 MAX_Y = 0x00; + constexpr double CENTER_X = (MAX_X + MIN_X) / 2.0; + constexpr double CENTER_Y = (MAX_Y + MIN_Y) / 2.0; + + const auto stylus_state = m_stylus->GetState(); + const auto stylus_x = u16(std::lround(CENTER_X + stylus_state.x * (MAX_X - CENTER_X))); + const auto stylus_y = u16(std::lround(CENTER_Y + stylus_state.y * (MAX_Y - CENTER_Y))); + + tablet_data.stylus_x1 = u8(stylus_x); + tablet_data.stylus_x2 = u8(stylus_x >> 8); + + tablet_data.stylus_y1 = u8(stylus_y); + tablet_data.stylus_y2 = u8(stylus_y >> 8); + + // TODO: Expose the lifted stylus state in the UI. + // Note: Pen X/Y holds the last value when the pen is lifted. + const bool is_stylus_lifted = false; + + constexpr u8 NEUTRAL_STATUS = 0x8; + constexpr u8 PEN_LIFTED_BIT = 0x10; + + u8 status = NEUTRAL_STATUS; + + if (is_stylus_lifted) + status |= PEN_LIFTED_BIT; + + tablet_data.status = status; + + // Pressure (0 - 0x7ff): + constexpr u16 MAX_PRESSURE = 0x7ff; + + const auto touch_state = m_touch->GetState(); + const auto pressure = u16(std::lround(touch_state.data[0] * MAX_PRESSURE)); + + tablet_data.pressure1 = u8(pressure); + tablet_data.pressure2 = u8(pressure >> 8); + + Common::BitCastPtr(&m_reg.controller_data) = tablet_data; +} + +void DrawsomeTablet::Reset() +{ + EncryptedExtension::Reset(); + + m_reg.identifier = drawsome_tablet_id; + + // Assuming calibration data is 0xff filled. + m_reg.calibration.fill(0xff); +} + +bool DrawsomeTablet::IsButtonPressed() const +{ + // Device has no buttons. + return false; +} + +ControllerEmu::ControlGroup* DrawsomeTablet::GetGroup(DrawsomeTabletGroup group) +{ + switch (group) + { + case DrawsomeTabletGroup::Stylus: + return m_stylus; + case DrawsomeTabletGroup::Touch: + return m_touch; + default: + assert(false); + return nullptr; + } +} + +} // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h b/Source/Core/Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h new file mode 100644 index 0000000000..32b38d2d16 --- /dev/null +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h @@ -0,0 +1,61 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Common/BitField.h" +#include "Common/Swap.h" +#include "Core/HW/WiimoteEmu/Extension/Extension.h" + +namespace ControllerEmu +{ +class AnalogStick; +class Triggers; +class ControlGroup; +} // namespace ControllerEmu + +namespace WiimoteEmu +{ +enum class DrawsomeTabletGroup +{ + Stylus, + Touch, +}; + +class DrawsomeTablet : public Extension3rdParty +{ +public: + DrawsomeTablet(); + + void Update() override; + bool IsButtonPressed() const override; + void Reset() override; + + ControllerEmu::ControlGroup* GetGroup(DrawsomeTabletGroup group); + + struct DataFormat + { + // Pen X/Y is little endian. + u8 stylus_x1; + u8 stylus_x2; + + u8 stylus_y1; + u8 stylus_y2; + + u8 pressure1; + + union + { + BitField<0, 3, u8> pressure2; + BitField<3, 5, u8> status; + }; + }; + + static_assert(6 == sizeof(DataFormat), "Wrong size."); + +private: + ControllerEmu::AnalogStick* m_stylus; + ControllerEmu::Triggers* m_touch; +}; +} // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h b/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h index 7f4f5c979c..3a266bcc07 100644 --- a/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h +++ b/Source/Core/Core/HW/WiimoteEmu/ExtensionPort.h @@ -20,6 +20,7 @@ enum ExtensionNumber : u8 DRUMS, TURNTABLE, UDRAW_TABLET, + DRAWSOME_TABLET, TATACON, }; diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index f8034901a2..87f64e14bf 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -26,6 +26,7 @@ #include "Core/HW/WiimoteCommon/WiimoteConstants.h" #include "Core/HW/WiimoteCommon/WiimoteHid.h" #include "Core/HW/WiimoteEmu/Extension/Classic.h" +#include "Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h" #include "Core/HW/WiimoteEmu/Extension/Drums.h" #include "Core/HW/WiimoteEmu/Extension/Guitar.h" #include "Core/HW/WiimoteEmu/Extension/Nunchuk.h" @@ -168,6 +169,7 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index) 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->AddAttachment(std::make_unique()); m_attachments->AddSetting(&m_motion_plus_setting, {_trans("Attach MotionPlus")}, true); @@ -293,7 +295,13 @@ ControllerEmu::ControlGroup* Wiimote::GetUDrawTabletGroup(UDrawTabletGroup group return static_cast( m_attachments->GetAttachmentList()[ExtensionNumber::UDRAW_TABLET].get()) ->GetGroup(group); - ; +} + +ControllerEmu::ControlGroup* Wiimote::GetDrawsomeTabletGroup(DrawsomeTabletGroup group) +{ + return static_cast( + m_attachments->GetAttachmentList()[ExtensionNumber::DRAWSOME_TABLET].get()) + ->GetGroup(group); } ControllerEmu::ControlGroup* Wiimote::GetTaTaConGroup(TaTaConGroup group) diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index 495a25ce0a..d90bc65d64 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -56,6 +56,7 @@ enum class GuitarGroup; enum class DrumsGroup; enum class TurntableGroup; enum class UDrawTabletGroup; +enum class DrawsomeTabletGroup; enum class TaTaConGroup; template @@ -116,6 +117,7 @@ public: ControllerEmu::ControlGroup* GetDrumsGroup(DrumsGroup group); ControllerEmu::ControlGroup* GetTurntableGroup(TurntableGroup group); ControllerEmu::ControlGroup* GetUDrawTabletGroup(UDrawTabletGroup group); + ControllerEmu::ControlGroup* GetDrawsomeTabletGroup(DrawsomeTabletGroup group); ControllerEmu::ControlGroup* GetTaTaConGroup(TaTaConGroup group); void Update(); diff --git a/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.cpp b/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.cpp index 7d68d7da27..27a94ed5b5 100644 --- a/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.cpp @@ -11,6 +11,7 @@ #include "Core/HW/Wiimote.h" #include "Core/HW/WiimoteEmu/Extension/Classic.h" +#include "Core/HW/WiimoteEmu/Extension/DrawsomeTablet.h" #include "Core/HW/WiimoteEmu/Extension/Drums.h" #include "Core/HW/WiimoteEmu/Extension/Guitar.h" #include "Core/HW/WiimoteEmu/Extension/Nunchuk.h" @@ -30,6 +31,7 @@ WiimoteEmuExtension::WiimoteEmuExtension(MappingWindow* window) : MappingWidget( CreateNunchukLayout(); CreateTurntableLayout(); CreateUDrawTabletLayout(); + CreateDrawsomeTabletLayout(); CreateTaTaConLayout(); CreateMainLayout(); @@ -203,6 +205,22 @@ void WiimoteEmuExtension::CreateUDrawTabletLayout() m_udraw_tablet_box->setLayout(hbox); } +void WiimoteEmuExtension::CreateDrawsomeTabletLayout() +{ + const auto hbox = new QHBoxLayout(); + m_drawsome_tablet_box = new QGroupBox(tr("Drawsome Tablet"), this); + + hbox->addWidget(CreateGroupBox( + tr("Stylus"), + Wiimote::GetDrawsomeTabletGroup(GetPort(), WiimoteEmu::DrawsomeTabletGroup::Stylus))); + + hbox->addWidget(CreateGroupBox( + tr("Touch"), + Wiimote::GetDrawsomeTabletGroup(GetPort(), WiimoteEmu::DrawsomeTabletGroup::Touch))); + + m_drawsome_tablet_box->setLayout(hbox); +} + void WiimoteEmuExtension::CreateTaTaConLayout() { auto* hbox = new QHBoxLayout(); @@ -227,6 +245,7 @@ void WiimoteEmuExtension::CreateMainLayout() m_main_layout->addWidget(m_nunchuk_box); m_main_layout->addWidget(m_turntable_box); m_main_layout->addWidget(m_udraw_tablet_box); + m_main_layout->addWidget(m_drawsome_tablet_box); m_main_layout->addWidget(m_tatacon_box); setLayout(m_main_layout); @@ -258,5 +277,6 @@ void WiimoteEmuExtension::ChangeExtensionType(u32 type) m_drums_box->setHidden(type != ExtensionNumber::DRUMS); m_turntable_box->setHidden(type != ExtensionNumber::TURNTABLE); m_udraw_tablet_box->setHidden(type != ExtensionNumber::UDRAW_TABLET); + m_drawsome_tablet_box->setHidden(type != ExtensionNumber::DRAWSOME_TABLET); m_tatacon_box->setHidden(type != ExtensionNumber::TATACON); } diff --git a/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.h b/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.h index b1c97339b3..dec935aae7 100644 --- a/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.h +++ b/Source/Core/DolphinQt/Config/Mapping/WiimoteEmuExtension.h @@ -32,6 +32,7 @@ private: void CreateNunchukLayout(); void CreateTurntableLayout(); void CreateUDrawTabletLayout(); + void CreateDrawsomeTabletLayout(); void CreateTaTaConLayout(); void CreateMainLayout(); @@ -44,5 +45,6 @@ private: QGroupBox* m_nunchuk_box; QGroupBox* m_turntable_box; QGroupBox* m_udraw_tablet_box; + QGroupBox* m_drawsome_tablet_box; QGroupBox* m_tatacon_box; };