From 5882cc0502f48136088b955db7afd0a330254375 Mon Sep 17 00:00:00 2001
From: Chloe Marcec <dmarcecguzman@gmail.com>
Date: Mon, 25 Jan 2021 00:34:01 +1100
Subject: [PATCH] hle: Implement remaining services for Stereo Vision

Used by Zelda Breath of the Wild, Super Mario Odyssey and Nintendo Labo
---
 src/core/hle/service/am/am.cpp       |  9 ++++-
 src/core/hle/service/am/am.h         |  1 +
 src/core/hle/service/pctl/module.cpp | 57 +++++++++++++++++++++++++---
 3 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 1743bcb2b3..41bd1497c6 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -635,7 +635,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
         {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
         {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
         {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
-        {53, nullptr, "BeginVrModeEx"},
+        {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
         {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
         {55, nullptr, "IsInControllerFirmwareUpdateSection"},
         {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
@@ -732,6 +732,13 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx
     rb.Push(RESULT_SUCCESS);
 }
 
+void ICommonStateGetter::BeginVrModeEx(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(RESULT_SUCCESS);
+}
+
 void ICommonStateGetter::EndVrModeEx(Kernel::HLERequestContext& ctx) {
     LOG_WARNING(Service_AM, "(STUBBED) called");
 
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index f51aca1af3..50737432c3 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -189,6 +189,7 @@ private:
     void IsVrModeEnabled(Kernel::HLERequestContext& ctx);
     void SetVrModeEnabled(Kernel::HLERequestContext& ctx);
     void SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx);
+    void BeginVrModeEx(Kernel::HLERequestContext& ctx);
     void EndVrModeEx(Kernel::HLERequestContext& ctx);
     void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
     void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp
index 6ab1e4124e..f9089bf2f7 100644
--- a/src/core/hle/service/pctl/module.cpp
+++ b/src/core/hle/service/pctl/module.cpp
@@ -50,11 +50,11 @@ public:
             {1046, nullptr, "DisableFeaturesForReset"},
             {1047, nullptr, "NotifyApplicationDownloadStarted"},
             {1048, nullptr, "NotifyNetworkProfileCreated"},
-            {1061, nullptr, "ConfirmStereoVisionRestrictionConfigurable"},
-            {1062, nullptr, "GetStereoVisionRestriction"},
-            {1063, nullptr, "SetStereoVisionRestriction"},
-            {1064, nullptr, "ResetConfirmedStereoVisionPermission"},
-            {1065, nullptr, "IsStereoVisionPermitted"},
+            {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"},
+            {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"},
+            {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"},
+            {1064, &IParentalControlService::ResetConfirmedStereoVisionPermission, "ResetConfirmedStereoVisionPermission"},
+            {1065, &IParentalControlService::IsStereoVisionPermitted, "IsStereoVisionPermitted"},
             {1201, nullptr, "UnlockRestrictionTemporarily"},
             {1202, nullptr, "UnlockSystemSettingsRestriction"},
             {1203, nullptr, "SetPinCode"},
@@ -114,6 +114,7 @@ public:
             {2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
             {2016, nullptr, "RequestUpdateExemptionListAsync"},
         };
+        // clang-format on
         RegisterHandlers(functions);
     }
 
@@ -131,6 +132,49 @@ private:
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
     }
+
+    void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_PCTL, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+    }
+
+    void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_PCTL, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 3};
+        rb.Push(RESULT_SUCCESS);
+        rb.Push(true);
+    }
+
+    void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        const auto can_use = rp.Pop<bool>();
+        LOG_WARNING(Service_PCTL, "(STUBBED) called, can_use={}", can_use);
+
+        can_use_stereo_vision = can_use;
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+    }
+
+    void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_PCTL, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 3};
+        rb.Push(RESULT_SUCCESS);
+        rb.Push(can_use_stereo_vision);
+    }
+
+    void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service_PCTL, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+    }
+
+    bool can_use_stereo_vision = true;
 };
 
 void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
@@ -149,7 +193,8 @@ void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext
     rb.PushIpcInterface<IParentalControlService>(system);
 }
 
-Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, const char* name)
+Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_,
+                             const char* name)
     : ServiceFramework{system_, name}, module{std::move(module_)} {}
 
 Module::Interface::~Interface() = default;