Просмотр исходного кода

ns: rewrite IReadOnlyApplicationControlDataInterface

Liam 2 лет назад
Родитель
Сommit
2eded86b4b

+ 2 - 0
src/core/CMakeLists.txt

@@ -765,6 +765,8 @@ add_library(core STATIC
     hle/service/ns/pdm_qry.h
     hle/service/ns/platform_service_manager.cpp
     hle/service/ns/platform_service_manager.h
+    hle/service/ns/read_only_application_control_data_interface.cpp
+    hle/service/ns/read_only_application_control_data_interface.h
     hle/service/ns/read_only_application_record_interface.cpp
     hle/service/ns/read_only_application_record_interface.h
     hle/service/nvdrv/core/container.cpp

+ 1 - 45
src/core/hle/service/ns/ns.cpp

@@ -24,6 +24,7 @@
 #include "core/hle/service/ns/ns_results.h"
 #include "core/hle/service/ns/pdm_qry.h"
 #include "core/hle/service/ns/platform_service_manager.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
 #include "core/hle/service/ns/read_only_application_record_interface.h"
 #include "core/hle/service/server_manager.h"
 #include "core/hle/service/set/settings_server.h"
@@ -469,51 +470,6 @@ Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
     return ResultSuccess;
 }
 
-IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
-    Core::System& system_)
-    : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"},
-        {1, nullptr, "GetApplicationDesiredLanguage"},
-        {2, nullptr, "ConvertApplicationLanguageToLanguageCode"},
-        {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
-        {4, nullptr, "SelectApplicationDesiredLanguage"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
-
-void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(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};
-    std::vector<u8> nacp_data{};
-    const auto parameters{rp.PopRaw<RequestParameters>()};
-    const auto result =
-        system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id);
-
-    if (result == ResultSuccess) {
-        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[] = {

+ 0 - 10
src/core/hle/service/ns/ns.h

@@ -32,16 +32,6 @@ private:
     void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx);
 };
 
-class IReadOnlyApplicationControlDataInterface final
-    : public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
-public:
-    explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
-    ~IReadOnlyApplicationControlDataInterface() override;
-
-private:
-    void GetApplicationControlData(HLERequestContext& ctx);
-};
-
 class NS final : public ServiceFramework<NS> {
 public:
     explicit NS(const char* name, Core::System& system_);

+ 6 - 0
src/core/hle/service/ns/ns_types.h

@@ -16,6 +16,12 @@ enum class ApplicationRecordType : u8 {
     GameCard = 0x10,
 };
 
+enum class ApplicationControlSource : u8 {
+    CacheOnly = 0,
+    Storage = 1,
+    StorageOnly = 2,
+};
+
 struct ApplicationRecord {
     u64 application_id;
     ApplicationRecordType type;

+ 122 - 0
src/core/hle/service/ns/read_only_application_control_data_interface.cpp

@@ -0,0 +1,122 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
+#include "core/file_sys/vfs/vfs.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/ns_results.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
+#include "core/hle/service/set/settings_server.h"
+
+namespace Service::NS {
+
+IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
+    Core::System& system_)
+    : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"},
+        {1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
+        {2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
+        {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
+        {4, nullptr, "SelectApplicationDesiredLanguage"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
+
+Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
+    OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
+    ApplicationControlSource application_control_source, u64 application_id) {
+    LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
+             application_control_source, application_id);
+
+    const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
+                                   system.GetContentProvider()};
+    const auto control = pm.GetControlMetadata();
+    const auto size = out_buffer.size();
+
+    const auto icon_size = control.second ? control.second->GetSize() : 0;
+    const auto total_size = 0x4000 + icon_size;
+
+    if (size < total_size) {
+        LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
+                  size);
+        R_THROW(ResultUnknown);
+    }
+
+    if (control.first != nullptr) {
+        const auto bytes = control.first->GetRawBytes();
+        std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
+    } else {
+        LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
+                    application_id);
+        std::memset(out_buffer.data(), 0, 0x4000);
+    }
+
+    if (control.second != nullptr) {
+        control.second->Read(out_buffer.data() + 0x4000, icon_size);
+    } else {
+        LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id);
+    }
+
+    *out_actual_size = static_cast<u32>(total_size);
+    R_SUCCEED();
+}
+
+Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage(
+    Out<u8> out_desired_language, u32 supported_languages) {
+    LOG_INFO(Service_NS, "called with supported_languages={:08X}", supported_languages);
+
+    // Get language code from settings
+    const auto language_code =
+        Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
+
+    // Convert to application language, get priority list
+    const auto application_language = ConvertToApplicationLanguage(language_code);
+    if (application_language == std::nullopt) {
+        LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
+                  language_code);
+        R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+    }
+    const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
+    if (!priority_list) {
+        LOG_ERROR(Service_NS,
+                  "Could not find application language priorities! application_language={}",
+                  *application_language);
+        R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+    }
+
+    // Try to find a valid language.
+    for (const auto lang : *priority_list) {
+        const auto supported_flag = GetSupportedLanguageFlag(lang);
+        if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
+            *out_desired_language = static_cast<u8>(lang);
+            R_SUCCEED();
+        }
+    }
+
+    LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
+              supported_languages);
+    R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+}
+
+Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode(
+    Out<u64> out_language_code, ApplicationLanguage application_language) {
+    const auto language_code = ConvertToLanguageCode(application_language);
+    if (language_code == std::nullopt) {
+        LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
+        R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+    }
+
+    *out_language_code = static_cast<u64>(*language_code);
+    R_SUCCEED();
+}
+
+} // namespace Service::NS

+ 29 - 0
src/core/hle/service/ns/read_only_application_control_data_interface.h

@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IReadOnlyApplicationControlDataInterface final
+    : public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
+public:
+    explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
+    ~IReadOnlyApplicationControlDataInterface() override;
+
+private:
+    Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
+                                     Out<u32> out_actual_size,
+                                     ApplicationControlSource application_control_source,
+                                     u64 application_id);
+    Result GetApplicationDesiredLanguage(Out<u8> out_desired_language, u32 supported_languages);
+    Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
+                                                    ApplicationLanguage application_language);
+};
+
+} // namespace Service::NS