Commit Graph
10207 Commits
Author SHA1 Message Date
xXPBSXxandClaude Sonnet 5.5 6b2be773aa docs(debt): say "several titles" in the storage image refusal entry
A fourth title reached the refusal on another GPU and OS (reported on the
PR), so the entry no longer names a count.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-22 03:01:05 +02:00
Yunus Shaikh 4d57a206c7 test(libc): check private collects against a region query under APS5_VERIFY_DIRECT_COLLECT
A private collect read from the allocation map makes no query, so it
can't see memory that code bypassing WindowsMappings changed inside a
recorded allocation. A page decommitted in place there is the case it
can't catch: GetWriteWatch still succeeds over it, so the collect
reports no writes where a query would have refused the range.

With APS5_VERIFY_DIRECT_COLLECT set, each such collect also queries its
span's regions, and Collect throws, naming the span and the switch, when
GetWriteWatch succeeded over memory that is no longer committed
private. ENVIRONMENT.md lists the switch.

windows_write_watch_verify_direct (the same test binary with
--verify-direct, the switch set) collects a recorded private allocation,
checks its write is still reported, decommits one page in place and
requires the next collect not to succeed. Without the check the collect
succeeds.

Adapts fable-void's 2760ad808.
2026-10-21 17:59:12 -07:00
Queuze 63be1c0cf5 feat(libSceNet): read reuse and broadcast flags 2026-10-21 21:56:25 -03:00
Ondra97 6f9b6bad1f feat(libSceFreeType): implement outline orientation 2026-10-22 02:41:48 +02:00
Yuri Olive 232cf9373b Merge remote-tracking branch 'origin/main' into feat/appinstutil-missing-exports
# Conflicts:
#	docs/dev/debt/libSceAppInstUtil.md
2026-10-21 21:38:15 -03:00
orezraeyandClaude Opus 5.5 da0ed3b5c3 Merge main into fix/net-utilities-measured-ps5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 21:25:51 -03:00
zaryabzip c13218735e feat(libSceNpTus): create TSS title contexts in the TUS context table
sceNpTssCreateNpTitleCtxA creates a context like sceNpTusCreateNpTitleCtxA,
and sceNpTssCreateNpTitleCtx checks its NpId and service label first, as
shadPS4 does; both share the TUS table, its 32-context limit and its
requests.
2026-10-22 05:25:26 +05:00
SwagandClaude Opus 5.5 ca32e706e8 feat(libSceLibreSsl): implement the per-thread error queue
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 20:15:46 -04:00
Queuze e8d989b6c0 feat(libSceNet): expose socket type and listen state 2026-10-21 21:11:41 -03:00
Queuze d805762120 feat(libSceNet): support SO_KEEPALIVE 2026-10-21 21:09:42 -03:00
Yunus Shaikh aea804d9fd fix(libkernel): getsockopt reads options of libSceNet sockets
setsockopt reaches a socket created with sceNetSocket through the option setter libSceNet registers, but getsockopt looked the descriptor up only among libkernel's own sockets and failed, so a title could set an option on such a socket through the BSD call and not read it back. libSceNet now registers an option getter with libkernel next to its setter, which answers through sceNetGetsockopt, so SO_RCVTIMEO and SO_SNDTIMEO come back as a struct timeval.
2026-10-21 16:57:33 -07:00
orezraeyandClaude Opus 5.5 3bcc0fd719 Merge main into fix/http-uri-parse-measured-ps5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 20:51:44 -03:00
orezraeyandClaude Opus 5.5 20ec66fe21 Merge main into fix/http-status-line-measured-ps5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 20:49:58 -03:00
orezraeyandClaude Opus 5.5 eed64b8c11 Merge main into fix/http-uri-copy-measured-ps5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 20:48:42 -03:00
orezraeyandClaude Opus 5.5 718a1de062 Merge main into fix/agcdriver-workload-registration-measured-ps5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 20:46:45 -03:00
Ondra97 58108841b1 fix(net): return empty connected TCP receives without waiting 2026-10-22 01:46:16 +02:00
Ondra97 2236680340 fix(libSceNpAuth): reject completion queries before request start 2026-10-22 01:41:08 +02:00
Yunus Shaikh 56b2a6393f fix(libkernel): keep another thread's block of a signal a running handler also blocks
A handler's blocks are now holds kept apart from the mask sigprocmask sets, and released when the handler returns, so a sigprocmask(SIG_BLOCK) from another thread meanwhile survives even for a signal in the handler's sa_mask. sigprocmask reports the holds; SIG_UNBLOCK of a held signal releases its hold and SIG_SETMASK, which longjmp uses, releases them all, while sigsuspend's own restore keeps them.
2026-10-21 16:39:02 -07:00
Yunus Shaikh 5daa8cb7a9 fix(agc): take a native multisample depth metadata fill noted again once its GPU write is recorded
A compute dispatch of the memory-value fill kernel is noted twice: the
dispatch path notes it from MatchMemoryValueFill before the fill runs
(Dispatch.cpp), and storeBufferFill notes it again after FillBuffer has
recorded its GPU write. On a native multisample depth target the second
note refused "overlapping native multisample depth clear transitions
are not implemented" for the HTILE, and the same refusal for the
separate stencil plane, so a compute fill of either one never reached
the sample.

A second note of a pending fill is now taken as the same fill when it
has the same pattern, the first note had no write note, and the one
write recorded over the range since the first note is a word fill of
the whole range with that pattern. That write's note becomes the fill's
note, and the first note's write generation is kept, so CPU writes
between the two notes are still refused. Two notes without that write
between them still refuse as overlapping (agc_driver_native_depth_stencil's
FillOverlap case, and a new stencil plane case). A memory-value fill
that falls back to CPU stores, with no host import of the range, is
still refused as overlapping.

Tested: agc_driver_native_depth_separate_stencil runs Ghost's sequence
with each fill noted, queued on the GPU and noted again, and samples
the cleared depth and stencil 0. A stencil plane fill noted twice
without a write between is refused. Without the change the second
note refuses "overlapping native multisample depth clear transitions
are not implemented".
2026-10-21 23:37:29 +00:00
Ondra97 f2173bba34 docs(ssl): remove obsolete terminated connection ownership claims 2026-10-22 01:35:46 +02:00
Yunus Shaikh 0e17d12ff4 fix(agc): take a native multisample depth metadata fill whose GPU write is recorded after the fill is noted
Ghost of Tsushima (PPSA02225) fills the HTILE (0x50000 bytes) and the
separate stencil plane (0x870000 bytes) of its two-sample D32S8 target
with pattern 0 before it samples the target. Both are DMA_DATA fills
larger than 64 KiB. PacketMemory notes a DMA_DATA fill before
storeBufferFill records it, so when the range has a host import the
fill's GPU write is recorded after NoteDepthMetadataFill took
LastWriteNote. The note was then 0, the fill did not count as the
queued fill, and the sample that followed in the same batch refused
"external GPU writes over native multisample depth are not implemented".
A compute fill is noted after its write is recorded and was not
affected.

When the noted fill had no write note yet, the sample now looks at the
writes recorded over the HTILE or the stencil plane since the fill was
noted. It takes the one write as the fill's note when that write is the
only one, covers the whole range, and is a word fill of the noted
pattern. A second write since, a different word or a fill of part of
the range keeps the refusal. Everything else is proven as before:
complete tracked stores, no CPU write since the fill, and the plane or
HTILE words holding the fill once it has landed.

The "native multisample depth metadata fill transition is not
implemented" stop reported on #6300 is set by a fill over the HTILE
that does not cover all of it, or by any HTILE fill when the target's
sampling never activated. Ghost's fill covers the whole HTILE, so its
target was most likely refused at creation, and on #6300 the fill's
message replaced that refusal. Refusals now keep the first one, so a
target refused at creation reports its creation reason after the fills.

Tested: agc_driver_native_depth_separate_stencil runs Ghost's sequence
(creation of a depth-only HTILE that is neither pipe-aligned nor
ITERATE_256 with a separate stencil plane, clear 0 and stencil 0, a
whole-HTILE fill of 0, a whole stencil plane fill of 0, then the first
sample) with the fill stored, queued after it is noted, and queued
before it is noted. Each one samples the cleared depth and passes only
the stencil reference 0. A later queued stencil write, a queued HTILE
fill of another word and a queued fill of part of the HTILE are
refused, and a target refused at creation keeps its refusal after the
fills. Without the change the fill queued after it is noted refuses
"external GPU writes over native multisample depth are not
implemented".
2026-10-21 23:31:37 +00:00
Yunus Shaikh 90d652a1ed fix(agc): take a whole-plane fill of a separate stencil plane as a stencil clear
Ghost of Tsushima (PPSA02225) fills the separate stencil plane of its
two-sample D32S8 target with pattern 0 (0x870000) before it samples the
target. Any write over the plane was refused ("guest writes over native
multisample depth are not implemented").

A DMA or compute fill that covers the whole plane of a target whose
depth-only HTILE leaves the stencil in the plane is now recorded like a
whole-HTILE fill. At the next sample it is proven the way a whole-HTILE
fill is: no CPU write since the fill, complete tracked stores since the
fill unless the fill is the plane's newest queued GPU write, and every
plane byte equal to the fill byte once it has landed. The host image's
stencil aspect is then cleared to that byte. A fill that covers part of
the plane is refused ("native multisample stencil plane partial fill
transition is not implemented"), and so is a pattern that is not one
byte, a fill over unwatched memory and a second fill before the plane
was proven.

Tested: agc_driver_native_depth_separate_stencil fills the HTILE, the
stencil plane, or both, after a draw replaced the stencil, on pipe-aligned
and non-pipe-aligned depth-only HTILE, and checks the sampled depth and
which stencil reference the next draw passes. Partial, two-byte-pattern,
unstored and CPU-raced plane fills are refused. Without the change the
first plane fill refuses "guest writes over native multisample depth are
not implemented", and the partial fill refuses with that text instead of
the partial fill one.
2026-10-21 23:16:37 +00:00
Yunus Shaikh 770a499ba9 fix(agc): import native multisample depth with a non-pipe-aligned depth-only HTILE when every word proves the same clear
Ghost of Tsushima (PPSA02225) samples a two-sample D32S8 1920x2160
target with a separate stencil plane and a depth-only HTILE that is
neither pipe-aligned nor ITERATE_256. The import required a pipe-aligned
HTILE.

Pipe alignment only decides where each tile's word sits in the HTILE.
When every word is the same and proves the clear, their order cannot
change what they prove, so a depth-only HTILE that is not pipe-aligned
is imported when all its words are one word proving the clear value.
A non-pipe-aligned HTILE whose words differ is refused ("native
multisample depth HTILE that is not pipe-aligned holds more than one
word"), and one that holds stencil state keeps the alignment refusal.
The range stays HtileMetadataBytes(extent): Ghost's whole-HTILE fill
covers exactly that, 0x50000 bytes for 1920x2160. ITERATE_256 is
already independent of the import (752cca10f).

Tested: agc_driver_native_depth_separate_stencil runs every separate
stencil case on a depth-only HTILE that is not pipe-aligned or
ITERATE_256 too, sampled through a descriptor naming that HTILE and one
without metadata; one differing word is refused. Without the change the
target refuses "native multisample depth initial import requires
pipe-aligned HTILE without VRS".
2026-10-21 23:09:29 +00:00
Yunus Shaikh 5be005ea13 fix(agc): sample a native multisample depth target through a descriptor without HTILE
Once its D32S8 target imports, The Grinch: Christmas Adventures
(PPSA07656) samples the depth plane through a T# with no metadata
(META_DATA_ADDRESS 0, not pipe-aligned) while the target has its HTILE.
The pipe/bank XOR and ITERATE_256 match. CheckResource required the
descriptor's metadata to be the target's HTILE and stopped the title
with "native multisample depth sampled metadata or XOR mismatch".

The host image keeps the depth decompressed, so a descriptor that reads
the plane without metadata reads the values a metadata-aware one does.
CheckResource now accepts a descriptor with no metadata at all beside
one naming the target's HTILE, when its address, format, XOR and
ITERATE_256 match. A descriptor with any other metadata keeps refusing.

Assumption: on hardware such a read returns the decompressed depth only
once the guest has expanded the plane (an in-place expand with
compression disabled). Main draws an in-place expand as an ordinary draw
that writes the depth attachment (DB_RENDER_CONTROL compress-disable bits
are not refused), over a host image that already holds the decompressed
depth, and has no out-of-place expand for multisampled planes. Nothing
here observes whether the guest expanded first; a title that samples the
plane unexpanded gets the decompressed values instead of the raw plane.

Tested: agc_driver_native_depth_separate_stencil samples the separate
stencil target through a descriptor without metadata, before and after
raster writes and after a depth-only HTILE fill, and gets the depth.
The same descriptor with another XOR and one naming other metadata are
refused. Without the change the first sample refuses "native
multisample depth sampled metadata or XOR mismatch".
2026-10-21 23:03:54 +00:00
MarcZX10 72316ad618 fix(libc): scale large finite cosh inputs 2026-10-21 22:59:10 +00:00
MarcZX10 c9b80f0304 feat(libc): implement _Cosh 2026-10-21 22:58:44 +00:00
Yunus Shaikh 7d6e968d6b fix(agc): import native multisample D32S8 targets with a separate cleared stencil plane
The Grinch: Christmas Adventures (PPSA07656) binds a two-sample
D32_SFLOAT_S8_UINT target whose stencil is a plane of its own and whose
HTILE is depth-only (DB_STENCIL_INFO.TILE_STENCIL_DISABLE), so HTILE
holds no stencil state. Every byte of that plane is the clear stencil
when the target is first bound. The import refused it ("native
multisample stencil import requires HTILE stencil metadata") and the
title stopped before its first present.

With a depth-only HTILE the stencil is uncompressed in its plane, so the
plane is its own proof: the import scans it once and accepts the target
when every byte equals DB_STENCIL_CLEAR. The depth keeps its HTILE clear
proof. The plane is already one of the import's ranges, accessible,
watched, generation-checked, guarded from guest publication and kept
apart from the depth and HTILE ranges, so a later CPU or GPU write to it
refuses sampling like a write to the depth. The host image is created
cleared to the clear stencil. The plane's base keeps the 64 KiB
alignment of the depth plane: both use SW_64KB_Z_X, the decode takes
the pipe/bank XOR from the depth base's low 16 bits and masks both bases.

A whole HTILE fill of such a target is proven for the depth only and
clears only the host depth: the stencil plane is untouched by the fill
and still proven unchanged since the import.

A stencil plane that is not all clear, a stencil in neither HTILE nor
its own plane, D16S8 and HTILE words that do not prove a clear keep
their refusals.

Tested: agc_driver_native_depth_separate_stencil imports a four-sample
target (two and eight where the device has them), samples the clear
depth, stencil-tests the clear stencil, and refills a depth-only HTILE
keeping a replaced stencil; one stencil byte not clear, a later stencil
write and an unwatched plane are refused. Without the import change the
target refuses "native multisample stencil import requires HTILE
stencil metadata"; without the fill change the refilled target loses
its stencil.
2026-10-21 22:55:19 +00:00
xXPBSXxandClaude Sonnet 5.5 c3bd7c5f63 docs(debt): note that a title call of sceAjmBatchJobSetResampleParametersEx agrees with the argument registers
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-22 00:53:16 +02:00
Yunus Shaikh 780aa44726 fix(libkernel): block every word of a signal handler's mask while it runs
main now keeps all four words of the guest signal mask. A handler's sa_mask above signal 32 is added too, and SIGKILL and SIGSTOP stay unblocked, as sigprocmask leaves them.
2026-10-21 15:52:34 -07:00
Yunus Shaikh e607ba1b41 Merge main into fix/libkernel-signal-handler-mask 2026-10-21 15:52:33 -07:00
Yunus Shaikh 8eba29aeef Merge main into fix/agc-msaa-d32s8-separate-stencil
Brings upstream main a6dcea927 under #6300's two commits.

Conflicts:
- DepthSurface.cpp prepareDepthSampling: #6300's stencil checks are kept
  and main's 752cca10f drops the ITERATE_256 requirement, so the HTILE
  check is main's line ("requires pipe-aligned HTILE without VRS").
- DepthSurface.cpp NoteHtileDepthClear and NoteDepthMetadataFill: #6300's
  clear and fill proofs are kept, written with main's first-refusal-wins
  DepthSamplingState::Refuse. After the proven whole-fill branch, the
  remaining fills take main's ForgetClear/NoteHtileClear and single-sample
  plane-fill paths.
- NativeMultisampleDepth.cpp CheckDepthTarget takes both #6300's
  ClearSource and main's iterate256, in that order; main's ITERATE_256
  call passes ClearSource::HtileDispatch.
- docs/dev/debt/libSceAgcDriver.md: one entry with #6300's stencil and
  fill text and main's ITERATE_256 text.

Adapted to main: main samples a native multisampled depth target
through a shadow copy that is refreshed when the sampled view is looked
up (1912045c1, 5a0a00f42). CheckStencilTarget recorded its raster and
the fetch in one batch, so the fetch read the shadow from before the
raster ("native depth-stencil sampled fetch lost a depth sample or a
stencil test outcome"). It now submits the raster, looks the view up
again and syncs before the fetch, as main's CheckDepthTarget does.
2026-10-21 22:49:54 +00:00
Yunus Shaikh ef49574f5a Merge main into fix/libscenet-inet-text-rules 2026-10-21 15:49:51 -07:00
qpavyros f9cd3ba1ce chore: merge current main into named shared memory 2026-10-22 01:44:14 +03:00
JJenkxandClaude Opus 5.5 7bfcc9d07a fix(audio-propagation): accept the public render output formats
sceAudioPropagationSourceRender accepted only format 2. The RenderInfo
word at +0x28 is SharpProspero's AudioPropagationOutputFormat: 0, 1 and 2
are first- to third-order Ambisonics (4, 9 and 16 float channels), 4 and 5
are 8 interleaved float channels. SAROS (PPSA07631) renders format 0.
Other values still throw, and an output that is not a whole number of
frames is rejected. Based on db91769497 from the JJenkx fork.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 18:33:49 -04:00
JJenkx f066bd61b3 feat(audio-propagation): track source-owned configurable path slots 2026-10-21 18:33:20 -04:00
JJenkxandClaude Opus 5.5 0bf6a77e8f fix(libScePlayGo): answer ids past the listed scenario chunks as unlisted
A dump with sce_sys/playgo-scenario.json and no chunk table lists chunks 0
to 999 through scePlayGoGetChunkId, but every other id was still reported as
installed. Destruction AllStars (PPSA02630) asks for chunk ids from 0 up until
one is rejected; because no id ever was, the walk wrapped the 16-bit id and
grew an array of 16-byte entries until a 5.18 GiB allocation failed about one
second into startup ("Ran out of memory allocating 5565054976 bytes").

An id outside the listed 0 to 999 is now answered like an unlisted id of a
dump without any playgo file: APS5_PLAYGO_UNLISTED_CHUNKS=installed or
=absent answers it, and without an answer the call throws naming the missing
chunk table.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 18:26:40 -04:00
Yunus Shaikh cfda40433c Merge main into fix/libkernel-udp-unreachable-port 2026-10-21 15:15:13 -07:00
JAB-devandClaude Sonnet 5.5 5e39fbda86 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into fix/audiopropagation-remove-inline-helpers
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-22 00:04:19 +02:00
JAB-devandClaude Sonnet 5.5 43a76fcdb5 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into fix/audioout2-speaker-info-errors
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-22 00:02:33 +02:00
hugodearaujo 25b7991c6a fix(netctl): start the library initialized, as titles find it
Titles register and check NetCtl callbacks without importing
sceNetCtlInit: libSceNetCtl is an internal sysmodule the system has
started before the title runs. 007 First Light traps at start-up when
sceNetCtlRegisterCallback answers NOT_INITIALIZED.
2026-10-21 18:56:52 -03:00
bluandClaude Opus 5.5 6287af9657 docs(libc): name the num_get<char> vtable's slots from the console
mazen320 mapped the relocated slots of KfcTPbeaOqg in the console's
libSceLibcInternal: offset-to-top, typeinfo, the two destructors,
locale::facet::_Incref and _Decref, and the eleven do_get. The debt
entry now says so instead of leaving the two extra entries unknown.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 14:56:43 -07:00
Yunus Shaikh 7d6c475b95 fix(agc): an address-based build evicts idle imports instead of copying past the cap
AcquireRegistered imports every registered GPU range whole without
eviction, so a range the import budget refuses and no mirror serves is
copied on every build, and copies past APS5_ADDRESS_COPY_MAX_MIB (64 MiB
by default) abort the process. Resident Evil Village (PPSA01556) aborts
this way on a 768 MiB heap 8 MiB over the budget.

The pass now retries such a range's import with eviction when, and only
when, copying it would take the build's copies past the cap, that is when
the build would abort otherwise. Imports the build already looked up or
made count as held (buildFloor) and are never evicted; the retire moves
the import epoch, which Upload and the address-space cache already honour,
and a retired import lives through the hold. Every other build still
imports without eviction, so the set of imported ranges stays as stable
across builds as before. A rate-limited [gpu] line reports such an import.

The copy reason of a heap now names what refused it (an import over the
host import budget, a heap not fully write-watched, a refused heap mirror)
instead of "outside the write-watched arena" for every heap.
2026-10-21 21:55:04 +00:00
MarcZX10 173603428d feat(libSceFontFt): report TrueType GX support 2026-10-21 21:44:31 +00:00
Chikimaro 6e2fbcda84 Merge main into feat/libscenetctl-nptoolkit-callbacks
Resolve the conflicts with main's libSceNetCtl initialization and
callback validation: the shared check now returns NOT_INITIALIZED before
sceNetCtlInit, as sceNetCtlCheckCallback does on main, so the NpToolkit
check does too; sceNetCtlTerm stays the no-op main measured; the NpToolkit
register and unregister keep their implementations with main's parameter
names. The NpToolkit entry joins main's rewritten debt file, and
GuestNetCtl checks the three before initialization.
2026-10-21 21:39:23 +00:00
frankea 41d551eb60 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into ps5-measured-1340
# Conflicts:
#	core/libs/prx/libSceSystemService/Export.cpp
2026-10-21 17:37:31 -04:00
Get-fix f04d16d702 feat: PS4 NpTrophy, save data v1, NpWebApi offline and Limbo's other imports
NpTrophy reads the trophy count and icons from the title's trophy
package (names are encrypted and stay not implemented), PS4 v1 save data
calls wrap the native v2/v3 ones, and NpWebApi library contexts, handles
and push event filters work offline (service filters fail without a
signed-in user). libSceAjm is built from the libSceAjm.native sources
for PS4 titles. Limbo's (CUSA01664) remaining PS4 imports, including the
synchronous PS4 TUS calls and the Facebook dialog calls next to the
existing libraries, are exported as not implemented.
2026-10-22 00:35:09 +03:00
boykopovar a6dcea9279 Merge pull request #9137 from boykopovar/fix/funcs-abi-debt-2026-10-20
fix(libs): libs funcs abi debt 2026 10 20
Corrected signatures or behaviour of 1,702 existing exported functions across 96 libraries. Added 85 typed export wrappers. Unimplemented functions retain NotImplemented_nid_no_patch(__func__).
2026-10-22 00:32:11 +03:00
David 375b53d918 refactor(libkernel): move pselect into libkernel
The PS5 3.20 export lists have pselect in libkernel as well as
libkernel_sys, and on Windows a libkernel import never reaches
libkernel_sys. The implementation moves unchanged to
libkernel/Socket/src/Pselect.cpp, beside select.
2026-10-21 22:30:43 +01:00
David 642c0d56ac docs(debt): list the ktimer calls under Functional 2026-10-21 22:27:24 +01:00
David 7820a5353a refactor(libkernel): move the ktimer calls into libkernel
The PS5 3.20 export lists have ktimer_* in libkernel as well as
libkernel_sys, and on Windows a libkernel import never reaches
libkernel_sys. The implementation moves unchanged to
libkernel/Time/Ktimer.cpp.
2026-10-21 22:22:16 +01:00