From c457f34eb22eb43aa2beca0414e59f2a284715dd Mon Sep 17 00:00:00 2001
From: goaaats <16760685+goaaats@users.noreply.github.com>
Date: Fri, 19 Jan 2018 21:44:58 +0100
Subject: [PATCH] acc, set, applet_oe: stub various functions, add set service
 (#105)

* Stubs for various acc:u0 funcs needed

* Stub for GetDesiredLanguage in IApplicationFunctions

* Add set service + stubs needed for games

* Fix formatting

* Implement IProfile, IManagerForApplication, return bool in CheckAvailability, style fixes

* Remove IProfile::Get(needs more research), fix IPC response sizes
---
 src/core/CMakeLists.txt               |  2 +
 src/core/hle/service/acc/acc_u0.cpp   | 61 +++++++++++++++++++++++++++
 src/core/hle/service/acc/acc_u0.h     | 15 +++++++
 src/core/hle/service/am/applet_oe.cpp |  8 ++++
 src/core/hle/service/am/applet_oe.h   |  6 +++
 src/core/hle/service/service.cpp      |  2 +
 src/core/hle/service/set/set.cpp      | 42 ++++++++++++++++++
 src/core/hle/service/set/set.h        | 25 +++++++++++
 8 files changed, 161 insertions(+)
 create mode 100644 src/core/hle/service/set/set.cpp
 create mode 100644 src/core/hle/service/set/set.h

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 57f578baee..8836ddf637 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -124,6 +124,8 @@ add_library(core STATIC
     hle/service/pctl/pctl_a.h
     hle/service/service.cpp
     hle/service/service.h
+    hle/service/set/set.cpp
+    hle/service/set/set.h
     hle/service/sm/controller.cpp
     hle/service/sm/controller.h
     hle/service/sm/sm.cpp
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 147f4e62ed..7f0192fd3f 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -9,15 +9,76 @@
 namespace Service {
 namespace Account {
 
+class IProfile final : public ServiceFramework<IProfile> {
+public:
+    IProfile() : ServiceFramework("IProfile") {
+        static const FunctionInfo functions[] = {
+            {1, &IProfile::GetBase, "GetBase"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    void GetBase(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service, "(STUBBED) called");
+        ProfileBase profile_base{};
+        IPC::RequestBuilder rb{ctx, 16};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushRaw(profile_base);
+    }
+};
+
+class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
+public:
+    IManagerForApplication() : ServiceFramework("IProfile") {
+        static const FunctionInfo functions[] = {
+            {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
+        };
+        RegisterHandlers(functions);
+    }
+
+private:
+    void CheckAvailability(Kernel::HLERequestContext& ctx) {
+        LOG_WARNING(Service, "(STUBBED) called");
+        IPC::RequestBuilder rb{ctx, 3};
+        rb.Push(RESULT_SUCCESS);
+        rb.Push(true); // TODO: Check when this is supposed to return true and when not
+    }
+};
+
+void ACC_U0::GetUserExistence(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service, "(STUBBED) called");
+    IPC::RequestBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push(true); // TODO: Check when this is supposed to return true and when not
+}
+
+void ACC_U0::GetProfile(Kernel::HLERequestContext& ctx) {
+    IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushIpcInterface<IProfile>();
+    LOG_DEBUG(Service, "called");
+}
+
 void ACC_U0::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
     LOG_WARNING(Service, "(STUBBED) called");
     IPC::RequestBuilder rb{ctx, 2};
     rb.Push(RESULT_SUCCESS);
 }
 
+void ACC_U0::GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx) {
+    IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushIpcInterface<IManagerForApplication>();
+    LOG_DEBUG(Service, "called");
+}
+
 ACC_U0::ACC_U0() : ServiceFramework("acc:u0") {
     static const FunctionInfo functions[] = {
+        {1, &ACC_U0::GetUserExistence, "GetUserExistence"},
+        {5, &ACC_U0::GetProfile, "GetProfile"},
         {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
+        {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
     };
     RegisterHandlers(functions);
 }
diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h
index ac243d5b8e..51676e8594 100644
--- a/src/core/hle/service/acc/acc_u0.h
+++ b/src/core/hle/service/acc/acc_u0.h
@@ -9,13 +9,28 @@
 namespace Service {
 namespace Account {
 
+// TODO: RE this structure
+struct UserData {
+    INSERT_PADDING_BYTES(0x80);
+};
+static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
+
+// TODO: RE this structure
+struct ProfileBase {
+    INSERT_PADDING_BYTES(0x38);
+};
+static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase structure has incorrect size");
+
 class ACC_U0 final : public ServiceFramework<ACC_U0> {
 public:
     ACC_U0();
     ~ACC_U0() = default;
 
 private:
+    void GetUserExistence(Kernel::HLERequestContext& ctx);
+    void GetProfile(Kernel::HLERequestContext& ctx);
     void InitializeApplicationInfo(Kernel::HLERequestContext& ctx);
+    void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx);
 };
 
 } // namespace Account
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index 038080e8cf..79ad4f53b5 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -270,6 +270,7 @@ public:
     IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
         static const FunctionInfo functions[] = {
             {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
+            {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
             {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
             {66, &IApplicationFunctions::InitializeGamePlayRecording,
              "InitializeGamePlayRecording"},
@@ -313,6 +314,13 @@ private:
         LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result);
     }
 
+    void GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
+        IPC::RequestBuilder rb{ctx, 4};
+        rb.Push(RESULT_SUCCESS);
+        rb.Push<u64>(SystemLanguage::English);
+        LOG_WARNING(Service, "(STUBBED) called");
+    }
+
     void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
         IPC::RequestBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h
index beb75bf2ad..6ee5b0e9f8 100644
--- a/src/core/hle/service/am/applet_oe.h
+++ b/src/core/hle/service/am/applet_oe.h
@@ -10,6 +10,12 @@
 namespace Service {
 namespace AM {
 
+// TODO: Add more languages
+enum SystemLanguage {
+    Japanese = 0,
+    English = 1,
+};
+
 class AppletOE final : public ServiceFramework<AppletOE> {
 public:
     AppletOE();
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 9a49d9e9c0..19213a2f40 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -24,6 +24,7 @@
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/pctl/pctl.h"
 #include "core/hle/service/service.h"
+#include "core/hle/service/set/set.h"
 #include "core/hle/service/sm/controller.h"
 #include "core/hle/service/sm/sm.h"
 #include "core/hle/service/sockets/sockets.h"
@@ -178,6 +179,7 @@ void Init() {
     Sockets::InstallInterfaces(*SM::g_service_manager);
     Time::InstallInterfaces(*SM::g_service_manager);
     VI::InstallInterfaces(*SM::g_service_manager);
+    Set::InstallInterfaces(*SM::g_service_manager);
 
     LOG_DEBUG(Service, "initialized OK");
 }
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
new file mode 100644
index 0000000000..3715acd742
--- /dev/null
+++ b/src/core/hle/service/set/set.cpp
@@ -0,0 +1,42 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <chrono>
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/client_port.h"
+#include "core/hle/kernel/client_session.h"
+#include "core/hle/service/set/set.h"
+
+namespace Service {
+namespace Set {
+
+void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
+    constexpr std::array<u8, 13> lang_codes{};
+
+    const auto& output_buffer = ctx.BufferDescriptorC()[0];
+
+    Memory::WriteBlock(output_buffer.Address(), lang_codes.data(), lang_codes.size());
+
+    IPC::RequestBuilder rb{ctx, 4};
+
+    rb.Push(RESULT_SUCCESS);
+    rb.Push(static_cast<u64>(lang_codes.size()));
+
+    LOG_WARNING(Service, "(STUBBED) called");
+}
+
+SET::SET(const char* name) : ServiceFramework(name) {
+    static const FunctionInfo functions[] = {
+        {1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
+    };
+    RegisterHandlers(functions);
+}
+
+void InstallInterfaces(SM::ServiceManager& service_manager) {
+    std::make_shared<SET>("set")->InstallAsService(service_manager);
+}
+
+} // namespace Set
+} // namespace Service
diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h
new file mode 100644
index 0000000000..61e9579463
--- /dev/null
+++ b/src/core/hle/service/set/set.h
@@ -0,0 +1,25 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service {
+namespace Set {
+
+class SET final : public ServiceFramework<SET> {
+public:
+    explicit SET(const char* name);
+    ~SET() = default;
+
+private:
+    void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
+};
+
+/// Registers all Set services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& service_manager);
+
+} // namespace Set
+} // namespace Service