Undrained triggers queued without limit and AddEvent copied the whole queue, so a flip/vblank flood could exhaust the host heap while guest memory stayed free. Keep the armed event plus at most 64 queued events per registration, dropping the oldest queued event past the cap and keeping the latest payload; an AddEvent carrying more keeps the latest 64. Drained bursts report as before.
Return the event's data when EV_ERROR is set in its flags and 0 otherwise, as KytyPS5 does and as FreeBSD 11 kevent stores the errno of a failed change. A null event throws like the other accessors.
A user event added with sceKernelAddUserEvent stays triggered until it is
deleted. The collection loop kept re-emitting it until the caller's event
buffer was full, so a wait with num > 1 returned the same event num times.
Like kevent, each event is now reported at most once per call; distinct
queued completions of one event are still delivered in order.
(cherry picked from commit db28ebbb7f)
sceKernelGetEventId, sceKernelGetEventFilter, sceKernelGetEventFflags,
sceKernelGetEventData and sceKernelGetEventUserData return the matching
field of the KernelEvent filled by sceKernelWaitEqueue and throw on a
null event. sceKernelGetEventError still throws NotImplemented.
Co-Authored-By: Claude Opus 5.5 <[email protected]>