From 9b7e57f3f41ef0a5052a7da78b3984f95f55b7c0 Mon Sep 17 00:00:00 2001
From: Morph <39850852+Morph1984@users.noreply.github.com>
Date: Fri, 16 Jul 2021 13:35:59 -0400
Subject: [PATCH] applet_controller: Add preliminary support for version 8

Version 8 adds support for key remapping introduced in FW 11.0, we will not be implementing this for now.
---
 .../service/am/applets/applet_controller.cpp  | 21 ++++++++++++++++++-
 .../service/am/applets/applet_controller.h    | 15 +++++++++++--
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 12682effe6..2721679c10 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -87,6 +87,10 @@ void Controller::Initialize() {
         case sizeof(ControllerUpdateFirmwareArg):
             controller_private_arg.mode = ControllerSupportMode::ShowControllerFirmwareUpdate;
             break;
+        case sizeof(ControllerKeyRemappingArg):
+            controller_private_arg.mode =
+                ControllerSupportMode::ShowControllerKeyRemappingForSystem;
+            break;
         default:
             UNIMPLEMENTED_MSG("Unknown ControllerPrivateArg mode={} with arg_size={}",
                               controller_private_arg.mode, controller_private_arg.arg_size);
@@ -99,7 +103,9 @@ void Controller::Initialize() {
     // 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.mode == ControllerSupportMode::ShowControllerFirmwareUpdate ||
+             controller_private_arg.mode ==
+                 ControllerSupportMode::ShowControllerKeyRemappingForSystem)) {
             controller_private_arg.caller = ControllerSupportCaller::System;
         } else {
             controller_private_arg.caller = ControllerSupportCaller::Application;
@@ -121,6 +127,7 @@ void Controller::Initialize() {
             std::memcpy(&controller_user_arg_old, user_arg.data(), user_arg.size());
             break;
         case ControllerAppletVersion::Version7:
+        case ControllerAppletVersion::Version8:
             ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew));
             std::memcpy(&controller_user_arg_new, user_arg.data(), user_arg.size());
             break;
@@ -143,6 +150,16 @@ void Controller::Initialize() {
         std::memcpy(&controller_update_arg, update_arg.data(), update_arg.size());
         break;
     }
+    case ControllerSupportMode::ShowControllerKeyRemappingForSystem: {
+        const auto remapping_arg_storage = broker.PopNormalDataToApplet();
+        ASSERT(remapping_arg_storage != nullptr);
+
+        const auto& remapping_arg = remapping_arg_storage->GetData();
+        ASSERT(remapping_arg.size() == sizeof(ControllerKeyRemappingArg));
+
+        std::memcpy(&controller_key_remapping_arg, remapping_arg.data(), remapping_arg.size());
+        break;
+    }
     default: {
         UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode);
         break;
@@ -179,6 +196,7 @@ void Controller::Execute() {
                     std::vector<ExplainText>(controller_user_arg_old.explain_text.begin(),
                                              controller_user_arg_old.explain_text.end()));
             case ControllerAppletVersion::Version7:
+            case ControllerAppletVersion::Version8:
             default:
                 return ConvertToFrontendParameters(
                     controller_private_arg, controller_user_arg_new.header,
@@ -210,6 +228,7 @@ void Controller::Execute() {
     }
     case ControllerSupportMode::ShowControllerStrapGuide:
     case ControllerSupportMode::ShowControllerFirmwareUpdate:
+    case ControllerSupportMode::ShowControllerKeyRemappingForSystem:
         UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented",
                           controller_private_arg.mode);
         ConfigurationComplete();
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h
index 20617e91fa..0a34c4fc0c 100644
--- a/src/core/hle/service/am/applets/applet_controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
@@ -25,13 +25,15 @@ 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
-    Version7 = 0x7, // 8.0.0+
+    Version7 = 0x7, // 8.0.0 - 10.2.0
+    Version8 = 0x8, // 11.0.0+
 };
 
 enum class ControllerSupportMode : u8 {
     ShowControllerSupport,
     ShowControllerStrapGuide,
     ShowControllerFirmwareUpdate,
+    ShowControllerKeyRemappingForSystem,
 
     MaxControllerSupportMode,
 };
@@ -78,7 +80,7 @@ struct ControllerSupportArgOld {
 static_assert(sizeof(ControllerSupportArgOld) == 0x21C,
               "ControllerSupportArgOld has incorrect size.");
 
-// LibraryAppletVersion 0x7
+// LibraryAppletVersion 0x7, 0x8
 struct ControllerSupportArgNew {
     ControllerSupportArgHeader header{};
     std::array<IdentificationColor, 8> identification_colors{};
@@ -95,6 +97,14 @@ struct ControllerUpdateFirmwareArg {
 static_assert(sizeof(ControllerUpdateFirmwareArg) == 0x4,
               "ControllerUpdateFirmwareArg has incorrect size.");
 
+struct ControllerKeyRemappingArg {
+    u64 unknown{};
+    u32 unknown_2{};
+    INSERT_PADDING_WORDS(1);
+};
+static_assert(sizeof(ControllerKeyRemappingArg) == 0x10,
+              "ControllerKeyRemappingArg has incorrect size.");
+
 struct ControllerSupportResultInfo {
     s8 player_count{};
     INSERT_PADDING_BYTES(3);
@@ -128,6 +138,7 @@ private:
     ControllerSupportArgOld controller_user_arg_old;
     ControllerSupportArgNew controller_user_arg_new;
     ControllerUpdateFirmwareArg controller_update_arg;
+    ControllerKeyRemappingArg controller_key_remapping_arg;
     bool complete{false};
     ResultCode status{ResultSuccess};
     bool is_single_mode{false};