mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-23 04:13:40 +00:00
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:
@@ -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,8 +353,9 @@ private:
|
||||
}
|
||||
|
||||
if (issued) {
|
||||
LOG_ERROR(Service_ARP,
|
||||
"Attempted to issue registrar, but registrar is already issued!");
|
||||
LOG_ERROR(
|
||||
Service_ARP,
|
||||
"Attempted to issue registrar, but registrar is already issued!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(Glue::ResultAlreadyBound);
|
||||
return;
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user