diff --git a/core/libs/prx/libkernel/System/src/Process.cpp b/core/libs/prx/libkernel/System/src/Process.cpp index e2b5eb47d..61db84d80 100644 --- a/core/libs/prx/libkernel/System/src/Process.cpp +++ b/core/libs/prx/libkernel/System/src/Process.cpp @@ -333,6 +333,14 @@ int APS5_VABI sceKernelGetCurrentCpu(void) { return GuestCpuFromHost(index, scePthreadSelf()->affinity.load(std::memory_order_relaxed)); } +int APS5_VABI sceKernelGetMainSocId(void) { + return 0; +} + +int APS5_VABI sceKernelGetCpumode(void) { + return 0; +} + std::uint64_t APS5_VABI sceKernelGetGPI(void) { return gpoBits.load(std::memory_order_relaxed); } diff --git a/core/libs/prx/libkernel/Time/Time.cpp b/core/libs/prx/libkernel/Time/Time.cpp index a161c30d6..b16a1c94d 100644 --- a/core/libs/prx/libkernel/Time/Time.cpp +++ b/core/libs/prx/libkernel/Time/Time.cpp @@ -612,6 +612,10 @@ uint64_t APS5_VABI sceKernelGetTscFrequency(void) { return frequency; } +std::int64_t APS5_VABI sceKernelGetCpuFrequency(void) { + return static_cast(sceKernelGetTscFrequency()); +} + unsigned int APS5_VABI sceKernelSleep(unsigned int seconds) { CancellableSleep(static_cast(seconds) * 1000000000ULL); return 0; diff --git a/core/libs/tests/GuestCurrentCpu.cpp b/core/libs/tests/GuestCurrentCpu.cpp index b7d7d75cc..389ad302f 100644 --- a/core/libs/tests/GuestCurrentCpu.cpp +++ b/core/libs/tests/GuestCurrentCpu.cpp @@ -6,6 +6,10 @@ extern "C" { int APS5_VABI sceKernelGetCurrentCpu(void); +int APS5_VABI sceKernelGetMainSocId(void); +int APS5_VABI sceKernelGetCpumode(void); +std::int64_t APS5_VABI sceKernelGetCpuFrequency(void); +std::uint64_t APS5_VABI sceKernelGetTscFrequency(void); KernelCpumask APS5_VABI sceKernelGetAvailableCpumask(void); Pthread APS5_VABI scePthreadSelf(); int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); @@ -38,6 +42,8 @@ static void* APS5_VABI ReportWhilePinned(void* arg) { int main() { const KernelCpumask available = sceKernelGetAvailableCpumask(); + Require(sceKernelGetMainSocId() == 0 && sceKernelGetCpumode() == 0); + Require(sceKernelGetCpuFrequency() > 0 && static_cast(sceKernelGetCpuFrequency()) == sceKernelGetTscFrequency()); const std::array affinities{available, 0x1FFB, 0x3, 0x3F, 0x1000, 0x1, 0xFFFF, 0x10000}; for (const KernelCpumask affinity : affinities) { diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index 71c07945e..4de1570bd 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -30,6 +30,7 @@ Throughout the project, every function at every stage either **does exactly what - [libSceHmd2](../../core/libs/prx/libSceHmd2/Export.cpp) has no PS VR2 runtime: `sceHmd2Initialize` fails, and every other export it has (and every [libSceVrTracker2](../../core/libs/prx/libSceVrTracker2/Export.cpp) export) throws. PPSA01317 skips its whole VR set-up when initialization fails - [libSceMbus](../../core/libs/prx/libSceMbus/Export.cpp) implements only the no-device path: initialization and termination succeed, no device events are reported and device queries return no entries - [libSceAudioPropagation](../../core/libs/prx/libSceAudioPropagation/Export.cpp) implements only the no-acoustic-propagation path: the system keeps a 16-byte header in the title's CPU memory (no GPU memory), rooms, portals, sources and materials are tracked handles, attributes are validated and have no effect, no rays are requested and sources report no audio paths. Ray results, path calculation and audio paths are accepted only when empty and throw otherwise; `sceAudioPropagationSourceRender` writes silence (zeroes) to each source's output buffer for the given size, without a dry signal. Objects still alive when their system is destroyed become unusable, and their later destroy or unregister is a no-op: PPSA21567 releases its reference-counted room, portal and source owners just before `sceAudioPropagationSystemDestroy`, so the order for every object is not proven. Occlusion, reflections and reverb from level geometry are absent; in-game behaviour remains unverified. +- [sceKernelGetMainSocId and sceKernelGetCpumode](../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) both return 0, and [sceKernelGetCpuFrequency](../../core/libs/prx/libkernel/Time/Time.cpp) returns the host TSC frequency measured for `sceKernelGetTscFrequency`, not the console CPU clock. The PS5's SoC id and CPU mode are unknown; shadPS4's PS4 values are [0x710f10/0x740f30 and 0, 2 or 5 from the param.sfo CPU-mode flags](https://github.com/shadps4-emu/shadPS4/blob/e0a466753a1a/src/core/libraries/kernel/process.cpp). PPSA99203 only logs them (`[console] main SoC id: result=%#x out=%#x`, `CPU: %llu Hz, cpumode %d`), passing a pointer that `sceKernelGetMainSocId` leaves untouched - [libSceAcm](../../core/libs/prx/libSceAcm/Export.cpp) batches execute as silent no-ops, so `sceAcm_ConvReverb_SharedInput`, `sceAcm_FFT` and `sceAcm_Panner` return success without encoding audio commands. - [libSceNpCommerce](../../core/libs/prx/libSceNpCommerce/Export.cpp) - the PS Store icon show/hide calls and `sceNpCommerceSetPsStoreIconLayout` do nothing - [libSceUsbd](../../core/libs/prx/libSceUsbd/Export.cpp) implements only the no-device path: `sceUsbdInit` and `sceUsbdExit` succeed without a host USB context, the device list is always empty and event handling waits for its timeout; calls that need a device throw. Transfers follow the `libusb_transfer` layout from [libusb.h](https://github.com/libusb/libusb/blob/master/libusb/libusb.h), which [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/usbd/usbd.h) passes to titles as `SceUsbdTransfer`: `sceUsbdAllocTransfer` zero-allocates one with its iso packet count (a negative count returns null), `sceUsbdFillInterruptTransfer` fills the fields `libusb_fill_interrupt_transfer` sets, and `sceUsbdCancelTransfer` reports `LIBUSB_ERROR_NOT_FOUND` mapped to `0x80240005` by shadPS4's `0x80240000 - error` rule, since no transfer can be submitted. `sceUsbdEventHandlingOk` returns 1 because no other thread handles events, and `sceUsbdFreeConfigDescriptor` accepts only null because no descriptor is ever returned. The device and handle calls take the argument lists of FreeBSD 11.4 libusb ([libusb.h](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb.h)) and return `0x80240002` for the null arguments it rejects with `LIBUSB_ERROR_INVALID_PARAM` ([libusb10.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb10.c), [libusb10_desc.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb10_desc.c), [libusb10_io.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb10_io.c)); a null device or handle in the calls it treats as null-safe returns 0, null or nothing, as there. `sceUsbdOpen` and `sceUsbdGetActiveConfigDescriptor` throw on a null device, which libusb dereferences. Any other device or handle was never returned by this library, so those calls throw. The layout, the argument lists and the error codes are unverified on PS5