mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 10:43:33 +00:00
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:
@@ -1,6 +1,12 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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.h"
|
||||||
#include "core/hle/kernel/svc_results.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,
|
Result CreateInterruptEvent(Core::System& system, Handle* out, int32_t interrupt_id,
|
||||||
InterruptType type) {
|
InterruptType type) {
|
||||||
UNIMPLEMENTED();
|
LOG_DEBUG(Kernel_SVC, "called, interrupt_id={}, type={}", interrupt_id, static_cast<u32>(type));
|
||||||
R_THROW(ResultNotImplemented);
|
|
||||||
|
// 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,
|
Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id,
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_
|
|||||||
{181, nullptr, "UpgradeLaunchRequiredVersion"},
|
{181, nullptr, "UpgradeLaunchRequiredVersion"},
|
||||||
{190, nullptr, "SendServerMaintenanceOverlayNotification"},
|
{190, nullptr, "SendServerMaintenanceOverlayNotification"},
|
||||||
{200, nullptr, "GetLastApplicationExitReason"},
|
{200, nullptr, "GetLastApplicationExitReason"},
|
||||||
{210, nullptr, "GetLaunchRequiredVersionUpgrade"},
|
{210, D<&IApplicationFunctions::GetLaunchRequiredVersionUpgrade>, "GetLaunchRequiredVersionUpgrade"},
|
||||||
{211, nullptr, "GetLaunchRequiredVersionUpgradeStatus"},
|
{211, nullptr, "GetLaunchRequiredVersionUpgradeStatus"},
|
||||||
{300, nullptr, "RequestToLaunchApplication"},
|
{300, nullptr, "RequestToLaunchApplication"},
|
||||||
{301, nullptr, "RequestToLaunchApplicationWithUserAndArguments"},
|
{301, nullptr, "RequestToLaunchApplicationWithUserAndArguments"},
|
||||||
@@ -508,4 +508,13 @@ Result IApplicationFunctions::PrepareForJit() {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetLaunchRequiredVersionUpgrade(OutCopyHandle<Kernel::KReadableEvent> 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
|
} // namespace Service::AM
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ private:
|
|||||||
Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
Result PrepareForJit();
|
Result PrepareForJit();
|
||||||
|
Result GetLaunchRequiredVersionUpgrade(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
|
||||||
const std::shared_ptr<Applet> m_applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user