diff --git a/core/libs/prx/libSceContentDelete/Export.cpp b/core/libs/prx/libSceContentDelete/Export.cpp index 16dd322fb..4c80330e3 100644 --- a/core/libs/prx/libSceContentDelete/Export.cpp +++ b/core/libs/prx/libSceContentDelete/Export.cpp @@ -24,6 +24,11 @@ int APS5_VABI sceContentDeleteByPath(void) { return 0; } +int APS5_VABI sceContentDeleteById(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + int APS5_VABI sceContentDeleteTerminate(void) { bool expected = true; if (!g_initialized.compare_exchange_strong(expected, false)) throw std::logic_error(std::string(__func__) + ": not initialized"); diff --git a/core/libs/prx/libSceContentExport/CMakeLists.txt b/core/libs/prx/libSceContentExport/CMakeLists.txt index 7c401ea5f..7efbba37e 100644 --- a/core/libs/prx/libSceContentExport/CMakeLists.txt +++ b/core/libs/prx/libSceContentExport/CMakeLists.txt @@ -12,4 +12,14 @@ if(BUILD_TESTING) set_tests_properties(guest_content_export PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + + add_test_executable(guest_content_unimplemented_tests ${LIBS_INCLUDE_DIR}/tests/GuestContentUnimplemented.cpp) + target_include_directories(guest_content_unimplemented_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_content_unimplemented_tests PRIVATE libSceContentExport libSceContentSearch libSceContentDelete libc) + configure_windows_unwind(guest_content_unimplemented_tests) + add_test(NAME guest_content_unimplemented COMMAND guest_content_unimplemented_tests) + if(WIN32) + set_tests_properties(guest_content_unimplemented PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() endif() diff --git a/core/libs/prx/libSceContentExport/Export.cpp b/core/libs/prx/libSceContentExport/Export.cpp index 1a7fde306..a626f6a42 100644 --- a/core/libs/prx/libSceContentExport/Export.cpp +++ b/core/libs/prx/libSceContentExport/Export.cpp @@ -46,6 +46,21 @@ int APS5_VABI sceContentExportStart(void) { return 0; } +int APS5_VABI sceContentExportGetProgress(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + +int APS5_VABI sceContentExportCancel(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + +int APS5_VABI sceContentExportFromDataWithThumbnail(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + int APS5_VABI sceContentExportTerm(void) { bool expected = true; if (!g_initialized.compare_exchange_strong(expected, false)) throw std::logic_error(std::string(__func__) + ": not initialized"); diff --git a/core/libs/prx/libSceContentSearch/Export.cpp b/core/libs/prx/libSceContentSearch/Export.cpp index cfb70402a..7a40aabad 100644 --- a/core/libs/prx/libSceContentSearch/Export.cpp +++ b/core/libs/prx/libSceContentSearch/Export.cpp @@ -44,6 +44,26 @@ int APS5_VABI sceContentSearchSearchContent(void) { return 0; } +int APS5_VABI sceContentSearchGetContentLastUpdateId(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + +int APS5_VABI sceContentSearchOpenMetadataByContentId(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + +int APS5_VABI sceContentSearchGetTotalContentSize(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + +int APS5_VABI sceContentSearchGetNumOfContent(void) { + NotImplemented_nid_no_patch(__func__); + return 0; +} + int APS5_VABI sceContentSearchTerm(void) { bool expected = true; if (!g_initialized.compare_exchange_strong(expected, false)) throw std::logic_error(std::string(__func__) + ": not initialized"); diff --git a/core/libs/tests/GuestContentUnimplemented.cpp b/core/libs/tests/GuestContentUnimplemented.cpp new file mode 100644 index 000000000..00a291f52 --- /dev/null +++ b/core/libs/tests/GuestContentUnimplemented.cpp @@ -0,0 +1,45 @@ +#include "prx/libc/include/general/VabiMacros.hpp" + +#include +#include +#include + +extern "C" { +int APS5_VABI sceContentDeleteById(); +int APS5_VABI sceContentExportGetProgress(); +int APS5_VABI sceContentExportCancel(); +int APS5_VABI sceContentExportFromDataWithThumbnail(); +int APS5_VABI sceContentSearchGetContentLastUpdateId(); +int APS5_VABI sceContentSearchOpenMetadataByContentId(); +int APS5_VABI sceContentSearchGetTotalContentSize(); +int APS5_VABI sceContentSearchGetNumOfContent(); +} + +namespace { + +bool ReportsNotImplemented(const char* name, int (APS5_VABI *function)()) { + try { + function(); + } catch (const std::runtime_error& error) { + if (std::string(error.what()) == std::string(name) + " not implemented") return true; + std::fprintf(stderr, "%s threw: %s\n", name, error.what()); + return false; + } + std::fprintf(stderr, "%s returned instead of reporting that it is not implemented\n", name); + return false; +} + +} + +int main() { + bool correct = true; + correct &= ReportsNotImplemented("sceContentDeleteById", sceContentDeleteById); + correct &= ReportsNotImplemented("sceContentExportGetProgress", sceContentExportGetProgress); + correct &= ReportsNotImplemented("sceContentExportCancel", sceContentExportCancel); + correct &= ReportsNotImplemented("sceContentExportFromDataWithThumbnail", sceContentExportFromDataWithThumbnail); + correct &= ReportsNotImplemented("sceContentSearchGetContentLastUpdateId", sceContentSearchGetContentLastUpdateId); + correct &= ReportsNotImplemented("sceContentSearchOpenMetadataByContentId", sceContentSearchOpenMetadataByContentId); + correct &= ReportsNotImplemented("sceContentSearchGetTotalContentSize", sceContentSearchGetTotalContentSize); + correct &= ReportsNotImplemented("sceContentSearchGetNumOfContent", sceContentSearchGetNumOfContent); + return correct ? 0 : 1; +} diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index 727f26c3c..b00ae11ac 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -116,6 +116,7 @@ Throughout the project, every function at every stage either **does exactly what - [sceSaveDataCancel](../../core/libs/prx/libSceSaveData.native/Export.cpp) (libSceSaveData.native) - imported by PPSA23126, which fails to load without it; added without an implementation because its signature is unknown. Every save data call here finishes before it returns, so nothing is ever in flight to cancel, but what the console returns then is unknown - [sceAudioOutExClose, sceAudioOutExConfigureOutput, sceAudioOutExGetMonitorInfo, sceAudioOutExOpen](../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - imported by PPSA99505, which fails to load without them; added without an implementation and declared without parameters. PPSA99505 calls them only for its HDMI bitstream output, an option that is off by default, to read the formats the TV or receiver lists, switch the HDMI output mode and open a port for IEC 61937 bursts ([Jelly5](https://github.com/02dnot/Jelly5/blob/552b866d89b2a58b27f7f7b0484dc743ce235526/app/src/jelly5_bitstream.cpp#L110-L179)); [EVO-PLAYER-PS5](https://github.com/sainsaji/EVO-PLAYER-PS5/blob/da0c0451333bab82e79fffd2de4718e917f9dcb0/projects/evoplayer/core/src/audio/evo_pt.cpp) also calls `sceAudioOutExOpen`, `sceAudioOutExConfigureOutput` and `sceAudioOutExClose` for HDMI bitstream output. The two declare the arguments of `sceAudioOutExConfigureOutput` differently and neither is confirmed on a console. Audio reaches the host device through SDL as PCM, so there is no encoded HDMI output to switch to - [sceOpusCeltDecCreateEx, sceOpusCeltDecDecode, sceOpusCeltDecDestroy, sceOpusCeltDecGetSize, sceOpusCeltDecInitialize, sceOpusCeltDecTerminate](../../core/libs/prx/libSceOpusCeltDec/Export.cpp) (libSceOpusCeltDec) - imported by PPSA99001, which fails to load without the module; added without an implementation. Their signatures match libSceOpusDec's in [ProsperoRadio](https://github.com/blackbearreloaded/ProsperoRadio/blob/2c4029c3a8f43e9e1dfef98374d94d99b14d745d/src/opus_decoder.cpp). PPSA99001 opens this decoder only as a fallback when libSceOpusDec reports a retryable error for a CELT packet, which [libSceOpusDec](../../core/libs/prx/libSceOpusDec/Export.cpp) here never returns, so the fallback is not reached +- [sceContentDeleteById](../../core/libs/prx/libSceContentDelete/Export.cpp) (libSceContentDelete), [sceContentExportGetProgress, sceContentExportCancel, sceContentExportFromDataWithThumbnail](../../core/libs/prx/libSceContentExport/Export.cpp) (libSceContentExport) and [sceContentSearchGetContentLastUpdateId, sceContentSearchOpenMetadataByContentId, sceContentSearchGetTotalContentSize, sceContentSearchGetNumOfContent](../../core/libs/prx/libSceContentSearch/Export.cpp) (libSceContentSearch) - imported by PPSA06465, which fails to load without them; added without an implementation because their signatures are unknown - [sce::Json::Parser::parse](../../core/libs/prx/libSceJson2/Export.cpp) (libSceJson2) - a number that overflows a double (e.g. `1e309`) throws: whether the console rejects the document or stores an infinite real is unknown - [sceUserServiceGetNpAccountId](../../core/libs/prx/libSceUserService/Export.cpp) (libSceUserService) - the account id for a user with no linked PSN account is assumed to be 0 with success; libSceNpManager's `sceNpGetAccountIdA` answers the same question with `SCE_NP_ERROR_SIGNED_OUT` - [sceUserServiceGetUserColor](../../core/libs/prx/libSceUserService/Export.cpp) (libSceUserService) - the default profile colour is assumed to be blue (0)