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] 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 2151da7834..6b8eeabf4c 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 86269190b5..05788966e2 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 {