mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-22 23:02:47 +01:00
ns: rewrite IReadOnlyApplicationControlDataInterface
This commit is contained in:
parent
786fc512e2
commit
2eded86b4b
6 changed files with 160 additions and 55 deletions
|
@ -765,6 +765,8 @@ add_library(core STATIC
|
||||||
hle/service/ns/pdm_qry.h
|
hle/service/ns/pdm_qry.h
|
||||||
hle/service/ns/platform_service_manager.cpp
|
hle/service/ns/platform_service_manager.cpp
|
||||||
hle/service/ns/platform_service_manager.h
|
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.cpp
|
||||||
hle/service/ns/read_only_application_record_interface.h
|
hle/service/ns/read_only_application_record_interface.h
|
||||||
hle/service/nvdrv/core/container.cpp
|
hle/service/nvdrv/core/container.cpp
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "core/hle/service/ns/ns_results.h"
|
#include "core/hle/service/ns/ns_results.h"
|
||||||
#include "core/hle/service/ns/pdm_qry.h"
|
#include "core/hle/service/ns/pdm_qry.h"
|
||||||
#include "core/hle/service/ns/platform_service_manager.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/ns/read_only_application_record_interface.h"
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
#include "core/hle/service/set/settings_server.h"
|
#include "core/hle/service/set/settings_server.h"
|
||||||
|
@ -469,51 +470,6 @@ Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||||
return ResultSuccess;
|
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} {
|
NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
|
|
|
@ -32,16 +32,6 @@ private:
|
||||||
void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx);
|
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> {
|
class NS final : public ServiceFramework<NS> {
|
||||||
public:
|
public:
|
||||||
explicit NS(const char* name, Core::System& system_);
|
explicit NS(const char* name, Core::System& system_);
|
||||||
|
|
|
@ -16,6 +16,12 @@ enum class ApplicationRecordType : u8 {
|
||||||
GameCard = 0x10,
|
GameCard = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ApplicationControlSource : u8 {
|
||||||
|
CacheOnly = 0,
|
||||||
|
Storage = 1,
|
||||||
|
StorageOnly = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct ApplicationRecord {
|
struct ApplicationRecord {
|
||||||
u64 application_id;
|
u64 application_id;
|
||||||
ApplicationRecordType type;
|
ApplicationRecordType type;
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in a new issue