diff options
| author | 2020-09-10 19:28:23 -0400 | |
|---|---|---|
| committer | 2020-09-10 19:28:23 -0400 | |
| commit | 03179ecafe8a5e9dedcab57f593f47ecc71b6877 (patch) | |
| tree | ac862b62f9d1e8c3c50915dcefc3f34863140e93 /src/core | |
| parent | Merge pull request #4608 from lioncash/sign3 (diff) | |
| parent | Resolve spacing inconsistencies in style.qrc/qss files (diff) | |
| download | yuzu-03179ecafe8a5e9dedcab57f593f47ecc71b6877.tar.gz yuzu-03179ecafe8a5e9dedcab57f593f47ecc71b6877.tar.xz yuzu-03179ecafe8a5e9dedcab57f593f47ecc71b6877.zip | |
Merge pull request #4597 from Morph1984/mjolnir-p2
Project Mjölnir: Part 2 - Controller Applet
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/core/frontend/applets/controller.cpp | 81 | ||||
| -rw-r--r-- | src/core/frontend/applets/controller.h | 48 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/applets.cpp | 71 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/applets.h | 19 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/controller.cpp | 210 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/controller.h | 123 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 116 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 7 |
9 files changed, 548 insertions, 131 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b96ca9374..d0c405ec7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -126,6 +126,8 @@ add_library(core STATIC | |||
| 126 | file_sys/vfs_vector.h | 126 | file_sys/vfs_vector.h |
| 127 | file_sys/xts_archive.cpp | 127 | file_sys/xts_archive.cpp |
| 128 | file_sys/xts_archive.h | 128 | file_sys/xts_archive.h |
| 129 | frontend/applets/controller.cpp | ||
| 130 | frontend/applets/controller.h | ||
| 129 | frontend/applets/error.cpp | 131 | frontend/applets/error.cpp |
| 130 | frontend/applets/error.h | 132 | frontend/applets/error.h |
| 131 | frontend/applets/general_frontend.cpp | 133 | frontend/applets/general_frontend.cpp |
| @@ -244,6 +246,8 @@ add_library(core STATIC | |||
| 244 | hle/service/am/applet_oe.h | 246 | hle/service/am/applet_oe.h |
| 245 | hle/service/am/applets/applets.cpp | 247 | hle/service/am/applets/applets.cpp |
| 246 | hle/service/am/applets/applets.h | 248 | hle/service/am/applets/applets.h |
| 249 | hle/service/am/applets/controller.cpp | ||
| 250 | hle/service/am/applets/controller.h | ||
| 247 | hle/service/am/applets/error.cpp | 251 | hle/service/am/applets/error.cpp |
| 248 | hle/service/am/applets/error.h | 252 | hle/service/am/applets/error.h |
| 249 | hle/service/am/applets/general_backend.cpp | 253 | hle/service/am/applets/general_backend.cpp |
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp new file mode 100644 index 000000000..4505da758 --- /dev/null +++ b/src/core/frontend/applets/controller.cpp | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | #include "core/core.h" | ||
| 8 | #include "core/frontend/applets/controller.h" | ||
| 9 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 10 | #include "core/hle/service/hid/hid.h" | ||
| 11 | #include "core/hle/service/sm/sm.h" | ||
| 12 | |||
| 13 | namespace Core::Frontend { | ||
| 14 | |||
| 15 | ControllerApplet::~ControllerApplet() = default; | ||
| 16 | |||
| 17 | DefaultControllerApplet::~DefaultControllerApplet() = default; | ||
| 18 | |||
| 19 | void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback, | ||
| 20 | ControllerParameters parameters) const { | ||
| 21 | LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); | ||
| 22 | |||
| 23 | auto& npad = | ||
| 24 | Core::System::GetInstance() | ||
| 25 | .ServiceManager() | ||
| 26 | .GetService<Service::HID::Hid>("hid") | ||
| 27 | ->GetAppletResource() | ||
| 28 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); | ||
| 29 | |||
| 30 | auto& players = Settings::values.players; | ||
| 31 | |||
| 32 | const std::size_t min_supported_players = | ||
| 33 | parameters.enable_single_mode ? 1 : parameters.min_players; | ||
| 34 | |||
| 35 | // Disconnect Handheld first. | ||
| 36 | npad.DisconnectNPadAtIndex(8); | ||
| 37 | |||
| 38 | // Deduce the best configuration based on the input parameters. | ||
| 39 | for (std::size_t index = 0; index < players.size() - 2; ++index) { | ||
| 40 | // First, disconnect all controllers regardless of the value of keep_controllers_connected. | ||
| 41 | // This makes it easy to connect the desired controllers. | ||
| 42 | npad.DisconnectNPadAtIndex(index); | ||
| 43 | |||
| 44 | // Only connect the minimum number of required players. | ||
| 45 | if (index >= min_supported_players) { | ||
| 46 | continue; | ||
| 47 | } | ||
| 48 | |||
| 49 | // Connect controllers based on the following priority list from highest to lowest priority: | ||
| 50 | // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld | ||
| 51 | if (parameters.allow_pro_controller) { | ||
| 52 | npad.AddNewControllerAt( | ||
| 53 | npad.MapSettingsTypeToNPad(Settings::ControllerType::ProController), index); | ||
| 54 | } else if (parameters.allow_dual_joycons) { | ||
| 55 | npad.AddNewControllerAt( | ||
| 56 | npad.MapSettingsTypeToNPad(Settings::ControllerType::DualJoyconDetached), index); | ||
| 57 | } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) { | ||
| 58 | // Assign left joycons to even player indices and right joycons to odd player indices. | ||
| 59 | // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and | ||
| 60 | // a right Joycon for Player 2 in 2 Player Assist mode. | ||
| 61 | if (index % 2 == 0) { | ||
| 62 | npad.AddNewControllerAt( | ||
| 63 | npad.MapSettingsTypeToNPad(Settings::ControllerType::LeftJoycon), index); | ||
| 64 | } else { | ||
| 65 | npad.AddNewControllerAt( | ||
| 66 | npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); | ||
| 67 | } | ||
| 68 | } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && | ||
| 69 | !Settings::values.use_docked_mode) { | ||
| 70 | // We should *never* reach here under any normal circumstances. | ||
| 71 | npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), | ||
| 72 | index); | ||
| 73 | } else { | ||
| 74 | UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | callback(); | ||
| 79 | } | ||
| 80 | |||
| 81 | } // 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..a227f15cd --- /dev/null +++ b/src/core/frontend/applets/controller.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <functional> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Core::Frontend { | ||
| 12 | |||
| 13 | using BorderColor = std::array<u8, 4>; | ||
| 14 | using ExplainText = std::array<char, 0x81>; | ||
| 15 | |||
| 16 | struct ControllerParameters { | ||
| 17 | s8 min_players{}; | ||
| 18 | s8 max_players{}; | ||
| 19 | bool keep_controllers_connected{}; | ||
| 20 | bool enable_single_mode{}; | ||
| 21 | bool enable_border_color{}; | ||
| 22 | std::vector<BorderColor> border_colors{}; | ||
| 23 | bool enable_explain_text{}; | ||
| 24 | std::vector<ExplainText> explain_text{}; | ||
| 25 | bool allow_pro_controller{}; | ||
| 26 | bool allow_handheld{}; | ||
| 27 | bool allow_dual_joycons{}; | ||
| 28 | bool allow_left_joycon{}; | ||
| 29 | bool allow_right_joycon{}; | ||
| 30 | }; | ||
| 31 | |||
| 32 | class ControllerApplet { | ||
| 33 | public: | ||
| 34 | virtual ~ControllerApplet(); | ||
| 35 | |||
| 36 | virtual void ReconfigureControllers(std::function<void()> callback, | ||
| 37 | ControllerParameters parameters) const = 0; | ||
| 38 | }; | ||
| 39 | |||
| 40 | class DefaultControllerApplet final : public ControllerApplet { | ||
| 41 | public: | ||
| 42 | ~DefaultControllerApplet() override; | ||
| 43 | |||
| 44 | void ReconfigureControllers(std::function<void()> callback, | ||
| 45 | ControllerParameters parameters) const override; | ||
| 46 | }; | ||
| 47 | |||
| 48 | } // namespace Core::Frontend | ||
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index c3261f3e6..4e0800f9a 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/frontend/applets/controller.h" | ||
| 8 | #include "core/frontend/applets/error.h" | 9 | #include "core/frontend/applets/error.h" |
| 9 | #include "core/frontend/applets/general_frontend.h" | 10 | #include "core/frontend/applets/general_frontend.h" |
| 10 | #include "core/frontend/applets/profile_select.h" | 11 | #include "core/frontend/applets/profile_select.h" |
| @@ -15,6 +16,7 @@ | |||
| 15 | #include "core/hle/kernel/writable_event.h" | 16 | #include "core/hle/kernel/writable_event.h" |
| 16 | #include "core/hle/service/am/am.h" | 17 | #include "core/hle/service/am/am.h" |
| 17 | #include "core/hle/service/am/applets/applets.h" | 18 | #include "core/hle/service/am/applets/applets.h" |
| 19 | #include "core/hle/service/am/applets/controller.h" | ||
| 18 | #include "core/hle/service/am/applets/error.h" | 20 | #include "core/hle/service/am/applets/error.h" |
| 19 | #include "core/hle/service/am/applets/general_backend.h" | 21 | #include "core/hle/service/am/applets/general_backend.h" |
| 20 | #include "core/hle/service/am/applets/profile_select.h" | 22 | #include "core/hle/service/am/applets/profile_select.h" |
| @@ -140,14 +142,14 @@ void Applet::Initialize() { | |||
| 140 | 142 | ||
| 141 | AppletFrontendSet::AppletFrontendSet() = default; | 143 | AppletFrontendSet::AppletFrontendSet() = default; |
| 142 | 144 | ||
| 143 | AppletFrontendSet::AppletFrontendSet(ParentalControlsApplet parental_controls, ErrorApplet error, | 145 | AppletFrontendSet::AppletFrontendSet(ControllerApplet controller, ECommerceApplet e_commerce, |
| 146 | ErrorApplet error, ParentalControlsApplet parental_controls, | ||
| 144 | PhotoViewer photo_viewer, ProfileSelect profile_select, | 147 | PhotoViewer photo_viewer, ProfileSelect profile_select, |
| 145 | SoftwareKeyboard software_keyboard, WebBrowser web_browser, | 148 | SoftwareKeyboard software_keyboard, WebBrowser web_browser) |
| 146 | ECommerceApplet e_commerce) | 149 | : controller{std::move(controller)}, e_commerce{std::move(e_commerce)}, error{std::move(error)}, |
| 147 | : parental_controls{std::move(parental_controls)}, error{std::move(error)}, | 150 | parental_controls{std::move(parental_controls)}, photo_viewer{std::move(photo_viewer)}, |
| 148 | photo_viewer{std::move(photo_viewer)}, profile_select{std::move(profile_select)}, | 151 | profile_select{std::move(profile_select)}, software_keyboard{std::move(software_keyboard)}, |
| 149 | software_keyboard{std::move(software_keyboard)}, web_browser{std::move(web_browser)}, | 152 | web_browser{std::move(web_browser)} {} |
| 150 | e_commerce{std::move(e_commerce)} {} | ||
| 151 | 153 | ||
| 152 | AppletFrontendSet::~AppletFrontendSet() = default; | 154 | AppletFrontendSet::~AppletFrontendSet() = default; |
| 153 | 155 | ||
| @@ -164,20 +166,37 @@ const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const { | |||
| 164 | } | 166 | } |
| 165 | 167 | ||
| 166 | void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { | 168 | void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { |
| 167 | if (set.parental_controls != nullptr) | 169 | if (set.controller != nullptr) { |
| 168 | frontend.parental_controls = std::move(set.parental_controls); | 170 | frontend.controller = std::move(set.controller); |
| 169 | if (set.error != nullptr) | 171 | } |
| 172 | |||
| 173 | if (set.e_commerce != nullptr) { | ||
| 174 | frontend.e_commerce = std::move(set.e_commerce); | ||
| 175 | } | ||
| 176 | |||
| 177 | if (set.error != nullptr) { | ||
| 170 | frontend.error = std::move(set.error); | 178 | frontend.error = std::move(set.error); |
| 171 | if (set.photo_viewer != nullptr) | 179 | } |
| 180 | |||
| 181 | if (set.parental_controls != nullptr) { | ||
| 182 | frontend.parental_controls = std::move(set.parental_controls); | ||
| 183 | } | ||
| 184 | |||
| 185 | if (set.photo_viewer != nullptr) { | ||
| 172 | frontend.photo_viewer = std::move(set.photo_viewer); | 186 | frontend.photo_viewer = std::move(set.photo_viewer); |
| 173 | if (set.profile_select != nullptr) | 187 | } |
| 188 | |||
| 189 | if (set.profile_select != nullptr) { | ||
| 174 | frontend.profile_select = std::move(set.profile_select); | 190 | frontend.profile_select = std::move(set.profile_select); |
| 175 | if (set.software_keyboard != nullptr) | 191 | } |
| 192 | |||
| 193 | if (set.software_keyboard != nullptr) { | ||
| 176 | frontend.software_keyboard = std::move(set.software_keyboard); | 194 | frontend.software_keyboard = std::move(set.software_keyboard); |
| 177 | if (set.web_browser != nullptr) | 195 | } |
| 196 | |||
| 197 | if (set.web_browser != nullptr) { | ||
| 178 | frontend.web_browser = std::move(set.web_browser); | 198 | frontend.web_browser = std::move(set.web_browser); |
| 179 | if (set.e_commerce != nullptr) | 199 | } |
| 180 | frontend.e_commerce = std::move(set.e_commerce); | ||
| 181 | } | 200 | } |
| 182 | 201 | ||
| 183 | void AppletManager::SetDefaultAppletFrontendSet() { | 202 | void AppletManager::SetDefaultAppletFrontendSet() { |
| @@ -186,15 +205,23 @@ void AppletManager::SetDefaultAppletFrontendSet() { | |||
| 186 | } | 205 | } |
| 187 | 206 | ||
| 188 | void AppletManager::SetDefaultAppletsIfMissing() { | 207 | void AppletManager::SetDefaultAppletsIfMissing() { |
| 189 | if (frontend.parental_controls == nullptr) { | 208 | if (frontend.controller == nullptr) { |
| 190 | frontend.parental_controls = | 209 | frontend.controller = std::make_unique<Core::Frontend::DefaultControllerApplet>(); |
| 191 | std::make_unique<Core::Frontend::DefaultParentalControlsApplet>(); | 210 | } |
| 211 | |||
| 212 | if (frontend.e_commerce == nullptr) { | ||
| 213 | frontend.e_commerce = std::make_unique<Core::Frontend::DefaultECommerceApplet>(); | ||
| 192 | } | 214 | } |
| 193 | 215 | ||
| 194 | if (frontend.error == nullptr) { | 216 | if (frontend.error == nullptr) { |
| 195 | frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); | 217 | frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); |
| 196 | } | 218 | } |
| 197 | 219 | ||
| 220 | if (frontend.parental_controls == nullptr) { | ||
| 221 | frontend.parental_controls = | ||
| 222 | std::make_unique<Core::Frontend::DefaultParentalControlsApplet>(); | ||
| 223 | } | ||
| 224 | |||
| 198 | if (frontend.photo_viewer == nullptr) { | 225 | if (frontend.photo_viewer == nullptr) { |
| 199 | frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); | 226 | frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); |
| 200 | } | 227 | } |
| @@ -211,10 +238,6 @@ void AppletManager::SetDefaultAppletsIfMissing() { | |||
| 211 | if (frontend.web_browser == nullptr) { | 238 | if (frontend.web_browser == nullptr) { |
| 212 | frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); | 239 | frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>(); |
| 213 | } | 240 | } |
| 214 | |||
| 215 | if (frontend.e_commerce == nullptr) { | ||
| 216 | frontend.e_commerce = std::make_unique<Core::Frontend::DefaultECommerceApplet>(); | ||
| 217 | } | ||
| 218 | } | 241 | } |
| 219 | 242 | ||
| 220 | void AppletManager::ClearAll() { | 243 | void AppletManager::ClearAll() { |
| @@ -225,6 +248,8 @@ std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { | |||
| 225 | switch (id) { | 248 | switch (id) { |
| 226 | case AppletId::Auth: | 249 | case AppletId::Auth: |
| 227 | return std::make_shared<Auth>(system, *frontend.parental_controls); | 250 | return std::make_shared<Auth>(system, *frontend.parental_controls); |
| 251 | case AppletId::Controller: | ||
| 252 | return std::make_shared<Controller>(system, *frontend.controller); | ||
| 228 | case AppletId::Error: | 253 | case AppletId::Error: |
| 229 | return std::make_shared<Error>(system, *frontend.error); | 254 | return std::make_shared<Error>(system, *frontend.error); |
| 230 | case AppletId::ProfileSelect: | 255 | case AppletId::ProfileSelect: |
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index e75be86a2..a1f4cf897 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h | |||
| @@ -17,6 +17,7 @@ class System; | |||
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | namespace Core::Frontend { | 19 | namespace Core::Frontend { |
| 20 | class ControllerApplet; | ||
| 20 | class ECommerceApplet; | 21 | class ECommerceApplet; |
| 21 | class ErrorApplet; | 22 | class ErrorApplet; |
| 22 | class ParentalControlsApplet; | 23 | class ParentalControlsApplet; |
| @@ -155,19 +156,20 @@ protected: | |||
| 155 | }; | 156 | }; |
| 156 | 157 | ||
| 157 | struct AppletFrontendSet { | 158 | struct AppletFrontendSet { |
| 158 | using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>; | 159 | using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>; |
| 160 | using ECommerceApplet = std::unique_ptr<Core::Frontend::ECommerceApplet>; | ||
| 159 | using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; | 161 | using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; |
| 162 | using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>; | ||
| 160 | using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; | 163 | using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; |
| 161 | using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; | 164 | using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; |
| 162 | using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; | 165 | using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; |
| 163 | using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; | 166 | using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; |
| 164 | using ECommerceApplet = std::unique_ptr<Core::Frontend::ECommerceApplet>; | ||
| 165 | 167 | ||
| 166 | AppletFrontendSet(); | 168 | AppletFrontendSet(); |
| 167 | AppletFrontendSet(ParentalControlsApplet parental_controls, ErrorApplet error, | 169 | AppletFrontendSet(ControllerApplet controller, ECommerceApplet e_commerce, ErrorApplet error, |
| 168 | PhotoViewer photo_viewer, ProfileSelect profile_select, | 170 | ParentalControlsApplet parental_controls, PhotoViewer photo_viewer, |
| 169 | SoftwareKeyboard software_keyboard, WebBrowser web_browser, | 171 | ProfileSelect profile_select, SoftwareKeyboard software_keyboard, |
| 170 | ECommerceApplet e_commerce); | 172 | WebBrowser web_browser); |
| 171 | ~AppletFrontendSet(); | 173 | ~AppletFrontendSet(); |
| 172 | 174 | ||
| 173 | AppletFrontendSet(const AppletFrontendSet&) = delete; | 175 | AppletFrontendSet(const AppletFrontendSet&) = delete; |
| @@ -176,13 +178,14 @@ struct AppletFrontendSet { | |||
| 176 | AppletFrontendSet(AppletFrontendSet&&) noexcept; | 178 | AppletFrontendSet(AppletFrontendSet&&) noexcept; |
| 177 | AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; | 179 | AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; |
| 178 | 180 | ||
| 179 | ParentalControlsApplet parental_controls; | 181 | ControllerApplet controller; |
| 182 | ECommerceApplet e_commerce; | ||
| 180 | ErrorApplet error; | 183 | ErrorApplet error; |
| 184 | ParentalControlsApplet parental_controls; | ||
| 181 | PhotoViewer photo_viewer; | 185 | PhotoViewer photo_viewer; |
| 182 | ProfileSelect profile_select; | 186 | ProfileSelect profile_select; |
| 183 | SoftwareKeyboard software_keyboard; | 187 | SoftwareKeyboard software_keyboard; |
| 184 | WebBrowser web_browser; | 188 | WebBrowser web_browser; |
| 185 | ECommerceApplet e_commerce; | ||
| 186 | }; | 189 | }; |
| 187 | 190 | ||
| 188 | class AppletManager { | 191 | class AppletManager { |
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp new file mode 100644 index 000000000..2151da783 --- /dev/null +++ b/src/core/hle/service/am/applets/controller.cpp | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cstring> | ||
| 7 | |||
| 8 | #include "common/assert.h" | ||
| 9 | #include "common/logging/log.h" | ||
| 10 | #include "common/string_util.h" | ||
| 11 | #include "core/core.h" | ||
| 12 | #include "core/frontend/applets/controller.h" | ||
| 13 | #include "core/hle/result.h" | ||
| 14 | #include "core/hle/service/am/am.h" | ||
| 15 | #include "core/hle/service/am/applets/controller.h" | ||
| 16 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 17 | |||
| 18 | namespace Service::AM::Applets { | ||
| 19 | |||
| 20 | // This error code (0x183ACA) is thrown when the applet fails to initialize. | ||
| 21 | [[maybe_unused]] constexpr ResultCode ERR_CONTROLLER_APPLET_3101{ErrorModule::HID, 3101}; | ||
| 22 | // This error code (0x183CCA) is thrown when the u32 result in ControllerSupportResultInfo is 2. | ||
| 23 | [[maybe_unused]] constexpr ResultCode ERR_CONTROLLER_APPLET_3102{ErrorModule::HID, 3102}; | ||
| 24 | |||
| 25 | static Core::Frontend::ControllerParameters ConvertToFrontendParameters( | ||
| 26 | ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, | ||
| 27 | std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) { | ||
| 28 | HID::Controller_NPad::NPadType npad_style_set; | ||
| 29 | npad_style_set.raw = private_arg.style_set; | ||
| 30 | |||
| 31 | return { | ||
| 32 | .min_players = std::max(s8(1), header.player_count_min), | ||
| 33 | .max_players = header.player_count_max, | ||
| 34 | .keep_controllers_connected = header.enable_take_over_connection, | ||
| 35 | .enable_single_mode = header.enable_single_mode, | ||
| 36 | .enable_border_color = header.enable_identification_color, | ||
| 37 | .border_colors = identification_colors, | ||
| 38 | .enable_explain_text = enable_text, | ||
| 39 | .explain_text = text, | ||
| 40 | .allow_pro_controller = npad_style_set.pro_controller == 1, | ||
| 41 | .allow_handheld = npad_style_set.handheld == 1, | ||
| 42 | .allow_dual_joycons = npad_style_set.joycon_dual == 1, | ||
| 43 | .allow_left_joycon = npad_style_set.joycon_left == 1, | ||
| 44 | .allow_right_joycon = npad_style_set.joycon_right == 1, | ||
| 45 | }; | ||
| 46 | } | ||
| 47 | |||
| 48 | Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_) | ||
| 49 | : Applet{system_.Kernel()}, frontend(frontend_) {} | ||
| 50 | |||
| 51 | Controller::~Controller() = default; | ||
| 52 | |||
| 53 | void Controller::Initialize() { | ||
| 54 | Applet::Initialize(); | ||
| 55 | |||
| 56 | LOG_INFO(Service_HID, "Initializing Controller Applet."); | ||
| 57 | |||
| 58 | LOG_DEBUG(Service_HID, | ||
| 59 | "Initializing Applet with common_args: arg_version={}, lib_version={}, " | ||
| 60 | "play_startup_sound={}, size={}, system_tick={}, theme_color={}", | ||
| 61 | common_args.arguments_version, common_args.library_version, | ||
| 62 | common_args.play_startup_sound, common_args.size, common_args.system_tick, | ||
| 63 | common_args.theme_color); | ||
| 64 | |||
| 65 | library_applet_version = LibraryAppletVersion{common_args.library_version}; | ||
| 66 | |||
| 67 | const auto private_arg_storage = broker.PopNormalDataToApplet(); | ||
| 68 | ASSERT(private_arg_storage != nullptr); | ||
| 69 | |||
| 70 | const auto& private_arg = private_arg_storage->GetData(); | ||
| 71 | ASSERT(private_arg.size() == sizeof(ControllerSupportArgPrivate)); | ||
| 72 | |||
| 73 | std::memcpy(&controller_private_arg, private_arg.data(), sizeof(ControllerSupportArgPrivate)); | ||
| 74 | ASSERT_MSG(controller_private_arg.arg_private_size == sizeof(ControllerSupportArgPrivate), | ||
| 75 | "Unknown ControllerSupportArgPrivate revision={} with size={}", | ||
| 76 | library_applet_version, controller_private_arg.arg_private_size); | ||
| 77 | |||
| 78 | switch (controller_private_arg.mode) { | ||
| 79 | case ControllerSupportMode::ShowControllerSupport: { | ||
| 80 | const auto user_arg_storage = broker.PopNormalDataToApplet(); | ||
| 81 | ASSERT(user_arg_storage != nullptr); | ||
| 82 | |||
| 83 | const auto& user_arg = user_arg_storage->GetData(); | ||
| 84 | switch (library_applet_version) { | ||
| 85 | case LibraryAppletVersion::Version3: | ||
| 86 | case LibraryAppletVersion::Version4: | ||
| 87 | case LibraryAppletVersion::Version5: | ||
| 88 | ASSERT(user_arg.size() == sizeof(ControllerSupportArgOld)); | ||
| 89 | std::memcpy(&controller_user_arg_old, user_arg.data(), sizeof(ControllerSupportArgOld)); | ||
| 90 | break; | ||
| 91 | case LibraryAppletVersion::Version7: | ||
| 92 | ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew)); | ||
| 93 | std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew)); | ||
| 94 | break; | ||
| 95 | default: | ||
| 96 | UNIMPLEMENTED_MSG("Unknown ControllerSupportArg revision={} with size={}", | ||
| 97 | library_applet_version, controller_private_arg.arg_size); | ||
| 98 | ASSERT(user_arg.size() >= sizeof(ControllerSupportArgNew)); | ||
| 99 | std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew)); | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | case ControllerSupportMode::ShowControllerStrapGuide: | ||
| 105 | case ControllerSupportMode::ShowControllerFirmwareUpdate: | ||
| 106 | default: { | ||
| 107 | UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode); | ||
| 108 | break; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | bool Controller::TransactionComplete() const { | ||
| 114 | return complete; | ||
| 115 | } | ||
| 116 | |||
| 117 | ResultCode Controller::GetStatus() const { | ||
| 118 | return status; | ||
| 119 | } | ||
| 120 | |||
| 121 | void Controller::ExecuteInteractive() { | ||
| 122 | UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet."); | ||
| 123 | } | ||
| 124 | |||
| 125 | void Controller::Execute() { | ||
| 126 | switch (controller_private_arg.mode) { | ||
| 127 | case ControllerSupportMode::ShowControllerSupport: { | ||
| 128 | const auto parameters = [this] { | ||
| 129 | switch (library_applet_version) { | ||
| 130 | case LibraryAppletVersion::Version3: | ||
| 131 | case LibraryAppletVersion::Version4: | ||
| 132 | case LibraryAppletVersion::Version5: | ||
| 133 | return ConvertToFrontendParameters( | ||
| 134 | controller_private_arg, controller_user_arg_old.header, | ||
| 135 | controller_user_arg_old.enable_explain_text, | ||
| 136 | std::vector<IdentificationColor>( | ||
| 137 | controller_user_arg_old.identification_colors.begin(), | ||
| 138 | controller_user_arg_old.identification_colors.end()), | ||
| 139 | std::vector<ExplainText>(controller_user_arg_old.explain_text.begin(), | ||
| 140 | controller_user_arg_old.explain_text.end())); | ||
| 141 | case LibraryAppletVersion::Version7: | ||
| 142 | default: | ||
| 143 | return ConvertToFrontendParameters( | ||
| 144 | controller_private_arg, controller_user_arg_new.header, | ||
| 145 | controller_user_arg_new.enable_explain_text, | ||
| 146 | std::vector<IdentificationColor>( | ||
| 147 | controller_user_arg_new.identification_colors.begin(), | ||
| 148 | controller_user_arg_new.identification_colors.end()), | ||
| 149 | std::vector<ExplainText>(controller_user_arg_new.explain_text.begin(), | ||
| 150 | controller_user_arg_new.explain_text.end())); | ||
| 151 | } | ||
| 152 | }(); | ||
| 153 | |||
| 154 | is_single_mode = parameters.enable_single_mode; | ||
| 155 | |||
| 156 | LOG_DEBUG(Service_HID, | ||
| 157 | "Controller Parameters: min_players={}, max_players={}, " | ||
| 158 | "keep_controllers_connected={}, enable_single_mode={}, enable_border_color={}, " | ||
| 159 | "enable_explain_text={}, allow_pro_controller={}, allow_handheld={}, " | ||
| 160 | "allow_dual_joycons={}, allow_left_joycon={}, allow_right_joycon={}", | ||
| 161 | parameters.min_players, parameters.max_players, | ||
| 162 | parameters.keep_controllers_connected, parameters.enable_single_mode, | ||
| 163 | parameters.enable_border_color, parameters.enable_explain_text, | ||
| 164 | parameters.allow_pro_controller, parameters.allow_handheld, | ||
| 165 | parameters.allow_dual_joycons, parameters.allow_left_joycon, | ||
| 166 | parameters.allow_right_joycon); | ||
| 167 | |||
| 168 | frontend.ReconfigureControllers([this] { ConfigurationComplete(); }, parameters); | ||
| 169 | break; | ||
| 170 | } | ||
| 171 | case ControllerSupportMode::ShowControllerStrapGuide: | ||
| 172 | case ControllerSupportMode::ShowControllerFirmwareUpdate: | ||
| 173 | default: { | ||
| 174 | ConfigurationComplete(); | ||
| 175 | break; | ||
| 176 | } | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | void Controller::ConfigurationComplete() { | ||
| 181 | ControllerSupportResultInfo result_info{}; | ||
| 182 | |||
| 183 | const auto& players = Settings::values.players; | ||
| 184 | |||
| 185 | // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. | ||
| 186 | // Otherwise, only count connected players from P1-P8. | ||
| 187 | result_info.player_count = | ||
| 188 | is_single_mode ? 1 | ||
| 189 | : static_cast<s8>(std::count_if( | ||
| 190 | players.begin(), players.end() - 2, | ||
| 191 | [](Settings::PlayerInput player) { return player.connected; })); | ||
| 192 | |||
| 193 | result_info.selected_id = HID::Controller_NPad::IndexToNPad( | ||
| 194 | std::distance(players.begin(), | ||
| 195 | std::find_if(players.begin(), players.end(), | ||
| 196 | [](Settings::PlayerInput player) { return player.connected; }))); | ||
| 197 | |||
| 198 | result_info.result = 0; | ||
| 199 | |||
| 200 | LOG_DEBUG(Service_HID, "Result Info: player_count={}, selected_id={}, result={}", | ||
| 201 | result_info.player_count, result_info.selected_id, result_info.result); | ||
| 202 | |||
| 203 | complete = true; | ||
| 204 | out_data = std::vector<u8>(sizeof(ControllerSupportResultInfo)); | ||
| 205 | std::memcpy(out_data.data(), &result_info, out_data.size()); | ||
| 206 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(out_data))); | ||
| 207 | broker.SignalStateChanged(); | ||
| 208 | } | ||
| 209 | |||
| 210 | } // namespace Service::AM::Applets | ||
diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h new file mode 100644 index 000000000..f7bb3fba9 --- /dev/null +++ b/src/core/hle/service/am/applets/controller.h | |||
| @@ -0,0 +1,123 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "core/hle/result.h" | ||
| 13 | #include "core/hle/service/am/applets/applets.h" | ||
| 14 | |||
| 15 | namespace Core { | ||
| 16 | class System; | ||
| 17 | } | ||
| 18 | |||
| 19 | namespace Service::AM::Applets { | ||
| 20 | |||
| 21 | using IdentificationColor = std::array<u8, 4>; | ||
| 22 | using ExplainText = std::array<char, 0x81>; | ||
| 23 | |||
| 24 | enum class LibraryAppletVersion : u32_le { | ||
| 25 | Version3 = 0x3, // 1.0.0 - 2.3.0 | ||
| 26 | Version4 = 0x4, // 3.0.0 - 5.1.0 | ||
| 27 | Version5 = 0x5, // 6.0.0 - 7.0.1 | ||
| 28 | Version7 = 0x7, // 8.0.0+ | ||
| 29 | }; | ||
| 30 | |||
| 31 | enum class ControllerSupportMode : u8 { | ||
| 32 | ShowControllerSupport = 0, | ||
| 33 | ShowControllerStrapGuide = 1, | ||
| 34 | ShowControllerFirmwareUpdate = 2, | ||
| 35 | }; | ||
| 36 | |||
| 37 | enum class ControllerSupportCaller : u8 { | ||
| 38 | Application = 0, | ||
| 39 | System = 1, | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct ControllerSupportArgPrivate { | ||
| 43 | u32 arg_private_size{}; | ||
| 44 | u32 arg_size{}; | ||
| 45 | bool flag_0{}; | ||
| 46 | bool flag_1{}; | ||
| 47 | ControllerSupportMode mode{}; | ||
| 48 | ControllerSupportCaller caller{}; | ||
| 49 | u32 style_set{}; | ||
| 50 | u32 joy_hold_type{}; | ||
| 51 | }; | ||
| 52 | static_assert(sizeof(ControllerSupportArgPrivate) == 0x14, | ||
| 53 | "ControllerSupportArgPrivate has incorrect size."); | ||
| 54 | |||
| 55 | struct ControllerSupportArgHeader { | ||
| 56 | s8 player_count_min{}; | ||
| 57 | s8 player_count_max{}; | ||
| 58 | bool enable_take_over_connection{}; | ||
| 59 | bool enable_left_justify{}; | ||
| 60 | bool enable_permit_joy_dual{}; | ||
| 61 | bool enable_single_mode{}; | ||
| 62 | bool enable_identification_color{}; | ||
| 63 | }; | ||
| 64 | static_assert(sizeof(ControllerSupportArgHeader) == 0x7, | ||
| 65 | "ControllerSupportArgHeader has incorrect size."); | ||
| 66 | |||
| 67 | // LibraryAppletVersion 0x3, 0x4, 0x5 | ||
| 68 | struct ControllerSupportArgOld { | ||
| 69 | ControllerSupportArgHeader header{}; | ||
| 70 | std::array<IdentificationColor, 4> identification_colors{}; | ||
| 71 | bool enable_explain_text{}; | ||
| 72 | std::array<ExplainText, 4> explain_text{}; | ||
| 73 | }; | ||
| 74 | static_assert(sizeof(ControllerSupportArgOld) == 0x21C, | ||
| 75 | "ControllerSupportArgOld has incorrect size."); | ||
| 76 | |||
| 77 | // LibraryAppletVersion 0x7 | ||
| 78 | struct ControllerSupportArgNew { | ||
| 79 | ControllerSupportArgHeader header{}; | ||
| 80 | std::array<IdentificationColor, 8> identification_colors{}; | ||
| 81 | bool enable_explain_text{}; | ||
| 82 | std::array<ExplainText, 8> explain_text{}; | ||
| 83 | }; | ||
| 84 | static_assert(sizeof(ControllerSupportArgNew) == 0x430, | ||
| 85 | "ControllerSupportArgNew has incorrect size."); | ||
| 86 | |||
| 87 | struct ControllerSupportResultInfo { | ||
| 88 | s8 player_count{}; | ||
| 89 | INSERT_PADDING_BYTES(3); | ||
| 90 | u32 selected_id{}; | ||
| 91 | u32 result{}; | ||
| 92 | }; | ||
| 93 | static_assert(sizeof(ControllerSupportResultInfo) == 0xC, | ||
| 94 | "ControllerSupportResultInfo has incorrect size."); | ||
| 95 | |||
| 96 | class Controller final : public Applet { | ||
| 97 | public: | ||
| 98 | explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_); | ||
| 99 | ~Controller() override; | ||
| 100 | |||
| 101 | void Initialize() override; | ||
| 102 | |||
| 103 | bool TransactionComplete() const override; | ||
| 104 | ResultCode GetStatus() const override; | ||
| 105 | void ExecuteInteractive() override; | ||
| 106 | void Execute() override; | ||
| 107 | |||
| 108 | void ConfigurationComplete(); | ||
| 109 | |||
| 110 | private: | ||
| 111 | const Core::Frontend::ControllerApplet& frontend; | ||
| 112 | |||
| 113 | LibraryAppletVersion library_applet_version; | ||
| 114 | ControllerSupportArgPrivate controller_private_arg; | ||
| 115 | ControllerSupportArgOld controller_user_arg_old; | ||
| 116 | ControllerSupportArgNew controller_user_arg_new; | ||
| 117 | bool complete{false}; | ||
| 118 | ResultCode status{RESULT_SUCCESS}; | ||
| 119 | bool is_single_mode{false}; | ||
| 120 | std::vector<u8> out_data; | ||
| 121 | }; | ||
| 122 | |||
| 123 | } // namespace Service::AM::Applets | ||
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e742497e1..7818c098f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -193,7 +193,8 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 193 | controller.battery_level[0] = BATTERY_FULL; | 193 | controller.battery_level[0] = BATTERY_FULL; |
| 194 | controller.battery_level[1] = BATTERY_FULL; | 194 | controller.battery_level[1] = BATTERY_FULL; |
| 195 | controller.battery_level[2] = BATTERY_FULL; | 195 | controller.battery_level[2] = BATTERY_FULL; |
| 196 | styleset_changed_events[controller_idx].writable->Signal(); | 196 | |
| 197 | SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); | ||
| 197 | } | 198 | } |
| 198 | 199 | ||
| 199 | void Controller_NPad::OnInit() { | 200 | void Controller_NPad::OnInit() { |
| @@ -518,13 +519,17 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 518 | last_processed_vibration = vibrations.back(); | 519 | last_processed_vibration = vibrations.back(); |
| 519 | } | 520 | } |
| 520 | 521 | ||
| 522 | Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | ||
| 523 | return last_processed_vibration; | ||
| 524 | } | ||
| 525 | |||
| 521 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { | 526 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { |
| 522 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; | 527 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; |
| 523 | return styleset_event.readable; | 528 | return styleset_event.readable; |
| 524 | } | 529 | } |
| 525 | 530 | ||
| 526 | Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | 531 | void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { |
| 527 | return last_processed_vibration; | 532 | styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal(); |
| 528 | } | 533 | } |
| 529 | 534 | ||
| 530 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { | 535 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { |
| @@ -534,7 +539,7 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz | |||
| 534 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, | 539 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, |
| 535 | bool connected) { | 540 | bool connected) { |
| 536 | if (!connected) { | 541 | if (!connected) { |
| 537 | DisconnectNPad(IndexToNPad(npad_index)); | 542 | DisconnectNPadAtIndex(npad_index); |
| 538 | return; | 543 | return; |
| 539 | } | 544 | } |
| 540 | 545 | ||
| @@ -554,16 +559,19 @@ void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::siz | |||
| 554 | } | 559 | } |
| 555 | 560 | ||
| 556 | void Controller_NPad::DisconnectNPad(u32 npad_id) { | 561 | void Controller_NPad::DisconnectNPad(u32 npad_id) { |
| 557 | const auto npad_index = NPadIdToIndex(npad_id); | 562 | DisconnectNPadAtIndex(NPadIdToIndex(npad_id)); |
| 558 | connected_controllers[npad_index].is_connected = false; | 563 | } |
| 564 | |||
| 565 | void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { | ||
| 559 | Settings::values.players[npad_index].connected = false; | 566 | Settings::values.players[npad_index].connected = false; |
| 567 | connected_controllers[npad_index].is_connected = false; | ||
| 560 | 568 | ||
| 561 | auto& controller = shared_memory_entries[npad_index]; | 569 | auto& controller = shared_memory_entries[npad_index]; |
| 562 | controller.joy_styles.raw = 0; // Zero out | 570 | controller.joy_styles.raw = 0; // Zero out |
| 563 | controller.device_type.raw = 0; | 571 | controller.device_type.raw = 0; |
| 564 | controller.properties.raw = 0; | 572 | controller.properties.raw = 0; |
| 565 | 573 | ||
| 566 | styleset_changed_events[npad_index].writable->Signal(); | 574 | SignalStyleSetChangedEvent(IndexToNPad(npad_index)); |
| 567 | } | 575 | } |
| 568 | 576 | ||
| 569 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { | 577 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { |
| @@ -666,13 +674,13 @@ void Controller_NPad::ClearAllConnectedControllers() { | |||
| 666 | } | 674 | } |
| 667 | 675 | ||
| 668 | void Controller_NPad::DisconnectAllConnectedControllers() { | 676 | void Controller_NPad::DisconnectAllConnectedControllers() { |
| 669 | for (ControllerHolder& controller : connected_controllers) { | 677 | for (auto& controller : connected_controllers) { |
| 670 | controller.is_connected = false; | 678 | controller.is_connected = false; |
| 671 | } | 679 | } |
| 672 | } | 680 | } |
| 673 | 681 | ||
| 674 | void Controller_NPad::ConnectAllDisconnectedControllers() { | 682 | void Controller_NPad::ConnectAllDisconnectedControllers() { |
| 675 | for (ControllerHolder& controller : connected_controllers) { | 683 | for (auto& controller : connected_controllers) { |
| 676 | if (controller.type != NPadControllerType::None && !controller.is_connected) { | 684 | if (controller.type != NPadControllerType::None && !controller.is_connected) { |
| 677 | controller.is_connected = true; | 685 | controller.is_connected = true; |
| 678 | } | 686 | } |
| @@ -680,7 +688,7 @@ void Controller_NPad::ConnectAllDisconnectedControllers() { | |||
| 680 | } | 688 | } |
| 681 | 689 | ||
| 682 | void Controller_NPad::ClearAllControllers() { | 690 | void Controller_NPad::ClearAllControllers() { |
| 683 | for (ControllerHolder& controller : connected_controllers) { | 691 | for (auto& controller : connected_controllers) { |
| 684 | controller.type = NPadControllerType::None; | 692 | controller.type = NPadControllerType::None; |
| 685 | controller.is_connected = false; | 693 | controller.is_connected = false; |
| 686 | } | 694 | } |
| @@ -728,92 +736,4 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const | |||
| 728 | return false; | 736 | return false; |
| 729 | } | 737 | } |
| 730 | 738 | ||
| 731 | Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( | ||
| 732 | NPadControllerType priority) const { | ||
| 733 | if (IsControllerSupported(priority)) { | ||
| 734 | return priority; | ||
| 735 | } | ||
| 736 | const auto is_docked = Settings::values.use_docked_mode; | ||
| 737 | if (is_docked && priority == NPadControllerType::Handheld) { | ||
| 738 | priority = NPadControllerType::JoyDual; | ||
| 739 | if (IsControllerSupported(priority)) { | ||
| 740 | return priority; | ||
| 741 | } | ||
| 742 | } | ||
| 743 | std::vector<NPadControllerType> priority_list; | ||
| 744 | switch (priority) { | ||
| 745 | case NPadControllerType::ProController: | ||
| 746 | priority_list.push_back(NPadControllerType::JoyDual); | ||
| 747 | if (!is_docked) { | ||
| 748 | priority_list.push_back(NPadControllerType::Handheld); | ||
| 749 | } | ||
| 750 | priority_list.push_back(NPadControllerType::JoyLeft); | ||
| 751 | priority_list.push_back(NPadControllerType::JoyRight); | ||
| 752 | priority_list.push_back(NPadControllerType::Pokeball); | ||
| 753 | break; | ||
| 754 | case NPadControllerType::Handheld: | ||
| 755 | priority_list.push_back(NPadControllerType::JoyDual); | ||
| 756 | priority_list.push_back(NPadControllerType::ProController); | ||
| 757 | priority_list.push_back(NPadControllerType::JoyLeft); | ||
| 758 | priority_list.push_back(NPadControllerType::JoyRight); | ||
| 759 | priority_list.push_back(NPadControllerType::Pokeball); | ||
| 760 | break; | ||
| 761 | case NPadControllerType::JoyDual: | ||
| 762 | if (!is_docked) { | ||
| 763 | priority_list.push_back(NPadControllerType::Handheld); | ||
| 764 | } | ||
| 765 | priority_list.push_back(NPadControllerType::ProController); | ||
| 766 | priority_list.push_back(NPadControllerType::JoyLeft); | ||
| 767 | priority_list.push_back(NPadControllerType::JoyRight); | ||
| 768 | priority_list.push_back(NPadControllerType::Pokeball); | ||
| 769 | break; | ||
| 770 | case NPadControllerType::JoyLeft: | ||
| 771 | priority_list.push_back(NPadControllerType::JoyRight); | ||
| 772 | priority_list.push_back(NPadControllerType::JoyDual); | ||
| 773 | if (!is_docked) { | ||
| 774 | priority_list.push_back(NPadControllerType::Handheld); | ||
| 775 | } | ||
| 776 | priority_list.push_back(NPadControllerType::ProController); | ||
| 777 | priority_list.push_back(NPadControllerType::Pokeball); | ||
| 778 | break; | ||
| 779 | case NPadControllerType::JoyRight: | ||
| 780 | priority_list.push_back(NPadControllerType::JoyLeft); | ||
| 781 | priority_list.push_back(NPadControllerType::JoyDual); | ||
| 782 | if (!is_docked) { | ||
| 783 | priority_list.push_back(NPadControllerType::Handheld); | ||
| 784 | } | ||
| 785 | priority_list.push_back(NPadControllerType::ProController); | ||
| 786 | priority_list.push_back(NPadControllerType::Pokeball); | ||
| 787 | break; | ||
| 788 | case NPadControllerType::Pokeball: | ||
| 789 | priority_list.push_back(NPadControllerType::JoyLeft); | ||
| 790 | priority_list.push_back(NPadControllerType::JoyRight); | ||
| 791 | priority_list.push_back(NPadControllerType::JoyDual); | ||
| 792 | if (!is_docked) { | ||
| 793 | priority_list.push_back(NPadControllerType::Handheld); | ||
| 794 | } | ||
| 795 | priority_list.push_back(NPadControllerType::ProController); | ||
| 796 | break; | ||
| 797 | default: | ||
| 798 | priority_list.push_back(NPadControllerType::JoyDual); | ||
| 799 | if (!is_docked) { | ||
| 800 | priority_list.push_back(NPadControllerType::Handheld); | ||
| 801 | } | ||
| 802 | priority_list.push_back(NPadControllerType::ProController); | ||
| 803 | priority_list.push_back(NPadControllerType::JoyLeft); | ||
| 804 | priority_list.push_back(NPadControllerType::JoyRight); | ||
| 805 | priority_list.push_back(NPadControllerType::JoyDual); | ||
| 806 | break; | ||
| 807 | } | ||
| 808 | |||
| 809 | const auto iter = std::find_if(priority_list.begin(), priority_list.end(), | ||
| 810 | [this](auto type) { return IsControllerSupported(type); }); | ||
| 811 | if (iter == priority_list.end()) { | ||
| 812 | UNIMPLEMENTED_MSG("Could not find supported controller!"); | ||
| 813 | return priority; | ||
| 814 | } | ||
| 815 | |||
| 816 | return *iter; | ||
| 817 | } | ||
| 818 | |||
| 819 | } // namespace Service::HID | 739 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index ad25c6fbf..e9788da8d 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -115,15 +115,19 @@ public: | |||
| 115 | void VibrateController(const std::vector<u32>& controller_ids, | 115 | void VibrateController(const std::vector<u32>& controller_ids, |
| 116 | const std::vector<Vibration>& vibrations); | 116 | const std::vector<Vibration>& vibrations); |
| 117 | 117 | ||
| 118 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | ||
| 119 | Vibration GetLastVibration() const; | 118 | Vibration GetLastVibration() const; |
| 120 | 119 | ||
| 120 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | ||
| 121 | void SignalStyleSetChangedEvent(u32 npad_id) const; | ||
| 122 | |||
| 121 | // Adds a new controller at an index. | 123 | // Adds a new controller at an index. |
| 122 | void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); | 124 | void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); |
| 123 | // Adds a new controller at an index with connection status. | 125 | // Adds a new controller at an index with connection status. |
| 124 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); | 126 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); |
| 125 | 127 | ||
| 126 | void DisconnectNPad(u32 npad_id); | 128 | void DisconnectNPad(u32 npad_id); |
| 129 | void DisconnectNPadAtIndex(std::size_t index); | ||
| 130 | |||
| 127 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); | 131 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); |
| 128 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; | 132 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; |
| 129 | LedPattern GetLedPattern(u32 npad_id); | 133 | LedPattern GetLedPattern(u32 npad_id); |
| @@ -315,7 +319,6 @@ private: | |||
| 315 | 319 | ||
| 316 | void InitNewlyAddedController(std::size_t controller_idx); | 320 | void InitNewlyAddedController(std::size_t controller_idx); |
| 317 | bool IsControllerSupported(NPadControllerType controller) const; | 321 | bool IsControllerSupported(NPadControllerType controller) const; |
| 318 | NPadControllerType DecideBestController(NPadControllerType priority) const; | ||
| 319 | void RequestPadStateUpdate(u32 npad_id); | 322 | void RequestPadStateUpdate(u32 npad_id); |
| 320 | 323 | ||
| 321 | u32 press_state{}; | 324 | u32 press_state{}; |