From 88192af8ace632ed37fd1ec0406e84ed083e5301 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Wed, 4 Nov 2020 10:56:36 -0500 Subject: [PATCH 1/4] applets/controller: Add ControllerUpdateFirmwareArg struct --- src/core/hle/service/am/applets/controller.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index f7bb3fba9..86269190b 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -84,6 +84,13 @@ struct ControllerSupportArgNew { static_assert(sizeof(ControllerSupportArgNew) == 0x430, "ControllerSupportArgNew has incorrect size."); +struct ControllerUpdateFirmwareArg { + bool enable_force_update{}; + INSERT_PADDING_BYTES(3); +}; +static_assert(sizeof(ControllerUpdateFirmwareArg) == 0x4, + "ControllerUpdateFirmwareArg has incorrect size."); + struct ControllerSupportResultInfo { s8 player_count{}; INSERT_PADDING_BYTES(3); From af1183a9938d885a643efaf28397235a4d1bd2ef Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Wed, 4 Nov 2020 11:21:17 -0500 Subject: [PATCH 2/4] applets/controller: Introduce additional checks for mode and caller Some games like Cave Story+ set invalid values in the ControllerPrivateArg's mode and caller fields. Use other fields to determine the appropriate mode and caller should either or both fields be invalid. --- .../hle/service/am/applets/controller.cpp | 30 +++++++++++++++++++ src/core/hle/service/am/applets/controller.h | 14 +++++---- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 2151da783..6b8eeabf4 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -75,6 +75,36 @@ void Controller::Initialize() { "Unknown ControllerSupportArgPrivate revision={} with size={}", library_applet_version, controller_private_arg.arg_private_size); + // Some games such as Cave Story+ set invalid values for the ControllerSupportMode. + // Defer to arg_size to set the ControllerSupportMode. + if (controller_private_arg.mode >= ControllerSupportMode::MaxControllerSupportMode) { + switch (controller_private_arg.arg_size) { + case sizeof(ControllerSupportArgOld): + case sizeof(ControllerSupportArgNew): + controller_private_arg.mode = ControllerSupportMode::ShowControllerSupport; + break; + case sizeof(ControllerUpdateFirmwareArg): + controller_private_arg.mode = ControllerSupportMode::ShowControllerFirmwareUpdate; + break; + default: + UNIMPLEMENTED_MSG("Unknown ControllerPrivateArg mode={} with arg_size={}", + controller_private_arg.mode, controller_private_arg.arg_size); + controller_private_arg.mode = ControllerSupportMode::ShowControllerSupport; + break; + } + } + + // Some games such as Cave Story+ set invalid values for the ControllerSupportCaller. + // This is always 0 (Application) except with ShowControllerFirmwareUpdateForSystem. + if (controller_private_arg.caller >= ControllerSupportCaller::MaxControllerSupportCaller) { + if (controller_private_arg.flag_1 && + controller_private_arg.mode == ControllerSupportMode::ShowControllerFirmwareUpdate) { + controller_private_arg.caller = ControllerSupportCaller::System; + } else { + controller_private_arg.caller = ControllerSupportCaller::Application; + } + } + switch (controller_private_arg.mode) { case ControllerSupportMode::ShowControllerSupport: { const auto user_arg_storage = broker.PopNormalDataToApplet(); diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index 86269190b..05788966e 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -29,14 +29,18 @@ enum class LibraryAppletVersion : u32_le { }; enum class ControllerSupportMode : u8 { - ShowControllerSupport = 0, - ShowControllerStrapGuide = 1, - ShowControllerFirmwareUpdate = 2, + ShowControllerSupport, + ShowControllerStrapGuide, + ShowControllerFirmwareUpdate, + + MaxControllerSupportMode, }; enum class ControllerSupportCaller : u8 { - Application = 0, - System = 1, + Application, + System, + + MaxControllerSupportCaller, }; struct ControllerSupportArgPrivate { From 9efbf5309f687b64ff246f1b19ff224ce52814a0 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 5 Nov 2020 22:43:39 -0500 Subject: [PATCH 3/4] applets/controller: Pop normal data for StrapGuide and FirmwareUpdate --- .../hle/service/am/applets/controller.cpp | 24 ++++++++++++++----- src/core/hle/service/am/applets/controller.h | 1 + 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 6b8eeabf4..4da10dd38 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -70,7 +70,7 @@ void Controller::Initialize() { const auto& private_arg = private_arg_storage->GetData(); ASSERT(private_arg.size() == sizeof(ControllerSupportArgPrivate)); - std::memcpy(&controller_private_arg, private_arg.data(), sizeof(ControllerSupportArgPrivate)); + std::memcpy(&controller_private_arg, private_arg.data(), private_arg.size()); ASSERT_MSG(controller_private_arg.arg_private_size == sizeof(ControllerSupportArgPrivate), "Unknown ControllerSupportArgPrivate revision={} with size={}", library_applet_version, controller_private_arg.arg_private_size); @@ -106,7 +106,8 @@ void Controller::Initialize() { } switch (controller_private_arg.mode) { - case ControllerSupportMode::ShowControllerSupport: { + case ControllerSupportMode::ShowControllerSupport: + case ControllerSupportMode::ShowControllerStrapGuide: { const auto user_arg_storage = broker.PopNormalDataToApplet(); ASSERT(user_arg_storage != nullptr); @@ -116,11 +117,11 @@ void Controller::Initialize() { case LibraryAppletVersion::Version4: case LibraryAppletVersion::Version5: ASSERT(user_arg.size() == sizeof(ControllerSupportArgOld)); - std::memcpy(&controller_user_arg_old, user_arg.data(), sizeof(ControllerSupportArgOld)); + std::memcpy(&controller_user_arg_old, user_arg.data(), user_arg.size()); break; case LibraryAppletVersion::Version7: ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew)); - std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew)); + std::memcpy(&controller_user_arg_new, user_arg.data(), user_arg.size()); break; default: UNIMPLEMENTED_MSG("Unknown ControllerSupportArg revision={} with size={}", @@ -131,8 +132,16 @@ void Controller::Initialize() { } break; } - case ControllerSupportMode::ShowControllerStrapGuide: - case ControllerSupportMode::ShowControllerFirmwareUpdate: + case ControllerSupportMode::ShowControllerFirmwareUpdate: { + const auto update_arg_storage = broker.PopNormalDataToApplet(); + ASSERT(update_arg_storage != nullptr); + + const auto& update_arg = update_arg_storage->GetData(); + ASSERT(update_arg.size() == sizeof(ControllerUpdateFirmwareArg)); + + std::memcpy(&controller_update_arg, update_arg.data(), update_arg.size()); + break; + } default: { UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode); break; @@ -200,6 +209,9 @@ void Controller::Execute() { } case ControllerSupportMode::ShowControllerStrapGuide: case ControllerSupportMode::ShowControllerFirmwareUpdate: + UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented", + controller_private_arg.mode); + [[fallthrough]]; default: { ConfigurationComplete(); break; diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index 05788966e..dfc52da58 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -125,6 +125,7 @@ private: ControllerSupportArgPrivate controller_private_arg; ControllerSupportArgOld controller_user_arg_old; ControllerSupportArgNew controller_user_arg_new; + ControllerUpdateFirmwareArg controller_update_arg; bool complete{false}; ResultCode status{RESULT_SUCCESS}; bool is_single_mode{false}; From a6ecdf42bc4c1de948f5343e66418a9a32dc0ae3 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sun, 8 Nov 2020 09:34:53 -0500 Subject: [PATCH 4/4] applets: Rename LibraryAppletVersion to ControllerAppletVersion --- .../hle/service/am/applets/controller.cpp | 26 +++++++++---------- src/core/hle/service/am/applets/controller.h | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 4da10dd38..a0152b4ea 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -62,7 +62,7 @@ void Controller::Initialize() { common_args.play_startup_sound, common_args.size, common_args.system_tick, common_args.theme_color); - library_applet_version = LibraryAppletVersion{common_args.library_version}; + controller_applet_version = ControllerAppletVersion{common_args.library_version}; const auto private_arg_storage = broker.PopNormalDataToApplet(); ASSERT(private_arg_storage != nullptr); @@ -73,7 +73,7 @@ void Controller::Initialize() { std::memcpy(&controller_private_arg, private_arg.data(), private_arg.size()); ASSERT_MSG(controller_private_arg.arg_private_size == sizeof(ControllerSupportArgPrivate), "Unknown ControllerSupportArgPrivate revision={} with size={}", - library_applet_version, controller_private_arg.arg_private_size); + controller_applet_version, controller_private_arg.arg_private_size); // Some games such as Cave Story+ set invalid values for the ControllerSupportMode. // Defer to arg_size to set the ControllerSupportMode. @@ -112,20 +112,20 @@ void Controller::Initialize() { ASSERT(user_arg_storage != nullptr); const auto& user_arg = user_arg_storage->GetData(); - switch (library_applet_version) { - case LibraryAppletVersion::Version3: - case LibraryAppletVersion::Version4: - case LibraryAppletVersion::Version5: + switch (controller_applet_version) { + case ControllerAppletVersion::Version3: + case ControllerAppletVersion::Version4: + case ControllerAppletVersion::Version5: ASSERT(user_arg.size() == sizeof(ControllerSupportArgOld)); std::memcpy(&controller_user_arg_old, user_arg.data(), user_arg.size()); break; - case LibraryAppletVersion::Version7: + case ControllerAppletVersion::Version7: ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew)); std::memcpy(&controller_user_arg_new, user_arg.data(), user_arg.size()); break; default: UNIMPLEMENTED_MSG("Unknown ControllerSupportArg revision={} with size={}", - library_applet_version, controller_private_arg.arg_size); + controller_applet_version, controller_private_arg.arg_size); ASSERT(user_arg.size() >= sizeof(ControllerSupportArgNew)); std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew)); break; @@ -165,10 +165,10 @@ void Controller::Execute() { switch (controller_private_arg.mode) { case ControllerSupportMode::ShowControllerSupport: { const auto parameters = [this] { - switch (library_applet_version) { - case LibraryAppletVersion::Version3: - case LibraryAppletVersion::Version4: - case LibraryAppletVersion::Version5: + switch (controller_applet_version) { + case ControllerAppletVersion::Version3: + case ControllerAppletVersion::Version4: + case ControllerAppletVersion::Version5: return ConvertToFrontendParameters( controller_private_arg, controller_user_arg_old.header, controller_user_arg_old.enable_explain_text, @@ -177,7 +177,7 @@ void Controller::Execute() { controller_user_arg_old.identification_colors.end()), std::vector(controller_user_arg_old.explain_text.begin(), controller_user_arg_old.explain_text.end())); - case LibraryAppletVersion::Version7: + case ControllerAppletVersion::Version7: default: return ConvertToFrontendParameters( controller_private_arg, controller_user_arg_new.header, diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index dfc52da58..a7a1f2b65 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -21,7 +21,7 @@ namespace Service::AM::Applets { using IdentificationColor = std::array; using ExplainText = std::array; -enum class LibraryAppletVersion : u32_le { +enum class ControllerAppletVersion : u32_le { Version3 = 0x3, // 1.0.0 - 2.3.0 Version4 = 0x4, // 3.0.0 - 5.1.0 Version5 = 0x5, // 6.0.0 - 7.0.1 @@ -121,7 +121,7 @@ public: private: const Core::Frontend::ControllerApplet& frontend; - LibraryAppletVersion library_applet_version; + ControllerAppletVersion controller_applet_version; ControllerSupportArgPrivate controller_private_arg; ControllerSupportArgOld controller_user_arg_old; ControllerSupportArgNew controller_user_arg_new;