From 69c3bc705c34fd1f853d4c61fb5626b80587f5df Mon Sep 17 00:00:00 2001 From: Zephyron Date: Fri, 5 Sep 2025 15:43:59 +1000 Subject: [PATCH] feat: implement missing kernel event handle and service function - Implement CreateInterruptEvent SVC function to resolve panic - Add proper resource management with KScopedResourceReservation - Use regular KEvent as placeholder for interrupt events - Add proper cleanup with SCOPE_EXIT - Include debug logging for troubleshooting - Implement GetLaunchRequiredVersionUpgrade in IApplicationFunctions service - Fix "Unknown / unimplemented function" error for command 210 - Return event handle instead of boolean to match Nintendo Switch API - Use state_changed_event as placeholder until dedicated event is implemented - Add function declaration to header file Tested with Hollow Knight: Silksong - successfully boots. Signed-off-by: Zephyron --- .../hle/kernel/svc/svc_interrupt_event.cpp | 40 ++++++++++++++++++- .../am/service/application_functions.cpp | 11 ++++- .../am/service/application_functions.h | 1 + 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/core/hle/kernel/svc/svc_interrupt_event.cpp b/src/core/hle/kernel/svc/svc_interrupt_event.cpp index 768b30a1f..07c02211b 100644 --- a/src/core/hle/kernel/svc/svc_interrupt_event.cpp +++ b/src/core/hle/kernel/svc/svc_interrupt_event.cpp @@ -1,6 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/logging/log.h" +#include "common/scope_exit.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc_results.h" @@ -8,8 +14,38 @@ namespace Kernel::Svc { Result CreateInterruptEvent(Core::System& system, Handle* out, int32_t interrupt_id, InterruptType type) { - UNIMPLEMENTED(); - R_THROW(ResultNotImplemented); + LOG_DEBUG(Kernel_SVC, "called, interrupt_id={}, type={}", interrupt_id, static_cast(type)); + + // Get the kernel reference and handle table. + auto& kernel = system.Kernel(); + auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); + + // Reserve a new event from the process resource limit + KScopedResourceReservation event_reservation(GetCurrentProcessPointer(kernel), + LimitableResource::EventCountMax); + R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); + + // Create a new event (for now, we'll use a regular event as interrupt events aren't fully implemented) + KEvent* event = KEvent::Create(kernel); + R_UNLESS(event != nullptr, ResultOutOfResource); + + // Initialize the event. + event->Initialize(GetCurrentProcessPointer(kernel)); + + // Commit the thread reservation. + event_reservation.Commit(); + + // Ensure that we clean up the event (and its only references are handle table) on function end. + SCOPE_EXIT { + event->GetReadableEvent().Close(); + event->Close(); + }; + + // Register the event. + KEvent::Register(kernel, event); + + // Add the readable event to the handle table. + R_RETURN(handle_table.Add(out, std::addressof(event->GetReadableEvent()))); } Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp index fe4d250a3..0d005dec5 100644 --- a/src/core/hle/service/am/service/application_functions.cpp +++ b/src/core/hle/service/am/service/application_functions.cpp @@ -86,7 +86,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ {181, nullptr, "UpgradeLaunchRequiredVersion"}, {190, nullptr, "SendServerMaintenanceOverlayNotification"}, {200, nullptr, "GetLastApplicationExitReason"}, - {210, nullptr, "GetLaunchRequiredVersionUpgrade"}, + {210, D<&IApplicationFunctions::GetLaunchRequiredVersionUpgrade>, "GetLaunchRequiredVersionUpgrade"}, {211, nullptr, "GetLaunchRequiredVersionUpgradeStatus"}, {300, nullptr, "RequestToLaunchApplication"}, {301, nullptr, "RequestToLaunchApplicationWithUserAndArguments"}, @@ -508,4 +508,13 @@ Result IApplicationFunctions::PrepareForJit() { R_SUCCEED(); } +Result IApplicationFunctions::GetLaunchRequiredVersionUpgrade(OutCopyHandle out_event) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO(ZEP): Add a dedicated launch_required_version_upgrade_event when implemented + *out_event = m_applet->state_changed_event.GetHandle(); + + R_SUCCEED(); +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h index 10025a152..0da5e631b 100644 --- a/src/core/hle/service/am/service/application_functions.h +++ b/src/core/hle/service/am/service/application_functions.h @@ -77,6 +77,7 @@ private: Result GetNotificationStorageChannelEvent(OutCopyHandle out_event); Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle out_event); Result PrepareForJit(); + Result GetLaunchRequiredVersionUpgrade(OutCopyHandle out_event); const std::shared_ptr m_applet; };