From a468273221097462032991bad2cca1218c2364b2 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:05:50 -0400 Subject: [PATCH 1/9] patch_manager: Add getter for title version --- src/core/file_sys/patch_manager.cpp | 10 ++++++++++ src/core/file_sys/patch_manager.h | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index da823c37b..a8f80e2c6 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -493,6 +493,16 @@ std::map> PatchManager::GetPatchVersionNam return out; } +std::optional PatchManager::GetGameVersion() const { + const auto& installed = Core::System::GetInstance().GetContentProvider(); + const auto update_tid = GetUpdateTitleID(title_id); + if (installed.HasEntry(update_tid, ContentRecordType::Program)) { + return installed.GetEntryVersion(update_tid); + } + + return installed.GetEntryVersion(title_id); +} + std::pair, VirtualFile> PatchManager::GetControlMetadata() const { const auto& installed = Core::System::GetInstance().GetContentProvider(); diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 769f8c6f0..f82b4ae1e 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -66,8 +66,10 @@ public: std::map> GetPatchVersionNames( VirtualFile update_raw = nullptr) const; - // Given title_id of the program, attempts to get the control data of the update and parse it, - // falling back to the base control data. + std::optional GetGameVersion() const; + + // Given title_id of the program, attempts to get the control data of the update and parse + // it, falling back to the base control data. std::pair, VirtualFile> GetControlMetadata() const; // Version of GetControlMetadata that takes an arbitrary NCA From db2e5e5fa6731c02a016ae583732ce1df8fae3b3 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:10:17 -0400 Subject: [PATCH 2/9] registered_cache: Add getter to determine source slot in content provider union Used to determine StorageId source for application data. --- src/core/file_sys/registered_cache.cpp | 14 ++++++++++++++ src/core/file_sys/registered_cache.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 58917e094..3bb921210 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -645,6 +645,20 @@ ContentProviderUnion::ListEntriesFilterOrigin(std::optional ContentProviderUnion::GetSlotForEntry( + u64 title_id, ContentRecordType type) const { + for (const auto& [slot, provider] : providers) { + if (provider == nullptr) + continue; + + if (provider->HasEntry(title_id, type)) { + return slot; + } + } + + return std::nullopt; +} + ManualContentProvider::~ManualContentProvider() = default; void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type, diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index ec9052653..4398d63e1 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -199,6 +199,9 @@ public: std::optional title_type = {}, std::optional record_type = {}, std::optional title_id = {}) const; + std::optional GetSlotForEntry(u64 title_id, + ContentRecordType type) const; + private: std::map providers; }; From 5f8d2a2044842a0d0674d178e7bb98be2ee65be2 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:17:13 -0400 Subject: [PATCH 3/9] glue: Add manager to keep track of application registry Manages mapping between title IDs and application launch and control properties. --- src/core/CMakeLists.txt | 2 + src/core/hle/service/glue/manager.cpp | 73 +++++++++++++++++++++++++++ src/core/hle/service/glue/manager.h | 46 +++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 src/core/hle/service/glue/manager.cpp create mode 100644 src/core/hle/service/glue/manager.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cdb3bf6ab..6a9a3c180 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -276,6 +276,8 @@ add_library(core STATIC hle/service/friend/friend.h hle/service/friend/interface.cpp hle/service/friend/interface.h + hle/service/glue/manager.cpp + hle/service/glue/manager.h hle/service/grc/grc.cpp hle/service/grc/grc.h hle/service/hid/hid.cpp diff --git a/src/core/hle/service/glue/manager.cpp b/src/core/hle/service/glue/manager.cpp new file mode 100644 index 000000000..0d5bb4d50 --- /dev/null +++ b/src/core/hle/service/glue/manager.cpp @@ -0,0 +1,73 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/glue/errors.h" +#include "core/hle/service/glue/manager.h" + +namespace Service::Glue { + +ARPManager::ARPManager() = default; + +ARPManager::~ARPManager() = default; + +ResultVal ARPManager::GetLaunchProperty(u64 title_id) const { + if (title_id == 0) { + return ERR_TITLE_ID_ZERO; + } + + const auto iter = entries.find(title_id); + if (iter == entries.end()) { + return ERR_NONEXISTENT; + } + + return MakeResult(iter->second.launch); +} + +ResultVal> ARPManager::GetControlProperty(u64 title_id) const { + if (title_id == 0) { + return ERR_TITLE_ID_ZERO; + } + + const auto iter = entries.find(title_id); + if (iter == entries.end()) { + return ERR_NONEXISTENT; + } + + return MakeResult>(iter->second.control); +} + +ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, + std::vector control) { + if (title_id == 0) { + return ERR_TITLE_ID_ZERO; + } + + const auto iter = entries.find(title_id); + if (iter != entries.end()) { + return ERR_ALREADY_ISSUED; + } + + entries.insert_or_assign(title_id, MapEntry{launch, std::move(control)}); + return RESULT_SUCCESS; +} + +ResultCode ARPManager::Unregister(u64 title_id) { + if (title_id == 0) { + return ERR_TITLE_ID_ZERO; + } + + const auto iter = entries.find(title_id); + if (iter == entries.end()) { + return ERR_NONEXISTENT; + } + + entries.erase(iter); + return RESULT_SUCCESS; +} + +void ARPManager::ResetAll() { + entries.clear(); +} + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/manager.h b/src/core/hle/service/glue/manager.h new file mode 100644 index 000000000..561ebf4e0 --- /dev/null +++ b/src/core/hle/service/glue/manager.h @@ -0,0 +1,46 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/romfs_factory.h" +#include "core/hle/result.h" + +namespace Service::Glue { + +struct ApplicationLaunchProperty { + u64 title_id; + u32 version; + FileSys::StorageId base_game_storage_id; + FileSys::StorageId update_storage_id; + INSERT_PADDING_BYTES(0x2); +}; +static_assert(sizeof(ApplicationLaunchProperty) == 0x10, + "ApplicationLaunchProperty has incorrect size."); + +class ARPManager { +public: + ARPManager(); + ~ARPManager(); + + ResultVal GetLaunchProperty(u64 title_id) const; + ResultVal> GetControlProperty(u64 title_id) const; + + ResultCode Register(u64 title_id, ApplicationLaunchProperty launch, std::vector control); + + ResultCode Unregister(u64 title_id); + + void ResetAll(); + +private: + struct MapEntry { + ApplicationLaunchProperty launch; + std::vector control; + }; + + std::map entries; +}; + +} // namespace Service::Glue From 9003e19797eaec40f90e127a02b47d3effb2d005 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:17:48 -0400 Subject: [PATCH 4/9] arp: Move to glue services Glue is the name of the sysmodule that contains both arp and bgtc. --- src/core/hle/service/arp/arp.cpp | 75 -------------------------------- src/core/hle/service/arp/arp.h | 16 ------- 2 files changed, 91 deletions(-) delete mode 100644 src/core/hle/service/arp/arp.cpp delete mode 100644 src/core/hle/service/arp/arp.h diff --git a/src/core/hle/service/arp/arp.cpp b/src/core/hle/service/arp/arp.cpp deleted file mode 100644 index e675b0188..000000000 --- a/src/core/hle/service/arp/arp.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include - -#include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/service/arp/arp.h" -#include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" - -namespace Service::ARP { - -class ARP_R final : public ServiceFramework { -public: - explicit ARP_R() : ServiceFramework{"arp:r"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetApplicationLaunchProperty"}, - {1, nullptr, "GetApplicationLaunchPropertyWithApplicationId"}, - {2, nullptr, "GetApplicationControlProperty"}, - {3, nullptr, "GetApplicationControlPropertyWithApplicationId"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class IRegistrar final : public ServiceFramework { -public: - explicit IRegistrar() : ServiceFramework{"IRegistrar"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "Issue"}, - {1, nullptr, "SetApplicationLaunchProperty"}, - {2, nullptr, "SetApplicationControlProperty"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class ARP_W final : public ServiceFramework { -public: - explicit ARP_W() : ServiceFramework{"arp:w"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, - {1, nullptr, "DeleteProperties"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void AcquireRegistrar(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_ARP, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(); - } -}; - -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared()->InstallAsService(sm); - std::make_shared()->InstallAsService(sm); -} - -} // namespace Service::ARP diff --git a/src/core/hle/service/arp/arp.h b/src/core/hle/service/arp/arp.h deleted file mode 100644 index 9d100187c..000000000 --- a/src/core/hle/service/arp/arp.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service::SM { -class ServiceManager; -} - -namespace Service::ARP { - -/// Registers all ARP services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm); - -} // namespace Service::ARP From 4fab0d392b9bde614ac140920074290976c322aa Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:20:06 -0400 Subject: [PATCH 5/9] glue: Add scaffolding for bgtc:t and bgtc:sc services --- src/core/hle/service/glue/bgtc.cpp | 50 ++++++++++++++++++++++++++++++ src/core/hle/service/glue/bgtc.h | 23 ++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/core/hle/service/glue/bgtc.cpp create mode 100644 src/core/hle/service/glue/bgtc.h diff --git a/src/core/hle/service/glue/bgtc.cpp b/src/core/hle/service/glue/bgtc.cpp new file mode 100644 index 000000000..cd89d088f --- /dev/null +++ b/src/core/hle/service/glue/bgtc.cpp @@ -0,0 +1,50 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/glue/bgtc.h" + +namespace Service::Glue { + +BGTC_T::BGTC_T() : ServiceFramework{"bgtc:t"} { + // clang-format off + static const FunctionInfo functions[] = { + {1, nullptr, "NotifyTaskStarting"}, + {2, nullptr, "NotifyTaskFinished"}, + {3, nullptr, "GetTriggerEvent"}, + {4, nullptr, "IsInHalfAwake"}, + {5, nullptr, "NotifyClientName"}, + {6, nullptr, "IsInFullAwake"}, + {11, nullptr, "ScheduleTask"}, + {12, nullptr, "GetScheduledTaskInterval"}, + {13, nullptr, "UnscheduleTask"}, + {14, nullptr, "GetScheduleEvent"}, + {15, nullptr, "SchedulePeriodicTask"}, + {101, nullptr, "GetOperationMode"}, + {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"}, + {103, nullptr, "WillStayHalfAwakeInsteadSleep"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +BGTC_T::~BGTC_T() = default; + +BGTC_SC::BGTC_SC() : ServiceFramework{"bgtc:sc"} { + // clang-format off + static const FunctionInfo functions[] = { + {1, nullptr, "GetState"}, + {2, nullptr, "GetStateChangedEvent"}, + {3, nullptr, "NotifyEnteringHalfAwake"}, + {4, nullptr, "NotifyLeavingHalfAwake"}, + {5, nullptr, "SetIsUsingSleepUnsupportedDevices"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +BGTC_SC::~BGTC_SC() = default; + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/bgtc.h b/src/core/hle/service/glue/bgtc.h new file mode 100644 index 000000000..81844f03e --- /dev/null +++ b/src/core/hle/service/glue/bgtc.h @@ -0,0 +1,23 @@ +// Copyright 2019 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::Glue { + +class BGTC_T final : public ServiceFramework { +public: + BGTC_T(); + ~BGTC_T() override; +}; + +class BGTC_SC final : public ServiceFramework { +public: + BGTC_SC(); + ~BGTC_SC() override; +}; + +} // namespace Service::Glue From df3ee4f44431ad6b026d404a234680f51fe702b6 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:20:28 -0400 Subject: [PATCH 6/9] glue: Add errors for glue/arp services --- src/core/CMakeLists.txt | 9 +++++++-- src/core/hle/service/glue/errors.h | 17 +++++++++++++++++ src/core/hle/service/glue/glue.cpp | 25 +++++++++++++++++++++++++ src/core/hle/service/glue/glue.h | 16 ++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 src/core/hle/service/glue/errors.h create mode 100644 src/core/hle/service/glue/glue.cpp create mode 100644 src/core/hle/service/glue/glue.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6a9a3c180..d65659b44 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -209,8 +209,6 @@ add_library(core STATIC hle/service/apm/apm.h hle/service/apm/interface.cpp hle/service/apm/interface.h - hle/service/arp/arp.cpp - hle/service/arp/arp.h hle/service/audio/audctl.cpp hle/service/audio/audctl.h hle/service/audio/auddbg.cpp @@ -276,6 +274,13 @@ add_library(core STATIC hle/service/friend/friend.h hle/service/friend/interface.cpp hle/service/friend/interface.h + hle/service/glue/arp.cpp + hle/service/glue/arp.h + hle/service/glue/bgtc.cpp + hle/service/glue/bgtc.h + hle/service/glue/errors.h + hle/service/glue/glue.cpp + hle/service/glue/glue.h hle/service/glue/manager.cpp hle/service/glue/manager.h hle/service/grc/grc.cpp diff --git a/src/core/hle/service/glue/errors.h b/src/core/hle/service/glue/errors.h new file mode 100644 index 000000000..594e20a01 --- /dev/null +++ b/src/core/hle/service/glue/errors.h @@ -0,0 +1,17 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/result.h" + +namespace Service::Glue { + +constexpr ResultCode ERR_OUTPUT_TOO_SMALL{0x3C9D}; +constexpr ResultCode ERR_PROCESS_ID_ZERO{0x3E9D}; +constexpr ResultCode ERR_TITLE_ID_ZERO{0x3E9D}; +constexpr ResultCode ERR_ALREADY_ISSUED{0x549D}; +constexpr ResultCode ERR_NONEXISTENT{0xCC9D}; + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp new file mode 100644 index 000000000..c728e815c --- /dev/null +++ b/src/core/hle/service/glue/glue.cpp @@ -0,0 +1,25 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "core/core.h" +#include "core/hle/service/glue/arp.h" +#include "core/hle/service/glue/bgtc.h" +#include "core/hle/service/glue/glue.h" + +namespace Service::Glue { + +void InstallInterfaces(Core::System& system) { + // ARP + std::make_shared(system, system.GetARPManager()) + ->InstallAsService(system.ServiceManager()); + std::make_shared(system, system.GetARPManager()) + ->InstallAsService(system.ServiceManager()); + + // BackGround Task Controller + std::make_shared()->InstallAsService(system.ServiceManager()); + std::make_shared()->InstallAsService(system.ServiceManager()); +} + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/glue.h b/src/core/hle/service/glue/glue.h new file mode 100644 index 000000000..112cd238b --- /dev/null +++ b/src/core/hle/service/glue/glue.h @@ -0,0 +1,16 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Core { +class System; +} // namespace Core + +namespace Service::Glue { + +/// Registers all Glue services with the specified service manager. +void InstallInterfaces(Core::System& system); + +} // namespace Service::Glue From ce2197302236c0990d2d5234ab52f1579c126090 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:26:16 -0400 Subject: [PATCH 7/9] glue: Implement arp:w and arp:r services These keep track of running process' launch properties and control properties and allows for issuing and reading them by process and title ID. --- src/core/hle/service/glue/arp.cpp | 285 ++++++++++++++++++++++++++++++ src/core/hle/service/glue/arp.h | 43 +++++ src/core/hle/service/service.cpp | 4 +- 3 files changed, 330 insertions(+), 2 deletions(-) create mode 100644 src/core/hle/service/glue/arp.cpp create mode 100644 src/core/hle/service/glue/arp.h diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp new file mode 100644 index 000000000..19c75ff2f --- /dev/null +++ b/src/core/hle/service/glue/arp.cpp @@ -0,0 +1,285 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "common/logging/log.h" +#include "core/file_sys/control_metadata.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/process.h" +#include "core/hle/service/glue/arp.h" +#include "core/hle/service/glue/errors.h" +#include "core/hle/service/glue/manager.h" +#include "core/hle/service/service.h" + +namespace Service::Glue { + +namespace { +std::optional GetTitleIDForProcessID(const Core::System& system, u64 process_id) { + const auto& list = system.Kernel().GetProcessList(); + const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { + return process->GetProcessID() == process_id; + }); + + if (iter == list.end()) { + return std::nullopt; + } + + return (*iter)->GetTitleID(); +} +} // Anonymous namespace + +ARP_R::ARP_R(const Core::System& system, const ARPManager& manager) + : ServiceFramework{"arp:r"}, system(system), manager(manager) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ARP_R::GetApplicationLaunchProperty, "GetApplicationLaunchProperty"}, + {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"}, + {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"}, + {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ARP_R::~ARP_R() = default; + +void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + const auto title_id = GetTitleIDForProcessID(system, process_id); + if (!title_id.has_value()) { + LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NONEXISTENT); + } + + const auto res = manager.GetLaunchProperty(*title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get launch property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(*res); +} + +void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto title_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); + + const auto res = manager.GetLaunchProperty(title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get launch property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(*res); +} + +void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + const auto title_id = GetTitleIDForProcessID(system, process_id); + if (!title_id.has_value()) { + LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NONEXISTENT); + } + + const auto res = manager.GetControlProperty(*title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get control property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + ctx.WriteBuffer(*res); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto title_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); + + const auto res = manager.GetControlProperty(title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get control property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + ctx.WriteBuffer(*res); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +class IRegistrar final : public ServiceFramework { + friend class ARP_W; + +public: + explicit IRegistrar( + std::function)> issuer) + : ServiceFramework{"IRegistrar"}, issue_process_id(std::move(issuer)) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IRegistrar::Issue, "Issue"}, + {1, &IRegistrar::SetApplicationLaunchProperty, "SetApplicationLaunchProperty"}, + {2, &IRegistrar::SetApplicationControlProperty, "SetApplicationControlProperty"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void Issue(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + if (process_id == 0) { + LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_PROCESS_ID_ZERO); + } + + if (issued) { + LOG_ERROR(Service_ARP, + "Attempted to issue registrar, but registrar is already issued!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_ALREADY_ISSUED); + } + + issue_process_id(process_id, launch, std::move(control)); + issued = true; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ARP, "called"); + + if (issued) { + LOG_ERROR( + Service_ARP, + "Attempted to set application launch property, but registrar is already issued!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_ALREADY_ISSUED); + } + + IPC::RequestParser rp{ctx}; + launch = rp.PopRaw(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetApplicationControlProperty(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ARP, "called"); + + if (issued) { + LOG_ERROR( + Service_ARP, + "Attempted to set application control property, but registrar is already issued!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_ALREADY_ISSUED); + } + + control = ctx.ReadBuffer(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + std::function)> issue_process_id; + bool issued = false; + ApplicationLaunchProperty launch; + std::vector control; +}; + +ARP_W::ARP_W(const Core::System& system, ARPManager& manager) + : ServiceFramework{"arp:w"}, system(system), manager(manager) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, + {1, &ARP_W::DeleteProperties, "DeleteProperties"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ARP_W::~ARP_W() = default; + +void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ARP, "called"); + + registrar = std::make_shared( + [this](u64 process_id, ApplicationLaunchProperty launch, std::vector control) { + const auto res = GetTitleIDForProcessID(system, process_id); + if (!res.has_value()) { + return ERR_NONEXISTENT; + } + + return manager.Register(*res, launch, std::move(control)); + }); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(registrar); +} + +void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + if (process_id == 0) { + LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_PROCESS_ID_ZERO); + } + + const auto title_id = GetTitleIDForProcessID(system, process_id); + + if (!title_id.has_value()) { + LOG_ERROR(Service_ARP, "No title ID for process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NONEXISTENT); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(manager.Unregister(*title_id)); +} + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/arp.h b/src/core/hle/service/glue/arp.h new file mode 100644 index 000000000..d5f8a7e7a --- /dev/null +++ b/src/core/hle/service/glue/arp.h @@ -0,0 +1,43 @@ +// Copyright 2019 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::Glue { + +class ARPManager; +class IRegistrar; + +class ARP_R final : public ServiceFramework { +public: + explicit ARP_R(const Core::System& system, const ARPManager& manager); + ~ARP_R() override; + +private: + void GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx); + void GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx); + void GetApplicationControlProperty(Kernel::HLERequestContext& ctx); + void GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx); + + const Core::System& system; + const ARPManager& manager; +}; + +class ARP_W final : public ServiceFramework { +public: + explicit ARP_W(const Core::System& system, ARPManager& manager); + ~ARP_W() override; + +private: + void AcquireRegistrar(Kernel::HLERequestContext& ctx); + void DeleteProperties(Kernel::HLERequestContext& ctx); + + const Core::System& system; + ARPManager& manager; + std::shared_ptr registrar; +}; + +} // namespace Service::Glue diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index b2954eb34..beae9c510 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -19,7 +19,6 @@ #include "core/hle/service/am/am.h" #include "core/hle/service/aoc/aoc_u.h" #include "core/hle/service/apm/apm.h" -#include "core/hle/service/arp/arp.h" #include "core/hle/service/audio/audio.h" #include "core/hle/service/bcat/module.h" #include "core/hle/service/bpc/bpc.h" @@ -33,6 +32,7 @@ #include "core/hle/service/fgm/fgm.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/friend/friend.h" +#include "core/hle/service/glue/glue.h" #include "core/hle/service/grc/grc.h" #include "core/hle/service/hid/hid.h" #include "core/hle/service/lbl/lbl.h" @@ -207,7 +207,6 @@ void Init(std::shared_ptr& sm, Core::System& system, AM::InstallInterfaces(*sm, nv_flinger); AOC::InstallInterfaces(*sm); APM::InstallInterfaces(*sm); - ARP::InstallInterfaces(*sm); Audio::InstallInterfaces(*sm); BCAT::InstallInterfaces(*sm); BPC::InstallInterfaces(*sm); @@ -221,6 +220,7 @@ void Init(std::shared_ptr& sm, Core::System& system, FGM::InstallInterfaces(*sm); FileSystem::InstallInterfaces(*sm, vfs); Friend::InstallInterfaces(*sm); + Glue::InstallInterfaces(system); GRC::InstallInterfaces(*sm); HID::InstallInterfaces(*sm); LBL::InstallInterfaces(*sm); From d40a38df8d5833397da942a338728da6d07eae84 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:27:35 -0400 Subject: [PATCH 8/9] core: Keep track of ARPManager and register current application on boot --- src/core/core.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++ src/core/core.h | 8 ++++++ 2 files changed, 76 insertions(+) diff --git a/src/core/core.cpp b/src/core/core.cpp index c00dfd33c..2d7e83522 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -25,6 +25,7 @@ #include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" #include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/glue/manager.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" #include "core/loader/loader.h" @@ -33,12 +34,39 @@ #include "core/settings.h" #include "core/telemetry_session.h" #include "file_sys/cheat_engine.h" +#include "file_sys/patch_manager.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/renderer_base.h" #include "video_core/video_core.h" namespace Core { +namespace { + +FileSys::StorageId GetStorageIdForFrontendSlot( + std::optional slot) { + if (!slot.has_value()) { + return FileSys::StorageId::None; + } + + switch (*slot) { + case FileSys::ContentProviderUnionSlot::UserNAND: + return FileSys::StorageId::NandUser; + case FileSys::ContentProviderUnionSlot::SysNAND: + return FileSys::StorageId::NandSystem; + case FileSys::ContentProviderUnionSlot::SDMC: + return FileSys::StorageId::SdCard; + case FileSys::ContentProviderUnionSlot::FrontendManual: + return FileSys::StorageId::Host; + default: + return FileSys::StorageId::None; + } + + UNREACHABLE(); +} + +} // Anonymous namespace + /*static*/ System System::s_instance; FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, @@ -110,6 +138,9 @@ struct System::Impl { /// Create default implementations of applets if one is not provided. applet_manager.SetDefaultAppletsIfMissing(); + /// Reset all glue registrations + arp_manager.ResetAll(); + telemetry_session = std::make_unique(); service_manager = std::make_shared(); @@ -161,6 +192,7 @@ struct System::Impl { return static_cast(static_cast(ResultStatus::ErrorLoader) + static_cast(load_result)); } + AddGlueRegistrationForProcess(*app_loader, *main_process); kernel.MakeCurrentProcess(main_process.get()); // Main process has been loaded and been made current. @@ -219,6 +251,31 @@ struct System::Impl { return app_loader->ReadTitle(out); } + void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::Process& process) { + std::vector nacp_data; + FileSys::NACP nacp; + if (loader.ReadControlData(nacp) == Loader::ResultStatus::Success) { + nacp_data = nacp.GetRawBytes(); + } else { + nacp_data.resize(sizeof(FileSys::RawNACP)); + } + + Service::Glue::ApplicationLaunchProperty launch{}; + launch.title_id = process.GetTitleID(); + + FileSys::PatchManager pm{launch.title_id}; + launch.version = pm.GetGameVersion().value_or(0); + + // TODO(DarkLordZach): When FSController/Game Card Support is added, if + // current_process_game_card use correct StorageId + launch.base_game_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry( + launch.title_id, FileSys::ContentRecordType::Program)); + launch.update_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry( + FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); + + arp_manager.Register(launch.title_id, launch, std::move(nacp_data)); + } + void SetStatus(ResultStatus new_status, const char* details = nullptr) { status = new_status; if (details) { @@ -249,6 +306,9 @@ struct System::Impl { /// Frontend applets Service::AM::Applets::AppletManager applet_manager; + /// Glue services + Service::Glue::ARPManager arp_manager; + /// Service manager std::shared_ptr service_manager; @@ -500,6 +560,14 @@ const Reporter& System::GetReporter() const { return impl->reporter; } +Service::Glue::ARPManager& System::GetARPManager() { + return impl->arp_manager; +} + +const Service::Glue::ARPManager& System::GetARPManager() const { + return impl->arp_manager; +} + System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { return impl->Init(*this, emu_window); } diff --git a/src/core/core.h b/src/core/core.h index 226ef4630..70adb7af9 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -43,6 +43,10 @@ struct AppletFrontendSet; class AppletManager; } // namespace AM::Applets +namespace Glue { +class ARPManager; +} + namespace SM { class ServiceManager; } // namespace SM @@ -288,6 +292,10 @@ public: const Reporter& GetReporter() const; + Service::Glue::ARPManager& GetARPManager(); + + const Service::Glue::ARPManager& GetARPManager() const; + private: System(); From d10fc2d7277cf075f875fe2831501cb79c50e21a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 25 Jun 2019 22:25:10 -0400 Subject: [PATCH 9/9] glue: Correct missing bytes in ApplicationLaunchParameter --- src/core/core.cpp | 2 -- src/core/file_sys/patch_manager.h | 3 +++ src/core/file_sys/registered_cache.cpp | 14 ++++++------ src/core/hle/service/glue/arp.cpp | 30 ++++++++++++++++++-------- src/core/hle/service/glue/errors.h | 9 ++++---- src/core/hle/service/glue/manager.cpp | 21 +++++++++++------- src/core/hle/service/glue/manager.h | 29 +++++++++++++++++++------ 7 files changed, 71 insertions(+), 37 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 2d7e83522..df26eb109 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -61,8 +61,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot( default: return FileSys::StorageId::None; } - - UNREACHABLE(); } } // Anonymous namespace diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index f82b4ae1e..a363c6577 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -66,6 +66,9 @@ public: std::map> GetPatchVersionNames( VirtualFile update_raw = nullptr) const; + // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails, + // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be + // std::nullopt std::optional GetGameVersion() const; // Given title_id of the program, attempts to get the control data of the update and parse diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 3bb921210..4608490e0 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -647,16 +647,16 @@ ContentProviderUnion::ListEntriesFilterOrigin(std::optional ContentProviderUnion::GetSlotForEntry( u64 title_id, ContentRecordType type) const { - for (const auto& [slot, provider] : providers) { - if (provider == nullptr) - continue; + const auto iter = + std::find_if(providers.begin(), providers.end(), [title_id, type](const auto& provider) { + return provider.second != nullptr && provider.second->HasEntry(title_id, type); + }); - if (provider->HasEntry(title_id, type)) { - return slot; - } + if (iter == providers.end()) { + return std::nullopt; } - return std::nullopt; + return iter->first; } ManualContentProvider::~ManualContentProvider() = default; diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index 19c75ff2f..b591ce31b 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -58,7 +58,8 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } const auto res = manager.GetLaunchProperty(*title_id); @@ -67,6 +68,7 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_ARP, "Failed to get launch property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } IPC::ResponseBuilder rb{ctx, 6}; @@ -86,6 +88,7 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestCont LOG_ERROR(Service_ARP, "Failed to get launch property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } IPC::ResponseBuilder rb{ctx, 6}; @@ -103,7 +106,8 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } const auto res = manager.GetControlProperty(*title_id); @@ -112,6 +116,7 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_ARP, "Failed to get control property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } ctx.WriteBuffer(*res); @@ -132,6 +137,7 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestCon LOG_ERROR(Service_ARP, "Failed to get control property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } ctx.WriteBuffer(*res); @@ -168,14 +174,16 @@ private: if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_PROCESS_ID_ZERO); + rb.Push(ERR_INVALID_PROCESS_ID); + return; } if (issued) { LOG_ERROR(Service_ARP, "Attempted to issue registrar, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } issue_process_id(process_id, launch, std::move(control)); @@ -193,7 +201,8 @@ private: Service_ARP, "Attempted to set application launch property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } IPC::RequestParser rp{ctx}; @@ -211,7 +220,8 @@ private: Service_ARP, "Attempted to set application control property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } control = ctx.ReadBuffer(); @@ -247,7 +257,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { [this](u64 process_id, ApplicationLaunchProperty launch, std::vector control) { const auto res = GetTitleIDForProcessID(system, process_id); if (!res.has_value()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } return manager.Register(*res, launch, std::move(control)); @@ -267,7 +277,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_PROCESS_ID_ZERO); + rb.Push(ERR_INVALID_PROCESS_ID); + return; } const auto title_id = GetTitleIDForProcessID(system, process_id); @@ -275,7 +286,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "No title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } IPC::ResponseBuilder rb{ctx, 2}; diff --git a/src/core/hle/service/glue/errors.h b/src/core/hle/service/glue/errors.h index 594e20a01..c2874c585 100644 --- a/src/core/hle/service/glue/errors.h +++ b/src/core/hle/service/glue/errors.h @@ -8,10 +8,9 @@ namespace Service::Glue { -constexpr ResultCode ERR_OUTPUT_TOO_SMALL{0x3C9D}; -constexpr ResultCode ERR_PROCESS_ID_ZERO{0x3E9D}; -constexpr ResultCode ERR_TITLE_ID_ZERO{0x3E9D}; -constexpr ResultCode ERR_ALREADY_ISSUED{0x549D}; -constexpr ResultCode ERR_NONEXISTENT{0xCC9D}; +constexpr ResultCode ERR_INVALID_RESOURCE{ErrorModule::ARP, 0x1E}; +constexpr ResultCode ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 0x1F}; +constexpr ResultCode ERR_INVALID_ACCESS{ErrorModule::ARP, 0x2A}; +constexpr ResultCode ERR_NOT_REGISTERED{ErrorModule::ARP, 0x66}; } // namespace Service::Glue diff --git a/src/core/hle/service/glue/manager.cpp b/src/core/hle/service/glue/manager.cpp index 0d5bb4d50..6da52d2d6 100644 --- a/src/core/hle/service/glue/manager.cpp +++ b/src/core/hle/service/glue/manager.cpp @@ -7,18 +7,23 @@ namespace Service::Glue { +struct ARPManager::MapEntry { + ApplicationLaunchProperty launch; + std::vector control; +}; + ARPManager::ARPManager() = default; ARPManager::~ARPManager() = default; ResultVal ARPManager::GetLaunchProperty(u64 title_id) const { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } return MakeResult(iter->second.launch); @@ -26,12 +31,12 @@ ResultVal ARPManager::GetLaunchProperty(u64 title_id) ResultVal> ARPManager::GetControlProperty(u64 title_id) const { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } return MakeResult>(iter->second.control); @@ -40,12 +45,12 @@ ResultVal> ARPManager::GetControlProperty(u64 title_id) const { ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, std::vector control) { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter != entries.end()) { - return ERR_ALREADY_ISSUED; + return ERR_INVALID_ACCESS; } entries.insert_or_assign(title_id, MapEntry{launch, std::move(control)}); @@ -54,12 +59,12 @@ ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, ResultCode ARPManager::Unregister(u64 title_id) { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } entries.erase(iter); diff --git a/src/core/hle/service/glue/manager.h b/src/core/hle/service/glue/manager.h index 561ebf4e0..a7f5ce3ee 100644 --- a/src/core/hle/service/glue/manager.h +++ b/src/core/hle/service/glue/manager.h @@ -4,6 +4,9 @@ #pragma once +#include +#include +#include "common/common_types.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/romfs_factory.h" #include "core/hle/result.h" @@ -15,31 +18,45 @@ struct ApplicationLaunchProperty { u32 version; FileSys::StorageId base_game_storage_id; FileSys::StorageId update_storage_id; - INSERT_PADDING_BYTES(0x2); + u8 program_index; + u8 reserved; }; static_assert(sizeof(ApplicationLaunchProperty) == 0x10, "ApplicationLaunchProperty has incorrect size."); +// A class to manage state related to the arp:w and arp:r services, specifically the registration +// and unregistration of launch and control properties. class ARPManager { public: ARPManager(); ~ARPManager(); + // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was + // previously registered, otherwise ERR_NOT_REGISTERED if it was never registered or + // ERR_INVALID_PROCESS_ID if the title ID is 0. ResultVal GetLaunchProperty(u64 title_id) const; + + // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to + // the provided title ID if it was previously registered, otherwise ERR_NOT_REGISTERED if it was + // never registered or ERR_INVALID_PROCESS_ID if the title ID is 0. ResultVal> GetControlProperty(u64 title_id) const; + // Adds a new entry to the internal database with the provided parameters, returning + // ERR_INVALID_ACCESS if attempting to re-register a title ID without an intermediate Unregister + // step, and ERR_INVALID_PROCESS_ID if the title ID is 0. ResultCode Register(u64 title_id, ApplicationLaunchProperty launch, std::vector control); + // Removes the registration for the provided title ID from the database, returning + // ERR_NOT_REGISTERED if it doesn't exist in the database and ERR_INVALID_PROCESS_ID if the + // title ID is 0. ResultCode Unregister(u64 title_id); + // Removes all entries from the database, always succeeds. Should only be used when resetting + // system state. void ResetAll(); private: - struct MapEntry { - ApplicationLaunchProperty launch; - std::vector control; - }; - + struct MapEntry; std::map entries; };