Commit Graph
5577 Commits
Author SHA1 Message Date
boykopovar 13c648bebb feat(libkernel): impl file, time, process, signal for posix 2026-09-27 11:43:38 +03:00
boykopovar 62c16792ff feat(libkernel): impl pthread condition variables + posix thread attribute queries 2026-09-27 11:43:37 +03:00
boykopovar a709e220f2 feat(libkernel): implement posix mutex locking and timed waits 2026-09-27 11:43:37 +03:00
boykopovar ae2e5cba7e feat(libc): implement heap trace info 2026-09-27 11:43:36 +03:00
boykopovar c9cb3cae39 feat(libkernel): implement disabled address sanitizer state + replacement tables 2026-09-27 11:43:36 +03:00
boykopovar 9fd6816356 fix(libkernel): store rtld allocator table separately from application heap 2026-09-27 11:43:35 +03:00
boykopovar dbb56adcf6 feat(libkernel): implement process, cpu, uuid, gpi, gpo, sync funcs 2026-09-27 11:43:34 +03:00
boykopovar 55e1c4a238 feat(libkernel): implement application heap and thread atexit registration 2026-09-27 11:43:33 +03:00
boykopovar 2e654e4f89 feat(relinker): scan sce modules for syscalls 2026-09-27 11:43:33 +03:00
boykopovar 630cb018c0 feat(relinker): add --skip-sce-module flag 2026-09-27 11:43:32 +03:00
boykopovar 5887c8d6e2 feat(libkernel): add memory segment, backtrace, heap error report definitions 2026-09-27 11:43:32 +03:00
boykopovar 40101471ee feat(libkernel): add new posix, pthread, semaphore, process funcs definitions 2026-09-27 11:43:31 +03:00
boykopovar 0783e369da feat(libkernel): add definitions for standard guest libc imports 2026-09-27 11:43:31 +03:00
boykopovar 337e763597 fix(relinker): support operand-size prefixes on fs:[0] access 2026-09-27 11:43:30 +03:00
boykopovar 2cc34985c0 fix(codegen): decode int imm8 instruction length correctly 2026-09-27 11:43:30 +03:00
boykopovar fa10c6d7eb fix(relinker): scan reachable code for windows guest tls accesses 2026-09-27 11:43:30 +03:00
boykopovar 6b2db1d8a8 fix(relinker): support windows guest tls relocations and accesses 2026-09-27 11:43:29 +03:00
boykopovar 0c6765e6a6 fix(relinker): ignore non-loadable SCE segments outside file bounds 2026-09-27 11:43:29 +03:00
boykopovar 1379ec001b feat(relinker): add native guest module loading with export priority 2026-09-27 11:43:28 +03:00
boykopovar fce5889d91 Merge pull request #21 from obelisk-complex/test/wire-up-exception-runtime-test
test: wire up the orphaned exception runtime test
- `core/libs/CMakeLists.txt`: registered `ExceptionRuntime.cpp` as `exception_runtime_tests`/`exception_runtime`, following the existing `Guest*.cpp` test pattern, linked against `libc`.
2026-09-27 11:39:23 +03:00
boykopovar 228802b7f5 Merge pull request #23 from obelisk-complex/test/fix-agc-driver-test-bitrot
test(agc): fix and re-enable 3 of 8 bitrotted AGC driver tests
- `agc_driver_graphics_tests`: fixed the link failure by adding the three missing source files and linking `shader_recompiler_agc_driver`. Still fails at runtime against stale assertions accumulated over many commits of not being built (an expected "not implemented" message that texture support since removed, and a sampler test fixture value that no longer fits its 12-bit field). Left `EXCLUDE_FROM_ALL`; fixing the assertions is a separate pass across the whole 1150-line test file, not a build fix.
- `agc_driver_recompiler_tests`: root-caused but not fixed. It needs `COMPUTE_NUM_THREAD_X` set, and its pass condition checks for a "not implemented" stub error that no longer exists now that the real recompiler is in. Restoring its original intent needs a shader deliberately built to fail recompilation, which is a design decision, not something this PR should decide unilaterally. Left `EXCLUDE_FROM_ALL`.
- `agc_driver_tests`, `agc_shader_memory_tests`, `agc_driver_flip_tests` and `agc_driver_pm4_tests` already passed; registered them with `add_test` so none of the four can bitrot silently again.
2026-09-27 11:34:45 +03:00
boykopovar 7894745fba Merge pull request #15 from obelisk-complex/fix/sscanf-signedness-and-substr-copy
fix: correct sscanf %x signedness and avoid a substr copy
- `core/libs/prx/libSceSysmodule/Export.cpp`: `devMajor`/`devMinor` now `unsigned int`.
- `core/libs/nid/include/nid/NidPatcherUtils.hpp`: two `substr(0, n)` calls replaced with `resize(n)`.
2026-09-27 11:30:50 +03:00
QDarkRexandClaude Opus 5.5 2081071237 refactor(kernel): share SCE kernel error codes through KernelErrors.hpp
Kernel error codes were redeclared per file under three prefixes
(SCE_KERNEL_ERROR_, EQUEUE_ERROR_, KERNEL_SEMA_ERROR_), which let wrong
values go unnoticed. Define them once as 0x80020000 | errno for errno
1..94 and use the SCE_KERNEL_ERROR_ names everywhere. Values are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 13:32:28 +07:00
QDarkRexandClaude Opus 5.5 ac0f8af228 fix(kernel): use SCE kernel error codes in equeue, direct memory and mutex
SCE kernel errors are 0x80020000 plus the FreeBSD errno. The equeue and
direct memory constants used an unrelated 0x8001xxxx range with mismatched
errno values (e.g. ETIMEDOUT was 0x80010023), so a guest checking
sceKernelWaitEqueue for SCE_KERNEL_ERROR_ETIMEDOUT saw an unexpected error.
SCE_KERNEL_ERROR_EDEADLK in Mutex.cpp held the EAGAIN value.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 13:27:23 +07:00
QDarkRexandClaude Opus 5.5 97cae1458e fix(kernel): use SCE kernel error codes in equeue, direct memory and mutex
SCE kernel errors are 0x80020000 plus the FreeBSD errno. The equeue and
direct memory constants used an unrelated 0x8001xxxx range with mismatched
errno values (e.g. ETIMEDOUT was 0x80010023), so a guest checking
sceKernelWaitEqueue for SCE_KERNEL_ERROR_ETIMEDOUT saw an unexpected error.
SCE_KERNEL_ERROR_EDEADLK in Mutex.cpp held the EAGAIN value.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 13:22:01 +07:00
QDarkRexandClaude Opus 5.5 be127fd0f1 feat(kernel): implement sceKernelDeleteSema
Waiters are woken with SCE_KERNEL_ERROR_EACCES and the semaphore is freed
once they have left.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 12:38:59 +07:00
QDarkRexandClaude Opus 5.5 15b749c2ba fix(kernel): return 64-bit offsets from sceKernelLseek
The SCE ABI returns off_t; offsets above INT_MAX threw instead of being returned.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 12:38:59 +07:00
QDarkRexandClaude Opus 5.5 76b7f998f5 fix(kernel): give every thread a pthread handle and keep mutex ownership consistent
- scePthreadSelf returned null on Linux and for threads not created by
  scePthreadCreate (including the main thread); such threads now get a
  lazily adopted, non-joinable handle
- scePthreadExit on Linux skipped FinishThread, losing the join value
- detached threads on Linux were never freed; use the reference count
  already used on Windows
- unlocking a recursive mutex from a non-owner was undefined behaviour;
  return SCE_KERNEL_ERROR_EPERM
- scePthreadCondTimedwait did not restore the mutex owner after waking,
  so another thread locking during the wait made the waiter's unlock
  fail with EPERM and left the mutex locked forever
- SCE_KERNEL_ERROR_ETIMEDOUT in Cond.cpp was 0x80020062 instead of 0x8002003C

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 12:38:59 +07:00
QDarkRexandClaude Opus 5.5 908befe81d feat(relinker): add --windows-gui to emit a GUI subsystem executable
Generated executables always used the console subsystem and opened a
console window on launch. The opt-in flag writes IMAGE_SUBSYSTEM_WINDOWS_GUI.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 12:24:15 +07:00
QDarkRexandClaude Opus 5.5 7ac1198e74 fix(audioout): reject zero sample count and frequency in sceAudioOutOpen
A zero frequency was stored and later used as a divisor when computing
the output block duration. Return SCE_AUDIO_OUT_ERROR_INVALID_SIZE and
SCE_AUDIO_OUT_ERROR_INVALID_SAMPLE_FREQ instead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 12:24:15 +07:00
QDarkRexandClaude Opus 5.5 f8485ce6a6 fix(relinker): return unpacked exit status and wait for a single Enter in autorun
std::system returns a wait status on POSIX, so returning it from main
truncated a guest exit code of 1 (status 256) to 0. The prompt also
required pressing Enter twice because cin.get followed cin.ignore.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 12:24:14 +07:00
devilismyfriendandClaude Fable 5.1 29b4601564 perf(agc): dispatch and draw recipes, data-only cache hits, unit shadows, bindless image tables
Dispatch cache with per-key value variants and data-only hits (flat-SRT leaves the recompiler
proves pure are refreshed into the resource template instead of re-captured), dispatch and draw
recipes replaying a proven prepare, register-keyed draw entries, template data refresh, unit
shadows in device-local slabs, 64 KiB block-unit storage tracking with windowed detile, DCC
clear-key proofs, per-class GPU timing, a CPU copy path with batch read tracking, present slot
ring, rate-limited reaps and lazy completion counting, plan-failure and poisoned source memos,
bindless image tables (runtime-indexed descriptor arrays from a CPU-read table) so the
per-frame compute program that failed its plan now compiles. Worker affinity opt-in, per-draw
logs behind APS5_TRACE_DRAWS, wait-timeout reports include the recorder's view of the label.
Fixes a use-after-free behind BDA-miss dispatch snapshots and the CPU-write stamp of
UnchangedSinceCollected. Intro-video stage: 154 -> ~500 presents per 10 s at 4K.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-26 19:00:40 -07:00
devilismyfriendandClaude Fable 5.1 01c4e3edf7 feat(relinker): --to-intel lowers SSE4a sites to same-length jumps into an appended stub section
EXTRQ, INSERTQ, MOVNTSS and MOVNTSD are rewritten at relink time: same-length in-place forms
where they exist, otherwise a jmp rel32 into an appended executable section holding a
scratch-free SSE body and a jump back, so no code shifts and no RIP-relative or jump-table
operand needs adjusting. Decoder fixes for POPCNT and 0F BB (BTC), codegen and elfpatcher
tests, README and technical-debt notes. The runtime illegal-instruction trap stays as a
fallback.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-26 19:00:39 -07:00
devilismyfriendandClaude Fable 5.1 af3c2024ed feat(runtime): timed waits, sync primitive fixes, heap and RTC fixes, unattended-run switches
libkernel: a TimedWait service for condition variables, semaphores, event flags, rwlocks and
equeues with the scheduler tick; mutex/cond/sem corner cases the title hits; job worker
affinity is opt-in (APS5_JOB_AFFINITY). libc: calloc/realloc heap slot swap, a default
terminate handler with a backtrace, CPU topology helper. libSceRtc export fixes with tests.
libSceVideoOut: APS5_NO_PAD_INPUT ignores host input for unattended measurements,
APS5_FLIP_QUEUE_WAIT keeps a stalled process alive for a debugger. ApplicationHeap and
GuestRtc tests wired into the test build.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-26 19:00:39 -07:00
ownerandClaude Sonnet 5 f4ff3be07f test(agc): fix and re-enable 3 of 8 bitrotted AGC driver tests
These EXCLUDE_FROM_ALL targets weren't registered with add_test, so
they silently bitrotted with no CI/ctest visibility:

- agc_driver_graphics_tests: fixed a link failure (Draw.cpp, Pipeline.cpp
  and GraphicsPipelineCache.cpp were never added to the target's sources
  when the test started calling into them). Still fails at runtime against
  several stale assertions (a removed "not implemented" error message, a
  sampler fixture value that doesn't fit its bitfield) accumulated over
  many commits of not being built; left EXCLUDE_FROM_ALL pending an
  assertion-maintenance pass.
- agc_driver_recompiler_tests: root-caused (missing COMPUTE_NUM_THREAD_X
  register setup, plus a pass condition checking for a stub error message
  that no longer exists now that the real recompiler is implemented) but
  left unfixed and EXCLUDE_FROM_ALL — restoring its original intent needs
  a shader deliberately built to fail recompilation, a design decision.

agc_driver_tests, agc_shader_memory_tests, agc_driver_flip_tests and
agc_driver_pm4_tests already passed; registered them with add_test too
so none of the five can bitrot silently again.

agc_driver_bda_device_tests: dropped from this commit's scope. Upstream
PR #20 already proposes the same one-line BdaContracts.cpp fix (matching
the runtime message's "signature" text), so BdaContracts.cpp is left
untouched here to avoid duplicating that fix. The test target stays
defined (EXCLUDE_FROM_ALL, still buildable by name) but is no longer
registered with add_test until #20 or an equivalent fix lands.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-26 14:49:14 -06:00
ownerandClaude Sonnet 5 d3a1b89be3 test: wire up the orphaned exception runtime test
ExceptionRuntime.cpp existed complete and working but was never
registered in CMakeLists.txt, so it never built or ran. Wired it in
following the existing Guest*.cpp test pattern.

The other three orphaned test files (PthreadStart.cpp, FileStreams.cpp,
Formatting.cpp) were left out: each has genuine bitrot against current
code (a moved header, fseek returning errno instead of throwing on an
invalid whence, and vsnprintf's expected va_list mutation) that needs a
source-level decision, not a CMake wiring fix.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-26 14:36:33 -06:00
ownerandClaude Sonnet 5 63209b584f fix: correct sscanf %x signedness and avoid a substr copy
libSceSysmodule/Export.cpp parsed /proc/self/maps device major/minor
numbers into signed int with a %x format, which is undefined behaviour
per the C standard even though it happened to work on this target;
switched to unsigned int to match the format specifier.

NidPatcherUtils.hpp's StripNidPostfix built a truncated copy with
substr(0, n) where the prefix is already the string itself; resize(n)
does the same truncation without the extra allocation and copy.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-26 14:11:50 -06:00
ownerandClaude Sonnet 5 d01be2b0e9 fix(exceptions): alias uncaught_exception(s) to their purpose-built wrappers
Exports.cpp aliased the real std::uncaught_exception(s) mangled names
directly to __cxa_uncaught_exception(s)_nid_postfix instead of the
existing _ZSt18uncaught_exceptionv_nid_postfix/_ZSt19uncaught_exceptionsv_nid_postfix
wrappers, leaving the latter as dead code and breaking the file's own
bare-name -> matching-nid_postfix alias pattern (caught by fleet QA
review, no functional impact since it's a raw symbol alias and both
sides return in the same register).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-26 13:39:10 -06:00
ownerandClaude Sonnet 5 a4c519b262 fix(exceptions): interpose libstdc++ ABI on Linux so the project's own unwinder drives it
On native Linux these PRX shared libraries and their test executables
dynamically link real libstdc++/libgcc, so a plain throw went through the
system's __cxa_throw/_Unwind_RaiseException. That still invoked this
project's own __gxx_personality_v0_nid_postfix (the CIE's personality
pointer is a raw function address, agnostic to which unwinder is walking
the stack), but handed it libgcc's incompatible private _Unwind_Context
layout, corrupting every field Personality.cpp reads and aborting with no
exception message.

Fix: OwnPersonality() now recognises the bare __gxx_personality_v0 wrapper
on Linux too (previously Windows-only), and Exports.cpp exports the real
ABI names (__cxa_throw, __cxa_begin_catch/end_catch, __cxa_rethrow,
__cxa_allocate/free_exception, __cxa_call_terminate, __cxa_get_exception_ptr,
__cxa_current_exception_type, __cxa_init_primary_exception, the std::
terminate/uncaught_exception(s) mangled names, and the core _Unwind_*
entry points) via the existing GCC_GLOBAL_ALIAS assembler-alias mechanism,
so ELF symbol interposition makes this project's own implementation win
process-wide over libgcc_s.so.1/libstdc++.so.6. __cxa_init_primary_exception
is newly implemented; GCC 13's inline std::make_exception_ptr needs it and
nothing provided it before.

Fixes 7 previously-aborting tests: guest_rendering_wait, guest_buffer_reuse,
guest_shader_link, guest_system_exit_parameters, guest_once, guest_memory,
guest_search.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-26 13:39:10 -06:00
boykopovar 1a0ebbc849 Merge pull request #9 from Pacuka/feat/scertc
feat(rtc): implement libSceRtc date and tick functions
- Ticks count microseconds since 0001-01-01 00:00:00 in the proleptic Gregorian calendar, up to 9999-12-31 23:59:59.999999. `sceRtcGetTickResolution` returns 1000000.
- Validation (`sceRtcCheckValid`, `sceRtcIsLeapYear`, `sceRtcGetDayOfWeek`) returns the matching `SCE_RTC_ERROR_INVALID_*` code (`0x80B50002`–`0x80B5000E`).
- Conversions: `sceRtcGetTick`/`SetTick`, `GetTime_t`/`SetTime_t`, `GetWin32FileTime`/`SetWin32FileTime`.
- Current time: `sceRtcGetCurrentTick`, `GetCurrentClock`, `GetCurrentClockLocalTime`. `sceRtcGetCurrentNetworkTick` uses the host clock.
- UTC and local time conversion through the host time zone.
- `sceRtcFormatRFC3339` (`YYYY-MM-DDThh:mm:ss.cc` plus `Z` or `±hh:mm`) and `sceRtcParseRFC3339`.
- Tick arithmetic (`sceRtcTickAdd*`) rejects results outside the valid range with `SCE_RTC_ERROR_INVALID_VALUE`.
- New exports: `sceRtcGetDaysInMonth`, `sceRtcTickAddMonths` and `sceRtcTickAddYears`. The last two clamp the day to the end of the target month (2024-01-31 + 1 month = 2024-02-29).
2026-09-26 13:41:16 +03:00
PacukaandClaude Opus 5.5 c0508a7f5f feat(rtc): implement libSceRtc date and tick functions
Ticks count microseconds since 0001-01-01 in the proleptic Gregorian
calendar, up to 9999-12-31 23:59:59.999999. Implement validation, tick
and date conversion, time_t and Win32 FILETIME conversion, UTC and
local time conversion through the host time zone, RFC 3339 formatting
and parsing, and tick arithmetic. Add sceRtcGetDaysInMonth,
sceRtcTickAddMonths and sceRtcTickAddYears, which clamp the day to the
end of the target month.

The network clock uses the host clock.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 12:21:23 +02:00
PacukaandClaude Opus 5.5 d1c25097e3 feat(random): implement sceRandomGetRandomNumber
Fill the buffer from std::random_device and reject a null buffer or a
size above SCE_RANDOM_MAX_SIZE (64) with SCE_RANDOM_ERROR_INVALID, as
the system library does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 12:14:46 +02:00
boykopovar fb5f582e52 Merge pull request #7 from Pacuka/fix/linux-runtime
fix: Linux build and runtime fixes found while booting a retail UE title
2026-09-26 13:04:53 +03:00
boykopovar 2f30b62a69 fix(relinker): use general pipeline after converting for --to-intel flag 2026-09-26 12:47:31 +03:00
PacukaandClaude Opus 5.5 37074ab893 fix(build): link guest library tests dynamically on Linux
Tests in core/libs link against the prx shared libraries, which the
global -static flag rejects on Linux ("attempted static link of dynamic
object"). Drop -static in that directory on non-Windows hosts while
keeping the static GCC runtime.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 11:15:16 +02:00
PacukaandClaude Opus 5.5 f9695c1069 fix(agc): accept the SDK default GDS range in sceAgcCbReleaseMem
The SDK's inline release wrapper passes gdsOffset 0 and gdsSize 1 for
every release, not only GDS ones. The packet ignores the range unless the
GDS data selector is used, so accept that default.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 11:15:16 +02:00
PacukaandClaude Opus 5.5 b98257b75d fix(libc): register the main guest image on Linux
Guest mprotect calls on the executable's own segments failed with
"guest protection or unmap range is not registered" because only the
Windows build registered the main image. Register the PT_LOAD segments of
the main executable page by page, merging the protections of segments that
share a page.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 11:15:16 +02:00
PacukaandClaude Opus 5.5 ca23f10612 fix(kernel): accept AMPR and ACP access bits in memory protections
Retail titles pass protections such as 0xC2 (CPU read/write plus the
0x40 and 0x80 device access bits). The device bits do not affect CPU
access and were rejected as unsupported.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 11:15:16 +02:00
PacukaandClaude Opus 5.5 d15e93681f fix(kernel): map SCE protections to readable host pages
SCE_KERNEL_PROT_CPU_RW (0x02) and CPU_EXEC (0x04) include read access,
but were translated to write-only and execute-only host pages. GPU read
and write bits also need host access because the emulated GPU reads and
writes guest memory from the CPU. Write-only mappings made the AGC driver
reject guest data segments as unreadable.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 11:15:16 +02:00
PacukaandClaude Opus 5.5 998605fe4e fix(libc): swap calloc and realloc slots of the malloc replacement table
SceLibcMallocReplace lists calloc before realloc (malloc, free, calloc,
realloc, memalign, reallocalign, posix_memalign, ...), as the table in
retail titles shows. realloc therefore called the application's calloc
with the old pointer as the element count, and calloc called realloc.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 11:15:16 +02:00