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 <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-09-05 15:43:59 +10:00
parent 50afaefffb
commit 69c3bc705c
3 changed files with 49 additions and 3 deletions

View File

@@ -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<u32>(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,