diff --git a/core/libs/prx/libScePsml_debug/CMakeLists.txt b/core/libs/prx/libScePsml_debug/CMakeLists.txt new file mode 100644 index 000000000..ee07e525e --- /dev/null +++ b/core/libs/prx/libScePsml_debug/CMakeLists.txt @@ -0,0 +1,20 @@ +add_library(libScePsml_debug SHARED EXCLUDE_FROM_ALL Export.cpp) +target_include_directories(libScePsml_debug PRIVATE ${LIBS_INCLUDE_DIR}) +configure_windows_unwind(libScePsml_debug) + +if(MINGW) + foreach(runtimeLinkFlag IN ITEMS -static-libgcc -static-libstdc++ -static) + string(REPLACE "${runtimeLinkFlag}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + endforeach() +endif() + +if(BUILD_TESTING) + add_test_executable(guest_psml_tests ${LIBS_INCLUDE_DIR}/tests/GuestPsml.cpp) + target_include_directories(guest_psml_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_psml_tests PRIVATE libScePsml_debug) + add_test(NAME guest_psml COMMAND guest_psml_tests) + if(WIN32) + set_tests_properties(guest_psml PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() diff --git a/core/libs/prx/libScePsml_debug/Export.cpp b/core/libs/prx/libScePsml_debug/Export.cpp index 67d7cf76b..2e8ee6e64 100644 --- a/core/libs/prx/libScePsml_debug/Export.cpp +++ b/core/libs/prx/libScePsml_debug/Export.cpp @@ -3,22 +3,45 @@ #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" +namespace { + +constexpr std::int32_t SCE_PSML_ERROR_NOT_INITIALIZED = static_cast(0x8A810001); + +} + extern "C" { +std::int32_t APS5_VABI scePsmlMfsrGetContextBufferRequirement1100(void* requirement, const void* param) { + (void)requirement; + (void)param; + return SCE_PSML_ERROR_NOT_INITIALIZED; +} + +std::int32_t APS5_VABI scePsmlMfsrCreateContext1100(void** context, const void* param) { + (void)context; + (void)param; + return SCE_PSML_ERROR_NOT_INITIALIZED; +} + +std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1100(void* context, void* commandBuffer, const void* param) { + (void)context; + (void)commandBuffer; + (void)param; + return SCE_PSML_ERROR_NOT_INITIALIZED; +} + APS5_EXPORT("+2KpvixvL6E", scePsmlUnknown__P2KpvixvL6E); int APS5_VABI scePsmlUnknown__P2KpvixvL6E() { NotImplemented_nid_no_patch(__func__); return 0; } -APS5_EXPORT("3WVD91e12ZQ", scePsmlUnknown_3WVD91e12ZQ); -int APS5_VABI scePsmlUnknown_3WVD91e12ZQ() { +int APS5_VABI scePsmlMfsrInit() { NotImplemented_nid_no_patch(__func__); return 0; } -APS5_EXPORT("AHalTX9wFZY", scePsmlUnknown_AHalTX9wFZY); -int APS5_VABI scePsmlUnknown_AHalTX9wFZY() { +int APS5_VABI scePsmlMfsrGetDispatchMfsrPacketSizeInDwords() { NotImplemented_nid_no_patch(__func__); return 0; } @@ -47,8 +70,7 @@ int APS5_VABI scePsmlUnknown_GJY0MvuTcs8() { return 0; } -APS5_EXPORT("JaLBe0P3jSU", scePsmlUnknown_JaLBe0P3jSU); -int APS5_VABI scePsmlUnknown_JaLBe0P3jSU() { +int APS5_VABI scePsmlMfsrReleaseContext() { NotImplemented_nid_no_patch(__func__); return 0; } diff --git a/core/libs/tests/GuestPsml.cpp b/core/libs/tests/GuestPsml.cpp new file mode 100644 index 000000000..d0aac1d17 --- /dev/null +++ b/core/libs/tests/GuestPsml.cpp @@ -0,0 +1,53 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include + +extern "C" { +std::int32_t APS5_VABI scePsmlMfsrGetContextBufferRequirement1100(void* requirement, const void* param); +std::int32_t APS5_VABI scePsmlMfsrCreateContext1100(void** context, const void* param); +std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1100(void* context, void* commandBuffer, const void* param); +} + +namespace { + +void Require(bool value) { if (!value) std::abort(); } + +constexpr std::int32_t kErrNotInitialized = static_cast(0x8A810001); + +struct CommandBuffer { + std::uint32_t* cursor; + std::uint32_t sizeInDwords; +}; + +} + +int main() { + std::array param{}; + + std::array requirement; + requirement.fill(0xa5); + const auto untouchedRequirement = requirement; + Require(scePsmlMfsrGetContextBufferRequirement1100(requirement.data(), param.data()) == kErrNotInitialized); + Require(requirement == untouchedRequirement); + Require(scePsmlMfsrGetContextBufferRequirement1100(nullptr, nullptr) == kErrNotInitialized); + + std::uint64_t contextStorage = 0; + void* const sentinel = &contextStorage; + void* context = sentinel; + Require(scePsmlMfsrCreateContext1100(&context, param.data()) == kErrNotInitialized); + Require(context == sentinel); + Require(scePsmlMfsrCreateContext1100(nullptr, nullptr) == kErrNotInitialized); + + std::array dwords; + dwords.fill(0xa5a5a5a5u); + const auto untouchedDwords = dwords; + CommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; + Require(scePsmlMfsrGetDispatchMfsrPacket1100(&contextStorage, &commandBuffer, param.data()) == kErrNotInitialized); + Require(commandBuffer.cursor == dwords.data()); + Require(commandBuffer.sizeInDwords == dwords.size()); + Require(dwords == untouchedDwords); + Require(scePsmlMfsrGetDispatchMfsrPacket1100(nullptr, &commandBuffer, param.data()) == kErrNotInitialized); + Require(commandBuffer.cursor == dwords.data()); + Require(dwords == untouchedDwords); +} diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index a490dce87..02ea84a84 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -56,6 +56,7 @@ Throughout the project, every function at every stage either **does exactly what - [sceAudioOutGetLastOutputTime](../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - signature and behaviour taken from the [shadPS4](https://github.com/shadps4-emu/shadPS4) and [fpPS4](https://github.com/red-prig/fpPS4) reimplementations of the PS4 library, not confirmed on a PS5 title: the time is the process time at which `sceAudioOutOutput` or `sceAudioOutOutputs` accepted the port's last block, not the time the block reached the device - [AOWqIYsgVHs](../../core/libs/prx/libSceContentExport/Export.cpp) (libSceContentExport) - unknown name, signature - [GQTObcITIXI](../../core/libs/prx/libSceShare/Export.cpp) (libSceShare) - unknown name, signature +- [scePsmlMfsrGetContextBufferRequirement1100, scePsmlMfsrCreateContext1100, scePsmlMfsrGetDispatchMfsrPacket1100](../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml_debug) - argument layouts unknown; only 0x8A810001 (not initialized) is returned - [BnMAMrsfVWo](../../core/libs/prx/libc/src/HeapDiagnostics.cpp) (libc) - unknown name, signature - [scePngEncEncode](../../core/libs/prx/libScePngEnc/Export.cpp) (libScePngEnc) - whether rows may stay unfiltered when `filter_type` names a subset of the filters is unknown; as in shadPS4, they may only for 0 and for the all-filters mask - AudioIn, NpSessionSignaling and PlayerInvitationDialog exports added without an implementation have assumed signatures