Merge branch 'glue-add-new-functions-services' into 'master'

hle/service: Implement missing Glue services for 20.0.0+ support

See merge request citron/rewrite!30
This commit is contained in:
Zephyron
2025-07-01 10:09:20 +00:00
7 changed files with 275 additions and 10 deletions

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
@@ -11,6 +12,7 @@
#include "core/hle/service/glue/errors.h"
#include "core/hle/service/glue/glue_manager.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/kernel_helpers.h"
namespace Service::Glue {
@@ -30,6 +32,103 @@ std::optional<u64> GetTitleIDForProcessID(Core::System& system, u64 process_id)
}
} // Anonymous namespace
class IUnregistrationNotifier final : public ServiceFramework<IUnregistrationNotifier> {
public:
explicit IUnregistrationNotifier(Core::System& system_)
: ServiceFramework{system_, "IUnregistrationNotifier"},
service_context{system_, "IUnregistrationNotifier"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IUnregistrationNotifier::GetReadableHandle, "GetReadableHandle"},
};
// clang-format on
RegisterHandlers(functions);
unregistration_event =
service_context.CreateEvent("IUnregistrationNotifier:UnregistrationEvent");
}
~IUnregistrationNotifier() {
service_context.CloseEvent(unregistration_event);
}
private:
void GetReadableHandle(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(unregistration_event->GetReadableEvent());
}
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* unregistration_event;
};
class IApplicationProcessPropertyUpdater final : public ServiceFramework<IApplicationProcessPropertyUpdater> {
public:
explicit IApplicationProcessPropertyUpdater(Core::System& system_)
: ServiceFramework{system_, "IApplicationProcessPropertyUpdater"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IApplicationProcessPropertyUpdater::Issue, "Issue"},
{1, &IApplicationProcessPropertyUpdater::SetApplicationProcessProperty, "SetApplicationProcessProperty"},
{2, &IApplicationProcessPropertyUpdater::DeleteApplicationProcessProperty, "DeleteApplicationProcessProperty"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void Issue(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SetApplicationProcessProperty(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void DeleteApplicationProcessProperty(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
class IApplicationCertificateUpdater final : public ServiceFramework<IApplicationCertificateUpdater> {
public:
explicit IApplicationCertificateUpdater(Core::System& system_)
: ServiceFramework{system_, "IApplicationCertificateUpdater"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IApplicationCertificateUpdater::Issue, "Issue"},
{1, &IApplicationCertificateUpdater::SetApplicationCertificate, "SetApplicationCertificate"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void Issue(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SetApplicationCertificate(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_)
: ServiceFramework{system_, "arp:r"}, manager{manager_} {
// clang-format off
@@ -38,12 +137,12 @@ ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_)
{1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"},
{2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"},
{3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"},
{4, nullptr, "GetApplicationInstanceUnregistrationNotifier"},
{5, nullptr, "ListApplicationInstanceId"},
{6, nullptr, "GetMicroApplicationInstanceId"},
{7, nullptr, "GetApplicationCertificate"},
{9998, nullptr, "GetPreomiaApplicationLaunchProperty"},
{9999, nullptr, "GetPreomiaApplicationControlProperty"},
{4, &ARP_R::GetApplicationInstanceUnregistrationNotifier, "GetApplicationInstanceUnregistrationNotifier"},
{5, &ARP_R::ListApplicationInstanceId, "ListApplicationInstanceId"},
{6, &ARP_R::GetMicroApplicationInstanceId, "GetMicroApplicationInstanceId"},
{7, &ARP_R::GetApplicationCertificate, "GetApplicationCertificate"},
{9998, &ARP_R::GetPreomiaApplicationLaunchProperty, "GetPreomiaApplicationLaunchProperty"},
{9999, &ARP_R::GetPreomiaApplicationControlProperty, "GetPreomiaApplicationControlProperty"},
};
// clang-format on
@@ -154,6 +253,72 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(HLERequestContext& ct
rb.Push(ResultSuccess);
}
void ARP_R::GetApplicationInstanceUnregistrationNotifier(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IUnregistrationNotifier>(std::make_shared<IUnregistrationNotifier>(system));
}
void ARP_R::ListApplicationInstanceId(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
// Return empty list for now
const std::vector<u64> application_instance_ids;
ctx.WriteBuffer(application_instance_ids);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(static_cast<s32>(application_instance_ids.size()));
}
void ARP_R::GetMicroApplicationInstanceId(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto process_id = rp.PopRaw<u64>();
LOG_WARNING(Service_ARP, "(STUBBED) called, process_id={:016X}", process_id);
// Same as GetApplicationInstanceId for now
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(Glue::ResultProcessIdNotRegistered);
return;
}
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(*title_id); // Use title_id as application instance id for now
}
void ARP_R::GetApplicationCertificate(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto application_instance_id = rp.PopRaw<u64>();
LOG_WARNING(Service_ARP, "(STUBBED) called, application_instance_id={:016X}", application_instance_id);
// Return empty certificate data for now
std::vector<u8> certificate_data(0x528, 0); // ApplicationCertificate is 0x528 bytes
ctx.WriteBuffer(certificate_data);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ARP_R::GetPreomiaApplicationLaunchProperty(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
// Same as GetApplicationLaunchProperty for compatibility
GetApplicationLaunchProperty(ctx);
}
void ARP_R::GetPreomiaApplicationControlProperty(HLERequestContext& ctx) {
LOG_WARNING(Service_ARP, "(STUBBED) called");
// Same as GetApplicationControlProperty for compatibility
GetApplicationControlProperty(ctx);
}
class IRegistrar final : public ServiceFramework<IRegistrar> {
friend class ARP_W;
@@ -188,7 +353,8 @@ private:
}
if (issued) {
LOG_ERROR(Service_ARP,
LOG_ERROR(
Service_ARP,
"Attempted to issue registrar, but registrar is already issued!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(Glue::ResultAlreadyBound);
@@ -251,8 +417,10 @@ ARP_W::ARP_W(Core::System& system_, ARPManager& manager_)
// clang-format off
static const FunctionInfo functions[] = {
{0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
{1, &ARP_W::UnregisterApplicationInstance , "UnregisterApplicationInstance "},
{2, nullptr, "AcquireUpdater"},
{1, &ARP_W::UnregisterApplicationInstance, "UnregisterApplicationInstance"}, // [10.0.0+] UnregisterApplicationInstance, [1.0.0-9.2.0] DeleteProperties
{2, &ARP_W::AcquireApplicationProcessPropertyUpdater, "AcquireApplicationProcessPropertyUpdater"}, // [15.0.0+] AcquireApplicationProcessPropertyUpdater, [10.0.0-14.1.2] AcquireUpdater
{3, &ARP_W::AcquireApplicationCertificateUpdater, "AcquireApplicationCertificateUpdater"}, // [15.0.0+]
{4, &ARP_W::RegisterApplicationControlProperty, "RegisterApplicationControlProperty"}, // [19.0.0+]
};
// clang-format on
@@ -305,4 +473,41 @@ void ARP_W::UnregisterApplicationInstance(HLERequestContext& ctx) {
rb.Push(manager.Unregister(*title_id));
}
void ARP_W::AcquireApplicationProcessPropertyUpdater(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto application_instance_id = rp.PopRaw<u64>();
LOG_WARNING(Service_ARP, "(STUBBED) called, application_instance_id={:016X}", application_instance_id);
// Return stub updater interface
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IApplicationProcessPropertyUpdater>(std::make_shared<IApplicationProcessPropertyUpdater>(system));
}
void ARP_W::AcquireApplicationCertificateUpdater(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto application_instance_id = rp.PopRaw<u64>();
LOG_WARNING(Service_ARP, "(STUBBED) called, application_instance_id={:016X}", application_instance_id);
// Return stub certificate updater interface
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IApplicationCertificateUpdater>(std::make_shared<IApplicationCertificateUpdater>(system));
}
void ARP_W::RegisterApplicationControlProperty(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto application_id = rp.PopRaw<u64>();
const auto control_property = ctx.ReadBufferCopy();
LOG_WARNING(Service_ARP, "(STUBBED) called, application_id={:016X}, control_property_size={}",
application_id, control_property.size());
// For now, just return success
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
} // namespace Service::Glue

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -20,6 +21,12 @@ private:
void GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx);
void GetApplicationControlProperty(HLERequestContext& ctx);
void GetApplicationControlPropertyWithApplicationId(HLERequestContext& ctx);
void GetApplicationInstanceUnregistrationNotifier(HLERequestContext& ctx);
void ListApplicationInstanceId(HLERequestContext& ctx);
void GetMicroApplicationInstanceId(HLERequestContext& ctx);
void GetApplicationCertificate(HLERequestContext& ctx);
void GetPreomiaApplicationLaunchProperty(HLERequestContext& ctx);
void GetPreomiaApplicationControlProperty(HLERequestContext& ctx);
const ARPManager& manager;
};
@@ -32,6 +39,9 @@ public:
private:
void AcquireRegistrar(HLERequestContext& ctx);
void UnregisterApplicationInstance(HLERequestContext& ctx);
void AcquireApplicationProcessPropertyUpdater(HLERequestContext& ctx);
void AcquireApplicationCertificateUpdater(HLERequestContext& ctx);
void RegisterApplicationControlProperty(HLERequestContext& ctx);
ARPManager& manager;
std::shared_ptr<IRegistrar> registrar;

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/glue/ectx.h"
@@ -59,4 +60,16 @@ void ECTX_AW::CreateContextRegistrar(HLERequestContext& ctx) {
rb.PushIpcInterface<IContextRegistrar>(std::make_shared<IContextRegistrar>(system));
}
ECTX_R::ECTX_R(Core::System& system_) : ServiceFramework{system_, "ectx:r"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "CommitContext"}, // Stub - context reading functionality
};
// clang-format on
RegisterHandlers(functions);
}
ECTX_R::~ECTX_R() = default;
} // namespace Service::Glue

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -20,4 +21,10 @@ private:
void CreateContextRegistrar(HLERequestContext& ctx);
};
class ECTX_R final : public ServiceFramework<ECTX_R> {
public:
explicit ECTX_R(Core::System& system_);
~ECTX_R() override;
};
} // namespace Service::Glue

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
@@ -30,6 +31,7 @@ void LoopProcess(Core::System& system) {
// Error Context
server_manager->RegisterNamedService("ectx:aw", std::make_shared<ECTX_AW>(system));
server_manager->RegisterNamedService("ectx:r", std::make_shared<ECTX_R>(system));
// Notification Services
server_manager->RegisterNamedService(

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
@@ -149,6 +150,9 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch
{106, nullptr, "GetFunctionBlackListVersion"},
{1000, nullptr, "LoadNgWordDataForPlatformRegionChina"},
{1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"},
{2010, D<&IPlatformServiceManager::Unknown2010>, "[S2] Unknown2010"}, // [S2] Switch 2
{2020, D<&IPlatformServiceManager::Unknown2020>, "[S2] Unknown2020"}, // [S2] Switch 2
{2100, D<&IPlatformServiceManager::OpenFont>, "[S2] OpenFont"}, // [S2] Switch 2 - Returns IFontService
};
// clang-format on
RegisterHandlers(functions);
@@ -270,4 +274,22 @@ Result IPlatformServiceManager::GetSharedFontInOrderOfPriority(
R_SUCCEED();
}
Result IPlatformServiceManager::Unknown2010(/* Unknown parameters */) {
LOG_WARNING(Service_NS, "(STUBBED) called - [S2] Switch 2 function");
R_SUCCEED();
}
Result IPlatformServiceManager::Unknown2020(/* Unknown parameters */) {
LOG_WARNING(Service_NS, "(STUBBED) called - [S2] Switch 2 function");
R_SUCCEED();
}
Result IPlatformServiceManager::OpenFont(/* Out<SharedPointer<IFontService>> out_font_service */) {
LOG_WARNING(Service_NS, "(STUBBED) called - [S2] OpenFont");
// Return stub font service for Switch 2
// TODO: Implement proper IFontService interface when needed
R_SUCCEED();
}
} // namespace Service::NS

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -70,6 +71,11 @@ private:
Out<bool> out_fonts_are_loaded, Out<u32> out_font_count,
Set::LanguageCode language_code);
// [S2] Switch 2 functions
Result Unknown2010(/* Unknown parameters */);
Result Unknown2020(/* Unknown parameters */);
Result OpenFont(/* Out<SharedPointer<IFontService>> out_font_service */);
struct Impl;
std::unique_ptr<Impl> impl;
};