diff options
Diffstat (limited to 'src/core/frontend')
| -rw-r--r-- | src/core/frontend/applets/controller.cpp | 81 | ||||
| -rw-r--r-- | src/core/frontend/applets/controller.h | 56 | ||||
| -rw-r--r-- | src/core/frontend/emu_window.cpp | 12 | ||||
| -rw-r--r-- | src/core/frontend/emu_window.h | 4 | ||||
| -rw-r--r-- | src/core/frontend/framebuffer_layout.cpp | 12 | ||||
| -rw-r--r-- | src/core/frontend/framebuffer_layout.h | 6 | ||||
| -rw-r--r-- | src/core/frontend/input.h | 36 |
7 files changed, 189 insertions, 18 deletions
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp new file mode 100644 index 000000000..03bbedf8b --- /dev/null +++ b/src/core/frontend/applets/controller.cpp @@ -0,0 +1,81 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/logging/log.h" +#include "core/frontend/applets/controller.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/hid.h" +#include "core/hle/service/sm/sm.h" + +namespace Core::Frontend { + +ControllerApplet::~ControllerApplet() = default; + +DefaultControllerApplet::DefaultControllerApplet(Service::SM::ServiceManager& service_manager_) + : service_manager{service_manager_} {} + +DefaultControllerApplet::~DefaultControllerApplet() = default; + +void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback, + const ControllerParameters& parameters) const { + LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); + + auto& npad = + service_manager.GetService<Service::HID::Hid>("hid") + ->GetAppletResource() + ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); + + auto& players = Settings::values.players.GetValue(); + + const std::size_t min_supported_players = + parameters.enable_single_mode ? 1 : parameters.min_players; + + // Disconnect Handheld first. + npad.DisconnectNpadAtIndex(8); + + // Deduce the best configuration based on the input parameters. + for (std::size_t index = 0; index < players.size() - 2; ++index) { + // First, disconnect all controllers regardless of the value of keep_controllers_connected. + // This makes it easy to connect the desired controllers. + npad.DisconnectNpadAtIndex(index); + + // Only connect the minimum number of required players. + if (index >= min_supported_players) { + continue; + } + + // Connect controllers based on the following priority list from highest to lowest priority: + // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld + if (parameters.allow_pro_controller) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::ProController), index); + } else if (parameters.allow_dual_joycons) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::DualJoyconDetached), index); + } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) { + // Assign left joycons to even player indices and right joycons to odd player indices. + // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and + // a right Joycon for Player 2 in 2 Player Assist mode. + if (index % 2 == 0) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::LeftJoycon), index); + } else { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); + } + } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && + !Settings::values.use_docked_mode.GetValue()) { + // We should *never* reach here under any normal circumstances. + npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), + index); + } else { + UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); + } + } + + callback(); +} + +} // namespace Core::Frontend diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h new file mode 100644 index 000000000..dff71d8d9 --- /dev/null +++ b/src/core/frontend/applets/controller.h @@ -0,0 +1,56 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <functional> + +#include "common/common_types.h" + +namespace Service::SM { +class ServiceManager; +} + +namespace Core::Frontend { + +using BorderColor = std::array<u8, 4>; +using ExplainText = std::array<char, 0x81>; + +struct ControllerParameters { + s8 min_players{}; + s8 max_players{}; + bool keep_controllers_connected{}; + bool enable_single_mode{}; + bool enable_border_color{}; + std::vector<BorderColor> border_colors{}; + bool enable_explain_text{}; + std::vector<ExplainText> explain_text{}; + bool allow_pro_controller{}; + bool allow_handheld{}; + bool allow_dual_joycons{}; + bool allow_left_joycon{}; + bool allow_right_joycon{}; +}; + +class ControllerApplet { +public: + virtual ~ControllerApplet(); + + virtual void ReconfigureControllers(std::function<void()> callback, + const ControllerParameters& parameters) const = 0; +}; + +class DefaultControllerApplet final : public ControllerApplet { +public: + explicit DefaultControllerApplet(Service::SM::ServiceManager& service_manager_); + ~DefaultControllerApplet() override; + + void ReconfigureControllers(std::function<void()> callback, + const ControllerParameters& parameters) const override; + +private: + Service::SM::ServiceManager& service_manager; +}; + +} // namespace Core::Frontend diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index eda466a5d..8c1193894 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -46,7 +46,7 @@ private: EmuWindow::EmuWindow() { // TODO: Find a better place to set this. config.min_client_area_size = - std::make_pair(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); + std::make_pair(Layout::MinimumSize::Width, Layout::MinimumSize::Height); active_config = config; touch_state = std::make_shared<TouchState>(); Input::RegisterFactory<Input::TouchDevice>("emu_window", touch_state); @@ -84,10 +84,12 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { return; std::lock_guard guard{touch_state->mutex}; - touch_state->touch_x = static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) / - (framebuffer_layout.screen.right - framebuffer_layout.screen.left); - touch_state->touch_y = static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) / - (framebuffer_layout.screen.bottom - framebuffer_layout.screen.top); + touch_state->touch_x = + static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) / + static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left); + touch_state->touch_y = + static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) / + static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top); touch_state->touch_pressed = true; } diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 13aa14934..3e8780243 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -39,7 +39,7 @@ public: class Scoped { public: - explicit Scoped(GraphicsContext& context_) : context(context_) { + [[nodiscard]] explicit Scoped(GraphicsContext& context_) : context(context_) { context.MakeCurrent(); } ~Scoped() { @@ -52,7 +52,7 @@ public: /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value /// ends - Scoped Acquire() { + [[nodiscard]] Scoped Acquire() { return Scoped{*this}; } }; diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 68a0e0906..b9a270a55 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -14,8 +14,8 @@ namespace Layout { template <class T> static Common::Rectangle<T> MaxRectangle(Common::Rectangle<T> window_area, float screen_aspect_ratio) { - float scale = std::min(static_cast<float>(window_area.GetWidth()), - window_area.GetHeight() / screen_aspect_ratio); + const float scale = std::min(static_cast<float>(window_area.GetWidth()), + static_cast<float>(window_area.GetHeight()) / screen_aspect_ratio); return Common::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)), static_cast<T>(std::round(scale * screen_aspect_ratio))}; } @@ -25,11 +25,11 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) { ASSERT(height > 0); // The drawing code needs at least somewhat valid values for both screens // so just calculate them both even if the other isn't showing. - FramebufferLayout res{width, height}; + FramebufferLayout res{width, height, false, {}}; - const float window_aspect_ratio = static_cast<float>(height) / width; + const float window_aspect_ratio = static_cast<float>(height) / static_cast<float>(width); const float emulation_aspect_ratio = EmulationAspectRatio( - static_cast<AspectRatio>(Settings::values.aspect_ratio), window_aspect_ratio); + static_cast<AspectRatio>(Settings::values.aspect_ratio.GetValue()), window_aspect_ratio); const Common::Rectangle<u32> screen_window_area{0, 0, width, height}; Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio); @@ -47,7 +47,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) { FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { u32 width, height; - if (Settings::values.use_docked_mode) { + if (Settings::values.use_docked_mode.GetValue()) { width = ScreenDocked::Width * res_scale; height = ScreenDocked::Height * res_scale; } else { diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 15ecfb13d..e2e3bbbb3 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -4,10 +4,16 @@ #pragma once +#include "common/common_types.h" #include "common/math_util.h" namespace Layout { +namespace MinimumSize { +constexpr u32 Width = 640; +constexpr u32 Height = 360; +} // namespace MinimumSize + namespace ScreenUndocked { constexpr u32 Width = 1280; constexpr u32 Height = 720; diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index 2b098b7c6..11c2e96ca 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h @@ -30,7 +30,12 @@ public: virtual StatusType GetStatus() const { return {}; } - virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { + virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const { + return {}; + } + virtual bool SetRumblePlay([[maybe_unused]] f32 amp_low, [[maybe_unused]] f32 freq_low, + [[maybe_unused]] f32 amp_high, + [[maybe_unused]] f32 freq_high) const { return {}; } }; @@ -119,11 +124,18 @@ using ButtonDevice = InputDevice<bool>; using AnalogDevice = InputDevice<std::tuple<float, float>>; /** - * A motion device is an input device that returns a tuple of accelerometer state vector and - * gyroscope state vector. + * A vibration device is an input device that returns an unsigned byte as status. + * It represents whether the vibration device supports vibration or not. + * If the status returns 1, it supports vibration. Otherwise, it does not support vibration. + */ +using VibrationDevice = InputDevice<u8>; + +/** + * A motion status is an object that returns a tuple of accelerometer state vector, + * gyroscope state vector, rotation state vector and orientation state matrix. * * For both vectors: - * x+ is the same direction as LEFT on D-pad. + * x+ is the same direction as RIGHT on D-pad. * y+ is normal to the touch screen, pointing outward. * z+ is the same direction as UP on D-pad. * @@ -133,8 +145,22 @@ using AnalogDevice = InputDevice<std::tuple<float, float>>; * For gyroscope state vector: * Orientation is determined by right-hand rule. * Units: deg/sec + * + * For rotation state vector + * Units: rotations + * + * For orientation state matrix + * x vector + * y vector + * z vector + */ +using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>, + std::array<Common::Vec3f, 3>>; + +/** + * A motion device is an input device that returns a motion status object */ -using MotionDevice = InputDevice<std::tuple<Common::Vec3<float>, Common::Vec3<float>>>; +using MotionDevice = InputDevice<MotionStatus>; /** * A touch device is an input device that returns a tuple of two floats and a bool. The floats are |
