From a9b298e9dfa309f5abe9ef7068eab36f24fa4825 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 12 Feb 2024 01:03:41 -0500 Subject: [PATCH] am: activate button poller --- src/core/CMakeLists.txt | 2 + src/core/hle/service/am/am.cpp | 3 + src/core/hle/service/am/button_poller.cpp | 94 +++++++++++++++++++++++ src/core/hle/service/am/button_poller.h | 39 ++++++++++ 4 files changed, 138 insertions(+) create mode 100644 src/core/hle/service/am/button_poller.cpp create mode 100644 src/core/hle/service/am/button_poller.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8700fe7ae0..abca753eac 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -405,6 +405,8 @@ add_library(core STATIC hle/service/am/applet_data_broker.cpp hle/service/am/applet_data_broker.h hle/service/am/applet_manager.h + hle/service/am/button_poller.cpp + hle/service/am/button_poller.h hle/service/am/display_layer_manager.cpp hle/service/am/display_layer_manager.h hle/service/am/frontend/applet_cabinet.cpp diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 8c4e14f08c..ecd0f60162 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/am/am.h" +#include "core/hle/service/am/button_poller.h" #include "core/hle/service/am/service/all_system_applet_proxies_service.h" #include "core/hle/service/am/service/application_proxy_service.h" #include "core/hle/service/server_manager.h" @@ -9,6 +10,8 @@ namespace Service::AM { void LoopProcess(Core::System& system) { + ButtonPoller button_poller(system); + auto server_manager = std::make_unique(system); server_manager->RegisterNamedService("appletAE", diff --git a/src/core/hle/service/am/button_poller.cpp b/src/core/hle/service/am/button_poller.cpp new file mode 100644 index 0000000000..7933e79929 --- /dev/null +++ b/src/core/hle/service/am/button_poller.cpp @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/am/button_poller.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" +#include "hid_core/hid_types.h" + +namespace Service::AM { + +namespace { + +enum class ButtonPressDuration { + ShortPressing, + MiddlePressing, + LongPressing, +}; + +[[maybe_unused]] ButtonPressDuration ClassifyPressDuration( + std::chrono::steady_clock::time_point start) { + using namespace std::chrono_literals; + + const auto dur = std::chrono::steady_clock::now() - start; + + // TODO: determine actual thresholds + // TODO: these are likely different for each button + if (dur < 500ms) { + return ButtonPressDuration::ShortPressing; + } else if (dur < 1000ms) { + return ButtonPressDuration::MiddlePressing; + } else { + return ButtonPressDuration::LongPressing; + } +} + +} // namespace + +ButtonPoller::ButtonPoller(Core::System& system) { + // TODO: am reads this from the home button state in hid, which is controller-agnostic. + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = + [this](Core::HID::ControllerTriggerType type) { + if (type == Core::HID::ControllerTriggerType::Button) { + this->OnButtonStateChanged(); + } + }, + .is_npad_service = true, + }; + + m_handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + m_handheld_key = m_handheld->SetCallback(engine_callback); + m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + m_player1_key = m_player1->SetCallback(engine_callback); +} + +ButtonPoller::~ButtonPoller() { + m_handheld->DeleteCallback(m_handheld_key); + m_player1->DeleteCallback(m_player1_key); +} + +void ButtonPoller::OnButtonStateChanged() { + const bool home_button = + m_handheld->GetHomeButtons().home.Value() || m_player1->GetHomeButtons().home.Value(); + const bool capture_button = m_handheld->GetCaptureButtons().capture.Value() || + m_player1->GetCaptureButtons().capture.Value(); + + // Buttons pressed which were not previously pressed + if (home_button && !m_home_button_press_start) { + m_home_button_press_start = std::chrono::steady_clock::now(); + } + if (capture_button && !m_capture_button_press_start) { + m_capture_button_press_start = std::chrono::steady_clock::now(); + } + // if (power_button && !m_power_button_press_start) { + // m_power_button_press_start = std::chrono::steady_clock::now(); + // } + + // Buttons released which were previously held + if (!home_button && m_home_button_press_start) { + // TODO + m_home_button_press_start = std::nullopt; + } + if (!capture_button && m_capture_button_press_start) { + // TODO + m_capture_button_press_start = std::nullopt; + } + // if (!power_button && m_power_button_press_start) { + // // TODO + // m_power_button_press_start = std::nullopt; + // } +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/button_poller.h b/src/core/hle/service/am/button_poller.h new file mode 100644 index 0000000000..040ae036a0 --- /dev/null +++ b/src/core/hle/service/am/button_poller.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include "hid_core/frontend/emulated_controller.h" + +namespace Core { +namespace HID { +class EmulatedController; +} + +class System; +} // namespace Core + +namespace Service::AM { + +class ButtonPoller { +public: + explicit ButtonPoller(Core::System& system); + ~ButtonPoller(); + +private: + void OnButtonStateChanged(); + +private: + Core::HID::EmulatedController* m_handheld{}; + int m_handheld_key{}; + Core::HID::EmulatedController* m_player1{}; + int m_player1_key{}; + + std::optional m_home_button_press_start{}; + std::optional m_capture_button_press_start{}; + std::optional m_power_button_press_start{}; +}; + +} // namespace Service::AM