mirror of
https://github.com/yuzu-emu/yuzu-android
synced 2024-12-24 22:21:22 -08:00
Merge pull request #2607 from DarkLordZach/arp-1
glue: Implement arp:w and arp:r services
This commit is contained in:
commit
4ed2774c26
@ -209,8 +209,6 @@ add_library(core STATIC
|
|||||||
hle/service/apm/apm.h
|
hle/service/apm/apm.h
|
||||||
hle/service/apm/interface.cpp
|
hle/service/apm/interface.cpp
|
||||||
hle/service/apm/interface.h
|
hle/service/apm/interface.h
|
||||||
hle/service/arp/arp.cpp
|
|
||||||
hle/service/arp/arp.h
|
|
||||||
hle/service/audio/audctl.cpp
|
hle/service/audio/audctl.cpp
|
||||||
hle/service/audio/audctl.h
|
hle/service/audio/audctl.h
|
||||||
hle/service/audio/auddbg.cpp
|
hle/service/audio/auddbg.cpp
|
||||||
@ -276,6 +274,15 @@ add_library(core STATIC
|
|||||||
hle/service/friend/friend.h
|
hle/service/friend/friend.h
|
||||||
hle/service/friend/interface.cpp
|
hle/service/friend/interface.cpp
|
||||||
hle/service/friend/interface.h
|
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
|
hle/service/grc/grc.cpp
|
||||||
hle/service/grc/grc.h
|
hle/service/grc/grc.h
|
||||||
hle/service/hid/hid.cpp
|
hle/service/hid/hid.cpp
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "core/hle/kernel/scheduler.h"
|
#include "core/hle/kernel/scheduler.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
#include "core/hle/service/am/applets/applets.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/service.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
@ -33,12 +34,37 @@
|
|||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/telemetry_session.h"
|
#include "core/telemetry_session.h"
|
||||||
#include "file_sys/cheat_engine.h"
|
#include "file_sys/cheat_engine.h"
|
||||||
|
#include "file_sys/patch_manager.h"
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
#include "video_core/debug_utils/debug_utils.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
FileSys::StorageId GetStorageIdForFrontendSlot(
|
||||||
|
std::optional<FileSys::ContentProviderUnionSlot> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
/*static*/ System System::s_instance;
|
/*static*/ System System::s_instance;
|
||||||
|
|
||||||
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||||
@ -110,6 +136,9 @@ struct System::Impl {
|
|||||||
/// Create default implementations of applets if one is not provided.
|
/// Create default implementations of applets if one is not provided.
|
||||||
applet_manager.SetDefaultAppletsIfMissing();
|
applet_manager.SetDefaultAppletsIfMissing();
|
||||||
|
|
||||||
|
/// Reset all glue registrations
|
||||||
|
arp_manager.ResetAll();
|
||||||
|
|
||||||
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||||
service_manager = std::make_shared<Service::SM::ServiceManager>();
|
service_manager = std::make_shared<Service::SM::ServiceManager>();
|
||||||
|
|
||||||
@ -161,6 +190,7 @@ struct System::Impl {
|
|||||||
return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
|
return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
|
||||||
static_cast<u32>(load_result));
|
static_cast<u32>(load_result));
|
||||||
}
|
}
|
||||||
|
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
||||||
kernel.MakeCurrentProcess(main_process.get());
|
kernel.MakeCurrentProcess(main_process.get());
|
||||||
|
|
||||||
// Main process has been loaded and been made current.
|
// Main process has been loaded and been made current.
|
||||||
@ -219,6 +249,31 @@ struct System::Impl {
|
|||||||
return app_loader->ReadTitle(out);
|
return app_loader->ReadTitle(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::Process& process) {
|
||||||
|
std::vector<u8> 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) {
|
void SetStatus(ResultStatus new_status, const char* details = nullptr) {
|
||||||
status = new_status;
|
status = new_status;
|
||||||
if (details) {
|
if (details) {
|
||||||
@ -249,6 +304,9 @@ struct System::Impl {
|
|||||||
/// Frontend applets
|
/// Frontend applets
|
||||||
Service::AM::Applets::AppletManager applet_manager;
|
Service::AM::Applets::AppletManager applet_manager;
|
||||||
|
|
||||||
|
/// Glue services
|
||||||
|
Service::Glue::ARPManager arp_manager;
|
||||||
|
|
||||||
/// Service manager
|
/// Service manager
|
||||||
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
||||||
|
|
||||||
@ -500,6 +558,14 @@ const Reporter& System::GetReporter() const {
|
|||||||
return impl->reporter;
|
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) {
|
System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
|
||||||
return impl->Init(*this, emu_window);
|
return impl->Init(*this, emu_window);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,10 @@ struct AppletFrontendSet;
|
|||||||
class AppletManager;
|
class AppletManager;
|
||||||
} // namespace AM::Applets
|
} // namespace AM::Applets
|
||||||
|
|
||||||
|
namespace Glue {
|
||||||
|
class ARPManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace SM {
|
namespace SM {
|
||||||
class ServiceManager;
|
class ServiceManager;
|
||||||
} // namespace SM
|
} // namespace SM
|
||||||
@ -288,6 +292,10 @@ public:
|
|||||||
|
|
||||||
const Reporter& GetReporter() const;
|
const Reporter& GetReporter() const;
|
||||||
|
|
||||||
|
Service::Glue::ARPManager& GetARPManager();
|
||||||
|
|
||||||
|
const Service::Glue::ARPManager& GetARPManager() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
System();
|
System();
|
||||||
|
|
||||||
|
@ -493,6 +493,16 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<u32> 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<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const {
|
std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const {
|
||||||
const auto& installed = Core::System::GetInstance().GetContentProvider();
|
const auto& installed = Core::System::GetInstance().GetContentProvider();
|
||||||
|
|
||||||
|
@ -66,8 +66,13 @@ public:
|
|||||||
std::map<std::string, std::string, std::less<>> GetPatchVersionNames(
|
std::map<std::string, std::string, std::less<>> GetPatchVersionNames(
|
||||||
VirtualFile update_raw = nullptr) const;
|
VirtualFile update_raw = nullptr) const;
|
||||||
|
|
||||||
// Given title_id of the program, attempts to get the control data of the update and parse it,
|
// If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails,
|
||||||
// falling back to the base control data.
|
// it will fallback to the Meta-type NCA of the base game. If that fails, the result will be
|
||||||
|
// std::nullopt
|
||||||
|
std::optional<u32> 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<std::unique_ptr<NACP>, VirtualFile> GetControlMetadata() const;
|
std::pair<std::unique_ptr<NACP>, VirtualFile> GetControlMetadata() const;
|
||||||
|
|
||||||
// Version of GetControlMetadata that takes an arbitrary NCA
|
// Version of GetControlMetadata that takes an arbitrary NCA
|
||||||
|
@ -645,6 +645,20 @@ ContentProviderUnion::ListEntriesFilterOrigin(std::optional<ContentProviderUnion
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<ContentProviderUnionSlot> ContentProviderUnion::GetSlotForEntry(
|
||||||
|
u64 title_id, ContentRecordType type) const {
|
||||||
|
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 (iter == providers.end()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iter->first;
|
||||||
|
}
|
||||||
|
|
||||||
ManualContentProvider::~ManualContentProvider() = default;
|
ManualContentProvider::~ManualContentProvider() = default;
|
||||||
|
|
||||||
void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type,
|
void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type,
|
||||||
|
@ -199,6 +199,9 @@ public:
|
|||||||
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
|
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
|
||||||
std::optional<u64> title_id = {}) const;
|
std::optional<u64> title_id = {}) const;
|
||||||
|
|
||||||
|
std::optional<ContentProviderUnionSlot> GetSlotForEntry(u64 title_id,
|
||||||
|
ContentRecordType type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<ContentProviderUnionSlot, ContentProvider*> providers;
|
std::map<ContentProviderUnionSlot, ContentProvider*> providers;
|
||||||
};
|
};
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
// Copyright 2018 yuzu emulator team
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#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<ARP_R> {
|
|
||||||
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<IRegistrar> {
|
|
||||||
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<ARP_W> {
|
|
||||||
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<IRegistrar>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void InstallInterfaces(SM::ServiceManager& sm) {
|
|
||||||
std::make_shared<ARP_R>()->InstallAsService(sm);
|
|
||||||
std::make_shared<ARP_W>()->InstallAsService(sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::ARP
|
|
@ -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
|
|
297
src/core/hle/service/glue/arp.cpp
Normal file
297
src/core/hle/service/glue/arp.cpp
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
// Copyright 2018 yuzu emulator team
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#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<u64> 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<u64>();
|
||||||
|
|
||||||
|
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_NOT_REGISTERED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<u64>();
|
||||||
|
|
||||||
|
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());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<u64>();
|
||||||
|
|
||||||
|
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_NOT_REGISTERED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<u64>();
|
||||||
|
|
||||||
|
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());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.WriteBuffer(*res);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
class IRegistrar final : public ServiceFramework<IRegistrar> {
|
||||||
|
friend class ARP_W;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit IRegistrar(
|
||||||
|
std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> 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<u64>();
|
||||||
|
|
||||||
|
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_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_INVALID_ACCESS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_INVALID_ACCESS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
launch = rp.PopRaw<ApplicationLaunchProperty>();
|
||||||
|
|
||||||
|
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_INVALID_ACCESS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
control = ctx.ReadBuffer();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issue_process_id;
|
||||||
|
bool issued = false;
|
||||||
|
ApplicationLaunchProperty launch;
|
||||||
|
std::vector<u8> 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<IRegistrar>(
|
||||||
|
[this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) {
|
||||||
|
const auto res = GetTitleIDForProcessID(system, process_id);
|
||||||
|
if (!res.has_value()) {
|
||||||
|
return ERR_NOT_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<u64>();
|
||||||
|
|
||||||
|
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_INVALID_PROCESS_ID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_NOT_REGISTERED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(manager.Unregister(*title_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Glue
|
43
src/core/hle/service/glue/arp.h
Normal file
43
src/core/hle/service/glue/arp.h
Normal file
@ -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<ARP_R> {
|
||||||
|
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<ARP_W> {
|
||||||
|
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<IRegistrar> registrar;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Glue
|
50
src/core/hle/service/glue/bgtc.cpp
Normal file
50
src/core/hle/service/glue/bgtc.cpp
Normal file
@ -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
|
23
src/core/hle/service/glue/bgtc.h
Normal file
23
src/core/hle/service/glue/bgtc.h
Normal file
@ -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<BGTC_T> {
|
||||||
|
public:
|
||||||
|
BGTC_T();
|
||||||
|
~BGTC_T() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BGTC_SC final : public ServiceFramework<BGTC_SC> {
|
||||||
|
public:
|
||||||
|
BGTC_SC();
|
||||||
|
~BGTC_SC() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Glue
|
16
src/core/hle/service/glue/errors.h
Normal file
16
src/core/hle/service/glue/errors.h
Normal file
@ -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
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Service::Glue {
|
||||||
|
|
||||||
|
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
|
25
src/core/hle/service/glue/glue.cpp
Normal file
25
src/core/hle/service/glue/glue.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2019 yuzu emulator team
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#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<ARP_R>(system, system.GetARPManager())
|
||||||
|
->InstallAsService(system.ServiceManager());
|
||||||
|
std::make_shared<ARP_W>(system, system.GetARPManager())
|
||||||
|
->InstallAsService(system.ServiceManager());
|
||||||
|
|
||||||
|
// BackGround Task Controller
|
||||||
|
std::make_shared<BGTC_T>()->InstallAsService(system.ServiceManager());
|
||||||
|
std::make_shared<BGTC_SC>()->InstallAsService(system.ServiceManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Glue
|
16
src/core/hle/service/glue/glue.h
Normal file
16
src/core/hle/service/glue/glue.h
Normal file
@ -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
|
78
src/core/hle/service/glue/manager.cpp
Normal file
78
src/core/hle/service/glue/manager.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// 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 {
|
||||||
|
|
||||||
|
struct ARPManager::MapEntry {
|
||||||
|
ApplicationLaunchProperty launch;
|
||||||
|
std::vector<u8> control;
|
||||||
|
};
|
||||||
|
|
||||||
|
ARPManager::ARPManager() = default;
|
||||||
|
|
||||||
|
ARPManager::~ARPManager() = default;
|
||||||
|
|
||||||
|
ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const {
|
||||||
|
if (title_id == 0) {
|
||||||
|
return ERR_INVALID_PROCESS_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = entries.find(title_id);
|
||||||
|
if (iter == entries.end()) {
|
||||||
|
return ERR_NOT_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MakeResult<ApplicationLaunchProperty>(iter->second.launch);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
|
||||||
|
if (title_id == 0) {
|
||||||
|
return ERR_INVALID_PROCESS_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = entries.find(title_id);
|
||||||
|
if (iter == entries.end()) {
|
||||||
|
return ERR_NOT_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MakeResult<std::vector<u8>>(iter->second.control);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
|
||||||
|
std::vector<u8> control) {
|
||||||
|
if (title_id == 0) {
|
||||||
|
return ERR_INVALID_PROCESS_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = entries.find(title_id);
|
||||||
|
if (iter != entries.end()) {
|
||||||
|
return ERR_INVALID_ACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_INVALID_PROCESS_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = entries.find(title_id);
|
||||||
|
if (iter == entries.end()) {
|
||||||
|
return ERR_NOT_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.erase(iter);
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARPManager::ResetAll() {
|
||||||
|
entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Glue
|
63
src/core/hle/service/glue/manager.h
Normal file
63
src/core/hle/service/glue/manager.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2019 yuzu emulator team
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#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;
|
||||||
|
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<ApplicationLaunchProperty> 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<std::vector<u8>> 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<u8> 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;
|
||||||
|
std::map<u64, MapEntry> entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Glue
|
@ -19,7 +19,6 @@
|
|||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/aoc/aoc_u.h"
|
#include "core/hle/service/aoc/aoc_u.h"
|
||||||
#include "core/hle/service/apm/apm.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/audio/audio.h"
|
||||||
#include "core/hle/service/bcat/module.h"
|
#include "core/hle/service/bcat/module.h"
|
||||||
#include "core/hle/service/bpc/bpc.h"
|
#include "core/hle/service/bpc/bpc.h"
|
||||||
@ -33,6 +32,7 @@
|
|||||||
#include "core/hle/service/fgm/fgm.h"
|
#include "core/hle/service/fgm/fgm.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/friend/friend.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/grc/grc.h"
|
||||||
#include "core/hle/service/hid/hid.h"
|
#include "core/hle/service/hid/hid.h"
|
||||||
#include "core/hle/service/lbl/lbl.h"
|
#include "core/hle/service/lbl/lbl.h"
|
||||||
@ -207,7 +207,6 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
|
|||||||
AM::InstallInterfaces(*sm, nv_flinger);
|
AM::InstallInterfaces(*sm, nv_flinger);
|
||||||
AOC::InstallInterfaces(*sm);
|
AOC::InstallInterfaces(*sm);
|
||||||
APM::InstallInterfaces(*sm);
|
APM::InstallInterfaces(*sm);
|
||||||
ARP::InstallInterfaces(*sm);
|
|
||||||
Audio::InstallInterfaces(*sm);
|
Audio::InstallInterfaces(*sm);
|
||||||
BCAT::InstallInterfaces(*sm);
|
BCAT::InstallInterfaces(*sm);
|
||||||
BPC::InstallInterfaces(*sm);
|
BPC::InstallInterfaces(*sm);
|
||||||
@ -221,6 +220,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
|
|||||||
FGM::InstallInterfaces(*sm);
|
FGM::InstallInterfaces(*sm);
|
||||||
FileSystem::InstallInterfaces(*sm, vfs);
|
FileSystem::InstallInterfaces(*sm, vfs);
|
||||||
Friend::InstallInterfaces(*sm);
|
Friend::InstallInterfaces(*sm);
|
||||||
|
Glue::InstallInterfaces(system);
|
||||||
GRC::InstallInterfaces(*sm);
|
GRC::InstallInterfaces(*sm);
|
||||||
HID::InstallInterfaces(*sm);
|
HID::InstallInterfaces(*sm);
|
||||||
LBL::InstallInterfaces(*sm);
|
LBL::InstallInterfaces(*sm);
|
||||||
|
Loading…
Reference in New Issue
Block a user