diff --git a/CMakeLists.txt b/CMakeLists.txt index 25abb6896a..21e51188ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -466,7 +466,7 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_package_release.py) add_test(NAME web_release COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_web_release.py) - set_tests_properties(web_release PROPERTIES TIMEOUT 20) + set_tests_properties(web_release PROPERTIES TIMEOUT 120) add_test(NAME web_library_assets COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_build_web.py) set_tests_properties(web_library_assets PROPERTIES TIMEOUT 20) diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp index 87107f2054..de2e3a8c71 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp @@ -929,7 +929,7 @@ void CheckBdaSpan(AgcDriver::VulkanDevice& device, const Block& block, std::size failure = error.what(); } const auto deferred = log.Finish(); - if (failure.empty()) failure = deferred; + if (failure.empty() && deferred.find("BDA access failed:") != std::string::npos) failure = deferred; if (refused) { Require(failure.find("BDA access failed:") != std::string::npos, "BDA access to a resident native multisample range was not refused: " + failure); Require(std::equal(before.begin(), before.end(), block.data), "a refused BDA access changed guest memory"); diff --git a/core/libs/prx/libSceAppContent/Export.cpp b/core/libs/prx/libSceAppContent/Export.cpp index 7f4947a6c1..ce58e1546e 100644 --- a/core/libs/prx/libSceAppContent/Export.cpp +++ b/core/libs/prx/libSceAppContent/Export.cpp @@ -62,6 +62,7 @@ bool IsTemporaryMountPoint(const AppContentMountPoint* mountPoint) { return std::strncmp(mountPoint->data, TEMPORARY_MOUNT_POINT, sizeof(mountPoint->data)) == 0; } +std::atomic download1QuotaBytes{0}; std::atomic download2QuotaBytes{0}; bool IsDownloadMountPoint(const AppContentMountPoint* mountPoint) { @@ -173,10 +174,10 @@ int APS5_VABI sceAppContentDownloadDataGetAvailableSpaceKb(const AppContentMount const std::uint64_t quotaMiB = GetAppDownloadDataSizeMiB_nid_postfix(); if (quotaMiB > std::numeric_limits::max() / 1024u) throw std::overflow_error("AppContent download quota exceeds KiB range"); quotaKb = quotaMiB * 1024u; + } else if (std::strncmp(mountPoint->data, "/download1", sizeof(mountPoint->data)) == 0) { + quotaKb = download1QuotaBytes.load() / 1024u; } else if (std::strncmp(mountPoint->data, "/download2", sizeof(mountPoint->data)) == 0) { quotaKb = download2QuotaBytes.load() / 1024u; - } else { - NotImplemented_nid_no_patch(__func__); } if (quotaKb == 0) { *availableSpaceKb = 0; @@ -322,8 +323,13 @@ int APS5_VABI sceAppContentDownload0Shrink(void) { return 0; } -int APS5_VABI sceAppContentDownload1Expand(void) { - NotImplemented_nid_no_patch(__func__); +int APS5_VABI sceAppContentDownload1Expand(size_t size) { + if (!initialized.load()) return SCE_APP_CONTENT_ERROR_NOT_INITIALIZED; + if (size == 0) return SCE_APP_CONTENT_ERROR_PARAMETER; + const auto directory = ResolvePath_nid_no_patch("/download1"); + if (std::filesystem::create_directories(directory)) RecordWrittenPath_nid_no_patch(directory); + size_t current = download1QuotaBytes.load(); + while (size > current && !download1QuotaBytes.compare_exchange_weak(current, size)) {} return 0; } diff --git a/core/libs/prx/libSceAppContent/include/Api.hpp b/core/libs/prx/libSceAppContent/include/Api.hpp index e6c6f7021a..ec4fc67145 100644 --- a/core/libs/prx/libSceAppContent/include/Api.hpp +++ b/core/libs/prx/libSceAppContent/include/Api.hpp @@ -36,7 +36,7 @@ int APS5_VABI sceAppContentCheckBundleLicenseOnDisc(uint32_t serviceLabel, const int APS5_VABI sceAppContentAppParamGetString(void); int APS5_VABI sceAppContentDownload0Expand(void); int APS5_VABI sceAppContentDownload0Shrink(void); -int APS5_VABI sceAppContentDownload1Expand(void); +int APS5_VABI sceAppContentDownload1Expand(size_t size); int APS5_VABI sceAppContentDownload1Shrink(void); int APS5_VABI sceAppContentDownload2Expand(size_t size); int APS5_VABI sceAppContentDownload2Shrink(void); diff --git a/core/libs/prx/libSceContentSearch/Export.cpp b/core/libs/prx/libSceContentSearch/Export.cpp index 13c17b161a..9e0c985a9f 100644 --- a/core/libs/prx/libSceContentSearch/Export.cpp +++ b/core/libs/prx/libSceContentSearch/Export.cpp @@ -190,16 +190,26 @@ int APS5_VABI sceContentBinderStart() { int APS5_VABI sceContentBinderTerminate() { return static_cast(0x809D000F); } -int APS5_VABI sceContentSearchGetApplicationLastUpdateId() { +int APS5_VABI sceContentSearchGetApplicationLastUpdateId(std::int64_t* lastUpdateId) { + if (!g_initialized.load()) return ErrorNotInitialized; + if (lastUpdateId == nullptr) return ErrorInvalidArgument; + *lastUpdateId = LibraryUpdateId; + return 0; +} +int APS5_VABI sceContentSearchGetMyApplicationIndex(std::int32_t* index) { + if (!g_initialized.load()) return ErrorNotInitialized; + if (index == nullptr) return ErrorInvalidArgument; + *index = 0; NotImplemented_nid_no_patch(__func__); return 0; } -int APS5_VABI sceContentSearchGetMyApplicationIndex() { - NotImplemented_nid_no_patch(__func__); - return 0; -} -int APS5_VABI sceContentSearchGetNumOfApplication() { - NotImplemented_nid_no_patch(__func__); +int APS5_VABI sceContentSearchGetNumOfApplication(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, const ContentSearchContentOrderByCondition* orderByConditions, std::uint32_t orderByConditionsLength, std::int64_t* numOfApplication, std::int64_t* lastUpdateId) { + if (!g_initialized.load()) return ErrorNotInitialized; + if ((columnSet == nullptr) != (columnSetLength == 0) || (orderByConditions == nullptr) != (orderByConditionsLength == 0) || numOfApplication == nullptr || lastUpdateId == nullptr) return ErrorInvalidArgument; + ValidateColumnSets(__func__, columnSet, columnSetLength); + ValidateOrderBy(__func__, orderByConditions, orderByConditionsLength); + *numOfApplication = 0; + *lastUpdateId = LibraryUpdateId; return 0; } int APS5_VABI sceContentSearchSearchApplication() { diff --git a/core/libs/prx/libSceContentSearch/include/Api.hpp b/core/libs/prx/libSceContentSearch/include/Api.hpp index b54e8efb17..c648e0c87f 100644 --- a/core/libs/prx/libSceContentSearch/include/Api.hpp +++ b/core/libs/prx/libSceContentSearch/include/Api.hpp @@ -23,9 +23,9 @@ int APS5_VABI sceContentBinderReset(); int APS5_VABI sceContentBinderSearchDifference(); int APS5_VABI sceContentBinderStart(); int APS5_VABI sceContentBinderTerminate(); -int APS5_VABI sceContentSearchGetApplicationLastUpdateId(); -int APS5_VABI sceContentSearchGetMyApplicationIndex(); -int APS5_VABI sceContentSearchGetNumOfApplication(); +int APS5_VABI sceContentSearchGetApplicationLastUpdateId(std::int64_t* lastUpdateId); +int APS5_VABI sceContentSearchGetMyApplicationIndex(std::int32_t* index); +int APS5_VABI sceContentSearchGetNumOfApplication(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, const ContentSearchContentOrderByCondition* orderByConditions, std::uint32_t orderByConditionsLength, std::int64_t* numOfApplication, std::int64_t* lastUpdateId); int APS5_VABI sceContentSearchSearchApplication(); } diff --git a/core/libs/prx/libSceJxr/CMakeLists.txt b/core/libs/prx/libSceJxr/CMakeLists.txt index 33b74ee021..58e6eeb696 100644 --- a/core/libs/prx/libSceJxr/CMakeLists.txt +++ b/core/libs/prx/libSceJxr/CMakeLists.txt @@ -2,8 +2,13 @@ add_library(jxr_lookup_native STATIC src/NativeLookup.c src/NativeQuant.c) configure_jxr_native(jxr_lookup_native) target_include_directories(jxr_lookup_native PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(jxr_lookup_native PRIVATE jxr) -add_library(libSceJxr SHARED EXCLUDE_FROM_ALL Export.cpp src/Allocation.cpp src/PixelFormatLookup.cpp src/GuidExports.cpp src/Quantizer.cpp) -target_link_libraries(libSceJxr PRIVATE jxr_lookup_native) +add_library(libSceJxr SHARED EXCLUDE_FROM_ALL Export.cpp src/Allocation.cpp src/GlueHelpers.cpp src/PixelFormatLookup.cpp src/GuidExports.cpp src/Quantizer.cpp) +add_library(jxr_glue_guest STATIC ${JXR_SOURCE_DIR}/jxrgluelib/JXRGlue.c src/NativeGlue.c) +configure_jxr_native(jxr_glue_guest) +set_source_files_properties(${JXR_SOURCE_DIR}/jxrgluelib/JXRGlue.c TARGET_DIRECTORY jxr_glue_guest + PROPERTIES COMPILE_OPTIONS "-include;${CMAKE_CURRENT_SOURCE_DIR}/src/GuestHeap.h") +target_link_libraries(jxr_glue_guest PRIVATE jxr) +target_link_libraries(libSceJxr PRIVATE jxr_glue_guest jxr_lookup_native) if(NOT APPLE) target_link_options(libSceJxr PRIVATE LINKER:--exclude-libs,ALL) endif() @@ -70,6 +75,19 @@ if(BUILD_TESTING) endif() endif() +if(BUILD_TESTING) + add_test_executable(guest_jxr_glue_tests ${LIBS_INCLUDE_DIR}/tests/GuestJxrGlue.cpp) + target_include_directories(guest_jxr_glue_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_jxr_glue_tests PRIVATE libSceJxr libc jxr) + configure_windows_unwind(guest_jxr_glue_tests) + add_test(NAME guest_jxr_glue COMMAND guest_jxr_glue_tests) + set_tests_properties(guest_jxr_glue PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_jxr_glue PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() + if(BUILD_TESTING) add_library(jxr_quantizer_reference STATIC ${LIBS_INCLUDE_DIR}/tests/GuestJxrQuantizerReference.c) configure_jxr_native(jxr_quantizer_reference) diff --git a/core/libs/prx/libSceJxr/Export.cpp b/core/libs/prx/libSceJxr/Export.cpp index b4baa3f677..8ebbe554ea 100644 --- a/core/libs/prx/libSceJxr/Export.cpp +++ b/core/libs/prx/libSceJxr/Export.cpp @@ -139,18 +139,6 @@ int APS5_VABI FreeDescMetadata_nid_postfix() { NotImplemented_nid_no_patch(__func__); } -int APS5_VABI GetImageDecodeIID_nid_postfix() { - NotImplemented_nid_no_patch(__func__); -} - -int APS5_VABI GetImageEncodeIID_nid_postfix() { - NotImplemented_nid_no_patch(__func__); -} - -int APS5_VABI GetPixelFormatFromHash_nid_postfix() { - NotImplemented_nid_no_patch(__func__); -} - int APS5_VABI GetPosWS_File_nid_postfix() { NotImplemented_nid_no_patch(__func__); } @@ -165,14 +153,6 @@ std::int64_t APS5_VABI GetPosWS_Memory_nid_postfix(Jxr::Stream* stream, std::siz return WmpErrSuccess; } -int APS5_VABI IDPEmpty_nid_postfix() { - NotImplemented_nid_no_patch(__func__); -} - -int APS5_VABI PKAllocAligned_nid_postfix() { - NotImplemented_nid_no_patch(__func__); -} - int APS5_VABI PKCodecFactory_CreateCodec_nid_postfix() { NotImplemented_nid_no_patch(__func__); } @@ -245,10 +225,6 @@ int APS5_VABI PKFormatConverter_Release_nid_postfix() { NotImplemented_nid_no_patch(__func__); } -int APS5_VABI PKFreeAligned_nid_postfix() { - NotImplemented_nid_no_patch(__func__); -} - int APS5_VABI PKImageDecode_Copy_nid_postfix() { NotImplemented_nid_no_patch(__func__); } diff --git a/core/libs/prx/libSceJxr/include/Api.hpp b/core/libs/prx/libSceJxr/include/Api.hpp index e573f434e0..eedd733a29 100644 --- a/core/libs/prx/libSceJxr/include/Api.hpp +++ b/core/libs/prx/libSceJxr/include/Api.hpp @@ -2,6 +2,7 @@ #include "SceTypes.hpp" #include +#include #include "prx/libSceJxr/GuestPixelInfo.h" #include "prx/libSceJxr/Stream.hpp" @@ -11,6 +12,12 @@ std::int64_t APS5_VABI PKFree_nid_postfix(void** memory); std::int64_t APS5_VABI PixelFormatLookup_nid_postfix(JxrPixelInfo* value, std::uint8_t mode); std::int64_t APS5_VABI readIS_nid_postfix(void* codec, Jxr::BitIo* io); std::int64_t APS5_VABI writeIS_nid_postfix(void* codec, Jxr::BitIo* io); +std::int64_t APS5_VABI GetImageDecodeIID_nid_postfix(const char* extension, const std::uint32_t** iid); +std::int64_t APS5_VABI GetImageEncodeIID_nid_postfix(const char* extension, const std::uint32_t** iid); +const void* APS5_VABI GetPixelFormatFromHash_nid_postfix(std::uint8_t hash); +std::int32_t APS5_VABI IDPEmpty_nid_postfix(void* codec); +std::int64_t APS5_VABI PKAllocAligned_nid_postfix(void** memory, std::size_t size, std::size_t alignment); +std::int64_t APS5_VABI PKFreeAligned_nid_postfix(void** memory); void APS5_VABI remapQP_nid_postfix(void* quantizer, std::int32_t shift, std::int32_t scaled); void APS5_VABI formatQuantizer_nid_postfix(void** quantizers, std::uint8_t mode, std::size_t channels, std::size_t position, std::int32_t shiftedUv, std::int32_t scaled); @@ -24,14 +31,9 @@ std::int64_t APS5_VABI CreateWS_Memory_nid_postfix(Jxr::Stream** stream, void* b int APS5_VABI EOSWS_File_nid_postfix(); std::int32_t APS5_VABI EOSWS_Memory_nid_postfix(Jxr::Stream* stream); int APS5_VABI FreeDescMetadata_nid_postfix(); -int APS5_VABI GetImageDecodeIID_nid_postfix(); -int APS5_VABI GetImageEncodeIID_nid_postfix(); -int APS5_VABI GetPixelFormatFromHash_nid_postfix(); int APS5_VABI GetPosWS_File_nid_postfix(); int APS5_VABI GetPosWS_List_nid_postfix(); std::int64_t APS5_VABI GetPosWS_Memory_nid_postfix(Jxr::Stream* stream, std::size_t* position); -int APS5_VABI IDPEmpty_nid_postfix(); -int APS5_VABI PKAllocAligned_nid_postfix(); std::int64_t APS5_VABI PKAlloc_nid_postfix(void** memory, std::size_t size); int APS5_VABI PKCodecFactory_CreateCodec_nid_postfix(); int APS5_VABI PKCodecFactory_CreateDecoderFromFile_nid_postfix(); @@ -51,7 +53,6 @@ int APS5_VABI PKFormatConverter_GetSourcePixelFormat_nid_postfix(); int APS5_VABI PKFormatConverter_InitializeConvert_nid_postfix(); int APS5_VABI PKFormatConverter_Initialize_nid_postfix(); int APS5_VABI PKFormatConverter_Release_nid_postfix(); -int APS5_VABI PKFreeAligned_nid_postfix(); int APS5_VABI PKImageDecode_Copy_nid_postfix(); int APS5_VABI PKImageDecode_Create_WMP_nid_postfix(); int APS5_VABI PKImageDecode_Create_nid_postfix(); diff --git a/core/libs/prx/libSceJxr/src/GlueHelpers.cpp b/core/libs/prx/libSceJxr/src/GlueHelpers.cpp new file mode 100644 index 0000000000..a328b6b262 --- /dev/null +++ b/core/libs/prx/libSceJxr/src/GlueHelpers.cpp @@ -0,0 +1,81 @@ +#include "prx/libSceJxr/libSceJxr.hpp" +#include "prx/libc/include/Api.hpp" +#include +#include +#include +#include +#include + +extern "C" { +const void* JxrHashLookup_nid_no_patch(std::uint8_t hash); +std::int64_t JxrEncodeIid_nid_no_patch(const char* extension, std::uint32_t* value); +std::int64_t JxrDecodeIid_nid_no_patch(const char* extension, std::uint32_t* value); +std::int64_t JxrAllocAligned_nid_no_patch(void** memory, std::size_t size, std::size_t alignment); +std::int64_t JxrFreeAligned_nid_no_patch(void** memory); +std::int32_t JxrIdpEmpty_nid_no_patch(void* codec); + +void* JxrGuestCalloc_nid_no_patch(std::size_t count, std::size_t size) { + return calloc_nid_postfix(count, size); +} + +void JxrGuestFree_nid_no_patch(void* memory) { + free_nid_postfix(memory); +} +} + +namespace { + +constexpr std::uint32_t ImageUnsupported = 100; + +std::int64_t StoreIid(std::int64_t (*lookup)(const char*, std::uint32_t*), const char* extension, + const std::uint32_t** iid, const char* function) { + if (!extension) throw std::invalid_argument(std::string(function) + " requires an extension"); + std::uint32_t value = 0; + const auto result = lookup(extension, &value); + if (result < 0) return result; + if (!iid) throw std::invalid_argument(std::string(function) + " requires an output for a known extension"); + switch (value) { + case 101: *iid = &JxrGuest_IID_PKImageWmpEncode_nid_no_patch; break; + case 201: *iid = &JxrGuest_IID_PKImageWmpDecode_nid_no_patch; break; + case ImageUnsupported: *iid = &ImageUnsupported; break; + default: throw std::logic_error(std::string(function) + ": jxrlib returned an unknown IID " + std::to_string(value) + " for " + extension); + } + return result; +} + +} // namespace + +extern "C" { + +const void* APS5_VABI GetPixelFormatFromHash_nid_postfix(std::uint8_t hash) { + return JxrHashLookup_nid_no_patch(hash); +} + +std::int64_t APS5_VABI GetImageEncodeIID_nid_postfix(const char* extension, const std::uint32_t** iid) { + return StoreIid(JxrEncodeIid_nid_no_patch, extension, iid, "GetImageEncodeIID"); +} + +std::int64_t APS5_VABI GetImageDecodeIID_nid_postfix(const char* extension, const std::uint32_t** iid) { + return StoreIid(JxrDecodeIid_nid_no_patch, extension, iid, "GetImageDecodeIID"); +} + +std::int64_t APS5_VABI PKAllocAligned_nid_postfix(void** memory, std::size_t size, std::size_t alignment) { + if (!memory) throw std::invalid_argument("PKAllocAligned requires an output pointer"); + *memory = nullptr; + if (alignment < sizeof(void*)) + throw std::invalid_argument("PKAllocAligned: alignments below 8 can leave no room for the original pointer"); + constexpr auto maximum = std::numeric_limits::max(); + if (size > maximum - sizeof(void*) || alignment - 1 > maximum - sizeof(void*) - size) + throw std::length_error("PKAllocAligned: block size overflows size_t"); + return JxrAllocAligned_nid_no_patch(memory, size, alignment); +} + +std::int64_t APS5_VABI PKFreeAligned_nid_postfix(void** memory) { + return JxrFreeAligned_nid_no_patch(memory); +} + +std::int32_t APS5_VABI IDPEmpty_nid_postfix(void* codec) { + return JxrIdpEmpty_nid_no_patch(codec); +} + +} diff --git a/core/libs/prx/libSceJxr/src/GuestHeap.h b/core/libs/prx/libSceJxr/src/GuestHeap.h new file mode 100644 index 0000000000..777f12743a --- /dev/null +++ b/core/libs/prx/libSceJxr/src/GuestHeap.h @@ -0,0 +1,13 @@ +#ifndef CORE_LIBS_PRX_LIBSCEJXR_SRC_GUESTHEAP_H +#define CORE_LIBS_PRX_LIBSCEJXR_SRC_GUESTHEAP_H + +#include +#include + +void* JxrGuestCalloc_nid_no_patch(size_t count, size_t size); +void JxrGuestFree_nid_no_patch(void* memory); + +#define calloc JxrGuestCalloc_nid_no_patch +#define free JxrGuestFree_nid_no_patch + +#endif diff --git a/core/libs/prx/libSceJxr/src/NativeGlue.c b/core/libs/prx/libSceJxr/src/NativeGlue.c new file mode 100644 index 0000000000..7718a39ac6 --- /dev/null +++ b/core/libs/prx/libSceJxr/src/NativeGlue.c @@ -0,0 +1,36 @@ +#include "strcodec.h" +#include "JXRGlue.h" +#include + +const void* JxrHashLookup_nid_no_patch(U8 hash) { + return GetPixelFormatFromHash(hash); +} + +typedef ERR (*IidLookup)(const char*, const PKIID**); + +static int64_t StoreIid(IidLookup lookup, const char* extension, uint32_t* value) { + const PKIID* iid = NULL; + const ERR result = lookup(extension, &iid); + if (result >= 0 && iid) *value = *iid; + return result; +} + +int64_t JxrEncodeIid_nid_no_patch(const char* extension, uint32_t* value) { + return StoreIid(GetImageEncodeIID, extension, value); +} + +int64_t JxrDecodeIid_nid_no_patch(const char* extension, uint32_t* value) { + return StoreIid(GetImageDecodeIID, extension, value); +} + +int64_t JxrAllocAligned_nid_no_patch(void** memory, size_t size, size_t alignment) { + return PKAllocAligned(memory, size, alignment); +} + +int64_t JxrFreeAligned_nid_no_patch(void** memory) { + return PKFreeAligned(memory); +} + +int32_t JxrIdpEmpty_nid_no_patch(void* codec) { + return IDPEmpty((CWMImageStrCodec*)codec); +} diff --git a/core/libs/prx/libSceLibcInternal/CMakeLists.txt b/core/libs/prx/libSceLibcInternal/CMakeLists.txt index e222b977f1..54fb2e4c10 100644 --- a/core/libs/prx/libSceLibcInternal/CMakeLists.txt +++ b/core/libs/prx/libSceLibcInternal/CMakeLists.txt @@ -327,3 +327,16 @@ if(BUILD_TESTING AND (WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")) -- "$") set_tests_properties(guest_sigvec_modules PROPERTIES TIMEOUT 20) endif() + +if(BUILD_TESTING) + add_test_executable(guest_libc_internal_firmware_answers_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibcInternalFirmwareAnswers.cpp) + target_include_directories(guest_libc_internal_firmware_answers_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libc_internal_firmware_answers_tests PRIVATE libSceLibcInternal libkernel libc) + configure_windows_unwind(guest_libc_internal_firmware_answers_tests) + add_test(NAME guest_libc_internal_firmware_answers COMMAND guest_libc_internal_firmware_answers_tests) + set_tests_properties(guest_libc_internal_firmware_answers PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_libc_internal_firmware_answers PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() diff --git a/core/libs/prx/libSceLibcInternal/Export.cpp b/core/libs/prx/libSceLibcInternal/Export.cpp index dff386de77..e33c9e736d 100644 --- a/core/libs/prx/libSceLibcInternal/Export.cpp +++ b/core/libs/prx/libSceLibcInternal/Export.cpp @@ -1136,9 +1136,16 @@ int APS5_VABI _Closreg_nid_postfix() { return 0; } -int APS5_VABI _Daysto_nid_postfix() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI _Daysto_nid_postfix(int year, int month) { + static constexpr short DaysBeforeMonth[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + static constexpr short LeapDaysBeforeMonth[12] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}; + if (month < 0 || month >= 12) throw std::out_of_range("_Daysto: the month index is outside the twelve-entry tables"); + const auto bits = static_cast(year); + std::uint32_t leapDays = 0; + if (year > 0) leapDays = (bits - 1u) >> 2; + else if (year <= -4) leapDays = ((4u - bits) >> 2) + 1u; + const bool common = (bits & 3u) != 0 || year == 0; + return static_cast(leapDays + static_cast(common ? DaysBeforeMonth[month] : LeapDaysBeforeMonth[month])); } int APS5_VABI _Deletegloballocale_nid_postfix() { @@ -1248,9 +1255,15 @@ int APS5_VABI _FXp_addx_nid_postfix() { return 0; } -int APS5_VABI _FXp_getw_nid_postfix() { - NotImplemented_nid_no_patch(__func__); - return 0; +float APS5_VABI _FXp_getw_nid_postfix(const float* parts, int count) { + if (count == 0) return 0.0f; + if (count == 1 || parts[0] == 0.0f || parts[1] == 0.0f) return parts[0]; + if (count == 2 || parts[2] == 0.0f) return parts[0] + parts[1]; + const float head = parts[0] + parts[1]; + float tail = parts[2]; + if (count >= 4) tail += parts[3]; + if (head - parts[0] == parts[1]) return head + tail; + return parts[0] + (parts[1] + tail); } int APS5_VABI _FXp_invx_nid_postfix() { @@ -1440,8 +1453,7 @@ int APS5_VABI sceLibcInternalUnknown_wUa_oPQvFZ0_nid_no_patch() { APS5_EXPORT("wUa+oPQvFZ0", sceLibcInternalUnknown_wUa_oPQvFZ0_nid_no_patch); int APS5_VABI _Isdst_nid_postfix() { - NotImplemented_nid_no_patch(__func__); - return 0; + return -1; } int APS5_VABI _LAtan_nid_postfix() { diff --git a/core/libs/prx/libSceLibcInternal/include/MathInternals.hpp b/core/libs/prx/libSceLibcInternal/include/MathInternals.hpp index d706b9c36f..508e2c90dd 100644 --- a/core/libs/prx/libSceLibcInternal/include/MathInternals.hpp +++ b/core/libs/prx/libSceLibcInternal/include/MathInternals.hpp @@ -16,7 +16,7 @@ int APS5_VABI _FTan_nid_postfix(); int APS5_VABI _FTgamma_nid_postfix(); int APS5_VABI _FXp_addh_nid_postfix(); int APS5_VABI _FXp_addx_nid_postfix(); -int APS5_VABI _FXp_getw_nid_postfix(); +float APS5_VABI _FXp_getw_nid_postfix(const float* parts, int count); int APS5_VABI _FXp_invx_nid_postfix(); int APS5_VABI _FXp_ldexpx_nid_postfix(); int APS5_VABI _FXp_movx_nid_postfix(); diff --git a/core/libs/prx/libSceLibcInternal/include/RuntimeInternals.hpp b/core/libs/prx/libSceLibcInternal/include/RuntimeInternals.hpp index 4d3634a435..b3a225156c 100644 --- a/core/libs/prx/libSceLibcInternal/include/RuntimeInternals.hpp +++ b/core/libs/prx/libSceLibcInternal/include/RuntimeInternals.hpp @@ -11,7 +11,7 @@ int APS5_VABI _CStrxfrm_nid_postfix(); int APS5_VABI _CWcsxfrm_nid_postfix(); int APS5_VABI _Call_onceEx_nid_postfix(); int APS5_VABI _Closreg_nid_postfix(); -int APS5_VABI _Daysto_nid_postfix(); +int APS5_VABI _Daysto_nid_postfix(int year, int month); int APS5_VABI _Deletegloballocale_nid_postfix(); int APS5_VABI _Do_call_nid_postfix(); int APS5_VABI _Fac_tidy_nid_postfix(); diff --git a/core/libs/prx/libSceLibreSsl/CMakeLists.txt b/core/libs/prx/libSceLibreSsl/CMakeLists.txt index dfa0a287ee..702be242c9 100644 --- a/core/libs/prx/libSceLibreSsl/CMakeLists.txt +++ b/core/libs/prx/libSceLibreSsl/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(libSceLibreSsl SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Bignum.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Digest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Runtime.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Aes.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Error.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ocsp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Stack.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ui.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rsa.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/X509StoreContext.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Pkey.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpCipherCtx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Evp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/OcspResponse.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpCipher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpAes.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/X509Name.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ssl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/SslCtx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/SslCtxCallbacks.cpp) +add_library(libSceLibreSsl SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Bignum.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Digest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Runtime.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Aes.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Error.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ocsp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Stack.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ui.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rsa.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/X509StoreContext.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Pkey.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpCipherCtx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Evp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/OcspResponse.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpCipher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpAes.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/X509Name.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Ssl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/SslCtx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/SslCtxCallbacks.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/SslSession.cpp) target_include_directories(libSceLibreSsl PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(libSceLibreSsl PRIVATE mbedcrypto) configure_windows_unwind(libSceLibreSsl) @@ -282,6 +282,17 @@ if(BUILD_TESTING) set_tests_properties(guest_libressl_ssl_ctx_callbacks PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + + add_test_executable(guest_libressl_ssl_session_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibreSslSslSession.cpp) + target_include_directories(guest_libressl_ssl_session_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libressl_ssl_session_tests PRIVATE libSceLibreSsl) + configure_windows_unwind(guest_libressl_ssl_session_tests) + add_test(NAME guest_libressl_ssl_session COMMAND guest_libressl_ssl_session_tests) + set_tests_properties(guest_libressl_ssl_session PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(guest_libressl_ssl_session PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() endif() target_sources(libSceLibreSsl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/Cipher.cpp) diff --git a/core/libs/prx/libSceLibreSsl/Export.cpp b/core/libs/prx/libSceLibreSsl/Export.cpp index 0fdead5b82..341d6c696f 100644 --- a/core/libs/prx/libSceLibreSsl/Export.cpp +++ b/core/libs/prx/libSceLibreSsl/Export.cpp @@ -590,15 +590,6 @@ int APS5_VABI SSL_get1_session_nid_postfix(void) { return 0; } -int APS5_VABI SSL_get_certificate_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI SSL_get_current_cipher_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} int APS5_VABI SSL_get_error_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); @@ -625,20 +616,12 @@ int APS5_VABI SSL_get_peer_certificate_nid_postfix(void) { return 0; } -int APS5_VABI SSL_get_privatekey_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} int APS5_VABI SSL_get_servername_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; } -int APS5_VABI SSL_get_session_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} int APS5_VABI SSL_library_init_nid_postfix(void) { return 1; diff --git a/core/libs/prx/libSceLibreSsl/include/Api.hpp b/core/libs/prx/libSceLibreSsl/include/Api.hpp index 6ee7f5ee64..75282ec9f0 100644 --- a/core/libs/prx/libSceLibreSsl/include/Api.hpp +++ b/core/libs/prx/libSceLibreSsl/include/Api.hpp @@ -523,6 +523,23 @@ struct LibreSslX509Name { int canonEnclen; }; +struct LibreSslCertKey { + void* x509; + void* privatekey; + const void* digest; +}; + +struct LibreSslCert { + LibreSslCertKey* key; + unsigned char rest[248]; +}; + +struct LibreSslSession { + unsigned char beforeCipher[168]; + const void* cipher; + unsigned char rest[56]; +}; + extern "C" { std::int64_t APS5_VABI ASN1_INTEGER_get_nid_postfix(const Asn1String* value); @@ -775,8 +792,8 @@ void APS5_VABI SSL_get0_alpn_selected_nid_postfix(const LibreSslSsl* ssl, const int APS5_VABI SSL_get0_param_nid_postfix(void); int APS5_VABI SSL_get1_session_nid_postfix(void); void* APS5_VABI SSL_get_SSL_CTX_nid_postfix(const LibreSslSsl* ssl); -int APS5_VABI SSL_get_certificate_nid_postfix(void); -int APS5_VABI SSL_get_current_cipher_nid_postfix(void); +void* APS5_VABI SSL_get_certificate_nid_postfix(const LibreSslSsl* ssl); +const void* APS5_VABI SSL_get_current_cipher_nid_postfix(const LibreSslSsl* ssl); int APS5_VABI SSL_get_error_nid_postfix(void); int APS5_VABI SSL_get_ex_data_nid_postfix(void); int APS5_VABI SSL_get_ex_data_X509_STORE_CTX_idx_nid_postfix(void); @@ -784,13 +801,13 @@ int APS5_VABI SSL_get_ex_new_index_nid_postfix(std::int64_t argl, void* argp, Li int APS5_VABI SSL_get_fd_nid_postfix(void); int APS5_VABI SSL_get_peer_cert_chain_nid_postfix(void); int APS5_VABI SSL_get_peer_certificate_nid_postfix(void); -int APS5_VABI SSL_get_privatekey_nid_postfix(void); void* APS5_VABI SSL_get_rbio_nid_postfix(const LibreSslSsl* ssl); +void* APS5_VABI SSL_get_privatekey_nid_postfix(const LibreSslSsl* ssl); int APS5_VABI SSL_get_servername_nid_postfix(void); -int APS5_VABI SSL_get_session_nid_postfix(void); int APS5_VABI SSL_get_shutdown_nid_postfix(const LibreSslSsl* ssl); std::int64_t APS5_VABI SSL_get_verify_result_nid_postfix(const LibreSslSsl* ssl); void* APS5_VABI SSL_get_wbio_nid_postfix(const LibreSslSsl* ssl); +LibreSslSession* APS5_VABI SSL_get_session_nid_postfix(const LibreSslSsl* ssl); int APS5_VABI SSL_library_init_nid_postfix(void); void APS5_VABI SSL_load_error_strings_nid_postfix(void); int APS5_VABI SSL_new_nid_postfix(void); diff --git a/core/libs/prx/libSceLibreSsl/src/SslSession.cpp b/core/libs/prx/libSceLibreSsl/src/SslSession.cpp new file mode 100644 index 0000000000..800b903fd4 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/src/SslSession.cpp @@ -0,0 +1,54 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" +#include +#include +#include +#include "prx/libc/include/General.hpp" + +static_assert(sizeof(LibreSslCertKey) == 24); +static_assert(offsetof(LibreSslCertKey, privatekey) == 8); +static_assert(sizeof(LibreSslCert) == 256); +static_assert(sizeof(LibreSslSession) == 232); +static_assert(offsetof(LibreSslSession, cipher) == 168); + +namespace { + +const LibreSslSsl& Connection(const LibreSslSsl* ssl, const char* function) { + if (!ssl) throw std::invalid_argument(std::string(function) + ": null connection"); + return *ssl; +} + +LibreSslSession* Session(const LibreSslSsl* ssl, const char* function) { + return static_cast(Connection(ssl, function).session); +} + +const LibreSslCertKey* CurrentKey(const LibreSslSsl* ssl, const char* function) { + const LibreSslCert* cert = static_cast(Connection(ssl, function).cert); + if (!cert) return nullptr; + if (!cert->key) throw std::invalid_argument(std::string(function) + ": null current key"); + return cert->key; +} + +} + +extern "C" { + +LibreSslSession* APS5_VABI SSL_get_session_nid_postfix(const LibreSslSsl* ssl) { + return Session(ssl, __func__); +} + +const void* APS5_VABI SSL_get_current_cipher_nid_postfix(const LibreSslSsl* ssl) { + const LibreSslSession* session = Session(ssl, __func__); + return session ? session->cipher : nullptr; +} + +void* APS5_VABI SSL_get_certificate_nid_postfix(const LibreSslSsl* ssl) { + const LibreSslCertKey* key = CurrentKey(ssl, __func__); + return key ? key->x509 : nullptr; +} + +void* APS5_VABI SSL_get_privatekey_nid_postfix(const LibreSslSsl* ssl) { + const LibreSslCertKey* key = CurrentKey(ssl, __func__); + return key ? key->privatekey : nullptr; +} + +} diff --git a/core/libs/prx/libSceLibreSsl3/CMakeLists.txt b/core/libs/prx/libSceLibreSsl3/CMakeLists.txt index 8371d3cbf8..731a049eca 100644 --- a/core/libs/prx/libSceLibreSsl3/CMakeLists.txt +++ b/core/libs/prx/libSceLibreSsl3/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(libSceLibreSsl3 SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Digest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/IntegerDecoder.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Key.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpDigest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/X509PubkeyParam.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ObjCmp.cpp) +add_library(libSceLibreSsl3 SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Digest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/IntegerDecoder.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Key.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/EvpDigest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/X509PubkeyParam.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ObjCmp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/X509Extensions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Asn1.cpp) target_include_directories(libSceLibreSsl3 PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(libSceLibreSsl3 PRIVATE libSceLibreSsl libc) configure_windows_unwind(libSceLibreSsl3) @@ -145,6 +145,28 @@ if(BUILD_TESTING) set_tests_properties(guest_crypto_memcmp guest_libressl3_digest guest_libressl3_asn1 guest_libressl3_key_reference guest_libressl3_evp guest_libressl3_version guest_libressl3_x509_pubkey_param PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + + add_test_executable(guest_libressl3_asn1_string_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibreSsl3Asn1.cpp) + target_include_directories(guest_libressl3_asn1_string_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libressl3_asn1_string_tests PRIVATE libSceLibreSsl3 libc) + configure_windows_unwind(guest_libressl3_asn1_string_tests) + add_test(NAME guest_libressl3_asn1_string COMMAND guest_libressl3_asn1_string_tests) + set_tests_properties(guest_libressl3_asn1_string PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(guest_libressl3_asn1_string PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() + + add_test_executable(guest_libressl3_x509_extensions_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibreSsl3X509Extensions.cpp) + target_include_directories(guest_libressl3_x509_extensions_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libressl3_x509_extensions_tests PRIVATE libSceLibreSsl3) + configure_windows_unwind(guest_libressl3_x509_extensions_tests) + add_test(NAME guest_libressl3_x509_extensions COMMAND guest_libressl3_x509_extensions_tests) + set_tests_properties(guest_libressl3_x509_extensions PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(guest_libressl3_x509_extensions PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() endif() if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL "Linux" AND EXISTS "${LIBS_INCLUDE_DIR}/prx/libSceLibreSsl/src/Evp.cpp") diff --git a/core/libs/prx/libSceLibreSsl3/Export.cpp b/core/libs/prx/libSceLibreSsl3/Export.cpp index 6ba83e997a..c942136dd4 100644 --- a/core/libs/prx/libSceLibreSsl3/Export.cpp +++ b/core/libs/prx/libSceLibreSsl3/Export.cpp @@ -8,21 +8,11 @@ extern "C" { APS5_DUMMY_FUN -int APS5_VABI ASN1_INTEGER_free_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI ASN1_OBJECT_free_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; } -int APS5_VABI ASN1_STRING_get0_data_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI BIO_up_ref_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -286,11 +276,6 @@ int APS5_VABI X509_STORE_up_ref_nid_postfix(void) { return 0; } -int APS5_VABI X509_get0_extensions_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI X509_get0_notAfter_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -306,16 +291,6 @@ int APS5_VABI X509_get0_signature_nid_postfix(void) { return 0; } -int APS5_VABI X509_get_ext_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI X509_get_ext_count_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI X509_get_version_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceLibreSsl3/include/Api.hpp b/core/libs/prx/libSceLibreSsl3/include/Api.hpp index e0191ebfb1..c08e3f750d 100644 --- a/core/libs/prx/libSceLibreSsl3/include/Api.hpp +++ b/core/libs/prx/libSceLibreSsl3/include/Api.hpp @@ -6,6 +6,25 @@ #include "prx/libSceLibreSsl/include/Api.hpp" #include "prx/libSceLibreSsl3/include/Cipher.hpp" +struct LibreSsl3Stack { + int num; + char** data; + int sorted; + int numAlloc; + void* comp; +}; + +struct LibreSsl3ExtensionsCertInfo { + unsigned char beforeExtensions[72]; + const LibreSsl3Stack* extensions; + unsigned char rest[24]; +}; + +struct LibreSsl3ExtensionsX509 { + const LibreSsl3ExtensionsCertInfo* certInfo; + unsigned char rest[208]; +}; + struct LibreSsl3Asn1String { int length; int type; @@ -32,9 +51,9 @@ static_assert(offsetof(LibreSsl3X509Pubkey, publicKey) == 8); extern "C" { -int APS5_VABI ASN1_INTEGER_free_nid_postfix(void); +void APS5_VABI ASN1_INTEGER_free_nid_postfix(Asn1String* integer); int APS5_VABI ASN1_OBJECT_free_nid_postfix(void); -int APS5_VABI ASN1_STRING_get0_data_nid_postfix(void); +const unsigned char* APS5_VABI ASN1_STRING_get0_data_nid_postfix(const Asn1String* string); int APS5_VABI BIO_up_ref_nid_postfix(void); int APS5_VABI BIO_vfree_nid_postfix(void); int APS5_VABI CRYPTO_memcmp_nid_postfix(const void* first, const void* second, std::size_t length); @@ -99,12 +118,12 @@ int APS5_VABI X509_STORE_CTX_free_nid_postfix(void); int APS5_VABI X509_STORE_CTX_init_nid_postfix(void); int APS5_VABI X509_STORE_CTX_new_nid_postfix(void); int APS5_VABI X509_STORE_up_ref_nid_postfix(void); -int APS5_VABI X509_get0_extensions_nid_postfix(void); +const LibreSsl3Stack* APS5_VABI X509_get0_extensions_nid_postfix(const LibreSsl3ExtensionsX509* certificate); int APS5_VABI X509_get0_notAfter_nid_postfix(void); int APS5_VABI X509_get0_notBefore_nid_postfix(void); int APS5_VABI X509_get0_signature_nid_postfix(void); -int APS5_VABI X509_get_ext_nid_postfix(void); -int APS5_VABI X509_get_ext_count_nid_postfix(void); +void* APS5_VABI X509_get_ext_nid_postfix(const LibreSsl3ExtensionsX509* certificate, int loc); +int APS5_VABI X509_get_ext_count_nid_postfix(const LibreSsl3ExtensionsX509* certificate); int APS5_VABI X509_get_version_nid_postfix(void); int APS5_VABI X509_getm_notAfter_nid_postfix(void); int APS5_VABI X509_getm_notBefore_nid_postfix(void); diff --git a/core/libs/prx/libSceLibreSsl3/src/Asn1.cpp b/core/libs/prx/libSceLibreSsl3/src/Asn1.cpp new file mode 100644 index 0000000000..8948cdf2f6 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl3/src/Asn1.cpp @@ -0,0 +1,32 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include +#include +#include +#include +#include +#include "prx/libc/include/General.hpp" + +namespace { + +constexpr std::int64_t Asn1StringFlagNdef = 0x010; + +} + +extern "C" { +const unsigned char* APS5_VABI ASN1_STRING_get0_data_nid_postfix(const Asn1String* string) { + if (!string) throw std::invalid_argument(std::string(__func__) + ": null string"); + return string->data; +} + +void APS5_VABI ASN1_INTEGER_free_nid_postfix(Asn1String* integer) { + if (!integer) return; + if (!(integer->flags & Asn1StringFlagNdef) && integer->data) { + if (integer->length < 0) throw std::invalid_argument(std::string(__func__) + ": negative length"); + std::memset(integer->data, 0, static_cast(integer->length)); + free_nid_postfix(integer->data); + } + free_nid_postfix(integer); +} + +} diff --git a/core/libs/prx/libSceLibreSsl3/src/X509Extensions.cpp b/core/libs/prx/libSceLibreSsl3/src/X509Extensions.cpp new file mode 100644 index 0000000000..d9aa68ab68 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl3/src/X509Extensions.cpp @@ -0,0 +1,41 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" +#include +#include +#include +#include "prx/libc/include/General.hpp" + +static_assert(sizeof(LibreSsl3Stack) == 32); +static_assert(offsetof(LibreSsl3Stack, data) == 8); +static_assert(sizeof(LibreSsl3ExtensionsCertInfo) == 104); +static_assert(offsetof(LibreSsl3ExtensionsCertInfo, extensions) == 72); +static_assert(sizeof(LibreSsl3ExtensionsX509) == 216); + +namespace { + +const LibreSsl3Stack* Extensions(const LibreSsl3ExtensionsX509* certificate, const char* function) { + if (!certificate) throw std::invalid_argument(std::string(function) + ": null certificate"); + if (!certificate->certInfo) throw std::invalid_argument(std::string(function) + ": null certificate info"); + return certificate->certInfo->extensions; +} + +} + +extern "C" { + +const LibreSsl3Stack* APS5_VABI X509_get0_extensions_nid_postfix(const LibreSsl3ExtensionsX509* certificate) { + return Extensions(certificate, __func__); +} + +int APS5_VABI X509_get_ext_count_nid_postfix(const LibreSsl3ExtensionsX509* certificate) { + const LibreSsl3Stack* extensions = Extensions(certificate, __func__); + return extensions ? extensions->num : 0; +} + +void* APS5_VABI X509_get_ext_nid_postfix(const LibreSsl3ExtensionsX509* certificate, int loc) { + const LibreSsl3Stack* extensions = Extensions(certificate, __func__); + if (!extensions || loc < 0 || loc >= extensions->num) return nullptr; + if (!extensions->data) throw std::invalid_argument(std::string(__func__) + ": null extension array"); + return extensions->data[loc]; +} + +} diff --git a/core/libs/prx/libSceNKWebKit/Export.cpp b/core/libs/prx/libSceNKWebKit/Export.cpp index b2ecc459d8..8ea08a2e67 100644 --- a/core/libs/prx/libSceNKWebKit/Export.cpp +++ b/core/libs/prx/libSceNKWebKit/Export.cpp @@ -19454,10 +19454,6 @@ int APS5_VABI _ZN3WTF26normalizeLineEndingsToCRLFEONS_6VectorIhLm0ENS_15CrashOnO NotImplemented_nid_no_patch(__func__); } -int APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_() { - NotImplemented_nid_no_patch(__func__); -} - int APS5_VABI _ZN3WTF28encodeWithURLEscapeSequencesERKNS_6StringE() { NotImplemented_nid_no_patch(__func__); } diff --git a/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp b/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp index 1294a580d9..d3f9823f6a 100644 --- a/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp +++ b/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp @@ -1834,7 +1834,6 @@ int APS5_VABI _ZN3WTF24normalizeLineEndingsToLFEONS_6VectorIhLm0ENS_15CrashOnOve int APS5_VABI _ZN3WTF25activateSignalHandlersForENS_6SignalE(); int APS5_VABI _ZN3WTF26getAndResetAccumulatedLogsEv(); int APS5_VABI _ZN3WTF26normalizeLineEndingsToCRLFEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE(); -int APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_(); int APS5_VABI _ZN3WTF28encodeWithURLEscapeSequencesERKNS_6StringE(); int APS5_VABI _ZN3WTF28normalizeLineEndingsToNativeEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE(); int APS5_VABI _ZN3WTF30numCodeUnitsInGraphemeClustersENS_10StringViewEj(); diff --git a/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp b/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp index 860b654119..04d520ffb2 100644 --- a/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp +++ b/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp @@ -136,6 +136,7 @@ WTF::LocalTimeOffset APS5_VABI _ZN3WTF24calculateLocalTimeOffsetEdNS_8TimeTypeE( void APS5_VABI _ZN3WTF25addLanguageChangeObserverEPvPFvS0_E(void* context, void (APS5_VABI *observer)(void*)); void APS5_VABI _ZN3WTF25fastDecommitAlignedMemoryEPvm(void*, std::size_t); void APS5_VABI _ZN3WTF25fastMallocDumpMallocStatsEv(); +bool APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_(const NKWebKit::WtfAbi::URL* a, const NKWebKit::WtfAbi::URL* b); void APS5_VABI _ZN3WTF27releaseFastMallocFreeMemoryEv(); NKWebKit::WtfAbi::String APS5_VABI _ZN3WTF28displayNameForLanguageLocaleERKNS_6StringE(const NKWebKit::WtfAbi::String* localeName); void APS5_VABI _ZN3WTF28removeLanguageChangeObserverEPv(void* context); diff --git a/core/libs/prx/libSceNKWebKit/src/WtfString.cpp b/core/libs/prx/libSceNKWebKit/src/WtfString.cpp index 32241b1e3d..f6ed222e4b 100644 --- a/core/libs/prx/libSceNKWebKit/src/WtfString.cpp +++ b/core/libs/prx/libSceNKWebKit/src/WtfString.cpp @@ -1116,6 +1116,27 @@ bool APS5_VABI _ZN3WTF31equalIgnoringFragmentIdentifierERKNS_3URLES2_(const URL* return EqualViews(ViewWithoutFragment(first), ViewWithoutFragment(second)); } +bool APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_(const URL* a, const URL* b) { + const auto& first = Checked(a); + const auto& second = Checked(b); + unsigned schemeEndA = first.bits >> 6; + unsigned schemeEndB = second.bits >> 6; + if (schemeEndA != schemeEndB) return false; + unsigned hostStartA = HostStart(first); + unsigned hostStartB = HostStart(second); + if (first.hostEnd < hostStartA || second.hostEnd < hostStartB) return false; + unsigned hostLengthA = first.hostEnd - hostStartA; + unsigned hostLengthB = second.hostEnd - hostStartB; + if (hostLengthA != hostLengthB) return false; + auto viewA = View(first.impl); + auto viewB = View(second.impl); + if (schemeEndA > viewA.length || schemeEndB > viewB.length) return false; + if (hostStartA + hostLengthA > viewA.length || hostStartB + hostLengthB > viewB.length) return false; + if (!EqualViews(Slice(viewA, 0, schemeEndA), Slice(viewB, 0, schemeEndB), true)) return false; + if (!EqualViews(Slice(viewA, hostStartA, hostLengthA), Slice(viewB, hostStartB, hostLengthB), true)) return false; + return URLPort(first) == URLPort(second); +} + void APS5_VABI _ZN3WTF3URL10invalidateEv(URL* self) { auto& url = Checked(self); url.bits = 0; diff --git a/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp b/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp index 9add2fce5e..d28828914b 100644 --- a/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp +++ b/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp @@ -804,6 +804,7 @@ const auto URLJavaScript = &_ZNK3WTF3URL20protocolIsJavaScriptEv; const auto URLInvalidate = &_ZN3WTF3URL10invalidateEv; const auto URLEqualIgnoringFragment = &_ZN3WTF31equalIgnoringFragmentIdentifierERKNS_3URLES2_; const auto URLPortAllowed = &_ZN3WTF11portAllowedERKNS_3URLE; +const auto URLProtocolHostAndPortAreEqual = &_ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_; const auto IsJavaScript = &_ZN3WTF20protocolIsJavaScriptENS_10StringViewE; const auto IsHTTP = &_ZN3WTF22protocolIsInHTTPFamilyENS_10StringViewE; const auto JSRealloc = &_ZN3WTF14jsValueReallocEPvm; @@ -1386,6 +1387,127 @@ void TestURLsAndReallocation() { Check(URLPortAllowed(&urlWraparoundPort)); Check(URLPortAllowed(&absent)); Throws([&] { URLPortAllowed(nullptr); }); + { + Check(URLProtocolHostAndPortAreEqual(&url, &url)); + Check(URLProtocolHostAndPortAreEqual(&url, &urlNoFrag)); + Check(URLProtocolHostAndPortAreEqual(&url, &urlDiffQuery)); + Check(URLProtocolHostAndPortAreEqual(&url, &urlDiffPath)); + auto urlUpperSchemeStr = FromUTF8Z(U8("HTTPS://u%20:p%40@example.test:8443/a/b?q=1#frag")); + URL urlUpperScheme = url; + urlUpperScheme.impl = urlUpperSchemeStr.impl; + Check(URLProtocolHostAndPortAreEqual(&url, &urlUpperScheme)); + auto urlUpperHostStr = FromUTF8Z(U8("https://u%20:p%40@EXAMPLE.TEST:8443/a/b?q=1#frag")); + URL urlUpperHost = url; + urlUpperHost.impl = urlUpperHostStr.impl; + Check(URLProtocolHostAndPortAreEqual(&url, &urlUpperHost)); + auto urlHttpStr = FromUTF8Z(U8("http://u%20:p%40@example.test:8443/a/b?q=1#frag")); + URL urlHttp = url; + urlHttp.impl = urlHttpStr.impl; + urlHttp.bits = 1U | 2U | (5U << 3) | (4U << 6); + Check(!URLProtocolHostAndPortAreEqual(&url, &urlHttp)); + Check(!URLProtocolHostAndPortAreEqual(&url, &urlDiffHost)); + auto urlShortHostStr = FromUTF8Z(U8("https://u%20:p%40@ex.test:8443/a/b?q=1#frag")); + URL urlShortHost = url; + urlShortHost.impl = urlShortHostStr.impl; + urlShortHost.hostEnd = 25; + Check(!URLProtocolHostAndPortAreEqual(&url, &urlShortHost)); + auto urlDiffPortStr = FromUTF8Z(U8("https://u%20:p%40@example.test:9443/a/b?q=1#frag")); + URL urlDiffPort = url; + urlDiffPort.impl = urlDiffPortStr.impl; + Check(!URLProtocolHostAndPortAreEqual(&url, &urlDiffPort)); + auto urlPort80Str = FromUTF8Z(U8("http://example.test:80/path")); + URL urlPort80{urlPort80Str.impl, 1U | 2U | (3U << 3) | (4U << 6), 7, 7, 7, 19, 23, 27, 27}; + auto urlNoPortStr = FromUTF8Z(U8("http://example.test/path")); + URL urlNoPort{urlNoPortStr.impl, 1U | 2U | (0U << 3) | (4U << 6), 7, 7, 7, 19, 20, 24, 24}; + Check(!URLProtocolHostAndPortAreEqual(&urlPort80, &urlNoPort)); + auto urlNoPort2Str = FromUTF8Z(U8("http://example.test/other")); + URL urlNoPort2{urlNoPort2Str.impl, 1U | 2U | (0U << 3) | (4U << 6), 7, 7, 7, 19, 20, 25, 25}; + Check(URLProtocolHostAndPortAreEqual(&urlNoPort, &urlNoPort2)); + auto widePort = Create16(u"http://wide.test:8080/path", 26); + URL urlWidePort{widePort.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 16, 22, 26, 26}; + auto widePortMatch = Create16(u"HTTP://WIDE.TEST:8080/other", 27); + URL urlWideMatch{widePortMatch.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 16, 22, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWidePort, &urlWideMatch)); + auto narrowPortStr = FromUTF8Z(U8("http://wide.test:8080/narrow")); + URL urlNarrowPort{narrowPortStr.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 16, 22, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlWidePort, &urlNarrowPort)); + auto urlPort0Str = FromUTF8Z(U8("http://example.test:0/path")); + URL urlPort0{urlPort0Str.impl, 1U | 2U | (2U << 3) | (4U << 6), 7, 7, 7, 19, 22, 26, 26}; + Check(URLProtocolHostAndPortAreEqual(&urlPort0, &urlPort0)); + Check(!URLProtocolHostAndPortAreEqual(&urlPort0, &urlNoPort)); + Check(!URLProtocolHostAndPortAreEqual(&urlPort0, &urlPort80)); + auto urlPortMaxStr = FromUTF8Z(U8("http://example.test:65535/path")); + URL urlPortMax{urlPortMaxStr.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 19, 26, 30, 30}; + Check(URLProtocolHostAndPortAreEqual(&urlPortMax, &urlPortMax)); + Check(!URLProtocolHostAndPortAreEqual(&urlPortMax, &urlPort80)); + auto urlEmptyPortStr = FromUTF8Z(U8("http://example.test:/path")); + URL urlEmptyPort{urlEmptyPortStr.impl, 1U | 2U | (1U << 3) | (4U << 6), 7, 7, 7, 19, 21, 25, 25}; + Check(!URLProtocolHostAndPortAreEqual(&urlEmptyPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlEmptyPort, &urlNoPort)); + auto urlMalformedPortStr = FromUTF8Z(U8("http://example.test:8x/path")); + URL urlMalformedPort{urlMalformedPortStr.impl, 1U | 2U | (3U << 3) | (4U << 6), 7, 7, 7, 19, 23, 27, 27}; + Check(!URLProtocolHostAndPortAreEqual(&urlMalformedPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlMalformedPort, &urlNoPort)); + auto urlOutOfRangePortStr = FromUTF8Z(U8("http://example.test:70000/path")); + URL urlOutOfRangePort{urlOutOfRangePortStr.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 19, 26, 30, 30}; + Check(!URLProtocolHostAndPortAreEqual(&urlOutOfRangePort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlOutOfRangePort, &urlNoPort)); + auto urlPlusPort80Str = FromUTF8Z(U8("http://example.test:+80/path")); + URL urlPlusPort80{urlPlusPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlPlusPort80, &urlPort80)); + Check(!URLProtocolHostAndPortAreEqual(&urlPlusPort80, &urlNoPort)); + auto urlSpacePort80Str = FromUTF8Z(U8("http://example.test: 80 /path")); + URL urlSpacePort80{urlSpacePort80Str.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 19, 25, 29, 29}; + Check(URLProtocolHostAndPortAreEqual(&urlSpacePort80, &urlPort80)); + Check(!URLProtocolHostAndPortAreEqual(&urlSpacePort80, &urlNoPort)); + auto urlTabPort80Str = FromUTF8Z(U8("http://example.test:\t80/path")); + URL urlTabPort80{urlTabPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlTabPort80, &urlPort80)); + auto urlNewlinePort80Str = FromUTF8Z(U8("http://example.test:\n80/path")); + URL urlNewlinePort80{urlNewlinePort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlNewlinePort80, &urlPort80)); + auto urlReturnPort80Str = FromUTF8Z(U8("http://example.test:\r80/path")); + URL urlReturnPort80{urlReturnPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlReturnPort80, &urlPort80)); + auto urlFormFeedPort80Str = FromUTF8Z(U8("http://example.test:\f80/path")); + URL urlFormFeedPort80{urlFormFeedPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlFormFeedPort80, &urlPort80)); + auto widePlusPort = Create16(u"http://wide.test:+8080/path", 27); + URL urlWidePlusPort{widePlusPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWidePlusPort, &urlWidePort)); + auto wideSpacePort = Create16(u"http://wide.test: 8080 /path", 28); + URL urlWideSpacePort{wideSpacePort.impl, 1U | 2U | (7U << 3) | (4U << 6), 7, 7, 7, 16, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlWideSpacePort, &urlWidePort)); + auto wideTabPort = Create16(u"http://wide.test:\t8080/path", 27); + URL urlWideTabPort{wideTabPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideTabPort, &urlWidePort)); + auto wideNewlinePort = Create16(u"http://wide.test:\n8080/path", 27); + URL urlWideNewlinePort{wideNewlinePort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideNewlinePort, &urlWidePort)); + auto wideReturnPort = Create16(u"http://wide.test:\r8080/path", 27); + URL urlWideReturnPort{wideReturnPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideReturnPort, &urlWidePort)); + auto wideFormFeedPort = Create16(u"http://wide.test:\f8080/path", 27); + URL urlWideFormFeedPort{wideFormFeedPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideFormFeedPort, &urlWidePort)); + auto urlMinusPortStr = FromUTF8Z(U8("http://example.test:-80/path")); + URL urlMinusPort{urlMinusPortStr.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(!URLProtocolHostAndPortAreEqual(&urlMinusPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlMinusPort, &urlNoPort)); + auto urlBarePlusPortStr = FromUTF8Z(U8("http://example.test:+/path")); + URL urlBarePlusPort{urlBarePlusPortStr.impl, 1U | 2U | (2U << 3) | (4U << 6), 7, 7, 7, 19, 22, 26, 26}; + Check(!URLProtocolHostAndPortAreEqual(&urlBarePlusPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlBarePlusPort, &urlNoPort)); + auto urlPortOutOfBoundsStr = FromUTF8Z(U8("http://example.test:80")); + URL urlPortOutOfBounds{urlPortOutOfBoundsStr.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 19, 24, 22, 22}; + Check(URLProtocolHostAndPortAreEqual(&urlPortOutOfBounds, &urlNoPort)); + Check(!URLProtocolHostAndPortAreEqual(&urlPortOutOfBounds, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&absent, &absent)); + Check(!URLProtocolHostAndPortAreEqual(&url, &absent)); + Check(!URLProtocolHostAndPortAreEqual(&absent, &url)); + Throws([&] { URLProtocolHostAndPortAreEqual(nullptr, &url); }); + Throws([&] { URLProtocolHostAndPortAreEqual(&url, nullptr); }); + } URLInvalidate(&url); Check(url.impl == string.impl && url.bits == 0 && url.userStart == 0 && url.userEnd == 0); Check(url.passwordEnd == 0 && url.hostEnd == 0 && url.pathEnd == 0 && url.pathAfterLastSlash == 0 && url.queryEnd == 0); diff --git a/core/libs/prx/libSceNpCppWebApi/Export.cpp b/core/libs/prx/libSceNpCppWebApi/Export.cpp index d658955335..ec63a71bcb 100644 --- a/core/libs/prx/libSceNpCppWebApi/Export.cpp +++ b/core/libs/prx/libSceNpCppWebApi/Export.cpp @@ -347,6 +347,7 @@ int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi12downloadDataEi static constexpr int ParameterNotInitialized = static_cast(0x80553502); static constexpr int ParameterInvalidArgument = static_cast(0x80553503); +static constexpr int ParameterAllocationFailed = static_cast(0x80553504); static constexpr int ParameterAlreadyInitialized = static_cast(0x8055350f); static constexpr int ParameterTerminatedUninitialized = static_cast(0x80553510); static constexpr int ParameterBodyMissing = static_cast(0x80553512); @@ -1738,7 +1739,8 @@ bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_12Le static constexpr std::uint64_t VectorBodyMagic = 0x434e507056656342ULL; struct VectorBody { std::uint64_t magic; - std::uint8_t reserved[0x28]; + void* libContext; + std::uint8_t reserved[0x20]; std::int32_t referenceCount; std::int32_t elementKind; // 1 = IntrusivePtr elements, 2 = String elements void* elements; @@ -1765,6 +1767,14 @@ static void APS5_VABI DestroyVectorBody(void* object) { } static VectorBody* VectorBodyFor(IntrusivePtr* self, const std::int32_t elementKind, const char* function) { + auto* direct = static_cast(static_cast(self)); + if (direct != nullptr && direct->magic == VectorBodyMagic) { + if (direct->elementKind != elementKind) { + NotImplemented_nid_no_patch(function); + return nullptr; + } + return direct; + } auto* body = static_cast(self->object); if (body == nullptr) { body = static_cast(std::calloc(1, sizeof(VectorBody))); @@ -1772,6 +1782,7 @@ static VectorBody* VectorBodyFor(IntrusivePtr* self, const std::int32_t elementK body->magic = VectorBodyMagic; body->referenceCount = 1; body->elementKind = elementKind; + body->libContext = self->libContext; self->object = body; self->deleter = &DestroyVectorBody; return body; @@ -1794,15 +1805,22 @@ static bool VectorGrow(VectorBody* body, const std::size_t elementSize) { return true; } +static const VectorBody* ResolveVectorBody(const void* self) { + const auto* direct = static_cast(self); + if (direct == nullptr) return nullptr; + if (direct->magic == VectorBodyMagic) return direct; + return static_cast(static_cast(self)->object); +} + static std::uint64_t HostVectorSize(const void* self, const char* function) { - const auto* body = static_cast(static_cast(self)->object); + const auto* body = ResolveVectorBody(self); if (body == nullptr) return 0; if (body->magic != VectorBodyMagic) NotImplemented_nid_no_patch(function); return body->size; } static IntrusivePtr* HostVectorElement(void* self, const std::uint64_t index, const char* function) { - auto* body = static_cast(static_cast(self)->object); + auto* body = const_cast(ResolveVectorBody(self)); if (body == nullptr || body->magic != VectorBodyMagic || body->elementKind != 1) NotImplemented_nid_no_patch(function); return static_cast(body->elements) + index; } @@ -1859,6 +1877,103 @@ static CommonString* StringVectorElements(const IntrusivePtr* self, const bool e auto* elements = static_cast(body->elements); return end && body->size != 0 ? elements + body->size : elements; } + +static const VectorBody* HostVectorBody(const void* self, const std::int32_t elementKind, const char* function) { + const auto* body = ResolveVectorBody(self); + if (body == nullptr) return nullptr; + if (body->magic != VectorBodyMagic || body->elementKind != elementKind) NotImplemented_nid_no_patch(function); + return body; +} + +static void* HostVectorBegin(void* out, const void* self, const std::int32_t elementKind, const char* function) { + const VectorBody* body = HostVectorBody(self, elementKind, function); + auto* it = static_cast(out); + it->referenceCount = 0; + it->element = body != nullptr ? body->elements : nullptr; + return out; +} + +static void* HostVectorEnd(void* out, const void* self, const std::int32_t elementKind, const std::size_t elementSize, const char* function) { + const VectorBody* body = HostVectorBody(self, elementKind, function); + auto* it = static_cast(out); + it->referenceCount = 0; + it->element = body != nullptr ? static_cast(body->elements) + body->size * elementSize : nullptr; + return out; +} + +static void* HostIteratorAdvance(void* self, const std::size_t elementSize) { + auto* it = static_cast(self); + it->element = static_cast(it->element) + elementSize; + return self; +} + +static bool HostIteratorNotEqual(const void* self, const void* other) { + return static_cast(self)->element != static_cast(other)->element; +} + +static bool VectorReserve(VectorBody* body, const std::size_t elementSize, const std::uint64_t count) { + if (body->capacity >= count) return true; + std::uint64_t capacity = body->capacity != 0 ? body->capacity : 4; + while (capacity < count) capacity *= 2; + void* elements = std::realloc(body->elements, static_cast(capacity) * elementSize); + if (elements == nullptr) return false; + body->elements = elements; + body->capacity = capacity; + return true; +} + +static int HostVectorCopyFrom(IntrusivePtr* self, const IntrusivePtr* source, const char* function) { + VectorBody* body = VectorBodyFor(self, 1, function); + if (body == nullptr) return ParameterAllocationFailed; + const auto* sourceDirect = static_cast(static_cast(source)); + const bool sourceIsBody = sourceDirect != nullptr && sourceDirect->magic == VectorBodyMagic; + const auto* sourceBody = sourceIsBody ? sourceDirect : static_cast(source->object); + void** const selfContext = body == static_cast(static_cast(self)) ? &body->libContext : &self->libContext; + void* const sourceContext = sourceIsBody ? sourceDirect->libContext : source->libContext; + if (*selfContext == nullptr) *selfContext = sourceContext; + if (body->libContext == nullptr) body->libContext = *selfContext; + if (sourceBody != nullptr && (sourceBody->magic != VectorBodyMagic || sourceBody->elementKind != 1)) { + NotImplemented_nid_no_patch(function); + return ParameterAllocationFailed; + } + auto* elements = static_cast(body->elements); + for (std::uint64_t index = 0; index < body->size; ++index) { + ReleaseIntrusivePtr(&elements[index], ReferenceCountOffset, function); + } + body->size = 0; + const std::uint64_t count = sourceBody != nullptr ? sourceBody->size : 0; + if (count == 0) return 0; + if (!VectorReserve(body, sizeof(IntrusivePtr), count)) return ParameterAllocationFailed; + elements = static_cast(body->elements); + const auto* sourceElements = static_cast(sourceBody->elements); + for (std::uint64_t index = 0; index < count; ++index) { + elements[index] = {}; + CopyIntrusivePtr(&elements[index], &sourceElements[index], ReferenceCountOffset); + } + body->size = count; + return 0; +} + +static void* CopyMemberIntrusivePtr(void* out, const void* self, const std::size_t memberOffset, const std::size_t referenceCountOffset) { + CopyIntrusivePtr(static_cast(out), + reinterpret_cast(static_cast(self) + memberOffset), + referenceCountOffset); + return out; +} + +static void InitHostString(void* field, void* context) { + *static_cast(field) = {}; + static_cast(field)->libContext = context; +} + +static void DestroyHostString(void* field) { + auto* str = static_cast(field); + if (str->buffer != nullptr) { + std::free(str->buffer); + str->buffer = nullptr; + str->bufferSize = 0; + } +} // -------------------------------------------------------------------------- // SessionManager2V1 and extra Common symbols, from a title dump whose modules lack // libSceNpCppWebApi.prx. @@ -2081,10 +2196,8 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V1 CopyIntrusivePtr(self, source, 0x00); } -void* APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V130PostPlayerSessionsResponseBody17getPlayerSessionsEv(void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; +void* APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V130PostPlayerSessionsResponseBody17getPlayerSessionsEv(void* out, void* self) { + return CopyMemberIntrusivePtr(out, self, 0x30, VectorReferenceCountOffset); } int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi18leavePlayerSessionEiRKNS4_29ParameterToLeavePlayerSessionERNS1_6Common11TransactionINS8_15DefaultResponseENS8_12IntrusivePtrINS8_18ResponseHeaderBaseEEEEE() { @@ -2391,9 +2504,7 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V1 } const char* APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V113PlayerSession12getSessionIdEv(const void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; + return static_cast(self) + 0x10; } int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V158PostPlayerSessionsSessionIdMemberPlayersRequestBodyFactory6createEPNS1_6Common10LibContextERKNS5_6VectorINS5_12IntrusivePtrINS3_26RequestPlayerSessionPlayerEEEEEPNS9_INS3_51PostPlayerSessionsSessionIdMemberPlayersRequestBodyEEE() { @@ -2516,22 +2627,15 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage } bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEEneERKS9_(const void* self, const void* other) { - (void)self; - (void)other; - NotImplemented_nid_no_patch(__func__); - return false; + return HostIteratorNotEqual(self, other); } void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEEdeEv(const void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; + return static_cast(self)->element; } void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEEppEv(void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; + return HostIteratorAdvance(self, sizeof(IntrusivePtr)); } bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEEneERKS9_(const void* self, const void* other) { @@ -2560,8 +2664,7 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6 int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERSB_(const void* self, void* response) { (void)self; (void)response; - NotImplemented_nid_no_patch(__func__); - return 0; + return TransactionNotStarted; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self) { @@ -2575,8 +2678,7 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_1 int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(const void* self, void* response) { (void)self; (void)response; - NotImplemented_nid_no_patch(__func__); - return 0; + return TransactionNotStarted; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self) { @@ -2590,9 +2692,9 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(void* self, void* context) { (void)self; - (void)context; - NotImplemented_nid_no_patch(__func__); - return 0; + if (context == nullptr) return ParameterInvalidArgument; + if (*static_cast(context) == 0) return ParameterNotInitialized; + return SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN; } int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(void* self) { @@ -2615,16 +2717,12 @@ std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1 return HostVectorSize(self, __func__); } -void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5beginEv(void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5beginEv(void* out, void* self) { + return HostVectorBegin(out, self, 1, __func__); } -void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE3endEv(void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE3endEv(void* out, void* self) { + return HostVectorEnd(out, self, 1, sizeof(IntrusivePtr), __func__); } std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE4sizeEv(const void* self) { @@ -2643,10 +2741,8 @@ CommonIterator* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrI return iterator; } -void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V59Container11getChildrenEv(void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; +void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V59Container11getChildrenEv(void* out, void* self) { + return CopyMemberIntrusivePtr(out, self, 0x228, VectorReferenceCountOffset); } int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainerC1Ev(void* self) { @@ -2687,22 +2783,16 @@ const char* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product8getLabelEv return nullptr; } -void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V57Product7getSkusEv(void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return nullptr; +void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V57Product7getSkusEv(void* out, void* self) { + return CopyMemberIntrusivePtr(out, self, 0x1e0, VectorReferenceCountOffset); } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product7getTypeEv(const void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product7getTypeEv(const void* self) { + return static_cast(self) + 0x1c0; } bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product9skusIsSetEv(const void* self) { - (void)self; - NotImplemented_nid_no_patch(__func__); - return false; + return *reinterpret_cast(static_cast(self) + 0x1f8) != 0; } int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadData11setobjectIdEPKc(void* self, const char* objectId) { @@ -3273,9 +3363,8 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V1 *self = {}; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEEdeEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEEdeEv(const void* self) { + return static_cast(self)->element; } void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V118LeaderWithOnlineIdEEptEv(const IntrusivePtr* self) { @@ -3438,49 +3527,40 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS return TransactionNotStarted; } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE3endEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE3endEv(void* out, void* self) { + return HostVectorEnd(out, self, 1, sizeof(IntrusivePtr), __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE5beginEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE5beginEv(void* out, void* self) { + return HostVectorBegin(out, self, 1, __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE3endEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE3endEv(void* out, void* self) { + return HostVectorEnd(out, self, 3, sizeof(std::uint64_t), __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE5beginEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE5beginEv(void* out, void* self) { + return HostVectorBegin(out, self, 3, __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEppEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEppEv(void* self) { + return HostIteratorAdvance(self, sizeof(IntrusivePtr)); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorImEppEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorImEppEv(void* self) { + return HostIteratorAdvance(self, sizeof(std::uint64_t)); } -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getAccountIdEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getAccountIdEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x10); } -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getInContextEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getInContextEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x21) != 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence15getOnlineStatusEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence15getOnlineStatusEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x1c); } int APS5_VABI _ZNK3sce2Np9CppWebApi15ProfanityFilter2V223FilterProfanityResponse10getMessageEv() { @@ -3488,9 +3568,8 @@ int APS5_VABI _ZNK3sce2Np9CppWebApi15ProfanityFilter2V223FilterProfanityResponse return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponse13getRestrictedEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponse13getRestrictedEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x30) != 0; } void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEptEv(const IntrusivePtr* self) { @@ -3574,14 +3653,8 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V1 ReleaseIntrusivePtr(self, 0x00, __func__); } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5emptyEv(const IntrusivePtr* self) { - const auto* body = static_cast(self->object); - if (body == nullptr) return 1; - if (body->magic != VectorBodyMagic) { - NotImplemented_nid_no_patch(__func__); - return 0; - } - return body->size == 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5emptyEv(const void* self) { + return HostVectorSize(self, __func__) == 0; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEC1Ev(IntrusivePtr* self) { @@ -3669,18 +3742,16 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS return TransactionNotStarted; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorImE4sizeEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorImE4sizeEv(const void* self) { + return HostVectorSize(self, __func__); } std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEdeEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEdeEv(const void* self) { + return static_cast(self)->element; } int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv() { @@ -3723,9 +3794,8 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS return TransactionNotStarted; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEneERKS9_() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEneERKS9_(const void* self, const void* other) { + return HostIteratorNotEqual(self, other); } void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V139PatchPlayerSessionsSessionIdRequestBodyEEptEv(const IntrusivePtr* self) { @@ -3782,9 +3852,8 @@ std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12Intru return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEdeEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEdeEv(const void* self) { + return static_cast(self)->element; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V118LeaderWithOnlineIdEED1Ev(IntrusivePtr* self) { @@ -3795,28 +3864,20 @@ std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12Intru return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEneERKS4_() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEneERKS4_(const void* self, const void* other) { + return HostIteratorNotEqual(self, other); } -std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE4sizeEv(const IntrusivePtr* self) { - const auto* body = static_cast(self->object); - if (body == nullptr) return 0; - if (body->magic != VectorBodyMagic) { - NotImplemented_nid_no_patch(__func__); - return 0; - } - return body->size; +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE4sizeEv(const void* self) { + return HostVectorSize(self, __func__); } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V120PlayerSessionForReadEEEEEED1Ev(IntrusivePtr* self) { ReleaseIntrusivePtr(self, 0x30, __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5beginEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5beginEv(void* out, void* self) { + return HostVectorBegin(out, self, 1, __func__); } int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEEEE8pushBackERKS8_(IntrusivePtr* self, const void* element) { @@ -3847,9 +3908,8 @@ std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12Intru return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE8copyFromERKS9_() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE8copyFromERKS9_(void* self, const void* source) { + return HostVectorCopyFrom(static_cast(self), static_cast(source), __func__); } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEED1Ev(IntrusivePtr* self) { @@ -3860,9 +3920,8 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14 *self = {}; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10labelIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10labelIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x80) != 0; } struct MatchesParameter { @@ -4532,72 +4591,60 @@ bool APS5_VABI _ZNK3sce2Np9CppWebApi7Matches2V119RequestInGameRoster12playersIsS } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10priceIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10priceIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0xd8) != 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getPriceEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getPriceEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0xd4); } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku15getDisplayPriceEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku15getDisplayPriceEv(const void* self) { + return static_cast(self) + 0xe0; } int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer7setsortENS5_4SortE() { return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku18originalPriceIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku18originalPriceIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x108) != 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDescriptionEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDescriptionEv(const void* self) { + return static_cast(self) + 0x130; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getReleaseDateEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getReleaseDateEv(const void* self) { + return static_cast(self) + 0x80; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku23getDisplayOriginalPriceEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku23getDisplayOriginalPriceEv(const void* self) { + return static_cast(self) + 0x110; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDisplayNameEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDisplayNameEv(const void* self) { + return static_cast(self) + 0x60; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku16getOriginalPriceEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku16getOriginalPriceEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x104); } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku25displayOriginalPriceIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku25displayOriginalPriceIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x130) != 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getLabelEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getLabelEv(const void* self) { + return static_cast(self) + 0x60; } int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer9setoffsetEi() { return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product16releaseDateIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product16releaseDateIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0xa0) != 0; } int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer15setcontainerIdsEPKc(void* self, const char* containerIds) { @@ -4608,53 +4655,44 @@ int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToG return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku17displayPriceIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku17displayPriceIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x100) != 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product5getIdEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product5getIdEv(const void* self) { + return static_cast(self) + 0x10; } int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv() { return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEEaSERKSE_() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEEaSERKSE_(void* self, const void* source) { + auto* dst = static_cast(self); + const auto* src = static_cast(source); + dst[0] = src[0]; + dst[1] = src[1]; + return self; } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEppEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEppEv(void* self) { + return HostIteratorAdvance(self, sizeof(IntrusivePtr)); } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5emptyEv(const IntrusivePtr* self) { - const auto* body = static_cast(self->object); - if (body == nullptr) return 1; - if (body->magic != VectorBodyMagic) { - NotImplemented_nid_no_patch(__func__); - return 0; - } - return body->size == 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5emptyEv(const void* self) { + return HostVectorSize(self, __func__) == 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEneERKS9_() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEneERKS9_(const void* self, const void* other) { + return HostIteratorNotEqual(self, other); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE5beginEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE5beginEv(void* out, void* self) { + return HostVectorBegin(out, self, 1, __func__); } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEneERKS9_() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEneERKS9_(const void* self, const void* other) { + return HostIteratorNotEqual(self, other); } void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V57ProductEEEEEEdeEv(const IntrusivePtr* self) { @@ -4670,19 +4708,16 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_ return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE3endEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE3endEv(void* out, void* self) { + return HostVectorEnd(out, self, 1, sizeof(IntrusivePtr), __func__); } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEdeEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEdeEv(const void* self) { + return static_cast(self)->element; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEdeEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEdeEv(const void* self) { + return static_cast(self)->element; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEC1ERKSA_(IntrusivePtr* self, const IntrusivePtr* source) { @@ -4699,14 +4734,12 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_ return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5beginEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5beginEv(void* out, void* self) { + return HostVectorBegin(out, self, 1, __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE3endEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE3endEv(void* out, void* self) { + return HostVectorEnd(out, self, 1, sizeof(IntrusivePtr), __func__); } void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V53SkuEEEEEEdeEv(const IntrusivePtr* self) { @@ -4718,14 +4751,8 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGa return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5emptyEv(const IntrusivePtr* self) { - const auto* body = static_cast(self->object); - if (body == nullptr) return 1; - if (body->magic != VectorBodyMagic) { - NotImplemented_nid_no_patch(__func__); - return 0; - } - return body->size == 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5emptyEv(const void* self) { + return HostVectorSize(self, __func__) == 0; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEaSERKSA_(IntrusivePtr* self, const IntrusivePtr* source) { @@ -4806,16 +4833,26 @@ CommonString* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_6StringEEdeEv( // libSceNpCppWebApi.prx. // -------------------------------------------------------------------------- -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile19personalDetailIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile19personalDetailIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x40) != 0; } int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V115BasicProfileApi28ParameterToGetPublicProfiles9terminateEv() { return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileC1EPNS1_6Common10LibContextE() { +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileC1EPNS1_6Common10LibContextE(void* self, void* context) { + auto* object = static_cast(self); + *reinterpret_cast(object) = 0; + *reinterpret_cast(object + 8) = context; + std::memset(object + 0x10, 0, 0x38); + InitHostString(object + 0x48, context); + object[0x68] = 0; + std::memset(object + 0x70, 0, 0x40); + *reinterpret_cast(object + 0xb0) = 0; + object[0xb8] = 0; + *reinterpret_cast(object + 0xbc) = 0; + object[0xc0] = 0; return 0; } @@ -4844,9 +4881,8 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11 return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile25isOfficiallyVerifiedIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile25isOfficiallyVerifiedIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0xaa) != 0; } int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence14accountIdIsSetEv() { @@ -4858,25 +4894,33 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11 ReleaseIntrusivePtr(self, 0x30, __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setAccountIdERKm() { +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setAccountIdERKm(void* self, const std::uint64_t* accountId) { + auto* object = static_cast(self); + *reinterpret_cast(object + 0x10) = *accountId; + object[0x18] = 1; return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceC1EPNS1_6Common10LibContextE() { +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceC1EPNS1_6Common10LibContextE(void* self, void* context) { + auto* object = static_cast(self); + *reinterpret_cast(object) = 0; + *reinterpret_cast(object + 8) = context; + *reinterpret_cast(object + 0x10) = 0; + object[0x18] = 0; + *reinterpret_cast(object + 0x1c) = 0; + *reinterpret_cast(object + 0x1f) = 0; return 0; } int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv() { - NotImplemented_nid_no_patch(__func__); - return 0; + return TransactionNotStarted; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V114PersonalDetailEED1Ev(IntrusivePtr* self) { ReleaseIntrusivePtr(self, 0x00, __func__); } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { - NotImplemented_nid_no_patch(__func__); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { return 0; } @@ -4884,7 +4928,10 @@ int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_1 return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setInContextERKb() { +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setInContextERKb(void* self, const bool* inContext) { + auto* object = static_cast(self); + object[0x21] = *inContext ? 1 : 0; + object[0x22] = 1; return 0; } @@ -4912,7 +4959,11 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V118G ReleaseIntrusivePtr(self, 0x00, __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile11setOnlineIdERK13SceNpOnlineId() { +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile11setOnlineIdERK13SceNpOnlineId(void* self, const void* onlineId) { + auto* object = static_cast(self); + std::memcpy(object + 0x10, onlineId, 0x10); + *reinterpret_cast(object + 0x20) = *reinterpret_cast(static_cast(onlineId) + 0x10); + object[0x24] = 1; return 0; } @@ -4966,14 +5017,12 @@ int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V114PersonalDetail14getDisplayN return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile13onlineIdIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile13onlineIdIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x24) != 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence14inContextIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence14inContextIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x22) != 0; } int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv() { @@ -4992,8 +5041,13 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V112B ReleaseIntrusivePtr(self, 0x00, __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileD1Ev() { - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileD1Ev(void* self) { + auto* object = static_cast(self); + ReleaseIntrusivePtr(reinterpret_cast(object + 0x90), StringVectorReferenceCountOffset, __func__); + ReleaseIntrusivePtr(reinterpret_cast(object + 0x70), VectorReferenceCountOffset, __func__); + DestroyHostString(object + 0x48); + ReleaseIntrusivePtr(reinterpret_cast(object + 0x28), ReferenceCountOffset, __func__); + return self; } int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEEneERKS9_() { @@ -5063,19 +5117,16 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V112B CopyIntrusivePtr(self, source, 0x00); } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V125GetPublicProfilesResponse11getProfilesEv() { - NotImplemented_nid_no_patch(__func__); +void* APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V125GetPublicProfilesResponse11getProfilesEv(void* out, void* self) { + return CopyMemberIntrusivePtr(out, self, 0x30, VectorReferenceCountOffset); +} + +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEEppEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEEppEv(void* self) { + return HostIteratorAdvance(self, sizeof(IntrusivePtr)); } int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriends8setlimitEi() { @@ -5083,21 +5134,22 @@ int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFr } int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv() { - NotImplemented_nid_no_patch(__func__); - return 0; + return TransactionNotStarted; } void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEC1Ev(IntrusivePtr* self) { *self = {}; } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile23setIsOfficiallyVerifiedERKb() { +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile23setIsOfficiallyVerifiedERKb(void* self, const bool* verified) { + auto* object = static_cast(self); + object[0xa9] = *verified ? 1 : 0; + object[0xaa] = 1; return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence17onlineStatusIsSetEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence17onlineStatusIsSetEv(const void* self) { + return *reinterpret_cast(static_cast(self) + 0x20) != 0; } int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V115BasicProfileApi28ParameterToGetPublicProfilesD1Ev() { @@ -5113,13 +5165,12 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_30CommunicationRest CopyIntrusivePtr(self, source, 0x00); } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { - NotImplemented_nid_no_patch(__func__); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceD1Ev() { - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceD1Ev(void* self) { + return self; } int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self) { @@ -5137,16 +5188,14 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_ } int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv() { - NotImplemented_nid_no_patch(__func__); - return 0; + return TransactionNotStarted; } int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsers8setlimitEi() { return 0; } -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { - NotImplemented_nid_no_patch(__func__); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv() { return 0; } @@ -5158,18 +5207,19 @@ int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBloc return 0; } -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEE3endEv() { - NotImplemented_nid_no_patch(__func__); - return 0; +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEE3endEv(void* out, void* self) { + return HostVectorEnd(out, self, 1, sizeof(IntrusivePtr), __func__); } -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence15setOnlineStatusERKNS3_12OnlineStatusE() { +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence15setOnlineStatusERKNS3_12OnlineStatusE(void* self, const std::uint32_t* status) { + auto* object = static_cast(self); + *reinterpret_cast(object + 0x1c) = *status; + object[0x20] = 1; return 0; } int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv() { - NotImplemented_nid_no_patch(__func__); - return 0; + return TransactionNotStarted; } int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEEdeEv() { diff --git a/core/libs/prx/libSceNpCppWebApi/include/Api.hpp b/core/libs/prx/libSceNpCppWebApi/include/Api.hpp index 76abf99f39..7ad62d55b2 100644 --- a/core/libs/prx/libSceNpCppWebApi/include/Api.hpp +++ b/core/libs/prx/libSceNpCppWebApi/include/Api.hpp @@ -358,7 +358,7 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V1 const char* APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V136UsersPlayerSessionsInvitationForRead12getSessionIdEv(const void* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V136UsersPlayerSessionsInvitationForRead7getFromEv(const void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V129PostPlayerSessionsRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); -void* APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V130PostPlayerSessionsResponseBody17getPlayerSessionsEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V130PostPlayerSessionsResponseBody17getPlayerSessionsEv(void* out, void* self); int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi18leavePlayerSessionEiRKNS4_29ParameterToLeavePlayerSessionERNS1_6Common11TransactionINS8_15DefaultResponseENS8_12IntrusivePtrINS8_18ResponseHeaderBaseEEEEE(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V124PlayerSessionPushContextEEEE8pushBackERKS8_(IntrusivePtr* self, const void* element); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); @@ -474,12 +474,12 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(void* self, void* context); void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEixEm(void* self, std::uint64_t index); std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE4sizeEv(const void* self); -void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5beginEv(void* self); -void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE3endEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5beginEv(void* out, void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE3endEv(void* out, void* self); std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE4sizeEv(const void* self); CommonIterator* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEE5beginEv(CommonIterator* iterator, const IntrusivePtr* self); CommonIterator* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEE3endEv(CommonIterator* iterator, const IntrusivePtr* self); -void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V59Container11getChildrenEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V59Container11getChildrenEv(void* out, void* self); int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainerC1Ev(void* self); int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer10initializeEPNS1_6Common10LibContextE(void* self, const std::uint64_t* context); bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer13isInitializedEv(const void* self); @@ -488,8 +488,8 @@ int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToG int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainerD1Ev(void* self); int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi12getContainerEiRKNS4_23ParameterToGetContainerERNS1_6Common11TransactionINS8_12IntrusivePtrINS8_6VectorINSA_INS3_9ContainerEEEEEEENSA_INS8_18ResponseHeaderBaseEEEEE(); const char* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product8getLabelEv(const void* self); -void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V57Product7getSkusEv(void* self); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product7getTypeEv(const void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V57Product7getSkusEv(void* out, void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product7getTypeEv(const void* self); bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product9skusIsSetEv(const void* self); int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadData11setobjectIdEPKc(void* self, const char* objectId); int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi37ParameterToGetMultiDataStatusesByUserC1Ev(void* self); @@ -650,7 +650,7 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEED1Ev(Intru void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEED1Ev(IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEED2Ev(void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEC1Ev(IntrusivePtr* self); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEEdeEv(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEEdeEv(const void* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V118LeaderWithOnlineIdEEptEv(const IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEED1Ev(IntrusivePtr* self); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); @@ -690,17 +690,17 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common18ResponseHeaderBase14getHeaderValueEPKcRNS2_12IntrusivePtrINS2_6StringEEE(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE3endEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE5beginEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE3endEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE5beginEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEppEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorImEppEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getAccountIdEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getInContextEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence15getOnlineStatusEv(); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE3endEv(void* out, void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE5beginEv(void* out, void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE3endEv(void* out, void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorImE5beginEv(void* out, void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEppEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorImEppEv(void* self); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getAccountIdEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getInContextEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence15getOnlineStatusEv(const void* self); int APS5_VABI _ZNK3sce2Np9CppWebApi15ProfanityFilter2V223FilterProfanityResponse10getMessageEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponse13getRestrictedEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponse13getRestrictedEv(const void* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEptEv(const IntrusivePtr* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEptEv(const IntrusivePtr* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEptEv(const IntrusivePtr* self); @@ -721,7 +721,7 @@ int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrIN int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEED1Ev(IntrusivePtr* self); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5emptyEv(const IntrusivePtr* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5emptyEv(const void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEC1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V143PutPlayerSessionsSessionIdLeaderRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V139PatchPlayerSessionsSessionIdRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); @@ -742,9 +742,9 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V1 int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V12ToEED1Ev(IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorImE4sizeEv(); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorImE4sizeEv(const void* self); std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEdeEv(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEdeEv(const void* self); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEEixEm(IntrusivePtr* self, unsigned long index); void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEED1Ev(IntrusivePtr* self); @@ -753,7 +753,7 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14 void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V143PutPlayerSessionsSessionIdLeaderRequestBodyEEC1Ev(IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEneERKS9_(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEneERKS9_(const void* self, const void* other); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V139PatchPlayerSessionsSessionIdRequestBodyEEptEv(const IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEED1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V139PatchPlayerSessionsSessionIdRequestBodyEEC1Ev(IntrusivePtr* self); @@ -767,13 +767,13 @@ int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_1 void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEEC1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEdeEv(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEdeEv(const void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V118LeaderWithOnlineIdEED1Ev(IntrusivePtr* self); std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEneERKS4_(); -std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE4sizeEv(const IntrusivePtr* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEneERKS4_(const void* self, const void* other); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE4sizeEv(const void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V120PlayerSessionForReadEEEEEED1Ev(IntrusivePtr* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5beginEv(); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5beginEv(void* out, void* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEEEE8pushBackERKS8_(IntrusivePtr* self, const void* element); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); @@ -781,49 +781,49 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V1 void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEEEED1Ev(IntrusivePtr* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEptEv(const IntrusivePtr* self); std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE8copyFromERKS9_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE8copyFromERKS9_(void* self, const void* source); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEED1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V113PlayerSessionEEEEEEC1Ev(IntrusivePtr* self); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10labelIsSetEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10priceIsSetEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getPriceEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku15getDisplayPriceEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10labelIsSetEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku10priceIsSetEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getPriceEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku15getDisplayPriceEv(const void* self); int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer7setsortENS5_4SortE(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku18originalPriceIsSetEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDescriptionEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getReleaseDateEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku23getDisplayOriginalPriceEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDisplayNameEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku16getOriginalPriceEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku25displayOriginalPriceIsSetEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getLabelEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku18originalPriceIsSetEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDescriptionEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getReleaseDateEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku23getDisplayOriginalPriceEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product14getDisplayNameEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku16getOriginalPriceEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku25displayOriginalPriceIsSetEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku8getLabelEv(const void* self); int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer9setoffsetEi(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product16releaseDateIsSetEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product16releaseDateIsSetEv(const void* self); int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer15setcontainerIdsEPKc(void* self, const char* containerIds); int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer8setlimitEi(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku17displayPriceIsSetEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product5getIdEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku17displayPriceIsSetEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product5getIdEv(const void* self); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEEaSERKSE_(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEppEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5emptyEv(const IntrusivePtr* self); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEneERKS9_(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE5beginEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEneERKS9_(); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEEaSERKSE_(void* self, const void* source); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEppEv(void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE5emptyEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEneERKS9_(const void* self, const void* other); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE5beginEv(void* out, void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEneERKS9_(const void* self, const void* other); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V57ProductEEEEEEdeEv(const IntrusivePtr* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V53SkuEEptEv(const IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEED2Ev(void* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE3endEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEdeEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEdeEv(); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE3endEv(void* out, void* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEEdeEv(const void* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEdeEv(const void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEC1ERKSA_(IntrusivePtr* self, const IntrusivePtr* source); int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEEC1ERKSE_(void* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEED2Ev(void* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5beginEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE3endEv(); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5beginEv(void* out, void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE3endEv(void* out, void* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V53SkuEEEEEEdeEv(const IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEppEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5emptyEv(const IntrusivePtr* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5emptyEv(const void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEaSERKSA_(IntrusivePtr* self, const IntrusivePtr* source); CommonIterator* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_6StringEEppEv(CommonIterator* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEEC1Ev(IntrusivePtr* self); @@ -847,13 +847,13 @@ void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V124G void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEC1ERKS7_(IntrusivePtr* self, const IntrusivePtr* source); int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriends8setlimitEi(); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEE3getEv(const IntrusivePtr* self); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEEaSERKSB_(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V112BasicProfileEED1Ev(IntrusivePtr* self); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceD1Ev(); +void* APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceD1Ev(void* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEptEv(const IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V115BasicProfileApi28ParameterToGetPublicProfiles9terminateEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V125GetPublicProfilesResponse11getProfilesEv(); +void* APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V125GetPublicProfilesResponse11getProfilesEv(void* out, void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V112BasicProfileEEEEEEaSERKSA_(IntrusivePtr* self, const IntrusivePtr* source); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEED1Ev(IntrusivePtr* self); int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile17getPersonalDetailEv(); @@ -949,16 +949,16 @@ bool APS5_VABI _ZNK3sce2Np9CppWebApi7Matches2V119RequestInGameRoster10teamsIsSet bool APS5_VABI _ZNK3sce2Np9CppWebApi7Matches2V119RequestInGameRoster12playersIsSetEv(const void* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V115BasicProfileApi17getPublicProfilesEiRKNS4_28ParameterToGetPublicProfilesERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_25GetPublicProfilesResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setInContextERKb(); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile13onlineIdIsSetEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setInContextERKb(void* self, const bool* inContext); +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile13onlineIdIsSetEv(const void* self); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEaSERKS7_(IntrusivePtr* self, const IntrusivePtr* source); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence15setOnlineStatusERKNS3_12OnlineStatusE(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile23setIsOfficiallyVerifiedERKb(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileC1EPNS1_6Common10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence15setOnlineStatusERKNS3_12OnlineStatusE(void* self, const std::uint32_t* status); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile23setIsOfficiallyVerifiedERKb(void* self, const bool* verified); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileC1EPNS1_6Common10LibContextE(void* self, void* context); int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEED2Ev(void* self); int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V115BasicProfileApi28ParameterToGetPublicProfiles10initializeEPNS1_6Common10LibContextEPKc(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEC1Ev(IntrusivePtr* self); int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile23getIsOfficiallyVerifiedEv(); @@ -968,20 +968,20 @@ int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_1 int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEEC1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEED1Ev(IntrusivePtr* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEE3endEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence17onlineStatusIsSetEv(); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEE3endEv(void* out, void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence17onlineStatusIsSetEv(const void* self); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceC1EPNS1_6Common10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceC1EPNS1_6Common10LibContextE(void* self, void* context); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEEaSERKSA_(IntrusivePtr* self, const IntrusivePtr* source); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile25isOfficiallyVerifiedIsSetEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence14inContextIsSetEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile25isOfficiallyVerifiedIsSetEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence14inContextIsSetEv(const void* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileD1Ev(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEEppEv(); +void* APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileD1Ev(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEEppEv(void* self); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V112BasicProfileEEEEEE3getEv(const IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEC1Ev(IntrusivePtr* self); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile11setOnlineIdERK13SceNpOnlineId(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile11setOnlineIdERK13SceNpOnlineId(void* self, const void* onlineId); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEC1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEED1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V112BasicProfileEEEEEEC1Ev(IntrusivePtr* self); @@ -991,8 +991,8 @@ int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFr int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile11getOnlineIdEv(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1ERKSB_(void* self); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setAccountIdERKm(); -int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile19personalDetailIsSetEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setAccountIdERKm(void* self, const std::uint64_t* accountId); +bool APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile19personalDetailIsSetEv(const void* self); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEEneERKS9_(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V114PersonalDetailEED1Ev(IntrusivePtr* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); @@ -1002,7 +1002,7 @@ void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_ int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEC1Ev(IntrusivePtr* self); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEC1Ev(IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEEE5beginEv(); int APS5_VABI _ZNK3sce2Np9CppWebApi11UserProfile2V114PersonalDetail14getDisplayNameEv(); @@ -1011,7 +1011,7 @@ int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V115BasicProfileApi28ParameterTo int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEED1Ev(IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V112BasicProfileEEptEv(const IntrusivePtr* self); int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsers8setlimitEi(); @@ -1358,9 +1358,9 @@ int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrIN int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_17TitleCloudStorage2V122UploadDataResponseBodyEEENS4_INS6_7DataApi25UploadDataResponseHeadersEEEE18getResponseHeadersERSB_(); int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEE18getResponseHeadersERS7_(); std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEE4sizeEv(const void* self); -std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE4sizeEv(const void* self); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEE4sizeEv(const void* self); std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V118GameSessionForReadEEEE4sizeEv(const void* self); -std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE4sizeEv(const void* self); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE4sizeEv(const void* self); std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V113RequestMemberEEEE4sizeEv(const void* self); std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V116RequestMatchTeamEEEE4sizeEv(const void* self); std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V118RequestMatchPlayerEEEE4sizeEv(const void* self); diff --git a/core/libs/prx/libSceVideoOut/CMakeLists.txt b/core/libs/prx/libSceVideoOut/CMakeLists.txt index 96ceacccbe..bcaf2def20 100644 --- a/core/libs/prx/libSceVideoOut/CMakeLists.txt +++ b/core/libs/prx/libSceVideoOut/CMakeLists.txt @@ -81,6 +81,17 @@ if(BUILD_TESTING) "PATH=path_list_prepend:$") endif() + add_test_executable(guest_video_out_firmware_answers_tests ${LIBS_INCLUDE_DIR}/tests/GuestVideoOutFirmwareAnswers.cpp) + target_include_directories(guest_video_out_firmware_answers_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_video_out_firmware_answers_tests PRIVATE libSceVideoOut libkernel libc) + configure_windows_unwind(guest_video_out_firmware_answers_tests) + add_test(NAME guest_video_out_firmware_answers COMMAND guest_video_out_firmware_answers_tests) + set_tests_properties(guest_video_out_firmware_answers PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_video_out_firmware_answers PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() + add_test_executable(guest_video_out_high_frame_rate_tests ${LIBS_INCLUDE_DIR}/tests/GuestVideoOutHighFrameRate.cpp) target_include_directories(guest_video_out_high_frame_rate_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_video_out_high_frame_rate_tests PRIVATE libSceVideoOut libSceAgcDriver libkernel libc) diff --git a/core/libs/prx/libSceVideoOut/InventoryExports.cpp b/core/libs/prx/libSceVideoOut/InventoryExports.cpp index 77d4bde7ed..abb57b2e2e 100644 --- a/core/libs/prx/libSceVideoOut/InventoryExports.cpp +++ b/core/libs/prx/libSceVideoOut/InventoryExports.cpp @@ -3,6 +3,13 @@ #include "prx/libc/include/general/ExportMacros.hpp" #include "prx/libSceVideoOut/include/InventoryExports.hpp" #include "prx/libc/include/General.hpp" +#include +#include + +namespace { +constexpr int VideoOutErrorCurveSamplePoints = static_cast(0x8029001Cu); +constexpr int VideoOutErrorLatestEopHandle = static_cast(0x802900FFu); +} extern "C" { @@ -19,7 +26,7 @@ int APS5_VABI sceVideoOutAddBufferAnisoPrivilege() { } int APS5_VABI sceVideoOutAddBufferHdrPrivilege() { - NotImplemented_nid_no_patch(__func__); + return 0; } int APS5_VABI sceVideoOutAddBufferYccPrivilege() { @@ -91,7 +98,7 @@ int APS5_VABI sceVideoOutCursorSetPositionStereo() { } int APS5_VABI sceVideoOutCurveSamplePointsCalc_() { - NotImplemented_nid_no_patch(__func__); + return VideoOutErrorCurveSamplePoints; } int APS5_VABI sceVideoOutDebugAddVrrPrivilege() { @@ -155,7 +162,7 @@ int APS5_VABI sceVideoOutDriverGetFinishedEopHandle() { } int APS5_VABI sceVideoOutDriverGetLatestEopHandle() { - NotImplemented_nid_no_patch(__func__); + return VideoOutErrorLatestEopHandle; } int APS5_VABI sceVideoOutDriverIncrementBufferLabel() { @@ -255,7 +262,7 @@ int APS5_VABI sceVideoOutRazorAddCallback() { } int APS5_VABI sceVideoOutRazorRecallCallbacks() { - NotImplemented_nid_no_patch(__func__); + return 0; } int APS5_VABI sceVideoOutRazorRemoveCallback() { @@ -383,7 +390,7 @@ int APS5_VABI sceVideoOutSysGetKsvList() { } int APS5_VABI sceVideoOutSysGetMonitorInfo_() { - NotImplemented_nid_no_patch(__func__); + return -1; } int APS5_VABI sceVideoOutSysGetOutputStatus() { @@ -462,8 +469,10 @@ int APS5_VABI sceVideoOutSysModeIsVrNative() { NotImplemented_nid_no_patch(__func__); } -int APS5_VABI sceVideoOutSysModeIsVr() { - NotImplemented_nid_no_patch(__func__); +int APS5_VABI sceVideoOutSysModeIsVr(const void* mode) { + std::uint32_t flags; + std::memcpy(&flags, static_cast(mode) + 0x20, sizeof(flags)); + return static_cast((flags >> 1) & 1u); } int APS5_VABI sceVideoOutSysOpenInternal() { @@ -523,7 +532,7 @@ int APS5_VABI sceVideoOutSysUpdatePrivilege() { } int APS5_VABI sceVideoOutSysUpdateRenderingMode() { - NotImplemented_nid_no_patch(__func__); + return 0; } int APS5_VABI sceVideoOutUnlockBuffer() { diff --git a/core/libs/prx/libSceVideoOut/include/InventoryExports.hpp b/core/libs/prx/libSceVideoOut/include/InventoryExports.hpp index 5c65f81866..6b9f6feedc 100644 --- a/core/libs/prx/libSceVideoOut/include/InventoryExports.hpp +++ b/core/libs/prx/libSceVideoOut/include/InventoryExports.hpp @@ -118,7 +118,7 @@ int APS5_VABI sceVideoOutSysModeIsHdr(); int APS5_VABI sceVideoOutSysModeIsSystemDefault(); int APS5_VABI sceVideoOutSysModeIsVrLegacy(); int APS5_VABI sceVideoOutSysModeIsVrNative(); -int APS5_VABI sceVideoOutSysModeIsVr(); +int APS5_VABI sceVideoOutSysModeIsVr(const void* mode); int APS5_VABI sceVideoOutSysOpenInternal(); int APS5_VABI sceVideoOutSysOpenVrNative(); int APS5_VABI sceVideoOutSysReadCrc64(); diff --git a/core/libs/prx/libc/src/Math.cpp b/core/libs/prx/libc/src/Math.cpp index 1eb65f0e5a..bd7b048aa9 100644 --- a/core/libs/prx/libc/src/Math.cpp +++ b/core/libs/prx/libc/src/Math.cpp @@ -481,6 +481,18 @@ std::int64_t APS5_VABI imaxabs_nid_postfix(std::int64_t x) { } float APS5_VABI fmodf_nid_postfix(float x, float y) { + const std::uint32_t ix = std::bit_cast(x) & 0x7fffffffu; + const std::uint32_t iy = std::bit_cast(y) & 0x7fffffffu; + if (iy == 0 || ix >= 0x7f800000u || iy > 0x7f800000u) { + _Feraise_nid_postfix(0x01); + if (iy > 0x7f800000u) { + return y + y; + } + if (ix > 0x7f800000u) { + return x + x; + } + return (x * y) / (x * y); + } const int saved_errno = errno; const float result = std::fmod(x, y); errno = saved_errno; @@ -2560,9 +2572,11 @@ double APS5_VABI atanh_nid_postfix(double x) { const std::int32_t ix = hx & 0x7fffffff; if ((static_cast(ix) | ((lx | (0u - lx)) >> 31)) > 0x3ff00000u) { _Feraise_nid_postfix(0x01); + errno = EDOM; return (x - x) / (x - x); } if (ix == 0x3ff00000) { + _Feraise_nid_postfix(0x04); errno = ERANGE; return x / zero; } @@ -3391,9 +3405,32 @@ float APS5_VABI ldexpf_nid_postfix(float x, int exp) { errno = saved_errno; return result; } +/* Adapted from FreeBSD release/11.4.0 lib/msun/src/e_fmod.c: https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/e_fmod.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ double APS5_VABI fmod_nid_postfix(double x, double y) { - int saved_errno = errno; - double result = std::fmod(x, y); + const std::uint64_t ix = std::bit_cast(x) & 0x7fffffffffffffffull; + const std::uint64_t iy = std::bit_cast(y) & 0x7fffffffffffffffull; + if (iy == 0 || ix >= 0x7ff0000000000000ull || iy > 0x7ff0000000000000ull) { + _Feraise_nid_postfix(0x01); + if (iy > 0x7ff0000000000000ull) { + return y + y; + } + if (ix > 0x7ff0000000000000ull) { + return x + x; + } + return (x * y) / (x * y); + } + const int saved_errno = errno; + const double result = std::fmod(x, y); errno = saved_errno; return result; } diff --git a/core/libs/prx/libkernel/Socket/src/Udp.cpp b/core/libs/prx/libkernel/Socket/src/Udp.cpp index 11d3088b20..8e2ed3ec73 100644 --- a/core/libs/prx/libkernel/Socket/src/Udp.cpp +++ b/core/libs/prx/libkernel/Socket/src/Udp.cpp @@ -944,7 +944,15 @@ int SocketSendFlags(Socket& socket, int flags) { std::lock_guard lock(socket.modeMutex); return NativeSendFlags(socket.options.noSignal ? flags | GuestNoSignal : flags); } -int WaitForTransfer(Socket& socket, bool send, int flags) { +#ifdef _WIN32 +bool ReceiveWouldBlock(const Socket& socket) { + if (socket.type == 1) return PeerConnected(socket); + sockaddr_storage name{}; + socklen_t size = sizeof(name); + return ::getsockname(socket.value, reinterpret_cast(&name), &size) == 0; +} +#endif +int WaitForTransfer(Socket& socket, bool send, int flags, int receiver = -1) { if ((flags & GuestDontWait) != 0) { #ifdef _WIN32 NativePollDescriptor entry{}; @@ -961,22 +969,38 @@ int WaitForTransfer(Socket& socket, bool send, int flags) { if (socket.options.nonblocking) return 0; timeout = send ? socket.options.sendTimeout : socket.options.receiveTimeout; } - if (timeout == 0) return 0; +#ifdef _WIN32 + const bool watched = receiver >= 0 && ReceiveWouldBlock(socket); +#else + static_cast(receiver); + constexpr bool watched = false; +#endif + if (timeout == 0 && !watched) return 0; + const ReadWatch watch(watched ? std::vector{receiver} : std::vector{}); const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout >> 32) + std::chrono::nanoseconds((static_cast(static_cast(timeout)) * 1000000000) >> 32); for (;;) { - const auto left = deadline - std::chrono::steady_clock::now(); - if (left <= std::chrono::steady_clock::duration::zero()) return 35; - const int milliseconds = static_cast(std::min(std::chrono::ceil(left).count(), INT_MAX)); - NativePollDescriptor entry{}; - entry.fd = socket.value; + if (watched && ReceiveShut(socket)) return 0; + int milliseconds = -1; + if (timeout != 0) { + const auto left = deadline - std::chrono::steady_clock::now(); + if (left <= std::chrono::steady_clock::duration::zero()) return 35; + milliseconds = static_cast(std::min(std::chrono::ceil(left).count(), INT_MAX)); + } + NativePollDescriptor entries[2]{}; + entries[0].fd = socket.value; #ifdef _WIN32 - entry.events = static_cast(send ? POLLWRNORM : POLLRDNORM); - const int ready = WSAPoll(&entry, 1, milliseconds); - if (ready != 0) return 0; + entries[0].events = static_cast(send ? POLLWRNORM : POLLRDNORM); + if (watched) { + entries[1].fd = ThreadWaker().value; + entries[1].events = POLLRDNORM; + } + const int ready = WSAPoll(entries, watched ? 2 : 1, milliseconds); + if (ready < 0 || entries[0].revents != 0) return 0; + if (entries[1].revents != 0) DrainWaker(entries[1].fd); #else - entry.events = static_cast(send ? POLLOUT : POLLIN); - const int ready = ::poll(&entry, 1, milliseconds); + entries[0].events = static_cast(send ? POLLOUT : POLLIN); + const int ready = ::poll(entries, 1, milliseconds); if (ready > 0 || (ready < 0 && errno != EINTR)) return 0; #endif } @@ -1621,7 +1645,8 @@ std::int64_t APS5_VABI recv_nid_postfix(int descriptor, void* buffer, std::uint6 const GuestArena::HostWrite destination(length == 0 ? nullptr : buffer, static_cast(length)); if (!destination.Open()) return Fail(14); if (const int answered = ReceiveAnsweredHere(*socket, length); answered >= 0) return answered == 0 ? 0 : Fail(answered); - if (const int waited = WaitForTransfer(*socket, false, flags)) return Fail(waited); + if (const int waited = WaitForTransfer(*socket, false, flags, descriptor)) return Fail(waited); + if (ReceiveShut(*socket)) return 0; const auto result = ::recv(socket->value, static_cast(buffer), static_cast(length), NativeReceiveFlags(flags, socket->type)); #ifdef _WIN32 @@ -1678,9 +1703,9 @@ int APS5_VABI shutdown_nid_postfix(int descriptor, int how) { sockaddr_storage peer{}; socklen_t size = sizeof(peer); const bool unconnected = socket->type == 2 && ::getpeername(socket->value, reinterpret_cast(&peer), &size) != 0; - if (::shutdown(socket->value, how) && !unconnected && !AlreadyShut(socket->value, how)) return Fail(NativeError()); { std::lock_guard lock(socket->modeMutex); + if (::shutdown(socket->value, how) && !unconnected && !AlreadyShut(socket->value, how)) return Fail(NativeError()); if (how != 1) socket->receiveShut = true; if (how != 0) socket->sendShut = true; } @@ -1861,7 +1886,11 @@ std::int64_t APS5_VABI recvfrom_nid_postfix(int descriptor, void* buffer, std::u } sockaddr_storage native{}; socklen_t size = sizeof(native); - if (const int waited = WaitForTransfer(*socket, false, flags)) return Fail(waited); + if (const int waited = WaitForTransfer(*socket, false, flags, descriptor)) return Fail(waited); + if (ReceiveShut(*socket)) { + if (addressLength && !ReportAddress(address, addressLength, nullptr, address ? 0 : capacity)) return Fail(14); + return 0; + } std::uint64_t limit = length; #ifdef _WIN32 if (length != 0 && (limit = GuestPrefix(buffer, length, WritableProtection)) < length) { @@ -2187,11 +2216,12 @@ std::int64_t APS5_VABI recvmsg_nid_postfix(int descriptor, GuestMsghdr* message, ReceivedRights rights; bool controlTruncated = false; #endif - const bool shut = ReceiveShut(*socket); + bool shut = ReceiveShut(*socket); std::vector stamps; if (!shut && (total != 0 || socket->type == 1 || ReadableNow(*socket))) { size = sizeof(native); - if (const int waited = WaitForTransfer(*socket, false, flags)) return Fail(waited); + if (const int waited = WaitForTransfer(*socket, false, flags, descriptor)) return Fail(waited); + shut = ReceiveShut(*socket); #ifndef _WIN32 if (passing) { std::vector control(CMSG_SPACE(MostPassedDescriptors * sizeof(int))); @@ -2227,7 +2257,7 @@ std::int64_t APS5_VABI recvmsg_nid_postfix(int descriptor, GuestMsghdr* message, if (const int error = rights.Install((flags & GuestControlCloseOnExec) != 0)) return Fail(error); } else #endif - received = ::recvfrom(socket->value, buffer.data(), static_cast(buffer.size()), + if (!shut) received = ::recvfrom(socket->value, buffer.data(), static_cast(buffer.size()), NativeReceiveFlags(flags, socket->type), reinterpret_cast(&native), &size); if (received < 0) { #ifdef _WIN32 @@ -2237,7 +2267,7 @@ std::int64_t APS5_VABI recvmsg_nid_postfix(int descriptor, GuestMsghdr* message, return Fail(NativeError()); #endif } - if (header.control) { + if (header.control && !(received == 0 && ReceiveShut(*socket))) { int keptFlags = 0; { std::lock_guard lock(socket->modeMutex); diff --git a/core/libs/tests/GuestAppContent.cpp b/core/libs/tests/GuestAppContent.cpp index a57e43df2c..0086125a1d 100644 --- a/core/libs/tests/GuestAppContent.cpp +++ b/core/libs/tests/GuestAppContent.cpp @@ -38,6 +38,7 @@ int main() { Require(sceAppContentTemporaryDataGetAvailableSpaceKb(nullptr, nullptr) == notInitialized); Require(sceAppContentDownloadDataFormat(nullptr) == notInitialized); Require(sceAppContentDownloadDataGetAvailableSpaceKb(nullptr, nullptr) == notInitialized); + Require(sceAppContentDownload1Expand(1024) == notInitialized); Require(sceAppContentDownload2Expand(1024) == notInitialized); Require(sceAppContentAddcontDelete(0, nullptr) == notInitialized); Require(sceAppContentAddcontEnqueueDownload(0, nullptr) == notInitialized); @@ -94,6 +95,7 @@ int main() { Require(sceAppContentDownloadDataGetAvailableSpaceKb(nullptr, nullptr) == ErrorParameter); AppContentMountPoint invalidMount{}; Require(sceAppContentDownloadDataGetAvailableSpaceKb(&invalidMount, &availableKb) == ErrorNotMounted); + Require(availableKb == 12345); const auto downloadData = ResolvePath_nid_no_patch("/download0"); Require(sceAppContentDownloadDataFormat(&download) == 0); Require(std::filesystem::is_directory(downloadData) && std::filesystem::is_empty(downloadData)); @@ -123,6 +125,25 @@ int main() { Require(sceAppContentDownload2Expand(1024 * 1024) == 0); Require(sceAppContentDownloadDataGetAvailableSpaceKb(&download2Mount, &download2Space) == 0); Require(download2Space == 2048); + AppContentMountPoint download1Mount{}; + std::memcpy(download1Mount.data, "/download1", 11); + const auto download1Data = ResolvePath_nid_no_patch("/download1"); + std::filesystem::create_directories(download1Data); + { std::ofstream file(download1Data / "old.bin"); file << "download1"; } + Require(sceAppContentDownloadDataFormat(&download1Mount) == 0); + Require(std::filesystem::is_directory(download1Data) && std::filesystem::is_empty(download1Data)); + Require(sceAppContentDownload1Expand(0) == ErrorParameter); + Require(sceAppContentDownload1Expand(2 * 1024 * 1024) == 0); + Require(std::filesystem::is_directory(download1Data)); + size_t download1Space = 12345; + Require(sceAppContentDownloadDataGetAvailableSpaceKb(&download1Mount, &download1Space) == 0); + Require(download1Space == 2048); + Require(sceAppContentDownload1Expand(1024 * 1024) == 0); + Require(sceAppContentDownloadDataGetAvailableSpaceKb(&download1Mount, &download1Space) == 0); + Require(download1Space == 2048); + { std::ofstream file(download1Data / "used.bin", std::ios::binary); file << std::string(1024, 'x'); } + Require(sceAppContentDownloadDataGetAvailableSpaceKb(&download1Mount, &download1Space) == 0); + Require(download1Space == 2047); const int32_t expectedParams[] = {3, 23566, -7, 0, 2147483647}; for (uint32_t id = 0; id < 5; ++id) { diff --git a/core/libs/tests/GuestContentSearch.cpp b/core/libs/tests/GuestContentSearch.cpp index 7101d21c48..e3cc01a47e 100644 --- a/core/libs/tests/GuestContentSearch.cpp +++ b/core/libs/tests/GuestContentSearch.cpp @@ -49,7 +49,11 @@ int main() { std::int64_t size = -1; std::int64_t updateId = -1; std::int32_t metadataId = -1; + std::int32_t applicationIndex = -1; + Require(sceContentSearchGetApplicationLastUpdateId(&updateId) == ErrorNotInitialized); + Require(sceContentSearchGetMyApplicationIndex(&applicationIndex) == ErrorNotInitialized); + Require(sceContentSearchGetNumOfApplication(&columnSet, 1, &orderBy, 1, &count, &updateId) == ErrorNotInitialized); Require(sceContentSearchGetContentLastUpdateId(&updateId) == ErrorNotInitialized); Require(sceContentSearchGetNumOfContent(&columnSet, 1, &count, &updateId) == ErrorNotInitialized); Require(sceContentSearchGetTotalContentSize(&columnSet, 1, &size, &updateId) == ErrorNotInitialized); @@ -92,8 +96,26 @@ int main() { updateId = -1; Require(sceContentSearchSearchContent(&columnSet, 1, &orderBy, 1, 0, 93, &count, infos, &updateId) == ErrorLimitTooBig); Require(count == -1 && updateId == -1); + updateId = -1; + Require(sceContentSearchGetApplicationLastUpdateId(&updateId) == 0 && updateId == 0); + count = -1; + updateId = -1; + Require(sceContentSearchGetNumOfApplication(&columnSet, 1, &orderBy, 1, &count, &updateId) == 0); + Require(count == 0 && updateId == 0); + count = -1; + updateId = -1; + Require(sceContentSearchGetNumOfApplication(nullptr, 0, nullptr, 0, &count, &updateId) == 0); + Require(count == 0 && updateId == 0); + count = -1; + updateId = -1; Require(sceContentSearchGetContentLastUpdateId(nullptr) == ErrorInvalidArgument); + Require(sceContentSearchGetApplicationLastUpdateId(nullptr) == ErrorInvalidArgument); + Require(sceContentSearchGetMyApplicationIndex(nullptr) == ErrorInvalidArgument); + Require(sceContentSearchGetNumOfApplication(&columnSet, 1, &orderBy, 1, nullptr, &updateId) == ErrorInvalidArgument); + Require(sceContentSearchGetNumOfApplication(&columnSet, 1, &orderBy, 1, &count, nullptr) == ErrorInvalidArgument); + Require(sceContentSearchGetNumOfApplication(&columnSet, 1, &orderBy, 0, &count, &updateId) == ErrorInvalidArgument); + Require(sceContentSearchGetNumOfApplication(&columnSet, 0, &orderBy, 1, &count, &updateId) == ErrorInvalidArgument); Require(sceContentSearchGetNumOfContent(&columnSet, 1, nullptr, &updateId) == ErrorInvalidArgument); Require(sceContentSearchGetNumOfContent(&columnSet, 1, &count, nullptr) == ErrorInvalidArgument); Require(sceContentSearchGetTotalContentSize(nullptr, 1, &size, &updateId) == ErrorInvalidArgument); @@ -113,6 +135,7 @@ int main() { ContentSearchContentColumn unknownColumn{8, 0, &photo, 2}; ContentSearchContentColumnSet unknownColumnSet{&unknownColumn, 1, 2}; Require(Throws([&] { sceContentSearchGetNumOfContent(&unknownColumnSet, 1, &count, &updateId); })); + Require(Throws([&] { sceContentSearchGetNumOfApplication(&unknownColumnSet, 1, &orderBy, 1, &count, &updateId); })); ContentSearchContentColumn missingValue{3, 0, nullptr, 2}; ContentSearchContentColumnSet missingValueSet{&missingValue, 1, 2}; Require(Throws([&] { sceContentSearchGetTotalContentSize(&missingValueSet, 1, &size, &updateId); })); @@ -121,6 +144,7 @@ int main() { Require(Throws([&] { sceContentSearchSearchContent(&unknownOperatorSet, 1, &orderBy, 1, 0, 2, &count, infos, &updateId); })); ContentSearchContentOrderByCondition unknownSort{3, 0}; Require(Throws([&] { sceContentSearchSearchContent(&columnSet, 1, &unknownSort, 1, 0, 2, &count, infos, &updateId); })); + Require(Throws([&] { sceContentSearchGetNumOfApplication(&columnSet, 1, &unknownSort, 1, &count, &updateId); })); Require(count == -1 && updateId == -1); Require(sceContentSearchSearchContent(nullptr, 0, nullptr, 0, 0, 0, nullptr, nullptr, nullptr) == ErrorInvalidArgument); Require(sceContentSearchSearchContent(nullptr, 0, nullptr, 0, 0, 93, nullptr, nullptr, nullptr) == ErrorLimitTooBig); @@ -141,6 +165,9 @@ int main() { Require(sceContentSearchSearchContent(&columnSet, 1, &orderBy, 1, 0, 2, &count, infos, &updateId) == ErrorNotInitialized); Require(sceContentSearchCloseMetadata(1) == ErrorNotInitialized); Require(sceContentSearchGetContentLastUpdateId(&updateId) == ErrorNotInitialized); + Require(sceContentSearchGetApplicationLastUpdateId(&updateId) == ErrorNotInitialized); + Require(sceContentSearchGetMyApplicationIndex(&applicationIndex) == ErrorNotInitialized); + Require(sceContentSearchGetNumOfApplication(&columnSet, 1, &orderBy, 1, &count, &updateId) == ErrorNotInitialized); Require(updateId == -1); constexpr int binderResult = static_cast(0x809D000F); Require(sceContentBinderInitialize() == binderResult); @@ -152,8 +179,5 @@ int main() { Require(sceContentBinderEnd() == binderResult); Require(sceContentBinderTerminate() == binderResult); - Require(ThrowsRuntimeError([] { sceContentSearchGetApplicationLastUpdateId(); })); - Require(ThrowsRuntimeError([] { sceContentSearchGetMyApplicationIndex(); })); - Require(ThrowsRuntimeError([] { sceContentSearchGetNumOfApplication(); })); Require(ThrowsRuntimeError([] { sceContentSearchSearchApplication(); })); } diff --git a/core/libs/tests/GuestJxrGlue.cpp b/core/libs/tests/GuestJxrGlue.cpp new file mode 100644 index 0000000000..7c4031147a --- /dev/null +++ b/core/libs/tests/GuestJxrGlue.cpp @@ -0,0 +1,202 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceJxr/include/Api.hpp" +#include "prx/libc/include/ApplicationHeap.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#include +#include +#include + +extern "C" const void* GetPixelFormatFromHash(unsigned char hash); + +namespace { + +void Require(bool value) { if (!value) std::abort(); } + +void* lastCalloc = nullptr; +std::size_t lastCount = 0; +std::size_t lastSize = 0; +void* lastFreed = nullptr; +int frees = 0; +bool failCalloc = false; + +void* APS5_VABI Allocate(std::size_t size) { return std::malloc(size); } +void APS5_VABI Free(void* pointer) { + if (pointer != nullptr) { + lastFreed = pointer; + ++frees; + } + std::free(pointer); +} +void* APS5_VABI Reallocate(void* pointer, std::size_t size) { return std::realloc(pointer, size); } +void* APS5_VABI Calloc(std::size_t count, std::size_t size) { + lastCount = count; + lastSize = size; + lastCalloc = failCalloc ? nullptr : std::calloc(count, size); + return lastCalloc; +} +void* APS5_VABI Align(std::size_t, std::size_t size) { return std::malloc(size); } +void* APS5_VABI Realign(void* pointer, std::size_t size, std::size_t) { return std::realloc(pointer, size); } +int APS5_VABI PosixAlign(void** pointer, std::size_t, std::size_t size) { + *pointer = std::malloc(size); + return *pointer ? 0 : 12; +} + +void InitializeHeap() { + alignas(16) static std::array process{}; + alignas(16) static std::array libc{}; + alignas(16) static std::array replacement{}; + const auto write = [](auto& data, std::size_t offset, auto value) { + std::memcpy(data.data() + offset, &value, sizeof(value)); + }; + write(process, 0, std::uint64_t{0x40}); + write(process, 8, std::uint32_t{0x4942524f}); + write(process, 0x38, libc.data()); + write(libc, 0, std::uint64_t{0x38}); + write(libc, 0x30, replacement.data()); + write(replacement, 0, std::uint64_t{0x78}); + write(replacement, 8, std::uint64_t{2}); + write(replacement, 0x20, reinterpret_cast(&Allocate)); + write(replacement, 0x28, reinterpret_cast(&Free)); + write(replacement, 0x30, reinterpret_cast(&Calloc)); + write(replacement, 0x38, reinterpret_cast(&Reallocate)); + write(replacement, 0x40, reinterpret_cast(&Align)); + write(replacement, 0x48, reinterpret_cast(&Realign)); + write(replacement, 0x50, reinterpret_cast(&PosixAlign)); + ApplicationHeapInitialize_nid_no_patch(process.data()); +} + +void TestPixelFormatHash() { + int found = 0; + for (int hash = 0; hash < 256; ++hash) { + const void* expected = GetPixelFormatFromHash(static_cast(hash)); + const void* actual = GetPixelFormatFromHash_nid_postfix(static_cast(hash)); + Require((expected == nullptr) == (actual == nullptr)); + if (!actual) continue; + ++found; + Require(std::memcmp(expected, actual, 16) == 0); + Require(static_cast(actual)[15] == hash); + } + Require(found > 0 && found < 256); + const std::uint8_t gray8[16] = {0x24, 0xc3, 0xdd, 0x6f, 0x03, 0x4e, 0xfe, 0x4b, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x08}; + const void* gray = GetPixelFormatFromHash_nid_postfix(0x08); + Require(gray && std::memcmp(gray, gray8, sizeof(gray8)) == 0); +} + +template +void RequireThrows(Function function) { + bool threw = false; + try { + function(); + } catch (const std::invalid_argument&) { + threw = true; + } catch (const std::length_error&) { + threw = true; + } + Require(threw); +} + +void TestImageIids() { + const std::uint32_t sentinel = 7; + const std::uint32_t* iid = &sentinel; + Require(GetImageEncodeIID_nid_postfix(".jxr", &iid) == 0 && *iid == 101); + Require(GetImageDecodeIID_nid_postfix(".jxr", &iid) == 0 && *iid == 201); + Require(GetImageEncodeIID_nid_postfix(".JXR", &iid) == 0 && *iid == 101); + Require(GetImageEncodeIID_nid_postfix(".jxr.tmp", &iid) == 0 && *iid == 101); + Require(GetImageEncodeIID_nid_postfix(".wdp", &iid) == 0 && *iid == 100); + Require(GetImageDecodeIID_nid_postfix(".WDP", &iid) == 0 && *iid == 201); + Require(GetImageEncodeIID_nid_postfix(".hdp", &iid) == 0 && *iid == 100); + Require(GetImageDecodeIID_nid_postfix(".Hdp", &iid) == 0 && *iid == 201); + const std::uint32_t* encode = nullptr; + const std::uint32_t* again = nullptr; + Require(GetImageEncodeIID_nid_postfix(".jxr", &encode) == 0); + Require(GetImageEncodeIID_nid_postfix(".jxr", &again) == 0 && encode == again); + for (const char* extension : {".png", ".jx", "", "jxr", ".j\xc3r", ".jpg"}) { + iid = &sentinel; + Require(GetImageEncodeIID_nid_postfix(extension, &iid) == -106 && iid == &sentinel); + Require(GetImageDecodeIID_nid_postfix(extension, &iid) == -106 && iid == &sentinel); + Require(GetImageEncodeIID_nid_postfix(extension, nullptr) == -106); + Require(GetImageDecodeIID_nid_postfix(extension, nullptr) == -106); + } + RequireThrows([] { GetImageEncodeIID_nid_postfix(".jxr", nullptr); }); + RequireThrows([] { GetImageDecodeIID_nid_postfix(".wdp", nullptr); }); + RequireThrows([] { + const std::uint32_t* out = nullptr; + GetImageEncodeIID_nid_postfix(nullptr, &out); + }); + RequireThrows([] { + const std::uint32_t* out = nullptr; + GetImageDecodeIID_nid_postfix(nullptr, &out); + }); +} + +void TestAlignedAllocation() { + for (std::size_t alignment : {std::size_t{8}, std::size_t{16}, std::size_t{24}, std::size_t{64}, + std::size_t{4096}}) { + for (std::size_t size : {std::size_t{0}, std::size_t{1}, std::size_t{100}}) { + void* memory = reinterpret_cast(std::uintptr_t{1}); + const int before = frees; + Require(PKAllocAligned_nid_postfix(&memory, size, alignment) == 0); + Require(memory != nullptr && lastCalloc != nullptr); + Require(lastCount == 1 && lastSize == size + sizeof(void*) + alignment - 1); + const auto address = reinterpret_cast(memory); + Require(address % alignment == 0); + const auto offset = address - reinterpret_cast(lastCalloc); + Require(offset >= sizeof(void*) && offset + size <= lastSize); + void* stored = nullptr; + std::memcpy(&stored, static_cast(memory) - sizeof(void*), sizeof(stored)); + Require(stored == lastCalloc); + for (std::size_t index = 0; index < size; ++index) + Require(static_cast(memory)[index] == 0); + void* const original = lastCalloc; + Require(PKFreeAligned_nid_postfix(&memory) == 0); + Require(memory == nullptr && frees == before + 1 && lastFreed == original); + } + } + void* memory = reinterpret_cast(std::uintptr_t{1}); + failCalloc = true; + Require(PKAllocAligned_nid_postfix(&memory, 32, 16) == -101 && memory == nullptr); + failCalloc = false; + const int before = frees; + Require(PKFreeAligned_nid_postfix(&memory) == 0 && frees == before); + Require(PKFreeAligned_nid_postfix(nullptr) == 0 && frees == before); + RequireThrows([] { PKAllocAligned_nid_postfix(nullptr, 32, 16); }); + memory = reinterpret_cast(std::uintptr_t{1}); + RequireThrows([&memory] { PKAllocAligned_nid_postfix(&memory, 32, 0); }); + Require(memory == nullptr); + for (std::size_t alignment : {std::size_t{1}, std::size_t{2}, std::size_t{4}, std::size_t{7}}) { + const int before = frees; + void* const previous = lastCalloc; + lastCalloc = nullptr; + memory = reinterpret_cast(std::uintptr_t{1}); + RequireThrows([&memory, alignment] { PKAllocAligned_nid_postfix(&memory, 32, alignment); }); + Require(memory == nullptr && frees == before && lastCalloc == nullptr); + lastCalloc = previous; + } + constexpr auto maximum = std::numeric_limits::max(); + RequireThrows([] { + void* out = nullptr; + PKAllocAligned_nid_postfix(&out, maximum - 4, 16); + }); + RequireThrows([] { + void* out = nullptr; + PKAllocAligned_nid_postfix(&out, 16, maximum - 8); + }); +} + +} + +int main() { + InitializeHeap(); + TestPixelFormatHash(); + TestImageIids(); + TestAlignedAllocation(); + Require(IDPEmpty_nid_postfix(nullptr) == 0); + int codec = 0; + Require(IDPEmpty_nid_postfix(&codec) == 0 && codec == 0); + return 0; +} diff --git a/core/libs/tests/GuestLibcInternalFirmwareAnswers.cpp b/core/libs/tests/GuestLibcInternalFirmwareAnswers.cpp new file mode 100644 index 0000000000..a07b48fb45 --- /dev/null +++ b/core/libs/tests/GuestLibcInternalFirmwareAnswers.cpp @@ -0,0 +1,62 @@ +#include "prx/libSceLibcInternal/include/MathInternals.hpp" +#include "prx/libSceLibcInternal/include/RuntimeInternals.hpp" +#include +#include +#include +#include + +static void Require(bool value, const char* message) { + if (!value) { + std::fprintf(stderr, "%s\n", message); + std::abort(); + } +} + +static void TestDaysto() { + Require(_Daysto_nid_postfix(1, 0) == 0, "_Daysto(1, 0)"); + Require(_Daysto_nid_postfix(1, 1) == 31, "_Daysto(1, 1)"); + Require(_Daysto_nid_postfix(4, 2) == 60, "a positive multiple of four uses the leap table"); + Require(_Daysto_nid_postfix(5, 2) == 60, "year 5 adds one leap day to the common table"); + Require(_Daysto_nid_postfix(0, 2) == 59, "year 0 uses the common table with no leap days"); + Require(_Daysto_nid_postfix(-1, 2) == 59, "years -1 to -3 add no leap days"); + Require(_Daysto_nid_postfix(-3, 11) == 334, "_Daysto(-3, 11)"); + Require(_Daysto_nid_postfix(-4, 2) == 63, "year -4 adds 1 + 8 / 4 days to the leap table"); + Require(_Daysto_nid_postfix(-5, 0) == 3, "year -5 adds 1 + 9 / 4 days to the common table"); + Require(_Daysto_nid_postfix(100, 11) == 359, "every fourth year uses the leap table, centuries included"); + Require(_Daysto_nid_postfix(2023, 11) == 334 + 505, "_Daysto(2023, 11)"); + Require(_Daysto_nid_postfix(2024, 11) == 335 + 505, "_Daysto(2024, 11)"); + constexpr int Lowest = std::numeric_limits::min(); + constexpr int Highest = std::numeric_limits::max(); + Require(_Daysto_nid_postfix(Lowest, 0) == 536870914 && _Daysto_nid_postfix(Lowest, 11) == 536871249, "the lowest year wraps 4 - year as an unsigned 32-bit value"); + Require(_Daysto_nid_postfix(Lowest + 1, 0) == 536870913 && _Daysto_nid_postfix(Lowest + 3, 11) == 536871247, "years just above the lowest wrap 4 - year"); + Require(_Daysto_nid_postfix(Lowest + 4, 0) == 536870913 && _Daysto_nid_postfix(Lowest + 4, 11) == 536871248, "the last wrapping year"); + Require(_Daysto_nid_postfix(Lowest + 5, 0) == 536870912 && _Daysto_nid_postfix(Lowest + 5, 11) == 536871246, "the first year whose 4 - year fits in int"); + Require(_Daysto_nid_postfix(Highest, 0) == 536870911 && _Daysto_nid_postfix(Highest, 11) == 536871245, "the highest year"); +} + +static void TestXpGetw() { + const float one[] = {5.0f, 7.0f, 11.0f, 13.0f}; + Require(_FXp_getw_nid_postfix(one, 0) == 0.0f, "no parts sum to 0"); + Require(_FXp_getw_nid_postfix(one, 1) == 5.0f, "one part is returned as it is"); + const float zeroHead[] = {0.0f, 7.0f, 11.0f}; + Require(_FXp_getw_nid_postfix(zeroHead, 3) == 0.0f, "a zero first part ends the sum"); + const float zeroSecond[] = {5.0f, 0.0f, 11.0f}; + Require(_FXp_getw_nid_postfix(zeroSecond, 3) == 5.0f, "a zero second part ends the sum"); + Require(_FXp_getw_nid_postfix(one, 2) == 12.0f, "two parts are added"); + const float zeroThird[] = {5.0f, 7.0f, 0.0f, 13.0f}; + Require(_FXp_getw_nid_postfix(zeroThird, 4) == 12.0f, "a zero third part ends the sum"); + Require(_FXp_getw_nid_postfix(one, 3) == 23.0f, "three exact parts are added"); + Require(_FXp_getw_nid_postfix(one, 4) == 36.0f, "the fourth part joins the third"); + const float carry[] = {16777216.0f, 1.0f, 1.0f, 2.0f}; + Require(_FXp_getw_nid_postfix(carry, 3) == 16777218.0f, "a second part lost in the first sum is folded with the third first"); + Require(_FXp_getw_nid_postfix(carry, 4) == 16777220.0f, "a second part lost in the first sum is folded with the third and fourth first"); + const float nan[] = {std::nanf(""), 1.0f}; + Require(std::isnan(_FXp_getw_nid_postfix(nan, 2)), "a NaN first part is summed, not compared away"); +} + +int main() { + Require(_Isdst_nid_postfix() == -1, "_Isdst did not return -1"); + TestDaysto(); + TestXpGetw(); + return 0; +} diff --git a/core/libs/tests/GuestLibreSsl3Asn1.cpp b/core/libs/tests/GuestLibreSsl3Asn1.cpp new file mode 100644 index 0000000000..303e7104d7 --- /dev/null +++ b/core/libs/tests/GuestLibreSsl3Asn1.cpp @@ -0,0 +1,87 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/ApplicationHeap.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#include +#include +#include + +static_assert(sizeof(Asn1String) == 24 && offsetof(Asn1String, data) == 8 && offsetof(Asn1String, flags) == 16); + +static void Require(bool condition, std::source_location location = std::source_location::current()) { + if (condition) return; + std::fprintf(stderr, "LibreSSL 3 ASN.1 check failed at line %u\n", location.line()); + std::abort(); +} + +template static void RequireThrows(TAction action, std::source_location location = std::source_location::current()) { + try { action(); } catch (const std::exception&) { return; } + Require(false, location); +} + +static void TestGet0Data() { + unsigned char bytes[] {1, 2, 3}; + Asn1String string {3, 2, bytes, 0}; + Require(ASN1_STRING_get0_data_nid_postfix(&string) == bytes); + string = {0, 4, nullptr, 0}; + Require(ASN1_STRING_get0_data_nid_postfix(&string) == nullptr); + string = {-1, 0x102, bytes, 0x010}; + Require(ASN1_STRING_get0_data_nid_postfix(&string) == bytes); + RequireThrows([] { ASN1_STRING_get0_data_nid_postfix(nullptr); }); +} + +static void InitializeHeap() { + void* const api[10] {}; + ApplicationHeapRegister_nid_no_patch(api); +} + +static Asn1String* NewInteger(int length, int type, std::int64_t flags) { + auto* integer = static_cast(malloc_nid_postfix(sizeof(Asn1String))); + Require(integer != nullptr); + integer->length = length; + integer->type = type; + integer->flags = flags; + integer->data = nullptr; + if (length > 0) { + integer->data = static_cast(malloc_nid_postfix(static_cast(length))); + Require(integer->data != nullptr); + std::memset(integer->data, 0x5A, static_cast(length)); + } + return integer; +} + +static void TestIntegerFree() { + ASN1_INTEGER_free_nid_postfix(nullptr); + ASN1_INTEGER_free_nid_postfix(NewInteger(4, 2, 0)); + ASN1_INTEGER_free_nid_postfix(NewInteger(16, 0x102, 0)); + ASN1_INTEGER_free_nid_postfix(NewInteger(0, 2, 0)); + ASN1_INTEGER_free_nid_postfix(NewInteger(4, 6, 0)); + + Asn1String* borrowed = NewInteger(4, 2, 0x010); + unsigned char* const data = borrowed->data; + ASN1_INTEGER_free_nid_postfix(borrowed); + Require(data[0] == 0x5A && data[3] == 0x5A); + free_nid_postfix(data); + + Asn1String* negative = NewInteger(4, 2, 0); + negative->length = -1; + RequireThrows([&] { ASN1_INTEGER_free_nid_postfix(negative); }); + Require(negative->data != nullptr && negative->data[0] == 0x5A); + negative->length = 4; + ASN1_INTEGER_free_nid_postfix(negative); + + Asn1String* empty = NewInteger(0, 2, 0); + empty->length = -1; + ASN1_INTEGER_free_nid_postfix(empty); +} + +int main() { + InitializeHeap(); + TestGet0Data(); + TestIntegerFree(); + std::puts("libSceLibreSsl3 ASN.1 tests passed"); +} diff --git a/core/libs/tests/GuestLibreSsl3X509Extensions.cpp b/core/libs/tests/GuestLibreSsl3X509Extensions.cpp new file mode 100644 index 0000000000..a89f8c328e --- /dev/null +++ b/core/libs/tests/GuestLibreSsl3X509Extensions.cpp @@ -0,0 +1,69 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#include + +static void Require(bool condition, std::source_location location = std::source_location::current()) { + if (condition) return; + std::fprintf(stderr, "LibreSSL X509 extension check failed at line %u\n", location.line()); + std::abort(); +} + +static void TestGet0Extensions() { + LibreSsl3Stack extensions {}; + LibreSsl3ExtensionsCertInfo info {}; + LibreSsl3ExtensionsX509 certificate {}; + certificate.certInfo = &info; + Require(X509_get0_extensions_nid_postfix(&certificate) == nullptr); + std::memset(info.beforeExtensions, 0xFF, sizeof(info.beforeExtensions)); + std::memset(info.rest, 0xFF, sizeof(info.rest)); + info.extensions = &extensions; + Require(X509_get0_extensions_nid_postfix(&certificate) == &extensions); +} + +static void TestGetExtCount() { + LibreSsl3Stack extensions {}; + LibreSsl3ExtensionsCertInfo info {}; + LibreSsl3ExtensionsX509 certificate {}; + certificate.certInfo = &info; + Require(X509_get_ext_count_nid_postfix(&certificate) == 0); + info.extensions = &extensions; + Require(X509_get_ext_count_nid_postfix(&certificate) == 0); + extensions.num = 3; + extensions.numAlloc = 8; + Require(X509_get_ext_count_nid_postfix(&certificate) == 3); +} + +static void TestGetExt() { + int first = 0; + int second = 0; + int third = 0; + char* slots[] {reinterpret_cast(&first), reinterpret_cast(&second), reinterpret_cast(&third)}; + LibreSsl3Stack extensions {}; + LibreSsl3ExtensionsCertInfo info {}; + LibreSsl3ExtensionsX509 certificate {}; + certificate.certInfo = &info; + Require(X509_get_ext_nid_postfix(&certificate, 0) == nullptr); + info.extensions = &extensions; + Require(X509_get_ext_nid_postfix(&certificate, 0) == nullptr); + extensions = {2, slots, 0, 3, nullptr}; + Require(X509_get_ext_nid_postfix(&certificate, 0) == &first); + Require(X509_get_ext_nid_postfix(&certificate, 1) == &second); + Require(X509_get_ext_nid_postfix(&certificate, 2) == nullptr); + Require(X509_get_ext_nid_postfix(&certificate, -1) == nullptr); + Require(X509_get_ext_nid_postfix(&certificate, INT_MIN) == nullptr); + Require(X509_get_ext_nid_postfix(&certificate, INT_MAX) == nullptr); + extensions.num = 3; + Require(X509_get_ext_nid_postfix(&certificate, 2) == &third); + Require(X509_get_ext_nid_postfix(&certificate, 3) == nullptr); +} + +int main() { + TestGet0Extensions(); + TestGetExtCount(); + TestGetExt(); + return 0; +} diff --git a/core/libs/tests/GuestLibreSslSslSession.cpp b/core/libs/tests/GuestLibreSslSslSession.cpp new file mode 100644 index 0000000000..55a3e23e08 --- /dev/null +++ b/core/libs/tests/GuestLibreSslSslSession.cpp @@ -0,0 +1,121 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#include + +struct TestCertKey { + void* x509; + void* privatekey; + const void* digest; +}; + +struct TestCert { + TestCertKey* key; + TestCertKey pkeys[8]; + unsigned char rest[56]; +}; + +struct TestSession { + unsigned char beforeCipher[168]; + const void* cipher; + unsigned char rest[56]; +}; + +struct TestSsl { + unsigned char beforeCert[80]; + TestCert* cert; + unsigned char beforeSession[40]; + TestSession* session; + unsigned char rest[96]; +}; + +static_assert(sizeof(TestCertKey) == 24 && sizeof(TestCert) == 256); +static_assert(sizeof(TestSession) == 232 && offsetof(TestSession, cipher) == 168); +static_assert(sizeof(TestSsl) == 232 && offsetof(TestSsl, cert) == 80 && offsetof(TestSsl, session) == 128); + +static const LibreSslSsl* Connection(const TestSsl* ssl) { + return reinterpret_cast(ssl); +} + +static void Require(bool condition, std::source_location location = std::source_location::current()) { + if (condition) return; + std::fprintf(stderr, "LibreSSL SSL session check failed at line %u\n", location.line()); + std::abort(); +} + +template static void RequireThrows(TAction action, std::source_location location = std::source_location::current()) { + try { action(); } catch (const std::exception&) { return; } + Require(false, location); +} + +static void TestGetSession() { + TestSession session {}; + TestCert cert {}; + TestSsl ssl {}; + RequireThrows([] { SSL_get_session_nid_postfix(nullptr); }); + Require(SSL_get_session_nid_postfix(Connection(&ssl)) == nullptr); + ssl.cert = &cert; + ssl.session = &session; + Require(reinterpret_cast(SSL_get_session_nid_postfix(Connection(&ssl))) == &session); +} + +static void TestCurrentCipher() { + int cipher = 0; + TestSession session {}; + TestSsl ssl {}; + RequireThrows([] { SSL_get_current_cipher_nid_postfix(nullptr); }); + Require(SSL_get_current_cipher_nid_postfix(Connection(&ssl)) == nullptr); + ssl.session = &session; + Require(SSL_get_current_cipher_nid_postfix(Connection(&ssl)) == nullptr); + session.cipher = &cipher; + Require(SSL_get_current_cipher_nid_postfix(Connection(&ssl)) == &cipher); +} + +static void TestGetCertificate() { + int x509 = 0; + int other = 0; + int key = 0; + TestCert cert {}; + TestSsl ssl {}; + RequireThrows([] { SSL_get_certificate_nid_postfix(nullptr); }); + Require(SSL_get_certificate_nid_postfix(Connection(&ssl)) == nullptr); + ssl.cert = &cert; + RequireThrows([&] { SSL_get_certificate_nid_postfix(Connection(&ssl)); }); + cert.pkeys[0].x509 = &other; + cert.pkeys[2].x509 = &x509; + cert.pkeys[2].privatekey = &key; + cert.key = &cert.pkeys[1]; + Require(SSL_get_certificate_nid_postfix(Connection(&ssl)) == nullptr); + cert.key = &cert.pkeys[2]; + Require(SSL_get_certificate_nid_postfix(Connection(&ssl)) == &x509); +} + +static void TestGetPrivateKey() { + int x509 = 0; + int key = 0; + int other = 0; + TestCert cert {}; + TestSsl ssl {}; + RequireThrows([] { SSL_get_privatekey_nid_postfix(nullptr); }); + Require(SSL_get_privatekey_nid_postfix(Connection(&ssl)) == nullptr); + ssl.cert = &cert; + RequireThrows([&] { SSL_get_privatekey_nid_postfix(Connection(&ssl)); }); + cert.pkeys[0].privatekey = &other; + cert.pkeys[3].x509 = &x509; + cert.pkeys[3].privatekey = &key; + cert.key = &cert.pkeys[1]; + Require(SSL_get_privatekey_nid_postfix(Connection(&ssl)) == nullptr); + cert.key = &cert.pkeys[3]; + Require(SSL_get_privatekey_nid_postfix(Connection(&ssl)) == &key); +} + +int main() { + TestGetSession(); + TestCurrentCipher(); + TestGetCertificate(); + TestGetPrivateKey(); + return 0; +} diff --git a/core/libs/tests/GuestMath.cpp b/core/libs/tests/GuestMath.cpp index 0bf49c3afa..3936b662ef 100644 --- a/core/libs/tests/GuestMath.cpp +++ b/core/libs/tests/GuestMath.cpp @@ -796,14 +796,14 @@ static void CheckFmodfErrno() { const RestoreFloatingPointState saved; const struct { std::uint32_t dividend; std::uint32_t divisor; std::uint32_t expected; bool invalid; bool nan; } cases[] = { {0x3f800000u, 0x00000000u, 0u, true, true}, {0x3f800000u, 0x80000000u, 0u, true, true}, - {0x7f800000u, 0x40000000u, 0u, true, true}, {0x7fc00000u, 0x40000000u, 0u, false, true}, + {0x7f800000u, 0x40000000u, 0u, true, true}, {0x7fc00000u, 0x40000000u, 0u, true, true}, {0x3f800000u, 0x7f800000u, 0x3f800000u, false, false}, {0xbf800000u, 0x7f800000u, 0xbf800000u, false, false}, {0x41280000u, 0x40000000u, 0x3f000000u, false, false}, {0xc1280000u, 0x40000000u, 0xbf000000u, false, false}, {0x41280000u, 0xc0000000u, 0x3f000000u, false, false}, {0xc1280000u, 0xc0000000u, 0xbf000000u, false, false}, {0x00000000u, 0x40000000u, 0x00000000u, false, false}, {0x80000000u, 0x40000000u, 0x80000000u, false, false}, {0x00000000u, 0x80000000u, 0u, true, true}, - {0x3f800000u, 0x7fc00001u, 0u, false, true}, - {0x00000000u, 0x7fc00001u, 0u, false, true}, + {0x3f800000u, 0x7fc00001u, 0u, true, true}, + {0x00000000u, 0x7fc00001u, 0u, true, true}, {0x7f800001u, 0x40000000u, 0u, true, true}, {0x3f800000u, 0x7f800001u, 0u, true, true}, {0x00000003u, 0x00000002u, 0x00000001u, false, false}, @@ -817,7 +817,7 @@ static void CheckFmodfErrno() { const std::uint32_t bits = std::bit_cast(result); const int invalid = std::fetestexcept(FE_INVALID) != 0; const bool nan = std::isnan(result); - if (nan != test.nan || (!nan && bits != test.expected) || invalid != test.invalid || *__error_nid_postfix() != 73) { + if (nan != test.nan || (!nan && bits != test.expected) || invalid != test.invalid || *__error_nid_postfix() != (test.nan ? EDOM : 73)) { std::fprintf(stderr, "Guest fmodf failed for %08x and %08x: got %08x, invalid %d, errno %d\n", test.dividend, test.divisor, bits, invalid, *__error_nid_postfix()); std::abort(); @@ -827,7 +827,7 @@ static void CheckFmodfErrno() { std::feraiseexcept(FE_DIVBYZERO); *__error_nid_postfix() = 73; (void)fmodf_nid_postfix(1.0f, 0.0f); - if (*__error_nid_postfix() != 73 || std::fetestexcept(FE_DIVBYZERO) == 0) { + if (*__error_nid_postfix() != EDOM || std::fetestexcept(FE_DIVBYZERO) == 0) { std::fprintf(stderr, "Guest fmodf dropped the floating-point environment\n"); std::abort(); } @@ -908,7 +908,7 @@ static void CheckNearbyintl() { static void CheckFmodErrno() { errno = 0; (void)fmod_nid_postfix(1.0, 0.0); - Require(errno == 0); + Require(errno == EDOM); Require(fmod_nid_postfix(1e300, 3.0) == std::fmod(1e300, 3.0)); } @@ -1506,13 +1506,56 @@ static void CheckExpm1ScalingRounding() { } _mm_setcsr(savedCsr); } -static void CheckAtanhEdgeFlags() { - for (const double input : {2.0, -2.0, std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN(), -std::numeric_limits::quiet_NaN()}) { - errno = 0; - std::feclearexcept(FE_ALL_EXCEPT); - Require(std::isnan(atanh_nid_postfix(input)) && errno == EDOM && std::fetestexcept(FE_INVALID) != 0); +static void CheckAtanhDomainEnvironment() { + const RestoreFloatingPointState saved; + const unsigned savedCsr = _mm_getcsr(); + const struct { + std::uint64_t input; + std::uint64_t result; + unsigned raised; + int error; + } cases[] = { + {0x3ff0000000000000ull, 0x7ff0000000000000ull, 4u, ERANGE}, + {0xbff0000000000000ull, 0xfff0000000000000ull, 4u, ERANGE}, + {0x3ff0000000000001ull, 0xfff8000000000000ull, 1u, EDOM}, + {0xbff0000000000001ull, 0xfff8000000000000ull, 1u, EDOM}, + {0x4000000000000000ull, 0xfff8000000000000ull, 1u, EDOM}, + {0xc000000000000000ull, 0xfff8000000000000ull, 1u, EDOM}, + {0x7ff0000000000000ull, 0xfff8000000000000ull, 1u, EDOM}, + {0xfff0000000000000ull, 0xfff8000000000000ull, 1u, EDOM}, + {0x7ff8000000001234ull, 0x7ff8000000001234ull, 1u, EDOM}, + {0xfff8000000001234ull, 0xfff8000000001234ull, 1u, EDOM}, + {0x7ff0000000000001ull, 0x7ff8000000000001ull, 1u, EDOM}, + {0xfff0000000000001ull, 0xfff8000000000001ull, 1u, EDOM}, + }; + const int rounding[] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO}; + double (APS5_VABI * volatile call)(double) = atanh_nid_postfix; + for (unsigned mode = 0; mode != 4; ++mode) { + for (unsigned denorm = 0; denorm != 4; ++denorm) { + const unsigned control = 0x1f80u | (mode << 13u) | ((denorm & 1u) ? 0x40u : 0u) | ((denorm & 2u) ? 0x8000u : 0u); + for (std::uint16_t sticky : {0u, 5u, 32u}) { + for (const auto& item : cases) { + Require(std::fesetenv(FE_DFL_ENV) == 0 && std::fesetround(rounding[mode]) == 0); + Require(fesetexceptflag_nid_postfix(&sticky, 0x3f) == 0); + _mm_setcsr(control | sticky); + GuestFloatingPointEnvironment before; + Require(fegetenv_nid_postfix(&before) == 0 && (before.status & 0x3fu) == sticky); + errno = 1234; + const auto result = std::bit_cast(call(std::bit_cast(item.input))); + const int error = errno; + GuestFloatingPointEnvironment after; + Require(fegetenv_nid_postfix(&after) == 0); + if (result != item.result || after.mxcsr != (control | sticky | item.raised) || (after.status & 0x3fu) != (sticky | item.raised) || after.control != before.control || error != item.error) { + std::fprintf(stderr, "atanh domain: input=%016llx mode=%u denorm=%u sticky=%u bits=%016llx csr=%x x87=%x errno=%d\n", static_cast(item.input), mode, denorm, sticky, static_cast(result), after.mxcsr, after.status, error); + Require(false); + } + } + } + } } + _mm_setcsr(savedCsr); } + static void CheckAtanhConsoleBits() { constexpr struct { std::uint64_t input; @@ -1538,6 +1581,14 @@ static void CheckAtanhConsoleBits() { Require(errno == (item.error != 0 ? item.error : 1234)); } } +static void CheckAtanhEdgeFlags() { + for (const double input : {2.0, -2.0, std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN(), -std::numeric_limits::quiet_NaN()}) { + errno = 0; + std::feclearexcept(FE_ALL_EXCEPT); + Require(std::isnan(atanh_nid_postfix(input)) && errno == EDOM && std::fetestexcept(FE_INVALID) != 0); + } +} + static void CheckHypotConsoleBits() { constexpr struct { std::uint64_t x; @@ -1575,6 +1626,77 @@ static void CheckHypotConsoleBits() { Require(std::bit_cast(hypot_nid_postfix(std::bit_cast(item.y), std::bit_cast(item.x))) == item.expected || std::isnan(std::bit_cast(item.expected))); } } +static void CheckFmodEdgeFlags() { + const double nan = std::numeric_limits::quiet_NaN(); + const double infinity = std::numeric_limits::infinity(); + constexpr double one = 1.0; + const std::pair cases[] = {{0.0, nan}, {one, -nan}, {nan, one}, {-nan, 0.0}, {one, 0.0}, {infinity, one}, {-infinity, -2.0}}; + for (const auto& [x, y] : cases) { + errno = 0; + std::feclearexcept(FE_ALL_EXCEPT); + Require(std::isnan(fmod_nid_postfix(x, y)) && errno == EDOM && std::fetestexcept(FE_INVALID) != 0); + errno = 0; + std::feclearexcept(FE_ALL_EXCEPT); + Require(std::isnan(fmodf_nid_postfix(static_cast(x), static_cast(y))) && errno == EDOM && std::fetestexcept(FE_INVALID) != 0); + } +} + +static void CheckFmodConsoleBits() { + constexpr struct { + std::uint64_t x; + std::uint64_t y; + std::uint64_t expected; + int expectedErrno; + } cases[] = { + {0x3ff0000000000000ull, 0x0000000000000000ull, 0xfff8000000000000ull, EDOM}, + {0xbff0000000000000ull, 0x8000000000000000ull, 0xfff8000000000000ull, EDOM}, + {0x7ff0000000000000ull, 0x4000000000000000ull, 0xfff8000000000000ull, EDOM}, + {0xfff0000000000000ull, 0x7ff0000000000000ull, 0xfff8000000000000ull, EDOM}, + {0x7ff8000000000123ull, 0x4000000000000000ull, 0x7ff8000000000123ull, EDOM}, + {0xfff8000000000123ull, 0x0000000000000000ull, 0xfff8000000000123ull, EDOM}, + {0x3ff0000000000000ull, 0x7ff8000000000456ull, 0x7ff8000000000456ull, EDOM}, + {0x7ff8000000000123ull, 0xfff8000000000456ull, 0xfff8000000000456ull, EDOM}, + {0x7ff4000000000000ull, 0x4000000000000000ull, 0x7ffc000000000000ull, EDOM}, + {0x3ff0000000000000ull, 0x7ff4000000000000ull, 0x7ffc000000000000ull, EDOM}, + {0x7ff0000000000000ull, 0x7ff8000000000456ull, 0x7ff8000000000456ull, EDOM}, + {0x3ff0000000000000ull, 0x7ff0000000000000ull, 0x3ff0000000000000ull, 0}, + {0x4016000000000000ull, 0x4000000000000000ull, 0x3ff8000000000000ull, 0}, + {0x0000000000000000ull, 0x8000000000000000ull, 0xfff8000000000000ull, EDOM}, + {0x0000000000000003ull, 0x0000000000000002ull, 0x0000000000000001ull, 0}, + }; + for (const auto& item : cases) { + errno = 1234; + Require(std::bit_cast(fmod_nid_postfix(std::bit_cast(item.x), std::bit_cast(item.y))) == item.expected); + Require(errno == (item.expectedErrno != 0 ? item.expectedErrno : 1234)); + } + constexpr struct { + std::uint32_t x; + std::uint32_t y; + std::uint32_t expected; + int expectedErrno; + } floatCases[] = { + {0x3f800000u, 0x00000000u, 0xffc00000u, EDOM}, + {0xbf800000u, 0x80000000u, 0xffc00000u, EDOM}, + {0x7f800000u, 0x40000000u, 0xffc00000u, EDOM}, + {0xff800000u, 0x7f800000u, 0xffc00000u, EDOM}, + {0x7fc00123u, 0x40000000u, 0x7fc00123u, EDOM}, + {0xffc00123u, 0x00000000u, 0xffc00123u, EDOM}, + {0x3f800000u, 0x7fc00456u, 0x7fc00456u, EDOM}, + {0x7fc00123u, 0xffc00456u, 0xffc00456u, EDOM}, + {0x7fa00000u, 0x40000000u, 0x7fe00000u, EDOM}, + {0x3f800000u, 0x7fa00000u, 0x7fe00000u, EDOM}, + {0x7f800000u, 0x7fc00456u, 0x7fc00456u, EDOM}, + {0x3f800000u, 0x7f800000u, 0x3f800000u, 0}, + {0x40b00000u, 0x40000000u, 0x3fc00000u, 0}, + {0x00000000u, 0x80000000u, 0xffc00000u, EDOM}, + {0x00000003u, 0x00000002u, 0x00000001u, 0}, + }; + for (const auto& item : floatCases) { + errno = 1234; + Require(std::bit_cast(fmodf_nid_postfix(std::bit_cast(item.x), std::bit_cast(item.y))) == item.expected); + Require(errno == (item.expectedErrno != 0 ? item.expectedErrno : 1234)); + } +} static void CheckHypotfConsoleBits() { constexpr struct { std::uint32_t x; @@ -3394,9 +3516,12 @@ int main() { CheckNextafterEnvironment(nextafterf_nid_postfix, 0x80000000u, 0x3f800000u, 0x00800000u, 0x7f7fffffu, 0x7f800000u); CheckNextafterEnvironment(nextafter_nid_postfix, std::uint64_t{0x8000000000000000ull}, std::uint64_t{0x3ff0000000000000ull}, std::uint64_t{0x0010000000000000ull}, std::uint64_t{0x7fefffffffffffffull}, std::uint64_t{0x7ff0000000000000ull}); CheckExpm1ScalingRounding(); + CheckFmodConsoleBits(); + CheckFmodEdgeFlags(); CheckHypotfConsoleBits(); CheckTrigConsoleBits(); CheckAtanhConsoleBits(); + CheckAtanhDomainEnvironment(); CheckAtanhEdgeFlags(); CheckHypotConsoleBits(); CheckPowConsoleBits(); diff --git a/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp b/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp index e9a056947e..4c9ce0e449 100644 --- a/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp +++ b/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp @@ -366,6 +366,53 @@ static void TestScalarVectorAssignment() { Require(deleterCalls == 0); } +static void TestVectorFunctionsAcceptTheHandleObject() { + int context = 0; + + IntrusivePtr vector; + _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V116RequestMatchTeamEEEEC1EPNS2_10LibContextE(&vector, &context); + unsigned char object[ObjectSize]; + std::memset(object, 0x5a, sizeof(object)); + WriteCount(object, 0, 1); + IntrusivePtr filled{object, RecordDelete, &context}; + Require(_ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V116RequestMatchTeamEEEE8pushBackERKS8_(&vector, &filled) == 0); + Require(_ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V116RequestMatchTeamEEEE4sizeEv(&vector) == 1); + Require(_ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V116RequestMatchTeamEEEE4sizeEv(vector.object) == 1); + _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_7Matches2V116RequestMatchTeamEEEED1Ev(&vector); + _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_7Matches2V116RequestMatchTeamEED1Ev(&filled); + + alignas(8) unsigned char body[0x50] = {}; + const std::uint64_t magic = 0x434e507056656342ULL; + std::memcpy(body, &magic, sizeof(magic)); + WriteCount(body, VectorReferenceCountOffset, 1); + *reinterpret_cast(body + 0x34) = 1; + IntrusivePtr elements[2] = {}; + *reinterpret_cast(body + 0x38) = elements; + *reinterpret_cast(body + 0x40) = 2; + *reinterpret_cast(body + 0x48) = 2; + IntrusivePtr handle{body, nullptr, &context}; + + const auto presenceBegin = reinterpret_cast(_ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE5beginEv); + const auto presenceEnd = reinterpret_cast(_ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE3endEv); + const auto presenceNext = reinterpret_cast(_ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEppEv); + const auto presenceNotEqual = reinterpret_cast(_ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEneERKS9_); + + unsigned char first[0x10] = {}, last[0x10] = {}; + Require(presenceBegin(first, body) == first); + Require(presenceEnd(last, body) == last); + Require(presenceNotEqual(first, last)); + Require(presenceNext(first) == first); + Require(presenceNotEqual(first, last)); + Require(presenceNext(first) == first); + Require(!presenceNotEqual(first, last)); + + Require(presenceBegin(first, &handle) == first); + Require(presenceEnd(last, &handle) == last); + Require(presenceNext(first) == first); + Require(presenceNext(first) == first); + Require(!presenceNotEqual(first, last)); +} + static void TestVectorAliasedGrowth() { unsigned cases = 0, moves = 0; for (unsigned sourceIndex = 0; sourceIndex < 4; ++sourceIndex) { @@ -433,7 +480,38 @@ static void TestUserProfileVectorAssign() { } static void TestUserProfileModelAndTransaction() { - Require(_ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileC1EPNS1_6Common10LibContextE() == 0); + std::uint8_t profile[0xd0]; + std::memset(profile, 0xa5, sizeof(profile)); + std::uint64_t context = 0; + Require(_ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileC1EPNS1_6Common10LibContextE(profile, &context) == 0); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile13onlineIdIsSetEv(profile) == false); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile19personalDetailIsSetEv(profile) == false); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile25isOfficiallyVerifiedIsSetEv(profile) == false); + const bool verified = true; + Require(_ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile23setIsOfficiallyVerifiedERKb(profile, &verified) == 0); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile25isOfficiallyVerifiedIsSetEv(profile)); + unsigned char onlineId[0x14]; + std::memset(onlineId, 0x61, sizeof(onlineId)); + Require(_ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfile11setOnlineIdERK13SceNpOnlineId(profile, onlineId) == 0); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V112BasicProfile13onlineIdIsSetEv(profile)); + Require(_ZN3sce2Np9CppWebApi11UserProfile2V112BasicProfileD1Ev(profile) == profile); + + std::uint8_t presence[0x28]; + std::memset(presence, 0xa5, sizeof(presence)); + Require(_ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceC1EPNS1_6Common10LibContextE(presence, &context) == 0); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence17onlineStatusIsSetEv(presence) == false); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence14inContextIsSetEv(presence) == false); + const std::uint64_t accountId = 0x1234; + Require(_ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setAccountIdERKm(presence, &accountId) == 0); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getAccountIdEv(presence) == 0x1234); + const bool inContext = true; + Require(_ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence12setInContextERKb(presence, &inContext) == 0); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence12getInContextEv(presence)); + const std::uint32_t status = 2; + Require(_ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresence15setOnlineStatusERKNS3_12OnlineStatusE(presence, &status) == 0); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence17onlineStatusIsSetEv(presence)); + Require(_ZNK3sce2Np9CppWebApi11UserProfile2V113BasicPresence15getOnlineStatusEv(presence) == 2); + Require(_ZN3sce2Np9CppWebApi11UserProfile2V113BasicPresenceD1Ev(presence) == presence); std::uint64_t transaction[0x20]; std::memset(transaction, 0xa5, sizeof(transaction)); @@ -613,6 +691,7 @@ int main(int argc, char** argv) { TestVectorPushBackReleasesElements(); TestAdoptedStringVectorCountsReferences(); TestScalarVectorAssignment(); + TestVectorFunctionsAcceptTheHandleObject(); TestUserProfileVectorAssign(); TestUserProfileModelAndTransaction(); TestUserProfilePublicProfileRequest(); diff --git a/core/libs/tests/GuestNpCppWebApiSignedOut.cpp b/core/libs/tests/GuestNpCppWebApiSignedOut.cpp index 5d7ea3cf4f..6fac1aec91 100644 --- a/core/libs/tests/GuestNpCppWebApiSignedOut.cpp +++ b/core/libs/tests/GuestNpCppWebApiSignedOut.cpp @@ -144,11 +144,13 @@ static const RequestFlow flows[] = { using Lifecycle = void (APS5_VABI*)(void*); using Finish = int (APS5_VABI*)(void*); using Identifier = std::int64_t (APS5_VABI*)(); +using Response = int (APS5_VABI*)(const void*, void*); struct TransactionLifecycle { Lifecycle construct; Lifecycle destroy; Finish finish; + Response getResponse; }; static const TransactionLifecycle lifecycles[] = { @@ -156,11 +158,13 @@ static const TransactionLifecycle lifecycles[] = { _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev, _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev, _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv, + _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERSB_, }, { _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev, _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev, _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv, + _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_, }, }; @@ -171,6 +175,10 @@ static const Call aborts[] = { _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv, _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv, _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv, + _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv, + _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv, + _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv, + _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv, }; static const Identifier identifiers[] = { @@ -179,6 +187,10 @@ static const Identifier identifiers[] = { _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv, _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv, _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv, + _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv, + _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv, + _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv, + _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetPublicProfilesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv, }; static void TestNeverStartedTransactions() { @@ -189,6 +201,12 @@ static void TestNeverStartedTransactions() { for (std::size_t index = 0; index < sizeof(transaction); ++index) Require(transaction[index] == (index < 0x10 ? 0 : 0x5a)); Require(lifecycle.finish(transaction) == TransactionNotStarted); + alignas(16) unsigned char response[0x18]; + std::memset(response, 0x5a, sizeof(response)); + Require(lifecycle.getResponse(transaction, response) == TransactionNotStarted); + for (const unsigned char byte : response) Require(byte == 0x5a); + for (std::size_t index = 0; index < sizeof(transaction); ++index) + Require(transaction[index] == (index < 0x10 ? 0 : 0x5a)); lifecycle.destroy(transaction); for (std::size_t index = 0; index < sizeof(transaction); ++index) Require(transaction[index] == (index < 0x10 ? 0 : 0x5a)); diff --git a/core/libs/tests/GuestTcp.cpp b/core/libs/tests/GuestTcp.cpp index 2538d521a1..ba32a68be0 100644 --- a/core/libs/tests/GuestTcp.cpp +++ b/core/libs/tests/GuestTcp.cpp @@ -3,6 +3,7 @@ #include "prx/libc/include/general/VabiMacros.hpp" #include #include +#include #include #include #include @@ -275,6 +276,59 @@ static void SocketNameFaults() { for (const int descriptor : {unconnected, accepted, client, listener}) Require(close_nid_postfix(descriptor) == 0); } +static void BlockedReceiveEndsAtShutRead() { + enum Call { Receive, ReceiveFrom, ReceiveMessage, Read, ThroughDuplicate, WithTimeout, Calls }; + for (int call = Receive; call < Calls; ++call) { + const int listener = socket_nid_postfix(2, 1, 0); + Require(listener >= 0); + std::array address{16, 2, 0, 0, 127, 0, 0, 1}; + Require(bind_nid_postfix(listener, address.data(), address.size()) == 0 && listen_nid_postfix(listener, 4) == 0); + std::uint32_t size = address.size(); + Require(getsockname_nid_postfix(listener, address.data(), &size) == 0); + const int client = socket_nid_postfix(2, 1, 0); + Require(client >= 0 && connect_nid_postfix(client, address.data(), address.size()) == 0); + const int accepted = accept_nid_postfix(listener, nullptr, nullptr); + Require(accepted >= 0); + const int watched = call == ThroughDuplicate ? dup_nid_postfix(accepted) : accepted; + Require(watched >= 0); + if (call == WithTimeout) { + const KernelTimeval timeout{3, 0}; + Require(setsockopt_nid_postfix(accepted, 0xffff, 0x1006, &timeout, sizeof(timeout)) == 0); + } + char buffer[8]; + std::array sender{}; + std::uint32_t senderSize = sender.size(); + KernelIovec vector{buffer, sizeof(buffer)}; + GuestMsghdr message{sender.data(), static_cast(sender.size()), &vector, 1, nullptr, 0, -1}; + std::atomic entered{false}; + std::atomic returned{false}; + std::int64_t received = -2; + std::chrono::steady_clock::duration waited{}; + std::thread receiver([&] { + const auto start = std::chrono::steady_clock::now(); + entered = true; + if (call == ReceiveFrom) received = recvfrom_nid_postfix(watched, buffer, sizeof(buffer), 0, sender.data(), &senderSize); + else if (call == ReceiveMessage) received = recvmsg_nid_postfix(watched, &message, 0); + else if (call == Read) received = read_nid_postfix(watched, buffer, sizeof(buffer)); + else received = recv_nid_postfix(watched, buffer, sizeof(buffer), 0); + waited = std::chrono::steady_clock::now() - start; + returned = true; + }); + while (!entered) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + Require(!returned); + Require(shutdown_nid_postfix(accepted, 0) == 0); + for (int poll = 0; poll < 100 && !returned; ++poll) std::this_thread::sleep_for(std::chrono::milliseconds(20)); + if (!returned) Require(shutdown_nid_postfix(client, 2) == 0); + receiver.join(); + Require(received == 0 && waited >= std::chrono::milliseconds(40) && waited < std::chrono::seconds(2)); + if (call == ReceiveFrom) Require(senderSize == 0); + if (call == ReceiveMessage) Require(message.nameLength == 0 && message.flags == 0); + if (call == ThroughDuplicate) Require(close_nid_postfix(watched) == 0); + for (const int descriptor : {client, accepted, listener}) Require(close_nid_postfix(descriptor) == 0); + } +} + int main() { StreamReceiveReportsNoSender(); SocketNameFaults(); @@ -282,6 +336,7 @@ int main() { AcceptedSocketsFollowListenerBlocking(); WaitAllReceivesTheWholeRequest(); ReceiveAnsweredWithoutTheHost(); + BlockedReceiveEndsAtShutRead(); UnboundSocketNameIsZero(); const int listener = socket_nid_postfix(2, 1, 6); Require(listener >= 0); diff --git a/core/libs/tests/GuestUdp.cpp b/core/libs/tests/GuestUdp.cpp index e177213445..99b6c7a997 100644 --- a/core/libs/tests/GuestUdp.cpp +++ b/core/libs/tests/GuestUdp.cpp @@ -4,6 +4,7 @@ #include "prx/libc/include/general/VabiMacros.hpp" #include #include +#include #include #include #include @@ -221,6 +222,49 @@ static void CheckShutReadUnconnected() { Require(close_nid_postfix(receiver) == 0 && close_nid_postfix(sender) == 0); } +#ifndef __APPLE__ +static void CheckShutReadEndsBlockedReceive() { + for (const bool stamped : {false, true}) { + const int receiver = socket_nid_postfix(2, 2, 0); + const int sender = socket_nid_postfix(2, 2, 0); + Require(receiver >= 0 && sender >= 0); + std::array address{16, 2, 0, 0, 127, 0, 0, 1}; + Require(bind_nid_postfix(receiver, address.data(), address.size()) == 0); + std::uint32_t size = address.size(); + Require(getsockname_nid_postfix(receiver, address.data(), &size) == 0); + const int enabled = 1; + if (stamped) Require(setsockopt_nid_postfix(receiver, 0xffff, 0x400, &enabled, sizeof(enabled)) == 0); + std::atomic entered{false}; + std::atomic returned{false}; + std::int64_t received = -2; + std::array control{}; + std::uint32_t controlLength = 0; + std::chrono::steady_clock::duration waited{}; + std::thread waiter([&] { + char buffer[4]; + KernelIovec vector{buffer, sizeof(buffer)}; + GuestMsghdr message{nullptr, 0, &vector, 1, control.data(), static_cast(control.size()), -1}; + const auto start = std::chrono::steady_clock::now(); + entered = true; + received = stamped ? recvmsg_nid_postfix(receiver, &message, 0) : recv_nid_postfix(receiver, buffer, sizeof(buffer), 0); + waited = std::chrono::steady_clock::now() - start; + controlLength = message.controlLength; + returned = true; + }); + while (!entered) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + Require(!returned); + Require(shutdown_nid_postfix(receiver, 0) == -1 && *__error_nid_postfix() == 57); + for (int poll = 0; poll < 100 && !returned; ++poll) std::this_thread::sleep_for(std::chrono::milliseconds(20)); + if (!returned) Require(sendto_nid_postfix(sender, "x", 1, 0, address.data(), address.size()) == 1); + waiter.join(); + Require(received == 0 && waited >= std::chrono::milliseconds(40) && waited < std::chrono::seconds(2)); + if (stamped) Require(controlLength == 0); + Require(close_nid_postfix(receiver) == 0 && close_nid_postfix(sender) == 0); + } +} +#endif + static void CheckDontWait() { const int receiver = socket_nid_postfix(2, 2, 0); const int sender = socket_nid_postfix(2, 2, 0); @@ -501,6 +545,9 @@ int main() { CheckDontWait(); CheckSendToPortZero(); CheckShutReadUnconnected(); +#ifndef __APPLE__ + CheckShutReadEndsBlockedReceive(); +#endif const int receiver = socket_nid_postfix(2, 2, 0); const int sender = socket_nid_postfix(2, 2, 17); Require(receiver >= 0 && sender >= 0 && receiver != sender); diff --git a/core/libs/tests/GuestVideoOutFirmwareAnswers.cpp b/core/libs/tests/GuestVideoOutFirmwareAnswers.cpp new file mode 100644 index 0000000000..c463fc5d09 --- /dev/null +++ b/core/libs/tests/GuestVideoOutFirmwareAnswers.cpp @@ -0,0 +1,34 @@ +#include "prx/libSceVideoOut/include/InventoryExports.hpp" +#include +#include +#include +#include +#include + +static void Require(bool value, const char* message) { + if (!value) { + std::fprintf(stderr, "%s\n", message); + std::abort(); + } +} + +static int ModeIsVr(std::uint32_t flags, std::uint8_t fill) { + std::array mode; + mode.fill(fill); + std::memcpy(mode.data() + 0x20, &flags, sizeof(flags)); + return sceVideoOutSysModeIsVr(mode.data()); +} + +int main() { + Require(sceVideoOutAddBufferHdrPrivilege() == 0, "sceVideoOutAddBufferHdrPrivilege did not return 0"); + Require(sceVideoOutRazorRecallCallbacks() == 0, "sceVideoOutRazorRecallCallbacks did not return 0"); + Require(sceVideoOutSysUpdateRenderingMode() == 0, "sceVideoOutSysUpdateRenderingMode did not return 0"); + Require(sceVideoOutCurveSamplePointsCalc_() == static_cast(0x8029001Cu), "sceVideoOutCurveSamplePointsCalc_ did not return 0x8029001C"); + Require(sceVideoOutDriverGetLatestEopHandle() == static_cast(0x802900FFu), "sceVideoOutDriverGetLatestEopHandle did not return 0x802900FF"); + Require(sceVideoOutSysGetMonitorInfo_() == -1, "sceVideoOutSysGetMonitorInfo_ did not return -1"); + Require(ModeIsVr(0x2u, 0) == 1, "bit 1 of the dword at 0x20 did not report VR"); + Require(ModeIsVr(0xFFFFFFFFu, 0xFF) == 1, "a mode with every bit set did not report VR"); + Require(ModeIsVr(0xFFFFFFFDu, 0xFF) == 0, "the other bits of the dword at 0x20 reported VR"); + Require(ModeIsVr(0u, 0xFF) == 0, "bytes outside the dword at 0x20 reported VR"); + return 0; +} diff --git a/docs/dev/debt/libSceAppContent.md b/docs/dev/debt/libSceAppContent.md index faac56021c..5c413cad89 100644 --- a/docs/dev/debt/libSceAppContent.md +++ b/docs/dev/debt/libSceAppContent.md @@ -8,15 +8,15 @@ | --- | --- | | `sceAppContentDownloadDataGetBlockSize` | `9ht66cHTj7g` | -- [sceAppContentDownloadDataGetAvailableSpaceKb](../../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) - a title whose `param.json` declares `downloadDataSize` 0 gets 0 KB and OK; the console's behaviour for a title without a download data area is unverified (it may return an error instead). KytyPS5 does not special-case it, and shadPS4 stubs 1048576 KB. One disassembled title (PPSA15246) calls it with the `/download0` mount point and a zeroed 64-bit output, ignores the return value and multiplies the output by 1024, so for that title an error that leaves the output untouched and an OK with 0 KB look the same. `/download1` queries remain unimplemented because their quota model is unverified; `/download2` reflects the expanded quota. +- [sceAppContentDownloadDataGetAvailableSpaceKb](../../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) - a title whose `param.json` declares `downloadDataSize` 0 gets 0 KB and OK; the console's behaviour for a title without a download data area is unverified (it may return an error instead). shadPS4 stubs 1048576 KB. One disassembled title (PPSA15246) calls it with the `/download0` mount point and a zeroed 64-bit output, ignores the return value and multiplies the output by 1024, so for that title an error that leaves the output untouched and an OK with 0 KB look the same. `/download1` and `/download2` queries reflect their configured quota. - [sceAppContentDownloadDataFormat](../../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) - empties the `/download0`, `/download1`, or `/download2` directory, creating it if needed. Imported by PPSA01317. A null mount point returns `PARAMETER` and another mount point returns `NOT_MOUNTED` as in `sceAppContentTemporaryDataFormat` and `sceAppContentDownloadDataGetAvailableSpaceKb`; the console's error codes for both and its behaviour with files still open are unverified -- [sceAppContentDownload0Expand, sceAppContentDownload0Shrink, sceAppContentDownload1Expand, sceAppContentDownload1Shrink and sceAppContentDownload2Shrink](../../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) - partition expansion and shrink behaviour on hardware is unverified. `sceAppContentDownload2Expand` expands `/download2` and updates its reported quota; the other partition expansion and shrink functions throw through `NotImplemented_nid_no_patch`. +- [sceAppContentDownload0Expand, sceAppContentDownload0Shrink, sceAppContentDownload1Shrink and sceAppContentDownload2Shrink](../../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) - partition expansion and shrink behaviour on hardware is unverified. `sceAppContentDownload1Expand` and `sceAppContentDownload2Expand` expand `/download1` and `/download2` and update their reported quotas; the other partition expansion and shrink functions throw through `NotImplemented_nid_no_patch`. - [sceAppContentUnknown_SWVxsi_ZBlw](../../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent, NID SWVxsi-ZBlw) - master data identifier query (UnknownMdid in [dlc_emu](https://github.com/drakmor/dlc_emu/blob/fcf69b16d46a9850578bce19dc2c1b4dc867cbb5/src/dlc_modules/dlc_content.cpp#L2258-L2262)). Reconstructed signature and return values on hardware are unverified; all calls throw through `NotImplemented_nid_no_patch`. - [libSceAppContent pending exports](../../../core/libs/prx/libSceAppContent/Export.cpp) - 8 named callable exports are listed in the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceAppContent.c) and were cross-checked against the same module in PS5 firmware 13.60. Their signatures and behaviour are unverified; the declarations use the no-parameter unknown-signature convention and throw through `NotImplemented_nid_no_patch`. ### Functional -- [Download partition expansion](../../../core/libs/prx/libSceAppContent/Export.cpp) - `/download2` expansion tracks size monotonically and reports available space in `sceAppContentDownloadDataGetAvailableSpaceKb`. The quota units and hardware shrink behavior remain unverified. +- [Download partition expansion](../../../core/libs/prx/libSceAppContent/Export.cpp) - `/download1` and `/download2` expansion tracks size monotonically and reports available space in `sceAppContentDownloadDataGetAvailableSpaceKb`. The quota units and hardware shrink behavior remain unverified. - [Download-data quota conversion](../../../core/libs/prx/libSceAppContent/Export.cpp) - console handling of `downloadDataSize` values too large to represent in 64-bit KiB is unverified. The host model throws `std::overflow_error` before writing the output or creating storage; no console error code is assigned. diff --git a/docs/dev/debt/libSceContentSearch.md b/docs/dev/debt/libSceContentSearch.md index 8051fd4b39..627bdcd5d1 100644 --- a/docs/dev/debt/libSceContentSearch.md +++ b/docs/dev/debt/libSceContentSearch.md @@ -11,11 +11,12 @@ | `sceContentSearchEnableAvContentCreatedEvent` | `vlOqhFPOLDs` | | `sceContentSearchGetContentIdByAvContentCreatedEvent` | `2Dj56xvkS5M` | -- [sceContentBinderEnd, sceContentBinderGetNumOfDifference, sceContentBinderInitialize, sceContentBinderIsUpdated, sceContentBinderReset, sceContentBinderSearchDifference, sceContentBinderStart, sceContentBinderTerminate, sceContentSearchGetApplicationLastUpdateId, sceContentSearchGetMyApplicationIndex, sceContentSearchGetNumOfApplication and sceContentSearchSearchApplication](../../../core/libs/prx/libSceContentSearch/Export.cpp) (libSceContentSearch) - names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceContentSearch.c), but no credible prototypes were found in the cited sources. They are declared without parameters solely to resolve known imports and make no ABI claim. +- [sceContentBinderEnd, sceContentBinderGetNumOfDifference, sceContentBinderInitialize, sceContentBinderIsUpdated, sceContentBinderReset, sceContentBinderSearchDifference, sceContentBinderStart, sceContentBinderTerminate and sceContentSearchSearchApplication](../../../core/libs/prx/libSceContentSearch/Export.cpp) (libSceContentSearch) - names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceContentSearch.c), but no credible prototypes were found in the cited sources. They are declared without parameters solely to resolve known imports and make no ABI claim. ### Functional - [Content queries](../../../core/libs/prx/libSceContentSearch/Export.cpp) use an empty host library and always report update id 0; the console's initial update id is unverified. No content rows are produced. Every title is assumed to have search permission. Nested filter/sort validation is incomplete: empty nested column sets, null filter values and unknown enum values throw. Guest heap allocation and the platform-dependent minimum heap size are unimplemented. Initialization and outer pointer/count/limit validation follow the supplied module. +- [sceContentSearchGetNumOfApplication, sceContentSearchGetApplicationLastUpdateId and sceContentSearchGetMyApplicationIndex](../../../core/libs/prx/libSceContentSearch/Export.cpp) (libSceContentSearch) - signatures from the 11.00 module wrappers at `0x18e70`, `0x18f70` and `0x191a0` in `libSceContentSearch.sprx` (SHA-256 `af44252b7b9a0c2d83d01197a4d38119375fb14b82c7e2a822187a49432b42e4`): `GetNumOfApplication` takes the column-set and order-by pairs plus the count and update-id outputs; `GetApplicationLastUpdateId` writes a 64-bit update id. The host reports zero applications and update id 0 because the host library has no application records; the console values are unverified. `GetMyApplicationIndex` writes a 32-bit index, defaults it to 0 before delegating, and returns the delegate's result, which is not established when the title is absent from the library, so the host writes 0 and then throws through `NotImplemented_nid_no_patch`. All three check initialization and null outputs first, and `GetNumOfApplication` validates the column-set and order-by contents as the content queries do. `sceContentSearchSearchApplication` still throws because its eleven-argument contract is not mapped. - [Metadata access](../../../core/libs/prx/libSceContentSearch/Export.cpp) cannot open metadata by path or content id because missing-content errors remain unresolved: past their argument checks, both opening calls go through `NotImplemented_nid_no_patch`. No metadata handles are issued. The field-info and value queries reject invalid outer pointers, then go through `NotImplemented_nid_no_patch`, as no metadata id is ever opened and the console's error for one depends on the requested field; closing an unopened handle returns the confirmed invalid-argument error. ### Additional callable exports diff --git a/docs/dev/debt/libSceJxr.md b/docs/dev/debt/libSceJxr.md index f69c19b96f..17d97669a4 100644 --- a/docs/dev/debt/libSceJxr.md +++ b/docs/dev/debt/libSceJxr.md @@ -16,6 +16,10 @@ - [readIS and writeIS](../../../core/libs/prx/libSceJxr/Export.cpp) use the non-ARM, LP64 `BitIOInfo` and `WMPStream` ABI and packet algorithm from [Microsoft's JPEG XR reference implementation](https://github.com/4creators/jxrlib/blob/f7521879862b9085318e814c6157490dd9dbbdb4/image/sys/strcodec.c#L1090-L1177). Console structure layouts and execution remain unverified. Profiling callbacks are omitted as in the reference Unix build with `DISABLE_PERF_MEASUREMENT`; the codec argument is unused. Where the reference uses an invalid pointer, `std::invalid_argument` is thrown instead: a null bit state, stream or callback, a read-only read packet, and a null packet when a read copies its shadow or a successful write offsets it; a null packet still reaches the callback first. No codec is instantiated by these helpers; callers must supply the reference ring buffer and guest-ABI stream callbacks. +- [GetPixelFormatFromHash, GetImageEncodeIID and GetImageDecodeIID](../../../core/libs/prx/libSceJxr/src/GlueHelpers.cpp) call jxrlib's [JXRGlue.c](https://github.com/4creators/jxrlib/blob/f7521879862b9085318e814c6157490dd9dbbdb4/jxrgluelib/JXRGlue.c#L256-L329), built from `3rdparty/jxrlib`, through a C bridge. That the console's module is jxrlib with these prototypes is inferred from the export names. The hash lookup, like `PixelFormatLookup`, borrows the bridge's read-only GUID. IID values map to the module's exported IID objects; `.wdp` and `.hdp` encoding return a private `IID_PKImageUnsupported` (100), which the module does not export. A null extension, or a null output for a known extension, throws where jxrlib dereferences it. Closes when: the console's functions are disassembled or measured on a PS5 + +- [PKAllocAligned, PKFreeAligned and IDPEmpty](../../../core/libs/prx/libSceJxr/src/GlueHelpers.cpp) call jxrlib's [JXRGlue.c](https://github.com/4creators/jxrlib/blob/f7521879862b9085318e814c6157490dd9dbbdb4/jxrgluelib/JXRGlue.c#L64-L102) and [strcodec.c](https://github.com/4creators/jxrlib/blob/f7521879862b9085318e814c6157490dd9dbbdb4/image/sys/strcodec.c#L239-L244), with that `JXRGlue.c` copy's `calloc` and `free` routed to the guest heap; that the console allocates there is inferred. A null output, an alignment below 8 and a block size over `SIZE_MAX` throw before jxrlib can fault, write before the block or wrap. Closes when: the console's functions are disassembled or measured on a PS5 + - [remapQP, formatQuantizer, getACPredMode and InitZigzagScan](../../../core/libs/prx/libSceJxr/src/Quantizer.cpp) call jxrlib's [strPredQuant.c](https://github.com/4creators/jxrlib/blob/f7521879862b9085318e814c6157490dd9dbbdb4/image/sys/strPredQuant.c#L79-L192), [strcodec.c](https://github.com/4creators/jxrlib/blob/f7521879862b9085318e814c6157490dd9dbbdb4/image/sys/strcodec.c#L861-L874) and [image.c](https://github.com/4creators/jxrlib/blob/f7521879862b9085318e814c6157490dd9dbbdb4/image/sys/image.c#L173-L183), built from `3rdparty/jxrlib`, on the caller's 20-byte quantizer, 1,160-byte macroblock and 704-byte coding context without `WMP_OPT_QT`. These prototypes and layouts are inferred from the export names. A null quantizer, quantizer table, used channel or macroblock, more than 16 channels, and a scaled shift that takes the QP outside 32 bits throw. Closes when: the console's functions are disassembled or measured on a PS5 -- The 119 additional exports in [Export.cpp](../../../core/libs/prx/libSceJxr/Export.cpp) are present in the pinned firmware 13.60 `libSceJxr` export inventory. Their parameter lists, return types and behavior are unverified. Parameterless `int` declarations are import-resolution placeholders, not verified ABI prototypes; every entry throws through `NotImplemented_nid_no_patch`. The `_nid_postfix` aliases keep the guest bindings distinct from private native helpers. No runtime functionality is implemented. +- The 113 additional exports in [Export.cpp](../../../core/libs/prx/libSceJxr/Export.cpp) are present in the pinned firmware 13.60 `libSceJxr` export inventory. Their parameter lists, return types and behavior are unverified. Parameterless `int` declarations are import-resolution placeholders, not verified ABI prototypes; every entry throws through `NotImplemented_nid_no_patch`. The `_nid_postfix` aliases keep the guest bindings distinct from private native helpers. No runtime functionality is implemented. diff --git a/docs/dev/debt/libSceLibcInternal.md b/docs/dev/debt/libSceLibcInternal.md index 8103b9faca..4bc9d97108 100644 --- a/docs/dev/debt/libSceLibcInternal.md +++ b/docs/dev/debt/libSceLibcInternal.md @@ -541,20 +541,21 @@ The named entries below use provider-specific NID aliases to avoid interposing h - [3.20 pending imports](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - The following PS5 3.20 inventory names are declared for import resolution only; their prototypes and behavior are unverified, and each call throws through `NotImplemented_nid_no_patch`. The source list is [PS5-3.20_Libs](https://github.com/DNNDHH/PS5-3.20_Libs). - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Atan`, `_Atqexit`, `_Atthreadexit`, `_CStrftime`, `_CStrxfrm`, `_CWcsxfrm`, `_Call_onceEx`, `_Closreg` -- [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Daysto`, `_Deletegloballocale`, `_Do_call`, `_Dtento`, `_Erfc`, `_FAtan` +- [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Deletegloballocale`, `_Do_call`, `_Dtento`, `_Erfc`, `_FAtan` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_FDtento`, `_FErfc`, `_FHypot`, `_FLogpoly`, `_FPlsw`, `_FPmsw`, `_FPow`, `_FQuad` -- [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_FQuadph`, `_FRint`, `_FSincos`, `_FTan`, `_FTgamma`, `_FXp_addh`, `_FXp_addx`, `_FXp_getw`, `_FXp_invx` +- [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_FQuadph`, `_FRint`, `_FSincos`, `_FTan`, `_FTgamma`, `_FXp_addh`, `_FXp_addx`, `_FXp_invx` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_FXp_ldexpx`, `_FXp_movx`, `_FXp_mulh`, `_FXp_mulx`, `_FXp_setn`, `_FXp_setw`, `_FXp_sqrtx`, `_FXp_subx`, `_Fac_tidy`, `_Fail_s` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Fgpos`, `_Fofind`, `_Fofree`, `_Fopen`, `_Foprep`, `_Frprep`, `_Fspos` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Fwprep`, `_Genld`, `_Gentime`, `_Getcloc`, `_Getctyptab`, `_Getdst`, `_Geterrno`, `_Getfld`, `_Getfloat`, `_Getgloballocale` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Getint`, `_Getpcostate`, `_Getpwcostate`, `_Getpwctrtab`, `_Getpwctytab`, `_Getstr`, `_Gettime`, `_Getzone`, `_Hypot` -- [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Isdst`, `_LAtan`, `_LDtento`, `_LErfc`, `_LHypot`, `_LLogpoly` +- [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_LAtan`, `_LDtento`, `_LErfc`, `_LHypot`, `_LLogpoly` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_LPlsw`, `_LPmsw`, `_LPow`, `_LQuad`, `_LQuadph`, `_LRint`, `_LSincos`, `_LTan` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_LTgamma`, `_LXp_addh`, `_LXp_addx`, `_LXp_getw`, `_LXp_invx`, `_LXp_ldexpx`, `_LXp_movx`, `_LXp_mulh`, `_LXp_mulx`, `_LXp_setn` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_LXp_setw`, `_LXp_sqrtx`, `_LXp_subx`, `_Ldtob`, `_Litob`, `_Lock_spin_lock`, `_Locsum`, `_Locterm`, `_Locvar`, `_Logpoly` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Makeloc`, `_Makestab`, `_Makewct`, `_Mbtowc`, `_Nnl` - [Additional imported names](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - `_Plsw`, `_Pmsw`, `_Pow`, `_Printf`, `_Putfld`, `_Putstr`, `_Puttxt`, `_Quad`, `_Quadph`, `_Readloc` +- [`_Daysto`, `_FXp_getw` and `_Isdst`](../../../core/libs/prx/libSceLibcInternal/Export.cpp) (libSceLibcInternal) - follow firmware 13.42's libSceLibcInternal: read to the return, disassembly only, not measured on a console. `_Isdst` returns -1 without reading its argument. `_Daysto(year, month)` adds the leap days before `year` to the module's twelve-entry common or leap month table, as Dinkumware's `_Daysto` does; the module indexes the table with any month, and a month outside 0 to 11 throws here instead of reading past it. `_FXp_getw` follows Dinkumware's `_Xp_getw` for `float` parts, branch for branch. ### Additional PS5 3.20 imports (round 6) diff --git a/docs/dev/debt/libSceLibreSsl.md b/docs/dev/debt/libSceLibreSsl.md index dc464346ef..a80278fd16 100644 --- a/docs/dev/debt/libSceLibreSsl.md +++ b/docs/dev/debt/libSceLibreSsl.md @@ -49,6 +49,7 @@ - [EVP_aes_128_gcm, EVP_aes_192_gcm, EVP_aes_256_gcm](../../../core/libs/prx/libSceLibreSsl/src/EvpAes.cpp) (libSceLibreSsl) - nothing is checked on the console. The descriptors hold the values of [LibreSSL 2.5.4's e_aes.c](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/evp/e_aes.c) (NID, 12-byte IV, flags, the 680-byte LP64 `ctx_size`) with host `init`, `do_cipher`, `cleanup` and `ctrl`, and the cipher data has the port's own layout, so a title reading it sees different bytes. `aes_gcm_ctrl`, the TLS record path and [gcm128.c](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/modes/gcm128.c) are followed; `EVP_CTRL_GCM_SET_IV_FIXED` fills the IV from host entropy. A key length the AES setup rejects throws where LibreSSL keeps a stale schedule, as do missing cipher data, null buffers, `EVP_CTRL_GCM_IV_GEN` with an IV under 8 bytes and an invocation field longer than the IV - [EVP_cleanup](../../../core/libs/prx/libSceLibreSsl/src/EvpCipherCtx.cpp) (libSceLibreSsl) - nothing is checked on the console. [LibreSSL 2.5.4's names.c](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/evp/names.c) empties the cipher and digest name tables, the PBE table, a deferred `OBJ_cleanup` and the signature-ID tables. Nothing in this module can fill them yet, because `OPENSSL_add_all_algorithms_noconf`, `CONF_modules_load_file` and `OPENSSL_load_builtin_modules` are not implemented, `SSL_library_init` returns 1 without adding a cipher or digest, `PKCS12_PBE_add` is empty as in LibreSSL 2.5.4, and no cipher or digest can be registered under an `OBJ_create` NID to defer `OBJ_cleanup`, so `EVP_cleanup` returns without doing anything; it must clear those tables once one of them fills them. The static cipher descriptors stay valid afterwards, as in LibreSSL - [OCSP_response_status, OCSP_single_get0_status](../../../core/libs/prx/libSceLibreSsl/src/OcspResponse.cpp) (libSceLibreSsl) - nothing is checked on the console. Layouts and results follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto) `ocsp.h`, `ocsp_cl.c` and `a_enum.c`, the version in the [firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). No export of this module decodes a response yet, so only structures the caller builds reach them. Enumerated values follow `ASN1_ENUMERATED_get` (0 for a null value or null data, -1 for another type or more than 8 bytes), truncated to `int`. A null response, a null certificate status, and a null revocation record when its time or reason is requested, which LibreSSL dereferences, throw +- [SSL_get_session, SSL_get_current_cipher, SSL_get_certificate, SSL_get_privatekey](../../../core/libs/prx/libSceLibreSsl/src/SslSession.cpp) (libSceLibreSsl) - nothing is checked on the console. Layouts and results follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libssl) `ssl.h`, `ssl_locl.h`, `ssl_lib.c` and `ssl_sess.c`, the version in the [firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). No export of this module creates a connection yet, so only connections the caller builds reach them. A null connection, and a certificate set without a current key, which LibreSSL dereferences, throw - [OCSP_resp_count and OCSP_resp_get0](../../../core/libs/prx/libSceLibreSsl/src/OcspBasicResponse.cpp) - not verified on the console. The signatures, the guest `OCSP_BASICRESP`, `OCSP_RESPDATA` and stack layouts and the results follow LibreSSL 2.5.4's [ocsp.h and ocsp_cl.c](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/ocsp) and [stack.h and stack.c](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/stack), the version in [published firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). Console modifications and other firmware layouts remain unverified. A null response data pointer, and a null entry array with an index in range, throw where that release dereferences them. - [SSL_CTX_set_info_callback, SSL_CTX_sess_set_new_cb, SSL_CTX_set_cert_verify_callback, SSL_CTX_set_client_cert_cb, SSL_CTX_set_next_proto_select_cb, SSL_CTX_set_alpn_select_cb](../../../core/libs/prx/libSceLibreSsl/src/SslCtxCallbacks.cpp) (libSceLibreSsl) - nothing is checked on the console. Layouts and results follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libssl) `ssl.h`, `ssl_locl.h`, `ssl_lib.c` and `ssl_sess.c`, the version in the [firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). The callbacks and their arguments are only stored in `ssl_ctx_internal_st`; no export of this module creates a context or calls them yet, so only contexts the caller builds reach them. A null context or internal state, which LibreSSL dereferences, throws diff --git a/docs/dev/debt/libSceLibreSsl3.md b/docs/dev/debt/libSceLibreSsl3.md index 316d4b8272..c79e4a8e37 100644 --- a/docs/dev/debt/libSceLibreSsl3.md +++ b/docs/dev/debt/libSceLibreSsl3.md @@ -10,7 +10,7 @@ ### Unknown function info -- [libSceLibreSsl3 pending exports](../../../core/libs/prx/libSceLibreSsl3/Export.cpp) - 67 named callable exports, excluding `CRYPTO_memcmp`, `MD5`, `SHA1`, `d2i_ASN1_INTEGER`, `EVP_PKEY_up_ref`, `EC_KEY_up_ref`, `RSA_up_ref`, `EVP_PKEY_get0_RSA`, `EVP_PKEY_get0_DSA`, `EVP_PKEY_get0_DH`, `EVP_MD_CTX_new`, `EVP_MD_CTX_free`, `EVP_DigestInit`, `EVP_sha1`, `EVP_sha224`, `ERR_load_crypto_strings`, `ERR_peek_last_error`, `OpenSSL_version`, `X509_PUBKEY_get0_param` and `OBJ_cmp`, remain unimplemented from the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibreSsl3.c), cross-checked against the same module in PS5 firmware 13.60. Their signatures and behaviour are unverified; the declarations use the no-parameter unknown-signature convention and throw through `NotImplemented_nid_no_patch`. +- [libSceLibreSsl3 pending exports](../../../core/libs/prx/libSceLibreSsl3/Export.cpp) - 62 named callable exports, excluding `CRYPTO_memcmp`, `MD5`, `SHA1`, `d2i_ASN1_INTEGER`, `EVP_PKEY_up_ref`, `EC_KEY_up_ref`, `RSA_up_ref`, `EVP_PKEY_get0_RSA`, `EVP_PKEY_get0_DSA`, `EVP_PKEY_get0_DH`, `EVP_MD_CTX_new`, `EVP_MD_CTX_free`, `EVP_DigestInit`, `EVP_sha1`, `EVP_sha224`, `ERR_load_crypto_strings`, `ERR_peek_last_error`, `OpenSSL_version`, `X509_PUBKEY_get0_param`, `OBJ_cmp`, `ASN1_STRING_get0_data`, `ASN1_INTEGER_free`, `X509_get0_extensions`, `X509_get_ext_count` and `X509_get_ext`, remain unimplemented from the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibreSsl3.c), cross-checked against the same module in PS5 firmware 13.60. Their signatures and behaviour are unverified; the declarations use the no-parameter unknown-signature convention and throw through `NotImplemented_nid_no_patch`. ### Functional @@ -29,6 +29,8 @@ - [EVP_CIPHER_key_length and EVP_CIPHER_iv_length](../../../core/libs/prx/libSceLibreSsl3/src/Cipher.cpp) (libSceLibreSsl3) - nothing is checked on the console. They return `key_len` and `iv_len` from the 80-byte `EVP_CIPHER` of [LibreSSL 4.0.0](https://github.com/libressl/openbsd/tree/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/evp) `evp_local.h` and `evp_cipher.c`. The fields are at offsets 8 and 12, as in the [2.5.4 layout](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/evp/evp.h) of the ciphers the forwarded libSceLibreSsl exports handle. A null cipher, which LibreSSL dereferences, throws. Closes when: compared with the console. - [X509_VERIFY_PARAM_set_flags](../../../core/libs/prx/libSceLibreSsl3/src/X509VerifyParam.cpp) (libSceLibreSsl3) - nothing is checked on the console. It ORs the flags into `flags` and returns 1, as both [LibreSSL 2.5.4](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509/x509_vpm.c) and [4.0.0](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/x509/x509_vpm.c) `x509_vpm.c` do. They differ when `EXPLICIT_POLICY`, `INHIBIT_ANY` or `INHIBIT_MAP` is set while `POLICY_CHECK` is neither set nor requested: 2.5.4 also adds `POLICY_CHECK` and 4.0.0 does not. The console's choice is unknown, so that case throws through `NotImplemented_nid_no_patch` and leaves the parameters unchanged. It writes libSceLibreSsl's 2.5.4 `LibreSslX509VerifyParam`, whose `flags` is at offset 24 as in 4.0.0. Null parameters throw. Closes when: the console's policy behaviour is measured. - [sk_new, sk_push and sk_free](../../../core/libs/prx/libSceLibreSsl3/src/Stack.cpp) (libSceLibreSsl3) - follow [LibreSSL 4.0.0](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/stack/stack.c) `stack.c` with libSceLibreSsl's 32-byte `_STACK` layout, which `stack_local.h` keeps there. Stacks and element arrays come from the guest heap, so the forwarded `sk_pop_free` can release them. Nothing is checked on the console. Where LibreSSL faults or overflows, they throw: `sk_push` on a null stack, on a negative element count, on a null element array it does not regrow, or when the element array cannot double without overflowing `int` +- [ASN1_STRING_get0_data, ASN1_INTEGER_free](../../../core/libs/prx/libSceLibreSsl3/src/Asn1.cpp) (libSceLibreSsl3) - nothing is checked on the console. The 24-byte `ASN1_STRING` layout and the results follow [LibreSSL 4.0.0](https://github.com/libressl/openbsd/tree/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/asn1) `asn1.h`, `a_string.c`, `a_int.c` and `tasn_fre.c`, the version in the [firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). No export of this module creates a string yet, so only strings the caller builds reach them. `ASN1_INTEGER_free` zeroes and frees the data unless `ASN1_STRING_FLAG_NDEF` is set, then frees the string, through the guest `free` as the module would through libc. A null string in `ASN1_STRING_get0_data`, which LibreSSL dereferences, and a negative length with data in `ASN1_INTEGER_free`, which `freezero` would take as a huge size, throw +- [X509_get0_extensions, X509_get_ext_count, X509_get_ext](../../../core/libs/prx/libSceLibreSsl3/src/X509Extensions.cpp) (libSceLibreSsl3) - nothing is checked on the console. The `X509`, `X509_CINF` and stack layouts and the results follow [LibreSSL 4.0.0](https://github.com/libressl/openbsd/tree/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto) `x509_local.h`, `stack_local.h`, `x509_set.c`, `x509_ext.c`, `x509_v3.c` and `stack.c`, the version in the [firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). No export of this module creates a certificate yet, so only certificates the caller builds reach them. A null certificate or certificate info, and an extension stack with a positive count and a null entry array, which LibreSSL dereferences, throw - [ASN1_TIME_diff](../../../core/libs/prx/libSceLibreSsl3/src/Time.cpp) has no console ABI or behavior verification. Its signature and date rules follow LibreSSL 4.0.0 [a_time.c](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/asn1/a_time.c), [a_time_tm.c](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/asn1/a_time_tm.c) and [a_time_posix.c](https://github.com/libressl/openbsd/blob/ce488b78e0bd994780569df718596b9776ff681a/src/lib/libcrypto/asn1/a_time_posix.c), using the existing 24-byte string layout. Null inputs use the host wall clock; the console clock relationship is unverified. Null output pointers throw after valid input parsing, where the reference dereferences them. Closes when: measured on a PS5. diff --git a/docs/dev/debt/libSceNKWebKit.md b/docs/dev/debt/libSceNKWebKit.md index 6ab3e588c7..38c89b962d 100644 --- a/docs/dev/debt/libSceNKWebKit.md +++ b/docs/dev/debt/libSceNKWebKit.md @@ -43,7 +43,7 @@ Inventory prose retains historical counts; use the [generated progress report](h - The [revision-pinned identity inventory](https://gist.github.com/kyon-eth/d44995f181e1818977bd38f0e6fc0f34/8afcb14b0707a09b6274ff7f7bcf33ef46cfe2e7) records the module, library, symbol type and NIDs for the declarations in [Export.cpp](../../../core/libs/prx/libSceNKWebKit/Export.cpp); it is a metadata summary rather than independent verification. For the 255 absent from the public catalogue, [per-image ELF records](https://gist.github.com/kyon-eth/147be8dd556e9cced2577ccbed548972/1a659ecfe819e724675991a574a1aebb5fbb48e5) include the raw qualified names, module and library identities, symbol type, values and sizes; the record file SHA-256 is `44bdc4d6073192a8f41b7be359b75364b3d41dbbd11ce649924b8cebdd4ffe51`. Image labels are not authenticated. -- [Additional callable exports](../../../core/libs/prx/libSceNKWebKit/Export.cpp) - 7366 of the 8703 inventory declarations listed below throw through `NotImplemented_nid_no_patch`; signatures and behavior are unverified. The later 13.60-labelled image contains all 8703; 8448 match the public 3.20 catalogue, while 255 are absent and their presence in retail 3.20 is unverified. Per-image records show the latter in a separate 3.20-labelled image, but neither image label is authenticated. Identified names match NIDs in the [public symbol database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv) or [supplemental catalog](https://github.com/claimore22/ps5rs/blob/2304be5131221bae0dac24b9767cabffda33f747/data/nids.csv). Data exports need separate analysis. +- [Additional callable exports](../../../core/libs/prx/libSceNKWebKit/Export.cpp) - 7365 of the 8703 inventory declarations listed below throw through `NotImplemented_nid_no_patch`; signatures and behavior are unverified. The later 13.60-labelled image contains all 8703; 8448 match the public 3.20 catalogue, while 255 are absent and their presence in retail 3.20 is unverified. Per-image records show the latter in a separate 3.20-labelled image, but neither image label is authenticated. Identified names match NIDs in the [public symbol database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv) or [supplemental catalog](https://github.com/claimore22/ps5rs/blob/2304be5131221bae0dac24b9767cabffda33f747/data/nids.csv). Data exports need separate analysis. | Name | NID | | --- | --- | @@ -1789,7 +1789,6 @@ Inventory prose retains historical counts; use the [generated progress report](h | `_ZN3WTF25activateSignalHandlersForENS_6SignalE` | `Pyu7Zyt6XUE` | | `_ZN3WTF26getAndResetAccumulatedLogsEv` | `bD3nxh6Om44` | | `_ZN3WTF26normalizeLineEndingsToCRLFEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE` | `oUjgPUMQcao` | -| `_ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_` | `tDDzvLlQ7CE` | | `_ZN3WTF28encodeWithURLEscapeSequencesERKNS_6StringE` | `3DqiPW3mayI` | | `_ZN3WTF28normalizeLineEndingsToNativeEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE` | `KWwKlT9hDkc` | | `_ZN3WTF30numCodeUnitsInGraphemeClustersENS_10StringViewEj` | `3PZOiy2oZ9w` | diff --git a/docs/dev/debt/libSceNpCppWebApi.md b/docs/dev/debt/libSceNpCppWebApi.md index 1186c51691..f264a6ad75 100644 --- a/docs/dev/debt/libSceNpCppWebApi.md +++ b/docs/dev/debt/libSceNpCppWebApi.md @@ -19,16 +19,20 @@ - [sce::Np::CppWebApi::Common::String](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - the 0x20-byte layout (32-bit reference count, buffer at 0x08, used size including the terminator at 0x10, `LibContext*` at 0x18), the `+0x10` semantics and the `0x80553503`/`0x80553504` results follow the module bundled with PPSA21564 and PPSA23732 (builds J03093737/J03341606): `append`, `copyFrom`, `clear`, `size`, `length`, `operator==`, `setContext` and the intrusive reference operations match it. Allocation and release still use the host allocator instead of the `LibContext` allocator, so a title-provided buffer released through this destructor would use the wrong allocator; `find`, `replace` and `npos` remain unimplemented. `pushBack` into `Vector` stores a deep copy, so a destroyed temporary cannot invalidate the stored element; a title that byte-copies a `String` with a live buffer would still double-free, as nothing increments the reference count - [sce::Np::CppWebApi::Common::Vector](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - imported by PPSA03671, whose dump ships no `libSceNpCppWebApi.prx`. A `Vector` handle is an `IntrusivePtr` over a shared body; bodies created by `pushBack` use a host layout with the reference count at 0x30. The pointer/deleter constructor adopts a title-provided `Vector`, counting the reference at 0x38, which the `Vector` constructor zeroes, as the module bundled with PPSA21564 does, and releases it through the stored deleter; `pushBack` on such a body throws, as its element layout is unknown. `Vector::begin`/`end` and `Iterator` operators walk host-created bodies and throw on title-provided ones; other `begin`, `end` and iterators, and `copyFrom`, throw: the only `Vector`s the title reads back come from failed transactions, which never produce one. `empty`, `size` and `operator[]` read host-created bodies and throw on title-provided ones - [sce::Np::CppWebApi::Common::Binary](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - the 0x20-byte layout (32-bit reference count, buffer at 0x08, size at 0x10, `LibContext*` at 0x18) comes from the module bundled with PPSA21564/PPSA23732 (builds `J03093737`/`J03341606`); other SDK versions are not checked. `setBinary` and `appendBinary` use the host allocator instead of the `LibContext` allocator, reject a null source with a non-zero size where the module does not, keep the old contents when the input is invalid or allocation fails, and copy the input before releasing a buffer it aliases. A title that byte-copies a `Binary` with a live buffer would double-free, as nothing increments the reference count +- [sce::Np::CppWebApi::Common::Vector audited members](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - `begin`, `end`, iterators and `copyFrom` follow the bundled module for the audited `IntrusivePtr`/`unsigned long` families (iterator = zero tag plus element pointer; `copyFrom` replaces elements through the element reference count) and throw on adopted bodies and other families; they accept either the `IntrusivePtr` handle or the object its `operator->` returns, which module bodies read at offsets 0x18/0x28. `copyFrom` releases old elements — a deliberate deviation: the module installs the fresh zeroed array before its release loop - [sce::Np::CppWebApi::SessionManager::V1 friends player sessions](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - the `getFriendsPlayerSessions` family follows the module bundled with the titles (build J03341606): `Friend` stores account id at 0x10, `accountIdIsSet` at 0x18, `IntrusivePtr>` at 0x30 and `playerSessionsIsSet` at 0x48; `FriendJoinedPlayerSession` stores `String sessionId` at 0x10 and `sessionIdIsSet` at 0x30; the response body stores `IntrusivePtr>` at 0x30. Vector views use the real inline layout (begin 0x18, end 0x28, refcount 0x30, 0x18-byte elements). The model layouts are measured in build J03341606; destroying the last vector reference without a deleter throws until the allocator lands. Other builds are not checked. - [sce::Np::CppWebApi::SessionManager::V1 friends transaction](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - the transaction is 0x10 bytes; its constructor zeroes it. `start` returns 0x80553503 for a null context, 0x80553502 for an uninitialized context and then `SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN`; `getResponse` and `getFriendsPlayerSessions` return 0x80553508 while the two transaction words are zero. No response is produced; these offline paths are not console measurements. - [sce::Np::CppWebApi::SessionManager2V1](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - imported by PPSA03671. Offline, the factories, `PlayerSessionsApi` calls and transaction `start`/`getResponse`/`readData` fail with `SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN`; parameter setters, `initialize`, `terminate`, constructors and destructors succeed without keeping state, as no request is ever sent. Response-body accessors (`getSessionId`, `getPlayerSessions`, `getInvitations`, the `IsSet` queries) throw: a failed request never produces a response object - [sce::Np::CppWebApi::Matchmaking::V1](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - imported by PPSA21564 (86 of 92) and PPSA05510, PPSA25256, PPSA17226 and PPSA08395 for the other six; behaviour comes from the module bundled with PPSA21564/PPSA23732 (builds J03093737/J03341606), not from a console. Offline, the four `Api` calls and four factories return `SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN`. The four `ParameterTo*` objects keep only an initialized flag: `initialize` returns 0x80553503 for a null context or string, 0x80553502 for an unset context, 0x8055350f when already initialized and 0x80553512 for an empty `SubmitTicketRequestBody`; `terminate` returns 0x80553510. `ParameterToGetTicket::setview` returns 0x80553502 uninitialized and 0x80553503 for a null string. Other setters succeed without keeping state. Response accessors throw: a failed request produces no response. 0x80553504 is never returned; the stub stores a static pointer. -- [sce::Np::CppWebApi::UserProfile::V1, ProfanityFilter::V2, CommunicationRestrictionStatus::V3](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - imported by an Epic Online Services module whose dump ships no `libSceNpCppWebApi.prx`. The reference-count offset 0x00 of `ResponseHeaderBase` and `WebApiFilterRequest` is assumed from the other objects, not measured. Offline, the five API calls, `WebApiFilterRequestFactory::create` and the transactions' `start`/`getResponseHeaders` fail with `SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN`. Response accessors, `ResponseHeaderBase::getHeaderValue` and the `Vector`/`Iterator` members over `unsigned long` and those over `IntrusivePtr` other than `size` throw: a failed request never produces a response +- [sce::Np::CppWebApi::UserProfile::V1, ProfanityFilter::V2, CommunicationRestrictionStatus::V3](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - imported by an Epic Online Services module whose dump ships no `libSceNpCppWebApi.prx`. The reference-count offset 0x00 of `ResponseHeaderBase` and `WebApiFilterRequest` is assumed from the other objects, not measured. Offline, the five API calls, `WebApiFilterRequestFactory::create` and the transactions' `start`/`getResponseHeaders` fail with `SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN`. Response accessors and `ResponseHeaderBase::getHeaderValue` throw: a failed request never produces a response. The `Vector`/`Iterator` members over `IntrusivePtr` follow the bundled module on host-created bodies and throw on title-provided ones. Nothing can create a host `Vector` body, so its `begin`, `end` and iterator throw for every non-empty vector - [libSceNpCppWebApi](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - unimplemented stubs have their parameter lists, const qualifiers and return types aligned with the demangled symbols confirmed by NID matching in [#8143](https://github.com/boykopovar/AnyPS5/issues/8143). They cover response-body accessors, iterators, and uninstantiated transactions in Leaderboards::V1, SessionManager::V1, InGameCatalog::V5, TitleCloudStorage::V1, and Common templates: each mangled name gives the method and parameter types, but the runtime layout of response objects and errors are unverified on console, so each call continues to throw NotImplemented_nid_no_patch. No call site is recorded for them - [sce::Np::CppWebApi::SessionManager2V1 and sce::Np::CppWebApi::InGameCatalog2V5](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - 198 further exports imported by PPSA20397, named from aerolib. API calls, factories and transaction `start`/`getResponse*` fail `SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN`; parameter bookkeeping succeeds without state, except the `PlayerSessionsApi` parameters, which track initialization per the SessionManager::V1 entry; `IntrusivePtr`/`Vector` helpers follow the layouts above, with `Vector::empty`/`size`/`operator[]` reading host bodies and throwing on title-provided ones. Response accessors, iterators, `Vector::begin`/`end`/`copyFrom` and transaction `operator=` throw: a failed request produces no response object. As `start` never succeeds here, `TransactionBase::finish` and `abort` return 0x80553508 and `getId` returns 0, as the module bundled with PPSA21564 does while the two words its `Transaction` constructor zeroes are unset - [sce::Np::CppWebApi::UserProfile::V1, sce::Np::CppWebApi::CommunicationRestrictionStatus::V3 and the remaining sce::Np::CppWebApi::Common instantiations](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - 87 further exports imported by PPSA20397, plus the previously-throwing `ContainerApi::ParameterToGetContainer` lifecycle and `getContainer`. API verbs and transaction `start`/`getResponse` fail `SCE_NP_WEBAPI_ERROR_NOT_SIGNED_IN`; parameter and model bookkeeping (`initialize`, `terminate`, `set*`, constructors, destructors) succeeds without state. `BasicProfile`/`BasicPresence`/`PersonalDetail` response accessors, `*IsSet` queries, `Get*Response` getters, vector `begin`/`end`, iterator dereference/compare and transaction `abort`/`getId`/`operator=` throw: no response object exists offline and the model layouts are unverified +- [sce::Np::CppWebApi::Common::TransactionBase and Transaction](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - not read in a module for the four `UserProfile::V1` transactions: their `abort` and `getId` return 0x80553508 and 0, as the `TransactionBase` code read in the PPSA21564 module does for six and five other instantiations ([#11235](https://github.com/boykopovar/AnyPS5/pull/11235)). The `InGameCatalog::V5` `Vector>` and `TitleCloudStorage::V1` `GetMultiDataStatusesResponseBody` transactions still throw from `start` and `DataApi::getMultiDataStatusesByUser`: past the `LibContext` checks (0x80553503, 0x80553502), the module bundled with PPSA21567 returns what `libSceNpWebApi2` and the service answer, which is not measured. Their `getResponse` returns 0x80553508 and writes nothing, as [that module](https://github.com/boykopovar/AnyPS5/pull/10832#issuecomment-6416121806) does while the words at +0 and +8 are null +- [sce::Np::CppWebApi::SessionManager2V1 and sce::Np::CppWebApi::InGameCatalog2V5 audited accessors](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - measured on the bundled module: the `Sku` price/label fields and `*IsSet` bytes, `Product` `getId`/`getType`/`getDisplayName`/`getDescription`/`getReleaseDate`/`releaseDateIsSet`/`skusIsSet`/`getSkus`, `Container::getChildren` (vector handle at 0x228), `PlayerSession::getSessionId` (string at 0x10), the matching iterators, `Vector` `begin`/`end`/`empty`/`size`, `ResponsePlayerSessionPlayer` `copyFrom`/`size` and the Container-response `TransactionBase::operator=`/`start` guards +- [sce::Np::CppWebApi::UserProfile::V1 and CommunicationRestrictionStatus::V3 audited accessors](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - measured on the bundled module: `BasicPresence` construct/destruct, `set{AccountId,InContext,OnlineStatus}`, `get{AccountId,InContext,OnlineStatus}` and the `inContextIsSet`/`onlineStatusIsSet` bytes at 0x22/0x20; `BasicProfile` construct/destruct, `setOnlineId`, `setIsOfficiallyVerified` and the `onlineIdIsSet`/`personalDetailIsSet`/`isOfficiallyVerifiedIsSet` bytes at 0x24/0x40/0xaa; `GetPublicProfilesResponse::getProfiles` (vector handle at 0x30) and the restriction response `getRestricted` (byte at 0x30) -- [sce::Np::CppWebApi title-imported exports](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - exports imported by the `sce_module` copies shipped with PPSA20397 and PPSA03530 that main did not declare. NIDs and signatures come only from the titles' import tables; const and return types are inferred from the demangled name. Layouts and offline behaviour follow the landed same-template implementations sourced from the module bundled with PPSA21564. Response-body accessors, `IsSet` queries, `Vector` begin/end, `Iterator` dereference/compare and transaction `operator=` throw: a failed request produces no response object and the layouts are unverified. `SessionManager::V1` `GameSessionsApi`, `Matches::V1`, `Matchmaking::V1`, `UserProfile::V1`, `TitleCloudStorage::V1` and `InGameCatalog::V5` accessors have no other source, so behaviour is only what the signatures admit. +- [sce::Np::CppWebApi title-imported exports](../../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - exports imported by the `sce_module` copies shipped with PPSA20397 and PPSA03530 that main did not declare. NIDs and signatures come only from the titles' import tables; const and return types are inferred from the demangled name. Layouts and offline behaviour follow the landed same-template implementations sourced from the module bundled with PPSA21564. The audited subset reads the bundled module's measured layouts — model fields, `Vector`/`Iterator` members, `copyFrom` and the transaction `operator=`/`start` guards; the rest still throw: a failed request produces no response object. `SessionManager::V1` `GameSessionsApi`, `Matches::V1`, `Matchmaking::V1`, `UserProfile::V1`, `TitleCloudStorage::V1` and `InGameCatalog::V5` accessors have no other source, so behaviour is only what the signatures admit. diff --git a/docs/dev/debt/libSceVideoOut.md b/docs/dev/debt/libSceVideoOut.md index 4c786e8a3a..754fd25e5f 100644 --- a/docs/dev/debt/libSceVideoOut.md +++ b/docs/dev/debt/libSceVideoOut.md @@ -65,14 +65,13 @@ - The [revision-pinned identity inventory](https://gist.github.com/kyon-eth/ea0a096e6231dbe7b98b5a308e2ac91e/00f8422a1ae71e32816d72ae579c2f2d097f63a0) records module, logical library, symbol type and NIDs for [InventoryExports.cpp](../../../core/libs/prx/libSceVideoOut/InventoryExports.cpp); it is a metadata summary rather than independent verification. Some NIDs belong to multiple logical libraries within the module. -- [Additional callable exports](../../../core/libs/prx/libSceVideoOut/InventoryExports.cpp) - 182 entries observed in a 3.20-labelled image and a later 13.60-labelled image; 107 match the public 3.20 catalogue and 75 do not. These are import-resolution declarations only. Neither image label authenticates a retail firmware version. Parameter lists, return types and behavior are unverified; parameterless `int` declarations are placeholders, not verified ABI contracts. Every entry throws through `NotImplemented_nid_no_patch`. Unidentified names use literal NID aliases. No runtime functionality is implemented; data exports need separate analysis. Identified candidate names match their NIDs in the [public symbol database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv) or [supplemental catalog](https://github.com/claimore22/ps5rs/blob/2304be5131221bae0dac24b9767cabffda33f747/data/nids.csv). +- [Additional callable exports](../../../core/libs/prx/libSceVideoOut/InventoryExports.cpp) - 175 entries observed in a 3.20-labelled image and a later 13.60-labelled image; of the original 182, 107 match the public 3.20 catalogue and 75 do not. These are import-resolution declarations only. Neither image label authenticates a retail firmware version. Parameter lists, return types and behavior are unverified; parameterless `int` declarations are placeholders, not verified ABI contracts. Every entry throws through `NotImplemented_nid_no_patch`. Unidentified names use literal NID aliases. No runtime functionality is implemented; data exports need separate analysis. Identified candidate names match their NIDs in the [public symbol database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv) or [supplemental catalog](https://github.com/claimore22/ps5rs/blob/2304be5131221bae0dac24b9767cabffda33f747/data/nids.csv). | Name | NID | | --- | --- | | `sceVideoOutAddBuffer` | `4iy9hG9Du1s` | | `sceVideoOutAddBuffer4k2kPrivilege` | `twrSaoZ9cJs` | | `sceVideoOutAddBufferAnisoPrivilege` | `lm+1oyWKwy0` | -| `sceVideoOutAddBufferHdrPrivilege` | `VAlir52gpQI` | | `sceVideoOutAddBufferYccPrivilege` | `D3s8DoEnuR4` | | `sceVideoOutAddDisplayPositionEvent` | `Cxb2w82t7lw` | | `sceVideoOutAddDriver` | `HtwSd4H2Tws` | @@ -90,7 +89,6 @@ | `sceVideoOutControlHdcpEncryption` | `M-JkRj7X+No` | | `sceVideoOutCursorIsUpdatePending` | `HibOtezzT6M` | | `sceVideoOutCursorSetPositionStereo` | `735GfVO9v2s` | -| `sceVideoOutCurveSamplePointsCalc_` | `kazBRXPqR7c` | | `sceVideoOutDebugAddVrrPrivilege` | `rAYR4zzw414` | | `sceVideoOutDebugBlankPipe` | `-9YA0lVAq+U` | | `sceVideoOutDebugReadCrc` | `4E8qvHf7Cj0` | @@ -106,7 +104,6 @@ | `sceVideoOutDriverGetBufferLabelAddress` | `NGyEl5aT4fc` | | `sceVideoOutDriverGetEopHandle` | `P1bIHoga4jE` | | `sceVideoOutDriverGetFinishedEopHandle` | `G6peSSDP4iA` | -| `sceVideoOutDriverGetLatestEopHandle` | `GL8+3RHW5vk` | | `sceVideoOutDriverIncrementBufferLabel` | `Ztx4b2LhRDk` | | `sceVideoOutDriverResetBufferLabel` | `soAIjspgdt8` | | `sceVideoOutDriverTriggerEvent` | `OHnnkrUcShM` | @@ -131,7 +128,6 @@ | `sceVideoOutHdmiMonitorInfoIsSupportedVideoOutMode_` | `WBZrUaQY+EU` | | `sceVideoOutLockBuffer` | `7ifZFxWJ9Q4` | | `sceVideoOutRazorAddCallback` | `ZX7C79uOujU` | -| `sceVideoOutRazorRecallCallbacks` | `hGcTks-qqIU` | | `sceVideoOutRazorRemoveCallback` | `zUDW7kIFclI` | | `sceVideoOutRegisterBufferAttribute` | `EJQifjOp8s4` | | `sceVideoOutRegisterStereoBuffers` | `lCTCOogRbk0` | @@ -163,7 +159,6 @@ | `sceVideoOutSysGetDeviceInfo` | `2sgenMqwczM` | | `sceVideoOutSysGetFlipStatus` | `21sS8EU45cw` | | `sceVideoOutSysGetKsvList` | `Ur8iOIm0tyE` | -| `sceVideoOutSysGetMonitorInfo_` | `vMLWuJckGv0` | | `sceVideoOutSysGetOutputStatus` | `Ip78YCQUrTo` | | `sceVideoOutSysGetPipelineStatus` | `dFhciCfO31s` | | `sceVideoOutSysGetResolutionStatus2` | `qLDCAl8ygCw` | @@ -183,7 +178,6 @@ | `sceVideoOutSysModeIsSystemDefault` | `5Y8uUbGMio0` | | `sceVideoOutSysModeIsVrLegacy` | `zecl8Gox+P0` | | `sceVideoOutSysModeIsVrNative` | `SgA2MtojPto` | -| `sceVideoOutSysModeIsVr` | `QEiuHxjungc` | | `sceVideoOutSysOpenInternal` | `kP4l+nyBjRA` | | `sceVideoOutSysOpenVrNative` | `WUU+ufqgLJg` | | `sceVideoOutSysReadCrc64` | `eBvoaLwfBBQ` | @@ -198,7 +192,6 @@ | `sceVideoOutSysSetOverscanRatio` | `nMbAqI1ty8w` | | `sceVideoOutSysUpdateDisplayParameter` | `UFDoqv4XXC0` | | `sceVideoOutSysUpdatePrivilege` | `Jl91AhxKc0w` | -| `sceVideoOutSysUpdateRenderingMode` | `4G37EIMMD+Q` | | `sceVideoOutUnlockBuffer` | `amghnA-Ev5s` | | `sceVideoOutUnregisterBufferAttribute` | `SRQSpP4QK5U` | | `Unknown` | `-5AIEU9+11g` | @@ -252,6 +245,8 @@ | `Unknown` | `yoK0AjkkBkI` | | `Unknown` | `ys239q8VgXY` | +- [Firmware 13.42 answers](../../../core/libs/prx/libSceVideoOut/InventoryExports.cpp) (libSceVideoOut) - `sceVideoOutAddBufferHdrPrivilege`, `sceVideoOutRazorRecallCallbacks` and `sceVideoOutSysUpdateRenderingMode` return 0, `sceVideoOutCurveSamplePointsCalc_` returns 0x8029001C, `sceVideoOutDriverGetLatestEopHandle` 0x802900FF and `sceVideoOutSysGetMonitorInfo_` -1, and `sceVideoOutSysModeIsVr` returns bit 1 of the dword at offset 0x20 of its argument, as firmware 13.42's libSceVideoOut does: read to the return, disassembly only, not measured on a console. Their parameter lists are unverified beyond what the code reads; the layout of the structure `sceVideoOutSysModeIsVr` reads is unknown apart from that dword. The module reads that dword without checking the pointer, so a null argument faults on the console as it does here + - [sceVideoOutSetConfigurationMode](../../../core/libs/prx/libSceVideoOut/InventoryExports.cpp): the name hashes to NID `N1+j0RymMUQ`, a function export in both older and later version-labelled images. Its signature and behavior are unverified; this import-resolution declaration throws. - [Older callable NIDs](../../../core/libs/prx/libSceVideoOut/InventoryExports.cpp): 7 unidentified exports have unverified names, signatures and behavior. These are throwing import-resolution placeholders; no functionality is implemented. No matching NIDs were found in the later module inventory. Six use the primary library qualifier and one uses the nosubmission qualifier; qualified guest import resolution is unverified. diff --git a/docs/dev/debt/libc.md b/docs/dev/debt/libc.md index f6d8a4cda5..6f87a8fec3 100644 --- a/docs/dev/debt/libc.md +++ b/docs/dev/debt/libc.md @@ -134,7 +134,6 @@ - [getsubopt](../../../core/libs/prx/libc/src/GetSubOpt.cpp) (libc, NID `h630-qzWzew`) follows FreeBSD 11.4 [getsubopt.c](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/libc/stdlib/getsubopt.c): suboptions delimited by commas or whitespace, token splitting on '=' with empty and leading '=' values preserved, and null parameter validation. The exported libc variable `suboptarg` (NID `ArJIt9shYaA`) is left untouched. Console behavior is unverified. - [_Cosh](../../../core/libs/prx/libc/src/Math.cpp) (libc) follows the two-argument Dinkumware CRT helper used by `std::complex`, including a scaled large-finite-input path; the signature, exact result and floating-point exception behavior are not verified against the console. - [std::thread::hardware_concurrency](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `CHrhwd8QSBs`) - the starting mask of a title's process, and so the value a title sees, are not measured, and neither is whether the console's count follows a process-wide `cpuset_setaffinity`. This returns 13, the number of CPUs in libkernel's default thread mask (`0x1FFF`), and a process-wide `cpuset_setaffinity` does not change it. In payload processes whose threads started with mask `0xea00` it returned 5 on PS5 firmware 13.60 and 12.70, while `hw.ncpu` read 16 and `sceKernelGetAvailableCpumask` `0x1fff` (both on 13.60). On 12.70 it still returned 5 when called first after `scePthreadSetaffinity` had narrowed the calling thread to one CPU, after the mask was restored, and in a thread created with a two-CPU mask. PPSA34015 imports it. -- [fmodf](../../../core/libs/prx/libc/src/Math.cpp) (libc) - console `errno`, exception flags and NaN payloads remain unverified. The wrapper preserves `errno` like the existing double `fmod`, following FreeBSD 11.4 [`e_fmodf.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/e_fmodf.c); host `std::fmod` still supplies the result and exception flags. - [_LCosh and _LSinh](../../../core/libs/prx/libc/src/Math.cpp) (libc) follow the two-argument Dinkumware CRT helpers `y * cosh(x)` and `y * sinh(x)`, including scaled large-finite-input paths; the signatures are confirmed by Dinkumware's public `ymath.h`, but the exact console results, range-error thresholds and floating-point exception behavior are not verified. - [modf and modff](../../../core/libs/prx/libc/src/Math.cpp) (libc) - native PS5 execution, Windows and unmasked exceptions remain unverified. Linux comparisons with bundled libraries from PPSA03766 and PPSA07923 cover result and integral bits, errno, SSE/x87 flags and control state. Signaling NaNs retain their payload and quiet bit; the measured float path raises SSE invalid while the double path leaves flags unchanged. - [_FSinh and _FCosh](../../../core/libs/prx/libc/src/Math.cpp) (libc) finite results are not verified bit for bit against the console: the scaled product uses the host's binary64 hyperbolic function before rounding to binary32, rather than the float rational and `_FExp` sequence in PRAGMATA's bundled `libc.prx`. NaN preference and payloads, signed zeros, infinite operands and the range-error thresholds follow that binary's instructions; the system `libSceLibcInternal` implementation and nondefault flush-to-zero modes are unverified. Against `libSceLibcInternal.sprx` on a PS5 (firmware 13.60), 12 of 36 measured results differ by one unit in the last place (`_FSinh(0.5, y)` and `_FCosh(1, y)`, `_FCosh(10, y)` for y of 0.5, 1 and 2); zeros, the overflow to infinity at 89 and 90 and the tiny-argument results matched @@ -143,6 +142,7 @@ - [Host stderr preservation](../../../core/libs/prx/libc/src/General.cpp) (WebAssembly) uses descriptor 2 directly, so host diagnostics do not retain an independent stream across guest stderr redirection - [Guest arena](../../../core/libs/prx/libc/src/GuestArena.cpp) (WebAssembly) is limited to an 8 GiB reservation, WebAssembly linear memory does not enforce guest page read, write or execute protections, and host region release throws because host virtual-address reservations are unavailable - [Guest long double conversions](../../../core/libs/prx/libc/include/GuestLongDouble.hpp) (WebAssembly) - storing a binary128 value discards fraction bits beyond x87 precision instead of rounding them; noncanonical x87 encodings are unverified +- [fmod and fmodf](../../../core/libs/prx/libc/src/Math.cpp) (libc) take their finite results and exception flags from the host `std::fmod`; the flags were not compared with the console. They set `EDOM` exactly where FreeBSD 11.4 [`e_fmod.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/e_fmod.c) returns `(x*y)/(x*y)`: a zero divisor, an infinite or NaN dividend, or a NaN divisor. There a NaN divisor is returned quieted, then a NaN dividend, then the default NaN. The `libc.prx` bundled with eleven titles (PPSA04158 to PPSA35169) gives the same bits and `errno` on 4,000,256 sampled pairs per function on a Windows host. - [_LDnorm](../../../core/libs/prx/libc/src/MathExact.cpp) (libSceLibcInternal, implemented in libc) - a zero significand never returns on the console, where the normalising loop shifts forever; this throws instead - [sscanf_s and vsscanf_s](../../../core/libs/prx/libc/src/Formatting.cpp) (libc) return `EOF` when a reached conversion has a null destination, stopping before further assignments, following C11 K.3.5.3.7 and K.3.5.3.14. Earlier assignments are retained. The constraint handler is not invoked, and console behaviour is unverified. diff --git a/docs/dev/debt/libkernel.md b/docs/dev/debt/libkernel.md index 08a150589a..ebbd688c3c 100644 --- a/docs/dev/debt/libkernel.md +++ b/docs/dev/debt/libkernel.md @@ -281,10 +281,11 @@ - Guest sockets on macOS ([the equeue wait, poll, kevent, fstat and ioctl](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp), [gethostbyname](../../../core/libs/prx/libScePosixForWebKit/Resolver.cpp)): macOS has no `ppoll`, so the wait uses `poll` with the timeout rounded up to a millisecond; it has no `POLLRDHUP`, so a stream that the peer closed is found by peeking one byte when it is readable; XNU's `poll` reports `POLLHUP`, with `POLLPRI` and without `POLLOUT`, once either direction of a stream has ended, so a guest stream socket it reports hung up is asked about each direction alone and keeps `POLLHUP` only once both have ended, as FreeBSD does; a call that asks for no event gets nothing, where FreeBSD reports `POLLHUP`; `FIONREAD` on a datagram socket, and the byte count that `fstat` and `kevent` report for it, is `SO_NREAD`, the size of the next datagram, because macOS adds the source address to `FIONREAD`; and `gethostbyname` replaces `gethostbyname_r`, which macOS lacks. - [recvmsg](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) loses received stream data on an output copy fault: outputs are checked after the host receive. FreeBSD 11.4 leaves unread stream data queued, though it also drops a datagram on a copy fault ([`soreceive_dgram`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L2308-L2312), [`soreceive_generic`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L1758-L1774)). A Linux `process_vm_readv` or `process_vm_writev` failure other than `EFAULT` throws - [MSG_DONTWAIT](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) in `send`, `sendto`, `sendmsg`, `recv`, `recvfrom` and `recvmsg` makes that one call non-blocking through the host's `MSG_DONTWAIT`, as FreeBSD 11.4's `soreceive_generic` returns `EWOULDBLOCK` for it (`sys/kern/uipc_socket.c`). Winsock has no per-call non-blocking flag, so on Windows the call first asks `WSAPoll` with a zero timeout whether the socket is ready and fails with `EAGAIN` when it is not. The check and the transfer are two host calls: a second thread that takes the data in between can leave a `recv` blocked, and a `send` of more bytes than the socket buffer holds can still block until it has sent them, where FreeBSD's `sosend_generic` returns a partial count -- [MSG_WAITALL](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) in `recv`, `recvfrom` and `recvmsg` on a stream socket is passed to the host, which returns when the buffer is full, the peer closes or an error occurs, as FreeBSD 11.4's [`soreceive_generic`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L1855-L1860) does; a datagram socket ignores it. It is not measured on a console, a nonblocking socket and a call that also passes `MSG_PEEK` follow the host's rules, and `SO_RCVTIMEO` bounds only the wait for the first data. Any other flag still fails with `EOPNOTSUPP`. +- [MSG_WAITALL](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) in `recv`, `recvfrom` and `recvmsg` on a stream socket is passed to the host, which returns when the buffer is full, the peer closes or an error occurs, as FreeBSD 11.4's [`soreceive_generic`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L1855-L1860) does; a datagram socket ignores it. It is not measured on a console, a nonblocking socket and a call that also passes `MSG_PEEK` follow the host's rules, and `SO_RCVTIMEO` bounds only the wait for the first data. On Windows, `shutdown(SHUT_RD)` from another thread does not end a wait that already holds part of the data, where that loop stops at `SBS_CANTRCVMORE` and returns it. Any other flag still fails with `EOPNOTSUPP`. - [recv and recvfrom](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) answer some cases without the host. A zero-length receive on a stream socket returns 0, or `ENOTCONN` when it is not connected ([L1566-L1578](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L1566-L1578)), as on a PS5 (firmware 13.60). On an empty datagram socket it returns 0 at once; the console was measured only with `MSG_DONTWAIT`, and the blocking case follows FreeBSD 11.4's `soreceive_dgram`, which returns 0 before waiting. `recvmsg` answers the empty datagram socket the same way but asks the host in the stream cases. A datagram another thread takes after the check makes a zero-length receive wait - [`shutdown(SHUT_RD)`](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) on a Windows TCP socket resets the connection when data is unread or arrives later, so the peer's next send fails with `EPIPE`, where FreeBSD's [`sorflush`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L2387-L2432) discards the data and the peer's sends succeed. The reset also makes `poll` report `POLLHUP` and `POLLERR` beside `POLLIN` for the shut socket, where FreeBSD's [`sopoll_generic`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L3060-L3103) reports only `POLLIN` and `POLLRDNORM`. On a Unix stream socket FreeBSD keeps appending the peer's later data ([`uipc_send`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_usrreq.c#L936-L1001) does not check the receiver's `SBS_CANTRCVMORE`) and receives return it; here receives return 0 and the peer's send fails with `EPIPE` on Linux. - [sendmsg and recvmsg](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) pass descriptors in `SCM_RIGHTS` messages on Unix-domain sockets through the host's `SCM_RIGHTS` (Linux only), in FreeBSD's guest layout: a 12-byte `cmsghdr`, data at offset 16, `CMSG_SPACE` records. Several `SCM_RIGHTS` messages in one `sendmsg` arrive as one record because the host merges them (FreeBSD keeps one per message), so a buffer sized for the first can't receive it alone. A received socket gets default emulated socket options. Sending a guest kqueue returns `EOPNOTSUPP`, as FreeBSD's `unp_internalize` does; a random device, directory or JIT shared memory descriptor (libkernel's state) throws, as does a zero-byte stream send with descriptors (Linux carries no record without data). Windows throws (socket pairs are loopback TCP), as do other control message types and control data on IP sockets. `MSG_PEEK` with a control buffer reads only the data and leaves passed descriptors queued. +- [Blocking receives](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) - `shutdown(SHUT_RD)` from another thread does not end every `recv`, `recvfrom` or `recvmsg` blocked on the socket, where FreeBSD's [`sorflush`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L2403-L2409) wakes them all. On Windows it misses a receive whose data a third thread took between its `WSAPoll` wait and the host receive, and one whose descriptor was closed or replaced while it waited when the shutdown goes through another descriptor of the socket. On macOS it misses a receive on an unconnected datagram socket: XNU's [`soshutdown`](https://github.com/apple-oss-distributions/xnu/blob/xnu-12377.121.6/bsd/kern/uipc_socket.c#L4351-L4356) fails with `ENOTCONN` without flushing. A `recvmsg` that takes a zero-length datagram as `SHUT_RD` lands returns it without its `SO_TIMESTAMP` or `SO_BINTIME` record. - [send, sendto](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) - send and sendto without an address on an unconnected datagram socket map Windows `WSAENOTCONN` to FreeBSD's `EDESTADDRREQ` (39). - [bind, connect, sendto](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) - a connected stream socket's `sendto` ignores the address once its length passes, as FreeBSD 11.4's `tcp_usr_send` does, which was not measured. Otherwise they check a socket address as a payload process on a PS5 (firmware 13.60) did on datagram and stream sockets: a length below 2 fails with `EINVAL` and above 255 with `ENAMETOOLONG`; then an `AF_INET` socket needs exactly 16 bytes and an `AF_INET6` socket 28, or `EINVAL`, before the family is looked at (an `AF_INET6` address of 28 or 10 bytes on an `AF_INET` socket fails with `EINVAL`); then another family, `AF_UNSPEC` with `INADDR_ANY` included, fails with `EAFNOSUPPORT`; and `connect` on a listening stream socket fails with `EOPNOTSUPP` - [bind, connect](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) on an `AF_INET6` datagram socket with `IPV6_V6ONLY` cleared accept an IPv4-mapped address longer than 28 bytes and use its first 28, as FreeBSD 11.4's `udp6_bind` and `udp6_connect` hand it to `in_pcbbind` and `in_pcbconnect` as a `sockaddr_in` without the length test of `in6_pcbbind`; `sendto` still fails it with `EINVAL`, as `udp6_send` tests the length first. The console was measured only with `::1` and `IPV6_V6ONLY` at its default, so this case is not measured