From 86bd3b6621633dfdcc2b07013abb5c31394fbcc2 Mon Sep 17 00:00:00 2001 From: jagrat Singh Date: Sun, 11 Oct 2026 21:40:58 +0530 Subject: [PATCH] feat(libSceAcm): implement sceAcm_FFT and sceAcm_Panner --- core/libs/CMakeLists.txt | 10 ++++++++ core/libs/prx/libSceAcm/Export.cpp | 6 ++--- core/libs/tests/GuestAcm.cpp | 41 ++++++++++++++++++++++++++++++ docs/dev/TechnicalDebt.md | 1 + 4 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 core/libs/tests/GuestAcm.cpp diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index 2da76ed8e..4889bf240 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -329,4 +329,14 @@ if(BUILD_TESTING) set_tests_properties(guest_posix_random PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + + add_test_executable(guest_acm_tests tests/GuestAcm.cpp) + target_include_directories(guest_acm_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(guest_acm_tests PRIVATE libSceAcm libc) + configure_windows_unwind(guest_acm_tests) + add_test(NAME guest_acm COMMAND guest_acm_tests) + if(WIN32) + set_tests_properties(guest_acm PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() endif() diff --git a/core/libs/prx/libSceAcm/Export.cpp b/core/libs/prx/libSceAcm/Export.cpp index e62e5934d..fd80c9e1a 100644 --- a/core/libs/prx/libSceAcm/Export.cpp +++ b/core/libs/prx/libSceAcm/Export.cpp @@ -53,13 +53,11 @@ int APS5_VABI sceAcm_ConvReverb_SharedInput(void) { return 0; } -int APS5_VABI sceAcm_FFT() { - NotImplemented_nid_no_patch(__func__); +int APS5_VABI sceAcm_FFT(void) { return 0; } -int APS5_VABI sceAcm_Panner() { - NotImplemented_nid_no_patch(__func__); +int APS5_VABI sceAcm_Panner(void) { return 0; } diff --git a/core/libs/tests/GuestAcm.cpp b/core/libs/tests/GuestAcm.cpp new file mode 100644 index 000000000..e360f8444 --- /dev/null +++ b/core/libs/tests/GuestAcm.cpp @@ -0,0 +1,41 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include + +extern "C" { +int APS5_VABI sceAcmContextCreate(std::uint32_t*); +int APS5_VABI sceAcmContextDestroy(std::uint32_t); +int APS5_VABI sceAcmBatchStartBuffer(std::uint32_t, const void*, std::size_t, void*, std::uint32_t*); +int APS5_VABI sceAcmBatchStartBuffers(std::uint32_t, std::uint32_t, const void* const[], void*, std::uint32_t*); +int APS5_VABI sceAcmBatchWait(std::uint32_t, std::uint32_t, std::uint32_t); +int APS5_VABI sceAcm_ConvReverb_SharedInput(void); +int APS5_VABI sceAcm_FFT(void); +int APS5_VABI sceAcm_Panner(void); +} + +static void Require(bool value) { + if (!value) std::abort(); +} + +int main() { + std::uint32_t context = 0; + Require(sceAcmContextCreate(nullptr) != 0); + Require(sceAcmContextCreate(&context) == 0 && context != 0); + + std::uint32_t batch = 0; + Require(sceAcmBatchStartBuffer(context, nullptr, 0, nullptr, nullptr) != 0); + Require(sceAcmBatchStartBuffer(context, nullptr, 0, nullptr, &batch) == 0 && batch != 0); + Require(sceAcmBatchWait(context, batch, 0) == 0); + + std::uint32_t batch2 = 0; + Require(sceAcmBatchStartBuffers(context, 0, nullptr, nullptr, nullptr) != 0); + Require(sceAcmBatchStartBuffers(context, 0, nullptr, nullptr, &batch2) == 0 && batch2 != 0); + Require(sceAcmBatchWait(context, batch2, 0) == 0); + + Require(sceAcm_ConvReverb_SharedInput() == 0); + Require(sceAcm_FFT() == 0); + Require(sceAcm_Panner() == 0); + + Require(sceAcmContextDestroy(context) == 0); +} diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index 0c72b62a7..506be0dbf 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -24,6 +24,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. +- [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 layout and error codes are unverified on PS5 - [libSceSystemService](../../core/libs/prx/libSceSystemService/Export.cpp) - `sceSystemServicePowerTick`, `sceSystemServiceReportAbnormalTermination`, `sceSystemServiceDisableMusicPlayer`, `sceSystemServiceReenableMusicPlayer`, `sceSystemServiceDisableMediaPlay` and `sceSystemServiceReenableMediaPlay` return success and do nothing: the host has no auto power-off timer to reset, no system crash reporter to notify, no system music player to pause or resume and no system media playback to disable. PPSA01521 calls `sceSystemServiceDisableMediaPlay` during start-up, and its wrappers for both pass no arguments