From 6bcd676b610773727f446a8c81bcca1c64a95b10 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Tue, 11 Oct 2022 18:15:30 -0400
Subject: [PATCH] general: preliminary support for hbl

---
 src/core/hle/service/ns/ns.cpp       | 30 ++++++++++-
 src/core/hle/service/ns/ns.h         |  3 ++
 src/core/hle/service/ptm/ts.cpp      | 15 ++++--
 src/core/hle/service/ptm/ts.h        |  1 +
 src/core/hle/service/set/set_sys.cpp | 79 +++++++++++++++++++++++++++-
 src/core/hle/service/set/set_sys.h   |  2 +
 6 files changed, 124 insertions(+), 6 deletions(-)

diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index f7318c3cb..f59a1a63d 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -8,6 +8,7 @@
 #include "core/file_sys/patch_manager.h"
 #include "core/file_sys/vfs.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/service/glue/glue_manager.h"
 #include "core/hle/service/ns/errors.h"
 #include "core/hle/service/ns/iplatform_service_manager.h"
 #include "core/hle/service/ns/language.h"
@@ -581,7 +582,7 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
     : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetApplicationControlData"},
+        {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"},
         {1, nullptr, "GetApplicationDesiredLanguage"},
         {2, nullptr, "ConvertApplicationLanguageToLanguageCode"},
         {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
@@ -594,6 +595,33 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
 
 IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
 
+void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
+    Kernel::HLERequestContext& ctx) {
+    enum class ApplicationControlSource : u8 {
+        CacheOnly,
+        Storage,
+        StorageOnly,
+    };
+
+    struct RequestParameters {
+        ApplicationControlSource source;
+        u64 application_id;
+    };
+    static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
+
+    IPC::RequestParser rp{ctx};
+    const auto parameters{rp.PopRaw<RequestParameters>()};
+    const auto nacp_data{system.GetARPManager().GetControlProperty(parameters.application_id)};
+    const auto result = nacp_data ? ResultSuccess : ResultUnknown;
+
+    if (nacp_data) {
+        ctx.WriteBuffer(nacp_data->data(), nacp_data->size());
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(result);
+}
+
 NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
     // clang-format off
     static const FunctionInfo functions[] = {
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index 4dc191518..9c18e935c 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -78,6 +78,9 @@ class IReadOnlyApplicationControlDataInterface final
 public:
     explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
     ~IReadOnlyApplicationControlDataInterface() override;
+
+private:
+    void GetApplicationControlData(Kernel::HLERequestContext& ctx);
 };
 
 class NS final : public ServiceFramework<NS> {
diff --git a/src/core/hle/service/ptm/ts.cpp b/src/core/hle/service/ptm/ts.cpp
index 65c3f135f..b1a0a5544 100644
--- a/src/core/hle/service/ptm/ts.cpp
+++ b/src/core/hle/service/ptm/ts.cpp
@@ -15,7 +15,7 @@ TS::TS(Core::System& system_) : ServiceFramework{system_, "ts"} {
         {0, nullptr, "GetTemperatureRange"},
         {1, &TS::GetTemperature, "GetTemperature"},
         {2, nullptr, "SetMeasurementMode"},
-        {3, nullptr, "GetTemperatureMilliC"},
+        {3, &TS::GetTemperatureMilliC, "GetTemperatureMilliC"},
         {4, nullptr, "OpenSession"},
     };
     // clang-format on
@@ -29,8 +29,6 @@ void TS::GetTemperature(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto location{rp.PopEnum<Location>()};
 
-    LOG_WARNING(Service_HID, "(STUBBED) called. location={}", location);
-
     const s32 temperature = location == Location::Internal ? 35 : 20;
 
     IPC::ResponseBuilder rb{ctx, 3};
@@ -38,4 +36,15 @@ void TS::GetTemperature(Kernel::HLERequestContext& ctx) {
     rb.Push(temperature);
 }
 
+void TS::GetTemperatureMilliC(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto location{rp.PopEnum<Location>()};
+
+    const s32 temperature = location == Location::Internal ? 35000 : 20000;
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(temperature);
+}
+
 } // namespace Service::PTM
diff --git a/src/core/hle/service/ptm/ts.h b/src/core/hle/service/ptm/ts.h
index 39a734ef7..39d51847e 100644
--- a/src/core/hle/service/ptm/ts.h
+++ b/src/core/hle/service/ptm/ts.h
@@ -20,6 +20,7 @@ private:
     };
 
     void GetTemperature(Kernel::HLERequestContext& ctx);
+    void GetTemperatureMilliC(Kernel::HLERequestContext& ctx);
 };
 
 } // namespace Service::PTM
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index 2a0b812c1..d7cea6aac 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -101,6 +101,81 @@ void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) {
     rb.Push(ResultSuccess);
 }
 
+// FIXME: implement support for the real system_settings.ini
+
+template <typename T>
+static std::vector<u8> ToBytes(const T& value) {
+    static_assert(std::is_trivially_copyable_v<T>);
+
+    const auto* begin = reinterpret_cast<const u8*>(&value);
+    const auto* end = begin + sizeof(T);
+
+    return std::vector<u8>(begin, end);
+}
+
+using Settings =
+    std::map<std::string, std::map<std::string, std::vector<u8>, std::less<>>, std::less<>>;
+
+static Settings GetSettings() {
+    Settings ret;
+
+    ret["hbloader"]["applet_heap_size"] = ToBytes(u64{0x0});
+    ret["hbloader"]["applet_heap_reservation_size"] = ToBytes(u64{0x8600000});
+
+    return ret;
+}
+
+void SET_SYS::GetSettingsItemValueSize(Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_SET, "called");
+
+    // The category of the setting. This corresponds to the top-level keys of
+    // system_settings.ini.
+    const auto setting_category_buf{ctx.ReadBuffer(0)};
+    const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()};
+
+    // The name of the setting. This corresponds to the second-level keys of
+    // system_settings.ini.
+    const auto setting_name_buf{ctx.ReadBuffer(1)};
+    const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()};
+
+    auto settings{GetSettings()};
+    u64 response_size{0};
+
+    if (settings.contains(setting_category) && settings[setting_category].contains(setting_name)) {
+        response_size = settings[setting_category][setting_name].size();
+    }
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(response_size == 0 ? ResultUnknown : ResultSuccess);
+    rb.Push(response_size);
+}
+
+void SET_SYS::GetSettingsItemValue(Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_SET, "called");
+
+    // The category of the setting. This corresponds to the top-level keys of
+    // system_settings.ini.
+    const auto setting_category_buf{ctx.ReadBuffer(0)};
+    const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()};
+
+    // The name of the setting. This corresponds to the second-level keys of
+    // system_settings.ini.
+    const auto setting_name_buf{ctx.ReadBuffer(1)};
+    const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()};
+
+    auto settings{GetSettings()};
+    Result response{ResultUnknown};
+
+    if (settings.contains(setting_category) && settings[setting_category].contains(setting_name)) {
+        auto setting_value = settings[setting_category][setting_name];
+        ctx.WriteBuffer(setting_value.data(), setting_value.size());
+        response = ResultSuccess;
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(response);
+}
+
 SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
     // clang-format off
     static const FunctionInfo functions[] = {
@@ -138,8 +213,8 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
         {32, nullptr, "SetAccountNotificationSettings"},
         {35, nullptr, "GetVibrationMasterVolume"},
         {36, nullptr, "SetVibrationMasterVolume"},
-        {37, nullptr, "GetSettingsItemValueSize"},
-        {38, nullptr, "GetSettingsItemValue"},
+        {37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"},
+        {38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"},
         {39, nullptr, "GetTvSettings"},
         {40, nullptr, "SetTvSettings"},
         {41, nullptr, "GetEdid"},
diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h
index ac97772b7..258ef8c57 100644
--- a/src/core/hle/service/set/set_sys.h
+++ b/src/core/hle/service/set/set_sys.h
@@ -23,6 +23,8 @@ private:
         BasicBlack = 1,
     };
 
+    void GetSettingsItemValueSize(Kernel::HLERequestContext& ctx);
+    void GetSettingsItemValue(Kernel::HLERequestContext& ctx);
     void GetFirmwareVersion(Kernel::HLERequestContext& ctx);
     void GetFirmwareVersion2(Kernel::HLERequestContext& ctx);
     void GetColorSetId(Kernel::HLERequestContext& ctx);