ns: rewrite IReadOnlyApplicationControlDataInterface

This commit is contained in:
Liam 2024-02-17 13:46:18 -05:00
parent 786fc512e2
commit 2eded86b4b
6 changed files with 160 additions and 55 deletions

View file

@ -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

View file

@ -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[] = {

View file

@ -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_);

View file

@ -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;

View file

@ -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

View file

@ -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